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()afterhasValue()):ADXValueposDI: number | undefinednegDI: number | undefinedadx: number | undefined
- Warm-up:
posDI/negDIfrom candleperiod + 1;adxfrom candleperiod + 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()afterhasValue()):BeepBoopValue | undefinedtrend: "up" | "down" | "neutral"
- Warm-up:
undefineduntil 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()afterhasValue()):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
EMAinstance and aMACDinstance built on the same series. - Value (
getValue()afterhasValue()):"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()afterhasValue()):number | undefined - Warm-up:
undefineduntilperiodvalues 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()afterhasValue()):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()afterhasValue()):HalfTrendValue | undefinedhalftrendValue: numberatrHigh: numberatrLow: numbertrend: "up" | "down"
- Warm-up:
undefineduntil 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()afterhasValue()):number | undefined - Warm-up:
undefineduntil candle2 × 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()afterhasValue()):IchimokuOutputtenkan: numberkijun: numbersenkouSpanA: number | undefinedsenkouSpanB: number | undefinedchikou?: number | undefined
- Warm-up:
tenkanandkijunfrom the first candle (partial windows); the Senkou spans areundefineduntillaggingSpanPeriodcandles have passed.chikouis alwaysundefinedon the current candle. senkouSpanAandsenkouSpanBare the cloud under the CURRENT candle (the spans computedlaggingSpanPeriodcandles ago), so "price above the cloud" isclose > 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()afterhasValue()):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()afterhasValue()):number | undefined - Warm-up:
undefineduntilperiodvalues 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()afterhasValue()):number | undefined - Warm-up:
undefineduntilperiodwindows 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()afterhasValue()):number | undefined - Warm-up:
undefineduntilperioddefined 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()afterhasValue()):SARValuetrend: "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()afterhasValue()):number | undefined - Warm-up:
undefineduntilperiodvalues 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()afterhasValue()):SuperTrendValue | undefinedclose: numberbottomLine: numbertopLine: numberup: booleandown: boolean
- Warm-up:
undefineduntil the ATR hasperiodvalues. upanddownare the current direction. To act on a flip, compare with the previous value throughnew 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()afterhasValue()):TTSValuehigh?: number | undefinedlow?: number | undefinedvalue?: number | undefinedup: booleandown: booleanextreme?: number | undefined
- Warm-up:
upanddownare booleans from the first candle;value,high,lowandextremeareundefineduntil candleperiod + 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()afterhasValue()):number | undefined VIDYAOptionsis{ 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 candleperiodwhenfixedCMOLengthis 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()afterhasValue()):VWAPValuewindow: numbervwap: number
- Warm-up: Ready from the first candle; it restarts at each window boundary (UTC).
value.windowidentifies 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()afterhasValue()):number - Warm-up: Returns a number from the first candle; it averages a partial window until
periodcandles have passed, and isNaNif 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()afterhasValue()):AlligatorValuejaw: number | undefinedteeth: number | undefinedlips: number | undefined
- Warm-up: Each line is
undefineduntil 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()afterhasValue()):number | undefined - Warm-up:
undefineduntilperiodvalues 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);
});