- corr()
- correlation matrix
- pct_change
- Pearson correlation
- multi-asset
- spurious correlation
- diversification
- portfolio risk
Multi-Asset Correlation Analysis
Scene: the risk desk, Monday 8:47am. Your PM slides a four-stock book across the desk — AAPL, MSFT, JPM, GS — and asks the only question that matters before adding leverage: "How diversified are we, really?" The answer is not four numbers. It is a matrix: every stock's co-movement with every other stock. Build it wrong — and plenty of interns do — and you will report a hedge that does not exist.
Correlation is fundamental to portfolio construction. Markowitz showed that diversification reduces risk only when asset correlations are below 1.
Pearson Correlation
ρ(i,j) = Cov(rᵢ, rⱼ) / (σᵢ · σⱼ)
| ρ value | Meaning |
|---|---|
| +1.0 | Perfect co-movement |
| +0.7 | Strong positive relationship |
| 0.0 | Independent assets |
| −1.0 | Perfect hedge |
🧠 The mental model: judge the steps, not the walk
A price series is a walk — 120 days of accumulated drift. A daily return is a single step. Two hikers can finish on the same summit without ever stepping in sync, and two dancers can mirror every step while drifting to opposite corners of the room. Co-movement lives in the steps, not in where the walk ends up.
That is why professionals correlate returns, never price levels:
- ›Price levels trend. Any two trending series show large spurious correlation — sometimes inflated, sometimes even flipped in sign — that says nothing about co-movement. Statisticians have warned about this since Yule's 1926 paper on "nonsense correlations".
- ›Daily returns are (nearly) trend-free, so their correlation answers the question you actually care about: when AAPL has a bad day, does JPM have one too?
Building the matrix in pandas
Pythonreturns = prices.pct_change().dropna() # wide format: rows = dates, columns = tickers corr = returns.corr() # symmetric matrix, diagonal = 1.0 print(corr.round(2).to_string()) # prints beautifully as text
No plotting library needed: corr.round(2) prints a perfectly readable matrix, and a few block characters (█) turn the six unique pairs into a text heatmap — exactly what the starter code below does.
📜 Why Correlations Break Down — The 2008 Lesson
The correlation matrix you are computing is the mathematical heart of Markowitz's 1952 diversification proof. But there is a brutal empirical truth that every portfolio manager learns the hard way:
Correlations are not stable. They are conditional on the market regime.
Normal markets (2005–2007): Large-cap US equities had average pairwise correlations of ~0.30–0.45. A portfolio of 20 stocks genuinely reduced risk through diversification.
September–October 2008: As Lehman Brothers collapsed, pairwise correlations across large-cap US equities spiked to 0.85–0.95 within weeks. Every diversified portfolio lost roughly the same fraction of value simultaneously. The mathematical diversification benefit — which Markowitz's formula assumed stable — effectively disappeared.
This phenomenon is known as "correlation breakdown under stress" and it is one of the most-cited limitations of standard mean-variance optimisation. It has led to:
- ›Regime-switching models (Hamilton 1989) — separate correlation matrices for bull and bear regimes
- ›Copula models — capturing non-linear dependence structures (David Li's Gaussian copula was controversially used to price CDOs before 2008)
- ›Stress testing — regulators now require banks to test portfolios under stressed correlation assumptions (Basel III, 2010)
2010 — Flash Crash: US equity correlations again spiked to near 1.0 during the 45 minutes in which the Dow Jones fell ~1,000 points. High-frequency trading algorithms, which assumed normal correlations, withdrew liquidity simultaneously.
The correlation matrix is not a historical fact. It is a current snapshot of a changing relationship. Always ask: what happens to these correlations in a crisis?
Career insight: Portfolio risk analysts spend a large portion of their time monitoring correlation breakdowns. During market stress, correlations spike toward 1 — meaning diversification fails exactly when you need it most.
Your Task
The starter simulates 120 business days of correlated prices for AAPL, MSFT, JPM and GS (fixed seed — the numbers are identical on every run), then prints the correlation matrix, a text heatmap of the six unique pairs, and a sanity check. The pipeline is complete except for one bug: the matrix is currently computed on price levels — prices.corr() — instead of returns.
Predict before you run: run the starter as-is and look at the AAPL row. The level matrix claims the AAPL–JPM correlation is −0.24 — a natural hedge inside a long-only equity book! Before touching anything, predict: once you correlate returns instead, will that number stay negative, sit near zero, or turn solidly positive? (The simulation's true underlying value is +0.40.) Then fix the 👉 line and see whether the sanity check agrees with you.