Double Exponential Moving Average (DEMA)

Haiyue
9min

I. What is DEMA

The Double Exponential Moving Average (DEMA) is an advanced moving average indicator designed to significantly reduce the lag inherent in traditional moving averages. It was first introduced by Patrick Mulloy in a 1994 article published in the Technical Analysis of Stocks & Commodities magazine.

Historical Background

Patrick Mulloy observed that both SMA and EMA exhibit noticeable lag when trends change rapidly. His innovation was to apply EMA twice to the data, then use a mathematical combination to cancel out most of the lag. This approach simultaneously gave rise to both DEMA (double) and TEMA (triple) improved moving averages. DEMA reduces lag to approximately half that of EMA while maintaining good smoothness.

Indicator Classification

  • Type: Overlay indicator, plotted on the price chart
  • Category: Moving Averages
  • Default Parameters: Period n=20n = 20, data source is closing price (Close)
Clarification of the Name

“Double exponential” does not mean using twice the exponential smoothing. Rather, it refers to the mathematical combination after applying EMA twice in a nested fashion. DEMA involves two layers of EMA, but the final formula is a linear combination designed to cancel lag.


II. Mathematical Principles and Calculation

Core Formula

DEMA is calculated in three steps:

Step 1: Calculate the EMA of price (denoted as EMA1EMA_1)

EMA1=EMA(P,n)EMA_1 = EMA(P, n)

Step 2: Apply EMA again to EMA1EMA_1 (denoted as EMA2EMA_2)

EMA2=EMA(EMA1,n)EMA_2 = EMA(EMA_1, n)

Step 3: Combine to get DEMA

DEMA=2EMA1EMA2DEMA = 2 \cdot EMA_1 - EMA_2

Mathematical Derivation

Why does this formula reduce lag? Assuming EMA’s lag is LL:

  • EMA1EMA_1 lags behind the original price by LL periods
  • EMA2EMA_2 applies EMA to the already-lagged EMA1EMA_1, so EMA2EMA_2 lags behind the original price by approximately 2L2L periods

Through the following derivation:

DEMA=2EMA1EMA2DEMA = 2 \cdot EMA_1 - EMA_2

Lag2L2L=0\text{Lag} \approx 2 \cdot L - 2L = 0

In practice, lag cannot be completely eliminated, but it is dramatically reduced to a level well below LL.

Equivalent Form

DEMA can also be written in the following equivalent form, which aids intuitive understanding:

DEMA=EMA1+(EMA1EMA2)DEMA = EMA_1 + (EMA_1 - EMA_2)

That is, DEMADEMA = current EMA + EMA’s “momentum correction term.” When EMA is rising, (EMA1EMA2)>0(EMA_1 - EMA_2) > 0, pushing DEMA upward; and vice versa.

Lag Comparison

Using a 20-day period as an example:

  • SMA average lag: approximately 9.5 days
  • EMA average lag: approximately 6.6 days
  • DEMA average lag: approximately 3-4 days

III. Python Implementation

import numpy as np
import pandas as pd

def ema(close: pd.Series, period: int) -> pd.Series:
    """Calculate EMA"""
    return close.ewm(span=period, adjust=False).mean()


def dema(close: pd.Series, period: int = 20) -> pd.Series:
    """
    Calculate the Double Exponential Moving Average (DEMA)

    Parameters
    ----------
    close : pd.Series
        Closing price series
    period : int
        Calculation period, default is 20

    Returns
    -------
    pd.Series
        DEMA value series
    """
    ema1 = ema(close, period)
    ema2 = ema(ema1, period)
    return 2 * ema1 - ema2


def dema_numpy(close: np.ndarray, period: int = 20) -> np.ndarray:
    """
    Manual DEMA implementation using numpy
    """
    alpha = 2.0 / (period + 1)
    n = len(close)

    ema1 = np.full(n, np.nan)
    ema2 = np.full(n, np.nan)

    # EMA1 initialization
    ema1[period - 1] = np.mean(close[:period])
    for i in range(period, n):
        ema1[i] = alpha * close[i] + (1 - alpha) * ema1[i - 1]

    # EMA2 initialization (based on EMA1)
    start = 2 * period - 2  # EMA1 valid from period-1, need another period
    if start < n:
        ema2[start] = np.nanmean(ema1[period - 1 : start + 1])
        for i in range(start + 1, n):
            ema2[i] = alpha * ema1[i] + (1 - alpha) * ema2[i - 1]

    result = 2 * ema1 - ema2
    return result


# ========== Usage Example ==========
if __name__ == "__main__":
    np.random.seed(42)
    dates = pd.date_range("2024-01-01", periods=120, freq="D")
    price = 100 + np.cumsum(np.random.randn(120) * 0.8)

    df = pd.DataFrame({
        "date": dates,
        "open":  price + np.random.randn(120) * 0.3,
        "high":  price + np.abs(np.random.randn(120) * 0.6),
        "low":   price - np.abs(np.random.randn(120) * 0.6),
        "close": price,
        "volume": np.random.randint(1000, 10000, size=120),
    })
    df.set_index("date", inplace=True)

    # Calculate various moving averages
    df["SMA_20"]  = df["close"].rolling(20).mean()
    df["EMA_20"]  = ema(df["close"], 20)
    df["DEMA_20"] = dema(df["close"], 20)

    print("=== SMA vs EMA vs DEMA Comparison ===")
    print(df[["close", "SMA_20", "EMA_20", "DEMA_20"]].tail(10))

    # DEMA trend-following signal
    df["trend"] = np.where(df["close"] > df["DEMA_20"], "UP", "DOWN")
    print("\n=== DEMA Trend Signal (last 10 rows) ===")
    print(df[["close", "DEMA_20", "trend"]].tail(10))

IV. Problems the Indicator Solves

1. Significantly Reduced Moving Average Lag

DEMA’s most critical contribution is the dramatic reduction of the lag inherent in EMA. At trend reversals, DEMA can signal several periods ahead of EMA.

2. Rapid Trend Identification

Due to its low lag, DEMA is better suited for detecting short-term trend changes. When price breaks through DEMA, the signal’s timeliness is far superior to SMA and EMA.

3. Improved Crossover Strategies

In moving average crossover strategies, replacing EMA/SMA with DEMA can:

  • Enter trends earlier
  • Reduce profit give-back at the end of trends
  • Decrease signal delay in ranging markets

4. Smoothing Component for Other Indicators

DEMA can replace EMA in the smoothing calculations of other indicators, for example:

  • DEMA-based MACD: Using DEMA(12) and DEMA(26) instead of traditional EMA
  • DEMA envelopes
Watch for Over-Sensitivity

DEMA’s low-lag property also means it is more sensitive to price noise. In ranging markets, DEMA may generate more false signals than EMA. It is recommended to use it alongside trend strength indicators such as ATR or ADX.


V. Advantages, Disadvantages, and Use Cases

Advantages

AdvantageDescription
Very low lagLag is approximately half that of EMA; captures trend reversals more promptly
Maintains smoothnessDespite low lag, the curve remains reasonably smooth
Simple calculationOnly requires two EMA operations and one linear combination
Universal substituteCan serve as a low-lag replacement for EMA in any scenario

Disadvantages

DisadvantageDescription
Noise sensitiveThe cost of low lag is higher sensitivity to short-term fluctuations
May overshootDuring sharp price reversals, DEMA may overshoot
Poor in ranging marketsTends to generate frequent false signals in trendless conditions
Longer startup periodRequires initialization data for two layers of EMA; effective output starts later

Use Cases

  • Markets with clear trends: Medium to strong unidirectional movements
  • Short to medium-term trading: Trading styles requiring fast response
  • EMA replacement: In strategies sensitive to lag, substitute EMA with DEMA

Comparison with Similar Indicators

FeatureSMAEMADEMATEMA
LagHighestMediumLowerLowest
SmoothnessHighestHighMediumLower
Noise sensitivityLowMediumHigherHighest
Overshoot riskNoneNoneSlightNotable
Computation layers1123
Practical Advice
  1. DEMA works best when combined with a trend filter (e.g., ADX > 25), leveraging its low-lag advantage when trends exist while avoiding false signals during consolidation.
  2. If DEMA still feels too slow, try TEMA; if it feels too sensitive, consider increasing the period parameter.
  3. When backtesting, compare DEMA and EMA strategies with special attention to differences in maximum drawdown and signal frequency.