SPB Git

spb/wp29_uqo

Public

# 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.
Files · main
Menu

Theme