DEMA Indicator: Formula, Settings and How to Read It

DEMA (Double Exponential Moving Average, Patrick Mulloy, 1994) is a smoothed price line built from two exponential averages arranged so that part of the lag of a single EMA is cancelled. It is computed as twice the EMA of close minus the EMA applied to that first EMA, and is drawn on the price chart.

Senzoukria · Indicators · Updated September 2026


DEMA ships with the Senzoukria desktop app, in the Averages & volatility group of the indicator catalogue. It is drawn on the price chart.

What DEMA measures

Both stages use the catalogue's EMA: seeded with the simple average of the first N samples, then updated with a smoothing factor of 2 / (N + 1). The second stage runs only over the part of the first stage that is actually defined, so no value is invented while the first EMA is still warming up. With a period of N the result is therefore available from bar index 2 x (N - 1) onward, twice the warm-up of a plain EMA. Should the upstream stage ever return a hole after its own start, the implementation refuses to interpolate and returns nothing at all rather than drawing a line based on a broken input.

The formula, as implemented

This is not a description of how the indicator is usually defined elsewhere — it is what the shipped code computes, documented next to the implementation:

EMA_N appliquée au SUFFIXE défini d'une série à préfixe null (sortie d'un étage EMA/lissage précédent — suffixe contigu par construction). Permet EMA(EMA(x)) sans inventer de valeur pendant le warm-up de l'étage amont. Défensif : un null APRÈS le début du suffixe (étage amont incohérent) → tout null, on ne trace rien de faux. */ function emaOverSuffix( values: ReadonlyArray<number | null>, period: number, ): Array<number | null> { const out: Array<number | null> = new Array(values.length).fill(null); let start = 0; while (start < values.length && values[start] === null) start++; if (start >= values.length) return out; const defined: number[] = []; for (let i = start; i < values.length; i++) { const v = values[i]; if (v === null) return out; // suffixe non contigu → dégradation totale defined.push(v); } const e = emaSeries(defined, period); for (let j = 0; j < e.length; j++) out[start + j] = e[j]; return out; } /** Moindres carrés y = a + b·t sur la fenêtre de n valeurs se terminant à l'indice i (t = 0 pour la plus ancienne, t = n−1 pour la courante). Sommes fermées : Σt = n(n−1)/2, Σt² = n(n−1)(2n−1)/6. n = 1 → b = 0. */ function linFit( values: readonly number[], i: number, n: number, ): { a: number; b: number } { const sumT = (n * (n - 1)) / 2; const sumT2 = (n * (n - 1) * (2 * n - 1)) / 6; let sumY = 0; let sumTY = 0; for (let t = 0; t < n; t++) { const y = values[i - n + 1 + t]; sumY += y; sumTY += t * y; } const denom = n * sumT2 - sumT * sumT; // > 0 dès n ≥ 2 const b = denom > 0 ? (n * sumTY - sumT * sumY) / denom : 0; const a = (sumY - b * sumT) / n; return { a, b }; } function periodOf( params: Record<string, unknown>, key: string, fallback: number, floor = 1, ): number { return Math.max(floor, Math.floor(numParam(params, key, fallback))); } // ── Défs ──────────────────────────────────────────────────────────────────── /** DEMA (Patrick Mulloy, 1994) : DEMA_N = 2·EMA_N(close) − EMA_N(EMA_N(close)) EMA du catalogue : graine = SMA des N premiers échantillons, α = 2/(N+1) (parité TradingView/ATAS). Le double étage compense le lag de l'EMA simple. Défini à partir de l'indice 2(N−1) — null avant. Défaut N=20.

How to read it

  • Expect the line to turn earlier than an EMA of the same period, and to overshoot more when price reverses sharply.
  • Subtracting a smoothed copy of the smoothing lets the line travel briefly outside the range of recent closes; that is a property of the construction, not a break.
  • A slope change is the useful event here. A price cross of a line that already extrapolates is the noisier one.
  • Put DEMA and EMA at the same period side by side: the gap between them widens with the strength of the current move and closes in quiet phases.
  • Short periods make the double stage amplify the most recent data, and the line then changes direction often.

Parameters and defaults

The period defaults to 20, the same default as the catalogue's EMA, and ranges from 1 to 500. A short period makes the lag compensation aggressive and the line jumpy; a long one restores stability at the cost of the responsiveness the construction was built for. Raising the period also pushes the first plotted bar twice as far to the right as it would for a single EMA.

DEMA — parameters exposed in the app, with the values it ships with.
ParameterTypeDefaultRange
Periodnumber201 – 500

What it does not show

The lag reduction is bought with overshoot: after a fast move that stops, DEMA can keep pointing in the old direction for a bar or two beyond the closes that produced it. Closes are its only input, so nothing about the bid and ask side of the traded volume reaches it. It also needs a long uninterrupted history before it produces anything, which matters on a freshly loaded chart or when the history depth available for that contract is limited by what your data provider supplies.

Using it in Senzoukria

Add it from the Indicators panel of any footprint chart or candle chart. It runs on futures data from Rithmic or Databento and on crypto pairs from Binance and Bybit, on the same engine — the calculation does not change with the venue, only the data feeding it does. Market data subscriptions are billed by the provider, separately from the app.

  • SMAAverages & volatility
  • EMAAverages & volatility
  • WMAAverages & volatility
  • Hull MAAverages & volatility
  • ATR (Wilder)Averages & volatility
  • BollingerAverages & volatility

See the full indicator library, or start with the order flow guide if you are new to reading aggression, delta and absorption.

Frequently asked questions

How is DEMA different from a double-smoothed moving average?
Applying an EMA twice makes a line slower, not faster. DEMA takes twice the first EMA and subtracts the second, so the double smoothing serves as a correction term rather than as extra filtering. The result reacts earlier than a single EMA of the same period.
Why is DEMA blank at the start of my chart?
Each exponential stage needs its own warm-up, and the second one starts only where the first is defined. With the default period of 20 the first plotted value falls at bar index 38, and nothing is estimated before that point.
Can DEMA go above the highest recent close?
Yes, and that is expected. Because the second EMA is subtracted from twice the first, the result is an extrapolation rather than a weighted average of the window, so it is not bounded by the closes it was computed from.

Keep reading