From 9521f38d2ac1ff1add7bf92ee03af62613833afd Mon Sep 17 00:00:00 2001 From: igerber Date: Mon, 16 Feb 2026 15:37:17 -0500 Subject: [PATCH] Bump version to 2.4.0 Update version numbers in __init__.py, pyproject.toml, and rust/Cargo.toml. Add CHANGELOG entry for v2.4.0 with Two-Stage DiD estimator and related fixes. Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 21 +++++++++++++++++++++ diff_diff/__init__.py | 2 +- pyproject.toml | 2 +- rust/Cargo.toml | 2 +- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1745866e..c38c03ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.4.0] - 2026-02-16 + +### Added +- **Gardner (2022) Two-Stage DiD estimator** (`TwoStageDiD`) + - Two-stage estimator: (1) estimate unit+time FE on untreated obs, (2) regress residualized outcomes on treatment indicators + - `TwoStageDiDResults` with overall ATT, event study, group effects, per-observation treatment effects + - `TwoStageBootstrapResults` for multiplier bootstrap inference on GMM influence function + - `two_stage_did()` convenience function for quick estimation + - Point estimates identical to ImputationDiD; different variance estimator (GMM sandwich vs. conservative) + - No finite-sample adjustments (raw asymptotic sandwich, matching R `did2s`) +- Proposition 5 detection for unidentified long-run horizons without never-treated units + +### Changed +- Workflow improvements to reduce PR review rounds + +### Fixed +- Zero-observation horizons/cohorts producing se=0 instead of NaN in TwoStageDiD +- Edge case fixes for TwoStageDiD (PR review feedback) +- Grep PCRE patterns updated to use POSIX character classes + ## [2.3.2] - 2026-02-16 ### Added @@ -719,6 +739,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `to_dict()` and `to_dataframe()` export methods - `is_significant` and `significance_stars` properties +[2.4.0]: https://github.com/igerber/diff-diff/compare/v2.3.2...v2.4.0 [2.3.2]: https://github.com/igerber/diff-diff/compare/v2.3.1...v2.3.2 [2.3.1]: https://github.com/igerber/diff-diff/compare/v2.3.0...v2.3.1 [2.3.0]: https://github.com/igerber/diff-diff/compare/v2.2.1...v2.3.0 diff --git a/diff_diff/__init__.py b/diff_diff/__init__.py index 01c50e75..05e3f517 100644 --- a/diff_diff/__init__.py +++ b/diff_diff/__init__.py @@ -148,7 +148,7 @@ load_mpdta, ) -__version__ = "2.3.2" +__version__ = "2.4.0" __all__ = [ # Estimators "DifferenceInDifferences", diff --git a/pyproject.toml b/pyproject.toml index 67c22abf..6e411d64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "diff-diff" -version = "2.3.2" +version = "2.4.0" description = "A library for Difference-in-Differences causal inference analysis" readme = "README.md" license = "MIT" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 450777cf..3b7f6178 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "diff_diff_rust" -version = "2.3.2" +version = "2.4.0" edition = "2021" description = "Rust backend for diff-diff DiD library" license = "MIT"