Stationarity and unit roots — when statistics on a time series mean anything
▸ Pretest — guess, even if you don't know
You regress Stock A's price on Stock B's price over five years of daily data and get R-squared 0.85 with a tiny p-value. What have you learned?
Stationarity: the license to estimate
Every statistic you compute on a time series — a mean, a volatility, an autocorrelation (the correlation of a series with its own past), a regression beta — is an average over time. Averaging over time only estimates something meaningful if the thing being estimated holds still. That requirement has a name. A series is weakly stationary if:
- its mean is constant over time,
- its variance is constant (and finite) over time,
- the covariance between and depends only on the lag , not on .
Reading the notation in condition 3: ("x sub t") is the series' value at time , and ("x sub t minus k") is its value steps earlier. The lag is how many steps back in time you look. So condition 3 says: how today relates to days ago is the same relationship in 2015 as in 2025 — it depends on the gap , not on the calendar date .
The trading question stationarity answers: is the past statistically like the future? If yes, history is a sample you can learn from. If no, your carefully estimated parameters describe a regime — a market era with its own behavior — that no longer exists. A model fit on such a series produces garbage forecasts with confident-looking standard errors.
Prices are not stationary; returns roughly are
From D1-02, a random walk's variance after steps is — "t times sigma squared," the variance of one step multiplied by the number of steps. It grows without bound, violating condition 2, and any drift (a steady tilt up or down) violates condition 1. Prices, being approximately random walks, are non-stationary. Their first difference, though — the series of changes, each value minus the one before, which for prices means returns — behaves much better. Returns have roughly constant mean near zero, roughly constant unconditional variance (unconditional — measured over the whole sample, ignoring what just happened), and autocorrelations that depend only on lag. Returns are approximately weakly stationary.
This is the general recipe. A series whose differences are stationary is called integrated of order one — meaning you must difference it exactly once to make it stationary. And differencing (np.diff, or log-price to log-return) is the standard transformation that turns it into something you may legitimately compute statistics on.
Two honest caveats. Volatility clustering (D1-01) means the conditional variance of returns — the variance given what just happened — moves around, so returns are not iid (independent and identically distributed). Weak stationarity is a workable approximation, not a law. And markets have regimes: a mean and volatility estimated in 2017 described 2017. Stationarity is always an assumption you argue for, never a fact you observe.
Spurious regression: the classic trap
Spurious means fake — an artifact of the method, not a real relationship. Why exactly does regressing price on price blow up? Both series wander; that is what random walks do. Over any given window, two wandering series will drift in some loosely shared way — up-up, down-down, or up-down — so the regression finds a strong "relationship" in-sample. Worse, the regression residuals — the leftover errors after the fit — are themselves non-stationary. That violates the assumptions behind OLS standard errors (OLS — ordinary least squares, the standard regression from A2-06). The t-statistics and p-values are simply wrong, and R-squared — the share of variation the regression claims to explain — stays high no matter how much data you add. Granger and Newbold's simulated independent walks produced (a t-statistic beyond the usual "significant" bar) about 75% of the time.
The trap wears many trading costumes: "my indicator is 0.9 correlated with the S&P," "these two coins move together." Computed on levels — the raw prices themselves rather than their changes — all of it is meaningless. The fix is mechanical: difference first. Regress returns on returns, changes on changes. (There is one important exception. Sometimes a combination of two non-stationary prices is genuinely stationary. That is called cointegration, and it is the respectable foundation of pairs trading. D1-04 builds the model for that spread.)
Unit roots and the ADF test
Write the suspicion formally with next lesson's model:
In words: the next value equals times the current value, plus a fresh shock. is the Greek letter phi — a number that says how much of today carries into tomorrow. ("epsilon sub t") is the shock — fresh random noise arriving at each step, as in D1-02. Concrete: with and today's value 10, tomorrow's expected value is 9 — the series gets pulled back toward zero.
If , this is exactly a random walk: today carries over in full, shocks never decay, and the series is said to have a unit root ("unit" = the value one; the root of the equation sits exactly at 1) — it is non-stationary. If , shocks decay and the series is stationary. The Augmented Dickey–Fuller (ADF) test asks which world you are in. Read it carefully, because the direction trips people up:
- Null hypothesis: the series has a unit root (non-stationary).
- Small p-value → reject the null → evidence the series is stationary.
- Large p-value → you failed to reject; the series may well be a random walk.
In practice it is one line (shown for orientation — the exercise runtime here is numpy-only, so run this locally):
from statsmodels.tsa.stattools import adfuller
stat, pvalue, *_ = adfuller(x) # H0: unit root (non-stationary)
Typical output: SPY prices, p around 0.6 — cannot reject the unit root. SPY returns, p far below 0.01 — stationary. One warning: the ADF test has low power near the boundary — low power meaning it often fails to detect a difference even when one exists. In practice it often cannot tell (slowly mean-reverting, tradeable) from (random walk, not tradeable). Failing to reject is absence of evidence, not proof of a unit root — and that ambiguity is exactly where many pairs trades go to die.
Try it
A crude but instructive stationarity check: a series whose mean drifts fails the most basic requirement.
Implement two functions. difference(x) returns the first difference of x, using np.diff. is_mean_stable(x) is a crude stationarity check: split x into a first half of len(x) // 2 points and a second half with the rest, and return True when the absolute gap between the two half means is at most 0.5 times the sample standard deviation of the whole series, np.std with ddof=1. Real work uses the ADF test; this builds the intuition that a stationary series has no drifting mean.
⧉ Review cardState the three conditions of weak stationarity and why they matter.
⧉ Review cardWhy are prices non-stationary while returns are roughly stationary?
⧉ Review cardWhat is spurious regression and what is the rule that prevents it?
⧉ Review cardWhat are the null hypothesis and reading of the ADF test?
Teach it
Teach spurious regression to an imaginary junior analyst who just proudly showed you a levels-on-levels regression with R-squared 0.9. In your own words: why do two independent random walks look related, what exactly breaks in the OLS standard errors, and what one-line rule should they follow from now on? Two minutes, out loud.
Predict before the next lesson
Next: autoregressive models (D1-04). Before then, predict: you want a model of a series that gets pulled back toward a long-run mean instead of wandering forever. How would you write next value as a function of the current value plus noise — and what coefficient value would turn your model back into a random walk?
◈ Calibration check
Could you define weak stationarity, explain to a colleague why regressing prices on prices is invalid, and state exactly what the ADF null hypothesis is?
1 = guessing · 5 = could teach it
⏻ End of lesson
Mark it read to book its 4 review cards into your deck.
Sources & further reading
- bookTsay (2010), Analysis of Financial Time Series, 3e — §2
- paperGranger & Newbold (1974), Spurious Regressions in Econometrics, Journal of Econometrics 2