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), givingbeta_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, feconvention (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_feis 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.