Rollforward Workflow API Reference
Rollforward Workflow
Rollforward is the single object for all three rollforward surfaces:
.run(mode="model") (in-memory), .run(mode="workflow", output_dir=...)
(artifact-emitting), and .readiness(...). run(), run_rollforward_workflow(),
and generate_rollforward_readiness_report() are convenience entry points over
it. Run readiness checks first when working with a new dataset. The result
types (RollforwardRunSummary, operational_status, etc.) are the canonical
cross-surface summary contract.
Each result also has .summary()/.plot() (RollforwardResult,
RollforwardWorkflowResult) matching vintage/survival/predictive.
ReadinessRunResult is a deliberate partial exception: it already has a field
named summary (the readiness scoring dict), so result.summary — no call —
already serves that role there; it still has .plot().
cranalytics.rollforward
Unified public front door for the rollforward workflow.
Rollforward is the single object for all three rollforward surfaces, hiding the
multi-module session / evaluation / reporting / result-translation chain behind a
small interface:
.run(mode="model")-> in-memory :class:RollforwardResult.run(mode="workflow")-> artifact-emitting :class:RollforwardWorkflowResult.readiness(...)-> readiness :class:ReadinessRunResult
model and workflow share the same session engine and differ only in
whether artifacts are written, so they are two modes of one run. readiness
uses a distinct session, config, and defaults, so it is a sibling method on the
same object rather than a mode with half-ignored parameters. The module-level
functions run (workflow-namespaced: cranalytics.rollforward.run),
run_rollforward_workflow, and generate_rollforward_readiness_report are
thin shims over this object.
No file I/O in model mode — fully in-memory.
This module carries the workflow's real entry-point logic (the Rollforward
class), unlike the pure re-export facades used by other workflows — there is
no separate flat module to preserve here. _workflow.py/_readiness.py-style
thin wrappers are intentionally kept inline below rather than split into their
own submodules: those submodules would need Rollforward from here, and this
module re-exports their functions, which is a circular import.
ReadinessRunResult
dataclass
No .summary() method here: summary is already a field (the
readiness scoring dict), so result.summary already gives the compact
summary other Phase 3 workflow results expose via a method call.
plot(**kwargs: Any) -> Any
Forecast-vs-actual chart already written to output_dir. Requires matplotlib.
RollforwardResult
dataclass
summary() -> pd.DataFrame
Champion-vs-challenger backtest comparison, best-first by MAPE.
plot(**kwargs: Any) -> Any
Per-segment champion MAPE bar chart. Requires matplotlib.
RollforwardWorkflowResult
dataclass
Workflow status and selected Rollforward model information.
summary() -> pd.DataFrame
One-row DataFrame of portfolio KPIs (total balance, champion, etc.).
plot(**kwargs: Any) -> Any
Forecast-vs-actual chart already written to output_dir. Requires matplotlib.
Rollforward
is_ready_to_model() -> bool
Quick pre-flight: no critical data issues and sufficient MOB history (>=18).
run(*, mode: RollforwardRunMode = 'model', output_dir: Path | str | None = None, holdout_months: int = 6, min_train_months: int = 12, step_months: int = 1, variants: list[str] | None = None, monitor_thresholds: dict[str, float] | None = None, segment: str | None = None, strict: bool = False) -> RollforwardResult | RollforwardWorkflowResult
Run the rollforward workflow in-memory (model) or with artifacts (workflow).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
RollforwardRunMode
|
|
'model'
|
output_dir
|
Path | str | None
|
Required when |
None
|
holdout_months
|
int
|
Final months reserved for holdout evaluation. |
6
|
min_train_months
|
int
|
Minimum historical months required for training. |
12
|
step_months
|
int
|
Backtest step size. |
1
|
variants
|
list[str] | None
|
Optional candidate variant names. |
None
|
monitor_thresholds
|
dict[str, float] | None
|
Optional KPI threshold overrides. |
None
|
segment
|
str | None
|
Optional single segment to model. |
None
|
strict
|
bool
|
Whether warnings should fail validation. |
False
|
Returns:
| Type | Description |
|---|---|
RollforwardResult | RollforwardWorkflowResult
|
class: |
RollforwardResult | RollforwardWorkflowResult
|
class: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
readiness(*, output_dir: Path | str, holdout_months: int = 6, min_train_months: int = 6, segment: str | None = None, strict: bool = False, scoring_config: ReadinessConfig | None = None, weights: Mapping[str, float] | None = None) -> ReadinessRunResult
Generate a rollforward readiness report and emit its artifacts.
Readiness uses a distinct session and scoring configuration from
:meth:run, including a lower default min_train_months.
build_facade_result(session: RollforwardWorkflowSessionResult) -> RollforwardResult
Translate a workflow session result into a Rollforward facade result.
build_rollforward_run_summary(*, surface: RollforwardResultSurface, status: str, issue_count: int = 0, max_mob: int | None = None, champion: str | None = None, challengers: Sequence[str] = (), promotion_reason: str | None = None, output_dir: Path | None = None, details: Mapping[str, Any] | None = None, is_production_ready: bool | None = None) -> RollforwardRunSummary
Build a canonical rollforward run summary from surface-specific inputs.
normalize_rollforward_operational_status(status: str, *, issue_count: int = 0, is_production_ready: bool | None = None) -> RollforwardOperationalStatus
Map surface-specific statuses into a shared pass/attention/blocker vocabulary.
rollforward_run_summary_payload(summary: RollforwardRunSummary) -> dict[str, Any]
Return a JSON-friendly payload for a shared rollforward run summary.
run(df: pd.DataFrame, **kwargs) -> RollforwardResult
Convenience one-liner: initialize, run in-memory model mode, return result.
For artifact-emitting workflow runs or readiness reports, use the
:class:Rollforward object directly (.run(mode="workflow", ...) /
.readiness(...)) — those need an output_dir and have different
defaults, so they are not folded into this convenience function.
run_rollforward_workflow(df: pd.DataFrame, *, output_dir: Path, holdout_months: int = 6, min_train_months: int = 12, step_months: int = 1, variants: list[str] | None = None, monitor_thresholds: dict[str, float] | None = None, amtloan_col: str = 'amtloan', segment: str | None = None, strict: bool = False) -> RollforwardWorkflowResult
Run the canonical monthly Rollforward workflow and emit artifacts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
Aggregated monthly flow data. |
required |
output_dir
|
Path
|
Directory for normalized data, diagnostics, forecasts, and committee-ready artifacts. |
required |
holdout_months
|
int
|
Number of final months reserved for holdout evaluation. |
6
|
min_train_months
|
int
|
Minimum historical months required for training. |
12
|
step_months
|
int
|
Backtest step size. |
1
|
variants
|
list[str] | None
|
Optional candidate variant names. |
None
|
monitor_thresholds
|
dict[str, float] | None
|
Optional KPI threshold overrides. |
None
|
amtloan_col
|
str
|
Original-loan-amount column used by contract checks. |
'amtloan'
|
segment
|
str | None
|
Optional single segment to model. |
None
|
strict
|
bool
|
Whether warnings should fail validation. |
False
|
Returns:
| Type | Description |
|---|---|
RollforwardWorkflowResult
|
Workflow result with status, output directory, champion, and |
RollforwardWorkflowResult
|
challengers. |
Examples:
>>> from tempfile import TemporaryDirectory
>>> import pandas as pd
>>> from cranalytics.rollforward import run_rollforward_workflow
>>> rows = [
... {"segment_id": "prime", "month_on_book": mob, "payments": 100.0,
... "chargeoffs": 5.0, "outstanding_balance": 2000.0 - mob * 100,
... "amtloan": 2000.0}
... for mob in range(1, 19)
... ]
>>> with TemporaryDirectory() as output_dir:
... result = run_rollforward_workflow(pd.DataFrame(rows), output_dir=output_dir)
... result.status in {"ok", "data_issues", "insufficient_data"}
True
generate_rollforward_readiness_report(data: pd.DataFrame, *, output_dir: Path, holdout_months: int = 6, min_train_months: int = 6, segment: str | None = None, amtloan_col: str = 'amtloan', strict: bool = False, scoring_config: ReadinessConfig | None = None, weights: Mapping[str, float] | None = None) -> ReadinessRunResult
Generate Rollforward readiness report artifacts from a rollforward frame.
DataFrame-first, matching the rest of the library. File reading is the
caller's (or the CLI's) responsibility. Thin shim over
:meth:Rollforward.readiness.
Rollforward Contract
The contract module owns reusable validation for aggregated monthly flow data. Use it when integrating a new source or diagnosing alias resolution.
cranalytics.rollforward._contract
Public input-contract helpers for the Rollforward workflow.
RollforwardContractResult
dataclass
Bases: IssueTableResultMixin
Normalized rollforward data plus collected contract issues.
normalized_df(*, segment: str | None = None) -> pd.DataFrame
Return normalized rollforward data, optionally filtered to one segment.
amtloan_series(*, segment: str | None = None) -> pd.Series | None
Return resolved denominator series, optionally filtered to one segment.
amtloan_map(*, segment: str | None = None) -> dict[str, float]
Return resolved denominators as a segment->value mapping.
validate_rollforward_input_contract(df: pd.DataFrame, *, amtloan_col: str = 'amtloan', strict: bool = False) -> RollforwardContractResult
Normalize columns, resolve aliases, and collect rollforward data issues.
Rollforward Backtest
Backtest helpers compare candidate Rollforward variants over historical holdouts. Use these lower-level functions when you need custom evaluation control beyond the workflow boundary.
cranalytics.rollforward._backtest
Backtesting helpers for Rollforward workflow variants.
run_rollforward_backtest_sweeps(df: pd.DataFrame, *, variants: list[str] | None = None, holdout_horizons: tuple[int, ...] = (3, 6), min_train_months: int = 12, step_months: int = 1, amtloan_by_segment: pd.Series | None = None, amtloan_col: str = 'amtloan') -> pd.DataFrame
Run rolling OOT backtests across configured rollforward variants.
summarize_rollforward_variant_performance(results: pd.DataFrame) -> pd.DataFrame
Aggregate split-level rollforward backtest results to one row per variant.
select_rollforward_champion_and_challengers(summary: pd.DataFrame, *, benchmark_variant: str = 'baseline_flat_last_hazard', challenger_count: int = 2) -> dict[str, Any]
Select a champion variant subject to baseline promotion rules.