Quant Memo
Advanced

Ornstein-Uhlenbeck Mean Reversion

The working model behind almost every spread trade — a quantity pulled back toward a level, with the pull proportional to how far it has strayed. Three parameters fall out of a single regression, and they tell you your holding period, your position size and whether the trade survives costs.

Prerequisites: Mean Reversion, Ordinary Least Squares (OLS)

A random walk has no memory: where it goes next has nothing to do with where it is. That is a fine model for a stock price and a useless one for a spread, because a spread is exactly the thing you believe does remember. The Ornstein-Uhlenbeck process is the smallest change to a random walk that gives it a memory — a pull back toward a level, strong when the thing is far away, weak when it is close. Every spread trade you will ever put on is, underneath, a bet that this model is roughly right.

Three parameters, one equation

dxt=θ(μxt)dt+σdWtdx_t = \theta(\mu - x_t)\,dt + \sigma\,dW_t

In words: over the next instant, the spread drifts toward μ\mu by a fraction θ\theta of its current distance from μ\mu, and then gets shoved around by noise of size σ\sigma. That is it. μ\mu is the level it comes home to, θ\theta is how hard it is pulled, σ\sigma is how hard it is pushed.

The signs matter. If xtx_t is above μ\mu, then μxt\mu - x_t is negative and the drift is down. If it is below, the drift is up. The pull is a restoring force, like a spring — and like a spring, the further you stretch it the harder it pulls back.

Drag the slider to the mean-reverting setting below and watch the paths. Raise the reversion speed and the paths hug the centre line; lower it and they wander for long stretches before coming back. Nothing else about the picture changes — same noise, same level, only the strength of the spring.

Path explorer
13055time →
end (bold path) 100.38spread of ends 58.966 independent paths, same settings

Getting the parameters out of data

You do not fit this in continuous time. Sample the spread daily and it becomes an AR(1) regression you already know how to run:

xt+1=c+ϕxt+εt+1x_{t+1} = c + \phi\,x_t + \varepsilon_{t+1}

Regress today's spread on yesterday's. Three numbers come back, and each maps onto one of the OU parameters:

  • Reversion speed. θ=lnϕ\theta = -\ln \phi per day. A slope near 1 means almost no pull; a slope near 0 means violent snap-back.
  • Long-run level. μ=c/(1ϕ)\mu = c/(1-\phi). For a properly constructed spread this should be close to zero.
  • Equilibrium spread width. σeq=σε/1ϕ2\sigma_{\text{eq}} = \sigma_\varepsilon/\sqrt{1-\phi^2}, where σε\sigma_\varepsilon is the regression's residual standard deviation. This is the standard deviation of the spread itself, not of its daily changes, and it is the number you divide by to get a z-score.

The quantity everyone actually quotes is the half-life, t1/2=ln2/θt_{1/2} = \ln 2/\theta: how many days it takes a deviation to decay halfway back.

Worked example: reading a real fit

Two refiners. You build the spread xt=PA1.2PBx_t = P_A - 1.2\,P_B and regress it on its own lag over 250 trading days. The output: ϕ=0.94\phi = 0.94, σε=0.42\sigma_\varepsilon = 0.42, intercept indistinguishable from zero.

  1. Speed. θ=ln0.94=0.0619\theta = -\ln 0.94 = 0.0619 per day.
  2. Half-life. t1/2=0.693/0.0619=11.2t_{1/2} = 0.693/0.0619 = 11.2 trading days. So roughly a two-and-a-half-week holding period — fast enough to be worth financing.
  3. Width. σeq=0.42/10.942=0.42/0.3412=1.23\sigma_{\text{eq}} = 0.42/\sqrt{1-0.94^2} = 0.42/0.3412 = 1.23. So one z-score is $1.23 of spread per share-pair.

The half-life is the single most useful output. It sets your holding period, your turnover, and therefore whether the trade clears costs. A half-life of days is tradeable. A half-life of a year is a value thesis wearing a stat-arb costume.

Worked example: does the trade pay?

Same fit. The spread stretches to z=+2z = +2, meaning $2.46 above its mean. You short one share of A at $60 and buy 1.2 shares of B at $50 — $120 of gross notional per share-pair. You will exit at z=+0.5z = +0.5.

  1. Distance travelled. From $2.46 down to $0.62 is $1.84 of gross profit per share-pair.
  2. Expected time. Decay from 2σ2\sigma to 0.5σ0.5\sigma is a factor of 4, so t=ln4/θ=1.386/0.0619=22.4t = \ln 4/\theta = 1.386/0.0619 = 22.4 days.
  3. Costs. The round trip touches $240 of notional (in and out, both legs). At 5 bp that is $0.12.
  4. Net. $1.72, or 1.72/120=1.43%1.72/120 = 1.43\% of gross notional over 22 trading days.

Redeployed continuously that would annualise to about 16%. It will not be, because the spread only sits beyond z=2z = 2 maybe a fifth of the time. This is the arithmetic that pushes every stat-arb desk toward running hundreds of spreads at once rather than one very good one.

Where the model lies to you

θ\theta is biased upward in short samples. The OLS estimate of an AR(1) slope is biased down by roughly (1+3ϕ)/T(1+3\phi)/T when you also estimate the mean. On 60 observations with a true ϕ\phi of 0.96, you expect to measure about 0.90 — which reports a half-life of 6.6 days when the truth is 17. You will size as though the trade turns over two and a half times faster than it does.

Reversion speed is not stable. θ\theta estimated on a calm quarter and θ\theta estimated through an earnings season are different numbers for the same pair. Re-fit on a rolling window and treat any large jump in the fit as a signal about the relationship, not just a new parameter.

A broken spread looks like a slow one. When two names genuinely decouple — a merger, a business-model divergence, an index deletion — the fit does not scream. It quietly returns ϕ=0.99\phi = 0.99, a half-life of 69 days, and a wide σeq\sigma_{\text{eq}} that makes your current 4-sigma loss look like a 2-sigma one. Nothing in the OU framework distinguishes "reverting slowly" from "no longer reverting at all"; that is what break tests and a hard time stop are for.

The noise is not Gaussian. σdWt\sigma\,dW_t assumes shocks are normal and independent. Spread shocks arrive in clusters and have fat tails, so a "5-sigma" move on OU arithmetic happens far more often than once a lifetime.

In interviews

Write the SDE, then immediately translate it: drift proportional to distance from the mean, plus noise. Say that you fit it as an AR(1) regression of the spread on its own lag, and produce the three mappings — θ=lnϕ\theta = -\ln\phi, half-life =ln2/θ=\ln 2/\theta, σeq=σε/1ϕ2\sigma_{\text{eq}} = \sigma_\varepsilon/\sqrt{1-\phi^2}. Then make the practical point unprompted: the half-life is what tells you whether the edge survives transaction costs, and the AR(1) slope is biased in short samples in the direction that flatters you.

Related concepts

Used in strategies

Practice in interviews

Further reading

  • Uhlenbeck & Ornstein (1930), On the Theory of the Brownian Motion
  • Avellaneda & Lee (2010), Statistical Arbitrage in the U.S. Equities Market
  • Chan, Algorithmic Trading (ch. on mean reversion)
ShareTwitterLinkedIn