Skip to content

Add Synthetic Difference-in-Differences (SDID) estimator#8

Merged
igerber merged 2 commits intomainfrom
claude/add-synthetic-control-did-aLI1X
Jan 2, 2026
Merged

Add Synthetic Difference-in-Differences (SDID) estimator#8
igerber merged 2 commits intomainfrom
claude/add-synthetic-control-did-aLI1X

Conversation

@igerber
Copy link
Copy Markdown
Owner

@igerber igerber commented Jan 2, 2026

Implements the Synthetic DiD method from Arkhangelsky et al. (2021) that
combines DiD with synthetic control by re-weighting control units to match
treated units' pre-treatment outcomes.

Key features:

  • SyntheticDiD estimator class with sklearn-like API
  • Unit weight optimization via projected gradient descent
  • Time weight computation for emphasizing informative periods
  • Bootstrap and placebo-based inference
  • SyntheticDiDResults with weight inspection methods
  • Comprehensive test suite (30+ new tests)
  • Documentation with use cases (few treated units, questionable parallel
    trends, heterogeneous controls)

Bumps version to 0.3.0.

claude added 2 commits January 2, 2026 19:40
Implements the Synthetic DiD method from Arkhangelsky et al. (2021) that
combines DiD with synthetic control by re-weighting control units to match
treated units' pre-treatment outcomes.

Key features:
- SyntheticDiD estimator class with sklearn-like API
- Unit weight optimization via projected gradient descent
- Time weight computation for emphasizing informative periods
- Bootstrap and placebo-based inference
- SyntheticDiDResults with weight inspection methods
- Comprehensive test suite (30+ new tests)
- Documentation with use cases (few treated units, questionable parallel
  trends, heterogeneous controls)

Bumps version to 0.3.0.
Add comprehensive bibliography covering all techniques implemented in the library:
- Difference-in-Differences (Ashenfelter & Card, Card & Krueger, Angrist & Pischke)
- Two-Way Fixed Effects (Wooldridge, Imai & Kim)
- Robust Standard Errors (White, MacKinnon & White, Cameron et al.)
- Synthetic Control Method (Abadie et al.)
- Synthetic Difference-in-Differences (Arkhangelsky et al.)
- Parallel Trends Testing (Roth, Rambachan & Roth)
- Multi-Period/Staggered DiD (Callaway & Sant'Anna, Sun & Abraham, de Chaisemartin)
- General Causal Inference (Imbens & Rubin, Cunningham)
@igerber igerber merged commit 73327a2 into main Jan 2, 2026
@igerber igerber deleted the claude/add-synthetic-control-did-aLI1X branch January 3, 2026 12:51
igerber pushed a commit that referenced this pull request Jan 4, 2026
Revised review reflects:
- #1, #4 verified as non-issues (correct by design)
- #3, #5, #6, #8, #13 addressed in commit e40d6b4
- Updated recommendation to approve and merge
- Remaining items are low-priority style suggestions for future PRs
igerber added a commit that referenced this pull request Apr 18, 2026
…StageDiD

Addresses axis-C findings #8, #9, and #10 from the silent-failures audit:
three sites where a sparse factorization failure silently fell back to
dense lstsq without any user-facing signal.

- diff_diff/imputation.py:1516 (variance path: scipy.sparse.linalg.spsolve
  on (A_0' W A_0) z = A_1' w). Bare `except Exception` was swallowing
  the root cause before dense lstsq. Now emits a UserWarning identifying
  the exception type and explaining the fallback implication.
- diff_diff/two_stage.py:1647 (GMM sandwich: sparse_factorized on
  X'_{10} W X_{10} for Stage 1 normal equations). `except RuntimeError`
  was silent; now emits a UserWarning.
- diff_diff/two_stage_bootstrap.py:134 (bootstrap path: same pattern as
  above). `except RuntimeError` was silent; now emits a UserWarning.

All three are single-call sites (per fit, or per aggregation level, or
per bootstrap replicate at most a handful of times) so no aggregation
wrapper pattern is needed — one warning per fallback event is
appropriate.

REGISTRY.md updated under ImputationDiD and TwoStageDiD.

New tests (3): monkey-patch the sparse entry point to raise a
RuntimeError, run .fit(), assert the UserWarning fires with the
expected message prefix. Works against both the variance and bootstrap
surfaces.

Axis-C baseline: 3 major silent-fallback sites (imputation, two_stage,
two_stage_bootstrap) -> 0 remaining in these files. PowerAnalysis
simulation counter (finding #11) and ContinuousDiD B-spline (#12)
still open as separate follow-ups.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants