Mean Reversion and Statistical Arbitrage › The Johansen Test for Multiple Cointegration
Quantitative FinanceAll chapters Mean Reversion and Statistical Arbitrage › The Johansen Test for Multiple CointegrationOne section · Sections in this chapter8 / 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
When working with more than two securities, the Engle-Granger method becomes cumbersome. The problem is that Engle-Granger requires you to choose one series as the "dependent variable" and can only identify one cointegrating relationship. With three or more securities, there may be multiple independent cointegrating relationships, and the choice of which series to regress on which becomes arbitrary. The Johansen test provides a more general framework for testing cointegration among multiple time series and identifying all cointegrating relationships simultaneously.
Theoretical Framework
The Johansen procedure tests for cointegration in a vector autoregression (VAR) framework using a Vector Error Correction Model (VECM). The VECM representation is particularly elegant because it decomposes price changes into two distinct components: a long-term error correction component that pulls prices back toward equilibrium when they deviate, and short-term autoregressive dynamics that capture momentum and other temporary effects. For a vector of time series , the VECM representation is:
where:
- : vector of price changes at time
- : impact matrix governing long-run error correction
- : vector of price levels at time
- : matrices of coefficients for short-term dynamics
- : lag order of the VAR model
- : vector of error terms
The matrix contains all information about the long-run relationships among the series. Its rank equals the number of cointegrating relationships, and gives a characterization of the equilibrium structure:
- : No cointegration, all series have unit roots. The series can drift apart without bound.
- : Cointegration exists with cointegrating vectors. There are independent linear combinations of the series that are stationary.
- : All series are stationary. This case is unlikely for price series, which typically have unit roots.
When , the matrix can be decomposed as , where is an matrix whose columns are the cointegrating vectors, and is an matrix of adjustment coefficients that determines how quickly each series responds to deviations from equilibrium.
from statsmodels.tsa.vector_ar.vecm import coint_johansen
# Generate three cointegrated series
np.random.seed(789)
n = 500
# Common stochastic trend with a small drift
trend = np.cumsum(0.05 + np.random.randn(n))
# Add distinct stationary AR(1) deviations around the shared trend.
stationary_deviations = []
for _ in range(3):
deviation = np.zeros(n)
for t in range(1, n):
deviation[t] = 0.6 * deviation[t - 1] + 0.5 * np.random.randn()
stationary_deviations.append(deviation)
series1 = trend + stationary_deviations[0]
series2 = 0.8 * trend + 50 + stationary_deviations[1]
series3 = 1.2 * trend + 100 + stationary_deviations[2]
# Combine into matrix
data_matrix = np.column_stack([series1, series2, series3])
# Perform Johansen test
# det_order: -1 = no deterministic terms, 0 = constant inside cointegration, 1 = constant outside
johansen_result = coint_johansen(data_matrix, det_order=0, k_ar_diff=2)Johansen Cointegration Test Results ================================================== Trace Statistic Test: r Trace Stat 90% CV 95% CV 99% CV ------------------------------------------------------- r≤0 153.2536 27.0669 29.7961 35.4628 r≤1 73.1206 13.4294 15.4943 19.9349 r≤2 1.9926 2.7055 3.8415 6.6349 Cointegrating Vectors (normalized): Vector 1: [1.1684, -1.7605, 0.2016] Vector 2: [-1.0997, -0.7133, 1.3948] Vector 3: [0.0021, 0.0496, 0.0593]
The results show that the trace statistic exceeds the critical values for and , but not for . This implies the existence of two cointegrating relationships () among the three assets, consistent with the data generation process where a single common trend drives all three series. With three series and two cointegrating relationships, there is exactly one common stochastic trend, which matches our construction.
The trace statistic tests the null hypothesis against . When the trace statistic exceeds the critical value, we reject the null and conclude there are more than cointegrating relationships. The sequential testing procedure starts with and continues until we fail to reject, thereby determining the number of cointegrating relationships.
Constructing Baskets from Cointegrating Vectors
The cointegrating vectors from the Johansen test define stationary linear combinations of the prices. These become tradeable spreads for stat arb strategies. Each cointegrating vector specifies the weights to use when combining the securities into a spread. For instance, if the first cointegrating vector is , the corresponding spread is computed as . This spread will be stationary even though each individual series is non-stationary.


