Claude-skill-registry credit-risk
Assess credit risk and default probability for bonds using credit spreads, rating transitions, and recovery analysis. Requires numpy>=1.24.0, pandas>=2.0.0, scipy>=1.10.0. Use when evaluating corporate bonds, analyzing credit events, estimating default probabilities, or managing credit portfolio risk.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/credit-risk" ~/.claude/skills/majiayu000-claude-skill-registry-credit-risk && rm -rf "$T"
skills/data/credit-risk/SKILL.mdCredit Risk Assessment and Rating Analysis Skill Development
Objective
Evaluate and model issuer default risk, downgrade probability, and credit spread behavior using both fundamental analysis and market-implied approaches. Develop systematic frameworks for assessing credit quality and monitoring credit migrations.
Skill Classification
Domain: Fixed Income Credit Analysis Level: Advanced Prerequisites: Bond Pricing, Yield Measures Estimated Time: 20-25 hours
Focus Areas
1. Fundamental vs. Market-Implied Credit Risk
Fundamental Credit Analysis
Approach: Bottom-up analysis of issuer financials and business fundamentals.
Key Metrics:
class CreditMetrics: """Fundamental credit analysis metrics.""" @staticmethod def interest_coverage(ebit, interest_expense): """Times Interest Earned (TIE) ratio.""" return ebit / interest_expense @staticmethod def debt_to_ebitda(total_debt, ebitda): """Leverage ratio.""" return total_debt / ebitda @staticmethod def debt_to_equity(total_debt, total_equity): """Capital structure ratio.""" return total_debt / total_equity @staticmethod def current_ratio(current_assets, current_liabilities): """Liquidity ratio.""" return current_assets / current_liabilities @staticmethod def free_cash_flow_to_debt(fcf, total_debt): """Debt service capacity.""" return fcf / total_debt
Market-Implied Credit Risk
Approach: Extract default probability from market prices.
Credit Spread:
Credit Spread = YTM_Corporate - YTM_Treasury
Implied Default Probability:
def implied_default_probability(credit_spread, recovery_rate, years): """ Calculate market-implied annual default probability. Parameters: ----------- credit_spread : float Yield spread over risk-free rate (decimal) recovery_rate : float Expected recovery in default (decimal, e.g., 0.40 for 40%) years : float Time horizon Returns: -------- float : Implied annual default probability """ loss_given_default = 1 - recovery_rate annual_pd = credit_spread / loss_given_default return annual_pd def cumulative_default_prob(annual_pd, years): """ Calculate cumulative default probability. Returns: -------- float : Probability of default within 'years' horizon """ survival_prob = (1 - annual_pd) ** years return 1 - survival_prob
2. Credit Rating Agencies
Major Rating Agencies:
- Moody's: Aaa to C scale
- S&P: AAA to D scale
- Fitch: AAA to D scale
Rating Categories:
- Investment Grade: BBB-/Baa3 and above
- High Yield (Junk): BB+/Ba1 and below
Rating Equivalence:
RATING_SCALE = { 'Moody\'s': ['Aaa', 'Aa1', 'Aa2', 'Aa3', 'A1', 'A2', 'A3', 'Baa1', 'Baa2', 'Baa3', 'Ba1', 'Ba2', 'Ba3', 'B1', 'B2', 'B3', 'Caa1', 'Caa2', 'Caa3', 'Ca', 'C'], 'S&P': ['AAA', 'AA+', 'AA', 'AA-', 'A+', 'A', 'A-', 'BBB+', 'BBB', 'BBB-', 'BB+', 'BB', 'BB-', 'B+', 'B', 'B-', 'CCC+', 'CCC', 'CCC-', 'CC', 'C', 'D'], 'Fitch': ['AAA', 'AA+', 'AA', 'AA-', 'A+', 'A', 'A-', 'BBB+', 'BBB', 'BBB-', 'BB+', 'BB', 'BB-', 'B+', 'B', 'B-', 'CCC+', 'CCC', 'CCC-', 'CC', 'C', 'D'] } def numerical_rating(rating, agency='S&P'): """Convert letter rating to numerical score (higher = better).""" scale = RATING_SCALE[agency] try: return len(scale) - scale.index(rating) except ValueError: return None def is_investment_grade(rating, agency='S&P'): """Determine if rating is investment grade.""" numeric = numerical_rating(rating, agency) if agency == 'Moody\'s': threshold = numerical_rating('Baa3', agency) else: threshold = numerical_rating('BBB-', agency) return numeric >= threshold if numeric else False
Historical Default Rates by Rating:
# Average 10-year cumulative default rates (%) HISTORICAL_DEFAULT_RATES = { 'AAA': 0.60, 'AA': 1.50, 'A': 2.91, 'BBB': 7.20, 'BB': 19.00, 'B': 35.00, 'CCC': 54.00 }
3. Probability of Default (PD) and Loss Given Default (LGD)
Expected Loss Framework:
Expected Loss = PD × LGD × Exposure at Default
PD Modeling Approaches:
Structural Model (Merton Model)
from scipy.stats import norm def merton_default_probability(firm_value, debt_face_value, volatility, risk_free_rate, time_horizon): """ Calculate default probability using Merton structural model. Based on Black-Scholes option pricing framework. Parameters: ----------- firm_value : float Current market value of firm's assets debt_face_value : float Face value of debt volatility : float Volatility of firm value (annual) risk_free_rate : float Risk-free rate time_horizon : float Time to debt maturity (years) Returns: -------- float : Probability of default """ d2 = (np.log(firm_value / debt_face_value) + (risk_free_rate - 0.5 * volatility**2) * time_horizon) / \ (volatility * np.sqrt(time_horizon)) return norm.cdf(-d2)
Reduced-Form Model
def hazard_rate_pd(hazard_rate, time_horizon): """ Calculate default probability from constant hazard rate. Parameters: ----------- hazard_rate : float Instantaneous default intensity (annual) time_horizon : float Time period (years) Returns: -------- float : Cumulative default probability """ return 1 - np.exp(-hazard_rate * time_horizon)
LGD Estimation:
class LGDEstimator: """Loss Given Default estimation.""" # Historical average recovery rates by seniority RECOVERY_RATES = { 'Senior Secured': 0.65, 'Senior Unsecured': 0.45, 'Senior Subordinated': 0.35, 'Subordinated': 0.25, 'Junior Subordinated': 0.15 } @classmethod def lgd_from_seniority(cls, seniority): """Estimate LGD based on debt seniority.""" recovery = cls.RECOVERY_RATES.get(seniority, 0.40) return 1 - recovery @staticmethod def lgd_from_collateral(debt_value, collateral_value, liquidation_costs=0.20): """ Calculate LGD considering collateral. Parameters: ----------- debt_value : float Outstanding debt amount collateral_value : float Market value of collateral liquidation_costs : float Costs of liquidating collateral (as fraction) Returns: -------- float : Loss given default """ net_recovery = collateral_value * (1 - liquidation_costs) loss = max(0, debt_value - net_recovery) return loss / debt_value
4. Credit Spreads and Yield Differentials
Components of Credit Spread:
Credit Spread = Expected Loss + Risk Premium + Liquidity Premium
Spread Analysis:
def credit_spread_decomposition(corporate_yield, treasury_yield, expected_loss_component): """ Decompose credit spread into components. Parameters: ----------- corporate_yield : float YTM of corporate bond treasury_yield : float YTM of comparable Treasury expected_loss_component : float Expected loss (PD × LGD) Returns: -------- dict : Spread decomposition """ total_spread = corporate_yield - treasury_yield risk_liquidity_premium = total_spread - expected_loss_component return { 'total_spread': total_spread, 'expected_loss': expected_loss_component, 'risk_premium': risk_liquidity_premium * 0.60, # Estimate 'liquidity_premium': risk_liquidity_premium * 0.40 # Estimate } def option_adjusted_spread_credit(z_spread, option_cost): """ Calculate credit-adjusted OAS. Parameters: ----------- z_spread : float Zero-volatility spread option_cost : float Value of embedded options Returns: -------- float : Option-adjusted spread """ return z_spread - option_cost
Credit Spread Curve:
import matplotlib.pyplot as plt def plot_credit_spread_curve(maturities, spreads, rating, date): """ Visualize credit spread term structure. Parameters: ----------- maturities : array-like Bond maturities spreads : array-like Credit spreads (basis points) rating : str Credit rating date : str Observation date """ plt.figure(figsize=(10, 6)) plt.plot(maturities, spreads, 'ro-', linewidth=2, markersize=6) plt.xlabel('Maturity (Years)') plt.ylabel('Credit Spread (bps)') plt.title(f'{rating} Credit Spread Curve - {date}') plt.grid(True, alpha=0.3) plt.show()
5. Event Risk and Credit Migration
Event Risk Categories:
- M&A Activity: Leverage increases from acquisitions
- Dividend Recapitalization: Debt-funded special dividends
- Regulatory Changes: New compliance costs or restrictions
- Litigation: Major legal judgments
Credit Migration Matrix:
# One-year transition probabilities (%) TRANSITION_MATRIX = { 'AAA': {'AAA': 90.81, 'AA': 8.33, 'A': 0.68, 'BBB': 0.06, 'Default': 0.00}, 'AA': {'AAA': 0.70, 'AA': 90.65, 'A': 7.79, 'BBB': 0.64, 'Default': 0.02}, 'A': {'AAA': 0.09, 'AA': 2.27, 'A': 91.05, 'BBB': 5.52, 'Default': 0.06}, 'BBB': {'AAA': 0.02, 'AA': 0.33, 'A': 5.95, 'BBB': 86.93, 'BB': 5.30, 'Default': 0.18}, 'BB': {'AAA': 0.03, 'BBB': 0.67, 'BB': 80.53, 'B': 8.84, 'Default': 1.06}, 'B': {'BB': 0.43, 'B': 83.46, 'CCC': 4.07, 'Default': 4.89}, 'CCC': {'B': 0.69, 'CCC': 58.24, 'Default': 26.92} } def expected_rating_migration(current_rating, years=1): """ Calculate probability distribution of future ratings. Returns: -------- dict : Probabilities for each rating category """ return TRANSITION_MATRIX.get(current_rating, {}) def downgrade_probability(current_rating, years=1): """ Calculate probability of downgrade within time horizon. """ transitions = TRANSITION_MATRIX.get(current_rating, {}) # Sum probabilities of lower ratings ratings_order = ['AAA', 'AA', 'A', 'BBB', 'BB', 'B', 'CCC'] current_index = ratings_order.index(current_rating) downgrade_prob = sum(transitions.get(r, 0) for r in ratings_order[current_index+1:]) downgrade_prob += transitions.get('Default', 0) return downgrade_prob / 100 # Convert to decimal
Expected Competency
Upon completion, you will be able to:
- Perform fundamental credit analysis using financial ratios
- Extract market-implied default probabilities from credit spreads
- Interpret credit ratings and understand rating methodologies
- Model PD and LGD using structural and reduced-form approaches
- Analyze credit spread behavior and decompose spread components
- Assess credit migration risk using transition matrices
- Monitor credit events and evaluate impact on portfolio
Deliverables
1. credit_risk_model.py
Production Python module containing:
- Fundamental credit metrics calculators
- PD/LGD modeling (Merton, hazard rate)
- Credit spread analysis tools
- Rating migration simulator
- Monte Carlo default scenario generator
- Portfolio credit risk aggregation
2. credit_spread_dashboard.md
Analysis documentation including:
- Credit spread tracking vs. Treasuries
- Spread curve analysis by rating tier
- Credit migration monitoring
- Event risk assessment framework
- Portfolio credit exposure report
Reference Materials
Foundational Texts
- Lando, D. Credit Risk Modeling: Theory and Applications
- Duffie, D. & Singleton, K. Credit Risk: Pricing, Measurement, and Management
- CFA Institute. Fixed Income - Credit Analysis
Rating Agency Methodologies
- Moody's: Rating Methodology
- S&P: Corporate Criteria
- Fitch: Rating Criteria
Data Sources
- FRED: Corporate Bond Spreads
- FINRA: Corporate Bond Data
- Bloomberg: Credit default swap (CDS) spreads
Validation Framework
Self-Assessment Checklist
- Calculate key credit ratios from financial statements
- Estimate implied default probability from credit spread
- Interpret rating agency methodologies
- Model PD using Merton framework
- Estimate LGD by seniority and collateral
- Decompose credit spread into components
- Apply credit migration matrices
- Assess portfolio credit concentration risk
Practice Problems
- Calculate implied PD for BB-rated bond: 300 bps spread, 40% recovery
- Estimate LGD for senior secured debt with $100M collateral, $150M debt
- Determine downgrade probability for A-rated issuer over 1 year
- Decompose 250 bps spread into expected loss and risk premium
Integration with Other Skills
- Bond Pricing: Credit spreads adjust discount rates
- Yield Measures: Credit component in yield analysis
- Benchmarking: Credit quality comparison vs. peers
- Portfolio Management: Credit risk aggregation and limits
Standards and Compliance
All credit analysis must document:
- Data sources and dates
- Rating sources and effective dates
- Assumptions (recovery rates, transition probabilities)
- Model validation and back-testing results
Version Control
Version: 1.0.0 Last Updated: 2025-12-07 Author: Ordinis-1 Bond Analysis Framework Status: Production Ready
Previous Skill:
duration-convexity/
Next Skill: bond-benchmarking/