Models API¶
creditriskengine.models.pd.scorecard
¶
PD (Probability of Default) modeling framework.
Provides logistic regression scorecard, master scale construction, and PD calibration using the anchor point method.
References: - BCBS d350: Regulatory treatment of accounting provisions - EBA GL/2017/16: PD estimation, LGD estimation - Engelmann & Rauhmeier: The Basel II Risk Parameters (2nd ed.)
ScorecardBuilder
¶
Bases: BaseEstimator, ClassifierMixin
Sklearn-compatible PD scorecard builder.
Implements fit/predict interface for logistic regression-based PD models. Follows sklearn estimator patterns per project spec.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_score
|
float
|
Base scorecard score (default 600). |
600.0
|
pdo
|
float
|
Points to double the odds (default 20). |
20.0
|
base_odds
|
float
|
Odds at base score (default 50). |
50.0
|
Source code in creditriskengine\models\pd\scorecard.py
fit(X, y)
¶
Fit logistic regression and build master scale.
Uses sklearn LogisticRegression internally.
Source code in creditriskengine\models\pd\scorecard.py
predict_proba(X)
¶
Predict PD (probability of default) for each observation.
Source code in creditriskengine\models\pd\scorecard.py
predict(X)
¶
score_points(X)
¶
Convert to scorecard points.
Source code in creditriskengine\models\pd\scorecard.py
logistic_score(coefficients, features, intercept=0.0)
¶
Compute logistic regression log-odds scores.
Score = intercept + sum(coef_i * feature_i)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coefficients
|
ndarray
|
Model coefficients (length = n_features). |
required |
features
|
ndarray
|
Feature matrix (n_obs × n_features). |
required |
intercept
|
float
|
Model intercept. |
0.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of log-odds scores. |
Source code in creditriskengine\models\pd\scorecard.py
score_to_pd(scores)
¶
Convert log-odds scores to PD using the logistic function.
PD = 1 / (1 + exp(-score))
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
ndarray
|
Log-odds scores. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of PDs in [0, 1]. |
Source code in creditriskengine\models\pd\scorecard.py
pd_to_score(pds, base_score=600.0, base_odds=50.0, pdo=20.0)
¶
Convert PDs to scorecard points using the industry standard formula.
Score = base_score - pdo/ln(2) * ln(odds) where odds = (1-PD)/PD
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pds
|
ndarray
|
Probability of default values. |
required |
base_score
|
float
|
Score at which odds = base_odds. |
600.0
|
base_odds
|
float
|
Odds at the base score. |
50.0
|
pdo
|
float
|
Points to double the odds. |
20.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of scorecard points. |
Source code in creditriskengine\models\pd\scorecard.py
scorecard_to_pd(scores, base_score=600.0, base_odds=50.0, pdo=20.0)
¶
Convert scorecard points to PD (inverse of :func:pd_to_score).
Inverts the industry standard scorecard formula:
odds = exp((score - offset) / factor)
PD = 1 / (1 + odds)
where factor = pdo / ln(2) and
offset = base_score - factor * ln(base_odds).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
ndarray
|
Scorecard point values (e.g. 350, 500, 650, 800). |
required |
base_score
|
float
|
Score at which odds = base_odds. |
600.0
|
base_odds
|
float
|
Odds at the base score. |
50.0
|
pdo
|
float
|
Points to double the odds. |
20.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of PDs in (0, 1). |
Source code in creditriskengine\models\pd\scorecard.py
build_master_scale(grade_boundaries, grade_labels=None)
¶
Build a master scale mapping PD ranges to rating grades.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grade_boundaries
|
list[float]
|
Sorted ascending PD boundary values. N boundaries produce N-1 grades. First boundary is the lower PD bound, last is the upper. |
required |
grade_labels
|
list[str] | None
|
Optional labels for each grade. |
None
|
Returns:
| Type | Description |
|---|---|
list[dict[str, object]]
|
List of dicts with grade, pd_lower, pd_upper, pd_midpoint. |
Source code in creditriskengine\models\pd\scorecard.py
assign_rating_grade(pd, master_scale)
¶
Assign a rating grade based on PD and master scale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pd
|
float
|
Probability of default. |
required |
master_scale
|
list[dict[str, object]]
|
Master scale from build_master_scale(). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Grade label. |
Source code in creditriskengine\models\pd\scorecard.py
calibrate_pd_anchor_point(central_tendency, raw_pds)
¶
Calibrate PDs using the anchor-point method.
Scales raw (model) PDs so their portfolio-weighted average matches the long-run central tendency.
Formula
calibrated_PD_i = raw_PD_i × (central_tendency / mean(raw_PDs))
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
central_tendency
|
float
|
Long-run average default rate. |
required |
raw_pds
|
ndarray
|
Raw/uncalibrated PD estimates. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Calibrated PD array, clipped to [PD_floor, 1.0]. |
Source code in creditriskengine\models\pd\scorecard.py
calibrate_pd_bayesian(prior_pd, observed_defaults, n_observations, weight=0.5)
¶
Bayesian PD calibration combining prior with observed data.
PD_calibrated = weight × prior_PD + (1-weight) × observed_DR
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prior_pd
|
float
|
Prior (long-run) PD estimate. |
required |
observed_defaults
|
int
|
Number of observed defaults. |
required |
n_observations
|
int
|
Number of observations. |
required |
weight
|
float
|
Weight on prior (0 = pure data, 1 = pure prior). |
0.5
|
Returns:
| Type | Description |
|---|---|
float
|
Calibrated PD. |
Source code in creditriskengine\models\pd\scorecard.py
vasicek_single_factor_pd(pd_ttc, rho, confidence=0.999)
¶
Conditional PD under the Vasicek single-factor model.
PD_conditional = Phi( (Phi^-1(PD) + sqrt(rho)*Phi^-1(confidence)) / sqrt(1-rho) )
This is the stressed/downturn PD used in regulatory capital.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pd_ttc
|
float
|
Through-the-cycle PD. |
required |
rho
|
float
|
Asset correlation. |
required |
confidence
|
float
|
Confidence level (default 99.9%). |
0.999
|
Returns:
| Type | Description |
|---|---|
float
|
Conditional (stressed) PD. |
Source code in creditriskengine\models\pd\scorecard.py
creditriskengine.models.lgd.lgd_model
¶
LGD (Loss Given Default) modeling framework.
Provides workout LGD estimation, downturn LGD adjustment, and LGD curve generation.
References: - EBA GL/2017/16: LGD estimation - BCBS d424: CRE36 (LGD under IRB) - BCBS CRE32.22-32.24: Supervisory LGD values
LGDModel
¶
Bases: BaseEstimator, RegressorMixin
Sklearn-compatible LGD model.
Wraps workout LGD estimation with fit/predict interface.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
method
|
str
|
LGD estimation method ('workout', 'downturn', 'regulatory'). |
'workout'
|
downturn_method
|
str
|
Downturn LGD method ('additive', 'haircut', 'regulatory_formula'). |
'regulatory_formula'
|
downturn_add_on
|
float
|
Additive stress for downturn LGD. |
0.1
|
collateral_type
|
str
|
For regulatory LGD floor application. |
'unsecured'
|
Source code in creditriskengine\models\lgd\lgd_model.py
fit(X, y)
¶
Fit LGD model. X = features, y = realized LGDs.
Stores mean LGD for baseline predictions.
Source code in creditriskengine\models\lgd\lgd_model.py
predict(X)
¶
Predict LGD values. Returns mean LGD (baseline model).
Override in subclasses for more sophisticated models.
Source code in creditriskengine\models\lgd\lgd_model.py
workout_lgd(ead_at_default, total_recoveries, total_costs, discount_rate=0.0, time_to_recovery_years=0.0)
¶
Calculate workout LGD from realized recovery data.
LGD = 1 - (Recoveries - Costs) / EAD, discounted to default date.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ead_at_default
|
float
|
Exposure at the time of default. |
required |
total_recoveries
|
float
|
Total gross recoveries. |
required |
total_costs
|
float
|
Total workout/collection costs. |
required |
discount_rate
|
float
|
Annual discount rate for time value. |
0.0
|
time_to_recovery_years
|
float
|
Average time from default to recovery. |
0.0
|
Returns:
| Type | Description |
|---|---|
float
|
Workout LGD in [0, 1]. |
Source code in creditriskengine\models\lgd\lgd_model.py
downturn_lgd(base_lgd, downturn_add_on=None, method='additive')
¶
Estimate downturn LGD per EBA GL/2017/16 Section 6.3.
Functions:
| Name | Description |
|---|---|
- "additive" |
LGD_dt = base_LGD + add_on |
- "haircut" |
LGD_dt = 1 - (1 - base_LGD) × (1 - add_on) |
- "regulatory" |
Use BCBS formula max(base_LGD, 0.10 + 0.40 × base_LGD) |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_lgd
|
float
|
Through-the-cycle / long-run average LGD. |
required |
downturn_add_on
|
float | None
|
Downturn add-on (for additive/haircut). |
None
|
method
|
str
|
Estimation method. |
'additive'
|
Returns:
| Type | Description |
|---|---|
float
|
Downturn LGD, clipped to [0, 1]. |
Source code in creditriskengine\models\lgd\lgd_model.py
lgd_term_structure(base_lgd, n_periods, recovery_curve=None)
¶
Generate LGD term structure over multiple periods.
If a recovery curve is provided, LGD(t) = 1 - cumulative_recovery(t). Otherwise returns flat LGD.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_lgd
|
float
|
Base LGD estimate. |
required |
n_periods
|
int
|
Number of periods. |
required |
recovery_curve
|
ndarray | None
|
Optional cumulative recovery rates by period. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of LGD values by period. |
Source code in creditriskengine\models\lgd\lgd_model.py
apply_lgd_floor(lgd, is_secured=False, collateral_type='unsecured')
¶
Apply Basel III A-IRB LGD floors per CRE32.25.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lgd
|
float
|
Estimated LGD. |
required |
is_secured
|
bool
|
Whether exposure is secured. |
False
|
collateral_type
|
str
|
Type of collateral. |
'unsecured'
|
Returns:
| Type | Description |
|---|---|
float
|
Floored LGD. |
Source code in creditriskengine\models\lgd\lgd_model.py
creditriskengine.models.ead.ead_model
¶
EAD (Exposure at Default) modeling framework.
Provides CCF estimation, regulatory EAD calculation, and EAD term structure generation for off-balance sheet exposures.
References: - BCBS d424: CRE31 (EAD under IRB), CRE20 (EAD under SA) - CRE32.26-32.32: CCF parameters - EBA GL/2017/16: EAD estimation for A-IRB
EADModel
¶
Bases: BaseEstimator, RegressorMixin
Sklearn-compatible EAD model.
Wraps EAD/CCF estimation with fit/predict interface.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ccf_method
|
str
|
CCF estimation method ('supervisory', 'estimated'). |
'supervisory'
|
facility_type
|
str
|
For supervisory CCF lookup. |
'committed_other'
|
Source code in creditriskengine\models\ead\ead_model.py
fit(X, y)
¶
Fit EAD model. X = [drawn, undrawn], y = realized EAD.
Source code in creditriskengine\models\ead\ead_model.py
predict(X)
¶
Predict EAD. X columns: [drawn, undrawn].
Source code in creditriskengine\models\ead\ead_model.py
calculate_ead(drawn_amount, undrawn_commitment, ccf)
¶
Calculate Exposure at Default.
EAD = Drawn + CCF × Undrawn
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
drawn_amount
|
float
|
Current outstanding balance. |
required |
undrawn_commitment
|
float
|
Undrawn committed amount. |
required |
ccf
|
float
|
Credit Conversion Factor. |
required |
Returns:
| Type | Description |
|---|---|
float
|
EAD value. |
Source code in creditriskengine\models\ead\ead_model.py
estimate_ccf(ead_at_default, drawn_at_reference, limit)
¶
Estimate realized CCF from default observation.
CCF = (EAD - Drawn_ref) / (Limit - Drawn_ref)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ead_at_default
|
float
|
Actual EAD observed at default. |
required |
drawn_at_reference
|
float
|
Drawn amount at reference date (12m before default). |
required |
limit
|
float
|
Total committed limit. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Realized CCF, clipped to [0, 1]. |
Source code in creditriskengine\models\ead\ead_model.py
get_supervisory_ccf(facility_type)
¶
Get the F-IRB supervisory CCF for a facility type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
facility_type
|
str
|
Facility type key (see SUPERVISORY_CCFS). |
required |
Returns:
| Type | Description |
|---|---|
float
|
Supervisory CCF value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If facility type is unknown. |
Source code in creditriskengine\models\ead\ead_model.py
apply_ccf_floor(ccf, approach='airb')
¶
Apply regulatory CCF floor.
A-IRB floor per CRE32.33: CCF >= 50% for revolving. F-IRB: supervisory values are fixed, no floor needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ccf
|
float
|
Estimated CCF. |
required |
approach
|
str
|
"airb" or "firb". |
'airb'
|
Returns:
| Type | Description |
|---|---|
float
|
Floored CCF. |
Source code in creditriskengine\models\ead\ead_model.py
ead_term_structure(drawn_amount, undrawn_commitment, ccf, n_periods, amortization_rate=0.0)
¶
Generate EAD term structure with optional amortization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
drawn_amount
|
float
|
Current drawn amount. |
required |
undrawn_commitment
|
float
|
Undrawn commitment. |
required |
ccf
|
float
|
Credit conversion factor. |
required |
n_periods
|
int
|
Number of periods. |
required |
amortization_rate
|
float
|
Annual amortization rate for the drawn amount. |
0.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of EAD values by period. |
Source code in creditriskengine\models\ead\ead_model.py
creditriskengine.models.concentration.concentration
¶
Concentration risk analytics.
Single-name concentration, sector/geographic HHI, and the Granularity Adjustment (GA) per BCBS.
References: - BCBS d424: Pillar 2 concentration risk - Gordy (2003): A risk-factor model foundation for ratings-based capital rules - Gordy & Lütkebohmert (2013): Granularity adjustment for regulatory capital
single_name_concentration(eads)
¶
Measure single-name concentration in a portfolio.
Returns HHI and top-N exposure shares.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
eads
|
ndarray
|
EAD per obligor. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dict with hhi, top_1_share, top_5_share, top_10_share, n_obligors. |
Source code in creditriskengine\models\concentration\concentration.py
sector_concentration(eads, sector_labels)
¶
Measure sector concentration via HHI.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
eads
|
ndarray
|
EAD per exposure. |
required |
sector_labels
|
ndarray
|
Sector label per exposure. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, float | dict[str, float]]
|
Dict with sector_hhi and sector_shares. |
Source code in creditriskengine\models\concentration\concentration.py
granularity_adjustment(eads, pds, lgds, rho)
¶
Gordy (2003) Granularity Adjustment.
GA = (1/2) × C_3 × HHI_adj
Where C_3 captures the curvature of the loss distribution and HHI_adj is the EAD-weighted HHI of PD×LGD contributions.
Simplified single-factor version for Pillar 2 add-on estimation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
eads
|
ndarray
|
EAD per obligor. |
required |
pds
|
ndarray
|
PD per obligor. |
required |
lgds
|
ndarray
|
LGD per obligor. |
required |
rho
|
float
|
Common asset correlation. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Granularity adjustment as a fraction of total EAD. |