Skip to content

Commit 53cfd5d

Browse files
igerberclaude
andcommitted
Clear analytical event_study_vcov when bootstrap overwrites event-study SEs
Prevents HonestDiD from mixing analytical IF-based VCV with bootstrap SEs on bootstrap-fit CallawaySantAnna results. When n_bootstrap>0, the event_study_vcov is set to None so HonestDiD falls back to diagonal from the bootstrap SEs (consistent variance path). Add regression test: bootstrap CS → HonestDiD asserts vcov is None. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3b405b7 commit 53cfd5d

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

diff_diff/staggered.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1771,8 +1771,12 @@ def fit(
17711771
)
17721772

17731773
# Store results
1774-
# Retrieve event-study VCV from aggregation mixin (Phase 7d)
1774+
# Retrieve event-study VCV from aggregation mixin (Phase 7d).
1775+
# Clear it when bootstrap overwrites event-study SEs to prevent
1776+
# HonestDiD from mixing analytical VCV with bootstrap SEs.
17751777
event_study_vcov = getattr(self, "_event_study_vcov", None)
1778+
if bootstrap_results is not None and event_study_vcov is not None:
1779+
event_study_vcov = None
17761780

17771781
self.results_ = CallawaySantAnnaResults(
17781782
group_time_effects=group_time_effects,

tests/test_honest_did.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,30 @@ def test_replicate_weight_uses_diagonal_fallback(self):
12801280
# event_study_vcov should be None (diagonal fallback for replicate designs)
12811281
assert cs_result.event_study_vcov is None
12821282

1283+
def test_bootstrap_fit_clears_analytical_vcov(self):
1284+
"""Bootstrap CS results should NOT carry analytical event_study_vcov."""
1285+
from diff_diff import CallawaySantAnna, generate_staggered_data
1286+
1287+
data = generate_staggered_data(n_units=100, n_periods=5, seed=42)
1288+
cs_result = CallawaySantAnna(n_bootstrap=49, seed=42).fit(
1289+
data,
1290+
"outcome",
1291+
"unit",
1292+
"period",
1293+
"first_treat",
1294+
aggregate="event_study",
1295+
)
1296+
1297+
# event_study_vcov should be None when bootstrap is used
1298+
# (prevents HonestDiD from mixing analytical VCV with bootstrap SEs)
1299+
assert cs_result.event_study_vcov is None
1300+
1301+
# HonestDiD should still work (falls back to diagonal from bootstrap SEs)
1302+
honest = HonestDiD(method="relative_magnitude", M=1.0)
1303+
h_result = honest.fit(cs_result)
1304+
assert np.isfinite(h_result.original_se)
1305+
assert h_result.original_se > 0
1306+
12831307

12841308
# =============================================================================
12851309
# Tests for Visualization (without matplotlib)

0 commit comments

Comments
 (0)