# F2-dev-01 — Two-way fixed-effects slope with firm-clustered uncertainty ## Question What is the within-firm, within-year slope β of y on x in the model y_it = a_i + g_t + β x_it + u_it? Its uncertainty should allow arbitrary dependence of u_it within a firm over time. ## Data and exclusions Input: `data/firm_panel.csv` (simulated). There are 1200 rows (`n_input_rows`), 100 firms (`n_firms`) and 12 years, 2008–2019 (`n_years`). The panel is balanced (`panel_balanced`). There are no missing values, no duplicate rows and no duplicate firm–year keys. The SHA-256 matches the bundle (`input_sha256`). The exclusion rules in `out/exclusions.csv` removed nothing, so 1200 observations were analysed (`n_analysed`). `data_issues` is empty. ## Method - Baseline: pooled OLS of y on x with an intercept and no fixed effects (`beta_pooled`). - Main estimate: OLS with a dummy for each firm and each year (LSDV). This gives `beta_fe`. A Frisch–Waugh check confirms the slope. - Conventional SE: homoskedastic OLS standard error from the LSDV fit. It has 1088 residual degrees of freedom (`df_resid_conventional`). - Clustered SE: CR1 sandwich clustered by `firm_id`, built from the scores of the FE-residualised x times the FE residuals. The small-sample factor is G/(G−1)·(N−1)/(N−K) (`cluster_small_sample_factor`). Firm effects sit inside the clusters, so they are not counted in K; this follows the Stata `xtreg, fe vce(cluster)` and `reghdfe` convention. So K = intercept + 11 year effects + slope = 13. - 95% CI: `beta_fe` ± t(G−1 = 99, 0.975) × `se_cluster`. The critical value is 1.984 (`ci_t_critical_df_G_minus_1`). - No randomness is involved (`random_seed` = null). ## Results - Pooled OLS slope: `beta_pooled` = 1.268. - Two-way FE slope: `beta_fe` = 0.604. - The two estimates differ by a factor of about 2. This means the firm and/or year effects are correlated with x, so the pooled estimate is confounded by them. ## Uncertainty - `se_conventional` = 0.0326. - `se_cluster` = 0.0451, about 1.38 times the conventional SE. This suggests positive within-firm dependence in the residuals and/or x. - 95% CI from the clustered SE: [`beta_ci_low`, `beta_ci_high`] = [0.515, 0.694]. - Sensitivity to the degrees-of-freedom convention: - With no correction (CR0), `se_cluster_unadjusted_CR0` = 0.0446. - Counting all 112 parameters, including firm effects, in K (the statsmodels LSDV default) gives `se_cluster_allK_dfadj` = 0.0471 (= `se_cluster_statsmodels_lsdv`). - None of these choices changes the conclusion. ## Limitations and open issues - β is causal only if x is strictly exogenous once the two sets of fixed effects are controlled for. The data cannot test this. - Clustered inference relies on asymptotics in the number of firms. 100 clusters is usually enough, but it is not exact. - The choice of small-sample correction is a convention (see Uncertainty); reasonable choices move the SE by about ±5%. - The data are simulated.