Skip to content

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.survival or its run() unified entry point.
  • Flow-hazard curves also feed the rollforward workflow; this tutorial covers the standalone survival_flows surface.