Quant Memo
Advanced

Cholesky Decomposition

Every valid covariance matrix has a 'square root' that turns independent noise into correlated noise — the Cholesky decomposition is how simulations get correlated random numbers out of a stream of uncorrelated ones.

Prerequisites: Variance, Intuitively, Vector Spaces and Bases

You want to simulate tomorrow's returns for ten correlated stocks. Your computer's random number generator only produces independent numbers — every draw ignorant of every other. How do you turn a stream of independent noise into ten numbers with exactly the correlation structure you specified in a covariance matrix? You need something that plays the role of a "square root" for a matrix, and the Cholesky decomposition is that square root, built specifically for the matrices that show up as covariances.

The analogy: mixing paint to hit a target colour

Suppose you have pure red, pure green, and pure blue paint (independent ingredients) and you want to mix a specific shade of brown (a target with known relationships between its components). You need a recipe: how many parts red, then how many parts green on top, then how many parts blue on top of that. Cholesky is exactly this recipe, written as a matrix. It tells you: take independent standard-normal number one, scale it; take independent number two, mix in a bit of number one, scale the result; take independent number three, mix in bits of both — and so on, until the resulting numbers have exactly the variances and covariances you asked for. Each new ingredient only ever adds to the previous ones, never adjusts something already mixed — that one-directional structure is what makes Cholesky fast and unique.

Writing it down

Take a covariance matrix Σ\Sigma — symmetric, and positive definite (meaning every portfolio built from these assets has strictly positive variance; no combination is riskless or negatively risky). The Cholesky decomposition finds a lower-triangular matrix LL (zeros above the diagonal) such that

Σ=LL.\Sigma = LL^\top .

In words: LL is a "square root" of Σ\Sigma in matrix form — multiplying it by its own transpose reconstructs the whole covariance matrix. Because LL is lower-triangular, its first row only touches the first variable, its second row touches the first two, and so on — that's the "mix in one ingredient at a time" recipe from the paint analogy, made precise.

To generate correlated draws: take a vector zz of independent standard-normal numbers (mean 0, variance 1, uncorrelated with each other), and compute

x=Lz.x = Lz .

In words: multiply your plain independent noise by the recipe matrix LL, and the output xx has exactly covariance Σ\Sigma. Why? Because Cov(x)=Cov(Lz)=LCov(z)L=LIL=LL=Σ\text{Cov}(x) = \text{Cov}(Lz) = L\,\text{Cov}(z)\,L^\top = L I L^\top = LL^\top = \Sigma — the identity matrix II is the covariance of independent unit-variance noise, and it drops out of the middle.

The entries of LL are computed one at a time, top-left to bottom-right, each one from entries already found:

Lii=Σiik<iLik2,Lji=1Lii(Σjik<iLjkLik) for j>i.L_{ii} = \sqrt{\Sigma_{ii} - \sum_{k<i}L_{ik}^2}, \qquad L_{ji} = \frac{1}{L_{ii}}\left(\Sigma_{ji} - \sum_{k<i}L_{jk}L_{ik}\right) \text{ for } j>i .

In words: the diagonal entry is "how much new variance this variable has, after subtracting what's already explained by earlier variables" — under a square root, which is exactly why Σ\Sigma must be positive definite: a negative number under that square root means the matrix wasn't a legitimate covariance matrix at all.

Matrix explorer
dashed = before · solid = after
det 1.25trace 2.50λ 1.81, 0.69area scales by 1.25×

Set the transform to a strong shear (an asymmetric stretch, not a pure rotation) and watch the unit circle become a tilted ellipse. That tilt is correlation: a lower-triangular LL applied to independent circular noise produces exactly this kind of tilted, elongated cloud — the shape encodes both the variances (axis lengths) and the correlation (tilt angle).

L11 L21 L22 L31 L32 L33 variable 1 variable 3 uses variables 1 and 2, never the reverse
L is lower-triangular: row 1 depends only on variable 1, row 2 mixes in variable 1 to build variable 2's correlated piece, row 3 mixes in both. Nothing below a row ever feeds back into a row above it.

Worked example 1: two correlated assets, entirely by hand

Two assets with variances σ12=0.04\sigma_1^2 = 0.04 (20% vol) and σ22=0.09\sigma_2^2=0.09 (30% vol) and correlation ρ=0.5\rho=0.5, so Cov=ρσ1σ2=0.5(0.2)(0.3)=0.03\text{Cov} = \rho\sigma_1\sigma_2 = 0.5(0.2)(0.3)=0.03. The covariance matrix is Σ=(0.040.030.030.09)\Sigma = \begin{pmatrix}0.04 & 0.03\\0.03&0.09\end{pmatrix}.

Step 1, first diagonal: L11=0.04=0.20L_{11}=\sqrt{0.04}=0.20.

Step 2, below it: L21=Σ21/L11=0.03/0.20=0.15L_{21} = \Sigma_{21}/L_{11} = 0.03/0.20 = 0.15.

Step 3, second diagonal: L22=Σ22L212=0.090.0225=0.0675=0.2598L_{22} = \sqrt{\Sigma_{22} - L_{21}^2} = \sqrt{0.09 - 0.0225} = \sqrt{0.0675} = 0.2598.

So L=(0.2000.150.2598)L = \begin{pmatrix}0.20 & 0\\0.15 & 0.2598\end{pmatrix}. Check: LL=(0.040.030.030.0225+0.0675)=(0.040.030.030.09)LL^\top = \begin{pmatrix}0.04 & 0.03\\0.03 & 0.0225+0.0675\end{pmatrix} = \begin{pmatrix}0.04&0.03\\0.03&0.09\end{pmatrix} — matches Σ\Sigma exactly.

Now generate one correlated draw from independent standard normals z=(z1,z2)=(1.0,0.5)z=(z_1,z_2)=(1.0, -0.5) (picked for round arithmetic): x1=L11z1=0.20(1.0)=0.20x_1 = L_{11}z_1 = 0.20(1.0)=0.20; x2=L21z1+L22z2=0.15(1.0)+0.2598(0.5)=0.150.1299=0.0201x_2 = L_{21}z_1 + L_{22}z_2 = 0.15(1.0)+0.2598(-0.5) = 0.15-0.1299=0.0201. Notice asset 2's draw is built partly from z1z_1 (the shared piece, delivering correlation) and partly from its own independent z2z_2 (the leftover, idiosyncratic piece) — that split is the whole mechanism.

Worked example 2: pricing a spread option via simulation, one path

You want to Monte-Carlo price a spread option paying max(S1S2K,0)\max(S_1-S_2-K,0) where S1,S2S_1,S_2 have the Σ\Sigma above, current levels 100 and 100, and K=5K=5. Using the correlated draw above as one day's log-return shock scaled by 1/252\sqrt{1/252}: daily shocks are x1/252=0.0126x_1/\sqrt{252}=0.0126 and x2/252=0.00127x_2/\sqrt{252}=0.00127, giving S1100(1.0126)=101.26S_1 \approx 100(1.0126) = 101.26 and S2100(1.00127)=100.13S_2\approx 100(1.00127)=100.13. The spread is 101.26100.13=1.13101.26-100.13=1.13, below the 55 strike, so this single path pays 00. A real pricer repeats this thousands of times, averages the payoffs, and discounts — but every single path starts from exactly this Cholesky step.

What this means in practice

  • It's the engine behind every correlated Monte Carlo simulation — risk factor scenarios, VaR simulation, multi-asset option pricing all lean on Σ=LL\Sigma = LL^\top.
  • It's a fast, reliable way to test if a matrix is a valid covariance matrix. If Cholesky fails (a negative number appears under a square root), Σ\Sigma isn't positive definite — a real problem when covariance matrices are built from noisy, incomplete, or mismatched data.
  • It's cheaper than eigen-decomposition. Where the spectral theorem gives a decomposition useful for understanding structure (principal directions), Cholesky is the workhorse for computation — roughly n3/3n^3/3 operations versus a more expensive full eigendecomposition.

The Cholesky decomposition Σ=LL\Sigma=LL^\top is a triangular "square root" for covariance matrices. Multiplying independent standard-normal noise by LL produces draws with exactly the target covariance — it is the standard bridge from "my computer can only generate independent randomness" to "I need correlated randomness."

The classic confusion is assuming Cholesky works on any symmetric matrix. It only works on ones that are positive definite — every eigenvalue strictly positive, equivalently every possible portfolio has strictly positive variance. Correlation matrices estimated from limited historical data, or stitched together from different data sources, frequently fail this test (they come out only positive semi-definite, or not even that, once you have more assets than usable data points). Feeding such a matrix to Cholesky either crashes with a negative-square-root error or, worse, silently returns garbage in permissive implementations — always check positive-definiteness (or apply a fix like eigenvalue clipping) before decomposing an estimated covariance matrix.

Related concepts

Practice in interviews

Further reading

  • Glasserman, Monte Carlo Methods in Financial Engineering (ch. 2)
  • Golub & Van Loan, Matrix Computations (ch. 4)
ShareTwitterLinkedIn