stock-indicators/test/indicator/simple-moving-average.js
2025-03-31 11:20:04 +02:00

129 lines
3.8 KiB
JavaScript
Executable File

'use strict';
import chai from 'chai';
const assert = chai.assert;
import SMA from '../../lib/indicator/simple-moving-average.js';
describe('Simple Moving Average', () => {
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9];
it('should calculate correctly and return result', (done) => {
let runTest = async (options, values, expectedResult, expectedPrice) => {
let sma = new SMA(options);
sma.setValues(values);
let results = await sma.calculate();
assert.isTrue(results.length == expectedResult.length);
assert.isArray(results)
results.forEach((item, idx) => {
assert.isObject(item);
assert.containsAllKeys(item, ['price', 'sma']);
assert.isNumber(item.price);
assert.isNumber(item.sma);
assert.closeTo(expectedResult[idx], item.sma, 0.1);
assert.isTrue(item.price == expectedPrice[idx]);
});
};
let arr = [
{ o: { periods: 4, sliceOffset: true, lazyEvaluation: true }, v: data, e: [2.5, 3.5, 4.5, 5.5, 6.5, 7.5], ep: [4, 5, 6, 7, 8, 9] },
{ o: { periods: 9, sliceOffset: true }, v: data, e: [5], ep: [9] },
{ o: { periods: 4, sliceOffset: false }, v: data, e: [0, 0, 0, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5], ep: [1, 2, 3, 4, 5, 6, 7, 8, 9] },
];
(async function () {
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
await runTest(item.o, item.v, item.e, item.ep);
}
done();
})();
// RUN PARALLEL
// (async function(){
// let promises = await arr.map( async item => {
// return await runTest( item.o, item.v, item.e, item.ep );
// });
// await Promise.all( promises );
// done()
// })();
});
it('should calculate correctly with starIndex and endIndex options and return result', (done) => {
let runTest = async (opts, data, expectedResult) => {
let sma = new SMA(opts);
sma.setValues(data);
let results = await sma.calculate();
assert.isArray(results)
assert.isTrue((opts.endIndex + 1 - opts.startIndex + 1) - opts.periods == results.length);
results.forEach((item, idx) => {
assert.isObject(item);
assert.containsAllKeys(item, ['price', 'sma']);
assert.isNumber(item.price);
assert.isNumber(item.sma);
assert.closeTo(expectedResult[idx], item.sma, 0.1);
assert.isTrue(item.price == data[opts.startIndex + opts.periods - 1 + idx]);
});
}
(async function () {
let opts = { periods: 4, startIndex: 1, endIndex: data.length - 2, lazyEvaluation: true, sliceOffset: true };
let expectedResult = [3.5, 4.5, 5.5, 6.5];
await runTest(opts, data, expectedResult);
done();
})();
});
it('should throw error on invalid values', () => {
assert.throws(() => SMA(), Error);
assert.throws(() => (new SMA()).calculate(), Error);
assert.throws(() => (new SMA()).setValues(1), Error);
assert.throws(() => (new SMA()).setValues('foo'), Error);
let sma = new SMA();
sma.setValues(data);
sma.clear();
assert.throws(() => sma.calculate(), Error);
});
it('should throw error on invalid periods', () => {
function runTest(periods) {
let sma = new SMA({ periods, sliceOffset: true });
sma.setValues(data);
assert.throws(() => sma.calculate(), Error);
}
let tp = [data.length + 100, -100, 0, 1];
tp.forEach((val) => runTest(val));
});
it('should throw error on invalid startIndex and endIndex ', () => {
function runTest(startIndex, endIndex) {
let sma = new SMA({ startIndex, endIndex, lazyEvaluation: false, sliceOffset: true });
sma.setValues(data);
assert.throws(() => sma.calculate(), Error);
};
[[10, 5],
[5, 5],
[data.length, data.length + 1],
[-10, 2],
[0, -2],
].forEach(item => runTest(item[0], item[1]));
let sma = new SMA({ endIndex: data.length + 1 });
sma.setValues(data);
assert.throws(() => sma.calculate(), Error);
});
});