σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyRoadmapsSkills
Ctrl K
AO
+1.2k Learners
LoginJoin ↗
RoadmapsSkills
AO
+1.2k Learners
Login
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyRoadmapsSkills
Ctrl K
AO
+1.2k Learners
LoginJoin ↗
RoadmapsSkills
AO
+1.2k Learners
Login
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
statsmodels skill›Module 2 · Models for time series›Topic 2.9·~1 hrAdvanced

Cointegration and the trap of searching pairs

Skill positionModule 2 of 3 · Topic 9 of 9
2.9 Cointegration and the trap of searching pairs
—Lab score— / 100Total XP—Streak—

Two prices that stay together, and the trap of searching

Log prices aₜ and bₜ are each non-stationary, yet they are cointegrated if some combination sₜ=aₜ-βbₜ-α is stationary: the two drift together and the spread sₜ keeps returning to zero. The hedge ratio comes from an ordinary regression of a on b with a constant, sm.OLS(a, sm.add_constant(b)).fit(); its slope is β and its intercept α. How fast the spread reverts is measured by an AR(1): sₜ=c+φsₜ₋₁+uₜ. With 0<φ<1 the half-life is -ln 2/lnφ periods, the time to close half of a gap; φ near 1 means a random walk and no trade. The Engle-Granger test, coint(a, b), tests the null that the spread has a unit root, so a small p-value is evidence of cointegration. It uses special critical values, because the spread comes from a regression and is not an ordinary series.

Now search. Test 66 pairs at the 5% level and about 3 will pass by pure chance; with persistent prices the test is even more generous. A Bonferroni correction divides the level by the number of tests, 0.05/66, and keeps only the very small p-values. Here, on the first 669 weekly observations of 12 stocks, 13 of the 66 pairs have p<0.05 and 2 survive Bonferroni, and the best are not economically natural: a bank (WFC) with a beverage maker (PEP), p=0.0005. The honest check is out of sample. Fix the hedge ratio on the first half, form the spread on the second half, and test again. None of the five best pairs is still cointegrated (p-values 0.54 to 0.86), and the AR(1) coefficient of the later spread is 0.99: it no longer reverts. A strategy built on a search needs a correction for the search, and a test on data the search never saw.

  • Cointegration means a stationary spread a-βb-α; the Engle-Granger null is a unit root, so small p means cointegrated.
  • Half-life -ln 2/lnφ from the AR(1) coefficient tells how long a gap takes to close; φ≥1 means never.
  • Search, correct, then test out of sample: 66 pairs find noise; Bonferroni helps; only later data tells.

Lab · what's graded

  • The hedge ratio10 pts
  • The spread5 pts
  • The AR(1) coefficient10 pts
  • The half-life10 pts
  • The Engle-Granger test5 pts
  • Scanning all pairs15 pts
  • Counting discoveries10 pts
  • Out of sample15 pts
  • The pairs study20 pts
Explorer · lab-sx-19
▾ lab-sx-19
▾ data
…
bash · in-browser
learner@quantcraft:~/lab-sx-19$
Python not loaded yetPythonLn 1, Col 1Spaces: 4UTF-8

Reset this topic?

Everything in lab-sx-19 goes back to the starter files and the terminal is cleared. Your current solution will be lost — this can't be undone.

Will be reset
  • main.py → starter code
  • Terminal history and test output
  • Unsubmitted changes
Will be kept
  • Best lab score
  • Your XP and streak
  • Lecture progress and notes

Log in to run your code.

Every lecture is free to read. Create an account or log in to run code, run tests and submit this lab.

  • In-browser IDE with a bash terminal — nothing to install
  • Instant grading, XP and your place on the skill
Create an accountLog in
OR
Continue with GitHub