Quant Terminal
D1-09D1·advanced·~23 min

Cointegration and pairs trading — mean reversion you can hunt for

time-seriescointegrationpairs-tradingengle-grangerspreadmean-reversionhedge-ratio

▸ Pretest — guess, even if you don't know

Two oil majors have a daily RETURN correlation of 0.9. Does that guarantee the gap between their PRICES stays bounded over the next decade?

Correlated returns, drifting prices

Correlation (A2-08) lives in return space: do the two series zig together day by day? Cointegration lives in price space: is there a combination of the two prices that never wanders off? The two properties are genuinely independent — you can have either one without the other:

If you trade the gap between two prices, return correlation is the wrong safety check. You need the stronger property.

Cointegration: a stationary combination of non-stationary things

From D1-03: individual prices are non-stationary. They carry unit roots — shocks never decay — so there is no fixed mean to revert to, and the ADF test (augmented Dickey–Fuller, the D1-03 stationarity test) fails to reject. Two price series yty_t and xtx_t ("y sub t" and "x sub t" — the two prices on day t) are cointegrated if some linear combination

zt=ytγxtz_t = y_t - \gamma\, x_t

is stationary. In words: the spread "z sub t" equals the price of y minus gamma (the Greek letter γ\gamma) times the price of x. Gamma is the mixing weight — how many units of x you subtract per unit of y. Concrete numbers: with γ=2\gamma = 2, yt=210y_t = 210, and xt=100x_t = 100, the spread is 2102×100=10210 - 2 \times 100 = 10.

Each series wanders like a drunk, but they're two drunks handcuffed together: each path is unpredictable, the distance between them is not. The spread ztz_t has a fixed mean, finite variance, and mean-reverts. That's everything the D1-03 toolkit certifies — and everything the D1-04 machinery can then exploit. Economically the handcuff is usually an arbitrage force: dual listings, share classes, an ETF versus its basket, refiner versus crude. Someone with size gets paid to close the gap, so the gap closes.

Engle–Granger in two steps

The classic test for cointegration is almost embarrassingly simple:

  1. Regress yy on xx by OLS — ordinary least squares, the standard line-fitting regression from A2-06. The fitted slope γ^\hat\gamma ("gamma-hat" — the hat marks a value estimated from data) is the hedge ratio: how many units of xx offset one unit of yy. A hedge ratio of 2 means you short 2 shares of x against each share of y you buy.
  2. ADF-test the residuals (D1-03). The residuals — the leftover gaps between actual yy and the fitted line — are exactly the spread zt=ytγ^xtz_t = y_t - \hat\gamma x_t. If ADF rejects a unit root in zz, the pair is cointegrated: you found a stationary combination.

One honest technicality. Because γ^\hat\gamma was fitted — OLS deliberately chose the combination that looks most stationary — the ADF critical values must be stricter than the off-the-shelf ones (statsmodels' coint handles this). The two-step structure, though, is exactly regression plus the stationarity test you already know.

Trading the spread

Once ztz_t is certified stationary, it's an AR(1)-style mean reverter, and all of D1-04 applies to the spread. Estimate its ϕ\phi ("phi" — the AR(1) pull-back coefficient from D1-04) and you get a half-life — the typical time for a deviation to close half its gap, which is the practical timescale of the trade. Half-life of 8 days: tradeable. Half-life of 8 months: your capital ages while the spread thinks about it.

The playbook: compute the spread's z-score, (ztzˉ)/σz(z_t - \bar z)/\sigma_z. In words: take today's spread, subtract its historical average ("z-bar" — the bar means average), and divide by its standard deviation ("sigma sub z"). The result says how many standard deviations from normal the spread is right now. Concrete numbers: average spread 10, standard deviation 2, today's spread 14.5 — the z-score is (14.510)/2=2.25(14.5 - 10)/2 = 2.25, a stretched pair. When the z-score moves beyond about ±2, short the rich side and buy the cheap side in the ratio γ^\hat\gamma; exit near zero. The position is (roughly) market-neutral — you're long and short similar exposure — so the P&L comes from the gap converging, not from market direction. This is the cleanest expression in the whole curriculum of trading a statistical property rather than an opinion.

Honest warnings

Try it

Build the two objects everything above rests on — the hedge ratio (a regression slope via the covariance formula from A2-06) and the spread:

▮ EXERCISE · d1-09-ex1

Implement hedge_ratio(y, x): the OLS slope of y on x, computed as np.cov(y, x)[0, 1] / np.var(x, ddof=1). And spread(y, x): the array y - hedge_ratio(y, x) * x.

⧉ Review card
Why does high return correlation NOT protect a pairs trade?
Correlation measures daily co-movement of returns; the trade's risk lives in price levels. A small persistent drift difference, invisible in correlation, compounds into an unbounded price gap. Only cointegration bounds the spread.
⧉ Review card
Define cointegration.
Two non-stationary (unit-root) series are cointegrated if some linear combination z = y - gamma*x is stationary. Each series wanders; the spread between them mean-reverts — two drunks handcuffed together.
⧉ Review card
Describe the Engle-Granger two-step procedure.
Step 1: OLS-regress y on x; the slope is the hedge ratio. Step 2: ADF-test the residuals (the spread). Rejecting a unit root in the residuals means cointegrated. Caveat: fitted residuals need stricter ADF critical values.
⧉ Review card
How do you turn a cointegrated pair into a trade?
Treat the spread as an AR(1): estimate its half-life for the trade's timescale, z-score it, short the rich leg and buy the cheap leg in hedge-ratio proportion beyond about 2 sigma, exit near zero. Market-neutral; P&L comes from convergence.
⧉ Review card
Three honest failure modes of pairs trading?
1) Cointegration breaks with regime change — a 6-sigma spread may be a dead pair, not a bargain. 2) In-sample hedge ratios overfit; re-estimate rolling. 3) Scanning many pairs is multiple testing (HLZ) — demand an economic link before the statistical test.

Map it

On paper, draw a concept map linking: unit root (D1-03), return correlation (A2-08), OLS slope (A2-06), hedge ratio, spread, ADF test, stationarity, AR(1) half-life (D1-04), z-score entry, and regime break. Arrows should say things like "tested by", "computed as", "applies to", "kills".

Predict before the next lesson

Next is D1-10: regimes and structural breaks — the lesson every warning above has been pointing at. Predict: you fit one GARCH persistence and one pairs hedge ratio on 2005–2024 pooled data. Name two historical events inside that window that plausibly changed the true parameters mid-sample. What would the pooled estimate be a blend of?

◈ Calibration check

Could you explain to a skeptic why cointegration, not correlation, justifies a pairs trade — and walk through Engle-Granger plus its three failure modes from memory?

1 = guessing · 5 = could teach it

⏻ End of lesson

Mark it read to book its 5 review cards into your deck.

Sources & further reading