You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(conformal): one-sided alternatives + covariates in the CWZ proxy (#669)
* feat(conformal): one-sided alternatives + covariates in the CWZ proxy
Extends the SyntheticControl conformal layer (CWZ 2021) with both
user-locked extensions:
(a) alternative={"two-sided","greater","less"} on conformal_test /
conformal_confidence_intervals / conformal_average_effect. One-sided
tests use the SIGNED average-effect statistic S(u)=T_*^{-1/2} sum u_t,
grounded in Remark 1's statistic freedom + eq 2 (the paper has NO
section 7 - the prior TODO/REGISTRY "(§7 signed-t)" wording was a
Firpo-Possebom cross-contamination, fixed here). q=1 enforced for
one-sided. CI inversion reports half-line HULLS: the infinite side
attaches because p -> 1 in the accepted direction; contiguous is
RECOMPUTED against the final reported ray (Algorithm 1 has no
monotonicity guarantee after per-candidate proxy refits); an
all-rejected scanned grid reports the infinite side + an uncertified
NaN finite endpoint as grid_limited (never a false empty set).
(b) covariates=[...] stacks pivoted-variable matching rows RAW into the
constrained-LS proxy objective per the paper's note after eq 6;
residuals/statistic stay outcome-only; exchangeability preserved.
EXOGENEITY ASSUMPTION warned on every covariate run: Z(theta0)
null-imputes only the outcome, so covariates enter as observed
(no-intervention) values - a policy-affected covariate leaks treated
post-period information into the proxy. Block-collapsed average-effect
covariates collapse with the same T*-block structure; pointwise CIs
precompute the covariate panel once and slice per (pre, t) sub-series.
DiagnosticReport's conformal block carries alternative + covariates for
all three kinds. Scope excludes (c) the AR/innovation-permutation path
(TODO row rewritten to track only that remainder).
Tests (5 local review rounds): hand-rolled signed-statistic permutation
oracle; directional rejection; half-line endpoints bracketing the
two-sided interval; missed-ray grid_limited (9-block fixture - the
single-post-slot tie structure floors p at 1/n_blocks); deterministic
non-contiguous patterns incl. rejected-toward-infinity; proxy-weight
mechanism; exogenous covariate fixture + assumption-warning assertion;
report propagation; permutation floor with covariates. All pre-existing
conformal + SC + diagnostic-report suites pass unchanged. Reference
scoping: the authors' scinference R package anchors only the base
machinery; extensions anchor to paper formulas via the oracle tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lbd6nqWmg4snvvBmegwqiw
* docs(registry): drop the contradictory outcomes-only phrase from the proxy bullet
Review P3: the bullet both allowed covariate rows in the objective and
said outcomes-only; the invariant is that residuals/statistic are
outcome-only regardless of covariate rows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lbd6nqWmg4snvvBmegwqiw
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: TODO.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,7 +28,7 @@ The `Origin` column (Actionable tables) and the `PR` column (Deferred tables) bo
28
28
29
29
| Issue | Location | Origin | Effort | Priority |
30
30
|-------|----------|--------|--------|----------|
31
-
|`SyntheticControl` conformal (CWZ 2021) extensions: (a) one-sided / signed-`t` variants (§7); (b) covariates in the conformal proxy (`X_jt`, eqs 4/6 — current proxy is outcomes-only); (c) AR / innovation-permutation path (Lemmas 5-7) for time-series proxies. The joint test, pointwise CIs, and average-effect CI have landed. |`conformal.py`, `synthetic_control_results.py`| CWZ-2021 | Heavy | Low |
31
+
|`SyntheticControl` conformal (CWZ 2021) AR / innovation-permutation path (Lemmas 5-7) for time-series proxies — the residual-permutation shortcut is only valid for time-permutation-invariant proxies (SC/Lasso/DiD); an AR proxy needs innovationpermutation. One-sided alternatives (Remark 1 signed statistic) and proxy covariates (eq 4/6 note) SHIPPED 2026-07. |`diff_diff/conformal.py`, `diff_diff/synthetic_control_results.py`| CWZ-2021 | Heavy | Low |
32
32
| `ContinuousDiD` CGBS-2024 extensions. (a) `covariates=` kwarg — **DONE (reg/dr)**; (b) discrete-treatment saturated regression (`treatment_type="discrete"`) — **DONE**; (c) lowest-dose-as-control per Remark 3.1 when `P(D=0)=0` (`control_group="lowest_dose"`) — **DONE** (discrete + continuous mass-point, single-cohort; estimand `ATT(d)−ATT(d_L)`; see REGISTRY Note #7). Remaining (all deferred `NotImplementedError`, documented): `estimation_method="ipw"` on the dose curve (scalar-adjustment / degenerate); `covariates=` × `survey_design=` (weighted OR + weighted nuisance IF); multi-cohort **heterogeneous-support** discrete aggregation (support-aware: average each dose only over the cohorts that observe it); **multi-cohort `lowest_dose`** (within-cohort `d_L` reference + support-aware cross-cohort aggregation); and **`covariates=` × `lowest_dose`** (conditional-PT-relative-to-`d_L` estimand). Single-cohort / 2-period / shared-support multi-cohort are supported. | `continuous_did.py` | CGBS-2024 | Heavy | Low |
33
33
| TWFE's HC2/HC2-BM inline full-dummy build (`twfe.py:280-315`) duplicates the dummy-construction logic in `DifferenceInDifferences(fixed_effects=...)` (`estimators.py:478-486`). Extract a shared helper, or delegate TWFE's HC2/HC2-BM path to DiD's `fixed_effects=` branch (with TWFE-specific cluster-default threading), to reduce drift risk on FE naming / survey behavior / result-surface conventions. Substantive refactor — touches both estimators. |`twfe.py::fit`, `estimators.py::DifferenceInDifferences.fit`| follow-up | Heavy | Low |
0 commit comments