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
Copy file name to clipboardExpand all lines: CHANGELOG.md
+12Lines changed: 12 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
12
12
13
13
### Fixed
14
14
-**`LinearRegression.get_se()` / `get_inference()` no longer return a `NaN` standard error from a tiny-negative variance artifact.** A high-leverage / degenerate coefficient (e.g. an absorbed-FE dummy near-collinear with the treatment, whose Bell-McCaffrey Satterthwaite DOF already hits the noise-floor guard) can have a CR2/HC variance of ~0 (≈1e-32) whose vcov diagonal lands just-below-zero under BLAS-dependent float rounding; `np.sqrt` of the negative then produced a `NaN` SE **nondeterministically** — passing single-threaded but failing under the parallel pure-Python full-suite run (`tests/test_methodology_wls_cr2.py::TestLinearRegressionFENanGuardEndToEnd::test_did_absorbed_fe_lr_inference_nan_for_guarded_coefs`). Both SE sites now clamp the vcov diagonal at 0, so the SE is finite (0 for a genuinely-zero variance), deterministic, and BLAS-independent. **No change for any positive variance** (the clamp is a no-op there); only the previously-`NaN` degenerate case is affected.
15
+
-**`TripleDifference` power analysis now honors `n_periods > 2`.**`simulate_power`,
16
+
`simulate_mde`, and `simulate_sample_size` previously routed DDD to the
17
+
cross-sectional 2×2×2 `generate_ddd_data` regardless of `n_periods` (emitting an
18
+
"n_periods ignored" warning). They now route to the panel DGP
19
+
`generate_ddd_panel_data` when `n_periods > 2`, honoring `n_periods`/`treatment_period`
20
+
and sizing the panel by `n_units` directly (the sample-size search switches from the
21
+
multiple-of-8 grid to a continuous step-1 search). Because `simulate_power` defaults
22
+
to `n_periods=4`, the default DDD power call now uses the panel DGP. The panel DGP has
23
+
within-unit serial correlation, so construct the estimator as
24
+
`TripleDifference(cluster="unit")` for valid power — a `UserWarning` fires otherwise.
Copy file name to clipboardExpand all lines: TODO.md
-1Lines changed: 0 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -93,7 +93,6 @@ Deferred items from PR reviews that were not addressed before merge.
93
93
| Survey sandwich SE is not exactly invariant to zero-weight (subpopulation / padded) rows: the shared `_compute_stratified_psu_meat` finite-sample correction counts zero-weight units as PSUs (an `n_psu/(n_psu-1)`-style factor), so adding zero-weight rows shifts the SE by a second-order amount (~2e-4 relative in the EfficientDiD e2e). The point estimate is exactly invariant and the weighted scores of zero-weight rows are already zero — only the DOF correction's PSU count includes them. Cross-cutting across all survey-enabled estimators; fix by counting only positive-weight PSUs in the correction. |`survey.py` (`_compute_stratified_psu_meat`) | PR-B follow-up | Low |
94
94
| ImputationDiD: leave-one-out (LOO) conservative-variance refinement (BJS 2024 Supplementary Appendix A.9) not implemented — a finite-sample improvement to the auxiliary-model residuals that reduces overfitting of `tau_tilde_g` to `epsilon`. The asymptotic Theorem-3 variance is implemented and matches R `didimputation` (which also omits LOO by default). |`imputation.py`| imputation-validation follow-up | Low |
95
95
| TROP: extend Wave 4's `_setup_trop_data` helper to also cover the duplicated bootstrap resampling loop in `_bootstrap_variance` / `_bootstrap_variance_global` (~40 LoC dedup; mirrors the data-setup helper pattern with a `fit_callable` parameter for the per-draw refit step). |`trop_local.py`, `trop_global.py`| follow-up | Low |
96
-
| TripleDifference power auto-routing: `power.simulate_power` ignores `n_periods` for DDD because `_ddd_dgp_kwargs` is hard-coded to the cross-sectional `generate_ddd_data`. Now that `generate_ddd_panel_data` exists (Wave 4), add a new `_EstimatorProfile` registry entry (or extend the existing one) to route to the panel DGP when `n_periods > 2`. |`power.py`, `prep_dgp.py`| follow-up | Low |
97
96
| 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 |
98
97
| 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 |
99
98
| 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 |
0 commit comments