diff --git a/.prettierrc.json b/.prettierrc.json index 544138b..c1a6f66 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,3 +1,4 @@ { - "singleQuote": true + "singleQuote": true, + "trailingComma": "es5" } diff --git a/src/indicator/momentum/index.md b/src/indicator/momentum/index.md index 10542d0..0da909c 100644 --- a/src/indicator/momentum/index.md +++ b/src/indicator/momentum/index.md @@ -138,7 +138,7 @@ const result = defaultPercentageVolumeOscillator(volumes); #### Price Rate of Change (ROC) -The [roc](./priceRateOfChange.ts) function calculates a unbounded momentum indicator for the closing prices. A rising ROC above zero typically indicates an uptrend whereas a falling ROC below zero indicates a downtrend. +The [roc](./priceRateOfChange.ts) function calculates a unbounded momentum indicator for the closing prices. A rising ROC above zero typically indicates an uptrend whereas a falling ROC below zero indicates a downtrend. ``` ROC[i] = 0 when i < period diff --git a/src/indicator/momentum/priceRateOfChange.test.ts b/src/indicator/momentum/priceRateOfChange.test.ts index a7d5267..e8665ea 100644 --- a/src/indicator/momentum/priceRateOfChange.test.ts +++ b/src/indicator/momentum/priceRateOfChange.test.ts @@ -1,9 +1,9 @@ -import { deepStrictEqual } from "assert"; -import { roundDigitsAll } from "../../helper/numArray"; -import { roc } from "./priceRateOfChange"; +import { deepStrictEqual } from 'assert'; +import { roundDigitsAll } from '../../helper/numArray'; +import { roc } from './priceRateOfChange'; -describe("Price Rate of Change (ROC)", () => { - it("should be able to compute ROC", () => { +describe('Price Rate of Change (ROC)', () => { + it('should be able to compute ROC', () => { const values = [1, 3, 5, 4, 2, 5, 3]; const expected = [0, 0, 0, 300, -33.33, 0, -25]; const period = 3; diff --git a/src/indicator/volatility/atr.ts b/src/indicator/volatility/atr.ts index 4b54594..b902fe7 100644 --- a/src/indicator/volatility/atr.ts +++ b/src/indicator/volatility/atr.ts @@ -1,7 +1,7 @@ // Copyright (c) 2022 Onur Cinar. All Rights Reserved. // https://github.com/cinar/indicatorts -import { checkSameLength, max, subtract } from '../../helper/numArray'; +import { tr } from './tr'; import { sma } from '../../indicator/trend/sma'; /** @@ -32,14 +32,7 @@ export function atr( lows: number[], closings: number[] ): AtrResult { - checkSameLength(highs, lows, closings); - - const trLine = max( - subtract(highs, lows), - subtract(highs, closings), - subtract(closings, lows) - ); - + const trLine = tr(period, highs, lows, closings); const atrLine = sma(period, trLine); return { diff --git a/src/indicator/volatility/keltnerChannel.test.ts b/src/indicator/volatility/keltnerChannel.test.ts index be8efd4..bc9e4b6 100644 --- a/src/indicator/volatility/keltnerChannel.test.ts +++ b/src/indicator/volatility/keltnerChannel.test.ts @@ -10,8 +10,8 @@ describe('Keltner Channel', () => { const lows = [6, 7, 9, 12, 10]; const closings = [9, 11, 7, 10, 8]; const expectedMiddleLine = [9, 9.19, 8.98, 9.08, 8.98]; - const expectedUpperBand = [17, 17.19, 17.65, 17.58, 17.38]; - const expectedLowerBand = [1, 1.19, 0.32, 0.58, 0.58]; + const expectedUpperBand = [17, 15.19, 14.98, 17.08, 16.18]; + const expectedLowerBand = [1, 3.19, 2.98, 1.08, 1.78]; const actual = defaultKeltnerChannel(highs, lows, closings); expect(roundDigitsAll(2, actual.middleLine)).toStrictEqual( diff --git a/src/indicator/volatility/tr.ts b/src/indicator/volatility/tr.ts new file mode 100644 index 0000000..5507c92 --- /dev/null +++ b/src/indicator/volatility/tr.ts @@ -0,0 +1,40 @@ +// Copyright (c) 2022 Onur Cinar. All Rights Reserved. +// https://github.com/cinar/indicatorts + +import { + abs, + checkSameLength, + max, + shiftRightAndFillBy, + subtract, +} from '../../helper/numArray'; + +/** + * True Range (TR). + * + * TR = Max((High - Low), Abs(High - Closing[-1]), Abs(Low - Closing[-1])) + * + * @param period window period. + * @param highs high values. + * @param lows low values. + * @param closings closing values. + * @return tr values. + */ +export function tr( + period: number, + highs: number[], + lows: number[], + closings: number[] +): number[] { + checkSameLength(highs, lows, closings); + + const previous = shiftRightAndFillBy(1, closings[0], closings); + + const result = max( + subtract(highs, lows), + abs(subtract(highs, previous)), + abs(subtract(lows, previous)) + ); + + return result; +}