Moving Average Convergence Divergence (MACD)
I. What is MACD
The Moving Average Convergence Divergence (MACD) is one of the most popular trend-following momentum indicators in technical analysis. It measures changes in price momentum through the difference between two Exponential Moving Averages (EMAs) of different periods, helping traders identify trend direction, strength, and potential reversal points.
Historical Background
MACD was invented by Gerald Appel in 1979, and later enhanced by Thomas Aspray in 1986 with the addition of the Histogram component, forming the classic three-element structure we know today. Due to its dual functionality of trend following and momentum analysis, MACD has been called the “Swiss Army knife of technical analysis” and is one of the most frequently used indicators by traders worldwide.
Indicator Classification
- Type: Oscillator, displayed in a separate panel
- Category: Trend + Momentum composite indicator
- Default Parameters: Fast EMA period , Slow EMA period , Signal EMA period
- Value Range: Unbounded, oscillates around the zero line
- MACD Line (fast line): Difference between EMA(12) and EMA(26)
- Signal Line (slow line): EMA(9) of the MACD Line
- Histogram: MACD Line minus Signal Line
II. Mathematical Principles and Calculation
Core Formulas
Step 1: Calculate fast and slow EMAs
The EMA recursive formula:
- Fast EMA: ()
- Slow EMA: ()
Step 2: Calculate the MACD Line
Step 3: Calculate the Signal Line
That is, apply a 9-period EMA smoothing to the MACD Line.
Step 4: Calculate the Histogram
Step-by-Step Calculation Logic
- Calculate 12-period EMA using close prices as input
- Calculate 26-period EMA using close prices as input
- MACD Line = Fast EMA - Slow EMA
- Signal Line = 9-period EMA of the MACD Line
- Histogram = MACD Line - Signal Line
Intuitive Understanding
- When the short-term average rises faster than the long-term average, MACD is positive — upward momentum is increasing
- When the MACD Line is far from the Signal Line, the Histogram grows — current trend momentum is strong
- When the Histogram begins to shrink — momentum is weakening, a crossover may be imminent
Appel’s originally recommended parameters (12, 26, 9) were derived from empirical analysis of the U.S. stock market. 26 days is approximately one month of trading days, and 12 days is about half a month. Different markets and timeframes may require parameter adjustments.
III. Python Implementation
import numpy as np
import pandas as pd
def macd(close: pd.Series,
fast: int = 12,
slow: int = 26,
signal: int = 9) -> pd.DataFrame:
"""
Calculate the MACD indicator
Parameters
----------
close : pd.Series
Close price series
fast : int
Fast EMA period, default 12
slow : int
Slow EMA period, default 26
signal : int
Signal line EMA period, default 9
Returns
-------
pd.DataFrame
DataFrame with MACD, Signal, and Histogram columns
"""
ema_fast = close.ewm(span=fast, adjust=False).mean()
ema_slow = close.ewm(span=slow, adjust=False).mean()
macd_line = ema_fast - ema_slow
signal_line = macd_line.ewm(span=signal, adjust=False).mean()
histogram = macd_line - signal_line
return pd.DataFrame({
"MACD": macd_line,
"Signal": signal_line,
"Histogram": histogram
}, index=close.index)
# ========== Usage Example ==========
if __name__ == "__main__":
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=150, freq="D")
# Generate simulated price with trend
trend = np.linspace(0, 10, 150)
noise = np.cumsum(np.random.randn(150) * 0.8)
price = 100 + trend + noise
df = pd.DataFrame({
"date": dates,
"open": price + np.random.randn(150) * 0.3,
"high": price + np.abs(np.random.randn(150) * 0.6),
"low": price - np.abs(np.random.randn(150) * 0.6),
"close": price,
"volume": np.random.randint(1000, 10000, size=150),
})
df.set_index("date", inplace=True)
# Calculate MACD
macd_df = macd(df["close"])
df = pd.concat([df, macd_df], axis=1)
# Print last 10 rows
print("=== MACD Results ===")
print(df[["close", "MACD", "Signal", "Histogram"]].tail(10).to_string())
# Crossover signal detection
df["cross"] = np.sign(df["MACD"] - df["Signal"])
df["signal_type"] = df["cross"].diff()
golden = df[df["signal_type"] > 0] # MACD crosses above Signal
death = df[df["signal_type"] < 0] # MACD crosses below Signal
print("\n=== Bullish Crossovers ===")
print(golden[["close", "MACD", "Signal"]].to_string())
print("\n=== Bearish Crossovers ===")
print(death[["close", "MACD", "Signal"]].to_string())
IV. Problems the Indicator Solves
1. Trend Direction
- MACD > 0: Fast line is above the slow line, short-term trend is up
- MACD < 0: Fast line is below the slow line, short-term trend is down
- MACD rising continuously: Uptrend is accelerating
- MACD falling continuously: Downtrend is accelerating
2. Signal Line Crossover
| Signal Type | Condition | Meaning |
|---|---|---|
| Bullish Cross | MACD Line crosses above Signal Line | Bullish signal, especially significant when below zero |
| Bearish Cross | MACD Line crosses below Signal Line | Bearish signal, especially significant when above zero |
3. Zero Line Crossover
- MACD crosses above zero — EMA(12) exceeds EMA(26) — medium-term trend turns bullish
- MACD crosses below zero — EMA(12) falls below EMA(26) — medium-term trend turns bearish
4. Histogram Analysis
The Histogram is the most sensitive component of the MACD system:
- Histogram turns from negative to positive: Momentum shifts from bearish to bullish
- Histogram turns from positive to negative: Momentum shifts from bullish to bearish
- Histogram increasing: Trend is accelerating
- Histogram decreasing: Trend is decelerating, crossover approaching
5. Divergence Signals
- Bearish Divergence: Price makes a new high, MACD does not — upward momentum is fading
- Bullish Divergence: Price makes a new low, MACD does not — downward momentum is fading
MACD divergence can persist for a long time during strong trends; entering too early can lead to losses. It is advisable to wait for an actual crossover confirmation before acting.
V. Advantages, Disadvantages, and Use Cases
Advantages
| Advantage | Description |
|---|---|
| Dual functionality | Combines trend following and momentum oscillation |
| Rich signals | Crossovers, zero line, histogram, and divergence provide multi-layered information |
| Less lag | Based on EMA rather than SMA, responds faster |
| Widely recognized | Universal among global traders, strong self-fulfilling effect |
Disadvantages
| Disadvantage | Description |
|---|---|
| False signals in ranging markets | Frequent crossovers during trendless, sideways consolidation |
| No fixed boundaries | Unlike RSI’s 0-100 range, difficult to define absolute overbought/oversold |
| Still has lag | Based on moving averages, inherently a lagging indicator |
| Parameter dependent | (12,26,9) is not optimal for all markets |
Use Cases
- Medium to long-term trend trading: MACD signal line crossovers are suited for capturing multi-week trends
- Swing trading: Histogram changes help identify short-term momentum shifts
- Trend confirmation: Combined with price patterns, e.g., breakout + bullish MACD cross as dual confirmation
Comparison with Related Indicators
| Comparison | MACD | RSI | Stochastic |
|---|---|---|---|
| Type | Trend + Momentum | Pure Momentum | Pure Momentum |
| Value Range | Unbounded | 0-100 | 0-100 |
| Best Scenario | Trending markets | Ranging markets | Ranging markets |
| Signal Delay | Medium | Low | Low |
- Zero line filter: Only go long when MACD > 0, only go short when MACD < 0 — this significantly reduces false signals.
- Multi-timeframe: Use MACD on the daily chart for direction, find entries on the hourly chart.
- Histogram leads: The Histogram’s turning point usually precedes the MACD line crossover and can serve as an early warning.
- Combine with RSI: Bullish MACD cross + RSI recovering from oversold = stronger buy signal.