Moving averages & smoothing
14 functions
MA(X, N)Simple moving average of X over N bars.
N may itself be a series, so the length can vary bar by bar. Bars before the window is full return an invalid value.
- X(series)
- The series to average — usually CLOSE.
- N(integer)
- Number of bars in the window.
// a classic three-line moving average set
MA5: MA(CLOSE, 5);
MA10: MA(CLOSE, 10);
MA20: MA(CLOSE, 20), COLORYELLOW, LINETHICK2;
// N can be a series — a length that widens with volatility
LEN := 10 + INTPART(STD(CLOSE, 20) / CLOSE * 200);
ADAPTIVE: MA(CLOSE, LEN), COLORLIBLUE;EMA(X, N)Exponential moving average, weight 2/(N+1).
- X(series)
- The series to smooth.
- N(integer)
- Number of bars; the weight of the current bar is 2/(N+1).
// MACD, written out in full
DIF: EMA(CLOSE, 12) - EMA(CLOSE, 26);
DEA: EMA(DIF, 9);
// the histogram is the gap between the two lines, doubled
MACD: (DIF - DEA) * 2, COLORSTICK;EXPMA(X, N)Exponential moving average, seeded from the first valid value.
- X(series)
- The series to smooth.
- N(integer)
- Number of bars.
// same weighting as EMA, different starting value —
// the two only differ over the first few dozen bars
FAST: EXPMA(CLOSE, 12);
SLOW: EXPMA(CLOSE, 50), COLORYELLOW;EXPMEMA(X, N)Exponential average seeded with a simple average of the first N bars — the smoother EMA variant used by DMI.
- X(series)
- The series to smooth.
- N(integer)
- Number of bars, also the length of the seeding average.
// Wilder's ATR — TR is a built-in, no need to spell it out
ATR: EXPMEMA(TR, 14), COLORYELLOW;
// the same smoothing drives DMI
ATR14 := EXPMEMA(TR, 14);
PDI: EXPMEMA(MAX(HIGH - REF(HIGH, 1), 0), 14) / ATR14 * 100;SMA(X, N, M)Chinese-style smoothed average: Y = (M·X + (N−M)·Y') / N.
The backbone of KDJ and RSI. M is the weight of the current bar, so SMA(X, N, 1) is the classic Wilder smoothing.
- X(series)
- The series to smooth.
- N(integer)
- Smoothing length — the divisor in the formula.
- M(integer)
- Weight of the current bar. M = 1 gives Wilder smoothing; M must not exceed N.
// KDJ, built from the raw stochastic
RSV := (CLOSE - LLV(LOW, 9)) / (HHV(HIGH, 9) - LLV(LOW, 9)) * 100;
K: SMA(RSV, 3, 1);
D: SMA(K, 3, 1);
J: 3 * K - 2 * D, COLORMAGENTA;DMA(X, A)Dynamic moving average: Y = A·X + (1−A)·Y'. A may be a series.
Values of A outside 0–1 are clamped to the previous output, which makes it safe to drive A from volume ratios.
- X(series)
- The series to smooth.
- A(series)
- Weight of the current bar, 0–1. May vary bar by bar; values outside the range reuse the previous output.
// let today's share of the last 20 bars' volume set the weight,
// so heavy bars pull the average harder
W := VOL / SUM(VOL, 20);
VWMA: DMA(CLOSE, W), COLORYELLOW;WMA(X, N)Linearly weighted moving average — recent bars weigh more.
- X(series)
- The series to average.
- N(integer)
- Number of bars; the oldest bar in the window weighs 1, the newest N.
// WMA turns earlier than MA of the same length
MA10: MA(CLOSE, 10), COLORGRAY;
WMA10: WMA(CLOSE, 10), COLORYELLOW;
// the Hull average is built from two WMAs
HULL: WMA(2 * WMA(CLOSE, 5) - WMA(CLOSE, 10), 3), COLORLIBLUE;MEMA(X, N)Smoothed average: Y = (X + (N−1)·Y') / N.
- X(series)
- The series to smooth.
- N(integer)
- Number of bars. Equivalent to SMA(X, N, 1).
// smoother than EMA at the same length — the tail lags more
MEMA20: MEMA(CLOSE, 20), COLORYELLOW;
EMA20: EMA(CLOSE, 20), COLORGRAY;XMA(X, N)Moving average that starts producing values before the window is full.
- X(series)
- The series to average.
- N(integer)
- Number of bars. Early bars average whatever is available so far.
// MA leaves a gap at the left edge, XMA does not —
// handy when the chart only holds a short history
MA60: MA(CLOSE, 60), COLORGRAY;
XMA60: XMA(CLOSE, 60), COLORYELLOW;AMA(X, A)Adaptive moving average: Y = Y' + A·(X − Y'), with A below 1.
- X(series)
- The series to track.
- A(series)
- How much of the gap to close each bar, below 1. Larger follows price faster.
// speed up when price trends, slow down when it chops:
// efficiency = net move / total travel over 10 bars
EFF := ABS(CLOSE - REF(CLOSE, 10)) / SUM(ABS(CLOSE - REF(CLOSE, 1)), 10);
KAMA: AMA(CLOSE, EFF * 0.6), COLORYELLOW;TMA(X, A, B)Two-coefficient moving average: Y = A·Y' + B·X, both below 1.
- X(series)
- The series to smooth.
- A(float)
- Weight carried over from the previous bar, below 1.
- B(float)
- Weight of the current bar, below 1. A + B need not be 1 — that is the point of having both.
// A + B = 1 behaves exactly like EMA with weight 0.2
LIKE_EMA: TMA(CLOSE, 0.8, 0.2), COLORGRAY;
// A + B < 1 lets the line decay toward zero between moves
DECAYING: TMA(CLOSE, 0.8, 0.1), COLORYELLOW;TRMA(X, N)Triangular moving average — a simple average applied twice.
- X(series)
- The series to average.
- N(integer)
- Number of bars for the outer window; the inner average uses about half of it.
// averaging twice kills most of the noise, at the cost of lag
TRMA20: TRMA(CLOSE, 20), COLORYELLOW;
MA20: MA(CLOSE, 20), COLORGRAY;HARMEAN(X, N)Harmonic mean over N bars. Any zero in the window invalidates the result.
- X(series)
- The series to average. Must stay non-zero across the window.
- N(integer)
- Number of bars in the window.
// the harmonic mean sits below the simple mean and is pulled
// down harder by small values — use it on rates, not prices
HM: HARMEAN(CLOSE, 20), COLORYELLOW;
AM: MA(CLOSE, 20), COLORGRAY;TSMA(X, N)Linear regression value plus its slope — the trend line projected one bar forward.
- X(series)
- The series to fit.
- N(integer)
- Number of bars in the regression window.
// the regression line, extended one bar into the future
TSMA20: TSMA(CLOSE, 20), COLORYELLOW;
// price above the projection while the slope is up
LONG := CLOSE > TSMA20 AND SLOPE(CLOSE, 20) > 0;
DRAWICON(LONG AND NOT(REF(LONG, 1)), LOW, 85);