# PD and LGD development from linked credit records

Run `examples/model_development.py`, or call `run(data=..., retail_data=..., verify_reference=False)` with your own records following the paired JSON contracts. In R use `run_model_development(data=..., retail_data=..., verify_reference=FALSE)`. The packaged example uses `model_development.json` and the actual applicant cohorts in `retail_development.json`. It executes that upstream component, rather than treating a stored prediction or test output as a newly fitted model.

The same facility identifiers link applications, funding, dated default events, actual recovery cashflows and workout episodes. Canonical tables are validated and funded first-default observation windows are independently rebuilt. A closed target must reconcile to EAD less net recovery cash and any explicitly valued cured claim. Cure value is not counted again as cash. All cash and claim values in the closed-loss reference use an explicitly undiscounted EUR convention; this is not an imposed regulatory discount rate.

The 2016/2018 observed applicant cohorts train the models and preprocessing. The 2020 cohort supplies logistic, isotonic and grade calibration. The untouched 2022 cohort supplies comparison outcomes. The model manifest binds both each estimator and its preprocessor. Forward selection from the upstream component is preserved; additional GLM, ridge and Firth candidates are genuinely fitted. Grade cutpoint zero is fixed before calibration. Fitted isotonic and grade PDs are actually used in the held-out comparison, not merely printed as unused estimates.

The observed funded synthetic risk cells have probabilities 1/4 and 3/4. Their independent Brier oracle is 3/16. The Spiegelhalter numerator is zero and variance 15/8 under its explicitly separate independent-Bernoulli reference assumption. A second count test uses supplied shared macro innovations and correlation 0.25. The eight independent standard-normal draws were generated once and exported to both languages. Null counts are [20,22,31,21,10,15,26,22], giving the finite-simulation upper-tail value 7/9. Eight draws provide only a coarse software reference; they do not establish empirical macro dependence, test power or a reliable production rejection threshold.

Forty closed training workouts fit a fractional mean model and a structural zero/one inflated beta model. They are intercept-only models for the declared synthetic workout population. The mixture has zero/one masses 0.3 each and interior mass 0.4, with mean loss 0.5. Independent references check the fractional robust covariance and the beta precision likelihood equation. Nineteen closed test workouts have mean observed loss 9/19, so a 0.5 forecast has count-weighted bias 1/38. The twentieth remains open and has no invented final outcome.

A separate prior-known residual-terminal model is fitted to the same 2016/2018 workout landmarks with a February 2018 censoring cutoff. Duration draws are generated independently of the assigned synthetic recovery amounts. A real cure/positive-payout hurdle and censored Weibull AFT fit estimate the remaining gross terminal payout. The modeling contract assumes censoring independence and conditional independence of resolution timing and payout given the recorded landmark covariates. These are scoped assumptions, not empirical conclusions. The lognormal positive-payout model can assign values above exposure; no silent LGD floor or cap is applied.

For the open 2022 claim, the already received 10 is included once; remaining exposure is 90. Conditional survival from the valuation date determines the future-resolution masses. Supplied discount factors are 0.9 and 0.8 inside the grid and 0.7 beyond it. Removing the explicit tail-value assumption leaves final LGD unavailable while retaining the within-grid estimate and unresolved probability. The valuation is an estimate and never becomes a closed validation label.

The validation report combines the actual held-out PD comparison and closed-only LGD backtest under criteria dated before the test period. Statistical test diagnostics are reported separately in their native result schemas. A passing synthetic reference report is neither empirical approval nor regulatory certification.

Default Python tests cache one real full pipeline. Default R tests fit the loss models and test the censored Weibull profile-score root, conditional survival valuation and closed-cash reconciliation. Full R PD/report composition is also tested with `CREDITRATINGSYSTEM_EXTENDED_TESTS=true` and in the complete installed example. Independent optimizers retain their own diagnostics and unrounded estimates; same-origin frozen artifacts must replay across both languages.
