diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..10e83a60f3e 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,9 @@ +- bump: patch + changes: + fixed: + - Updates the thresholds and marginal tax rates rates for the Missouri individual income tax in `parameters/gov/states/mo/tax/income/rates.yaml` + - Adds the variable `mo_capital_gains_subtraction.py` and the parameter `parameters/gov/states/mo/tax/income/subtractions/net_capital_gain/rate.yaml` for the 2025 inclusion a full deductibility of capital gains in calculating Missouri adjusted gross income. + - Adds `agi_subtractions.yaml` list parameter with the two MO AGI subtractions for 2025, and creates a `mo_agi_subtractions.py` variable (Person-level), which is referenced in the `mo_adjusted_gross_income.py` calculation. + - Adds `mo_capital_gains_subtraction_person.py` to allocate the capital gains subtraction proportionally to each person based on their share of long-term capital gains, preventing overcounting in multi-person tax units. + - Updates the `parameters/gov/states/mo/tax/income/minimum_taxable_income.yaml` parameter with the new 2025 value. + - Adds new legislative references diff --git a/policyengine_us/parameters/gov/states/mo/tax/income/minimum_taxable_income.yaml b/policyengine_us/parameters/gov/states/mo/tax/income/minimum_taxable_income.yaml index 15a3e400ce9..7a9ed44d9a8 100644 --- a/policyengine_us/parameters/gov/states/mo/tax/income/minimum_taxable_income.yaml +++ b/policyengine_us/parameters/gov/states/mo/tax/income/minimum_taxable_income.yaml @@ -8,8 +8,11 @@ values: 2022-01-01: 111 2023-01-01: 1_207 2024-01-01: 1_273 + 2025-01-01: 1_313 metadata: reference: + - title: Missouri Department of Revenue 2025 Individual Income Tax Year Changes (This reference should be updated once the 2025 tax form comes out) + href: https://dor.mo.gov/taxation/individual/tax-types/income/year-changes/ - title: Missouri Legal Code | 143.021. Tax determined by rates in section 143.011 — no tax on taxable income, when. href: https://rezvisor.mo.gov/main/OneSection.aspx?section=143.021 - title: 2024 MO-1040 Book - Individual Income Tax Long Form diff --git a/policyengine_us/parameters/gov/states/mo/tax/income/rates.yaml b/policyengine_us/parameters/gov/states/mo/tax/income/rates.yaml index 44b019ded06..110f6d59bcf 100644 --- a/policyengine_us/parameters/gov/states/mo/tax/income/rates.yaml +++ b/policyengine_us/parameters/gov/states/mo/tax/income/rates.yaml @@ -17,6 +17,7 @@ brackets: 2022-01-01: 1_121 2023-01-01: 1_207 2024-01-01: 1_273 + 2025-01-01: 1_313 metadata: uprating: gov.irs.uprating rate: @@ -29,6 +30,7 @@ brackets: 2022-01-01: 2_242 2023-01-01: 2_414 2024-01-01: 2_546 + 2025-01-01: 2_626 metadata: uprating: gov.irs.uprating rate: @@ -41,6 +43,7 @@ brackets: 2022-01-01: 3_363 2023-01-01: 3_621 2024-01-01: 3_819 + 2025-01-01: 3_939 metadata: uprating: gov.irs.uprating rate: @@ -53,6 +56,7 @@ brackets: 2022-01-01: 4_484 2023-01-01: 4_828 2024-01-01: 5_092 + 2025-01-01: 5_252 metadata: uprating: gov.irs.uprating rate: @@ -65,6 +69,7 @@ brackets: 2022-01-01: 5_605 2023-01-01: 6_035 2024-01-01: 6_365 + 2025-01-01: 6_565 metadata: uprating: gov.irs.uprating rate: @@ -77,6 +82,7 @@ brackets: 2022-01-01: 6_726 2023-01-01: 7_242 2024-01-01: 7_638 + 2025-01-01: 7_878 metadata: uprating: gov.irs.uprating rate: @@ -89,6 +95,7 @@ brackets: 2022-01-01: 7_847 2023-01-01: 8_449 2024-01-01: 8_911 + 2025-01-01: 9_191 metadata: uprating: gov.irs.uprating rate: @@ -114,10 +121,10 @@ brackets: # withholding formula. Statutes allow further reductions to 0.046 in 2026 # and 0.045 in 2027, but we assume revenue conditions are not met until confirmed. 2025-01-01: 0.047 - # We model rates through 2025 based on 143.011: initial 4.95% rate in 2023 - # (subsection 2(1)), 0.15% reduction to 4.8% in 2024 (subsection 3(1)), and first - # 0.1% reduction to 4.7% in 2025 (subsection 4(1)). We do not model potential - # further 0.1% reductions allowed in subsection 4 until revenue conditions are + # We model rates through 2025 based on 143.011: initial 4.95% rate in 2023 + # (subsection 2(1)), 0.15% reduction to 4.8% in 2024 (subsection 3(1)), and first + # 0.1% reduction to 4.7% in 2025 (subsection 4(1)). We do not model potential + # further 0.1% reductions allowed in subsection 4 until revenue conditions are # confirmed met. metadata: @@ -136,6 +143,8 @@ metadata: href: https://revisor.mo.gov/main/OneSection.aspx?section=143.011&bid=51511&hl= - title: 2025 Missouri Withholding Tax Formula href: https://dor.mo.gov/forms/Withholding%20Table%20-%20Weekly_2025.pdf#page=2 + - title: Missouri Department of Revenue 2025 Individual Income Tax Year Changes (This reference should be updated once the 2025 tax form comes out) + href: https://dor.mo.gov/taxation/individual/tax-types/income/year-changes/ label: Missouri resident individual tax rates type: marginal_rate diff --git a/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/agi_subtractions.yaml b/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/agi_subtractions.yaml new file mode 100644 index 00000000000..1af2e51407a --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/agi_subtractions.yaml @@ -0,0 +1,18 @@ +description: Missouri subtracts these sources from federal adjusted gross income to determine state adjusted gross income. +values: + 2008-01-01: + - mo_qualified_health_insurance_premiums + 2025-01-01: + - mo_qualified_health_insurance_premiums + - mo_capital_gains_subtraction_person + + +metadata: + unit: list + period: year + label: Missouri adjusted gross income subtractions + reference: + - title: Revisor of Missouri, Title X Taxation and Revenue, Chapter 143, 143.121, Missouri adjusted gross income (8/28/2007) + href: https://www.revisor.mo.gov/main/OneSection.aspx?bid=50493§ion=143.121 + - title: Revisor of Missouri, Title X Taxation and Revenue, Chapter 143, 143.121, Missouri adjusted gross income (8/28/2025) + href: https://www.revisor.mo.gov/main/OneSection.aspx?section=143.121&bid=57543 diff --git a/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/net_capital_gain/rate.yaml b/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/net_capital_gain/rate.yaml new file mode 100644 index 00000000000..60f603f8abd --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/net_capital_gain/rate.yaml @@ -0,0 +1,14 @@ +description: Missouri deducts this fraction of net capital gains from taxable income. +values: + 0000-01-01: 0.00 + 2025-01-01: 1 + +metadata: + unit: /1 + period: year + label: Missouri net capital gain deduction rate + reference: + - title: Missouri House of Representatives HB 594 (2025) + href: https://www.senate.mo.gov/25info/bts_web/bill.aspx?SessionType=R&BillID=4957943 + - title: MO Dept of Revenue, Capital Gains Subtraction FAQs + href: https://dor.mo.gov/faq/taxation/individual/capital-gains-subtraction.html diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.yaml new file mode 100644 index 00000000000..ba4fc9377bc --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.yaml @@ -0,0 +1,176 @@ +- name: Pre capital gains subtraction law and qualified premiums, cap gains + period: 2024 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 1_000 + short_term_capital_gains: 500 + health_insurance_premiums: 12_000 + medical_out_of_pocket_expenses: 12_000 + tax_units: + tax_unit1: + members: [person1] + medical_expense_deduction: 0 + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1] + state_code: MO + output: + mo_capital_gains_subtraction: 0 + + +- name: Pre capital gains subtraction law and qualified premiums, health insurance + period: 2024 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 1_000 + short_term_capital_gains: 500 + health_insurance_premiums: 12_000 + medical_out_of_pocket_expenses: 12_000 + tax_units: + tax_unit1: + members: [person1] + medical_expense_deduction: 0 + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1] + state_code: MO + output: + mo_qualified_health_insurance_premiums: 12_000 + + +- name: Pre capital gains subtraction law and qualified premiums, subtractions + period: 2024 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 1_000 + short_term_capital_gains: 500 + health_insurance_premiums: 12_000 + medical_out_of_pocket_expenses: 12_000 + tax_units: + tax_unit1: + members: [person1] + medical_expense_deduction: 0 + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1] + state_code: MO + output: + mo_agi_subtractions: 12_000 + + +- name: Post capital gains subtraction law and qualified premiums, capital gains + period: 2025 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 1_000 + short_term_capital_gains: 500 + health_insurance_premiums: 12_000 + medical_out_of_pocket_expenses: 12_000 + tax_units: + tax_unit1: + members: [person1] + medical_expense_deduction: 0 + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1] + state_code: MO + output: + mo_capital_gains_subtraction: 1_000 + + +- name: Post capital gains subtraction law and qualified premiums, health insurance + period: 2025 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 1_000 + short_term_capital_gains: 500 + health_insurance_premiums: 12_000 + medical_out_of_pocket_expenses: 12_000 + tax_units: + tax_unit1: + members: [person1] + medical_expense_deduction: 0 + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1] + state_code: MO + output: + mo_qualified_health_insurance_premiums: 12_000 + + +- name: Post capital gains subtraction law and qualified premiums, subtractions + period: 2025 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 1_000 + short_term_capital_gains: 500 + health_insurance_premiums: 12_000 + medical_out_of_pocket_expenses: 12_000 + tax_units: + tax_unit1: + members: [person1] + medical_expense_deduction: 0 + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1] + state_code: MO + output: + mo_agi_subtractions: 13_000 + + +- name: Married couple - capital gains allocated by person + period: 2025 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 6_000 + short_term_capital_gains: 0 + health_insurance_premiums: 6_000 + medical_out_of_pocket_expenses: 6_000 + person2: + long_term_capital_gains: 4_000 + short_term_capital_gains: 0 + health_insurance_premiums: 6_000 + medical_out_of_pocket_expenses: 6_000 + tax_units: + tax_unit1: + members: [person1, person2] + medical_expense_deduction: 0 + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1, person2] + state_code: MO + output: + # Person-level capital gains subtraction allocation: 60%/40% of 10_000 + mo_capital_gains_subtraction_person: [6_000, 4_000] + # Person-level health insurance: 50%/50% of 12_000 + mo_qualified_health_insurance_premiums: [6_000, 6_000] + # Total subtractions per person: 6_000+6_000=12_000 and 4_000+6_000=10_000 + mo_agi_subtractions: [12_000, 10_000] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction.yaml new file mode 100644 index 00000000000..f36c5927ffc --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction.yaml @@ -0,0 +1,65 @@ +- name: Pre capital gains subtraction law + period: 2024 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 1_000 + short_term_capital_gains: 500 + tax_units: + tax_unit1: + members: [person1] + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1] + state_code: MO + output: + mo_capital_gains_subtraction: 0 + +- name: Post capital gains subtraction law + period: 2025 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 1_000 + short_term_capital_gains: 500 + tax_units: + tax_unit1: + members: [person1] + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1] + state_code: MO + output: + mo_capital_gains_subtraction: 1_000 + +- name: Post capital gains subtraction law - married couple + period: 2025 + absolute_error_margin: 0 + input: + people: + person1: + long_term_capital_gains: 6_000 + short_term_capital_gains: 0 + person2: + long_term_capital_gains: 4_000 + short_term_capital_gains: 0 + tax_units: + tax_unit1: + members: [person1, person2] + tax_unit_itemizes: false + taxable_income: 100_000 + households: + household1: + members: [person1, person2] + state_code: MO + output: + # Tax unit level subtraction should be full 10_000 + mo_capital_gains_subtraction: 10_000 + # Person level subtraction should be allocated by LTCG share + mo_capital_gains_subtraction_person: [6_000, 4_000] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nc/tax/income/deductions/nc_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/nc/tax/income/deductions/nc_itemized_deductions.yaml index 8ecacbf5ae7..31a7a288278 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nc/tax/income/deductions/nc_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nc/tax/income/deductions/nc_itemized_deductions.yaml @@ -1,4 +1,4 @@ -- name: Real estate taxes capped +- name: Real estate taxes capped period: 2022 input: filing_status: JOINT @@ -10,7 +10,7 @@ output: nc_itemized_deductions: 19_000 -- name: Real estate taxes and mortgage capped +- name: Real estate taxes and mortgage capped period: 2022 input: filing_status: SURVIVING_SPOUSE diff --git a/policyengine_us/variables/gov/states/mo/tax/income/adjusted_gross_income/mo_adjusted_gross_income.py b/policyengine_us/variables/gov/states/mo/tax/income/adjusted_gross_income/mo_adjusted_gross_income.py index d82fe9074ff..0fdf4f4a5d9 100644 --- a/policyengine_us/variables/gov/states/mo/tax/income/adjusted_gross_income/mo_adjusted_gross_income.py +++ b/policyengine_us/variables/gov/states/mo/tax/income/adjusted_gross_income/mo_adjusted_gross_income.py @@ -39,5 +39,5 @@ def formula(person, period, parameters): ) fed_agi = gross_income - ind_total_personal_alds - allocated_alds # return MO AGI including MO additions and MO subtractions - subtractions = person("mo_qualified_health_insurance_premiums", period) + subtractions = person("mo_agi_subtractions", period) return max_(0, fed_agi - subtractions) diff --git a/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.py b/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.py new file mode 100644 index 00000000000..22be9f85413 --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class mo_agi_subtractions(Variable): + value_type = float + entity = Person + label = "Missouri AGI subtractions" + unit = USD + definition_period = YEAR + defined_for = StateCode.MO + + def formula(person, period, parameters): + p = parameters(period).gov.states.mo.tax.income.subtractions + total_subtractions = add(person, period, p.agi_subtractions) + # Prevent negative subtractions from acting as additions + return max_(0, total_subtractions) diff --git a/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction.py b/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction.py new file mode 100644 index 00000000000..fe6387e9759 --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class mo_capital_gains_subtraction(Variable): + value_type = float + entity = TaxUnit + label = "Missouri capital gains subtraction" + unit = USD + definition_period = YEAR + reference = ( + "https://dor.mo.gov/faq/taxation/individual/capital-gains-subtraction.html", # MO form MO-A + ) + defined_for = StateCode.MO + + def formula(tax_unit, period, parameters): + net_capital_gain = max_(0, tax_unit("net_capital_gain", period)) + p = parameters( + period + ).gov.states.mo.tax.income.subtractions.net_capital_gain + return net_capital_gain * p.rate diff --git a/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction_person.py b/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction_person.py new file mode 100644 index 00000000000..5cb6ed362dc --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/tax/income/subtractions/mo_capital_gains_subtraction_person.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class mo_capital_gains_subtraction_person(Variable): + value_type = float + entity = Person + label = "Missouri capital gains subtraction for each person" + unit = USD + definition_period = YEAR + reference = ( + "https://dor.mo.gov/faq/taxation/individual/capital-gains-subtraction.html", + ) + defined_for = StateCode.MO + + def formula(person, period, parameters): + tax_unit = person.tax_unit + # Get the tax unit level capital gains subtraction + tax_unit_subtraction = tax_unit("mo_capital_gains_subtraction", period) + # Allocate proportionally based on each person's share of + # capital gains (both short-term and long-term) to match + # the net_capital_gain used at the tax unit level + person_cg = person("capital_gains", period) + tax_unit_cg = tax_unit.sum(person_cg) + # Use mask to avoid divide-by-zero, default to zero allocation + person_share = np.zeros_like(tax_unit_cg) + mask = tax_unit_cg > 0 + person_share[mask] = person_cg[mask] / tax_unit_cg[mask] + return person_share * tax_unit_subtraction