Core API Reference
Metrics
Use the metrics module for binary model discrimination and portfolio timing
measures. Start with calculate_gini() and calculate_ks() when comparing risk
scores against observed outcomes.
cranalytics.metrics
Core risk and portfolio metrics.
calculate_gini(y_true: np.ndarray, y_prob: np.ndarray) -> float
Calculate the binary-model Gini coefficient.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
ndarray
|
Binary observed outcomes. |
required |
y_prob
|
ndarray
|
Predicted risk scores or probabilities, where larger values indicate higher risk. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Gini coefficient, calculated as |
Examples:
>>> import numpy as np
>>> from cranalytics import calculate_gini
>>> calculate_gini(np.array([0, 1]), np.array([0.1, 0.9]))
1.0
calculate_ks(y_true: np.ndarray, y_prob: np.ndarray) -> float
Calculate the binary-model Kolmogorov-Smirnov statistic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
ndarray
|
Binary observed outcomes. |
required |
y_prob
|
ndarray
|
Predicted risk scores or probabilities, where larger values indicate higher risk. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Maximum absolute difference between cumulative good and bad shares. |
Examples:
>>> import numpy as np
>>> from cranalytics import calculate_ks
>>> calculate_ks(np.array([0, 1]), np.array([0.1, 0.9]))
1.0
calculate_classification_metrics(y_true: np.ndarray, y_prob: np.ndarray, threshold: float = 0.5) -> dict[str, float]
Calculate accuracy, precision, recall, and F1 score.
calculate_wal(schedule: pd.DataFrame) -> float
Calculate Weighted Average Life (WAL) in months.
Finance
The finance module contains amortization, present-value, and return helpers. These utilities are building blocks for analysis rather than an end-to-end Loss Forecasting workflow.
cranalytics.finance
Basic financial math utilities used in credit analytics.
generate_amortization_schedule(principal: float, annual_rate: float, term_months: int) -> pd.DataFrame
Generate a standard monthly amortization schedule.
calculate_irr(cash_flows: list[float], initial_investment: float, periods_per_year: int = 12) -> float
Calculate the annualized Internal Rate of Return (IRR) as a decimal.
calculate_npv(cash_flows: list[float], initial_investment: float, discount_rate: float, periods_per_year: int = 12) -> float
Calculate Net Present Value (NPV).
Portfolio
Use the portfolio module for score segmentation and collateral-based recovery
diagnostics. segment_fico() only requires a fico_score column; LGD helpers
need exposure fields such as principal.
cranalytics.portfolio
Portfolio transforms and loss calculation utilities.
assign_fico_band(fico_score: int, bands: dict[str, tuple[int, int]] | None = None) -> str
Assign a FICO band based on score.
assign_risk_grade(fico_score: int, cutoffs: list[int] | None = None) -> int
Assign a risk grade based on descending FICO score cutoffs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fico_score
|
int
|
The FICO score. |
required |
cutoffs
|
list[int] | None
|
A descending list of thresholds. If None, it defaults to [800, 750, 700, 650, 600], producing grades 1-6. |
None
|
segment_fico(df: pd.DataFrame, fico_column: str = 'fico_score', bands: dict[str, tuple[int, int]] | None = None, risk_cutoffs: list[int] | None = None) -> pd.DataFrame
Add FICO band and risk grade columns to a portfolio DataFrame.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
Input DataFrame. Only the score column is required. |
required |
fico_column
|
str
|
Name of the score column to segment. |
'fico_score'
|
bands
|
dict[str, tuple[int, int]] | None
|
Optional mapping of band labels to inclusive score ranges. |
None
|
risk_cutoffs
|
list[int] | None
|
Optional descending thresholds used to assign numeric grades. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Copy of the input DataFrame with |
Examples:
>>> import pandas as pd
>>> from cranalytics import segment_fico
>>> segmented = segment_fico(pd.DataFrame({"fico_score": [780, 640]}))
>>> segmented[["fico_band", "risk_grade"]].astype(str).to_dict("records")
[{'fico_band': '750-799', 'risk_grade': '2'}, {'fico_band': '600-649', 'risk_grade': '5'}]
calculate_fico_mix(df: pd.DataFrame, group_by: list[str] | None = None) -> pd.DataFrame
Calculate the FICO mix (distribution) for a portfolio or vintage.
calculate_lgd(loan_data: pd.DataFrame | pd.Series, haircuts: dict[str, float] | None = None) -> pd.Series | float
Calculate Loss Given Default (LGD) based on collateral.
LGD = 1 - (Recovery Value / Exposure) Recovery Value = Collateral Value * (1 - Haircut)
estimate_recovery(loan_data: pd.DataFrame | pd.Series, haircuts: dict[str, float] | None = None) -> pd.Series | float
Estimate recovery amount based on collateral value and haircuts.