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

136 lines
4.4 KiB
JavaScript
Executable File

'use strict';
import chai from 'chai';
const assert = chai.assert;
import ATR from '../../lib/indicator/average-true-range.js';
import Fixture from '../fixtures/average-true-range.js';
describe('Average True Range', () => {
const data = Fixture.data;
const expectedResults = Fixture.dataResults;
it('should calculate true range correctly and return result', () => {
let atr = new ATR({ lazyEvaluation: false });
function runTest(currentItem, prevItem, expectedResult) {
let result = atr._getTrueRange(currentItem, prevItem);
assert.isNumber(result);
assert.closeTo(result, expectedResult, 0.05);
};
for (let i = 0; i < 5; i++) {
let currItem = data[i];
currItem = { high: currItem[0], low: currItem[1], close: currItem[2] };
let prevItem = (i) ? data[i - 1] : null;
if (prevItem) {
prevItem = { high: prevItem[0], low: prevItem[1], close: prevItem[2] };
}
let expectedResult = expectedResults[i][3];
runTest(currItem, prevItem, expectedResult);
};
});
it('should calculate the first average true range in collection correctly and return result', () => {
let collection = [];
for (let i = 0; i < 14; i++) {
collection.push({ tr: expectedResults[i][3] });
}
let atr = new ATR();
let result = atr._calcFirstATR(collection);
assert.isNumber(result);
assert.closeTo(result, expectedResults[13][4], 0.01);
});
it('should calculate remaining average true range correctly and return results', () => {
let prevATR = expectedResults[13][4];
let currTR = expectedResults[14][3];
let atr = new ATR();
let result = atr._calcRemainingATR(prevATR, currTR, 14);
assert.isNumber(result);
assert.closeTo(result, expectedResults[14][4], 0.02);
});
it('should compute correctly and return results', () => {
let runTest = async (options, collection, expectedResults) => {
let atr = new ATR(options);
atr.setValues(collection);
let results = await atr.calculate();
assert.isArray(results);
assert.isTrue(results.length == expectedResults.length);
results.forEach((item, idx) => {
assert.isObject(item);
assert.closeTo(expectedResults[idx][3], item.tr, 0.02);
assert.closeTo(expectedResults[idx][4], item.atr, 0.02);
});
};
let collection = [];
data.forEach((item, idx) => {
collection.push({ high: item[0], low: item[1], close: item[2] });
});
runTest({ periods: 14 }, collection, expectedResults);
});
it('should throw error on invalid values', () => {
assert.throws(() => ATR(), Error);
assert.throws(() => (new ATR()).setValues(1), Error);
assert.throws(() => (new ATR()).setValues('foo'), Error);
let atr = new ATR();
atr.setValues([{ 'foo': 100 }]);
assert.throws(() => atr.calculate(), Error);
});
it('should throw error on invalid values when in async', (done) => {
let runTest = async () => {
try {
let atr = new ATR({ lazyEvaluation: true });
let r = await atr.calculate();
}
catch (err) {
return false;
}
return true;
}
(async () => {
let b = await runTest();
assert.isFalse(b);
done();
})();
})
it('should throw error on invalid options', () => {
function runTest(opts) {
opts = Object.assign({}, opts, { lazyEvaluation: false });
let atr = new ATR(opts);
atr.setValues(data);
assert.throws(() => atr.calculate(), Error);
};
[
{ periods: data.length + 1 },
{ startIndex: data.length + 1 },
{ startIndex: 1, periods: data.length },
{ endIndex: data.length + 1 },
{ periods: 'foo' },
{ startIndex: data.length, endIndex: 0 },
{ startIndex: 1, periods: 10 },
{ startIndex: 1, endIndex: 2 },
].forEach((item) => runTest(item));
});
});