Mean Reversion and Statistical Arbitrage › Testing for Mean Reversion
Quantitative FinanceAll chapters Mean Reversion and Statistical Arbitrage › Testing for Mean ReversionOne section · Sections in this chapter3 / 12 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Before trading a mean reversion strategy, you must verify that mean reversion exists in your target series. This verification step is essential. A random walk has no mean reversion: past deviations provide no information about future movements. Trading mean reversion on a random walk is a losing proposition because you are betting on convergence that has no statistical tendency to occur.
The distinction between a mean-reverting process and a random walk can be easy to miss. Both exhibit random fluctuations, and both can appear to drift away from their starting point over short horizons. The difference lies in long-term behavior: a mean-reverting process has a "gravitational center" that pulls it back toward equilibrium, while a random walk has no such anchor and can drift arbitrarily far from any reference point.
The Ornstein-Uhlenbeck Process
The canonical model for a mean-reverting process is the Ornstein-Uhlenbeck (OU) process. This stochastic differential equation captures the essential dynamics of mean reversion in continuous time, and gives a mathematically tractable framework for analysis and parameter estimation. The OU process is defined by:
where:
- : change in the process value
- : value of the process at time
- : speed of mean reversion (higher values mean faster reversion)
- : long-run mean level
- : small time increment
- : volatility of the process
- : standard Brownian motion increment
The intuition behind this equation becomes clear when we examine its two components. The first term, , represents the deterministic drift that creates mean reversion. When , the quantity is negative, making the drift term negative, which pushes the process down toward . Conversely, when , the drift is positive, pushing the process up toward . The further the process deviates from , the stronger this restoring force becomes, much like a spring that pulls harder when stretched further.
The parameter controls how quickly this reversion occurs. A high means strong mean reversion, where deviations correct rapidly. A low means weak mean reversion, where the process meanders more before returning to equilibrium. The second term, , represents random shocks that continuously buffet the process, creating the fluctuations around the mean that generate trading opportunities.
The half-life of mean reversion provides a practical measure of how quickly deviations decay. It is the expected time for a deviation to shrink by half:
where:
- : expected time for a deviation to decay by 50%
- : speed of mean reversion
The half-life determines the expected holding period for trades. If the half-life is too long relative to your trading horizon, you may not capture the reversion before other factors dominate. For instance, if a spread has a half-life of six months but you need to close positions within weeks due to margin constraints or reporting requirements, you face significant risk that the spread hasn't reverted by the time you must exit. Conversely, if the half-life is very short, perhaps hours or minutes, the strategy may require high-frequency execution capabilities that introduce additional costs and complexity.



The Augmented Dickey-Fuller Test
The Augmented Dickey-Fuller (ADF) test is the workhorse for testing whether a time series is stationary (mean-reverting) or contains a unit root (random walk). The test is constructed around a clever regression specification that directly tests for the presence of mean-reverting behavior. The test estimates the regression:
where:
- : change in the series value at time
- : drift constant
- : coefficient on the time trend
- : coefficient testing for mean reversion (unit root)
- : coefficients on lagged changes capturing serial correlation
- : number of lag terms
- : error term
The key parameter is , which determines the long-run dynamics of the series. The null hypothesis is that , indicating a unit root: the lagged level has no power to predict the current change . Under this null, the series follows a random walk and exhibits no mean reversion.
The alternative hypothesis is , indicating mean reversion. The intuition here is subtle but important. A negative coefficient on the lagged level means that when the series is high (large ), the expected change is negative (pushing the series down). When the series is low (small ), the expected change is positive (pushing the series up). This is precisely the behavior we want: a restoring force that pulls the series back toward its long-run trend.
The lagged changes are included to absorb any serial correlation in the data, so the test statistic has the correct distribution. A more negative test statistic provides stronger evidence against the null, indicating more convincing mean reversion.
import numpy as np
from statsmodels.tsa.stattools import adfuller
np.random.seed(42)
# Generate a mean-reverting series (OU process)
n = 500
kappa = 0.5 # Mean reversion speed
mu = 100 # Long-run mean
sigma = 2 # Volatility
dt = 1
ou_series = np.zeros(n)
ou_series[0] = mu
for t in range(1, n):
ou_series[t] = (
ou_series[t - 1]
+ kappa * (mu - ou_series[t - 1]) * dt
+ sigma * np.sqrt(dt) * np.random.randn()
)
# Generate a random walk for comparison
random_walk = np.cumsum(np.random.randn(n)) + 100
# Run ADF tests
adf_ou = adfuller(ou_series, maxlag=10, autolag="AIC")
adf_rw = adfuller(random_walk, maxlag=10, autolag="AIC")ADF Test Results ================================================== Mean-Reverting Series (OU Process): Test Statistic: -13.0600 p-value: 0.0000 Critical Values: 1%: -3.444, 5%: -2.867 Random Walk: Test Statistic: -0.3119 p-value: 0.9238 Critical Values: 1%: -3.444, 5%: -2.867
The OU process shows a highly negative test statistic well below the critical values, leading us to reject the null hypothesis of a unit root. The random walk, by contrast, has a test statistic close to zero, and we cannot reject the null. This distinction is fundamental: the OU process is suitable for mean reversion trading, while the random walk is not.


Estimating Mean Reversion Parameters
Once you've established that a series is mean-reverting, you need to estimate the parameters , , and to design trading rules. These parameters have direct practical implications: determines the target level for convergence trades, determines how long you should expect to hold positions, and determines the typical magnitude of fluctuations and hence appropriate position sizing.
The discrete-time analog of the OU process sets up parameter estimation:
where:
- : value of the process at time
- : speed of mean reversion
- : long-run mean
- : time step size
- : volatility parameter
- : standard normal random variable
This equation shows that the change in the process depends on how far the current value is from the long-run mean, scaled by the mean reversion speed and time step, plus a random shock. Rearranging terms allows us to formulate a linear regression that can be estimated using standard OLS techniques. We begin by expanding the drift term and regrouping:
This algebraic manipulation reveals that the OU process, when discretized, takes the form of a simple autoregressive model. The current value depends linearly on the previous value plus a constant and noise. This matches the form of a simple linear regression:
where:
- : regression intercept
- : regression slope
- : regression residual with variance
The power of this formulation is that simple OLS regression yields estimates of and , from which you can recover the underlying OU parameters. Specifically, solving for from the slope coefficient gives , and substituting into the intercept equation gives . The volatility parameter can be estimated from the standard deviation of the residuals.
from scipy import stats
def estimate_ou_parameters(series, dt=1):
"""Estimate OU process parameters from time series data."""
X_t = series[1:]
X_t_1 = series[:-1]
# OLS regression: X_t = a + b * X_{t-1}
slope, intercept, r_value, p_value, std_err = stats.linregress(X_t_1, X_t)
# Extract OU parameters
b = slope
a = intercept
kappa = (1 - b) / dt
mu = a / (kappa * dt)
# Estimate sigma from residuals
residuals = X_t - (a + b * X_t_1)
sigma = np.std(residuals) / np.sqrt(dt)
# Calculate half-life
half_life = np.log(2) / kappa if kappa > 0 else np.inf
return {
"kappa": kappa,
"mu": mu,
"sigma": sigma,
"half_life": half_life,
"r_squared": r_value**2,
}
ou_params = estimate_ou_parameters(ou_series)Estimated OU Parameters ======================================== Mean reversion speed (κ): 0.5120 Long-run mean (μ): 100.04 Volatility (σ): 1.9584 Half-life: 1.35 periods R-squared: 0.2377 True parameters: κ=0.50, μ=100.00, σ=2.00
The estimated parameters closely match the true values used to generate the series, validating our estimation procedure. The half-life of approximately 1.4 periods tells us that deviations from the mean shrink by half in about 1-2 time steps, indicating quite fast mean reversion.