A Monte Carlo engine that simulates losses across the capital structure of a Collateralized Loan Obligation (CLO) — from a synthetic leveraged-loan pool, through a quarterly cashflow waterfall with reinvestment and amortization periods, to correlated-default simulation under both Gaussian and t-copulas, and finally to tranche expected loss and implied ratings.
This reproduces, end-to-end, the core analytical workflow a rating agency (Fitch / Moody's / S&P) performs when it rates a CLO — and adds the two pieces that most distinguish a toy model from a realistic one: the time structure of a real deal and model risk from the choice of copula.
v1 → v2. v1 was an annual, single-copula reference implementation. v2 adds (1) quarterly cashflows with explicit reinvestment/amortization phases and OC turbo, and (2) a Gaussian-vs-t-copula comparison to quantify tail dependence.
Synthetic pool ─► Quarterly waterfall ─► Correlated MC ─────────► EL → Rating
(200 loans) reinvest → amortize Gaussian / t-copula (idealized EL)
+ OC/IC turbo (tail dependence)
- Loan pool — 200 synthetic leveraged loans calibrated to public market statistics (single-B concentration, SOFR+300–375 bps, ~35 industries, top-10 ~65%).
- Quarterly waterfall — 28 quarters (7y). During the reinvestment period (3y) recoveries are reinvested (no senior paydown); in the amortization period principal sequentially delevers the notes. OC/IC tests divert cash to turbo the seniors on breach.
- Correlated defaults — two-factor (systematic + industry) latent variables, quarterly default barriers, beta-distributed recoveries. Switchable Gaussian or t-copula (shared chi-square mixing → tail dependence).
- Rating — tranche expected loss mapped to an implied rating via a Moody's-style idealized-EL framework.
| Tranche | Base EL | 2020-like (×2) | 2008-like (×3) |
|---|---|---|---|
| AAA | 0.00% | 0.00% | 0.01% |
| AA | 0.00% | 0.49% | 7.90% |
| A | 0.06% | 9.70% | 47.29% |
| BBB | 1.24% | 37.13% | 83.48% |
| BB | 8.90% | 72.12% | 96.96% |
| Equity | 68.31% | 97.13% | 99.93% |
AAA expected loss is ~0 across scenarios (0.01% at a 2008-magnitude stress, with zero loss in 99%+ of paths). 36% subordination absorbs crisis-level losses even over a 7-year, reinvesting deal.
During reinvestment the AAA notes are not paid down (flat); only in amortization do they delever. Under stress the collateral erodes faster, thinning the senior cushion from ~34% to ~13% — but it stays positive, so AAA is protected.
Gaussian and t-copula give similar means but the t-copula puts more mass in the joint-default tail. At a 2008-like stress the AA tranche's 99th-percentile loss rises from 86% (Gaussian) to 97% (t-copula, ν=5).
With independent defaults the AA tranche's 99th-percentile loss is ~24%; with realistic correlation it is ~86%. Senior tranches are long correlation — only impaired when defaults cluster, the same structural exposure found in worst-of basket products.
clo_v2/
├── config.py # Parameters: pool, quarterly/reinvest structure, copula, tests
├── loan_pool.py # Synthetic leveraged-loan pool generator
├── waterfall.py # Quarterly waterfall + reinvestment/amortization + OC/IC turbo
├── simulation.py # Gaussian / t-copula Monte Carlo simulator
├── rating_engine.py # Expected loss → implied rating (idealized EL)
├── visualize.py # 7 charts (reads saved results)
├── main.py # End-to-end run; saves results_v2.json, timeline_v2.json
└── figures/ # Generated charts
pip install numpy pandas scipy matplotlib
python main.py # runs all scenarios/variants (~130s), saves JSON results
python visualize.py # builds the 7 figures from saved resultsTech: Python · NumPy · SciPy · pandas · matplotlib
- Why synthetic data? Deal-level CLO data (loan-by-loan composition, tranche trades) is proprietary (Trepp, LSEG, Intex). This project calibrates a synthetic pool to public aggregate statistics — standard for methodology demonstration.
- Reinvestment recycles recoveries into new risk; the reinvested sleeve defaults at a path-conditional (Vasicek) rate tied to the macro factor, so it co-moves with the original pool.
- t-copula uses a shared chi-square mixing variable (ν=5) to induce tail dependence absent from the Gaussian copula.
Documented honestly, because knowing the gap is half the skill:
- Recovery is independent of default (real LGD is procyclical) → add correlated recovery.
- Reinvestment sleeve is modeled at the aggregate (not loan-by-loan) level.
- No explicit reinvestment-eligibility covenants (WARF, diversity, WAS).
- Idealized-EL table is a public approximation; swap in official tables for production.
- Possible extensions: t-copula degrees-of-freedom sensitivity, Clayton copula, equity call/refinancing optionality.




