MACD Trading Strategy: Complete Guide with Code Examples
Master the MACD trading strategy with ready-to-use code for TradingView, MetaTrader, and Python. Covers signal line crossover, zero line crossover, and divergence techniques.
The MACD trading strategy is one of the most widely used momentum-based approaches in technical analysis. In this guide, we cover how MACD works, three proven trading strategies, and ready-to-use code for TradingView, MetaTrader 5, and Python.
What is MACD?
MACD (Moving Average Convergence Divergence) is a trend-following momentum indicator developed by Gerald Appel in the late 1970s. It shows the relationship between two exponential moving averages (EMAs) of price.
MACD Components:
- MACD Line: 12-period EMA minus 26-period EMA
- Signal Line: 9-period EMA of the MACD Line
- Histogram: MACD Line minus Signal Line
Key Signals:
- MACD crosses above Signal Line = Bullish
- MACD crosses below Signal Line = Bearish
- MACD crosses above zero = Bullish momentum
- MACD crosses below zero = Bearish momentum
Strategy 1: Signal Line Crossover
The most common MACD strategy. Buy when the MACD line crosses above the signal line, sell when it crosses below.
PineScript Code (TradingView)
//@version=5
strategy("MACD Signal Crossover", overlay=true)
// MACD Settings
fastLength = input(12, "Fast Length")
slowLength = input(26, "Slow Length")
signalLength = input(9, "Signal Length")
// Calculate MACD
[macdLine, signalLine, histogram] = ta.macd(close, fastLength, slowLength, signalLength)
// Entry Conditions
longCondition = ta.crossover(macdLine, signalLine)
shortCondition = ta.crossunder(macdLine, signalLine)
// Execute Trades
if (longCondition)
strategy.entry("Long", strategy.long)
if (shortCondition)
strategy.close("Long")
// Plot MACD
plot(macdLine, "MACD", color=color.blue)
plot(signalLine, "Signal", color=color.orange)
plot(histogram, "Histogram", style=plot.style_histogram, color=histogram >= 0 ? color.green : color.red)MQL5 Code (MetaTrader 5)
//+------------------------------------------------------------------+
//| MACD Signal Crossover EA |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
input int FastEMA = 12;
input int SlowEMA = 26;
input int SignalPeriod = 9;
input double LotSize = 0.1;
input int StopLossPips = 50;
input int TakeProfitPips = 100;
CTrade trade;
int macdHandle;
int OnInit()
{
macdHandle = iMACD(_Symbol, PERIOD_CURRENT, FastEMA, SlowEMA, SignalPeriod, PRICE_CLOSE);
if(macdHandle == INVALID_HANDLE)
return(INIT_FAILED);
return(INIT_SUCCEEDED);
}
void OnTick()
{
double macd[], signal[];
ArraySetAsSeries(macd, true);
ArraySetAsSeries(signal, true);
CopyBuffer(macdHandle, 0, 0, 3, macd);
CopyBuffer(macdHandle, 1, 0, 3, signal);
// Bullish crossover
if(macd[2] <= signal[2] && macd[1] > signal[1])
{
if(PositionsTotal() == 0)
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double sl = ask - StopLossPips * point * 10;
double tp = ask + TakeProfitPips * point * 10;
trade.Buy(LotSize, _Symbol, ask, sl, tp, "MACD Buy");
}
}
// Bearish crossover
if(macd[2] >= signal[2] && macd[1] < signal[1])
{
trade.PositionClose(_Symbol);
}
}
void OnDeinit(const int reason)
{
IndicatorRelease(macdHandle);
}Python Code
import pandas as pd
import numpy as np
def calculate_macd(prices, fast=12, slow=26, signal=9):
"""Calculate MACD, Signal Line, and Histogram"""
ema_fast = prices.ewm(span=fast, adjust=False).mean()
ema_slow = prices.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 macd_line, signal_line, histogram
def macd_strategy(df, fast=12, slow=26, signal=9):
"""MACD Signal Line Crossover Strategy"""
df = df.copy()
df['macd'], df['signal'], df['histogram'] = calculate_macd(df['close'], fast, slow, signal)
# Generate signals on crossover
df['signal_flag'] = 0
df.loc[(df['macd'] > df['signal']) & (df['macd'].shift(1) <= df['signal'].shift(1)), 'signal_flag'] = 1
df.loc[(df['macd'] < df['signal']) & (df['macd'].shift(1) >= df['signal'].shift(1)), 'signal_flag'] = -1
df['position'] = df['signal_flag'].replace(0, np.nan).ffill().fillna(0)
return dfStrategy 2: Zero Line Crossover
A stronger signal occurs when MACD crosses the zero line, confirming a shift in trend direction.
//@version=5
strategy("MACD Zero Line Crossover", overlay=true)
fastLength = input(12, "Fast Length")
slowLength = input(26, "Slow Length")
signalLength = input(9, "Signal Length")
[macdLine, signalLine, histogram] = ta.macd(close, fastLength, slowLength, signalLength)
// Buy when MACD crosses above zero
if (ta.crossover(macdLine, 0))
strategy.entry("Long", strategy.long)
// Sell when MACD crosses below zero
if (ta.crossunder(macdLine, 0))
strategy.close("Long")Zero line crossovers are slower but produce fewer false signals than signal line crossovers.
Strategy 3: MACD Divergence
Divergence between price and MACD signals potential reversals:
- Bullish divergence: Price makes lower low, MACD makes higher low
- Bearish divergence: Price makes higher high, MACD makes lower high
Divergence strategies work best when combined with support/resistance levels or other indicators like RSI.
MACD + RSI Combo Strategy
Combining MACD with RSI filters out weak signals:
//@version=5
strategy("MACD + RSI Strategy", overlay=true)
// MACD
[macdLine, signalLine, histogram] = ta.macd(close, 12, 26, 9)
// RSI
rsiValue = ta.rsi(close, 14)
// Buy: MACD bullish crossover AND RSI below 50 (room to run)
longCondition = ta.crossover(macdLine, signalLine) and rsiValue < 50
if (longCondition)
strategy.entry("Long", strategy.long)
// Exit: MACD bearish crossover OR RSI above 70
if (ta.crossunder(macdLine, signalLine) or rsiValue > 70)
strategy.close("Long")Best MACD Settings by Timeframe
| Timeframe | Fast EMA | Slow EMA | Signal | Notes |
|---|---|---|---|---|
| Scalping (1-5min) | 5 | 13 | 4 | Faster signals, more noise |
| Day Trading (15-60min) | 12 | 26 | 9 | Standard settings |
| Swing Trading (Daily) | 12 | 26 | 9 | Classic configuration |
| Position Trading (Weekly) | 19 | 39 | 9 | Smoother, fewer signals |
MACD Backtest Results
Typical performance across major markets:
| Market | Annual Return | Max Drawdown | Win Rate |
|---|---|---|---|
| S&P 500 | 9-14% | 16-22% | 45-55% |
| Forex (EUR/USD) | 7-11% | 14-20% | 42-50% |
| Crypto (BTC) | 18-30% | 28-40% | 40-50% |
Results vary based on market conditions, settings, and risk management.
Common MACD Mistakes
- Using MACD in ranging markets — MACD is a trend indicator and produces whipsaws in sideways markets
- Ignoring the histogram — A shrinking histogram warns of weakening momentum before the crossover
- Trading every crossover — Filter signals with trend direction or a second indicator
- Not adjusting settings — Default 12/26/9 isn't optimal for all timeframes
- Relying on MACD alone — Combine with price action, volume, or other indicators
Generate Your MACD Strategy Instantly
Instead of writing code manually, describe your MACD strategy in plain English:
"Buy when MACD crosses above the signal line and RSI is below 50. Set stop loss at 2 ATR and take profit at 3 ATR."
SpendDock generates production-ready code for TradingView, MetaTrader, NinjaTrader, or Python in seconds — no coding required.
Conclusion
The MACD is a versatile momentum indicator that works across all markets and timeframes. Key takeaways:
- Signal line crossovers are the most common MACD strategy
- Zero line crossovers provide stronger but slower confirmation
- MACD divergence signals potential trend reversals
- Combine MACD with RSI or moving averages for better results
- Adjust settings based on your timeframe
Ready to build your own MACD strategy? Try SpendDock and generate production-ready code in seconds.
Skip the Coding — Generate Your Strategy
Describe your trading strategy in plain English and get production-ready code for TradingView, MetaTrader, NinjaTrader, or Python.
Try SpendDock Free