SPB Git

spb/wp29_uqo

Public

# F2-dev-01 — Two-way fixed-effects slope with firm-clustered uncertainty

# Question

Estimate β in y_it = a_i + g_t + β x_it + u_it, the within-firm, within-year association of y with x. Firm effects a_i and year effects g_t are unrestricted. Inference allows arbitrary dependence of u_it within a firm over time and assumes independence across firms. The data are simulated.

# Data and exclusions

data/firm_panel.csv (SHA-256 ae54378f…72e0) has 1200 rows (n_input_rows). It is a balanced panel: 100 firms (n_firms) × 12 years, 2008–2019 (n_years). There are no missing values, no duplicate rows and no duplicate firm–year keys, so data_issues is empty. The exclusion rules (missing values, exact duplicates, conflicting firm–year keys) removed 0 rows, so n_analysed = 1200 (see out/exclusions.csv). Full audit: out/state/data_audit.md.

# Method

  • Baseline: pooled OLS of y on x with an intercept and no fixed effects (beta_pooled).
  • Main estimate: two-way fixed effects estimated by least-squares dummy variables (LSDV), i.e. OLS of y on x plus firm and year dummies, 112 parameters in total (n_params_lsdv). As a cross-check, the slope from two-way within-demeaning (which is exact because the panel is balanced) matches to within 1e-8 (beta_fe_within_check).
  • se_conventional: the classical homoskedastic OLS standard error from the LSDV regression, with N − K = 1088 degrees of freedom.
  • se_cluster: a cluster-robust sandwich standard error clustered by firm_id, with the CR1 small-sample factor G/(G−1)·(N−1)/(N−K). Here K counts all 112 LSDV parameters (Stata areg convention), which is the more conservative choice.
  • 95% CI: beta_fe ± t(0.975, G−1 = 99) × se_cluster. The critical value is ci_critical_value_t_Gminus1 = 1.984.
  • The method uses no randomness (random_seed = null).

# Results

  • Pooled OLS baseline: beta_pooled = 1.268 (conventional SE 0.028, baseline_se_pooled_conventional).
  • TWFE estimate: beta_fe = 0.6045.
  • The TWFE slope is about half the pooled slope. This pattern fits firm and/or year effects that are positively correlated with x and inflate the naïve estimate. The difference does not by itself identify which effects cause it.

# Uncertainty

  • se_conventional = 0.0326; se_cluster = 0.0471. The ratio is 1.44 (se_ratio_cluster_to_conventional), which fits positive within-firm dependence of the residuals and x over time. The conventional SE therefore understates uncertainty.
  • 95% firm-clustered CI: [beta_ci_low, beta_ci_high] = [0.511, 0.698]. It excludes 0 and also excludes the pooled estimate 1.268.
  • Sensitivity to the degrees-of-freedom convention: if the firm dummies are not counted in K, because they are nested within clusters (xtreg, fe convention), the clustered SE is 0.0451 (se_cluster_sensitivity_firmFE_not_counted). With no small-sample correction (CR0) it is 0.0446 (se_cluster_CR0_no_correction). The conclusions do not change.

# Limitations and open issues

  • β is a causal effect only under strict exogeneity of x given a_i and g_t; with simulated data, β is simply the parameter of the stated model.
  • Cluster-robust inference relies on asymptotics in the number of firms. G = 100 is a reasonable number of clusters, but the SE depends slightly on the small-sample convention (see Uncertainty). I report the conservative LSDV-K version as the primary result.
  • I found no data problems, and the task was completed in full (feasibility = "complete").
Files · main
Menu

Theme