CDFI portfolio stress testing engine — Monte Carlo simulation with correlated NOI, rate, and property-value shocks
Project description
cdfi-stress-tester
Professional CDFI portfolio stress testing engine for Python.
Monte Carlo simulation with correlated shocks to NOI, interest rates, and property values. Compute VaR, CVaR, and capital adequacy across 2008-style recession, COVID, rate-spike, and regional CRE crash scenarios — all from pure numpy/pandas, no simulation libraries required.
Why cdfi-stress-tester?
CDFI Fund regulations and investor due diligence increasingly require stress-tested capital adequacy projections. Building Monte Carlo models in Excel is brittle and hard to audit. cdfi-stress-tester provides a reproducible, testable Python engine tuned to community development finance portfolio characteristics.
Installation
pip install cdfi-stress-tester
Requires: numpy, pandas (Python 3.9+).
Quickstart
from cdfistress import (
generate_sample_portfolio,
from_standard,
MonteCarloEngine,
generate_stress_report,
scenario_comparison_table,
value_at_risk, conditional_var, capital_adequacy_report,
)
# Load a 50-loan CDFI portfolio
loans = generate_sample_portfolio(n=50, seed=42)
# Build the Monte Carlo engine
engine = MonteCarloEngine(loans=loans, available_capital=5_000_000)
# Run a 2008-style recession scenario
scenario = from_standard("2008_recession")
result = engine.run_simulation(scenario, n_iterations=1000, seed=42)
# Print human-readable report
print(generate_stress_report(result))
# ============================================================
# CDFI PORTFOLIO STRESS TEST REPORT
# Scenario: 2008-Style Recession [SEVERE]
# ============================================================
# LOSS METRICS
# Expected Loss : $2,341,205
# VaR (95%) : $3,879,450
# VaR (99%) : $4,672,000
# CAPITAL ADEQUACY
# CAR vs Expected Loss : 2.14x
# STATUS: ADEQUATE
# Compare multiple scenarios
scenarios = [from_standard(k) for k in ["mild_downturn", "rate_spike", "2008_recession"]]
results = [engine.run_simulation(s, n_iterations=500, seed=0) for s in scenarios]
print(scenario_comparison_table(results))
# Capital adequacy deep-dive
import numpy as np
losses = np.array([result.expected_loss]) # or use internal loss distribution
report = capital_adequacy_report(5_000_000, np.random.default_rng(0).lognormal(14, 0.5, 1000))
Key Features
| Feature | Detail |
|---|---|
| Monte Carlo engine | MonteCarloEngine with seed-controlled reproducibility |
| Correlated shocks | Multivariate normal draws for NOI, rate, and property value |
| Standard scenarios | 2008 recession, COVID, rate spike (+300 bps), regional CRE crash, mild downturn |
| Custom scenarios | create_recession_scenario(), create_rate_shock_scenario(), create_sector_specific_scenario() |
| VaR / CVaR | 95th and 99th percentile VaR; Expected Shortfall (CVaR) |
| Capital adequacy | CAR vs EL, VaR, and CVaR; breach count and breach rate |
| Tier 1 under stress | Post-stress Tier 1 ratio given risk-weighted assets |
| Sample portfolio | Reproducible 50-loan CDFI portfolio with realistic parameters |
| LGD modeling | Per-loan LGD with collateral shortfall and 30% foreclosure-cost floor |
| Reports | generate_stress_report() and scenario_comparison_table() |
Scenarios
STANDARD_SCENARIOS = {
"2008_recession": {"noi_shock": -0.35, "rate_shock": 0.00, "property_value_shock": -0.40, "default_rate_multiplier": 4.0},
"covid_shock": {"noi_shock": -0.25, "rate_shock": -0.01, "property_value_shock": -0.15, "default_rate_multiplier": 2.5},
"rate_spike": {"noi_shock": -0.05, "rate_shock": +0.03, "property_value_shock": -0.20, "default_rate_multiplier": 1.8},
"regional_cre_crash":{"noi_shock": -0.20, "rate_shock": +0.01, "property_value_shock": -0.50, "default_rate_multiplier": 3.0},
"mild_downturn": {"noi_shock": -0.10, "rate_shock": +0.005,"property_value_shock": -0.08, "default_rate_multiplier": 1.4},
}
Use Cases
- CDFI Fund reporting — Demonstrate capital adequacy under regulatory stress scenarios.
- Rating agency submissions — Produce reproducible loss distributions for credit analysis.
- Board risk committees — Run scenario comparison tables for governance reporting.
- Investors / lenders — Stress-test CDFI portfolios during due diligence.
- Policy researchers — Analyze CDFI sector resilience across geographic and sector concentrations.
API Reference
# Data
generate_sample_portfolio(n=50, seed=42) # 50-loan CDFI portfolio
Loan(loan_id, borrower_name, outstanding_balance, noi, debt_service,
property_value, interest_rate, sector, state, ltv)
.dscr # noi / debt_service
.is_stressed # dscr < 1.0
StressScenario(name, noi_shock, rate_shock, property_value_shock,
default_rate_multiplier, severity)
.summary()
# Scenarios
from_standard("2008_recession")
create_recession_scenario(noi_shock, rate_shock, property_value_shock, default_rate_multiplier)
create_rate_shock_scenario(rate_shock, property_value_shock)
create_sector_specific_scenario(sector, noi_shock, property_value_shock)
apply_shock_to_loan(loan, scenario) # returns stressed Loan
# Simulation
MonteCarloEngine(loans, available_capital, correlation_matrix)
.run_simulation(scenario, n_iterations=1000, seed=None) # → StressResult
.apply_correlated_shocks(scenario, n_iterations, seed) # → ndarray (n, 3)
.simulate_default_events(scenario, seed) # → {loan_id: pd}
# VaR / Capital
value_at_risk(losses, confidence=0.95)
conditional_var(losses, confidence=0.95)
expected_loss(losses)
tail_loss(losses, pct=0.01)
capital_adequacy(available_capital, expected_loss_amount)
tier1_under_stress(tier1_capital, losses, risk_weighted_assets, confidence=0.99)
buffer_breach_count(losses, capital_buffer)
capital_adequacy_report(available_capital, losses)
# Correlations
build_correlation_matrix(noi_rate, noi_property, rate_property)
default_correlations()
is_positive_semidefinite(matrix)
# Reports
generate_stress_report(result) # → str
scenario_comparison_table(results) # → str
License
MIT © Jay Patel
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cdfi_stress_tester-0.1.0.tar.gz.
File metadata
- Download URL: cdfi_stress_tester-0.1.0.tar.gz
- Upload date:
- Size: 15.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c87f922ecc10810ef1133ac7d540238c55850df4abd5bb4bc5ecc0af10d25b97
|
|
| MD5 |
3ca9fa28de4a7347744d4e8e9f1380b9
|
|
| BLAKE2b-256 |
29243fe1d9a8141c85ef2cdd04efbcf2ebf22e3bebceb9ae95893d578b018584
|
File details
Details for the file cdfi_stress_tester-0.1.0-py3-none-any.whl.
File metadata
- Download URL: cdfi_stress_tester-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe0ae845fe048059f99307f783f8d5f83ab2e2b45d88305d5b4c639062630b08
|
|
| MD5 |
390263c247aec8ee75c9a15dedf05528
|
|
| BLAKE2b-256 |
10d5bf0a3a28cd6cbc5eab1a94272bef0029a92111bbb355374075fb4d4e7f6f
|