Skip to content

Vintage Analysis Tutorial

This guide shows the baseline vintage workflow for comparing smoothing methods, validating them, and optionally projecting incomplete vintage tails.

Use this workflow when

  • you have cohort-level loss history by month on book
  • you want a fast cumulative-loss workflow without building a transition model
  • you need a ranked smoothing comparison as the first success metric

Do not start here if

  • your starting object is a portfolio snapshot plus a transition matrix — use Lifetime Loss Forecasting
  • your starting object is monthly aggregated rollforward data — use the Rollforward workflow
  • your main question is time-to-default or prepayment timing — use Survival Analysis

Inputs

Minimum columns:

  • vintage_date
  • months_on_book
  • cumulative_loss_rate

Useful segmentation columns:

  • vintage_name if you plan to override vintage_col
  • segment

If your data uses older labels such as vintage_name and mob, pass them through run_vintage_analysis_session(..., vintage_col=..., mob_col=...).

For the full contract, see Input Data Contracts.

Code

import numpy as np
import pandas as pd

from cranalytics import run_vintage_analysis_session

rows = []
for vintage_name, max_mob in [("2022-Q1", 12), ("2022-Q2", 9)]:
    curve = np.maximum.accumulate(
        0.055 * (1.0 - np.exp(-np.arange(1, max_mob + 1) / 6.0))
    )
    for mob, value in enumerate(curve, start=1):
        rows.append(
            {
                "vintage_date": vintage_name,
                "months_on_book": mob,
                "cumulative_loss_rate": float(value),
            }
        )

session = run_vintage_analysis_session(
    pd.DataFrame(rows),
    min_maturity_months=12,
    extrapolate_tails=True,
)
print(session.rankings[["method_name", "score"]])
print(session.validation_summary[["method_name", "train_mse", "test_mse"]])
print(session.tail_projections.tail())

Expected output / first win

Your first win is a vintage analysis session result with method rankings, validation output, and optional projected tails for incomplete vintages.

You should expect:

  • a ranked smoothing comparison table
  • a validation summary across smoothing methods
  • optional tail_projections rows when incomplete vintages are present and extrapolate_tails=True

Visualization

Visualize your vintage curves using the plotting utilities.

from cranalytics.viz import plot_vintage_triangle
import pandas as pd

triangle = pd.DataFrame(
    {
        1: [0.01, 0.008],
        2: [0.02, 0.018],
        3: [0.03, 0.027],
    },
    index=["2022-Q1", "2022-Q2"],
)

fig = plot_vintage_triangle(triangle)
fig.show()

Common mistakes

  • passing a wide pivoted table without first reshaping it into long vintage observations
  • feeding a non-cumulative loss series into a cumulative-loss workflow
  • expecting this workflow to model cashflows, transitions, or dynamic status migration
  • jumping straight to a single fitter before checking whether the session boundary already covers comparison, validation, and tail projection
  • using Vintage when your real business question is about feature ranking or ML backtesting

Next step

Run the packaged demo end-to-end with:

python -m cranalytics.examples.core_vintage

If you only need one direct parametric curve fit instead of the full analysis session, use CurveFitter from cranalytics.vintage.

If you need reserve-style portfolio forecasting instead of cohort curve fitting, continue to the Lifetime Loss Forecasting Tutorial.