Core credit risk analytics engine with vintage forecasting, FICO segmentation, and portfolio modeling
Project description
cranalytics - Credit Risk Analytics
DataFrame-first credit risk analytics for five core workflows plus advanced and supporting paths:
- Vintage curve fitting
- Lifetime loss forecasting
- FICO segmentation & portfolio diagnostics
- Feature analytics
- ML modeling — binary loan performance flags
- Survival analysis
- Portfolio simulation
- Rollforward workflow diagnostics
The base install includes every documented workflow in this repo, including
visualization and survival analysis. If you choose an external modeling backend
such as optbinning, xgboost, or lightgbm, install that backend directly.
Installation
Recommended environment:
- Official CPython 3.11 or 3.12 is the easiest path
- Python 3.10+ is supported
- Upgrade
pipfirst so binary wheels fornumpy,scipy, andpyarrowresolve cleanly
python -m pip install --upgrade pip
Latest preview release from TestPyPI:
Current preview builds are published to TestPyPI. Use the TestPyPI index for
cranalytics and keep PyPI as the fallback source for dependencies.
uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple cranalytics
# or: python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple cranalytics
Project page:
Stable install from PyPI:
Keep the standard install path separate. Once a production release is published to PyPI, these should remain the default commands.
uv add cranalytics
# or: python -m pip install cranalytics
If install fails on compiled dependencies:
- Upgrade
pipfirst - Prefer official CPython over alternative interpreters when validating wheels
- On Windows, install or update the Microsoft Visual C++ Redistributable if
pyarrowfails to import after install - If you already use conda/mamba,
conda-forgecan be the simplest fallback for scientific dependencies
From source:
uv pip install -e .
# or: python -m pip install -e .
Development dependencies (testing, linting, docs):
uv sync --group dev
Choose Your Path
After install, the canonical first command is cranalytics quickstart. Once you
know your question or data shape, use docs/choose_your_path.md and docs/reference/workflow_map.md to find the right workflow.
Hosted docs:
-
Deployment target: Vercel
-
Repo-owned deploy contract:
vercel.json -
If you already know the workflow and want to skip the menu, jump straight to the packaged demo or command that matches your first win:
-
Vintage: fitted curve and ultimate loss estimate
python -m cranalytics.examples.core_vintage -
Lifetime Loss: reserve estimate on a mock portfolio
python -m cranalytics.examples.core_lifetime_loss -
FICO Segmentation: FICO-band table and mix diagnostics
python -m cranalytics.examples.core_segmentation -
Feature Analytics: ranked feature table
python -m cranalytics.examples.core_feature_analytics -
ML Modeling: fold-level backtest summary table
python -m cranalytics.examples.core_ml_modeling -
Rollforward: readiness report directory and diagnostics
cranalytics rollforward-readiness your_rollforward_data.csv --output-dir rollforward_readiness_out -
Learn Workflow 4 with the tutorial:
docs/tutorials/feature_analytics.md -
Learn Workflow 5 with the tutorial:
docs/tutorials/ml_modeling.md -
Analyze time-to-default or prepayment timing:
python -m cranalytics.examples.core_survival -
Start from aggregated monthly rollforward data:
cranalytics rollforward-readiness your_rollforward_data.csv --output-dir rollforward_readiness_out
Start Here (After Install)
1) Verify your install
python -c "import cranalytics as ca; print(ca.__version__)"
Note: install name is cranalytics, import namespace is cranalytics.
2) Run the quickstart
cranalytics quickstart
Pick any workflow from the menu. Each runs in under 30 seconds with synthetic data, narrated output, and a summary of what data you need to run it on your own portfolio.
3) Install bundled Claude skills (optional)
Preview install actions first:
cranalytics install-skills --dry-run
Install all skills:
cranalytics install-skills --yes
Bundled skill names:
vintage-loss-curvesloss-forecastingportfolio-diagnosticspredictive-credit-modeling
Install only one skill:
cranalytics install-skills --skill vintage-loss-curves
Control conflict behavior on reinstall:
cranalytics install-skills --conflict overwrite # default
cranalytics install-skills --conflict skip
Show package and skills bundle version:
cranalytics install-skills --version
Why use --dry-run?
- Confirms which Claude skills path will be used
- Shows exactly what will be installed/updated/skipped
- Prevents accidental overwrite during validation
4) Pick a workflow and get one first win
Use docs/choose_your_path.md for narrative guidance
or docs/reference/workflow_map.md for a
compact command/input/output matrix. Then run one workflow end-to-end and look
for its first successful output before going deeper into API details. If you are
new, prefer cranalytics quickstart first and treat direct demo commands as a
shortcut once you already know the right path.
5) Run packaged examples (works from an installed package)
python -m cranalytics.examples.core_vintage
python -m cranalytics.examples.core_lifetime_loss
python -m cranalytics.examples.core_segmentation
Or use the CLI:
cranalytics demo --list
cranalytics demo lifetime-loss
6) Generate a readiness report on your own rollforward data
cranalytics rollforward-readiness your_rollforward_data.csv --output-dir rollforward_readiness_out
This command produces schema diagnostics, holdout forecast-vs-actual outputs,
baseline comparison metrics, and two onboarding charts to help new users
build trust before operational usage. rollforward-readiness is a preflight
diagnostic. For the full monthly operating workflow, use
cranalytics rollforward-workflow <input.csv>.
First-Time Rollforward Workflow
If you are running the Rollforward workflow for the first time:
- Prepare aggregated monthly rollforward data with these logical fields:
segment_id,month_on_book,payments,chargeoffs,outstanding_balance. Common aliases such assegment,mob,payment,chargeoff, andbalanceare accepted. For the full Rollforward contract and alias table, usedocs/reference/input_data_contracts.md. - Run the preflight diagnostic:
cranalytics rollforward-readiness your_rollforward_data.csv --output-dir rollforward_readiness_out
- Run the canonical operating workflow:
cranalytics rollforward-workflow your_rollforward_data.csv --output-dir rollforward_out
- Review the main outputs in
rollforward_out/:committee_summary.md,champion_selection.json,variant_summary.csv,segment_kpis.csv,schema_issues.csv, andnormalized_rollforward_data.csv.
Legacy CLI aliases remain supported.
CLI note: the CLI currently reads CSV inputs. If your source data is stored as Parquet or comes directly from a warehouse, load it into a pandas DataFrame and use the Python API instead:
from pathlib import Path
import pandas as pd
from cranalytics.rollforward_workflow import run_rollforward_workflow
df = pd.read_parquet("your_rollforward_data.parquet")
result = run_rollforward_workflow(
df,
output_dir=Path("rollforward_out"),
holdout_months=6,
min_train_months=12,
step_months=3,
)
print(result.status, result.champion)
Core Workflows
1) Vintage Curve Fitting
import numpy as np
from cranalytics.vintage import CurveFitter
mob = np.arange(1, 25)
losses = np.array([
0.001, 0.003, 0.006, 0.010, 0.014, 0.018, 0.022, 0.026,
0.030, 0.033, 0.036, 0.039, 0.041, 0.043, 0.045, 0.047,
0.048, 0.049, 0.050, 0.051, 0.052, 0.052, 0.053, 0.053
])
fitter = CurveFitter(method="weibull")
fitter.fit(mob, losses)
forecast = fitter.forecast(np.arange(1, 61))
print(f"Ultimate loss rate: {fitter.ultimate_:.3%}")
2) Lifetime Loss Forecasting
import pandas as pd
from cranalytics.loss_forecasting import forecast_lifetime_loss
portfolio_df = pd.DataFrame({
"loan_id": ["L101", "L102", "L103"],
"principal": [10000, 15000, 8000],
"annual_rate": [0.08, 0.10, 0.09],
"term_months": [36, 36, 24],
"start_date": [
pd.Timestamp("2024-01-01"),
pd.Timestamp("2024-02-01"),
pd.Timestamp("2024-01-15"),
],
"status": ["Current", "Delinquent", "Current"],
"fico_score": [720, 640, 700],
})
states = ["Current", "Delinquent", "Default"]
migration_matrix = pd.DataFrame(
[[0.95, 0.04, 0.01], [0.10, 0.80, 0.10], [0.00, 0.00, 1.00]],
index=states,
columns=states,
)
lifetime_loss = forecast_lifetime_loss(
portfolio_df,
migration_matrix,
lgd=0.55,
as_of_date=pd.Timestamp("2024-02-01"),
)
print(f"Estimated Lifetime Loss: ${lifetime_loss:,.2f}")
3) FICO Segmentation & Portfolio Diagnostics
import pandas as pd
from cranalytics.portfolio import calculate_fico_mix, calculate_lgd, segment_fico
df = pd.DataFrame({
"loan_id": [1, 2, 3],
"fico_score": [780, 650, 590],
"principal": [10000.0, 15000.0, 8000.0],
"collateral_value": [7000.0, 4000.0, 0.0],
"collateral_type": ["Vehicle", "Cash", "Unsecured"],
})
segmented = segment_fico(df)
print(segmented[["fico_score", "fico_band", "risk_grade"]])
mix = calculate_fico_mix(segmented)
print(mix)
lgd = calculate_lgd(df)
print(lgd)
4) Credit Risk Feature Analytics
Engineer ML-ready features from raw loan data and assess predictive power before training.
import pandas as pd
from cranalytics.early_performance import rank_features_by_separation
from cranalytics.model_development import (
engineer_loan_features,
fit_woe_binning,
lift_gain_table,
)
ref_date = pd.Timestamp("2025-12-31")
train = engineer_loan_features(train_df, as_of_date=ref_date)
# Rank features by IV / Gini / KS before committing to model
ranking = rank_features_by_separation(train, feature_cols=feature_cols, flag_col="fpf60")
# Optimal WoE binning (optional external dependency: optbinning)
process = fit_woe_binning(train, feature_cols=feature_cols, target_col="fpf60")
X_woe = process.transform(train[feature_cols], metric="woe")
5) ML Modeling — Binary Loan Performance Flags
Thin wrappers over sklearn/xgboost for the full lending model lifecycle: target construction, temporal backtesting, scoring, and bridging loan-level predictions to calendar-month charge-off dollars.
from cranalytics.forecasting_bridge import forecast_calendar_chargeoff_from_predictions
from cranalytics.predictive_backtest import run_predictive_backtest
from cranalytics.predictive_modeling import score_model, train_binary_model
from cranalytics.predictive_targets import build_targets
# Derive targets from monthly performance panel
targets = build_targets(panel_df, mode="panel", targets=["fpf30_flag", "dq30_mob6_flag"])
# Train with temporal OOT validation
backtest = run_predictive_backtest(
df, feature_cols, target_col="fpf30_flag",
split_col="origination_month", model_family="hgb_classifier",
)
# Train final model and score active book
estimator, metadata, diagnostics = train_binary_model(
train_df, feature_cols, target_col="fpf30_flag", model_family="logistic"
)
scored = score_model(active_df, estimator, feature_cols, output_col="fpf30_prob")
# Bridge to calendar charge-off dollars
forecast = forecast_calendar_chargeoff_from_predictions(scored, hazard_curves=curves)
Input Requirements (Lifetime Loss)
For onboarding, the minimum portfolio shape is loan_id, principal,
annual_rate, term_months, start_date, and status, plus transition input
in one of three shapes:
- a square transition matrix whose rows and columns share the same states
- a transition ledger with
loan_id,period, andstatus - a loan history panel with
loan_id,fund_date, andas_of_date
Use docs/reference/input_data_contracts.md for the full portfolio contract,
accepted status values, numeric ranges, and transition-input rules.
Advanced Modules
cranalytics.vintage: smoothing and model comparison utilitiescranalytics.viz: plotly/matplotlib visualizationscranalytics.survival: Kaplan-Meier/Cox/competing risks
Visualization and survival dependencies are included in the base install.
For smoothing and validation utilities, strict behavior is default. Use strict=False in comparison and validation helpers for best-effort fallback behavior.
Examples
Packaged Demos
The following examples are included in the package and can be run directly after installation:
# Basic vintage analysis and curve fitting
python -m cranalytics.examples.core_vintage
# Lifetime loss forecasting with transition inputs
python -m cranalytics.examples.core_lifetime_loss
# Portfolio segmentation and mix analysis
python -m cranalytics.examples.core_segmentation
# Survival analysis (Kaplan-Meier and Cox PH)
python -m cranalytics.examples.core_survival
You can also use the CLI to discover and run demos:
cranalytics demo --list
cranalytics demo vintage
cranalytics demo lifetime-loss
cranalytics demo segmentation
cranalytics demo survival
Advanced Examples
For more complex workflows, see the examples/ directory in the repository:
examples/lendingclub_full_pipeline.py— End-to-end pipeline on 35k LendingClub loans: FICO segmentation, LGD, vintage curves, survival analysis, loss forecasting, and simulation.examples/streamlit-demos/— Interactive Streamlit dashboard for portfolio diagnostics.
Documentation
- Hosted docs deployment target: Vercel
- Deploy contract:
vercel.json - Docs index:
docs/index.md - Choose your path:
docs/choose_your_path.md - Getting started:
docs/getting_started.md - Lifetime loss tutorial:
docs/tutorials/lifetime_loss_forecasting.md - FICO segmentation tutorial:
docs/tutorials/fico_segmentation.md - Claude skills guide:
docs/tutorials/claude_skills_getting_started.md - API reference:
docs/api/core.md,docs/api/engine.md,docs/api/predictive.md,docs/api/rollforward.md
Development
Run tests:
python -m pytest
License
MIT (see LICENSE).
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 cranalytics-0.2.0.tar.gz.
File metadata
- Download URL: cranalytics-0.2.0.tar.gz
- Upload date:
- Size: 225.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5720ac9fee86086472eb688530c9d62866ac31c5495b56bdbf2bd34352e9e67d
|
|
| MD5 |
d2885e30ef558e884134b33197f8bbd3
|
|
| BLAKE2b-256 |
e2cd21d909fd2d56d246ac9b44094f463b3708946792266322a3edc0fc0c40f9
|
Provenance
The following attestation bundles were made for cranalytics-0.2.0.tar.gz:
Publisher:
publish.yml on ClaySheffler/cranalytics
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cranalytics-0.2.0.tar.gz -
Subject digest:
5720ac9fee86086472eb688530c9d62866ac31c5495b56bdbf2bd34352e9e67d - Sigstore transparency entry: 1807503642
- Sigstore integration time:
-
Permalink:
ClaySheffler/cranalytics@852bd8b2cecf7ea401940f8f5b4a85128e7674fe -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ClaySheffler
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@852bd8b2cecf7ea401940f8f5b4a85128e7674fe -
Trigger Event:
push
-
Statement type:
File details
Details for the file cranalytics-0.2.0-py3-none-any.whl.
File metadata
- Download URL: cranalytics-0.2.0-py3-none-any.whl
- Upload date:
- Size: 277.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f56b3baf84098571f1126d3e490842c2a286fb11c4ff970e692173dc7e297c88
|
|
| MD5 |
758629b9976a9b250f3201d62fd1267e
|
|
| BLAKE2b-256 |
200a17453bf40f7c62abbf5f70a3f3b91abb0f59b9a622f3bcee138db53940c2
|
Provenance
The following attestation bundles were made for cranalytics-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on ClaySheffler/cranalytics
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cranalytics-0.2.0-py3-none-any.whl -
Subject digest:
f56b3baf84098571f1126d3e490842c2a286fb11c4ff970e692173dc7e297c88 - Sigstore transparency entry: 1807503654
- Sigstore integration time:
-
Permalink:
ClaySheffler/cranalytics@852bd8b2cecf7ea401940f8f5b4a85128e7674fe -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ClaySheffler
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@852bd8b2cecf7ea401940f8f5b4a85128e7674fe -
Trigger Event:
push
-
Statement type: