Skip to content
Open RaamTrade

MACD — Moving Average Convergence Divergence

Fast EMA minus slow EMA, with a signal-line EMA and a histogram. Multi-value: .line, .signal, .histogram.

Signature

MACD(fast_period, slow_period, signal_period, on=<source>)
Argument Type Required Notes
fast_period int Param or literal Yes Fast EMA length. Default 12, bounds 2–50.
slow_period int Param or literal Yes Slow EMA length. Default 26, bounds 10–200.
signal_period int Param or literal Yes Signal-line EMA length. Default 9, bounds 2–50.
on= symbol, OHLCV field, or indicator No Source. Defaults to the trade symbol’s close.

Formula

$$ \text{line} = \text{EMA}{\text{fast}}(\text{close}) - \text{EMA}{\text{slow}}(\text{close}) $$

$$ \text{signal} = \text{EMA}_{\text{signal}}(\text{line}), \qquad \text{histogram} = \text{line} - \text{signal} $$

Both price EMAs are seeded from the simple average of the first slow_period closes; the signal line seeds to the first computed MACD line value and follows its own EMA recursion from there.

Warmup

slow_period bars. All three outputs read 0 until the slow window is full.

Reading values

MACD is multi-value — you access fields with attributes, not .value.

m = MACD(12, 26, 9, on=self.trade)
m.line # fast EMA − slow EMA
m.signal # EMA of the line
m.histogram # line − signal

No crossed_above on multi-value

m.crossed_above(0) is RC2_CROSS_MULTIVALUE. Compare fields explicitly, or track the previous bar’s values in persistent state to detect a line/signal cross.

Example

class MACDHistogramTrend(Strategy):
"""Long while the MACD histogram is positive."""
fast_period = Param(12, min=2, max=50)
slow_period = Param(26, min=10, max=200)
signal_period = Param(9, min=2, max=50)
trade = Symbol()
sizing = FixedCapital()
def execute(self):
m = MACD(self.fast_period, self.slow_period, self.signal_period, on=self.trade)
self.stop_loss(3.0)
if m.histogram > 0 and self.trade.is_flat:
self.buy(self.trade, reason=f"MACD histogram positive ({m.histogram:.2f})")
if m.histogram < 0 and self.trade.is_long:
self.sell(self.trade, self.trade.position, reason=f"MACD histogram negative ({m.histogram:.2f})")

Notes

  • The histogram’s sign is the classic trend read (positive = line above signal); its slope leads the sign — a shrinking positive histogram often precedes the bearish cross.
  • MACD is unbounded and scales with price. To compare across instruments, divide by price or use percentage-based indicators (ROC, or the Percent Price Oscillator from the catalog).
  • For a true line/signal crossing signal, track last-bar values in persistent state — see the worked example in RC2_CROSS_MULTIVALUE.