Securitization Tranche Waterfall: Simulation and Analytic Loss
You have a simplified securitization backed by a pool of $M$ loans, each of equal size (normalized to $\
- Senior tranche: attachment point at $A_S$ (absorbs losses only after mezzanine is wiped out)
- Mezzanine tranche: first-loss piece with thickness $T_M$
Cash flows follow a sequential-pay waterfall: all principal and coupon payments go to the senior tranche first, then the mezzanine. There is an overcollateralization (OC) trigger: if the ratio of remaining pool assets to outstanding senior principal drops below a threshold $\alpha$, all cash flows (including mezzanine coupons) are diverted to the senior tranche until coverage is restored. Coupons are fixed rates $c_S$ (senior) and $c_M$ (mezzanine), paid monthly.
- Write a simulation algorithm (pseudocode or Python) that models the monthly cash flow waterfall over one year, applies the OC trigger logic, and computes the expected IRR for each tranche. Assume defaults occur at the start of each month with monthly default probability $p_m = 1 - (1-p)^{1/12}$.
- Derive an analytic approximation for the expected loss on the senior tranche using a normal approximation to the total portfolio loss $L = \sum_{i=1}^{M}(1-R)\,\mathbf{1}_{\{\text{default}_i\}}$.
Hints
- Think of the waterfall as a priority queue: cash flows to senior first, and the OC trigger is a circuit breaker that redirects mezzanine cash when collateral coverage deteriorates.
- Total portfolio loss is a sum of i.i.d. terms $(1-R) \cdot D_i$, so for large $M$ the CLT gives you a normal approximation. The senior tranche loss is then a call-spread payoff on the portfolio loss distribution.
- For the analytic part, use the identity $E[(X - K)^+] = (\mu - K)\Phi\!\left(\frac{\mu - K}{\sigma}\right) + \sigma\,\phi\!\left(\frac{\mu - K}{\sigma}\right)$ applied at both the mezzanine attachment and senior detachment points.
Worked Solution
How to Think About It: This problem tests two skills interviewers care about in structured products roles: (a) can you translate legal waterfall rules into code, and (b) can you do a quick analytic estimate without simulation? The waterfall is just a priority queue for cash -- senior gets paid first, and the OC trigger is a circuit breaker that protects senior investors when the collateral pool deteriorates. For the analytic part, the key observation is that total portfolio loss is a sum of i.i.d. random variables, so the CLT applies when $M$ is large.
## Part (i): Simulation Algorithm
Algorithm:
Each month, simulate which loans default, compute recoveries, and distribute cash through the waterfall. The OC trigger checks asset coverage before distributing to mezzanine.
Code:
```python import numpy as np from scipy.optimize import brentq
def simulate_waterfall(M, p, R, c_S, c_M, A_S, T_M, alpha, n_sims=10000): """ M: number of loans (each face = 1) p: annual default probability per loan R: recovery rate c_S, c_M: annual coupon rates (senior, mezz) A_S: senior attachment point (fraction of pool) T_M: mezzanine thickness (fraction of pool) alpha: OC trigger threshold """ p_m = 1 - (1 - p) ** (1/12) # monthly default prob senior_face = A_S * M # outstanding senior principal (simplified) mezz_face = T_M * M # But more precisely: senior covers losses above mezz # senior_face = (1 - A_S) * M, mezz_face = T_M * M # Adjust to your convention; here senior_face = pool - mezz attachment senior_size = (1 - A_S) * M mezz_size = T_M * M
senior_cfs = np.zeros((n_sims, 12)) mezz_cfs = np.zeros((n_sims, 12))
for sim in range(n_sims): alive = np.ones(M, dtype=bool) sr_outstanding = senior_size mz_outstanding = mezz_size cum_loss = 0.0
for month in range(12): # Simulate defaults this month defaults = alive & (np.random.rand(M) < p_m) n_def = defaults.sum() alive[defaults] = False loss = n_def * (1 - R) recovery_cf = n_def * R cum_loss += loss
# Allocate losses: mezzanine absorbs first if cum_loss <= mezz_size: mz_outstanding = mezz_size - cum_loss else: mz_outstanding = 0.0 sr_outstanding = senior_size - (cum_loss - mezz_size) sr_outstanding = max(sr_outstanding, 0.0)
# Available cash: coupons from alive loans + recoveries n_alive = alive.sum() # Total pool coupon (simplified: pool pays weighted avg) pool_coupon = n_alive * (c_S + c_M) / (12 * M) # More realistically, available = scheduled payments avail = n_alive / M * (c_S * senior_size + c_M * mezz_size) / 12 avail += recovery_cf
# OC trigger check asset_value = n_alive * 1.0 # surviving loan face oc_ratio = asset_value / sr_outstanding if sr_outstanding > 0 else 999 oc_triggered = oc_ratio < alpha
# Waterfall: senior first always sr_coupon_due = c_S / 12 * sr_outstanding sr_paid = min(avail, sr_coupon_due) avail -= sr_paid senior_cfs[sim, month] = sr_paid
if not oc_triggered and mz_outstanding > 0: mz_coupon_due = c_M / 12 * mz_outstanding mz_paid = min(avail, mz_coupon_due) avail -= mz_paid mezz_cfs[sim, month] = mz_paid else: # OC triggered: divert to senior senior_cfs[sim, month] += avail avail = 0
# Terminal principal repayment (month 12) # Remaining principal returned sr_principal = max(sr_outstanding, 0) mz_principal = max(mz_outstanding, 0) senior_cfs[sim, 11] += sr_principal mezz_cfs[sim, 11] += mz_principal
# Compute expected IRR for each tranche def compute_irr(init_invest, cf_matrix): avg_cf = cf_matrix.mean(axis=0) cfs = np.concatenate([[-init_invest], avg_cf]) try: irr_monthly = brentq( lambda r: sum(c / (1+r)**t for t, c in enumerate(cfs)), -0.5, 5.0 ) return (1 + irr_monthly) ** 12 - 1 except ValueError: return None
sr_irr = compute_irr(senior_size, senior_cfs) mz_irr = compute_irr(mezz_size, mezz_cfs) return sr_irr, mz_irr ```
Key implementation details: - Monthly default probability converts from annual: $p_m = 1 - (1-p)^{1/12}$ - Losses hit mezzanine first; once mezzanine is wiped out, senior absorbs - OC trigger diverts all remaining cash to senior when $\text{pool assets} / \text{senior outstanding} < \alpha$ - IRR is solved via root-finding on the NPV equation over monthly cash flows
Complexity: $O(n_{\text{sims}} \times 12 \times M)$ time, $O(M)$ space per simulation path.
## Part (ii): Analytic Approximation for Expected Senior Loss
Quick Estimate: Take $M = 100$, $p = 0.05$, $R = 0.4$. Expected total loss $= M \cdot p \cdot (1-R) = 100 \times 0.05 \times 0.6 = 3.0$. Standard deviation $= \sqrt{M \cdot p(1-p)} \cdot (1-R) = \sqrt{100 \times 0.0475} \times 0.6 \approx 2.18 \times 0.6 = 1.31$. If the mezzanine absorbs the first 5 units of loss (attachment point $A_S = 0.05$), then senior starts losing when $L > 5$. That is $(5 - 3)/1.31 \approx 1.53$ standard deviations above the mean, so $P(L > 5) \approx 6.3\%$. Expected senior loss is small -- on the order of 0.1-0.2 units. This is exactly how a structurer checks whether the mezzanine cushion is thick enough.
Approach: Model total loss as approximately normal, then compute the expected tranche loss as a call-spread payoff on portfolio loss.
Derivation:
Let $D_i \sim \text{Bernoulli}(p)$ indicate whether loan $i$ defaults. Total portfolio loss:
$L = (1-R) \sum_{i=1}^{M} D_i$
The number of defaults $N = \sum D_i$ has mean $\mu_N = Mp$ and variance $\sigma_N^2 = Mp(1-p)$. So $L$ has:
$\mu_L = M p (1-R), \quad \sigma_L = (1-R)\sqrt{Mp(1-p)}$
By the CLT, for large $M$:
$L \approx \mathcal{N}(\mu_L,\, \sigma_L^2)$
The senior tranche loses money only when total loss exceeds the mezzanine thickness. If the mezzanine absorbs losses up to $K_M = T_M \cdot M$ and the senior has thickness $K_S = (1 - A_S) \cdot M$, then the senior tranche loss is:
$L_S = \min\!\big(\max(L - K_M,\, 0),\, K_S\big)$
This is a call spread on $L$ with strikes $K_M$ and $K_M + K_S$. The expected value is:
$E[L_S] = E[(L - K_M)^+] - E[(L - K_M - K_S)^+]$
For $X \sim \mathcal{N}(\mu, \sigma^2)$, the expected excess over a threshold $K$ is:
$E[(X - K)^+] = (\mu - K)\,\Phi\!\left(\frac{\mu - K}{\sigma}\right) + \sigma\,\phi\!\left(\frac{\mu - K}{\sigma}\right)$
where $\Phi$ is the standard normal CDF and $\phi$ is the standard normal PDF. Define:
$d_1 = \frac{\mu_L - K_M}{\sigma_L}, \quad d_2 = \frac{\mu_L - (K_M + K_S)}{\sigma_L}$
Then:
$E[L_S] = \Big[(\mu_L - K_M)\,\Phi(d_1) + \sigma_L\,\phi(d_1)\Big] - \Big[(\mu_L - K_M - K_S)\,\Phi(d_2) + \sigma_L\,\phi(d_2)\Big]$
The expected senior loss rate (as a fraction of senior tranche size) is $E[L_S] / K_S$.
Practical note: This i.i.d. assumption understates tail risk because real mortgage defaults are correlated (housing downturns hit everyone). The Vasicek/Gaussian copula model adds a single systematic factor to capture this, which fattens the loss tail and increases senior expected loss substantially. In practice, you would calibrate the asset correlation parameter $\rho$ and use the Vasicek distribution instead of the simple normal.
Answer:
Part (i): The simulation loops over months, applies Bernoulli defaults, allocates losses bottom-up (mezzanine first), checks the OC trigger, and distributes cash through the waterfall. IRR is computed via root-finding on average cash flows.
Part (ii): Under the normal approximation, expected senior tranche loss is:
$E[L_S] = \big[(\mu_L - K_M)\Phi(d_1) + \sigma_L \phi(d_1)\big] - \big[(\mu_L - K_M - K_S)\Phi(d_2) + \sigma_L \phi(d_2)\big]$
where $\mu_L = Mp(1-R)$, $\sigma_L = (1-R)\sqrt{Mp(1-p)}$, and $d_1, d_2$ are the standardized distances to the mezzanine attachment and senior detachment points.
Intuition
Securitization is just financial triage -- you take a pool of risky assets and slice the loss distribution into layers. The mezzanine tranche is the first-loss buffer that protects senior investors, and the OC trigger is an early-warning system that diverts cash to senior before things get truly bad. The simulation part of this problem forces you to translate legal waterfall language into code, which is exactly what structurers and quant developers do when pricing new deals.
The analytic part reveals something deeper: under i.i.d. defaults, the CLT turns a messy discrete loss distribution into a tractable Gaussian, and the tranche expected loss becomes a call-spread formula that looks suspiciously like Black-Scholes. This is not a coincidence -- the Vasicek/Gaussian copula model used in practice is essentially this idea with a correlation parameter bolted on. The key limitation to flag in an interview is that real defaults are correlated (housing busts, credit cycles), so the i.i.d. normal approximation underestimates tail risk for senior tranches. That single insight -- correlation drives senior tranche risk -- is what the 2008 crisis made painfully clear.