Credit Ratings & Spreads Reference
How creditworthiness is measured, how it translates into yield spreads, and how the three fixed-income universes used in this toolkit — Treasuries, corporate bonds, and private credit — compare.
Credit Ratings
A credit rating is an opinion on the likelihood that a borrower will meet its debt obligations. The two major scales are:
| Quality tier | S&P / Fitch | Moody's | This toolkit |
|---|---|---|---|
| Highest quality | AAA | Aaa | AAA |
| High quality | AA+/AA/AA− | Aa1/Aa2/Aa3 | AA |
| Upper medium | A+/A/A− | A1/A2/A3 | A |
| Medium | BBB+/BBB/BBB− | Baa1/Baa2/Baa3 | BBB |
| Speculative | BB+/BB/BB− | Ba1/Ba2/Ba3 | BB |
| Highly speculative | B+/B/B− | B1/B2/B3 | B |
Everything BBB / Baa3 and above is investment grade (IG). Everything below is high yield (HY), sometimes called "junk."
The toolkit collapses the notch-level detail (e.g. AA+, AA, AA−) into a single letter grade for simplicity.
Credit Spread
What it measures: The extra yield an investor demands over the risk-free rate to compensate for credit risk (and, in some markets, liquidity risk).
Spreads are quoted in basis points (bps), where 1 bp = 0.01%.
Key drivers of spread width:
| Factor | Effect |
|---|---|
| Lower credit rating | Wider spread |
| Longer maturity | Wider spread (more time for default) |
| Economic stress | Wider spreads across all ratings |
| Illiquidity | Wider spread (private markets) |
The Spread Curve
Spreads vary by both rating and maturity. The toolkit stores a full
term structure in assumptions/credit_spreads.csv (values in bps):
| Rating | 1Y | 2Y | 3Y | 5Y | 7Y | 10Y | 20Y | 30Y |
|---|---|---|---|---|---|---|---|---|
| AAA | 23 | 35 | 46 | 70 | 93 | 116 | 139 | 151 |
| AA | 22 | 32 | 42 | 63 | 82 | 100 | 120 | 131 |
| A | 18 | 27 | 36 | 52 | 64 | 76 | 91 | 97 |
| BBB | 48 | 68 | 87 | 119 | 143 | 167 | 207 | 223 |
| BB | 106 | 141 | 177 | 226 | 262 | 297 | 354 | 375 |
| B | 212 | 264 | 312 | 374 | 418 | 460 | 531 | 552 |
When a bond's maturity falls between table tenors, get_spread()
linearly interpolates.
Code: get_spread() and get_credit_spreads() in src/alm/read.py
Updating Spreads from Market Data
The spread table can be refreshed from four FRED series that anchor the 10-year point for specific ratings:
| Rating | FRED anchor | Series ID | Description |
|---|---|---|---|
| AAA | AAA10Y | AAA10Y | Moody's Aaa yield − 10Y Treasury |
| A | IG_OAS | BAMLC0A0CM | ICE BofA US Corporate IG OAS |
| BBB | BAA10Y | BAA10Y | Moody's Baa yield − 10Y Treasury |
| BB | HY_OAS | BAMLH0A0HYM2 | ICE BofA US High Yield OAS |
The update algorithm:
- Fetch the latest 10Y anchor spread for AAA, A, BBB, BB from FRED
- Compute a scale factor for each:
new_10Y / old_10Y - Multiply the entire tenor curve for that rating by the scale factor
- AA is interpolated between AAA and A, preserving its original relative position between the two
- B is extrapolated from BB, preserving the original BB-to-B ratio at each tenor
- Round to whole basis points and write back to CSV
Code: update_credit_spreads() in src/alm/read.py
Comparing the Three Asset Classes
The toolkit models three fixed-income universes with distinct risk and return characteristics:
Treasuries (Government Bonds)
| Attribute | Detail |
|---|---|
| Issuer | U.S. government (sovereign) |
| Credit risk | Effectively zero (AAA / AA rated) |
| Liquidity | Highest — deep, transparent markets |
| Spread over risk-free | Minimal (the Treasury is the risk-free benchmark) |
| Typical ratings in toolkit | 70% AAA, 30% AA |
| Role in portfolio | Duration anchor, safe-haven allocation |
Treasuries define the risk-free yield curve. In this toolkit, the "discount rate" generally represents a Treasury-level rate, and all other instruments earn a spread above it.
Corporate Bonds
| Attribute | Detail |
|---|---|
| Issuer | Corporations (public companies) |
| Credit risk | Moderate — depends on rating |
| Liquidity | Good for IG; lower for HY |
| Spread over risk-free | 50–550+ bps depending on rating and maturity |
| Typical ratings in toolkit | 30% A, 50% BBB, 15% BB, 5% B |
| Role in portfolio | Yield enhancement, diversification |
Corporate bonds are the largest source of credit spread income in a typical insurance portfolio. The toolkit tilts toward BBB — the sweet spot at the bottom of investment grade, where spreads are meaningfully wider than A-rated debt but default risk remains relatively contained.
Private Credit
| Attribute | Detail |
|---|---|
| Issuer | Middle-market companies, project finance, etc. |
| Credit risk | Higher — typically BB / B rated |
| Liquidity | Very low — no secondary market |
| Spread over risk-free | Wide: credit spread + illiquidity premium + other |
| Typical ratings in toolkit | 40% BB, 60% B |
| Role in portfolio | Yield pickup, illiquidity premium capture |
| Regulatory cap | 10% of portfolio (SAA constraint) |
Private credit earns the widest total yield because it compensates for both credit risk and illiquidity. The toolkit decomposes the total yield into four components:
| Component | Toolkit default | Source |
|---|---|---|
| Risk-free rate | Varies (discount rate) | Treasury curve |
| Credit spread | Varies by rating / maturity | assumptions/credit_spreads.csv |
| Illiquidity spread | 200 bps (hardcoded) | Industry estimate |
| Other spread | 50 bps (hardcoded) | Catch-all (complexity, structuring) |
Valuation note: The PrivateCredit class discounts at the
risk-free rate by default (not the total yield). This means the PV
exceeds par — the excess represents the economic value of the
illiquidity premium to a buy-and-hold investor like an insurer.
Code: PrivateCredit in src/alm/asset.py, PC_RATING_DIST in src/alm/core.py
Side-by-Side Summary
| Treasury | Corporate | Private Credit | |
|---|---|---|---|
| Credit quality | AAA / AA | A to B | BB / B |
| 10Y spread (bps) | ~0 | 76–460 | 297–460 + 250 illiq/other |
| Liquidity | Excellent | Good (IG) / Fair (HY) | Poor |
| Valuation method | Discount at yield | Discount at yield | Discount at risk-free rate |
| Duration behavior | Standard | Standard | Standard (bullet-like) |
| SAA weight (default) | 40% | 30% | 10% |
| Maturities (default) | 5, 10, 20, 30Y | 5, 10, 20, 30Y | 3, 5Y |
Rating Distributions
Each asset class in the toolkit has a hardcoded rating distribution used when generating block-level portfolios:
Government bonds (GOVT_RATING_DIST):
| Rating | Weight |
|---|---|
| AAA | 70% |
| AA | 30% |
Corporate bonds (CORP_RATING_DIST):
| Rating | Weight |
|---|---|
| A | 30% |
| BBB | 50% |
| BB | 15% |
| B | 5% |
Private credit (PC_RATING_DIST):
| Rating | Weight |
|---|---|
| BB | 40% |
| B | 60% |
Code: GOVT_RATING_DIST, CORP_RATING_DIST, PC_RATING_DIST in src/alm/core.py