Double Exponential Moving Average (DEMA)
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 , data source is closing price (Close)
“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 )
Step 2: Apply EMA again to (denoted as )
Step 3: Combine to get DEMA
Mathematical Derivation
Why does this formula reduce lag? Assuming EMA’s lag is :
- lags behind the original price by periods
- applies EMA to the already-lagged , so lags behind the original price by approximately periods
Through the following derivation:
In practice, lag cannot be completely eliminated, but it is dramatically reduced to a level well below .
Equivalent Form
DEMA can also be written in the following equivalent form, which aids intuitive understanding:
That is, = current EMA + EMA’s “momentum correction term.” When EMA is rising, , pushing DEMA upward; and vice versa.
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
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
| Advantage | Description |
|---|---|
| Very low lag | Lag is approximately half that of EMA; captures trend reversals more promptly |
| Maintains smoothness | Despite low lag, the curve remains reasonably smooth |
| Simple calculation | Only requires two EMA operations and one linear combination |
| Universal substitute | Can serve as a low-lag replacement for EMA in any scenario |
Disadvantages
| Disadvantage | Description |
|---|---|
| Noise sensitive | The cost of low lag is higher sensitivity to short-term fluctuations |
| May overshoot | During sharp price reversals, DEMA may overshoot |
| Poor in ranging markets | Tends to generate frequent false signals in trendless conditions |
| Longer startup period | Requires 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
| Feature | SMA | EMA | DEMA | TEMA |
|---|---|---|---|---|
| Lag | Highest | Medium | Lower | Lowest |
| Smoothness | Highest | High | Medium | Lower |
| Noise sensitivity | Low | Medium | Higher | Highest |
| Overshoot risk | None | None | Slight | Notable |
| Computation layers | 1 | 1 | 2 | 3 |
- 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.
- If DEMA still feels too slow, try TEMA; if it feels too sensitive, consider increasing the period parameter.
- When backtesting, compare DEMA and EMA strategies with special attention to differences in maximum drawdown and signal frequency.