Commit 34a01c1
SpilloverDiD conley + survey + lag>0 via panel-block composition (Wave E.2 follow-up)
Extends the panel-aware stratified-Conley spatial sandwich (Wave E.2 cross-
sectional, PR igerber#474) to `conley_lag_cutoff > 0` by adding a within-PSU serial
Bartlett HAC term (Newey-West 1987 separable form). The composition
`meat = meat_spatial + meat_serial` has disjoint index sets, exactly matching
the no-survey panel-block decomposition at
`diff_diff.conley._compute_conley_meat`.
Methodology — documented synthesis of:
- Conley (1999) spatial-HAC
- Newey-West (1987) serial Bartlett kernel weights `(1 - |t-s|/(L+1))`
- Binder (1983) / Gerber (2026) Prop 1 stratified TSL on Wave D Gardner GMM
influence functions
Serial term uses per-period within-stratum centering (Binder TSL form,
matching the spatial helper); panel-wide per-stratum FPC (the serial sum is a
panel-level construct, so the cluster set is panel-wide); hardcoded Bartlett
serial kernel regardless of `conley_kernel` (mirrors `conley.py:951-965`);
panel-wide dense time codes for lag math (matches `conley.py:940` R deviation).
Supported surface — requires an effective PSU: either an explicit
`survey_design.psu` OR a `cluster=<col>` argument that gets injected as the
effective PSU per Wave E.1's `_inject_cluster_as_psu` routing. No-effective-PSU
survey designs (weights-only / strata-only WITHOUT a cluster fallback) raise
`NotImplementedError` post-resolution at `SpilloverDiD.fit` per
`feedback_no_silent_failures`: the pseudo-PSU = obs-index fallback would
silently zero the serial sum (each pseudo-PSU appears in exactly one period).
Routing the serial loop to `conley_unit` would mix IF allocators with the
spatial term and is queued as a follow-up.
Code changes:
- New sibling helper `_compute_stratified_serial_bartlett_meat` in
`diff_diff/two_stage.py` (T=1 short-circuit, three-mode singleton-stratum
branching with FPC inside the multi-PSU block to avoid divide-by-zero,
panel-wide mean for `lonely_psu='adjust'`, zeroed centering for
singleton-active-period cells so raw scores don't leak into the serial
Bartlett cross-products under unbalanced panels)
- Orchestrator `_compute_stratified_conley_meat` extended with
`conley_lag_cutoff` kwarg; spatial loop unchanged; serial helper called
after spatial loop when `L > 0`
- Dispatch in `_compute_gmm_corrected_meat` conley branch threads
`conley_lag_cutoff` through
- `spillover.py:2210` Wave E.2-era `NotImplementedError` gate for lag>0 +
survey deleted; replaced with post-resolution fail-closed gate that fires
only when `resolved_survey_fit.psu` is None AFTER cluster injection (so
the documented `cluster=<col>` injection surface continues to work)
Tests — 24 new methods across two classes
(`TestSpilloverDiDWaveE2FollowupConleySurveyLagCutoff` and
`TestSpilloverDiDWaveE2FollowupConleySurveyLagCutoffEventStudy`):
- `test_a` lag=0 strict bit-identity to shipped Wave E.2 meat
- `test_a2` lag=0 does NOT invoke serial helper (mock-spy)
- `test_b` lag=1 invokes serial helper exactly once (mock-spy)
- `test_c0` raw-vs-centered hand-check pins Binder TSL centering
- `test_c1`/`test_c2` hand-computation methodology anchors at L=1 and L=2
- `test_c3` AR(1) DGP serial inflation behavioral pin (rho=0.7, > 5%)
- `test_d` single-stratum lag=1 finite output
- `test_e` cross-stratum independence of serial term (partition + sum)
- `test_f` singleton-adjust + lag=1 no divide-by-zero
- `test_f2` all-singleton-remove + lag=1 returns zero meat
- `test_g` unbalanced panel + panel-wide dense time codes (hand-computed)
- `test_g2` lag > T-1 well-defined
- `test_h` singleton-active-period centering zeros (sparse-period regression)
- `test_j` no-survey panel-block conley unchanged after gate relaxation
- `test_k` replicate-weight rejection still fires
- `test_l` cluster + lag=1 + survey warn-and-use-PSU
- `test_m` fit-idempotency under lag=1 + survey
- `test_n`/`test_n2` no-effective-PSU survey + lag>0 raises NotImplementedError
- `test_n3` cluster-injected effective-PSU surface fits + matches explicit PSU
- `test_r` drift goldens at lag=1 vs lag=0 (ATT invariant, SE differs)
- `test_o`/`test_p`/`test_r` event-study mirror (both is_staggered branches)
Existing `test_j0_panel_conley_lag_cutoff_rejected_under_survey` (Wave E.2-era
gate-assertion) deleted.
Docs:
- REGISTRY `Variance (Wave E.2 follow-up)` subsection with documented-
synthesis framing + cross-references + effective-PSU restriction
- `spillover.rst` Wave E.2 follow-up stanza
- CHANGELOG `[Unreleased]` bullet
- `llms.txt` + `README.md` catalog entries updated
- `references.rst` adds Newey-West (1987)
- TODO row deleted (old deferral); new row added for the no-effective-PSU
follow-up tail
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1 parent 6c77137 commit 34a01c1
10 files changed
Lines changed: 1578 additions & 91 deletions
File tree
- diff_diff
- guides
- docs
- api
- methodology
- tests
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
106 | 106 | | |
107 | 107 | | |
108 | 108 | | |
109 | | - | |
| 109 | + | |
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
142 | | - | |
| 142 | + | |
143 | 143 | | |
144 | 144 | | |
145 | 145 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | | - | |
| 61 | + | |
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2197 | 2197 | | |
2198 | 2198 | | |
2199 | 2199 | | |
2200 | | - | |
2201 | | - | |
2202 | | - | |
2203 | | - | |
2204 | | - | |
2205 | | - | |
2206 | | - | |
2207 | | - | |
2208 | | - | |
2209 | | - | |
2210 | | - | |
2211 | | - | |
2212 | | - | |
2213 | | - | |
2214 | | - | |
2215 | | - | |
2216 | | - | |
2217 | | - | |
2218 | | - | |
2219 | | - | |
2220 | | - | |
2221 | | - | |
2222 | | - | |
2223 | | - | |
2224 | | - | |
2225 | | - | |
2226 | | - | |
2227 | | - | |
2228 | | - | |
2229 | | - | |
2230 | | - | |
| 2200 | + | |
| 2201 | + | |
| 2202 | + | |
| 2203 | + | |
| 2204 | + | |
| 2205 | + | |
| 2206 | + | |
| 2207 | + | |
| 2208 | + | |
| 2209 | + | |
| 2210 | + | |
| 2211 | + | |
| 2212 | + | |
| 2213 | + | |
| 2214 | + | |
| 2215 | + | |
| 2216 | + | |
2231 | 2217 | | |
2232 | 2218 | | |
2233 | 2219 | | |
| |||
3100 | 3086 | | |
3101 | 3087 | | |
3102 | 3088 | | |
| 3089 | + | |
| 3090 | + | |
| 3091 | + | |
| 3092 | + | |
| 3093 | + | |
| 3094 | + | |
| 3095 | + | |
| 3096 | + | |
| 3097 | + | |
| 3098 | + | |
| 3099 | + | |
| 3100 | + | |
| 3101 | + | |
| 3102 | + | |
| 3103 | + | |
| 3104 | + | |
| 3105 | + | |
| 3106 | + | |
| 3107 | + | |
| 3108 | + | |
| 3109 | + | |
| 3110 | + | |
| 3111 | + | |
| 3112 | + | |
| 3113 | + | |
| 3114 | + | |
| 3115 | + | |
| 3116 | + | |
| 3117 | + | |
| 3118 | + | |
| 3119 | + | |
| 3120 | + | |
| 3121 | + | |
| 3122 | + | |
| 3123 | + | |
| 3124 | + | |
| 3125 | + | |
| 3126 | + | |
| 3127 | + | |
| 3128 | + | |
| 3129 | + | |
| 3130 | + | |
| 3131 | + | |
| 3132 | + | |
3103 | 3133 | | |
3104 | 3134 | | |
3105 | 3135 | | |
| |||
0 commit comments