Flow-Hazard Forecasting Tutorial
Advanced / optional module. This is a separate workflow from classical event-time Survival Analysis: instead of modeling time-to-event at the loan level, it models aggregated monthly payment and charge-off hazards over outstanding balance, then rolls balances forward to forecast future flows.
Use it when you have aggregated monthly performance flows by segment and want to project payments, charge-offs, and runoff — not when you have loan-level durations and want Kaplan-Meier / Cox / competing risks.
Import
survival_flows is a stable, supported public module. The canonical import is:
from cranalytics.survival_flows import (
fit_flow_hazard_curves,
forecast_balance_flows,
compare_known_actuals_to_curves,
validate_flow_data,
FLOW_REQUIRED_COLUMNS,
)
The bare from cranalytics import fit_flow_hazard_curves form was retired in
0.2.0; accessing it now raises a tombstone that redirects you here.
Required input schema
Every function validates against this flow schema (FLOW_REQUIRED_COLUMNS):
| Column | Type | Meaning |
|---|---|---|
segment_id |
str-like | Segment identifier |
month_on_book |
int ≥ 0 | Age of the cohort in months |
payments |
float ≥ 0 | Dollar payments in the month |
chargeoffs |
float ≥ 0 | Dollar charge-offs in the month |
outstanding_balance |
float > 0 | Balance the hazards are taken over |
The two hazards are payments / outstanding_balance and
chargeoffs / outstanding_balance per month-on-book.
Fit hazard curves
fit_flow_hazard_curves aggregates flows by month-on-book (optionally by
segment) and returns smoothed monthly payment and charge-off hazard rates.
import pandas as pd
from cranalytics.survival_flows import fit_flow_hazard_curves
flows = pd.DataFrame({
"segment_id": ["prime", "prime", "prime"],
"month_on_book": [1, 2, 3],
"payments": [100.0, 95.0, 90.0],
"chargeoffs": [5.0, 5.0, 4.0],
"outstanding_balance": [1000.0, 900.0, 810.0],
})
curves = fit_flow_hazard_curves(flows, smoothing_window=1)
# columns: segment_id, month_on_book, payment_hazard_rate, chargeoff_hazard_rate
Forecast balance flows
forecast_balance_flows keeps observed months as Actual, then extends the
curve forward to max_month, rolling the balance down by projected payments and
charge-offs each month. Output carries both dollar values and ratios to
amtloan.
from cranalytics.survival_flows import forecast_balance_flows
forecast = forecast_balance_flows(flows, curves, max_month=5, amtloan=1000.0)
sorted(forecast["forecast_flag"].unique()) # ['Actual', 'Forecast']
int(forecast["month_on_book"].max()) # 5
This example is executed as a doctest on forecast_balance_flows, so it stays
in sync with the code.
Overflow policy
When a projected payment + charge-off hazard pair sums above 1.0, the
overflow_policy argument controls the response: "scale" (silent
proportional scaling), "warn" (scale + UserWarning, the default), or
"error" (raise). Use "error" in production / strict-mode pipelines so a bad
fit or bad data surfaces instead of being silently rescaled.
Backtesting fitted curves
compare_known_actuals_to_curves lines up realized hazards against the fitted
curve month-by-month and returns per-month variance columns, useful for
monitoring drift between expected and actual flows.
Relationship to other modules
- For loan-level time-to-event modeling (default/payoff timing), use
cranalytics.survivalor itsrun()unified entry point. - Flow-hazard curves also feed the rollforward workflow; this tutorial covers
the standalone
survival_flowssurface.