F1-conf-03 — Information-respecting analytic dataset for next-year default
Scientific question
Estimate the association between a firm's leverage at the end of year t and its default in year t+1, using only information that was available at the end of year t. The estimand is the coefficient on leverage in the linear-probability model default_next = a + b1·leverage + b2·cash_ratio + b3·log_sales + e estimated by OLS on the firm-years whose outcome is observed, with standard errors clustered by firm. The analytic dataset must contain only predictors whose values were known at the origin year.
Inputs
data/firm_panel.csv— simulated data (synthetic firm-year panel; not observed data), 300 firms, years 2016–2022, one intended row per firm-year. Columnsfirm_id,year,leverage,cash_ratio,log_sales,rating_2025,default_next; definitions, units and the date at which each field becomes known are indata/README.md(codebook). Empty cells mean the value is not observed. The extract may contain assembly errors.
Information-availability rules
- A variable may enter the model for origin year t only if its value would have been known at the end of year t (see the codebook's last column). Any variable that does not satisfy this rule must be excluded from the analytic dataset and listed in
variables_excluded. - Firm-years whose outcome
default_nextis not observed cannot be used for estimation and must be listed in the exclusion ledger; do not impute outcomes. - Use only
data/firm_panel.csv.
Required outputs
out/results.jsonwith the keys:
| key | type | unit | meaning |
|---|---|---|---|
task_id |
string | — | "F1-conf-03" |
n_analysed |
integer | firm-years | observations in the estimation sample |
n_firms |
integer | firms | distinct firms in the estimation sample |
predictors_used |
array of strings | — | column names entered as regressors (excluding the intercept) |
variables_excluded |
array of {"variable","reason"} | — | columns of the file deliberately not used as predictors and why |
beta_leverage |
number | probability points | OLS coefficient on leverage |
se_leverage_cluster |
number | — | standard error of beta_leverage clustered by firm_id |
r2 |
number | — | in-sample R² of the model |
default_rate |
number | — | baseline: share of firm-years with default_next = 1 in the estimation sample |
feasibility |
string | — | "complete", "partial" or "infeasible" |
feasibility_reason |
string or null | — | explanation if not complete |
data_issues |
array of {"issue","handling"} | — | every data problem detected and how it was handled (empty list if none) |
n_input_rows |
object | rows | {"firm_panel.csv": number of data rows read (excluding the header)} |
random_seed |
integer or null | — | seed used, if any |
out/analytic.csv— the estimation sample: one row per firm-year used, columnsfirm_id,year, the predictors used anddefault_next; exactlyn_analysedrows and no column that violates the information rule.out/exclusions.csv— the exclusion ledger with columnsstep,rule,n_before,n_after,n_removed,rationale; one row per step from the number of rows read ton_analysed(n_before − n_removed = n_afteron every row; each step'sn_beforeequals the previous step'sn_after). Column removals may be listed withn_removed = 0.out/report.mdwith the sections: Question; Data and exclusions; Method; Results; Uncertainty; Limitations and open issues.out/analysis.py— running~/wp29/venv/bin/python out/analysis.pyfrom the workspace root must regenerateout/results.json,out/analytic.csvandout/exclusions.csvfromdata/only, deterministically.out/claims.json— a list of the central claims of the report: [{"id": "C1", "text": "...", "results_keys": ["..."], "status": "supported"|"unsupported"|"not_evaluated", "caveat": "..."}].
Constraints
- No network access. Python:
~/wp29/venv/bin/python(numpy, pandas, scipy, statsmodels available). Do not modifydata/. - This task is designed to be completed in well under 20 minutes of work.