UNPKG

@ldrick/trade-indicators

Version:
31 lines (30 loc) 1.67 kB
import { apply as AP, either as E, function as F, option as O, readonlyArray as RA, readonlyNonEmptyArray as RNEA, } from 'fp-ts/lib'; import { smmaC } from '../averages/smma.js'; import { UnequalArraySizesError } from '../errors/UnequalArraySizesError.js'; import * as arr from '../utils/array.js'; import * as big from '../utils/big.js'; import * as num from '../utils/number.js'; import * as rec from '../utils/record.js'; const trueRange = (values) => F.pipe(values.high, arr.tail, E.chain(RNEA.traverseWithIndex(E.Applicative)((index, high) => F.pipe(O.bindTo('previousClose')(RA.lookup(index)(values.close)), O.bind('currentLow', () => RA.lookup(index + 1)(values.low)), O.map(({ previousClose, currentLow }) => big.max([ high.sub(currentLow), high.sub(previousClose).abs(), currentLow.sub(previousClose).abs(), ])), E.fromOption(() => new UnequalArraySizesError()))))); /** * ATR without checks and conversion. * * @internal */ export const atrC = (values, period) => F.pipe(values, trueRange, E.chain((tr) => smmaC(tr, period))); /** * The Average True Range (ATR) a period of the True Range Indicator, * being the greatest out of current high minus the current low, * the absolute value of current high minus previous close * and the absolute value of the current low minus the prevous close. * * @public */ export const atr = (values, period = 14) => F.pipe(AP.sequenceS(E.Applicative)({ periodV: num.validatePositiveInteger(period), valuesV: rec.validateRequiredSize(period + 1)(values), }), E.bind('valuesB', ({ valuesV }) => rec.toBig(valuesV)), E.chain(({ valuesB, periodV }) => atrC(valuesB, periodV)), E.map(arr.toNumber));