Skip to content

Commit 1a309c4

Browse files
igerberclaude
andcommitted
Fix universal base period skip and comparison-cohort REGISTRY docs
- Skip reference period (t == g-1-anticipation) in universal mode, matching CallawaySantAnna behavior. Event-study mixin injects synthetic reference row with effect=0. - Update REGISTRY comparison-group rule to match code: uses max(t, base_period) + anticipation for notyettreated threshold. - Add TODO.md entries for deferred P2 items (CSV fixtures, covariate parity, group-effect WIF). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4b7e440 commit 1a309c4

3 files changed

Lines changed: 19 additions & 3 deletions

File tree

TODO.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ Deferred items from PR reviews that were not addressed before merge.
5959
| TripleDifference power: `generate_ddd_data` is a fixed 2×2×2 cross-sectional DGP — no multi-period or unbalanced-group support. | `prep_dgp.py`, `power.py` | #208 | Low |
6060
| Survey design resolution/collapse patterns inconsistent across panel estimators — extract shared helpers for panel-to-unit collapse, post-filter re-resolution, metadata recomputation | `continuous_did.py`, `efficient_did.py`, `stacked_did.py` | #226 | Low |
6161
| TROP: `fit()` and `_fit_global()` share ~150 lines of near-identical data setup. Extract shared helpers to eliminate cross-file sync risk. | `trop.py`, `trop_global.py`, `trop_local.py` || Low |
62+
| StaggeredTripleDifference R cross-validation: CSV fixtures not committed (gitignored); tests skip without local R + triplediff. Commit fixtures or generate deterministically. | `tests/test_methodology_staggered_triple_diff.py` | #245 | Medium |
63+
| StaggeredTripleDifference R parity: benchmark only tests no-covariate path (xformla=~1). Add covariate-adjusted scenarios and aggregation SE parity assertions. | `benchmarks/R/benchmark_staggered_triplediff.R` | #245 | Medium |
64+
| StaggeredTripleDifference: per-cohort group-effect SEs include WIF (conservative vs R's wif=NULL). Documented in REGISTRY. Could override mixin for exact R match. | `staggered_triple_diff.py` | #245 | Low |
6265

6366
#### Performance
6467

diff_diff/staggered_triple_diff.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,16 @@ def fit(
272272
gmm_weights_store: Dict[Tuple, Dict] = {}
273273

274274
for g in treatment_groups:
275-
for t in time_periods:
275+
# In universal mode, skip the reference period (t == g-1-anticipation)
276+
# so it's omitted from GT estimation. The event-study mixin injects
277+
# a synthetic reference row with effect=0, matching CS behavior.
278+
if self.base_period == "universal":
279+
universal_base = g - 1 - self.anticipation
280+
valid_periods = [t for t in time_periods if t != universal_base]
281+
else:
282+
valid_periods = time_periods
283+
284+
for t in valid_periods:
276285
base_period_val = self._get_base_period(g, t)
277286
if base_period_val is None:
278287
continue

docs/methodology/REGISTRY.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,7 +1294,10 @@ This sign convention matches both the paper's Equation 4.1 and the existing
12941294
`TripleDifference` decomposition (DDD = DiD_3 + DiD_2 - DiD_1 with subgroups
12951295
4=G1P1, 3=G1P0, 2=G0P1, 1=G0P0).
12961296

1297-
Valid comparison groups: `G_c = {g_c : g_c > max(g, t)}`, including never-enabled (S=0).
1297+
Valid comparison groups: for `control_group="nevertreated"`, only the never-enabled
1298+
cohort (S=0). For `control_group="notyettreated"`, `G_c = {g_c : g_c > max(t, base_period)
1299+
+ anticipation}`, plus never-enabled. The anticipation-adjusted threshold ensures cohorts
1300+
within the anticipation window are excluded from controls.
12981301

12991302
*With covariates / doubly robust (DR, recommended):*
13001303

@@ -1396,7 +1399,8 @@ confidence bands (sup-t) for event study.
13961399
- [x] Panel data with (unit, time, enabling-group S, eligibility Q, outcome Y)
13971400
- [x] Three comparison sub-groups per (g, g_c): (S=g, Q=0), (S=g_c, Q=1), (S=g_c, Q=0)
13981401
- [x] Individual comparison cohorts, never pooled — combined via GMM weights
1399-
- [x] Comparison groups satisfy g_c > max{g, t}
1402+
- [x] Comparison groups satisfy g_c > max(t, base_period) + anticipation (notyettreated)
1403+
or g_c = never-enabled only (nevertreated)
14001404
- [x] Doubly robust: consistent if either propensity or outcome model correct (per component)
14011405
- [x] GMM-optimal weighting via closed-form inverse-variance formula
14021406
- [x] Event-study aggregation with cohort-share weights (via CS mixin)

0 commit comments

Comments
 (0)