# F2-dev-01 — Two-way fixed-effects slope with firm-clustered SE ## Question Estimate β in y_it = a_i + g_t + β x_it + u_it (firm and year effects unrestricted), with uncertainty robust to arbitrary within-firm dependence over time. ## Data and exclusions `data/firm_panel.csv` (synthetic), 1200 rows read (`n_input_rows`). Balanced panel: 100 firms (`n_firms`) × 12 years 2008–2019 (`n_years`). No missing values, non-finite values, duplicate rows or duplicate firm–year keys; the three screening steps in `out/exclusions.csv` removed 0 rows, so `n_analysed` = 1200. `data_issues` is empty. Full audit: `out/state/data_audit.md`. ## Method - Baseline: pooled OLS of y on x with intercept (`beta_pooled`). - Two-way FE: OLS with a full set of firm dummies and year dummies (LSDV; 112 parameters, `n_parameters_lsdv`), giving `beta_fe`. Cross-checked against the two-way within (demeaning) estimator and statsmodels (identical to ~1e-15). - Conventional SE: homoskedastic OLS variance with N−K = 1088 residual degrees of freedom (`se_conventional`). - Cluster SE: CR1 sandwich clustered by `firm_id`, finite-sample factor G/(G−1)·(N−1)/(N−K) with K = 12 (x plus 11 year dummies); firm effects are nested in clusters and not counted, the reghdfe / `xtreg, fe` convention (`se_cluster`). - 95% CI: `beta_fe` ± t(0.975, G−1 = 99) × `se_cluster` (`ci_critical_value_t_Gminus1` = 1.984). - No randomness (`random_seed` = null). ## Results - `beta_pooled` = 1.268 (naïve baseline). - `beta_fe` = 0.6045. - `se_conventional` = 0.0326; `se_cluster` = 0.0450. - 95% CI from the clustered SE: [`beta_ci_low`, `beta_ci_high`] = [0.515, 0.694]. - `feasibility` = "complete". The within-firm, within-year slope is about half the pooled slope. This means a large part of the pooled association comes from firm and/or year effects that are correlated with x. ## Uncertainty The firm-clustered SE is 1.38 times the conventional SE (`se_cluster_ratio_to_conventional`). This is consistent with within-firm serial dependence that the conventional SE ignores. The clustered SE changes only a little under other finite-sample conventions: - with no small-sample adjustment: 0.0446 (`se_cluster_alt_no_small_sample_adj`); - counting all 112 LSDV parameters in K, as statsmodels does: 0.0471 (`se_cluster_alt_K_all_dummies`). A normal-critical-value CI is [0.516, 0.693] (`ci_normal_low`, `ci_normal_high`). With G = 100 clusters, cluster-robust asymptotics should be reasonably reliable. ## Limitations and open issues - To read β as a causal effect, x must be strictly exogenous conditional on the firm and year effects. This cannot be tested with these data, so `beta_fe` is reported as a conditional association. - The choice of finite-sample correction for the clustered SE is a convention. The alternatives are reported above and differ by less than 5%. - The data are synthetic. No other limitations were found, and every required output was produced.