Your Data
Almost everything in cranalytics takes a pandas DataFrame. There are three
canonical data shapes. Learn these three and you know what every workflow
wants — everything else is a converter away.
Before running anything, check your frame:
import cranalytics as ca
report = ca.check(df) # auto-detects the workflow
report.ok # True when the frame is valid
report.workflow # e.g. "portfolio"
report.shape # e.g. "loan snapshot"
report.required_columns # what a passing frame must contain
report.issues # a DataFrame of problems (empty when ok)
check() never raises by default — it returns a report so you can see every
problem at once. Pass strict=True to raise instead, or workflow="vintage" to
skip auto-detection. On the command line: cranalytics check your_data.csv.
The three shapes
| Shape | Grain | Minimum columns | Workflow | check() reports |
|---|---|---|---|---|
| Loan snapshot | one row per loan, as of a date | loan_id, principal, annual_rate, term_months, start_date, status |
portfolio (FICO segmentation, lifetime loss, simulation) |
shape="loan snapshot" |
| Loan history | one row per loan per period | loan_id, principal, annual_rate, term_months, start_date, plus your target (e.g. fpf30_flag) |
feature-analytics (early performance, ML modeling) |
shape="loan history" |
| Rollforward aggregate | one row per segment per month-on-book | segment_id, month_on_book, payments, chargeoffs, outstanding_balance |
rollforward (readiness, flow forecasting) |
shape="rollforward aggregate" |
Loan snapshot
One row per loan, capturing its state as of a single date. This is the "portfolio" or "loan tape" most people start with.
Loan history
One row per loan per period (a.k.a. a performance panel). A loan history is a loan snapshot observed repeatedly over time; it carries a period column and the outcome you want to model.
Rollforward aggregate
Already summarized to one row per segment per month-on-book, with the dollar flows (payments, charge-offs, balance) the rollforward engine rolls forward.
A derived shape: the vintage triangle
The vintage workflow consumes a vintage triangle — a wide grid of cumulative loss by vintage (rows) and month-on-book (columns). It is not a base shape; it is derived from a loan history.
Converting between shapes
history_to_triangle and snapshot_from_history expect a loan history that
already carries a vintage cohort and a computed loss metric — the
vintage/performance-panel convention cranalytics.datasets.make_mock_performance_data
produces (vintage_name, mob, cumulative_loss_rate):
import cranalytics as ca
from cranalytics.datasets import make_mock_performance_data
history = make_mock_performance_data(max_mob=24)
# Loan history -> vintage triangle (for the vintage workflow)
triangle = ca.history_to_triangle(history)
# Loan history -> loan snapshot (latest period per loan)
snapshot = ca.snapshot_from_history(history)
If your loan history instead matches the loan_history_contract shape
(loan_id, fund_date, as_of_date, month_on_book), it has neither a
vintage cohort nor a precomputed loss rate — both require aggregation these
converters deliberately don't infer. Derive those columns yourself, then pass
explicit column names:
snapshot = ca.snapshot_from_history(history, period_col="month_on_book")
Both are deterministic DataFrame-to-DataFrame converters, so you can get from the data you have to the shape a workflow needs without reverse-engineering internals.
For the exact column types, accepted values, and aliases each contract enforces, see the Input Data Contracts reference. This page is the friendly front door; that page is the detailed spec.