Structured Credit Products (CDOs and Securitizations) › Worked Example: Analyzing a \$500M CDO

Michael BrenndoerferNovember 19, 20254 min read
Quantitative FinanceAll chapters
Part 4 of 15Swaps and Credit Derivatives
Chapter 23Structured Credit Products (CDOs and Securitizations) › Worked Example: Analyzing a \$500M CDO
Reading section 8 of 12 · Worked Example: Analyzing a \$500M CDO · 4 minSection 8 of 12 · 4 min

Book contents

Section 8 of 12 · 4 min read

Structured Credit Products (CDOs and Securitizations) › Worked Example: Analyzing a \$500M CDOOne section · Sections in this chapter8 / 12 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Let's work through a complete example of a cash CDO backed by 100 corporate loans.

In[29]:
Code
# CDO Parameters
pool_size = 500_000_000  # $500 million
n_loans = 100
loan_size = pool_size / n_loans
avg_default_prob = 0.04  # 4% annual default probability
recovery_rate = 0.40
correlation = 0.25

# Tranche structure
# Defined with explicit attachment/detachment to ensure consistency
cdo_tranches = {
    "Senior": {"coupon": 0.015, "attachment": 0.12, "detachment": 1.00},
    "Mezzanine A": {"coupon": 0.04, "attachment": 0.07, "detachment": 0.12},
    "Mezzanine B": {"coupon": 0.07, "attachment": 0.04, "detachment": 0.07},
    "Equity": {"coupon": 0.0, "attachment": 0.00, "detachment": 0.04},
}

# Calculate notionals
for name, spec in cdo_tranches.items():
    thickness = spec["detachment"] - spec["attachment"]
    spec["notional"] = thickness * pool_size
In[30]:
Code
# Run Monte Carlo simulation for 5-year horizon
n_simulations = 100000
years = 5
cumulative_default_prob = (
    1 - (1 - avg_default_prob) ** years
)  # ~18.5% over 5 years

defaults = simulate_correlated_defaults(
    n_loans, cumulative_default_prob, correlation, n_simulations
)
pool_losses = (defaults / n_loans) * (
    1 - recovery_rate
)  # Loss rate after recovery

# Calculate tranche metrics
tranche_metrics = []
for name, spec in cdo_tranches.items():
    attach = spec["attachment"]
    detach = spec["detachment"]
    thickness = detach - attach

    # Tranche losses
    tranche_loss_rates = np.clip(pool_losses - attach, 0, thickness) / thickness

    # Expected loss
    expected_loss = tranche_loss_rates.mean()

    # Probability of any loss
    prob_any_loss = (tranche_loss_rates > 0).mean()

    # Probability of total loss
    prob_total_loss = (tranche_loss_rates >= 0.999).mean()

    tranche_metrics.append(
        {
            "Tranche": name,
            "Notional ($M)": spec["notional"] / 1e6,
            "Attachment": f"{attach * 100:.0f}%",
            "Detachment": f"{detach * 100:.0f}%",
            "Expected Loss (%)": expected_loss * 100,
            "P(Any Loss)": prob_any_loss,
            "P(Total Loss)": prob_total_loss,
        }
    )

metrics_df = pd.DataFrame(tranche_metrics)
Out[31]:
Console
CDO Tranche Analysis - 5 Year Horizon
================================================================================
Pool Size: $500M | Loans: 100 | Correlation: 0.25
5-Year Default Prob: 18.5% | Recovery: 40%
--------------------------------------------------------------------------------
    Tranche  Notional ($M) Attachment Detachment  Expected Loss (%)  P(Any Loss)  P(Total Loss)
     Senior          440.0        12%       100%              3.471        0.360          0.000
Mezzanine A           25.0         7%        12%             47.829        0.604          0.383
Mezzanine B           15.0         4%         7%             68.445        0.779          0.604
     Equity           20.0         0%         4%             89.172        0.983          0.779

The simulation results quantify the risk segmentation. The Equity tranche, while offering potential upside, faces a high probability of total loss (approx. 60%). In contrast, the Senior tranche remains untouched in the vast majority of scenarios, protected by the subordination of the lower tranches.

Out[32]:
Visualization
Histogram of Senior tranche losses
Senior tranche loss distribution. The overwhelming concentration of outcomes at zero loss demonstrates the high level of structural protection provided by the subordination of junior tranches.
Histogram of Mezzanine A tranche losses
Mezzanine A tranche loss distribution. The distribution spans the full loss range, with substantial probability mass at both zero and total loss under the simulated five-year scenario.
Histogram of Mezzanine B tranche losses
Mezzanine B tranche loss distribution. The results reveal a high likelihood of partial or total loss, indicating limited protection against moderate pool default levels compared to more senior tranches.
Histogram of Equity tranche losses
Equity tranche loss distribution. Most simulated outcomes produce complete principal loss, with smaller probability mass across partial-loss outcomes.