getcracked
Blog / Technical

Pairs Trading Strategy (Mean Reversion)

Technical

"Find two drunk guys walking home together. You don't know where they are going (Random Walk), but you know they won't get too far apart (Cointegration)."


The Concept

Pairs Trading is a market-neutral strategy. You go Long Stock A and Short Stock B.
You don't care if the market goes up or down. You only care if the Spread between them reverts to the mean.

Step 1: Finding the Pair (Cointegration)

Do not look for correlation. Look for cointegration using the Augmented Dickey-Fuller (ADF) test on the spread.
Examples: PEP vs KO, XOM vs CVX, Gold vs Gold Miners.

Step 2: Calculate the Spread

Perform a linear regression to find the hedge ratio ($\beta$).$$ P_A = \alpha + \beta P_B + \epsilon $$The spread is the residual ($\epsilon$).$$ Spread_t = P_{A,t} - \beta P_{B,t} $$

Step 3: Generate Z-Score Signals

Normalize the spread to trade based on standard deviations.$$ Z_t = \frac{Spread_t - \mu_{spread}}{\sigma_{spread}} $$
Entry Long: If Z < -2.0 (Spread makes A cheap relative to B). Buy A, Short B.
Entry Short: If Z > +2.0 (Spread makes A expensive relative to B). Short A, Buy B.
Exit: If Z reverts to 0.0.

1
import numpy as np
2
import pandas as pd
3
import statsmodels.api as sm
4

5
def backtest_pairs(price_A, price_B, window=60):
6
    # 1. Calculate Hedge Ratio using Rolling OLS (Dynamic Beta)
7
    # Using statsmodels RollingOLS for efficiency
8
    
9
    # Simple static beta for clarity:
10
    model = sm.OLS(price_A, price_B).fit()
11
    beta = model.params[0]
12
    
13
    # 2. Calculate Spread
14
    spread = price_A - beta * price_B
15
    
16
    # 3. Calculate Z-Score
17
    spread_mean = spread.rolling(window=window).mean()
18
    spread_std = spread.rolling(window=window).std()
19
    z_score = (spread - spread_mean) / spread_std
20
    
21
    return z_score, beta
22

23
# Trading Logic
24
# if z_score > 2: Short Spread (Short A, Long beta * B)
25
# if z_score < -2: Long Spread (Long A, Short beta * B)
26
# if abs(z_score) < 0.5: Exit Positions
27

Risks

The Breakup (Divergence)

Sometimes the relationship breaks forever (structural change). Example: One company gets acquired, or discovers a massive oil field. The spread widens to infinity (Z-score goes to 10, 20...). You get margin called.Always use Stop Losses.