Skip to content

Commit 1b4b8ad

Browse files
Lower pension/SS split threshold from 60 to 55 (#935)
Closes #933. Colorado allows a $20K pension subtraction per filer aged 55-64. PR #925 split pension/SS only when both spouses were ≥60, leaving 55-59 mixed-age couples allocating the full pension to one spouse and losing the per-person CO subtraction on the other. Drop the threshold to 55 (the lowest practical state age gate). Higher-threshold states (DE 60, GA 62, MD 65) are unaffected: a 55-59 split doesn't create a false exclusion because those filers fail the higher state age gates anyway. 3K eCPS 2025 sample: identical aggregate match rates (no regression). Per-record: #933 CO joint, page=58/sage=56, $65K pensions now matches TaxAct exactly (siitax $1,224.24 vs prior $2,104.24; $40K subtraction vs prior $20K). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 43768f9 commit 1b4b8ad

3 files changed

Lines changed: 23 additions & 7 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lower the pension/SS age-aware split threshold from 60 to 55 to match Colorado's 55+ pension subtraction (so mixed-age couples ages 55-59 each claim the state per-person exclusion). Higher-threshold states (DE 60, GA 62, MD 65) are unaffected.

policyengine_taxsim/runners/policyengine_runner.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,19 @@ def _initialize_dataset_structure(self) -> dict:
195195
}
196196
)
197197

198-
# Pension and Social Security income are split only when both spouses
199-
# meet the state-level age threshold (60, the lowest common threshold
200-
# across states such as DE). In mixed-age households (e.g. spouse under
201-
# 60 while filer is elderly), the income stays with the primary filer so
202-
# age-based state exclusions aren't lost on the younger spouse's
203-
# incorrectly-allocated share.
198+
# Pension and Social Security income are split between spouses only
199+
# when both meet the state-level age threshold (55, the lowest common
200+
# threshold across states such as CO whose pension subtraction
201+
# qualifies filers 55+). In mixed-age households the income stays
202+
# with the older spouse so age-based state exclusions aren't lost on
203+
# the younger spouse's incorrectly-allocated share. Higher-threshold
204+
# states (DE 60, GA 62, MD 65) are unaffected: 55-59 splits don't
205+
# create false exclusions because the filers fail those states' age
206+
# gates anyway.
204207
_AGE_GATED_FIELDS = frozenset(
205208
{"taxable_private_pension_income", "social_security_retirement"}
206209
)
207-
_AGE_GATED_SPLIT_AGE = 60
210+
_AGE_GATED_SPLIT_AGE = 55
208211

209212
@staticmethod
210213
def _make_primary_split(source_field):

tests/test_spouse_income_splitting.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ def test_pension_splits_when_both_spouses_are_60_plus():
107107
np.testing.assert_allclose(values, [20000.0, 20000.0])
108108

109109

110+
def test_pension_splits_when_both_spouses_are_55_plus():
111+
"""Pension: when both spouses ≥ 55 (CO's threshold), allocate 50/50
112+
so each spouse claims the per-person CO pension subtraction. See
113+
taxsim issue #933: CO joint, page=58, sage=56 — both qualify for
114+
CO's 55-64 $20K subtraction. Pre-fix PE put pension on primary
115+
only, giving $20K total subtraction; correct behavior splits 50/50
116+
so each spouse claims $20K = $40K total (matching TaxAct)."""
117+
df = pd.DataFrame([_base_mfj_record(page=58, sage=56, pensions=40000)])
118+
values = _run_allocation(df, "taxable_private_pension_income")
119+
np.testing.assert_allclose(values, [20000.0, 20000.0])
120+
121+
110122
def test_pension_goes_to_primary_when_primary_is_older():
111123
"""Pension: mixed-age, primary older — keep full pension on primary
112124
so they claim the per-person elderly exclusion. Splitting 50/50 would

0 commit comments

Comments
 (0)