TradingView indicator calculations

Zero-lag MACD: compare the oscillator and its signal line

Zero-lag MACD replaces conventional smoothing with a lag-reduction formula, but the name does not identify one algorithm. DEMA MACD subtracts two double exponential moving averages; ZLEMA MACD subtracts two averages of lag-compensated inputs. The signal line is a separate choice. Changing either stage changes crossings, and neither structure guarantees zero delay or better trades.

See the decision guide

Three smoothing structures with different arithmetic

Let E_N(x) be an EMA with alpha = 2/(N + 1): E[t] = alpha × x[t] + (1 − alpha) × E[t−1]. For this audit, each EMA starts at its first valid input. Let F, S and G be the fast, slow and signal lengths, with F < S. Every histogram is M − Signal. These are explicit public-formula implementations, not replicas of a named private script.

  • DEMA doubles the first EMA and subtracts its second smoothing. Applying EMA twice without that subtraction is a different, slower filter.
  • ZLEMA compensates the input before averaging. Its lag is an integer: N = 12 uses L = 5 with floor rounding. A script that rounds differently can disagree.
  • TradingView exposes oscillator and signal MA choices in its standard MACD. Select EMA for both when checking the baseline here.
StructureMACD line MSignal choices
Standard EMA MACDE_F(close) − E_S(close)E_G(M) in this baseline
DEMA MACDD_F(close) − D_S(close), where D_N(x) = 2E_N(x) − E_N(E_N(x))E_G(M) gives a hybrid; D_G(M) gives a DEMA signal
Compensated-input ZLEMA MACDZ_F(close) − Z_S(close), where Z_N(x) = E_N(2x[t] − x[t−L]), L = floor((N − 1)/2)E_G(M), D_G(M) or Z_G(M) are different systems

A price step moves the crossover by two bars

This is a synthetic calculation, not a market backtest. Use 60 bars at 100, followed by bars held at 110. Set F = 3, S = 5 and G = 3. Bar 1 below is the first 110 bar; all earlier MACD and signal values are zero. The table shows histogram values rounded to six decimals. A cross below the signal occurs when the histogram becomes negative after being nonnegative.

  • At bar 1, standard fast EMA = 105 and slow EMA = 103.333333, so M = 1.666667. Its EMA signal is 0.833333, leaving a histogram of 0.833333.
  • At bar 2, DEMA MACD = 110 − 108.518519 = 1.481481. Its DEMA signal is 1.597222, so the histogram is −0.115741. Keeping the same MACD but using an EMA signal leaves a positive 0.254630.
  • The DEMA/DEMA crossing is two bars earlier than the standard baseline in this fixture. Price stays at 110 throughout: the earlier bearish crossing does not identify a falling price or prove a better exit. On other inputs the offset can change.
Step barEMA / EMADEMA / EMADEMA / DEMAZLEMA / EMA
10.8333330.9722220.4861111.666667
20.5555560.254630−0.115741−1.388889
30.162037−0.300926−0.335648−0.509259
4−0.100309−0.479681−0.257202−0.131173
First cross below signalBar 4Bar 3Bar 2Bar 2

Overshoot can reverse the MACD while price stays flat

On the same step, the fast DEMA reaches 110.625 at bar 3 and the slow DEMA reaches 110.658436 at bar 4. Both exceed the new price of 110. At bar 4, their difference is −0.033436 even though price has never fallen. That zero-line crossing is separate from the bar-2 signal crossing.

  • The overshoot comes from the filter weights, not a future price observation. A curve can respond quickly and still be a poor description of the current price level.
  • For a noise fixture, alternate prices between 101 and 99 for 300 bars. At settled values, the EMA MACD amplitude is 0.133333 and the DEMA MACD amplitude is 0.195556. DEMA amplifies this alternating input by about 1.47 times relative to the baseline.
  • The signal filter also matters: settled histogram amplitudes are 0.088889 for EMA/EMA, 0.130370 for DEMA/EMA and 0.086914 for DEMA/DEMA. All alternate each bar in this fixture. A larger MACD amplitude does not automatically mean a larger histogram or more crossings.
Filter in the fixtureObserved valueMeaning
Fast EMA, bar 3108.750000Still approaches 110 from below
Fast DEMA, bar 3110.625000Overshoots by 0.625 price points
Slow ZLEMA, bar 2111.111111Overshoots by 1.111111 price points
ZLEMA MACD, bar 2−1.111111Fast average is 110; slow average is above it

A three-period ZLEMA signal can erase the histogram

For G = 3, alpha = 1/2 and L = 1. The signal recurrence becomes Z[t] = M[t] − 0.5M[t−1] + 0.5Z[t−1]. Once Z[t−1] = M[t−1], it follows that Z[t] = M[t]. With the constant prehistory used above, a ZLEMA signal therefore tracks the MACD exactly in ideal arithmetic and the histogram is zero.

  • Finite-precision arithmetic can leave tiny residues near zero. Do not interpret those as meaningful crossings. A script that adds thresholds or rounds values is defining another rule.
  • G = 1 also makes an EMA or DEMA signal equal to its input and removes the histogram. The code allows this mathematical boundary, but it is not a useful crossover configuration.
  • The audit below compares EMA and DEMA signal choices. It deliberately does not offer a ZLEMA signal; the degenerate G = 3 case is explained here so the label cannot hide it.

Audit the variants in Pine Script v6

This indicator plots a standard EMA/EMA baseline and a selected DEMA or ZLEMA oscillator with an EMA or DEMA signal. Defaults are the short 3/5/3 fixture settings, not recommended trading parameters. Enable the step fixture to reproduce the table, then inspect Fixture step bar in the Data Window. Synthetic mode disables alerts.

  • The custom EMA seeds at its first valid input, returns na on a missing input and restarts at the next valid input. ZLEMA waits for its lagged input. Different seeding or gap policies can change early values.
  • All filter functions run on every bar. The fixture needs at least 64 loaded chart bars to include step bars 1 through 4. Changing the lengths means the published numerical table no longer applies.
  • The live line can change before a bar closes. Only the alert conditions require barstate.isconfirmed; this is a chart-timeframe script with no higher-timeframe requests.
An independent public-formula audit. Compare values in TradingView before using a market alert; syntax checking does not validate trading performance.pine
//@version=6
indicator("Zero-lag MACD calculation audit", overlay=false, precision=6, max_bars_back=500)
fastLen = input.int(3, "Fast length", minval=1, maxval=100)
slowLen = input.int(5, "Slow length", minval=2, maxval=100)
signalLen = input.int(3, "Signal length", minval=1, maxval=100)
oscillator = input.string("DEMA", "Selected oscillator", options=["DEMA", "ZLEMA"])
signalType = input.string("DEMA", "Selected signal", options=["EMA", "DEMA"])
fixture = input.bool(false, "Use 100 to 110 step fixture")
if fastLen >= slowLen
    runtime.error("Fast length must be below slow length.")
emaSeed(float x, int n) =>
    float value = na
    float alpha = 2.0 / (n + 1.0)
    value := na(x) ? na : na(value[1]) ? x : alpha * x + (1.0 - alpha) * value[1]
    value
dema(float x, int n) =>
    float first = emaSeed(x, n)
    2.0 * first - emaSeed(first, n)
zlema(float x, int n) =>
    int lag = int(math.floor((n - 1) / 2.0))
    emaSeed(2.0 * x - x[lag], n)
source = fixture ? (bar_index < 60 ? 100.0 : 110.0) : close
standard = emaSeed(source, fastLen) - emaSeed(source, slowLen)
standardSignal = emaSeed(standard, signalLen)
demaFast = dema(source, fastLen)
demaSlow = dema(source, slowLen)
zlemaFast = zlema(source, fastLen)
zlemaSlow = zlema(source, slowLen)
selectedFast = oscillator == "DEMA" ? demaFast : zlemaFast
selectedSlow = oscillator == "DEMA" ? demaSlow : zlemaSlow
selected = selectedFast - selectedSlow
emaSignal = emaSeed(selected, signalLen)
demaSignal = dema(selected, signalLen)
selectedSignal = signalType == "EMA" ? emaSignal : demaSignal
histogram = selected - selectedSignal
plot(standard, "Standard EMA MACD", color=color.gray)
plot(standardSignal, "Standard EMA signal", color=color.silver)
plot(selected, "Selected MACD", color=color.blue, linewidth=2)
plot(selectedSignal, "Selected signal", color=color.orange, linewidth=2)
plot(histogram, "Selected histogram", style=plot.style_histogram, color=histogram >= 0 ? color.teal : color.red)
plot(selectedFast, "Selected fast average", display=display.data_window)
plot(selectedSlow, "Selected slow average", display=display.data_window)
plot(standard - standardSignal, "Standard histogram", display=display.data_window)
plot(bar_index - 59, "Fixture step bar", display=display.data_window)
hline(0, "Zero", color=color.gray)
crossUp = ta.crossover(selected, selectedSignal)
crossDown = ta.crossunder(selected, selectedSignal)
ready = not na(selectedSignal[1]) and not fixture
alertcondition(ready and barstate.isconfirmed and crossUp, "Confirmed MACD cross up", "Selected MACD crossed above its signal on a closed chart bar.")
alertcondition(ready and barstate.isconfirmed and crossDown, "Confirmed MACD cross down", "Selected MACD crossed below its signal on a closed chart bar.")

Compare numbers before interpreting alerts

Add the audit to a standard candle chart. For the fixture, keep 3/5/3 and compare the Data Window values at step bars 1 through 4. For market data, turn the fixture off, choose the intended lengths, and add TradingView MACD with the same source and EMA settings for both averages.

  • Record symbol, timeframe, session, adjustment settings, available history and each smoothing choice. Compare completed bars after initialization, not only the appearance of the curves.
  • If the selected MACD matches but crossings differ, compare the signal value and initialization first. If both lines match but alerts differ, check bar-close timing and alert frequency.
  • Create an alert from Confirmed MACD cross up or down only after those checks. Recreate it after changing the script or inputs because TradingView alerts retain a snapshot of their setup.
  • A crossover is a calculation event. Entries still need execution assumptions, exits, position sizing, costs and independent testing. The examples here do not test a trading strategy.

Turn a verified calculation into an editable script

Give the Pine Script AI Coding Agent the chosen oscillator formula, signal smoother, lengths, seed rule, missing-input policy and closed-bar condition. Ask it to keep diagnostic plots and the synthetic fixture while drafting changes, then request a syntax check and compare the TradingView values yourself.

  • Use the formula names and recurrence, not only the phrase zero lag MACD. Ask for DEMA fast/slow with an EMA signal if that is the intended hybrid.
  • Pineify can create and update Pine source documents. A generated script still needs numerical review; a prompt cannot establish equivalence to unavailable proprietary source.
Where Pineify fits

Pine Script AI Coding Agent

Draft a MACD variant from explicit smoothing and confirmation rules, then review its code and compare the plotted calculations.

Draft a specified MACD variant

Frequently asked questions

Educational calculations, not investment advice. All example prices are synthetic. Faster crossings and syntax-valid code do not establish profitability. No proprietary indicator is reproduced or endorsed.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.