MACD Pine Script: EMA Differences, Crossovers and Histogram Colors
MACD compares two price averages, then compares that difference with its own average. This guide follows the exact EMA-based 12/26/9 script below. It distinguishes three quantities that are often confused: the sign of MACD, the sign of its histogram, and the direction in which that histogram changes.
Inspect the Pine ScriptThree series, three different questions
For this script, M = EMA(close,12) − EMA(close,26), S = EMA(M,9), and H = M − S. Positive M means the fast average is above the slow average. Positive H means M is above S. Rising H means that signed difference has increased since the previous bar. None alone says that the current close rose, measures buying orders, or establishes a profitable trade.
All three outputs use the source price units and have no fixed 0–100 scale. A two-point MACD on one asset is not directly comparable to two points on another. When negative M moves toward zero, the absolute gap between the price averages shrinks even though M rises.
TradingView’s MACD documentation describes the general calculation. Its current built-in interface also offers SMA/EMA choices and timeframe controls; those extra controls are not implemented by this fixed example.
A signal crossover can happen below zero
Consider a synthetic state with previous M = −3 and S = −2.5, so H = −0.5. On the next bar M becomes −2. With the signal EMA coefficient 2/(9+1) = 0.2, the new S is 0.2×(−2) + 0.8×(−2.5) = −2.4. H is now +0.4. M has crossed above S while M remains negative: the fast price EMA is still below the slow one.
These are conditional arithmetic values, not market observations. They show why a MACD–signal crossover and a MACD–zero crossover are different events. A zero crossover is equivalent to the two price EMAs crossing; a signal crossover compares their difference with its smoothed history.
Why a rising-histogram filter is redundant on the crossover bar
A bullish signal crossover requires current M > S and previous M ≤ S. Therefore current H > 0 and previous H ≤ 0: current H must be greater than previous H. Adding that same signed-rise condition cannot filter any valid bullish crossover when the inputs and bar timing match.
Absolute column height is different. A move from H = −2 to H = +0.2 is a signed increase but a decrease in absolute height. A later positive histogram bar can also shrink without a new crossover. State exactly which comparison you intend; do not treat these cases as contradictory versions of the same event.
H is a filtered difference, not a direct measurement of price acceleration. If M = 2 and previous S = 1, S updates to 1.2 and H = 0.8. If M stays at 2 next bar, S becomes 1.36 and H falls to 0.64 even though M is unchanged.
Read the four colors literally
- H ≥ 0 and H > previous H: opaque teal.
- H ≥ 0 and H ≤ previous H: faded teal.
- H < 0 and H > previous H: faded red.
- H < 0 and H ≤ previous H: opaque red.
A negative histogram moving from −2 to −1 is increasing and remains red. Equal values follow the faded-teal branch when nonnegative and the opaque-red branch when negative. With no valid previous value, the strict rise comparison is false. Colors encode these comparisons; they do not measure order flow or assign a reversal probability.
Divergence requires a defined series and confirmation time
Specify whether divergence compares price pivots with M or with H. They are different series and can produce different extrema. Define pivot widths, how price and oscillator pivots are paired, and when a pivot becomes known. A pivot requiring two right-hand bars is known two bars after its location; a historical annotation at the pivot is not evidence that a trade could have entered there.
The supplied script has no pivot detector. Its live-bar close, EMA values and crossings can change before the bar closes. A proposed alert adaptation should distinguish live updates from confirmed-bar events; confirmation does not prevent a different event on the following bar.
Parameters change a calculation, not an established success rate
The example uses close and fixed 12/26/9 lengths on the chart timeframe. It exposes no settings inputs, alert conditions, order logic or higher-timeframe requests. Edit the constants or explicitly add inputs to change the calculation. EMA lengths are recursive smoothing parameters, not finite windows that forget every price older than exactly 12 or 26 bars.
When comparing an adaptation with the built-in indicator, match the symbol, session, source, timeframe, average types and available history. A shorter length changes response; it does not establish a universal crossover count or a better win rate. Evaluating a trading rule additionally requires explicit entries, exits, fills, costs and a held-out evaluation period.
Pine Script v6: implementation and limits
The complete plotting example preserves the EMA-based ta.macd call and its four histogram color branches. It has no inputs or bar-close gate. Current-bar plots may update until the bar closes.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pineify
//======================================================================//
// ____ _ _ __ //
// | _ \(_)_ __ ___(_)/ _|_ _ //
// | |_) | | '_ \ / _ \ | |_| | | | //
// | __/| | | | | __/ | _| |_| | //
// |_| |_|_| |_|\___|_|_| \__, | //
// |___/ //
//======================================================================//
//@version=6
indicator(title="Moving Average Convergence Divergence", overlay=false, max_labels_count=500)
// MACD Calculation
[p_ind_1_macd, p_ind_1_signal, p_ind_1_histogram] = ta.macd(close, 12, 26, 9)
// Zero Line
hline(0, "MACD - Zero Line", color=color.new(#787B86, 50))
// MACD Histogram
plot(p_ind_1_histogram, "MACD - Histogram", style=plot.style_columns,
color = (p_ind_1_histogram >= 0 ?
(p_ind_1_histogram[1] < p_ind_1_histogram ? color.rgb(38, 166, 154, 0) : color.rgb(38, 166, 154, 70)) :
(p_ind_1_histogram[1] < p_ind_1_histogram ? color.rgb(255, 82, 82, 70) : color.rgb(255, 82, 82, 0))))
// MACD Line
plot(p_ind_1_macd, "MACD - MACD", color=color.rgb(41, 98, 255, 0), linewidth=1)
// Signal Line
plot(p_ind_1_signal, "MACD - Signal", color=color.rgb(255, 109, 0, 0), linewidth=1)
Specify a checkable adaptation in Pineify
Ask Pine Script AI Coding Agent for a defined adaptation, such as configurable EMA lengths and separate confirmed-bar alerts for signal and zero crossings. Inspect the generated source, validate syntax, and compare the plotted values with the fixed reference before evaluating any trading rule.
Open Pine Script AI Coding AgentEducational indicator analysis. No measured trading performance is established here. Syntax validation does not prove formula equivalence, execution assumptions or profitability.