Chapter 16 — Portfolio Credit Derivatives
"The Gaussian copula priced CDOs until it didn't, then it priced the crisis."
After this chapter you will be able to:
- Explain how CDO tranche structures distribute credit losses and why correlation determines tranche pricing
- Implement the one-factor Gaussian copula and derive conditional default probabilities
- Price CDO tranches using semi-analytic Gauss-Hermite quadrature or Monte Carlo
- Use the Vasicek large-portfolio approximation to derive closed-form VaR and ES for homogeneous pools
- Explain the fundamental mathematical flaw of the Gaussian copula — zero tail dependence — and contrast it with the Student's t copula
- Describe the 2006–2008 CDO market collapse in terms of model assumptions that failed
In 2000, David X. Li published a paper in the Journal of Fixed Income titled "On Default Correlation: A Copula Function Approach." It was elegantly simple: model the joint distribution of default times using a Gaussian copula, reducing the complex problem of correlated defaults to a single correlation parameter $\rho$. By 2004, his formula was the undisputed standard for pricing collateralised debt obligations (CDOs). By 2008, it had contributed to the largest financial crisis since 1929.
CDOs are instruments that pool hundreds of mortgages, corporate bonds, or other credit obligations and issue tranches of debt against the pool, ranked by seniority. The equity tranche absorbs the first 3% of losses — risky, high-yielding, usually retained by the originator. The senior tranche absorbs only losses above 10% — very safe, or so the models said. For the senior tranches to be truly safe, defaults across the underlying pool had to be largely independent. The Gaussian copula said they were, given a calibrated $\rho$ around 0.3.
The flaw was subtle but catastrophic. Mortgage defaults are not independent of each other in the way corporate bonds are. They share a common factor — nationwide house prices — that the calibrated $\rho$ in normal market conditions dramatically underestimated. When US house prices fell simultaneously across all 50 states in 2006–2007, the actual correlation among mortgage defaults was near 1.0. The senior tranches, rated AAA by agencies who relied on the same model, experienced losses that the models had assigned a probability of roughly one in a billion.
This chapter does not retreat from the Gaussian copula. Instead, it presents the model honestly: as a tractable pricing tool with a known failure mode that practitioners must understand. We build the full copula infrastructure, price CDO tranches analytically using Gauss-Hermite quadrature, derive the Vasicek large-portfolio approximation for VaR and ES, and discuss what the correlation parameter means and when it breaks down.
16.1 CDO Mechanics: How Tranches Work
Before the mathematics, a concrete example helps. Consider a pool of 100 bonds, each with $10M face value and $2%$ annual default probability, giving a pool notional of $1 billion. The expected annual loss on the pool is $1B \times 2% \times (1 - 40%) = $12M$ (assuming 40% recovery). Standard CDO tranches might be:
| Tranche | Attach | Detach | Tranche Size | Typical Spread (2006) |
|---|---|---|---|---|
| Equity | 0% | 3% | $30M | 500+ bp |
| Mezzanine A | 3% | 6% | $30M | ~250 bp |
| Mezzanine B | 6% | 9% | $30M | ~100 bp |
| Senior | 9% | 12% | $30M | ~30 bp |
| Super-Senior | 12% | 100% | $880M | ~5 bp |
How losses flow through tranches: Losses accumulate at the pool level. The equity tranche holder absorbs the first $30M of pool losses (0–3%). When cumulative losses reach $30M, the equity tranche is completely wiped out and mezzanine A begins absorbing losses. This sequential structure (the "waterfall") means that the equity tranche has high default probability but low duration loss on each default, while the super-senior tranche has very low default probability but represents the largest piece of capital.
Numerical example: Suppose 10 bonds default simultaneously (10% of the pool) with 40% recovery. Total loss = $10 \times $10M \times 60% = $60M$. The equity tranche ($30M) is completely wiped out. The mezzanine A tranche (\$30M) is also completely wiped out. The mezzanine B tranche absorbs the remaining \$0M (since \$60M = \$30M + \$30M exactly). If 12 bonds default instead, the mezzanine B tranche loses \$12M (40% of its \$30M). The senior and super-senior tranches are unharmed in both cases.
The correlation dependency: Whether the senior tranches are safe depends entirely on whether defaults cluster. Under independent defaults (ρ=0), 10 or more simultaneous defaults out of 100 is extremely rare — the binomial probability with p=2% is approximately $10^{-12}$. With correlation ρ=0.3, the same event has probability roughly 1–2%. With ρ=0.7 (the correlation that materialised in the US mortgage crisis), it is a near-certainty in a downturn. This is why the entire CDO market was disrupted by a change in one parameter.
16.2 Portfolio Credit Risk Fundamentals
In a portfolio of $n$ credits, default correlation drives the distribution of losses. With independent defaults:
$$L = \sum_{i=1}^n (1-R_i) \cdot N_i \cdot \mathbf{1}_{\tau_i \leq T}$$
$$E[L] = \sum_{i=1}^n (1-R_i) N_i p_i, \quad \text{Var}(L) = \sum_{i=1}^n (1-R_i)^2 N_i^2 p_i(1-p_i)$$
With correlated defaults, the variance increases and the tail loss distribution fattens.
module Portfolio_credit = struct
type name = {
notional : float;
pd : float; (* marginal default probability to maturity *)
recovery : float;
hazard_rate : float;
}
let expected_loss name = name.notional *. (1.0 -. name.recovery) *. name.pd
let lgd name = name.notional *. (1.0 -. name.recovery)
(** Independent Monte Carlo loss distribution *)
let loss_distribution ~names ~n_paths () =
let n = Array.length names in
let losses = Array.init n_paths (fun _ ->
Array.fold_left (fun total name ->
if Random.float 1.0 < name.pd then total +. lgd name
else total
) 0.0 names
) in
Array.sort compare losses;
losses
(** Expected loss of a tranche [attach, detach] of total loss distribution *)
let tranche_el ~loss_dist ~attach ~detach ~total_notional =
let n = float_of_int (Array.length loss_dist) in
let el = ref 0.0 in
Array.iter (fun l ->
let lp = l /. total_notional in (* loss as fraction of pool *)
let tranche_loss = Float.min detach (Float.max 0.0 lp -. attach) in
el := !el +. tranche_loss
) loss_dist;
!el /. n
end
16.2 The Gaussian Copula Model
Li's insight was to decouple the marginal default probabilities (which can be extracted from CDS spreads, as in Chapter 15) from the joint default structure. A copula is a multivariate distribution function that, given any set of marginal distributions, specifies how to combine them into a joint distribution with a prescribed correlation structure.
For credit, the construction works as follows. Each obligor $i$ has a default time $\tau_i$ with a known survival probability $S_i(t) = P(\tau_i > t)$ derived from market CDS spreads. Map this to a uniform random variable $u_i = 1 - S_i(\tau_i)$ (the probability integral transform). Then map $u_i$ to a standard normal $x_i = \Phi^{-1}(u_i)$. In the one-factor Gaussian copula, the latent variable $x_i$ is written as a linear combination of a common factor $M \sim N(0,1)$ and an idiosyncratic factor $Z_i \sim N(0,1)$:
$$\tau_i = -\frac{\ln U_i}{\lambda_i}, \quad U_i = \Phi(V_i)$$
$$V_i = \sqrt{\rho} \cdot M + \sqrt{1-\rho} \cdot Z_i, \quad M, Z_i \overset{iid}{\sim} N(0,1)$$
where $M$ is a common market factor and $Z_i$ are idiosyncratic.
Figure 16.2 — Gaussian Copula default distribution across four correlation $\rho$ levels. As correlation increases, the probability of extreme tail losses (simultaneous defaults) grows dramatically, while the probability of zero defaults also increases.
module Gaussian_copula = struct
(** One-factor Gaussian copula loss distribution *)
let loss_distribution_gc ~names ~correlation ~n_paths ~n_market =
let n = Array.length names in
let rho = sqrt correlation in
let irho = sqrt (1.0 -. correlation) in
let losses = Array.init n_paths (fun _ ->
let m = Mc.std_normal () in
Array.fold_left (fun total name ->
let z = Mc.std_normal () in
let v = rho *. m +. irho *. z in
(* Default threshold: Φ^{-1}(PD) *)
let thresh = Numerics.norm_ppf name.pd in
if v < thresh then total +. lgd name
else total
) 0.0 names
) in
ignore n_market; (* n_market integration points for semi-analytic *)
ignore n;
Array.sort compare losses;
losses
(** Semi-analytic: integrate over market factor M *)
let conditional_default_prob ~pd ~correlation ~m =
let rho = sqrt correlation in
let irho = sqrt (1.0 -. correlation) in
Numerics.norm_cdf ((Numerics.norm_ppf pd -. rho *. m) /. irho)
(** Semi-analytic tranche pricing: Gauss-Hermite quadrature over M *)
let tranche_el_semianalytic ~names ~correlation ~attach ~detach ~n_gauss_points =
let total_n = Array.fold_left (fun a name -> a +. lgd name) 0.0 names in
(* Gauss-Hermite nodes and weights (n=20) — use tables *)
let nodes, weights = Numerics.gauss_hermite_20 () in
let result = ref 0.0 in
for k = 0 to n_gauss_points - 1 do
let m = nodes.(k) *. sqrt 2.0 in
let w = weights.(k) /. sqrt Float.pi in
(* Conditional loss distribution given M: use recursive convolution *)
let cond_pds = Array.map (fun name ->
conditional_default_prob ~pd:name.pd ~correlation ~m
) names in
(* For large homogeneous pools, use Vasicek large pool approximation *)
let el_cond = Array.fold_left2 (fun acc name_lgd cpd ->
acc +. name_lgd *. cpd
) 0.0 (Array.map lgd names) cond_pds in
let lp = el_cond /. total_n in
let tranche = Float.min detach (Float.max 0.0 lp -. attach) in
result := !result +. w *. tranche
done;
ignore n_gauss_points;
!result
and lgd name = Portfolio_credit.lgd name
end
16.3 Vasicek Large Portfolio Approximation
For a homogeneous large portfolio, the conditional loss fraction converges to:
$$\ell(M) = \Phi\left(\frac{\Phi^{-1}(p) - \sqrt{\rho} M}{\sqrt{1-\rho}}\right)$$
The unconditional loss distribution is:
$$F(x) = \Phi\left(\frac{\sqrt{1-\rho} \Phi^{-1}(x) - \Phi^{-1}(p)}{\sqrt{\rho}}\right)$$
module Vasicek_portfolio = struct
(** CDF of loss fraction for large homogeneous portfolio *)
let loss_cdf ~pd ~correlation ~x =
if x <= 0.0 then 0.0
else if x >= 1.0 then 1.0
else
let rho = sqrt correlation in
let irho = sqrt (1.0 -. correlation) in
let _ = rho in
Numerics.norm_cdf (
(irho *. Numerics.norm_ppf x -. Numerics.norm_ppf pd)
/. sqrt correlation
)
(** Value at Risk at confidence level alpha *)
let var ~pd ~correlation ~lgd_avg ~alpha =
let x = Numerics.norm_cdf (
(Numerics.norm_ppf pd +. sqrt correlation *. Numerics.norm_ppf alpha)
/. sqrt (1.0 -. correlation)
) in
lgd_avg *. x
(** Expected Shortfall at confidence level alpha *)
let es ~pd ~correlation ~lgd_avg ~alpha =
let n = 1000 in
let sum = ref 0.0 in
for i = 0 to n - 1 do
let u = alpha +. (1.0 -. alpha) *. float_of_int i /. float_of_int n in
let v = var ~pd ~correlation ~lgd_avg ~alpha:u in
sum := !sum +. v
done;
!sum /. float_of_int n
end
16.4 CDO Pricing
A Collateralised Debt Obligation (CDO) slices the portfolio loss into tranches:
| Tranche | Attach | Detach | Nature |
|---|---|---|---|
| Equity | 0% | 3% | First-loss, highest spread |
| Mezzanine | 3% | 7% | Intermediate |
| Senior | 7% | 15% | Near-AAA |
| Super-senior | 15% | 100% | Safest |
Figure 16.1 — CDO portfolio loss distribution, highlighting how losses detach progressively through equity, mezzanine, and senior tranches.
module Cdo = struct
type tranche = {
attach : float; (* as fraction of total pool *)
detach : float;
spread_bps : float; (* fair spread in basis points *)
notional : float;
}
(** Compute fair spread for a tranche *)
let fair_spread ~loss_dist ~total_notional ~tranche ~discount_curve ~payment_times =
let n = float_of_int (Array.length loss_dist) in
(* Expected notional of tranche at each payment time
For simplicity, assume loss distribution is marginal at maturity *)
let tranche_size = (tranche.detach -. tranche.attach) *. total_notional in
(* Protection leg: expected tranche loss *)
let prot_el = Array.fold_left (fun acc l ->
let lp = l /. total_notional in
let tranche_loss = (Float.min tranche.detach lp -. Float.min tranche.attach lp) in
acc +. tranche_loss
) 0.0 loss_dist /. n in
let df_avg = List.fold_left (fun a t ->
a +. Interpolation.discount_factor discount_curve t
) 0.0 payment_times /. float_of_int (List.length payment_times) in
let prot_pv = prot_el *. total_notional *. df_avg in
(* Fee leg: spread on expected surviving tranche notional *)
let dt = (List.nth payment_times (List.length payment_times - 1))
/. float_of_int (List.length payment_times) in
let fee_1 = (1.0 -. prot_el) *. df_avg *. dt in
ignore tranche_size;
if fee_1 < 1e-10 then None
else Some (prot_pv /. (fee_1 *. total_notional) *. 10000.0) (* in bps *)
end
16.5 The Gaussian Copula's Fatal Flaw and the Student's t Alternative
The Gaussian copula has a fundamental mathematical property that makes it unsuitable for tail-loss estimation: zero tail dependence. Sklar's theorem tells us that any joint distribution can be decomposed into its marginals and a copula. The tail dependence coefficient $\lambda_U$ of a copula is defined as:
$$\lambda_U = \lim_{u \to 1^-} P(U_1 > u \mid U_2 > u)$$
This measures the probability that both variables are simultaneously extreme, conditional on one being extreme. For the Gaussian copula with correlation $\rho < 1$, it can be shown that $\lambda_U = 0$ for all finite $\rho$. Even with $\rho = 0.99$, the probability that Asset A defaults given that Asset B defaults in the extreme tail is zero in the Gaussian copula model.
This is not a calibration problem — it is a structural feature of the Gaussian distribution. The elliptical shape of the Gaussian contours means that as you move toward extreme events, the marginal conditional probability goes to zero faster than the event itself. In plain English: the Gaussian copula always says "given that one name is in extreme distress, the probability of another being simultaneously in extreme distress is negligible." For housing markets sharing a common factor, this was catastrophically wrong.
The Student's t copula has positive upper tail dependence:
$$\lambda_U = 2\cdot t_{\nu+1}!\left(-\sqrt{\nu+1}\sqrt{\frac{1-\rho}{1+\rho}}\right)$$
where $\nu$ is the degrees of freedom. For $\nu = 5, \rho = 0.3$: $\lambda_U \approx 0.14$ — a 14% probability that another asset is in the extreme right tail given the first is there. For $\nu = 5, \rho = 0.7$: $\lambda_U \approx 0.39$. This positive tail dependence means that the Student's t copula generates correlated extreme events at a frequency the Gaussian copula cannot replicate even at much higher implied correlations.
In practice, many practitioners used the Gaussian copula but with a "base correlation" approach: instead of a single flat $\rho$, they calibrated different $\rho$ values for each tranche (equity $\rho \approx 0.10$, senior $\rho \approx 0.50$). This pragmatic fix produced a volatility smile on the correlation surface — analogous to the implied vol smile in equity options — but did not resolve the underlying model inconsistency.
16.6 The 2006–2008 CDO Crisis: A Postmortem
The CDO crisis was not only a modelling failure. Several compounding factors contributed:
1. Feedback through ratings agencies: Rating agencies (Moody's, S&P, Fitch) used Gaussian copula models very similar to the market's standard. CDO tranches were rated as if their loss distributions were independent. Between 2003 and 2007, Moody's rated over $100 billion of CDO tranches as AAA. The circular dependency — banks structure CDOs to achieve AAA ratings from models that underestimate correlation risk — created a massive, hidden accumulation of tail risk.
2. MBS collateral correlations: Many CDOs held tranches of mortgage-backed securities (MBS) as collateral, not individual mortgages. This created "CDO-squared" structures where the underlying correlation was far higher than for a diversified corporate bond pool. The Gaussian copula parameters calibrated on corporate credit data were then applied to MBS-backed structures with fundamentally different correlation dynamics.
3. Originate-to-distribute model: Mortgage originators had no incentive to underwrite carefully because they could securitise and sell the risk immediately. Underwriting standards deteriorated systematically and silently. The "independent default" model could not be worse-calibrated for instruments where the originating process had introduced systematic correlated quality deterioration.
4. ABX index collapse: The ABX-HE index (a CDS index on subprime MBS) began declining in early 2007. By July 2007 the ABX 07-1 BBB- tranche had lost 50% of its value. This was the market's first coherent signal of systemic distress. Mark-to-model accounting initially obscured these losses; when mark-to-market was forced, banks were revealed to have enormous undisclosed losses.
The lesson for model users: any model calibrated in a benign part of the credit cycle will underestimate risk in a stressed part. This is not unique to the copula — it applies to every model that uses historical data. The appropriate response is stress testing with correlation assumptions well above the historically calibrated values, maintaining capital buffers for model uncertainty, and being extremely cautious about the credit cycle when structuring instruments that depend on tail dependence.
16.7 Chapter Summary
Portfolio credit risk is fundamentally different from single-name credit risk: the critical variable is not individual default probabilities but default correlation. Two portfolios with identical expected losses can have radically different risk profiles depending on whether defaults are independent (many small losses) or correlated (rare catastrophic losses). The Gaussian copula model, for all its flaws, provides the only analytically tractable framework that links marginal default probabilities (observable from market CDS spreads) to joint default distributions via a single correlation parameter.
The one-factor structure is key to tractability. By conditioning on the common market factor $M$, individual defaults become independent, and the conditional loss distribution can be computed analytically. Integrating over $M$ — using Gauss-Hermite quadrature — gives the unconditional loss distribution without simulation. This semi-analytic approach is far faster and smoother than Monte Carlo, which is why it dominated industry practice for CDO pricing.
The Vasicek large-portfolio approximation takes the analytics one step further: for homogeneous pools, the conditional default fraction converges to a deterministic function of $M$, giving a closed-form formula for the entire loss distribution. This is the basis for regulatory VaR formulas in Basel II and III, which compute capital requirements using the same one-factor structure.
The 2008 crisis was not a failure of the copula's mathematics — the formula is correct given its inputs. It was a failure of calibration and assumption: the correlation parameters estimated from CDS spread levels in a rising housing market dramatically underestimated the tail dependence structure in a falling one. Any model of complex instruments should be stress-tested not just by bumping its parameters but by questioning whether its functional form can capture the risk that actually materialises.
Exercises
16.1 [Basic] Simulate the loss distribution for a 100-name homogeneous pool ($p=2%$, $\rho=25%$, equal notionals) and compare to the Vasicek analytic CDF. What is the 99.9% VaR as a percentage of pool notional?
16.2 [Basic] Plot tranche breakeven spreads (equity, mezz, senior) as a function of correlation $\rho \in [0, 0.7]$. Observe the "correlation smile": equity spread decreases with $\rho$ (correlation reduces expected equity loss), while senior spread increases. Explain the economic intuition.
16.3 [Intermediate] Implement the CDO waterfall example from §16.1 numerically: simulate 10,000 scenarios of portfolio losses. For each scenario, compute losses to each tranche and verify that the waterfall correctly exhausts losses starting from the equity tranche.
16.4 [Intermediate] Implement the recursive algorithm for exact conditional loss distribution of a heterogeneous portfolio (no large-pool approximation) and use it in semi-analytic CDO pricing. Compare to Monte Carlo for a 20-name pool.
16.5 [Advanced] Compare Gaussian vs Student's t copula: implement the Student's t one-factor copula and show that for $\nu = 5, \rho = 0.3$, the senior tranche (12–15%) has substantially higher expected loss than under the Gaussian copula. Quantify the "tail underestimation" of the Gaussian.
16.6 [Advanced] Stress test: start with the 100-name pool calibrated to $\rho = 0.25$ and compute super-senior spread (12–100%). Then shock the correlation to $\rho = 0.70$ and $\rho = 0.90$ (replicating a housing crisis correlation regime). By how much does the super-senior expected loss increase? What does this imply about the safety of AAA-rated CDO tranches?