Moving averages and trend

Moving averages, adaptive averages and trend-following overlays. See the indicator reference for how to read a signature, and Indicators for the construction and guarding rules.

ADX

Average directional index with the +DI and −DI lines (Wilder smoothing), like TradingView's DMI: DI length period, ADX smoothing adxSmoothing.

new ADX(candleIndicator: Indicator<Candle>, period: number, adxSmoothing: number = period)
Parameter Type Default Meaning
candleIndicator Indicator<Candle> required The candle series.
period number required DI length (14 classically).
adxSmoothing number period ADX smoothing length (period by default).
  • Input: The candle series.
  • Value (getValue() after hasValue()): ADXValue
    • posDI: number | undefined
    • negDI: number | undefined
    • adx: number | undefined
  • Warm-up: posDI / negDI from candle period + 1; adx from candle period + adxSmoothing.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new ADX(candles, 14);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value.adx === undefined || value.posDI === undefined || value.negDI === undefined) return;
  manager.debugLog('ADX', value.adx, '+DI', value.posDI, '-DI', value.negDI);
});

BeepBoop

Trend label from a MACD(12, 26, 9) histogram sign and the candle position relative to a 50-period EMA: 'up' when the histogram is positive and the whole candle is above the EMA, 'down' for the mirror case, 'neutral' otherwise.

new BeepBoop(candleIndicator: ICandleIndicator, maType: 'ema' | 'sma')
Parameter Type Default Meaning
candleIndicator ICandleIndicator required The candle series.
maType 'ema' | 'sma' required Averages used by the MACD: 'ema' or 'sma'.
  • Input: The candle series.
  • Value (getValue() after hasValue()): BeepBoopValue | undefined
    • trend: "up" | "down" | "neutral"
  • Warm-up: undefined until the MACD histogram and the EMA50 are both ready (about 50 candles).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new BeepBoop(candles, 'ema');

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('trend', value.trend);
});

EIT

Ehlers instantaneous trendline, computed with a Hilbert-transform estimate of the dominant cycle.

new EIT(sourceIndicator: Indicator<number>)
Parameter Type Default Meaning
sourceIndicator Indicator<number> required The number stream (usually candles.hl2).
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: Needs a few dozen candles before the cycle estimate settles; treat the first ~50 values as unreliable.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new EIT(candles.hl2);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('EIT', value);
});

Elder

Elder impulse system: 'bullish' when both the EMA and the MACD histogram rose since the previous candle, 'bearish' when both fell, 'neutral' otherwise.

new Elder(emaIndicator: EMA, macdIndicator: MACD)
Parameter Type Default Meaning
emaIndicator EMA required An EMA (13 periods classically).
macdIndicator MACD required A MACD (12, 26, 9 classically).
  • Input: An EMA instance and a MACD instance built on the same series.
  • Value (getValue() after hasValue()): "neutral" | "bullish" | "bearish"
  • Warm-up: Returns 'neutral' until both inputs have two consecutive values (about 35 candles with the classic settings).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new Elder(new EMA(candles.close, 13), new MACD(candles.close, 'ema', 12, 26, 'ema', 9));

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  manager.debugLog('impulse', value);
});

EMA

Exponential moving average, seeded with the simple average of the first period values, then value = source × α + previous × (1 − α) with α = smoothing / (1 + period).

new EMA(sourceIndicator: Indicator<number | undefined>, period: number, smoothing: number = 2)
Parameter Type Default Meaning
sourceIndicator Indicator<number | undefined> required The number stream to average.
period number required The averaging length.
smoothing number 2 The smoothing factor numerator (2 gives the standard EMA).
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: undefined until period values have been seen.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new EMA(candles.close, 20);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('EMA20', value);
});

FIR

A 4-tap finite-impulse-response smoother: (4·x0 + 3·x1 + 2·x2 + x3) / 10.

new FIR(sourceIndicator: Indicator<number>)
Parameter Type Default Meaning
sourceIndicator Indicator<number> required The number stream to smooth.
  • Input: A number stream.
  • Value (getValue() after hasValue()): number
  • Warm-up: Returns a number from the first candle (partial weights for the first 3).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new FIR(candles.close);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  manager.debugLog('FIR', value);
});

HalfTrend

HalfTrend: a trend line that follows the amplitude-candle high/low averages and flips on a break, with ATR channels.

new HalfTrend(candleIndicator: ICandleIndicator, amplitude: number, channelDeviation: number)
Parameter Type Default Meaning
candleIndicator ICandleIndicator required The candle series.
amplitude number required Look-back for the high/low averages.
channelDeviation number required ATR channel width multiplier (ATR is a fixed 100-period Wilder average).
  • Input: The candle series.
  • Value (getValue() after hasValue()): HalfTrendValue | undefined
    • halftrendValue: number
    • atrHigh: number
    • atrLow: number
    • trend: "up" | "down"
  • Warm-up: undefined until its 100-period ATR is ready: first value on candle 100.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new HalfTrend(candles, 2, 2);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('trend', value.trend, 'line', value.halftrendValue);
});

HullMovingAverage

Hull moving average: WMA(2 × WMA(n/2) − WMA(n), √n), a low-lag average.

new HullMovingAverage(sourceIndicator: Indicator<number | undefined>, period: number = 9)
Parameter Type Default Meaning
sourceIndicator Indicator<number | undefined> required The number stream to average.
period number 9 The Hull length.
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: undefined until candle 2 × period − 1 (17 for period 9).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new HullMovingAverage(candles.close, 9);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('HMA9', value);
});

Ichimoku

Ichimoku cloud: Tenkan and Kijun (midpoints of the tPeriod / kPeriod high-low range), Senkou spans A and B, and the lagging span.

new Ichimoku(candleIndicator: ICandleIndicator, tPeriod: number, kPeriod: number, ssbPeriod: number, laggingSpanPeriod: number)
Parameter Type Default Meaning
candleIndicator ICandleIndicator required The candle series.
tPeriod number required Tenkan-sen length (9 classically).
kPeriod number required Kijun-sen length (26).
ssbPeriod number required Senkou span B length (52).
laggingSpanPeriod number required Displacement of the spans and the lagging span (26).
  • Input: The candle series.
  • Value (getValue() after hasValue()): IchimokuOutput
    • tenkan: number
    • kijun: number
    • senkouSpanA: number | undefined
    • senkouSpanB: number | undefined
    • chikou?: number | undefined
  • Warm-up: tenkan and kijun from the first candle (partial windows); the Senkou spans are undefined until laggingSpanPeriod candles have passed. chikou is always undefined on the current candle.
  • senkouSpanA and senkouSpanB are the cloud under the CURRENT candle (the spans computed laggingSpanPeriod candles ago), so "price above the cloud" is close > Math.max(senkouSpanA, senkouSpanB).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new Ichimoku(candles, 9, 26, 52, 26);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value.senkouSpanA === undefined || value.senkouSpanB === undefined) return;
  manager.debugLog('tenkan', value.tenkan, 'kijun', value.kijun, 'cloud', value.senkouSpanA, value.senkouSpanB);
});

KAMA

Kaufman adaptive moving average: its smoothing speeds up in trends and slows down in noise, based on the efficiency ratio over length values.

new KAMA(sourceIndicator: Indicator<number | undefined>, length: number, fastAlpha: number = 2, slowAlpha: number = 30, useLog: boolean = false)
Parameter Type Default Meaning
sourceIndicator Indicator<number | undefined> required The number stream to average.
length number required The efficiency-ratio lookback.
fastAlpha number 2 Fast smoothing length (2 by default).
slowAlpha number 30 Slow smoothing length (30 by default).
useLog boolean false Average the logarithm of the source and return exp of the result.
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: First value on candle length + 1.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new KAMA(candles.close, 10);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('KAMA10', value);
});

LinearRegression

The value, at the current candle, of the least-squares line fitted to the last period values.

new LinearRegression(sourceIndicator: Indicator<number | undefined>, period: number)
Parameter Type Default Meaning
sourceIndicator Indicator<number | undefined> required The number stream to fit.
period number required The fitting window.
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: undefined until period values have been seen.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new LinearRegression(candles.close, 20);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('linreg20', value);
});

MVWAP

Moving VWAP: the average of the last period completed VWAP windows (days, weeks or months).

new MVWAP(candleIndicator: ICandleIndicator, window: 'day' | 'week' | 'month', period: number)
Parameter Type Default Meaning
candleIndicator ICandleIndicator required The candle series.
window 'day' | 'week' | 'month' required The VWAP window: 'day', 'week' or 'month'.
period number required How many completed windows to average.
  • Input: The candle series.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: undefined until period windows have completed (5 days of candles for 'day', 5).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new MVWAP(candles, 'day', 5);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('MVWAP', value);
});

RMA

Wilder's running moving average (the smoothing used by RSI and ATR): seeded with a simple average, then value = (previous × (period − 1) + source) / period.

new RMA(sourceIndicator: Indicator<number | undefined>, period: number)
Parameter Type Default Meaning
sourceIndicator Indicator<number | undefined> required The number stream to smooth.
period number required The smoothing length.
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: undefined until period defined values have been seen. new RMA(new TR(candles), 14) is the standard 14-period ATR.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new RMA(new TR(candles), 14);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('ATR14', value);
});

SAR

Parabolic SAR: a trailing stop-and-reverse level that accelerates with the trend.

new SAR(candleIndicator: Indicator<Candle>, accfStart: number = 0.02, accfIncrement: number = 0.02, accfMax: number = 0.20)
Parameter Type Default Meaning
candleIndicator Indicator<Candle> required The candle series.
accfStart number 0.02 Initial acceleration factor.
accfIncrement number 0.02 Acceleration increment at each new extreme.
accfMax number 0.20 Maximum acceleration factor.
  • Input: The candle series.
  • Value (getValue() after hasValue()): SARValue
    • trend: "bullish" | "bearish"
    • value: number
  • Warm-up: Ready from the first candle; the first few values are an initialisation and should not drive trades.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new SAR(candles);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  manager.debugLog('SAR', value.value, value.trend);
});

SMA

Simple moving average: the arithmetic mean of the last period values.

new SMA(sourceIndicator: Indicator<number | undefined>, period: number)
Parameter Type Default Meaning
sourceIndicator Indicator<number | undefined> required The number stream to average.
period number required Number of values averaged.
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: undefined until period values have been seen.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new SMA(candles.close, 50);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('SMA50', value);
});

SuperTrend

SuperTrend: ATR bands around the median price (hl2 ± multiplier × ATR), flipping direction when the close crosses the active band.

new SuperTrend(candleIndicator: Indicator<Candle>, period: number, multiplier: number)
Parameter Type Default Meaning
candleIndicator Indicator<Candle> required The candle series.
period number required ATR length (Wilder smoothing).
multiplier number required Band width in ATRs.
  • Input: The candle series.
  • Value (getValue() after hasValue()): SuperTrendValue | undefined
    • close: number
    • bottomLine: number
    • topLine: number
    • up: boolean
    • down: boolean
  • Warm-up: undefined until the ATR has period values.
  • up and down are the current direction. To act on a flip, compare with the previous value through new History(supertrend, 2).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new SuperTrend(candles, 10, 3);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog(value.up ? 'bullish' : 'bearish', 'stop line', value.up ? value.bottomLine : value.topLine);
});

TTS

Trend Trader Strategy line: a trailing level at the period extreme offset by a weighted ATR multiple, with up / down direction flags.

new TTS(candleIndicator: Indicator<Candle>, period: number, multiplier: number)
Parameter Type Default Meaning
candleIndicator Indicator<Candle> required The candle series.
period number required Look-back for the extreme and the weighted ATR.
multiplier number required ATR multiple subtracted from / added to the extreme.
  • Input: The candle series.
  • Value (getValue() after hasValue()): TTSValue
    • high?: number | undefined
    • low?: number | undefined
    • value?: number | undefined
    • up: boolean
    • down: boolean
    • extreme?: number | undefined
  • Warm-up: up and down are booleans from the first candle; value, high, low and extreme are undefined until candle period + 2.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new TTS(candles, 21, 3);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value.value === undefined) return;
  manager.debugLog('TTS', value.value, value.up ? 'up' : value.down ? 'down' : 'flat');
});

VIDYA

Variable Index Dynamic Average: an EMA whose smoothing is scaled by the absolute Chande momentum (or by a standard-deviation ratio when useCMO is false).

new VIDYA(sourceIndicator: Indicator<number | undefined>, options: VIDYAOptions = {})
Parameter Type Default Meaning
sourceIndicator Indicator<number | undefined> required The number stream to average.
options VIDYAOptions {} Optional { period?: number (9), fixedCMOLength?: boolean (true: CMO over 9 values), useCMO?: boolean (true) }.
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • VIDYAOptions is { period?: number | undefined; fixedCMOLength?: boolean | undefined; useCMO?: boolean | undefined }.
  • Warm-up: First value on candle 9 with the default fixedCMOLength: true (the CMO window is fixed at 9), or on candle period when fixedCMOLength is false.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new VIDYA(candles.close, { period: 14 });

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('VIDYA14', value);
});

VWAP

Volume-weighted average price, reset at each UTC day, week (Monday) or calendar month.

new VWAP(candleIndicator: Indicator<Candle>, sourceIndicator: Indicator<number>, window: 'day' | 'week' | 'month')
Parameter Type Default Meaning
candleIndicator Indicator<Candle> required The candle series (volume and time come from it).
sourceIndicator Indicator<number> required The price averaged (typically candles.hlc3).
window 'day' | 'week' | 'month' required When the average resets: 'day', 'week' or 'month'.
  • Input: The candle series plus a price stream.
  • Value (getValue() after hasValue()): VWAPValue
    • window: number
    • vwap: number
  • Warm-up: Ready from the first candle; it restarts at each window boundary (UTC). value.window identifies the current window.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new VWAP(candles, candles.hlc3, 'day');

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  manager.debugLog('VWAP', value.vwap);
});

VWMA

Volume-weighted moving average: Σ(price × volume) / Σ(volume) over the last period candles.

new VWMA(priceIndicator: Indicator<number>, volumeIndicator: Indicator<number>, period: number)
Parameter Type Default Meaning
priceIndicator Indicator<number> required The price stream (for example candles.close).
volumeIndicator Indicator<number> required The volume stream (candles.volume).
period number required The window length.
  • Input: Two number streams: price and volume.
  • Value (getValue() after hasValue()): number
  • Warm-up: Returns a number from the first candle; it averages a partial window until period candles have passed, and is NaN if the window's volume is zero.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new VWMA(candles.close, candles.volume, 20);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  manager.debugLog('VWMA20', value);
});

WilliamsAlligator

Williams Alligator: three Wilder averages of the median price (jaw, teeth, lips), each shifted forward by its offset.

new WilliamsAlligator(candleIndicator: ICandleIndicator, jawPeriod: number = 13, jawOffset: number = 8, teethPeriod: number = 8, teethOffset: number = 5, lipsPeriod: number = 5, lipsOffset: number = 3)
Parameter Type Default Meaning
candleIndicator ICandleIndicator required The candle series.
jawPeriod number 13 Jaw average length.
jawOffset number 8 Jaw forward shift, in candles.
teethPeriod number 8 Teeth average length.
teethOffset number 5 Teeth forward shift.
lipsPeriod number 5 Lips average length.
lipsOffset number 3 Lips forward shift.
  • Input: The candle series.
  • Value (getValue() after hasValue()): AlligatorValue
    • jaw: number | undefined
    • teeth: number | undefined
    • lips: number | undefined
  • Warm-up: Each line is undefined until its average plus its offset have passed (jaw: 13 + 8 = 21 candles with the defaults).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new WilliamsAlligator(candles);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value.jaw === undefined || value.teeth === undefined || value.lips === undefined) return;
  manager.debugLog('jaw', value.jaw, 'teeth', value.teeth, 'lips', value.lips);
});

WMA

Linearly weighted moving average: the newest value weighs period, the oldest weighs 1.

new WMA(sourceIndicator: Indicator<number | undefined>, period: number)
Parameter Type Default Meaning
sourceIndicator Indicator<number | undefined> required The number stream to average.
period number required Number of values averaged.
  • Input: A number stream.
  • Value (getValue() after hasValue()): number | undefined
  • Warm-up: undefined until period values have been seen.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new WMA(candles.close, 20);

manager.onIntervalCandle(symbol, 60, () => {
  if (!indicator.hasValue()) return;
  const value = indicator.getValue();
  if (value === undefined) return;
  manager.debugLog('WMA20', value);
});
Browse the documentation