From 1ad2436b46d2a7b11729846fcdcca3bcfbce1b3f Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Thu, 22 Oct 2026 16:19:18 -0400 Subject: [PATCH 1/3] Add Montana's 2021-2023 partial pension, annuity, and IRA income exemption MCA 15-30-2110(2)(c) exempts the first $4,400 (2021), $4,640 (2022) or $5,060 (2023) of each taxpayer's pension, annuity, and IRA income, reduced by $2 for each $1 of federal AGI above $36,700, $38,660 or $42,140. The Form 2 worksheet reduces each spouse's amount by their own federal AGI on a separate return, and the spouses' combined amount once by the joint federal AGI on a joint return, so the exemption is added in mt_agi_indiv and mt_agi_joint (and the two Taxable Social Security schedules) rather than in the subtractions list. Repealed from 2024. Closes #10388 Co-Authored-By: Claude Opus 5.5 --- changelog.d/mt-pension-exemption.added.md | 1 + .../tax/income/subtractions/pension/cap.yaml | 18 ++++ .../subtractions/pension/in_effect.yaml | 13 +++ .../subtractions/pension/phase_out/rate.yaml | 12 +++ .../pension/phase_out/threshold.yaml | 18 ++++ .../income/subtractions/pension/sources.yaml | 17 ++++ .../subtractions/pension/integration.yaml | 22 +++++ ...mt_pension_exemption_before_phase_out.yaml | 43 +++++++++ .../pension/mt_pension_exemption_indiv.yaml | 63 +++++++++++++ .../pension/mt_pension_exemption_joint.yaml | 92 +++++++++++++++++++ .../states/mt/tax/income/base/mt_agi_indiv.py | 7 +- .../states/mt/tax/income/base/mt_agi_joint.py | 3 + .../income/base/mt_taxable_social_security.py | 6 +- .../base/mt_taxable_social_security_joint.py | 6 +- .../mt_pension_exemption_before_phase_out.py | 24 +++++ .../pension/mt_pension_exemption_indiv.py | 28 ++++++ .../pension/mt_pension_exemption_joint.py | 27 ++++++ 17 files changed, 397 insertions(+), 3 deletions(-) create mode 100644 changelog.d/mt-pension-exemption.added.md create mode 100644 policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/cap.yaml create mode 100644 policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/in_effect.yaml create mode 100644 policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/phase_out/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/phase_out/threshold.yaml create mode 100644 policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_indiv.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.yaml create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.py create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_indiv.py create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.py diff --git a/changelog.d/mt-pension-exemption.added.md b/changelog.d/mt-pension-exemption.added.md new file mode 100644 index 00000000000..661085b67a7 --- /dev/null +++ b/changelog.d/mt-pension-exemption.added.md @@ -0,0 +1 @@ +Add Montana's 2021–2023 partial pension, annuity, and IRA income exemption. diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/cap.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/cap.yaml new file mode 100644 index 00000000000..20ba3a7535e --- /dev/null +++ b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/cap.yaml @@ -0,0 +1,18 @@ +description: Montana caps the partial pension, annuity, and IRA income exemption at this amount for each taxpayer. +values: + 2021-01-01: 4_400 + 2022-01-01: 4_640 + 2023-01-01: 5_060 +metadata: + unit: currency-USD + period: year + label: Montana partial pension, annuity, and IRA income exemption cap + reference: + - title: Montana Code Annotated 2021, 15-30-2110(2)(c)(i) and (17) + href: https://web.archive.org/web/20220630022434/https://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0210/section_0100/0150-0300-0210-0100.html + - title: 2021 Montana Form 2 instructions, line 35, Partial Pension, Annuity, and IRA Income Exemption + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2021_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=30 + - title: 2022 Montana Form 2 instructions, line 34, Partial Pension, Annuity, and IRA Income Exemption + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=31 + - title: 2023 Montana Form 2 instructions, line 34, Partial Pension, Annuity, and IRA Income Exemption + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34 diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/in_effect.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/in_effect.yaml new file mode 100644 index 00000000000..06e01c03bf8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/in_effect.yaml @@ -0,0 +1,13 @@ +description: Montana provides the partial pension, annuity, and IRA income exemption if this is true. +values: + 2021-01-01: true + 2024-01-01: false +metadata: + unit: bool + period: year + label: Montana partial pension, annuity, and IRA income exemption in effect + reference: + - title: Montana Code Annotated 2021, 15-30-2110(2)(c), repealed effective January 1, 2024 (secs. 65, 70(1), Ch. 503, L. 2021) + href: https://web.archive.org/web/20220630022434/https://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0210/section_0100/0150-0300-0210-0100.html + - title: 2023 Montana Form 2 instructions, line 34, "Beginning in Tax Year 2024, this deduction is repealed" + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35 diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/phase_out/rate.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/phase_out/rate.yaml new file mode 100644 index 00000000000..0b8a8f9c49d --- /dev/null +++ b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/phase_out/rate.yaml @@ -0,0 +1,12 @@ +description: Montana reduces the partial pension, annuity, and IRA income exemption by this amount for each dollar of federal adjusted gross income above the threshold. +values: + 2021-01-01: 2 +metadata: + unit: /1 + period: year + label: Montana partial pension, annuity, and IRA income exemption phase-out rate + reference: + - title: Montana Code Annotated 2021, 15-30-2110(2)(c)(ii) + href: https://web.archive.org/web/20220630022434/https://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0210/section_0100/0150-0300-0210-0100.html + - title: 2023 Montana Form 2, Partial Pension, Annuity, and IRA Income Exemption Worksheet, line 6 + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2023_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/phase_out/threshold.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/phase_out/threshold.yaml new file mode 100644 index 00000000000..83cb0018d95 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/phase_out/threshold.yaml @@ -0,0 +1,18 @@ +description: Montana reduces the partial pension, annuity, and IRA income exemption when federal adjusted gross income exceeds this amount. +values: + 2021-01-01: 36_700 + 2022-01-01: 38_660 + 2023-01-01: 42_140 +metadata: + unit: currency-USD + period: year + label: Montana partial pension, annuity, and IRA income exemption phase-out threshold + reference: + - title: Montana Code Annotated 2021, 15-30-2110(2)(c)(ii) and (17) + href: https://web.archive.org/web/20220630022434/https://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0210/section_0100/0150-0300-0210-0100.html + - title: 2021 Montana Form 2 instructions, line 35, Partial Pension, Annuity, and IRA Income Exemption + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2021_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=30 + - title: 2022 Montana Form 2 instructions, line 34, Partial Pension, Annuity, and IRA Income Exemption + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=31 + - title: 2023 Montana Form 2 instructions, line 34, Partial Pension, Annuity, and IRA Income Exemption + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34 diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml new file mode 100644 index 00000000000..ce05022ada3 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml @@ -0,0 +1,17 @@ +description: Montana counts these sources as pension, annuity, and IRA income for the partial pension, annuity, and IRA income exemption. +values: + 2021-01-01: + # Form 2, page 1, lines 4b (IRA distributions) and 5b (pensions and + # annuities). Premature distributions do not qualify (MCA 15-30-2101(25)(d)) + # but are not separately modeled. + - taxable_pension_income + - taxable_retirement_distributions +metadata: + unit: list + period: year + label: Montana partial pension, annuity, and IRA income exemption sources + reference: + - title: Montana Code Annotated 2021, 15-30-2101(25), "Pension and annuity income" + href: https://web.archive.org/web/20220127192023/http://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0210/section_0010/0150-0300-0210-0010.html + - title: 2023 Montana Form 2, Partial Pension, Annuity, and IRA Income Exemption Worksheet, line 2 + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2023_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=6 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml new file mode 100644 index 00000000000..d05f0054b13 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml @@ -0,0 +1,22 @@ +# Single filer, 20,000 of taxable pension income, no other income, 2023 +# Form 2. Montana AGI: 20,000 - 5,060 = 14,940. Standard deduction: 20% of +# 14,940 = 2,988. Exemptions: 2,960 each. +- name: Single filer aged 60 with a pension + period: 2023 + input: + age: 60 + taxable_private_pension_income: 20_000 + state_code: MT + output: + # Taxable income 14,940 - 2,988 - 2,960 = 8,992; tax 8,992 x 3% - 99. + mt_income_tax: 170.76 + +- name: Single filer aged 70 with a pension + period: 2023 + input: + age: 70 + taxable_private_pension_income: 20_000 + state_code: MT + output: + # Taxable income 14,940 - 2,988 - 2 x 2,960 = 6,032; tax 6,032 x 2% - 36. + mt_income_tax: 84.64 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml new file mode 100644 index 00000000000..039457c1476 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml @@ -0,0 +1,43 @@ +- name: Pension above the 2023 cap is capped at 5,060 + period: 2023 + input: + taxable_private_pension_income: 25_000 + state_code: MT + output: + mt_pension_exemption_before_phase_out: 5_060 + +- name: Pension and IRA income below the 2023 cap are exempt in full + period: 2023 + input: + taxable_private_pension_income: 1_000 + taxable_ira_distributions: 1_300 + state_code: MT + output: + mt_pension_exemption_before_phase_out: 2_300 + +- name: A dependent's pension does not qualify + period: 2023 + input: + people: + head: + is_tax_unit_head: true + dependent: + is_tax_unit_dependent: true + taxable_private_pension_income: 3_000 + tax_units: + tax_unit: + members: [head, dependent] + households: + household: + members: [head, dependent] + state_code: MT + output: + mt_pension_exemption_before_phase_out: [0, 0] + +- name: The exemption is repealed from 2024 + period: 2024 + input: + taxable_private_pension_income: 20_000 + state_code: MT + output: + mt_pension_exemption_before_phase_out: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_indiv.yaml new file mode 100644 index 00000000000..bd52bb832cc --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_indiv.yaml @@ -0,0 +1,63 @@ +# Expected values are the examples in the Form 2 instructions: 2021 line 35 +# (PDF page 30), 2022 line 34 (PDF pages 31-32), 2023 line 34 (PDF pages 34-35). +- name: 2021 instructions example, federal AGI of 37,400 + period: 2021 + input: + employment_income: 17_400 + taxable_private_pension_income: 20_000 + state_code: MT + output: + # 4,400 - (700 x 2) = 3,000 + mt_pension_exemption_indiv: 3_000 + +- name: 2022 instructions example, federal AGI of 39,400 + period: 2022 + input: + employment_income: 19_400 + taxable_private_pension_income: 20_000 + state_code: MT + output: + # 4,640 - (740 x 2) = 3,160 + mt_pension_exemption_indiv: 3_160 + +- name: 2023 instructions example, federal AGI of 43,000 + period: 2023 + input: + employment_income: 23_000 + taxable_private_pension_income: 20_000 + state_code: MT + output: + # 5,060 - (860 x 2) = 3,340 + mt_pension_exemption_indiv: 3_340 + +- name: No exemption at the 2023 federal AGI of 44,670 + period: 2023 + input: + employment_income: 24_670 + taxable_private_pension_income: 20_000 + state_code: MT + output: + # 5,060 - (2,530 x 2) = 0 + mt_pension_exemption_indiv: 0 + +- name: On separate returns each spouse uses their own federal AGI + period: 2023 + input: + people: + head: + is_tax_unit_head: true + employment_income: 40_000 + spouse: + is_tax_unit_spouse: true + taxable_private_pension_income: 20_000 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: MT + output: + # The spouse's separately stated federal AGI, 20,000, is below 42,140. + mt_pension_exemption_indiv: [0, 5_060] + mt_agi_indiv: [40_000, 14_940] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.yaml new file mode 100644 index 00000000000..f82dce64326 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.yaml @@ -0,0 +1,92 @@ +# Jim and Pam examples in the Form 2 instructions: 2021 line 35 (PDF page 30), +# 2022 line 34 (PDF page 31), 2023 line 34 (PDF page 34). Federal AGI is +# 35,400; Jim has a 25,000 and Pam a 2,300 retirement distribution. +- name: 2021 instructions example, Jim and Pam + period: 2021 + input: + people: + jim: + is_tax_unit_head: true + employment_income: 8_100 + taxable_private_pension_income: 25_000 + pam: + is_tax_unit_spouse: true + taxable_private_pension_income: 2_300 + tax_units: + tax_unit: + members: [jim, pam] + households: + household: + members: [jim, pam] + state_code: MT + output: + # 4,400 + 2,300 + mt_pension_exemption_joint: 6_700 + +- name: 2022 instructions example, Jim and Pam + period: 2022 + input: + people: + jim: + is_tax_unit_head: true + employment_income: 8_100 + taxable_private_pension_income: 25_000 + pam: + is_tax_unit_spouse: true + taxable_private_pension_income: 2_300 + tax_units: + tax_unit: + members: [jim, pam] + households: + household: + members: [jim, pam] + state_code: MT + output: + # 4,640 + 2,300 + mt_pension_exemption_joint: 6_940 + +- name: 2023 instructions example, Jim and Pam + period: 2023 + input: + people: + jim: + is_tax_unit_head: true + employment_income: 8_100 + taxable_private_pension_income: 25_000 + pam: + is_tax_unit_spouse: true + taxable_private_pension_income: 2_300 + tax_units: + tax_unit: + members: [jim, pam] + households: + household: + members: [jim, pam] + state_code: MT + output: + # 5,060 + 2,300 + mt_pension_exemption_joint: 7_360 + # 35,400 - 7,360 + mt_agi_joint: 28_040 + +- name: A joint return reduces the exemption by the joint federal AGI + period: 2023 + input: + people: + head: + is_tax_unit_head: true + employment_income: 40_000 + spouse: + is_tax_unit_spouse: true + taxable_private_pension_income: 20_000 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: MT + output: + # Worksheet lines 3b-7: 5,060 - 2 x (60,000 - 42,140) is below zero. + mt_pension_exemption_joint: 0 + mt_agi_joint: 60_000 diff --git a/policyengine_us/variables/gov/states/mt/tax/income/base/mt_agi_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/base/mt_agi_indiv.py index ff6e632e58b..043651bfe56 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/base/mt_agi_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/base/mt_agi_indiv.py @@ -16,7 +16,12 @@ def formula(person, period, parameters): "mt_loss_ald_reallocation", period ) additions = person("mt_additions", period) - subtractions = person("mt_subtractions", period) + # The partial pension, annuity, and IRA income exemption is not in the + # subtractions list: on a separate return each spouse reduces it by + # their own federal AGI, and a joint return reduces it once. + subtractions = person("mt_subtractions", period) + person( + "mt_pension_exemption_indiv", period + ) reduced_agi = max_(agi + additions - subtractions, 0) # Montana taxable social security benefits can be either addition or subtraction # if mt_taxable_social security - taxable_social_security > 0, then addition, else subtraction diff --git a/policyengine_us/variables/gov/states/mt/tax/income/base/mt_agi_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/base/mt_agi_joint.py index 3a081d76218..7dcb593c319 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/base/mt_agi_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/base/mt_agi_joint.py @@ -23,6 +23,9 @@ def formula(tax_unit, period, parameters): on_return = person("is_tax_unit_head_or_spouse", period) additions = tax_unit.sum(person("mt_additions", period) * on_return) subtractions = tax_unit.sum(person("mt_subtractions", period) * on_return) + # A joint return claims the partial pension, annuity, and IRA income + # exemption once, reduced by the joint federal AGI. + subtractions += tax_unit("mt_pension_exemption_joint", period) # Apply pooled subtractions to pooled income reduced_agi = max_(agi + additions - subtractions, 0) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/base/mt_taxable_social_security.py b/policyengine_us/variables/gov/states/mt/tax/income/base/mt_taxable_social_security.py index 053c2a87ab4..0b0c6173385 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/base/mt_taxable_social_security.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/base/mt_taxable_social_security.py @@ -37,7 +37,11 @@ def formula(person, period, parameters): "student_loan_interest_ald", period ) # Line 8 - Montana subtractions + ald - subtractions = person("mt_subtractions", period) + # Subtractions Schedule line 35 includes the partial pension, annuity, + # and IRA income exemption (line 34). + subtractions = person("mt_subtractions", period) + person( + "mt_pension_exemption_indiv", period + ) increased_subtractions = subtractions + ald_less_student_loan # line 9: line 6 -line 8, if line 8 >= line 6, return 0 income_reduced_by_subtractions = max_( diff --git a/policyengine_us/variables/gov/states/mt/tax/income/base/mt_taxable_social_security_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/base/mt_taxable_social_security_joint.py index cebfa573b8f..54029434dd0 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/base/mt_taxable_social_security_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/base/mt_taxable_social_security_joint.py @@ -38,7 +38,11 @@ def formula(tax_unit, period, parameters): tax_unit, period, ["mt_applicable_ald_deductions"] ) - add(tax_unit, period, ["student_loan_interest_ald"]) # line 8: Montana subtractions + ald - subtractions = add(tax_unit, period, ["mt_subtractions"]) + # Subtractions Schedule line 35 includes the partial pension, annuity, + # and IRA income exemption (line 34). + subtractions = add(tax_unit, period, ["mt_subtractions"]) + tax_unit( + "mt_pension_exemption_joint", period + ) increased_subtractions = subtractions + ald_less_student_loan # line 9: line 6 - line 8, if line 8 >= line 6, return 0 income_reduced_by_subtractions = max_( diff --git a/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.py b/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.py new file mode 100644 index 00000000000..dd5ee2168bd --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class mt_pension_exemption_before_phase_out(Variable): + value_type = float + entity = Person + label = "Montana partial pension, annuity, and IRA income exemption before the phase-out" + unit = USD + definition_period = YEAR + reference = ( + "https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2023_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=6", + "https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34", + ) + defined_for = StateCode.MT + + def formula(person, period, parameters): + p = parameters(period).gov.states.mt.tax.income.subtractions.pension + if not p.in_effect: + return 0 + # Worksheet lines 1-3a: the smaller of the cap and the taxpayer's own + # pension, annuity, and IRA income. + income = add(person, period, p.sources) + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + return head_or_spouse * min_(p.cap, income) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_indiv.py new file mode 100644 index 00000000000..5ff616e1b51 --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_indiv.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class mt_pension_exemption_indiv(Variable): + value_type = float + entity = Person + label = "Montana partial pension, annuity, and IRA income exemption on a separate return" + unit = USD + definition_period = YEAR + reference = ( + "https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2023_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=6", + "https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34", + ) + defined_for = StateCode.MT + + def formula(person, period, parameters): + p = parameters(period).gov.states.mt.tax.income.subtractions.pension.phase_out + exemption = person("mt_pension_exemption_before_phase_out", period) + # Lines 4-6: a single filer, or each spouse filing separately, reduces + # the exemption by their own federal adjusted gross income. Spouses + # filing separately on the same form divide the return's losses + # equally, as in mt_agi_indiv. + agi = person("adjusted_gross_income_person", period) + person( + "mt_loss_ald_reallocation", period + ) + reduction = p.rate * max_(agi - p.threshold, 0) + # Line 7 + return max_(exemption - reduction, 0) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.py new file mode 100644 index 00000000000..238c2efe0eb --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class mt_pension_exemption_joint(Variable): + value_type = float + entity = TaxUnit + label = ( + "Montana partial pension, annuity, and IRA income exemption on a joint return" + ) + unit = USD + definition_period = YEAR + reference = ( + "https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2023_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=6", + "https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34", + ) + defined_for = StateCode.MT + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.mt.tax.income.subtractions.pension.phase_out + # Line 3b: a joint return adds the spouses' line 3a amounts. + exemption = add(tax_unit, period, ["mt_pension_exemption_before_phase_out"]) + # Lines 4-6: the reduction applies once, to the joint federal + # adjusted gross income. + agi = tax_unit("adjusted_gross_income", period) + reduction = p.rate * max_(agi - p.threshold, 0) + # Line 7 + return max_(exemption - reduction, 0) From 3e21104ac1e4665396fb3b4e6e6adfae6792685a Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Fri, 23 Oct 2026 17:13:14 -0400 Subject: [PATCH 2/3] Count military retired pay and Roth conversions in the Montana pension exemption - Add military_retirement_pay (MCA 15-30-2101(25)(b); Form 1040 line 5b) and taxable_roth_conversions (worksheet line 2 takes all of line 4b) to the exemption's sources. Survivor Benefit Plan annuities stay out: the 2023 line 34 instructions exclude death benefits, and Form 1099-R code 4 is for payments to a decedent's beneficiary. - Test joint returns in the phase-out range for 2021-2023, where reducing line 3b once by the joint federal AGI differs from reducing each spouse. - Note that years before 2021 use the 2021 cap and threshold. Co-Authored-By: Claude Opus 5.5 --- .../subtractions/pension/in_effect.yaml | 3 + .../income/subtractions/pension/sources.yaml | 13 ++++ .../subtractions/pension/integration.yaml | 11 +++ ...mt_pension_exemption_before_phase_out.yaml | 27 ++++++++ .../pension/mt_pension_exemption_joint.yaml | 68 +++++++++++++++++++ 5 files changed, 122 insertions(+) diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/in_effect.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/in_effect.yaml index 06e01c03bf8..9c5031acfc2 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/in_effect.yaml @@ -1,5 +1,8 @@ description: Montana provides the partial pension, annuity, and IRA income exemption if this is true. values: + # The exemption also applied before 2021, at lower indexed amounts + # (MCA 15-30-2110(2)(c) and (17)). Those amounts are not listed, so earlier + # years use the 2021 cap and phase-out threshold. 2021-01-01: true 2024-01-01: false metadata: diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml index ce05022ada3..1daf9f0f846 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml @@ -6,6 +6,15 @@ values: # but are not separately modeled. - taxable_pension_income - taxable_retirement_distributions + # Roth conversions are IRA or plan distributions included on line 4b or + # 5b (MCA 15-30-2101(25)(d)). + - taxable_roth_conversions + # Uniformed services retired pay (MCA 15-30-2101(25)(b)), reported on + # line 5b. Survivor Benefit Plan annuities + # (military_retirement_pay_survivors) are left out: the line 34 + # instructions exclude death benefits, and Form 1099-R code 4 is for + # payments to a decedent's beneficiary. + - military_retirement_pay metadata: unit: list period: year @@ -15,3 +24,7 @@ metadata: href: https://web.archive.org/web/20220127192023/http://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0210/section_0010/0150-0300-0210-0010.html - title: 2023 Montana Form 2, Partial Pension, Annuity, and IRA Income Exemption Worksheet, line 2 href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2023_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=6 + - title: 2023 Montana Form 2 instructions, line 34, "Death benefits and premature distributions of retirement income do not qualify for the exemption" + href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34 + - title: 2023 Instructions for Forms 1099-R and 5498, box 7 code 4, "payment to a decedent's beneficiary" + href: https://www.irs.gov/pub/irs-prior/i1099r--2023.pdf#page=15 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml index d05f0054b13..779a4525a42 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml @@ -20,3 +20,14 @@ output: # Taxable income 14,940 - 2,988 - 2 x 2,960 = 6,032; tax 6,032 x 2% - 36. mt_income_tax: 84.64 + +- name: Single filer aged 60 with military retired pay + period: 2023 + input: + age: 60 + military_retirement_pay: 20_000 + state_code: MT + output: + # MCA 15-30-2101(25)(b): the same Montana AGI (14,940) and tax as the + # pension case above. + mt_income_tax: 170.76 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml index 039457c1476..f12114c7bb4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml @@ -15,6 +15,33 @@ output: mt_pension_exemption_before_phase_out: 2_300 +- name: Military retired pay qualifies + period: 2023 + input: + military_retirement_pay: 20_000 + state_code: MT + output: + # MCA 15-30-2101(25)(b), capped at 5,060. + mt_pension_exemption_before_phase_out: 5_060 + +- name: Survivor Benefit Plan annuities do not qualify + period: 2023 + input: + military_retirement_pay_survivors: 20_000 + state_code: MT + output: + # Line 34 instructions: death benefits do not qualify. + mt_pension_exemption_before_phase_out: 0 + +- name: Roth conversions qualify + period: 2023 + input: + taxable_roth_conversions: 3_000 + state_code: MT + output: + # Included on Form 2, page 1, line 4b (worksheet line 2). + mt_pension_exemption_before_phase_out: 3_000 + - name: A dependent's pension does not qualify period: 2023 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.yaml index f82dce64326..198c6890f5d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_joint.yaml @@ -90,3 +90,71 @@ # Worksheet lines 3b-7: 5,060 - 2 x (60,000 - 42,140) is below zero. mt_pension_exemption_joint: 0 mt_agi_joint: 60_000 + +# In the phase-out range a joint return reduces the combined line 3b amount +# once by the joint federal AGI (worksheet line 7). Reducing each spouse's +# amount separately would give a lower total. +- name: 2021 joint return in the phase-out range + period: 2021 + input: + people: + head: + is_tax_unit_head: true + taxable_private_pension_income: 18_700 + spouse: + is_tax_unit_spouse: true + taxable_private_pension_income: 18_700 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: MT + output: + # 2 x 4,400 - 2 x (37,400 - 36,700) + mt_pension_exemption_joint: 7_400 + +- name: 2022 joint return in the phase-out range + period: 2022 + input: + people: + head: + is_tax_unit_head: true + taxable_private_pension_income: 19_700 + spouse: + is_tax_unit_spouse: true + taxable_private_pension_income: 19_700 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: MT + output: + # 2 x 4,640 - 2 x (39,400 - 38,660) + mt_pension_exemption_joint: 7_800 + +- name: 2023 joint return in the phase-out range + period: 2023 + input: + people: + head: + is_tax_unit_head: true + taxable_private_pension_income: 21_500 + spouse: + is_tax_unit_spouse: true + taxable_private_pension_income: 21_500 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: MT + output: + # 2 x 5,060 - 2 x (43,000 - 42,140) + mt_pension_exemption_joint: 8_400 + # 43,000 - 8,400 + mt_agi_joint: 34_600 From c81ca258e5d3d341eab5b29d0a0126ce39120606 Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Mon, 26 Oct 2026 10:45:41 -0400 Subject: [PATCH 3/3] Count Survivor Benefit Plan annuities in the Montana pension exemption The 2023 line 34 instructions qualify Form 1099-R code 7 income, and the 2023 Instructions for Forms 1099-R and 5498 (p. 2, Military retirement annuities) report military pensions and survivor benefit annuities with code 7. Code 4 is for separate death-benefit payments. Use military_retirement_income (retired pay plus SBP annuities) as the source, and test that a 2023 SBP annuity of 20,000 gives 5,060 and the same Montana tax as the pension case (170.76). Co-Authored-By: Claude Opus 5.5 --- .../income/subtractions/pension/sources.yaml | 18 +++++++++--------- .../subtractions/pension/integration.yaml | 11 +++++++++++ .../mt_pension_exemption_before_phase_out.yaml | 7 ++++--- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml index 1daf9f0f846..3b759e12a8f 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/subtractions/pension/sources.yaml @@ -9,12 +9,12 @@ values: # Roth conversions are IRA or plan distributions included on line 4b or # 5b (MCA 15-30-2101(25)(d)). - taxable_roth_conversions - # Uniformed services retired pay (MCA 15-30-2101(25)(b)), reported on - # line 5b. Survivor Benefit Plan annuities - # (military_retirement_pay_survivors) are left out: the line 34 - # instructions exclude death benefits, and Form 1099-R code 4 is for - # payments to a decedent's beneficiary. - - military_retirement_pay + # Uniformed services retired pay and Survivor Benefit Plan annuities + # (MCA 15-30-2101(25)(b)), reported on line 5b. The line 34 instructions + # qualify Form 1099-R code 7 income, and the 1099-R instructions put + # military pensions and survivor benefit annuities on code 7. Death + # benefits (code 4) do not qualify. + - military_retirement_income metadata: unit: list period: year @@ -24,7 +24,7 @@ metadata: href: https://web.archive.org/web/20220127192023/http://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0210/section_0010/0150-0300-0210-0010.html - title: 2023 Montana Form 2, Partial Pension, Annuity, and IRA Income Exemption Worksheet, line 2 href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2023_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=6 - - title: 2023 Montana Form 2 instructions, line 34, "Death benefits and premature distributions of retirement income do not qualify for the exemption" + - title: 2023 Montana Form 2 instructions, line 34, "Qualifying pension, annuity, and IRA income is reported on federal Form 1099-R with distribution code 7" href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34 - - title: 2023 Instructions for Forms 1099-R and 5498, box 7 code 4, "payment to a decedent's beneficiary" - href: https://www.irs.gov/pub/irs-prior/i1099r--2023.pdf#page=15 + - title: 2023 Instructions for Forms 1099-R and 5498, Military retirement annuities, "Use Code 7 in box 7 for reporting military pensions or survivor benefit annuities" + href: https://www.irs.gov/pub/irs-prior/i1099r--2023.pdf#page=2 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml index 779a4525a42..da8fa9b549d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/integration.yaml @@ -31,3 +31,14 @@ # MCA 15-30-2101(25)(b): the same Montana AGI (14,940) and tax as the # pension case above. mt_income_tax: 170.76 + +- name: Single filer aged 60 with a Survivor Benefit Plan annuity + period: 2023 + input: + age: 60 + military_retirement_pay_survivors: 20_000 + state_code: MT + output: + # Form 1099-R code 7: the same Montana AGI (14,940) and tax as the + # pension case above. + mt_income_tax: 170.76 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml index f12114c7bb4..e3607c0841e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/subtractions/pension/mt_pension_exemption_before_phase_out.yaml @@ -24,14 +24,15 @@ # MCA 15-30-2101(25)(b), capped at 5,060. mt_pension_exemption_before_phase_out: 5_060 -- name: Survivor Benefit Plan annuities do not qualify +- name: Survivor Benefit Plan annuities qualify period: 2023 input: military_retirement_pay_survivors: 20_000 state_code: MT output: - # Line 34 instructions: death benefits do not qualify. - mt_pension_exemption_before_phase_out: 0 + # Form 1099-R code 7 (1099-R instructions, Military retirement + # annuities), which the line 34 instructions qualify; capped at 5,060. + mt_pension_exemption_before_phase_out: 5_060 - name: Roth conversions qualify period: 2023