A Python implementation of a market-neutral pairs trading strategy using z-score based signals on highly correlated stock pairs.
I am a Mechatronics Engineering graduate and a postgraduate in Finance from Henley Business School, looking to enter the field of finance in data science, machine learning, or quantitative finance.
- 💼 LinkedIn: linkedin.com/in/sauravsen34
- 📧 Email: saurav0sen34@gmail.com
Pairs trading is a market-neutral strategy where two stocks from the same sector with high positive correlation are paired together. Because they are driven by the same macro factors — interest rates, regulation, consumer spending — they tend to move together over time.
When the spread between them diverges unusually, you bet on mean reversion — that the relationship will return to normal. You simultaneously go long the underperformer and short the outperformer, profiting when the gap closes regardless of which direction the overall market moves.
Pair used: Coca-Cola (KO) vs Pepsi (PEP) — same sector, same consumer base, high historical correlation.
The z-score measures how many standard deviations the current spread is from its 30-day historical mean:
Z-Score = (Spread - 30-day Mean) / 30-day Std Dev
| Z-Score | Meaning | Action |
|---|---|---|
| > +2 | Spread unusually wide | Short KO, Long PEP |
| < -2 | Spread unusually narrow | Long KO, Short PEP |
| Between -1 and +1 | Normal range | No trade |
A z-score near zero means the spread is close to its historical average — no divergence, no trade signal.
The strategy assumes the historical relationship between the two stocks remains stable. The biggest risk is cointegration breakdown — when a sector-wide event (like the 2008 housing crisis) causes correlations that held for years to collapse simultaneously. In that scenario both legs of the trade can lose money at the same time.
git clone https://github.com/sauravsen3/pairs-trading.git
cd pairs-trading
pip install -r requirements.txt
python pairs.pyOutput:
--- Pairs Trading Signals: KO vs PEP ---
Total trading days: 754
Long signals: 12
Short signals: 8
Current Z-Score: 0.34
Two charts are generated — the price spread over time with its rolling mean, and the z-score with upper and lower trading thresholds marked.
pairs-trading/
│
├── pairs.py # Spread calculation, signals, chart
├── requirements.txt # Python dependencies
└── pairs_trading.png # Generated on first run
- yfinance — historical price data for both tickers
- pandas / numpy — spread and z-score calculation
- matplotlib — dual-panel chart of spread and z-score
Part of a series of quantitative finance projects. Previous: Algorithmic Trading Backtest. Next: DCF Valuation Automator.