Skip to content

Commit fd28256

Browse files
igerberclaude
andcommitted
Address PR #408 R0 review (1 P2 test gap)
R0 P2: test_per_path_se_within_envelope_of_unweighted claimed an SE invariant in its name but only asserted point-estimate equality. Add finite-SE rtol=0.10 envelope assertion alongside the existing effect equality, matching the test's documented contract. Under unit weights + single stratum + PSU=group, Binder TSL contributes a Bessel n/(n-1) factor relative to plug-in SE's plain 1/n divisor, so SEs differ by O(1/n) but track within a few percent on cohort-clean panels. Empirical observation on the test fixture: max rtol ~0.84% (well under the 10% envelope). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f8f66a1 commit fd28256

1 file changed

Lines changed: 28 additions & 2 deletions

File tree

tests/test_chaisemartin_dhaultfoeuille.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9372,7 +9372,18 @@ def test_per_path_se_telescope_to_global_on_single_path(self):
93729372
)
93739373

93749374
def test_per_path_se_within_envelope_of_unweighted(self):
9375-
"""Constant weights + single PSU per group: survey SE matches plug-in SE."""
9375+
"""Constant weights + single PSU per group: survey SE within Bessel-
9376+
envelope of plug-in SE.
9377+
9378+
Under unit weights + single stratum + PSU=group, the survey path's
9379+
cell-period allocator reduces to a group-level allocator and Binder
9380+
TSL contributes a `n/(n-1)` Bessel factor relative to the plug-in
9381+
SE's plain `1/n` divisor. SE values therefore differ by O(1/n) but
9382+
track within a few percent on cohort-clean panels — the named
9383+
envelope. This test confirms (a) point estimates are bit-equal
9384+
(design-agnostic) and (b) survey SE is within a 10% rtol envelope
9385+
of plug-in SE on every (path, horizon) entry where both are finite.
9386+
"""
93769387
from diff_diff.survey import SurveyDesign
93779388

93789389
df = _by_path_survey_data()
@@ -9393,7 +9404,7 @@ def test_per_path_se_within_envelope_of_unweighted(self):
93939404
treatment="treatment", L_max=3,
93949405
)
93959406
assert res_survey.path_effects is not None and res_plain.path_effects is not None
9396-
# Effects must match exactly (point estimate is design-agnostic).
9407+
any_se_compared = False
93979408
for path in res_survey.path_effects:
93989409
if path not in res_plain.path_effects:
93999410
continue
@@ -9405,6 +9416,21 @@ def test_per_path_se_within_envelope_of_unweighted(self):
94059416
res_plain.path_effects[path]["horizons"][l_h]["effect"],
94069417
atol=1e-12,
94079418
)
9419+
se_survey = res_survey.path_effects[path]["horizons"][l_h]["se"]
9420+
se_plain = res_plain.path_effects[path]["horizons"][l_h]["se"]
9421+
if np.isfinite(se_survey) and np.isfinite(se_plain):
9422+
np.testing.assert_allclose(
9423+
se_survey, se_plain, rtol=0.10,
9424+
err_msg=(
9425+
f"path={path} l={l_h}: survey SE outside 10% "
9426+
f"rtol envelope of plug-in SE"
9427+
),
9428+
)
9429+
any_se_compared = True
9430+
assert any_se_compared, (
9431+
"No (path, horizon) entry had finite SE on both surfaces — "
9432+
"constant-weight SE envelope was not actually exercised."
9433+
)
94089434

94099435
# ----- Replicate-weight SE correctness (slow) -----
94109436

0 commit comments

Comments
 (0)