Indicators/probuilder · probacktest · proorder · proscreener

ZLEMA

ZLEMA in ProBuilder returns the Zero Lag Exponential Moving Average, an EMA variant that reduces lag for faster trend signals. Syntax, formula, examples.

Syntax

probuilder
ZLEMA[period](price)

Parameters

NameTypeDefaultDescription
periodinteger20Length of the exponential average and basis of the lag correction.
priceprice sourcecloseThe series being averaged. Accepts close, open, high, low, or a custom variable.

Formula

code
lag   = (period - 1) / 2
ZLEMA = EMA[period](price + (price - price[lag]))

The term price - price[lag] estimates how far a conventional average trails price, and adding it to the input shifts the data forward by roughly that amount before the EMA is applied.

How it works

Every moving average lags, because it summarises a window of past data whose centre of mass sits behind the current bar. For an EMA of length period that displacement is about (period - 1) / 2 bars. The ZLEMA compensates by feeding the EMA a modified series: the current price plus the change since lag bars ago. When price trends steadily, the correction cancels most of the delay and the line runs close to price; when price is flat, the correction term is near zero and the ZLEMA behaves like a plain EMA.

The compensation is an extrapolation, so it has a cost. At sharp turning points the de-lagged input briefly points the wrong way, producing overshoot and occasional whipsaw signals that a slower average would have filtered. ZLEMA belongs to the same low-lag family as DEMA, TEMA, and HullAverage, each of which trades smoothness for responsiveness with a different construction.

Examples

Example 1, 15-period ZLEMA of the close (Indicator)

probuilder
// Zero lag exponential average over 15 bars
myZLEMA = ZLEMA[15](close)
RETURN myZLEMA

The source example: computes and plots the 15-period ZLEMA of closing prices, which stays visibly closer to price than a 15-period EMA.

Example 2, ZLEMA versus EMA crossover (ProBacktest)

probuilder
// Use the faster ZLEMA against a plain EMA of the same length
fastLine = ZLEMA[20](close)
slowLine = ExponentialAverage[20](close)

IF fastLine CROSSES OVER slowLine THEN
  BUY 1 CONTRACT AT MARKET
ENDIF
IF fastLine CROSSES UNDER slowLine THEN
  SELL AT MARKET
ENDIF

Because ZLEMA leads an equal-length EMA, crossing the two lines of the same period produces a momentum-style signal without needing two different lengths.

Example 3, Screening for a fresh ZLEMA slope change (ProScreener)

probuilder
// Instruments whose 20-bar ZLEMA just turned upward
z = ZLEMA[20](close)
turnedUp = z > z[1] AND z[1] <= z[2]
SCREENER[turnedUp](((close / z) - 1) * 100 AS "% vs ZLEMA")

Returns instruments where the ZLEMA slope flipped from non-rising to rising on the current bar, an early trend-turn scan that benefits from the reduced lag.

Interpretation

ZLEMA is read like any moving average. Price above a rising line suggests an uptrend, price below a falling line a downtrend, and crossovers, either price against the line or two averages against each other, mark potential trend changes. Signals arrive earlier than with an equal-length EMA or SMA.

Earlier does not mean better. The lag reduction comes from extrapolating recent momentum, so in choppy conditions the ZLEMA generates more false starts than slower averages. It suits systems where late entries are the dominant cost, and it pairs naturally with a confirmation filter such as a longer average or a volatility measure.

Common errors and gotchas

  • Wrong bracket types. The period goes in square brackets and the price in parentheses: ZLEMA[20](close). ZLEMA(20, close) does not compile.
  • Expecting EMA-like smoothness. For the same period, ZLEMA is jumpier and overshoots at reversals. Dropping it into a system tuned for ExponentialAverage changes trade frequency and results.
  • Very short periods. With small period values the lag term is nearly zero and the line collapses toward raw price, adding noise without benefit. The technique needs a meaningful lag to remove.
  • Treating zero lag literally. The name is aspirational. The correction removes most steady-state lag but cannot anticipate turns, and the residual delay grows exactly when it matters, at reversals.