# Chronological applicant and thin-file development

Run `examples/retail_development.py`; `run(data=..., verify_reference=False)` (R: `run_retail_development(data=..., verify_reference=FALSE)`) accepts the complete documented JSON structure in `datasets/retail_development.json`. Every model is fitted from those supplied records. The example concerns one unsecured installment product, with a declared pooled applicant population; it does not establish a universal retail model.

Four disjoint synthetic applicant vintages contain 64 people each. The 2016 and 2018 vintages train the models, 2020 calibrates them, and 2022 provides an untouched test. All features are known before application. A later revision is excluded. A recent funded but immature application remains unlabeled; rejected and offered-but-not-taken-up applications have no invented own-contract outcome.

The two risk cells have observed default frequencies 1/4 and 3/4. A separate selection instrument changes funding from 1/2 to 3/4. The scorecard, forward stepwise model and monotone spline are fitted on observed training outcomes; logistic calibration uses only the calibration vintage. The spline has two observed endpoint values: its intermediate shape is constrained, not evidence of a learned nonlinear relationship. Held-out funded Brier loss is 3/16 and AUC is 3/4 by independent cell counting.

Selection nuisance models use a genuinely forward 2016-to-2018 fold. Warmup rows have zero target weight. IPW effective sample size is 38.4; the AIPW population estimate is 1/2 under the explicitly illustrated missing-at-random assumption. Unrestricted population bounds are [20/64,44/64]. Fuzzy augmentation and parceling retain hypothetical outcome roles. Joint selection uses caller-fixed correlation zero by default; `full_profiles=True` also fits -0.3 and +0.3 sensitivity profiles. Correlation is an assumption, not identified by these data. A deterministic zero-overlap example returns `POSITIVITY_FAILURE`.

The raw application PD target is the potential own contract after first draw. To evaluate observed funded performance, the already locked application forecast is republished at actual first draw without refitting or adding information. The comparison explicitly targets the funded subset; it cannot establish calibration for rejected applicants. A separately supplied pseudo evaluation row is excluded. The validation acceptance criterion was declared before the test period. Passing the synthetic algebraic check is not regulatory approval.

Thin-file inputs include a genuine bureau no-hit and a stale report, transaction coverage, borrowing and own-account transfers, and three overlapping income evidence sources. Documentary salary 100 is selected once; borrowing 1000 and duplicate declarations are not income. The Firth model uses the same training vintage; endpoint predictions have the independent Jeffreys half-count values 21/82 and 61/82. Hierarchical calibration uses separate calibration data and explicit pre-application bureau strata. An unseen group receives logistic-normal marginal prediction, independently checked by numerical integration. A cashflow ratio outside fitted support produces no risk prediction. Bureau absence is not zero debt or automatic rejection.

Pool definitions are fitted on training outcomes and estimated on the calibration cohort. Open default workouts leave LGD/EAD information missing rather than asserting zero loss. Thin-file population bounds describe synthetic strata, not an individual rejected person's PD.

Default tests execute a small real pipeline with analytical cell oracles. Backend optimizers can differ slightly; fitted artifacts and diagnostics remain unrounded. Cross-language verification must distinguish economic estimates, local content bindings and replay of the same frozen artifact. Full sensitivity profiles are optional and do not replace the fast tests.

For faster native package checks, `include_holdout=False` (R: `FALSE`) omits only construction of the five complete holdout report bundles; real estimation, selection analysis, thin-file cases and pools still run. The full installed example always includes holdout validation. Set `CREDITRATINGSYSTEM_EXTENDED_TESTS=true` to include it in the native test as well. Python defaults also include a negative test that changes only test outcomes and confirms all fitted models and calibrators remain identical.
