AR models — the math under mean reversion
▸ Pretest — guess, even if you don't know
A spread between two ETFs follows an AR(1) with phi = 0.9 at daily frequency. A shock knocks it 10 points above its long-run mean. Roughly how long until the expected deviation is back down to 5 points?
AR(1): a series with memory
The autoregressive model of order one ("autoregressive" — the series is regressed on itself):
In words: tomorrow's value is a constant , plus a fraction of today's value, plus fresh white noise. Reading the symbols: ("x sub t") is the value at time ; is yesterday's value, one lag back; is the Greek letter phi, the fraction that carries over; ("epsilon sub t") is the shock — fresh random noise arriving each period, as in D1-02. Concrete: with , , and today's value 10, tomorrow's expected value is .
The parameter is the memory dial — how much of today persists into tomorrow. The trading question it answers: if the spread I trade is stretched today, what do I expect it to do next? White noise says "nothing carries over" (); a random walk says "everything carries over" (); AR(1) covers the whole spectrum in between.
The phi dial
- : stationary and mean-reverting. Shocks decay geometrically — shrinking by the same multiplicative factor each step, like repeated halving — and the series is pulled back toward its long-run mean. This is the regime where trading a stretch makes sense.
- : random walk (D1-02) — the unit root of D1-03. Shocks never decay; there is no mean to revert to. The ADF test is literally a test of whether .
- : explosive — shocks compound; not a sustainable model of anything you can trade.
- : mean-reverting with overshoot — the series flip-flops around the mean. Rare in daily financial data, though bid-ask bounce (trades ping-ponging between the bid price and the ask price) induces something like it in high-frequency returns.
For the stationary case, where does the series settle? Call the settling point — the Greek letter mu, the long-run mean from A1-00. In a settled, noiseless world, tomorrow equals today: set in the equation with the noise removed. That gives , and solving for :
In words: the long-run mean is the constant divided by one minus phi. Concrete: , gives . Deviations from that mean decay geometrically in expectation:
In words: the expected deviation steps from now equals phi to the power , times today's deviation. Concrete: and a deviation of 10 today means an expected deviation of 9 tomorrow, 8.1 the day after, and so on.
Half-life: turning phi into a holding period
How long until half of a deviation is expected to be gone? That waiting time is the half-life. Find the number of steps at which — phi multiplied by itself times equals one half. Taking logs of both sides and solving:
In words: the half-life equals the natural log of one-half, divided by the natural log of phi ( is the natural logarithm — the np.log function; it undoes "raise to a power," which is exactly why it appears here). Worked example: gives periods. A feel for the dial:
| half-life (periods) | |
|---|---|
Why traders compute this before anything else: the half-life is roughly your expected holding period for a mean-reversion trade. That drives capital efficiency, cost drag, and how long you must survive being wrong. And notice how violently the half-life explodes as (read: "as phi approaches 1"). The difference between and is a week versus a quarter. Combine that with D1-03's warning that the ADF test can barely distinguish from , and you get the central risk of the strategy: your "mean-reverting" spread may be a random walk wearing a good backtest.
Fitting AR(1) is a regression you already know
No new machinery needed. Estimating AR(1) is OLS of on — OLS being ordinary least squares, the plain line-fitting regression from A2-06. You regress the series on its own lag: the same series shifted back one step. In code, x[1:] is the response and x[:-1] is the predictor. The closed form is the familiar slope and intercept:
phi = np.cov(x[:-1], x[1:])[0, 1] / np.var(x[:-1], ddof=1) # OLS slope
c = np.mean(x[1:]) - phi * np.mean(x[:-1]) # OLS intercept
Two honest caveats. First, in small samples the OLS estimate of is biased downward — it systematically comes out too low. This is the Kendall bias: on 100 points, a true fits as roughly , which flatters the half-life (makes reversion look faster than it is). Second, as always: a fitted on history describes history. Persistence itself drifts across market regimes.
The pairs-trading connection
Here is where the track's threads knot together. A pairs trade shorts one asset and buys a related one; the combined position's value is a spread — the gap between the two prices. If that spread is stationary — the cointegration exception flagged in D1-03 — then AR(1) with is its natural model, and the trade writes itself. Enter when the spread is stretched multiple standard deviations from . Exit near . Expect to wait about one half-life. This is the simplest honest description of statistical arbitrage — trading measured statistical regularities rather than opinions about companies. The failure mode is equally clean: the economic link between the pair breaks, drifts to 1, and the spread stops reverting. That is a model-risk loss, not bad luck, and no stop-loss inside the model can see it coming.
Try it
Implement fit_ar1(x) returning the tuple (c, phi) from the OLS regression of x[1:] on x[:-1]. phi is the covariance of the lagged pairs divided by the variance of x[:-1] — np.cov and np.var with ddof=1 — and c is the mean of x[1:] minus phi times the mean of x[:-1].
The first test sequence is worth staring at: with no noise, climbs toward the long-run mean , halving the remaining gap each step — a half-life of exactly one period, matching in the table.
⧉ Review cardWrite the AR(1) model and describe what each phi regime means.
⧉ Review cardWhat are the long-run mean and the expected decay of a deviation for a stationary AR(1)?
⧉ Review cardDefine the half-life of mean reversion and give the phi = 0.9 example.
⧉ Review cardHow do you fit an AR(1), and what small-sample caveat applies?
⧉ Review cardHow does AR(1) connect to pairs trading, and what is the characteristic failure mode?
Map it
On paper, draw a concept map connecting: phi, random walk, unit root, ADF test, long-run mean, half-life, OLS slope, and pairs trading. Label each arrow with the relationship (which phi value is a unit root? what does ADF test about phi? which formula turns phi into a holding period? which regression estimates phi?).
Predict before the next lesson
Last stop: MA and ARMA models (D1-05). AR remembers its own past values. Predict: what would a series look like that instead remembers only its most recent past shock — and how would its ACF differ from the geometric decay of an AR?
◈ Calibration check
Could you fit an AR(1) by hand with the OLS formulas, compute the half-life for phi = 0.9, and explain why the phi near 1 boundary is where pairs trades die?
1 = guessing · 5 = could teach it
⏻ End of lesson
Mark it read to book its 5 review cards into your deck.
Sources & further reading
- bookTsay (2010), Analysis of Financial Time Series, 3e — §2
- bookChan (2013), Algorithmic Trading: Winning Strategies and Their Rationale — §2