A statistical construction that measures the gap between two related instruments and expresses it in standard deviations.
A pairs-trading spread is not a single built-in indicator but a statistical construction: you take two instruments that have historically moved together, estimate a hedge ratio that scales one against the other, and plot the difference between them. The idea, popularized by statistical-arbitrage desks in the 1980s, is that the spread between two related instruments may be more stable and more mean-reverting than either price on its own. The z-score is the second half of the construction: it normalizes the spread by its own rolling mean and standard deviation, so a reading of +2 means the spread is two standard deviations above its recent average. To build one in Pine Script you need three ingredients: a second symbol fetched safely with request.security, a rolling hedge ratio (a least-squares slope, computable from correlation and standard deviations), and a rolling z-score of the resulting spread. All of this is descriptive statistics about the recent past. A spread that has mean-reverted historically carries no guarantee it will continue to — relationships between instruments break, sometimes abruptly. This page is educational only, not financial advice, and any trading based on spreads carries real risk of loss.
Start with two price series: the chart symbol (call it Y) and a second symbol (X) retrieved with request.security. To avoid repainting, the second series should be requested with a one-bar offset and lookahead disabled, which means the spread is built from the other symbol's last completed bar. Next, estimate the hedge ratio (beta) — how many units of X offset one unit of Y. A rolling ordinary-least-squares slope can be computed directly on the chart as correlation(Y, X) × stdev(Y) / stdev(X) over a chosen lookback. The spread is then Y − beta × X. Finally, the z-score standardizes the spread: subtract its rolling mean and divide by its rolling standard deviation over a second lookback window. The result oscillates around zero, with ±2 commonly drawn as reference lines. Every stage involves a lookback choice, and each choice changes the output: a short hedge-ratio window makes beta jumpy; a long one makes it stale when the relationship shifts. Critically, the whole construction assumes the two instruments are cointegrated — that the spread is genuinely stationary. That property is estimated in-sample and routinely breaks out-of-sample, which is the honest core caveat of all pairs analysis: statistical correctness of the calculation says nothing about future stability of the relationship.
There are no universal defaults because this is a construction, not a packaged indicator. Common starting points are a hedge-ratio lookback of 100–250 bars and a z-score lookback of 20–100 bars, with reference lines at ±2. Some practitioners fix beta at 1 (a simple price difference or ratio) for closely related instruments; others re-estimate it on a rolling basis. Longer windows give steadier estimates that adapt slowly; shorter windows adapt fast but are noisy. Every choice should be tested for sensitivity rather than assumed.
//@version=6
indicator("Pairs Spread Z-Score", overlay = false)
sym = input.symbol("OANDA:EURGBP", "Second Symbol")
betaLen = input.int(100, "Hedge Ratio Lookback", minval = 20)
zLen = input.int(50, "Z-Score Lookback", minval = 10)
// Non-repainting fetch: prior completed bar, lookahead off
x = request.security(sym, timeframe.period, close[1], lookahead = barmerge.lookahead_off)
y = close
// Rolling OLS hedge ratio: beta = corr(y,x) * stdev(y) / stdev(x)
beta = ta.correlation(y, x, betaLen) * ta.stdev(y, betaLen) / ta.stdev(x, betaLen)
spread = y - beta * x
meanS = ta.sma(spread, zLen)
stdS = ta.stdev(spread, zLen)
z = stdS != 0 ? (spread - meanS) / stdS : 0.0
plot(z, "Spread Z-Score", color = color.blue)
hline(2, "+2", color = color.gray)
hline(0, "Zero", color = color.new(color.gray, 50))
hline(-2, "-2", color = color.gray)Pro tip: Before reading any z-score, plot beta itself and check whether it is stable over your sample. If the hedge ratio drifts materially, the spread is not measuring what you think it is, and the z-score inherits that error. Re-test the construction across different lookbacks and time periods rather than trusting one clean-looking chart — an in-sample relationship is a description of the past, not a forecast. This is educational material only, not financial advice; pairs relationships can and do break, and trading involves risk of loss.
Educational only — not financial advice, not a recommendation to trade. No indicator is predictive; trading involves substantial risk of loss.