Covenant

Rendered unchanged from reports/model_eval.md. The demo serves the active model below (LightGBM, version 6).

Model card: 12-month distress model (feature set v1)

Generated by python -m tripwire_ml train on 2026-10-26. Data as of 2026-10-27. Model versions: LightGBM 6 (active), logistic 5, Altman 4.

Task

For each SEC filer at each quarter end T: will the company start a bankruptcy case (8-K Item 1.03, text-checked) within (T, T + 12 months]? Features use only data filed on or before T. Companies already in bankruptcy at T are excluded. Banks, insurers, REITs, funds and shells (SIC 6000-6799) are excluded.

Data

SplitAs-of datesRowsCompaniesPositivesBase rate
train2011-03-31 to 2018-12-31170,5508,59714920.9%
validation2020-03-31 to 2020-12-3118,3864,9201360.7%
test2021-12-31 to 2025-09-3077,8915,9388371.1%

Label windows of different splits never overlap (as-of dates in 2019 and early 2021 are left out). The test split was used only for these numbers, never for tuning.

Results on the test split

ModelPR-AUCROC-AUCRecall @ top 5%Recall @ top 10%Precision @ top 5%BrierMedian lead (months)Bankruptcies flagged
Altman Z'' (rule)0.0190.7324.3%13.3%0.9%0.01067.215/211
Logistic regression0.0510.82434.4%50.5%7.4%0.010613.5115/211
LightGBM0.0980.88945.0%65.0%9.7%0.010214.2151/211

Base rate on test: 1.1% (a random ranking scores PR-AUC ≈ 0.011). LightGBM PR-AUC is 5.1x the Altman baseline.

Recall @ top k%: share of test bankruptcies whose company ranked in the riskiest k% on that quarter end. Lead time: for bankruptcies starting from 2023-01-01 (so a year of test-period history exists), months between the first quarter end on which the company was in the high tier (top 5%) and the filing; looks back at most 24 months.

Calibration (LightGBM, test)

DecileMean predictedObserved rateRows
10.0%0.0%7,789
20.0%0.0%7,789
30.0%0.1%7,789
40.0%0.2%7,789
50.0%0.0%7,789
60.1%0.2%7,789
70.3%0.5%7,789
80.4%1.1%7,789
91.1%1.6%7,789
105.2%6.9%7,790

Rolling-origin backtest (PR-AUC by test year)

Train on as-of dates up to the end of Y-2, test on as-of dates in Y, fixed hyperparameters.

YearRowsPositivesBase rateAltmanLogisticLightGBM
201523,1543011.3%0.0180.0750.080
201621,9152531.2%0.0150.0590.104
201720,5821560.8%0.0140.0830.065
201819,5951931.0%0.0150.0660.085
201918,9912781.5%0.0200.0810.157
202018,3861360.7%0.0100.0930.132
202119,213680.4%0.0050.0280.042
202220,0062181.1%0.0200.0620.103
202320,0192901.4%0.0260.0850.137
202419,2352101.1%0.0210.0620.123

Top drivers (mean |SHAP|, LightGBM, test)

| Feature | Mean |SHAP| | |---|---| | Company size (log total assets) | 0.360 | | Total liabilities / total assets | 0.314 | | Free-cash-flow margin | 0.309 | | Return on assets | 0.281 | | EBIT / total assets | 0.280 | | Working capital / total assets | 0.223 | | Director / officer departures (8-K 5.02), last 12 months | 0.206 | | Interest coverage (EBIT / interest) | 0.193 | | Change in total assets, year over year | 0.179 | | Cash / total assets | 0.171 | | Revenue trend, last 4 quarters | 0.156 | | Gross margin | 0.152 | | Debt / total assets | 0.144 | | Book equity / total liabilities | 0.128 | | Revenue scale (log trailing-12-month revenue) | 0.124 |

Label quality

2,716 Item 1.03 8-Ks of in-scope companies were classified from their text into 1,400 bankruptcy cases.

Filing classFilings
petition1,227
follow_up1,030
no_bankruptcy_language130
unclear126
no_item_section93
subsidiary_petition41
other_entity35
receivership34
Case started byCases
petition1,164
follow_up159
unclear50
receivership27

Hand review of a fresh random sample (not used for rule changes): 18 of 20 petition filings were the filer's own bankruptcy (errors: a parent filed without this registrant); about half of unclear filings were new insolvencies. Estimated label precision ≈ 88%. Bankruptcies never reported on an Item 1.03 8-K are missing (recall is not measured).

Leakage check

Features are recomputed after deleting every filing, restatement and macro release dated after the as-of date; the output must be identical. It runs in the unit tests (synthetic data, including a planted leak that must be caught) and on real data during every dataset build (results in raw.ingest_runs, source ml_dataset).

Known limitations