Playground
Cointegration Half-Life Solver
Engle-Granger residual ADF + Ornstein-Uhlenbeck half-life from any two price/return series. Spread chart, hedge ratio, p-value.
Runs in your browser. Nothing you enter is uploaded, and no account or API key is needed.
Inputs
Price levels, one row per period. The last two numeric columns are used. Columns that look like returns (mean near 0, all values under 0.5) are compounded into a price path first.
Most recent rows used. Longer than the data uses all of it.
Half-life (periods; days for daily rows)
175.1
No clear mean reversion: the Engle-Granger test does not reject a unit root at 10%, so treat the half-life as unreliable. Test statistic -0.53 vs 5% critical value -3.34, approximate p 0.755. Based on 252 rows.
Cointegration diagnostics
Hedge ratio β
1.426
A = α + β·B + s
R²
0.147
OLS fit
DF stat
-0.53
t-stat on Δs, no lags
AR(1) φ
0.996
<1 ⇒ reverting
Spread series
Reading the result
The hedge ratio comes from regressing A on B; the residual is the spread. Regressing the change in the spread on its previous value gives φ = 1 + γ, and the half-life is −ln 2 / ln φ periods: the time for an expected deviation to shrink by half (ln 2 / θ with θ = −ln φ in Ornstein-Uhlenbeck terms). The unit-root test is a Dickey-Fuller test on the residual with Engle-Granger critical values (MacKinnon 2010: −3.90, −3.34, −3.04 at 1%, 5%, 10%); the p-value is interpolated between them and is approximate. A statistic below −3.34 rejects "no cointegration" at 5%.
How to use it
- Paste a CSV with one row per period and the two price series as the last two numeric columns (for example date, A, B), or load the demo. Rows must already be aligned; the tool does not match timestamps.
- Set the lookback window to the number of most recent rows to test (at least 30).
- Read the hedge ratio and the Engle-Granger result: a Dickey-Fuller statistic below the 5% critical value (−3.34) rejects 'no cointegration' at 5%.
- If the spread is mean-reverting, read the half-life in periods (days for daily data), computed as −ln 2 / ln φ from the spread's AR(1) coefficient, and check the spread chart for breaks.
- Re-run at a few lookback lengths. A half-life that stays similar across windows suggests a stable relationship; one that jumps around suggests a regime-dependent pair.
Questions people ask
What's cointegration half-life?
How long it takes for half of a spread's deviation from equilibrium to decay, in periods (days for daily data). With the spread modelled as AR(1), sₜ = φ·sₜ₋₁ + ε, an expected deviation shrinks by φ each period, so the half-life is −ln 2 / ln φ. In Ornstein-Uhlenbeck terms that is ln 2 / θ with θ = −ln φ. Shorter half-lives mean faster, more frequent round trips; whether a pair is tradeable also depends on the spread's size relative to your costs.
How is θ estimated?
By ordinary least squares of Δspreadₜ on spreadₜ₋₁ (no constant, since the residual spread has mean zero). The slope γ gives φ = 1 + γ and θ = −ln φ. Many write-ups use the shortcut θ ≈ −γ, which overstates the half-life slightly (by about 8% at φ = 0.85); the tool uses the exact mapping. It does not test the residuals for autocorrelation, so a spread with more complex dynamics than AR(1) can make the estimate misleading.
Does the tool test for cointegration first?
It runs the Engle-Granger two-step test: an OLS regression of A on B for the hedge ratio, then a Dickey-Fuller test (no lagged differences) on the residual, compared with MacKinnon (2010) critical values for two variables (−3.90, −3.34 and −3.04 at 1%, 5% and 10%). There is no Johansen test. The half-life is always shown, but when the test does not reject a unit root at 10% the result says the spread shows no clear mean reversion, and the half-life should not be trusted.
How sensitive is half-life to lookback length?
Highly: an estimate from six months of data can differ a lot from one on five years. The lookback slider limits the test to the most recent N rows, so re-run it at a few window lengths and compare. The tool does not compute rolling windows for you; a half-life that moves a lot between windows is a sign the relationship is regime-dependent.
Can I use this for cross-asset pairs?
The math doesn't care about asset class — it works for stock pairs, ETF arbitrage, crypto pairs, FX pairs. But the cointegration premise (a stable long-run equilibrium) is most credible for assets with structural linkage: dual-listed shares, ETF-vs-creation-basket, futures-vs-cash. Speculative pair trades on non-linked assets often produce false-positive cointegration tests.
Related tools
- Playgrounds Pair Trading Cointegration Tester
Paste two price series. Engle-Granger cointegration test: OLS hedge ratio, Augmented Dickey-Fuller on residuals, Ornstein-Uhlenbeck half-life, z-score time series with configurable entry/exit bands. Everything client-side.
- Calculators Statistical Arbitrage Capacity Calculator
Maximum strategy AUM from alpha, slippage, fees, daily volume and volatility, and signal half-life. Square-root impact closed-form.
- Calculators Portfolio Correlation Matrix
Paste a multi-asset returns CSV. See the Pearson correlation heatmap, condition number, average absolute correlation, and eigenvalue concentration — the diagnostics for detecting redundant strategies before you allocate capital.
Articles
- 11 min read Walk-Forward Window Sizing: A Decision Rule
On the canonical 50-bar tape the engine returns mean OOS Sharpe 0.653, efficiency 0.600 — but the four windows hide a regime flip the half-life rule fixes.
Use it from an agent or code
Any agent can run this calculator by URL: put the inputs in the query string and get JSON back, with the inputs that used defaults and a line to cite (add format=md for markdown). MCP clients reach it through https://aifinhub.io/mcp.
https://aifinhub.io/api/run/cointegration-half-life-solver
In code, import the same module; it runs where you import it, with no request or key.
import { compute } from "https://aifinhub.io/engines/cointegration-half-life-solver.js";