Skip to content

Commit 5459463

Browse files
matthieugomezclaude
andcommitted
Guard HC2/HC3 standard errors against fixed effects
HC2/HC3 compute leverage from the partialled-out (demeaned) regressors only, omitting the absorbed fixed-effect contribution to leverage. This silently understates leverage and yields anti-conservative standard errors whenever fe() is used. Throw an informative ArgumentError for the combination, mirroring the existing IV guard (HC2/HC3 are likewise rejected for IV), and point users to Vcov.robust() (HC1) or Vcov.cluster(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 7bde4e4 commit 5459463

1 file changed

Lines changed: 7 additions & 0 deletions

File tree

src/fit.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ function StatsAPI.fit(::Type{FixedEffectModel},
118118
has_iv = formula_iv != FormulaTerm(ConstantTerm(0), ConstantTerm(0))
119119
formula, formula_fes = parse_fe(formula)
120120
has_fes = formula_fes != FormulaTerm(ConstantTerm(0), ConstantTerm(0))
121+
# HC2/HC3 compute leverage from the partialled-out (demeaned) regressors only, which
122+
# omits the absorbed fixed-effect contribution to leverage. The resulting standard
123+
# errors are silently anti-conservative, so guard against the combination (mirroring
124+
# the IV guard, where HC2/HC3 are likewise rejected).
125+
if has_fes && vcov isa Vcov.RobustCovariance && vcov.correction (:hc2, :hc3)
126+
throw(ArgumentError("$(uppercase(string(vcov.correction))) standard errors are not supported with fixed effects, because the leverage correction does not account for the absorbed fixed effects. Use Vcov.robust() (HC1) or Vcov.cluster(...) instead."))
127+
end
121128
# when save = :fe but there are no fixed effects in the formula, don't save fixed effects
122129
save_fes = save (:fe, :all) && has_fes
123130
has_weights = weights !== nothing

0 commit comments

Comments
 (0)