From 831542a134cfa974abb7fe45fc37549331d44993 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 10 Oct 2026 13:26:34 -0400 Subject: [PATCH 1/4] Count gambling winnings in federal gross income and fix the wagering losses deduction Fixes #9637. - gambling_winnings joins gov.irs.gross_income.sources (26 U.S.C. 61(a), Schedule 1 line 8b). - wagering_losses_deduction is min(rate x losses, winnings) for the head and spouse; the rate is 1 through 2025 and 0.9 from 2026 (P.L. 119-21 sec. 70114). - The deduction moves into the Schedule A list (line 16) and the pre-2018 section 68(c) exclusions. - States: AL, CA, DC, DE, HI, KS, MI, MN, MS, MT, NY, PA, VA, WI. Co-Authored-By: Claude Opus 5.5 --- ...ix-gambling-winnings-gross-income.fixed.md | 1 + .../deductions/deductions_if_itemizing.yaml | 3 - .../limitation/excluded_deductions.yaml | 3 +- .../itemized/wagering_losses/rate.yaml | 17 ++ .../irs/deductions/itemized_deductions.yaml | 11 + .../gov/irs/gross_income/sources.yaml | 9 +- .../tax/income/agi/gross_income_sources.yaml | 3 + .../income/deductions/itemized/sources.yaml | 5 + .../itemized/limit/excluded_deductions.yaml | 5 + .../income/deductions/itemized/sources.yaml | 4 +- .../income/deductions/itemized/sources.yaml | 4 + .../states/mi/tax/income/subtractions.yaml | 19 ++ .../deductions/itemized/misc_deductions.yaml | 11 +- .../tax/income/nontaxable_income_sources.yaml | 4 + .../itemized/reduction/applicable.yaml | 4 + .../itemized/reduction/reducible.yaml | 6 +- .../crfb/senior_deduction_extension.py | 1 - ...temized_deduction_limitation_properties.py | 12 +- ...axable_income_deductions_if_itemizing.yaml | 21 +- .../itemizing/wagering_losses_deduction.yaml | 92 ++++++++ .../gambling_winnings_and_losses.yaml | 131 +++++++++++ .../gov/states/al/tax/income/al_agi.yaml | 11 + .../itemized/al_gambling_loss_deduction.yaml | 44 ++++ .../itemized/ca_itemized_deductions.yaml | 41 ++++ .../dc/tax/income/dc_itemized_deductions.yaml | 33 +++ .../itemized/de_itemized_deductions_indv.yaml | 28 +++ .../itemized/de_itemized_deductions_unit.yaml | 13 ++ .../itemized/hi_itemized_deductions.yaml | 33 +++ .../hi_reduced_itemized_deductions.yaml | 31 ++- .../ks/tax/income/ks_itemized_deductions.yaml | 30 +++ .../states/mi/tax/income/mi_subtractions.yaml | 44 ++++ .../mn/tax/income/mn_itemized_deductions.yaml | 16 ++ .../itemized/ms_itemized_deductions_unit.yaml | 12 + .../mt_wagering_losses_deduction.yaml | 54 +++++ .../ny_itemized_deductions_phase_out.yaml | 17 ++ .../ny_wagering_losses_deduction.yaml | 51 +++++ .../pa_total_taxable_income.yaml | 52 +++++ ...pa_property_tax_or_rent_rebate_income.yaml | 27 ++- .../deductions/va_itemized_deductions.yaml | 35 +++ .../income/wi_itemized_deduction_credit.yaml | 14 ++ ...gambling_winnings_and_losses_properties.py | 215 ++++++++++++++++++ .../itemizing/wagering_losses_deduction.py | 22 +- .../itemized/al_gambling_loss_deduction.py | 31 +++ .../ca_itemized_deductions_pre_limitation.py | 2 + .../itemized/ca_wagering_losses_deduction.py | 34 +++ .../deductions/dc_itemized_deductions.py | 4 + .../itemized/de_itemized_deductions_indv.py | 1 + .../hi_reduced_itemized_deductions.py | 9 +- .../deductions/ks_itemized_deductions.py | 7 +- .../mi_wagering_losses_deduction.py | 30 +++ .../deductions/mn_itemized_deductions.py | 10 +- .../itemized/ms_itemized_deductions_unit.py | 10 + .../general/mt_wagering_losses_deduction.py | 31 +++ .../itemized/ny_itemized_deductions_max.py | 2 + .../ny_itemized_deductions_phase_out.py | 21 +- .../pre_tcja/ny_wagering_losses_deduction.py | 27 +++ .../taxable_income/pa_gambling_loss_offset.py | 30 +++ .../pa_property_tax_or_rent_rebate_income.py | 12 +- .../va_reduced_itemized_deductions.py | 3 +- .../wi_itemized_deduction_credit_potential.py | 9 +- 60 files changed, 1419 insertions(+), 43 deletions(-) create mode 100644 changelog.d/fix-gambling-winnings-gross-income.fixed.md create mode 100644 policyengine_us/parameters/gov/irs/deductions/itemized/wagering_losses/rate.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/gambling_winnings_and_losses.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/al/tax/income/deductions/itemized/al_gambling_loss_deduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_unit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ms/tax/income/deductions/itemized/ms_itemized_deductions_unit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_wagering_losses_deduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_wagering_losses_deduction.yaml create mode 100644 policyengine_us/tests/unit/test_gambling_winnings_and_losses_properties.py create mode 100644 policyengine_us/variables/gov/states/al/tax/income/deductions/itemized/al_gambling_loss_deduction.py create mode 100644 policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_wagering_losses_deduction.py create mode 100644 policyengine_us/variables/gov/states/mi/tax/income/deductions/mi_wagering_losses_deduction.py create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_wagering_losses_deduction.py create mode 100644 policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/pre_tcja/ny_wagering_losses_deduction.py create mode 100644 policyengine_us/variables/gov/states/pa/tax/income/taxable_income/pa_gambling_loss_offset.py diff --git a/changelog.d/fix-gambling-winnings-gross-income.fixed.md b/changelog.d/fix-gambling-winnings-gross-income.fixed.md new file mode 100644 index 00000000000..02ddb809178 --- /dev/null +++ b/changelog.d/fix-gambling-winnings-gross-income.fixed.md @@ -0,0 +1 @@ +Count gambling winnings in federal gross income, limit the wagering losses deduction to 90% of losses from 2026 and to the head's and spouse's gambling, treat it as a Schedule A itemized deduction, and align the states that tax gambling winnings or build on federal itemized deductions. diff --git a/policyengine_us/parameters/gov/irs/deductions/deductions_if_itemizing.yaml b/policyengine_us/parameters/gov/irs/deductions/deductions_if_itemizing.yaml index 9d055329b32..8283c8ab53e 100644 --- a/policyengine_us/parameters/gov/irs/deductions/deductions_if_itemizing.yaml +++ b/policyengine_us/parameters/gov/irs/deductions/deductions_if_itemizing.yaml @@ -2,12 +2,10 @@ description: Deductions from taxable income if itemizing. values: 2018-01-01: - qualified_business_income_deduction - - wagering_losses_deduction - itemized_taxable_income_deductions 2025-01-01: - qualified_business_income_deduction - - wagering_losses_deduction - itemized_taxable_income_deductions - tip_income_deduction - overtime_income_deduction @@ -16,7 +14,6 @@ values: 2029-01-01: - qualified_business_income_deduction - - wagering_losses_deduction - itemized_taxable_income_deductions metadata: diff --git a/policyengine_us/parameters/gov/irs/deductions/itemized/limitation/excluded_deductions.yaml b/policyengine_us/parameters/gov/irs/deductions/itemized/limitation/excluded_deductions.yaml index 96e642fd5db..b37a9d2fb0a 100644 --- a/policyengine_us/parameters/gov/irs/deductions/itemized/limitation/excluded_deductions.yaml +++ b/policyengine_us/parameters/gov/irs/deductions/itemized/limitation/excluded_deductions.yaml @@ -5,8 +5,6 @@ values: # and wagering losses (section 165(c)(2), (c)(3) and (d)). # investment_interest_expense is the investment interest that # interest_deduction includes through non_mortgage_interest. - # wagering_losses_deduction is deducted outside - # total_itemized_taxable_income_deductions, so it never enters the base. # The 2017 worksheet also removes qualified disaster-relief contributions # (P.L. 115-63 sec. 504(a)(3), P.L. 115-123 sec. 20104(a)(3)), which are # not modeled. @@ -14,6 +12,7 @@ values: - medical_expense_deduction - investment_interest_expense - casualty_loss_deduction + - wagering_losses_deduction metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/irs/deductions/itemized/wagering_losses/rate.yaml b/policyengine_us/parameters/gov/irs/deductions/itemized/wagering_losses/rate.yaml new file mode 100644 index 00000000000..86e3b6d8a1a --- /dev/null +++ b/policyengine_us/parameters/gov/irs/deductions/itemized/wagering_losses/rate.yaml @@ -0,0 +1,17 @@ +description: The US allows this share of wagering losses as an itemized deduction, up to wagering gains. +values: + 0000-01-01: 1 + # P.L. 119-21 sec. 70114 rewrote section 165(d)(1) for taxable years + # beginning after December 31, 2025. + 2026-01-01: 0.9 +metadata: + unit: /1 + period: year + label: Wagering losses deduction rate + reference: + - title: 26 U.S. Code § 165(d) - Wagering losses + href: https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title26-section165&num=0&edition=prelim + - title: P.L. 119-21, sec. 70114 - Extension and modification of limitation on wagering losses + href: https://www.govinfo.gov/content/pkg/PLAW-119publ21/pdf/PLAW-119publ21.pdf#page=96 + - title: 2024 Instructions for Schedule A (Form 1040), line 16 - Gambling losses + href: https://www.irs.gov/pub/irs-prior/i1040sca--2024.pdf#page=11 diff --git a/policyengine_us/parameters/gov/irs/deductions/itemized_deductions.yaml b/policyengine_us/parameters/gov/irs/deductions/itemized_deductions.yaml index 14d369f6999..2353367d41d 100644 --- a/policyengine_us/parameters/gov/irs/deductions/itemized_deductions.yaml +++ b/policyengine_us/parameters/gov/irs/deductions/itemized_deductions.yaml @@ -7,6 +7,8 @@ values: - medical_expense_deduction - casualty_loss_deduction - misc_deduction + # Gambling losses, Schedule A line 16 (other itemized deductions). + - wagering_losses_deduction 2020-01-01: - charitable_deduction - charitable_deduction_for_non_itemizers @@ -15,6 +17,8 @@ values: - medical_expense_deduction - casualty_loss_deduction - misc_deduction + # Gambling losses, Schedule A line 16 (other itemized deductions). + - wagering_losses_deduction 2022-01-01: - charitable_deduction - interest_deduction @@ -22,6 +26,13 @@ values: - medical_expense_deduction - casualty_loss_deduction - misc_deduction + # Gambling losses, Schedule A line 16 (other itemized deductions). + - wagering_losses_deduction metadata: unit: list label: itemized deductions + reference: + - title: 2024 Schedule A (Form 1040), lines 4-17 + href: https://www.irs.gov/pub/irs-prior/f1040sa--2024.pdf#page=1 + - title: 2024 Instructions for Schedule A (Form 1040), line 16 - Other itemized deductions + href: https://www.irs.gov/pub/irs-prior/i1040sca--2024.pdf#page=11 diff --git a/policyengine_us/parameters/gov/irs/gross_income/sources.yaml b/policyengine_us/parameters/gov/irs/gross_income/sources.yaml index af8391cacdf..8e93dd5262b 100644 --- a/policyengine_us/parameters/gov/irs/gross_income/sources.yaml +++ b/policyengine_us/parameters/gov/irs/gross_income/sources.yaml @@ -33,6 +33,9 @@ values: - taxable_retirement_distributions - taxable_roth_conversions - miscellaneous_income + # Gambling winnings, including lotteries and raffles (Schedule 1 line + # 8b). Only itemizers deduct the losses (wagering_losses_deduction). + - gambling_winnings # Listed separately on 1040 line 8g. - ak_permanent_fund_dividend # Alimony from divorces executed before the TCJA cutoff (Schedule 1 line 2a). @@ -51,7 +54,11 @@ metadata: href: https://www.law.cornell.edu/uscode/text/26/111 - title: 26 U.S. Code § 61(a)(14) - Income from an interest in an estate or trust href: https://www.law.cornell.edu/uscode/text/26/61#a_14 - - title: 2024 Schedule 1 (Form 1040), line 5 - Rental real estate, royalties, partnerships, S corporations, trusts, etc. + - title: 2024 Schedule 1 (Form 1040), line 5 - Rental real estate, royalties, partnerships, S corporations, trusts, etc., and line 8b - Gambling href: https://www.irs.gov/pub/irs-prior/f1040s1--2024.pdf#page=1 - title: 2024 Instructions for Schedule E (Form 1040), Part III - Income or Loss From Estates and Trusts href: https://www.irs.gov/pub/irs-prior/i1040se--2024.pdf#page=11 + - title: 2024 Instructions for Form 1040, Schedule 1 line 8b - Gambling + href: https://www.irs.gov/pub/irs-prior/i1040gi--2024.pdf#page=85 + - title: 2025 Instructions for Form 1040, Schedule 1 line 8b - Gambling + href: https://www.irs.gov/pub/irs-prior/i1040gi--2025.pdf#page=91 diff --git a/policyengine_us/parameters/gov/states/al/tax/income/agi/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/al/tax/income/agi/gross_income_sources.yaml index c21a24968de..cff5b2322c4 100644 --- a/policyengine_us/parameters/gov/states/al/tax/income/agi/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/al/tax/income/agi/gross_income_sources.yaml @@ -19,6 +19,9 @@ values: - partnership_s_corp_income - farm_operations_income - farm_rent_income + # Prizes and awards: contests, lotteries and gambling winnings (Form 40 + # page 2, Part I, other income). + - gambling_winnings metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/sources.yaml b/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/sources.yaml index bad60cdd74a..4197a465dc5 100644 --- a/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/sources.yaml +++ b/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/sources.yaml @@ -12,6 +12,9 @@ values: - al_casualty_loss_deduction # Section (a), (6) - al_misc_deduction # Section (a), (23) - al_interest_deduction # Section (a), (2) + # Schedule A line 25: gambling losses to the extent of gambling winnings, + # not subject to the 2% limit. + - al_gambling_loss_deduction metadata: unit: list @@ -28,3 +31,5 @@ metadata: href: https://www.revenue.alabama.gov/ultraviewer/viewer/basic_viewer/index.html?form=2024/01/23f40schabdc_blk.pdf#page=1 - title: 2024 Alabama Income Tax Instructions href: https://www.revenue.alabama.gov/wp-content/uploads/2025/01/24f40bk.pdf#page=18 + - title: 2025 Alabama Income Tax Instructions, Schedule A line 25 - gambling losses + href: https://www.revenue.alabama.gov/wp-content/uploads/2026/01/25f40bk.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/deductions/itemized/limit/excluded_deductions.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/deductions/itemized/limit/excluded_deductions.yaml index d3d5fd934b8..120fb6de409 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/deductions/itemized/limit/excluded_deductions.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/deductions/itemized/limit/excluded_deductions.yaml @@ -4,12 +4,17 @@ values: - medical_expense_deduction - casualty_loss_deduction - non_mortgage_interest + # Itemized Deductions Worksheet line 2: "plus any gambling losses + # included on line 16". + - ca_wagering_losses_deduction metadata: unit: list period: year label: itemized deductions excluded from CA high-AGI limitation reference: + - title: 2025 Form 540 booklet, Schedule CA (540) Itemized Deductions Worksheet, line 2 + href: https://www.ftb.ca.gov/forms/2025/2025-540-booklet.pdf#page=68 - title: 2021 Form 540 Schedule CA instructions href: https://www.ftb.ca.gov/forms/2021/2021-540-ca-instructions.html - title: 2022 Form 540 Schedule CA instructions diff --git a/policyengine_us/parameters/gov/states/de/tax/income/deductions/itemized/sources.yaml b/policyengine_us/parameters/gov/states/de/tax/income/deductions/itemized/sources.yaml index ea8e0ca8dbe..d3f59d8c69e 100644 --- a/policyengine_us/parameters/gov/states/de/tax/income/deductions/itemized/sources.yaml +++ b/policyengine_us/parameters/gov/states/de/tax/income/deductions/itemized/sources.yaml @@ -5,6 +5,8 @@ values: - charitable_deduction - interest_deduction - casualty_loss_deduction + # PIT-RSA line 16, other itemized deductions permitted under federal law. + - wagering_losses_deduction metadata: unit: list period: year @@ -14,6 +16,6 @@ metadata: href: https://revenuefiles.delaware.gov/2022/TY22_PIT-RSA_2022-02_PaperInteractive.pdf - title: Code of Delaware. Title30. CHAPTER 11. Personal Income Tax, § 1109 href: https://delcode.delaware.gov/title30/c011/sc02/index.html - - title: 2025 Delaware Individual Income Tax Return Instructions + - title: "2025 Delaware Individual Income Tax Return Instructions #page 7,12" href: https://revenuefiles.delaware.gov/2025/PITForms_Instructions/Instructions/PIT-RES_Instructions_2025-01.pdf#page=7 diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/deductions/itemized/sources.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/deductions/itemized/sources.yaml index 20406023cc9..a2ec70cd98c 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/deductions/itemized/sources.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/deductions/itemized/sources.yaml @@ -6,6 +6,8 @@ values: - hi_interest_deduction - hi_casualty_loss_deduction - hi_salt_deduction + # Worksheet A-6, line 30: gambling losses, up to gambling winnings. + - wagering_losses_deduction metadata: unit: list period: year @@ -23,5 +25,7 @@ metadata: href: https://files.hawaii.gov/tax/forms/2018/n11ins.pdf#page=19 - title: Hawaii Income Tax Law, Chapter 235, Section 235-2.4 href: https://files.hawaii.gov/tax/legal/hrs/hrs_235.pdf#page=10 + - title: 2025 Hawaii N-11 Instructions, Worksheet A-6 line 30 - Gambling losses + href: https://files.hawaii.gov/tax/forms/2025/n11ins.pdf#page=19 - title: 2025 Hawaii N-11 Instructions Itemized Deductions href: https://files.hawaii.gov/tax/forms/current/n11ins.pdf#page=17 diff --git a/policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml b/policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml index 62d9a981878..f7c8883e128 100644 --- a/policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml @@ -11,6 +11,20 @@ values: - mi_interest_dividends_capital_gains_deduction # Line 27 - mi_529_deduction - salt_refund_income # Line 16 + # 2021 PA 168 added a deduction for the wagering losses a casual gambler + # deducts on the federal return, for tax years beginning in 2021. + 2021-01-01: + - us_govt_interest # Line 10 + - military_retirement_pay # Line 11 + - taxable_social_security # Line 14 + - military_service_income # Line 14 + - section_22_income # Line 22 + - mi_standard_deduction # Line 24 & 25 + - mi_pension_benefit # Line 26 + - mi_interest_dividends_capital_gains_deduction # Line 27 + - mi_529_deduction + - salt_refund_income # Line 16 + - mi_wagering_losses_deduction # Line 23 (2025), miscellaneous subtractions 2026-01-01: - us_govt_interest # Line 10 - military_retirement_pay # Line 11 @@ -24,6 +38,7 @@ values: - mi_qualified_tips_deduction # Qualified tips (PA 24 of 2025), TY2026-2028 - mi_qualified_overtime_deduction # Qualified overtime compensation (PA 24 of 2025), TY2026-2028 - salt_refund_income # Line 16 + - mi_wagering_losses_deduction # Line 23 (2025), miscellaneous subtractions metadata: unit: list label: Michigan taxable income subtraction sources @@ -35,6 +50,10 @@ metadata: href: https://www.michigan.gov/taxes/-/media/Project/Websites/taxes/Forms/IIT/TY2023/BOOK_MI-1040.pdf#page=47 - title: Michigan Legal Code Section 206.30 href: https://www.legislature.mi.gov/Laws/MCL?objectName=mcl-206-30 + - title: Michigan Treasury notice - New Tax Treatment of Wagering Losses for Casual Gamblers (2021 PA 168) + href: https://www.michigan.gov/taxes/rep-legal/notices/notice-new-tax-treatment-of-wagering-losses-for-casual-gamblers-under-the-michigan-income-tax-act + - title: 2025 MI-1040 booklet, Schedule 1 line 23 - Miscellaneous subtractions (wagering losses) + href: https://www.michigan.gov/taxes/-/media/Project/Websites/taxes/Forms/IIT/TY2025/MI-1040-Book.pdf#page=16 - title: Michigan Standard Deduction href: https://web.archive.org/web/20250202140014/https://www.michigan.gov/taxes/iit/retirement-and-pension-benefits/michigan-standard-deduction - title: Michigan 2022 MI-1040 Individual Income Tax FORMS AND INSTRUCTIONS diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml index 1eeb0351b1a..521c6736296 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml @@ -3,13 +3,22 @@ values: 2021-01-01: - mt_child_dependent_care_expense_deduction - casualty_loss_deduction - 2024-01-01: [] + # Gambling losses, up to gambling winnings (2023 Form 2 instructions). + - mt_wagering_losses_deduction + # From 2024 Montana starts from federal taxable income, which carries the + # federal itemized deductions. + 2024-01-01: + - mt_wagering_losses_deduction metadata: unit: list label: Montana miscellaneous deductions period: year reference: + - title: 2023 Montana Form 2 instructions, itemized deductions - gambling losses + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=39 + - title: 2025 Montana Form 2 instructions, line 2 - federal standard deduction or federal itemized deductions + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=13 - title: Montana Individual Income Tax Return (Form 2) 2024 href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=8 - title: Montana Individual Income Tax Return (Form 2) 2022 diff --git a/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml b/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml index e5270142c66..7a3dd5c276b 100644 --- a/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml @@ -8,9 +8,13 @@ values: - taxable_social_security - us_govt_interest - salt_refund_income + # PA-40 Schedule T line 4: the cost of bets comes off the winnings. + - pa_gambling_loss_offset metadata: unit: currency-USD label: PA nontaxable income sources reference: - title: 2021 Pennsylvania PIT Return Instructions (PA-40 IN) href: https://www.pa.gov/content/dam/copapwp-pagov/en/revenue/documents/formsandpublications/formsforindividuals/pit/documents/2021/2021_pa-40in.pdf#page=8 + - title: 2025 PA-40 Schedule T - Gambling and Lottery Winnings + href: https://www.pa.gov/content/dam/copapwp-pagov/en/revenue/documents/formsandpublications/formsforindividuals/pit/documents/2025/2025_pa-40t.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/applicable.yaml b/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/applicable.yaml index 2c9e4102ca5..47a20326b85 100644 --- a/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/applicable.yaml +++ b/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/applicable.yaml @@ -7,11 +7,15 @@ values: - real_estate_taxes - casualty_loss_deduction - va_capped_state_and_local_sales_or_income_tax + # Schedule A line 16a, gambling losses. + - wagering_losses_deduction metadata: unit: list period: year label: Virginia itemized deductions reduction applicable deduction sources reference: + - title: 2025 Virginia Schedule A Itemized Deductions, line 16a and Limited Itemized Deduction Worksheet line 1 + href: https://www.tax.virginia.gov/sites/default/files/taxforms/individual-income-tax/2025/schedule-2025.pdf#page=1 - title: 2024 Virginia Schedule A Itemized Deductions href: https://www.tax.virginia.gov/sites/default/files/taxforms/individual-income-tax/2024/schedule-2024.pdf#page=2 - title: 2023 Virginia Schedule A Itemized Deductions diff --git a/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/reducible.yaml b/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/reducible.yaml index 8518c31559b..4775e39d0a3 100644 --- a/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/reducible.yaml +++ b/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/reducible.yaml @@ -3,13 +3,17 @@ values: 2013-01-01: - medical_expense_deduction - investment_interest_expense - - gambling_losses + # Worksheet line 2: "any gambling losses included on Line 16a", which + # is the deduction allowed, not the losses incurred. + - wagering_losses_deduction - casualty_loss_deduction metadata: unit: list period: year label: Virginia itemized deductions reduction reducible deduction sources reference: + - title: 2025 Virginia Schedule A, Limited Itemized Deduction Worksheet line 2 + href: https://www.tax.virginia.gov/sites/default/files/taxforms/individual-income-tax/2025/schedule-2025.pdf#page=2 - title: 2024 Virginia Schedule A Itemized Deductions href: https://www.tax.virginia.gov/sites/default/files/taxforms/individual-income-tax/2024/schedule-2024.pdf#page=2 - title: 2023 Virginia Schedule A Itemized Deductions diff --git a/policyengine_us/reforms/crfb/senior_deduction_extension.py b/policyengine_us/reforms/crfb/senior_deduction_extension.py index 56bd3d19c4f..5b38a9ae641 100644 --- a/policyengine_us/reforms/crfb/senior_deduction_extension.py +++ b/policyengine_us/reforms/crfb/senior_deduction_extension.py @@ -10,7 +10,6 @@ def modify_parameters(parameters): start=instant("2029-01-01"), value=[ "qualified_business_income_deduction", - "wagering_losses_deduction", "itemized_taxable_income_deductions", "additional_senior_deduction", ], diff --git a/policyengine_us/tests/core/test_itemized_deduction_limitation_properties.py b/policyengine_us/tests/core/test_itemized_deduction_limitation_properties.py index 36c428c7094..4d6fb96038b 100644 --- a/policyengine_us/tests/core/test_itemized_deduction_limitation_properties.py +++ b/policyengine_us/tests/core/test_itemized_deduction_limitation_properties.py @@ -29,9 +29,9 @@ 7. With the OBBB structure switched off in 2026 (the prior-law counterfactual), the pre-2026 worksheet logic applies with the 2026 applicable amounts. -Gambling losses are deducted outside total_itemized_taxable_income_deductions -(wagering_losses_deduction), so they never enter the limited base; they are -not generated here. +Gambling losses (wagering_losses_deduction, Schedule A line 16) are part of +total_itemized_taxable_income_deductions and are one of the section 68(c) +exclusions, so they are generated here as an excluded deduction. """ from functools import cache @@ -59,7 +59,11 @@ # Components of total_itemized_taxable_income_deductions, split by whether # section 68(c) excludes them. Mortgage and investment interest are person # inputs that interest_deduction adds up. -EXCLUDED = ("medical_expense_deduction", "casualty_loss_deduction") +EXCLUDED = ( + "medical_expense_deduction", + "casualty_loss_deduction", + "wagering_losses_deduction", +) EXCLUDED_PERSON = ("investment_interest_expense",) OTHER = ("charitable_deduction", "salt_deduction", "misc_deduction") OTHER_PERSON = ("deductible_mortgage_interest",) diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/taxable_income_deductions_if_itemizing.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/taxable_income_deductions_if_itemizing.yaml index fb8dfc3a11a..225f1a94b32 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/taxable_income_deductions_if_itemizing.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/taxable_income_deductions_if_itemizing.yaml @@ -1,12 +1,11 @@ -- name: Integration test, reduction of itemized deductions but not QBID or wagering losses +- name: Integration test, reduction of itemized deductions but not QBID period: 2024 input: total_itemized_taxable_income_deductions: 1_000 itemized_taxable_income_deductions_reduction: 2_000 qualified_business_income_deduction: 1_000 - wagering_losses_deduction: 500 output: - taxable_income_deductions_if_itemizing: 1_500 + taxable_income_deductions_if_itemizing: 1_000 - name: Integration test, some itemized deductions over reduction threshold period: 2024 @@ -14,6 +13,18 @@ total_itemized_taxable_income_deductions: 3_000 itemized_taxable_income_deductions_reduction: 2_000 qualified_business_income_deduction: 1_000 - wagering_losses_deduction: 500 output: - taxable_income_deductions_if_itemizing: 2_500 + taxable_income_deductions_if_itemizing: 2_000 + +- name: Wagering losses are part of the itemized deductions total, not a separate deduction. + period: 2024 + input: + wagering_losses_deduction: 500 + charitable_deduction: 3_000 + qualified_business_income_deduction: 1_000 + output: + total_itemized_taxable_income_deductions: 3_500 + itemized_taxable_income_deductions: 3_500 + # 3,500 of itemized deductions and 1,000 of QBID; the wagering losses + # are not added a second time. + taxable_income_deductions_if_itemizing: 4_500 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.yaml index 6ded087918c..bada2192326 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.yaml @@ -69,3 +69,95 @@ members: [person1, person2] output: wagering_losses_deduction: 5 + +- name: Through 2025 all losses count, up to winnings. + absolute_error_margin: 0 + period: 2025 + input: + gambling_winnings: 10_000 + gambling_losses: 8_000 + output: + wagering_losses_deduction: 8_000 + +- name: Through 2025 losses above winnings are not deductible. + absolute_error_margin: 0 + period: 2025 + input: + gambling_winnings: 10_000 + gambling_losses: 12_000 + output: + wagering_losses_deduction: 10_000 + +- name: From 2026 only 90% of losses count. + absolute_error_margin: 0 + period: 2026 + input: + gambling_winnings: 10_000 + gambling_losses: 8_000 + output: + # 90% of 8,000 + wagering_losses_deduction: 7_200 + +- name: From 2026 the winnings cap applies after the 90% share. + absolute_error_margin: 0 + period: 2026 + input: + gambling_winnings: 10_000 + gambling_losses: 12_000 + output: + # min(90% of 12,000, 10,000) + wagering_losses_deduction: 10_000 + +- name: From 2026 equal winnings and losses leave 10% of the winnings taxed. + absolute_error_margin: 0 + period: 2026 + input: + gambling_winnings: 30_000 + gambling_losses: 30_000 + output: + wagering_losses_deduction: 27_000 + +- name: A dependent's gambling is not on the parent's return. + absolute_error_margin: 0 + period: 2024 + input: + people: + parent: + age: 40 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 10_000 + gambling_losses: 10_000 + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + output: + wagering_losses_deduction: 0 + +- name: A dependent's losses cannot use up the parent's winnings. + absolute_error_margin: 0 + period: 2024 + input: + people: + parent: + age: 40 + gambling_winnings: 10_000 + gambling_losses: 2_000 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 5_000 + gambling_losses: 9_000 + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + output: + # The parent's own 2,000, not min(11,000, 15,000). + wagering_losses_deduction: 2_000 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/gambling_winnings_and_losses.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/gambling_winnings_and_losses.yaml new file mode 100644 index 00000000000..0eef3f1d758 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/gambling_winnings_and_losses.yaml @@ -0,0 +1,131 @@ +# Gambling winnings are gross income (26 U.S.C. 61(a); Schedule 1 line 8b). +# Gambling losses are an itemized deduction up to the winnings (26 U.S.C. +# 165(d); Schedule A line 16), 90% of the losses from 2026 (P.L. 119-21 +# sec. 70114). The cases follow PolicyEngine/policyengine-us#9637: a single +# filer aged 40 in Texas with 60,000 of wages. The state and local tax +# deduction is set to zero so each figure can be computed by hand. + +- name: 2024, no gambling. + absolute_error_margin: 0.01 + period: 2024 + input: + age: 40 + employment_income: 60_000 + salt_deduction: 0 + state_code: TX + output: + adjusted_gross_income: 60_000 + # 60,000 - 14,600 standard deduction + taxable_income: 45_400 + # 10% x 11,600 + 12% x 33,800 + income_tax: 5_216 + +- name: 2024, winnings are income and losses below the standard deduction do not help. + absolute_error_margin: 0.01 + period: 2024 + input: + age: 40 + employment_income: 60_000 + gambling_winnings: 10_000 + gambling_losses: 8_000 + salt_deduction: 0 + state_code: TX + output: + irs_gross_income: 70_000 + adjusted_gross_income: 70_000 + wagering_losses_deduction: 8_000 + itemized_taxable_income_deductions: 8_000 + tax_unit_itemizes: false + # 70,000 - 14,600 + taxable_income: 55_400 + # 1,160 + 12% x 35,550 + 22% x 8,250 + income_tax: 7_241 + +- name: 2024, an itemizer deducts losses against the winnings in income. + absolute_error_margin: 0.01 + period: 2024 + input: + age: 40 + employment_income: 60_000 + gambling_winnings: 30_000 + gambling_losses: 25_000 + salt_deduction: 0 + state_code: TX + output: + adjusted_gross_income: 90_000 + wagering_losses_deduction: 25_000 + itemized_taxable_income_deductions: 25_000 + tax_unit_itemizes: true + # 90,000 - 25,000 + taxable_income: 65_000 + # 1,160 + 4,266 + 22% x 17,850 + income_tax: 9_353 + +- name: 2024, equal winnings and losses still raise tax by replacing the standard deduction. + absolute_error_margin: 0.01 + period: 2024 + input: + age: 40 + employment_income: 60_000 + gambling_winnings: 20_000 + gambling_losses: 20_000 + salt_deduction: 0 + state_code: TX + output: + adjusted_gross_income: 80_000 + wagering_losses_deduction: 20_000 + tax_unit_itemizes: true + # 80,000 - 20,000, against 45,400 with no gambling + taxable_income: 60_000 + # 1,160 + 4,266 + 22% x 12,850 + income_tax: 8_253 + +- name: 2026, the itemizer deducts 90% of losses. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 60_000 + gambling_winnings: 30_000 + gambling_losses: 25_000 + salt_deduction: 0 + state_code: TX + output: + adjusted_gross_income: 90_000 + # 90% of 25,000 + wagering_losses_deduction: 22_500 + itemized_taxable_income_deductions: 22_500 + tax_unit_itemizes: true + # 90,000 - 22,500 + taxable_income: 67_500 + # 10% x 12,400 + 12% x 38,000 + 22% x 17,100 + income_tax: 9_562 + +- name: A dependent's winnings and losses do not change the parent's return. + absolute_error_margin: 0.01 + period: 2024 + input: + people: + parent: + age: 40 + employment_income: 60_000 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 30_000 + gambling_losses: 25_000 + tax_units: + tax_unit: + members: [parent, child] + salt_deduction: 0 + households: + household: + members: [parent, child] + state_code: TX + output: + irs_gross_income: [60_000, 0] + adjusted_gross_income: 60_000 + wagering_losses_deduction: 0 + tax_unit_itemizes: false + # 60,000 - 21,900 head of household standard deduction + taxable_income: 38_100 diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/al_agi.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/al_agi.yaml index d1b72912602..61f8a63a5c7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/al_agi.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/al_agi.yaml @@ -68,3 +68,14 @@ # AGI leaves all of them on the child's return. adjusted_gross_income: 40_000 al_agi: 48_500 + +- name: Alabama taxes gambling winnings. + absolute_error_margin: 0.01 + period: 2026 + input: + irs_employment_income: 50_000 + gambling_winnings: 20_000 + gambling_losses: 12_000 + state_code: AL + output: + al_agi: 70_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/deductions/itemized/al_gambling_loss_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/deductions/itemized/al_gambling_loss_deduction.yaml new file mode 100644 index 00000000000..9f2a5792722 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/deductions/itemized/al_gambling_loss_deduction.yaml @@ -0,0 +1,44 @@ +- name: Alabama deducts all gambling losses up to winnings in 2026. + absolute_error_margin: 0.01 + period: 2026 + input: + gambling_winnings: 20_000 + gambling_losses: 12_000 + state_code: AL + output: + # The federal deduction is 90% of the losses from 2026; Alabama's is not. + wagering_losses_deduction: 10_800 + al_gambling_loss_deduction: 12_000 + +- name: Alabama gambling losses are capped at winnings. + absolute_error_margin: 0.01 + period: 2025 + input: + gambling_winnings: 5_000 + gambling_losses: 12_000 + state_code: AL + output: + al_gambling_loss_deduction: 5_000 + +- name: A dependent's gambling is not on the parent's Alabama return. + absolute_error_margin: 0.01 + period: 2025 + input: + people: + parent: + age: 40 + gambling_winnings: 1_000 + gambling_losses: 10_000 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 20_000 + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: AL + output: + al_gambling_loss_deduction: 1_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions.yaml index 13ce42b7d1c..548ce7f38f5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions.yaml @@ -51,3 +51,44 @@ ca_itemized_deductions_pre_limitation: 10_000 output: ca_itemized_deductions: 7_000 # charity subject to limitation + +- name: California allows all gambling losses up to winnings in 2026 and does not limit them. + absolute_error_margin: 0.01 + period: 2026 + input: + filing_status: SINGLE + adjusted_gross_income: 1_000_000 + gambling_winnings: 10_000 + gambling_losses: 10_000 + state_code: CA + output: + # The federal deduction is 90% of the losses from 2026. + wagering_losses_deduction: 9_000 + ca_wagering_losses_deduction: 10_000 + ca_itemized_deductions_pre_limitation: 10_000 + # Gambling losses are outside the high-income limitation. + ca_itemized_deductions: 10_000 + +- name: California gambling losses are capped at winnings and exclude a dependent's. + absolute_error_margin: 0.01 + period: 2025 + input: + people: + parent: + age: 40 + gambling_winnings: 5_000 + gambling_losses: 8_000 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 10_000 + gambling_losses: 10_000 + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: CA + output: + ca_wagering_losses_deduction: 5_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_itemized_deductions.yaml index b4bc41434fc..5d01c6cfcd4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_itemized_deductions.yaml @@ -53,3 +53,36 @@ state_code: DC output: dc_itemized_deductions: 8_000 # = 1_000 + (12_000 - 100_000 * 0.05) + +- name: Wagering losses are outside the DC itemized deduction phase-out. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 190_000 + gambling_winnings: 20_000 + gambling_losses: 20_000 + state_code: DC + output: + dc_agi: 210_000 + # 90% of 20,000 from 2026 + wagering_losses_deduction: 18_000 + # The phase-out, 5% x (210,000 - 200,000) = 500, applies only to + # deductions other than medical, casualty and wagering losses. + dc_itemized_deductions: 18_000 + +- name: The DC phase-out still reduces other deductions held with wagering losses. + absolute_error_margin: 0.01 + period: 2025 + input: + age: 40 + employment_income: 190_000 + gambling_winnings: 20_000 + gambling_losses: 20_000 + charitable_deduction: 10_000 + state_code: DC + output: + dc_agi: 210_000 + wagering_losses_deduction: 20_000 + # 20,000 + (10,000 - 500) + dc_itemized_deductions: 29_500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.yaml b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.yaml index 6c405d41d19..547b1136b91 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.yaml @@ -198,3 +198,31 @@ state_code: DE output: de_itemized_deductions_indv: [0, 5_000, 0] + +- name: Wagering losses go to the spouse who had them. + absolute_error_margin: 0.01 + period: 2025 + input: + people: + head: + age: 40 + employment_income: 50_000 + gambling_winnings: 10_000 + gambling_losses: 6_000 + spouse: + age: 40 + employment_income: 50_000 + gambling_losses: 2_000 + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: DE + output: + de_itemized_deductions_unit: 8_000 + de_itemized_deductions_indv: [6_000, 2_000] diff --git a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_unit.yaml b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_unit.yaml new file mode 100644 index 00000000000..ff28767425d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_unit.yaml @@ -0,0 +1,13 @@ +- name: Delaware carries the federal wagering losses deduction. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 50_000 + gambling_winnings: 10_000 + gambling_losses: 8_000 + state_code: DE + output: + adjusted_gross_income: 60_000 + # 90% of 8,000 from 2026 + de_itemized_deductions_unit: 7_200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_itemized_deductions.yaml index 5a44ba7f696..1ef26ddbdaf 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_itemized_deductions.yaml @@ -31,3 +31,36 @@ hi_reduced_itemized_deductions: 4_500 output: hi_itemized_deductions: 4_500 + +- name: Hawaii allows gambling losses and does not reduce them at high income. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 200_000 + gambling_winnings: 10_000 + gambling_losses: 10_000 + state_code: HI + output: + hi_agi: 210_000 + # 90% of 10,000 from 2026 + hi_total_itemized_deductions: 9_000 + # Total Itemized Deductions Worksheet line 4: line 3 (gambling losses) + # is not less than line 1, so the deduction is not limited. + hi_itemized_deductions: 9_000 + +- name: The Hawaii limitation reduces other deductions held with gambling losses. + absolute_error_margin: 0.01 + period: 2025 + input: + age: 40 + employment_income: 200_000 + gambling_winnings: 10_000 + gambling_losses: 10_000 + charitable_deduction: 20_000 + state_code: HI + output: + hi_agi: 210_000 + hi_total_itemized_deductions: 30_000 + # Smaller of 80% x 20,000 and 3% x (210,000 - 166,800) = 1,296. + hi_itemized_deductions: 28_704 diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.yaml index 912c803624b..0afcdac5fed 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.yaml @@ -43,7 +43,9 @@ members: [person1, person2] state_code: HI output: - hi_reduced_itemized_deductions: 0 + # Worksheet line 8: income is not over 166,800, so the deduction is not + # limited and line 1 is entered. + hi_reduced_itemized_deductions: 10_000 - name: Reduced itemized deductions same as total period: 2022 @@ -66,4 +68,29 @@ members: [person1, person2] state_code: HI output: - hi_reduced_itemized_deductions: 0 + # Worksheet line 4: the medical, investment interest and casualty + # deductions (300 + 200 + 400) are not less than the total, so the + # deduction is not limited and line 1 is entered. + hi_reduced_itemized_deductions: 900 + +- name: Gambling losses are outside the limitation (worksheet line 2d). + period: 2025 + input: + tax_units: + tax_unit: + filing_status: SINGLE + wagering_losses_deduction: 4_000 + hi_agi: 266_800 + members: [person1] + hi_total_itemized_deductions: 10_000 + people: + person1: {} + households: + household: + members: [person1] + state_code: HI + output: + # Smaller of 80% x (10,000 - 4,000) = 4,800 and 3% x (266,800 - 166,800) + # = 3,000. + hi_reduced_itemized_deductions: 7_000 + diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/tax/income/ks_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/tax/income/ks_itemized_deductions.yaml index 63a6603f62b..17eb7b38c4c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/tax/income/ks_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/tax/income/ks_itemized_deductions.yaml @@ -19,3 +19,33 @@ state_code: KS output: ks_itemized_deductions: 12 + 9 + 2 + +- name: Kansas taxes gambling winnings but its itemized deductions leave out wagering losses. + absolute_error_margin: 0.01 + period: 2025 + input: + age: 40 + employment_income: 40_000 + gambling_winnings: 10_000 + gambling_losses: 8_000 + state_code: KS + output: + wagering_losses_deduction: 8_000 + ks_agi: 50_000 + # K.S.A. 79-32,120(a) lists only charity, medical care, home mortgage + # interest and property taxes. + ks_itemized_deductions: 0 + +- name: Kansas itemized deductions keep charity and drop wagering losses in 2026. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 40_000 + gambling_winnings: 10_000 + gambling_losses: 8_000 + charitable_deduction: 3_000 + state_code: KS + output: + wagering_losses_deduction: 7_200 + ks_itemized_deductions: 3_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/mi_subtractions.yaml b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/mi_subtractions.yaml index 046978ff58e..0e29541db4d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/mi_subtractions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/mi_subtractions.yaml @@ -170,3 +170,47 @@ mi_subtractions: 49_422.75 # 110,000 - 49,422.75 - 11,600 mi_taxable_income: 48_977.25 + +- name: A Michigan filer who itemizes federally subtracts the wagering losses deducted. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 50_000 + gambling_winnings: 20_000 + gambling_losses: 20_000 + state_code: MI + output: + tax_unit_itemizes: true + # 90% of 20,000 from 2026 + mi_wagering_losses_deduction: 18_000 + mi_subtractions: 18_000 + +- name: A Michigan filer who takes the federal standard deduction subtracts no wagering losses. + absolute_error_margin: 0.01 + period: 2025 + input: + age: 40 + employment_income: 50_000 + gambling_winnings: 10_000 + gambling_losses: 8_000 + state_code: MI + output: + tax_unit_itemizes: false + wagering_losses_deduction: 8_000 + mi_wagering_losses_deduction: 0 + mi_subtractions: 0 + +- name: Michigan allowed no wagering losses before 2021. + absolute_error_margin: 0.01 + period: 2020 + input: + age: 40 + employment_income: 50_000 + gambling_winnings: 20_000 + gambling_losses: 20_000 + tax_unit_itemizes: true + state_code: MI + output: + wagering_losses_deduction: 20_000 + mi_subtractions: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_itemized_deductions.yaml index 632dba542f1..d5fd12c21bd 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_itemized_deductions.yaml @@ -90,3 +90,19 @@ state_code: MN output: mn_itemized_deductions: 10_000 + +- name: Wagering losses are outside the Minnesota itemized deduction limitation. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 200_000 + gambling_winnings: 100_000 + gambling_losses: 50_000 + state_code: MN + output: + adjusted_gross_income: 300_000 + # 90% of 50,000 + wagering_losses_deduction: 45_000 + # Minn. Stat. 290.0122, subd. 2(d)(3): no reduction of the losses. + mn_itemized_deductions: 45_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/tax/income/deductions/itemized/ms_itemized_deductions_unit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/tax/income/deductions/itemized/ms_itemized_deductions_unit.yaml new file mode 100644 index 00000000000..c85fc97e272 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/tax/income/deductions/itemized/ms_itemized_deductions_unit.yaml @@ -0,0 +1,12 @@ +- name: Mississippi itemized deductions leave out the federal wagering losses deduction. + absolute_error_margin: 0.01 + period: 2025 + input: + gambling_winnings: 10_000 + gambling_losses: 8_000 + charitable_deduction: 3_000 + state_code: MS + output: + wagering_losses_deduction: 8_000 + # Mississippi income here has no gambling winnings to deduct them from. + ms_itemized_deductions_unit: 3_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_wagering_losses_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_wagering_losses_deduction.yaml new file mode 100644 index 00000000000..7562dc3b96f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_wagering_losses_deduction.yaml @@ -0,0 +1,54 @@ +- name: Montana allows the federal wagering losses deduction. + absolute_error_margin: 0.01 + period: 2023 + input: + age: 40 + employment_income: 50_000 + gambling_winnings: 30_000 + gambling_losses: 20_000 + state_code: MT + output: + mt_wagering_losses_deduction: 20_000 + mt_misc_deductions: 20_000 + +- name: From 2026 Montana carries 90% of the losses. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 50_000 + gambling_winnings: 30_000 + gambling_losses: 20_000 + state_code: MT + output: + mt_wagering_losses_deduction: 18_000 + mt_misc_deductions: 18_000 + +- name: The Montana spouse who reports the winnings claims the losses. + absolute_error_margin: 0.01 + period: 2023 + input: + people: + head: + age: 40 + gambling_winnings: 10_000 + spouse: + age: 40 + gambling_losses: 8_000 + child: + age: 10 + is_tax_unit_dependent: true + gambling_winnings: 5_000 + tax_units: + tax_unit: + members: [head, spouse, child] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse, child] + state_code: MT + output: + wagering_losses_deduction: 8_000 + mt_wagering_losses_deduction: [8_000, 0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_itemized_deductions_phase_out.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_itemized_deductions_phase_out.yaml index 07de472c2ad..78ea7537a7a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_itemized_deductions_phase_out.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_itemized_deductions_phase_out.yaml @@ -134,3 +134,20 @@ # L1 = 130,000 - 30,000 = 100,000; L4 = 80,000; L8 = 2,734.50. # Reduction = min(80,000, 2,734.50) = 2,734.50 (same as without tuition). ny_itemized_deductions_phase_out: 2_734.50 + +- name: Gambling losses are not subject to the New York overall limitation. + absolute_error_margin: 0.01 + period: 2025 + input: + filing_status: SINGLE + adjusted_gross_income: 1_000_000 + gambling_winnings: 50_000 + gambling_losses: 50_000 + ny_itemized_deductions_phase_out_applies: true + ny_salt_deduction: 0 + state_code: NY + output: + ny_wagering_losses_deduction: 50_000 + ny_itemized_deductions_max: 50_000 + # Worksheet line 1 equals line 2 (gambling losses), so nothing is limited. + ny_itemized_deductions_phase_out: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_wagering_losses_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_wagering_losses_deduction.yaml new file mode 100644 index 00000000000..127f2bf0a40 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_wagering_losses_deduction.yaml @@ -0,0 +1,51 @@ +- name: New York allows all gambling losses up to winnings in 2026. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + filing_status: SINGLE + employment_income: 50_000 + gambling_winnings: 20_000 + gambling_losses: 20_000 + ny_salt_deduction: 0 + state_code: NY + output: + # The federal deduction is 90% of the losses from 2026. + wagering_losses_deduction: 18_000 + ny_wagering_losses_deduction: 20_000 + ny_agi: 70_000 + ny_itemized_deductions: 20_000 + # 70,000 - 20,000 + ny_taxable_income: 50_000 + +- name: New York gambling losses are capped at winnings. + absolute_error_margin: 0.01 + period: 2025 + input: + gambling_winnings: 5_000 + gambling_losses: 8_000 + state_code: NY + output: + ny_wagering_losses_deduction: 5_000 + +- name: A dependent's gambling is not on the parent's New York return. + absolute_error_margin: 0.01 + period: 2025 + input: + people: + parent: + age: 40 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 10_000 + gambling_losses: 10_000 + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NY + output: + ny_wagering_losses_deduction: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/taxable_income/pa_total_taxable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/taxable_income/pa_total_taxable_income.yaml index 9e21cddcfb6..587e961a7be 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/taxable_income/pa_total_taxable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/taxable_income/pa_total_taxable_income.yaml @@ -73,3 +73,55 @@ pa_total_taxable_income: 30_000 # 30,000 x 3.07% pa_income_tax_before_forgiveness: 921 + +- name: Pennsylvania taxes gambling winnings net of each spouse's own wagering costs. + absolute_error_margin: 0.01 + period: 2026 + input: + people: + head: + age: 65 + employment_income: 30_000 + gambling_winnings: 10_000 + gambling_losses: 8_000 + ssi: 0 + spouse: + age: 65 + gambling_winnings: 2_000 + gambling_losses: 5_000 + ssi: 0 + tax_units: + tax_unit: + members: [head, spouse] + filing_status: JOINT + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: PA + output: + adjusted_gross_income: 42_000 + pa_gambling_loss_offset: [8_000, 2_000] + # 30,000 + (10,000 - 8,000) + max(2,000 - 5,000, 0); the spouse's extra + # 3,000 of costs cannot reduce the head's winnings, and the federal 90% + # limit does not apply. + pa_total_taxable_income: 32_000 + pa_eligibility_income: 32_000 + # PA-1000 line 11b counts the same net winnings, once. + pa_property_tax_or_rent_rebate_income: 32_000 + # 3.07% x 32,000 + pa_income_tax_before_forgiveness: 982.40 + +- name: Pennsylvania taxes gross winnings when there are no losses. + absolute_error_margin: 0.01 + period: 2025 + input: + age: 40 + employment_income: 30_000 + gambling_winnings: 10_000 + state_code: PA + output: + pa_gambling_loss_offset: 0 + pa_total_taxable_income: 40_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/pa/tax/property/property_tax_or_rent_rebate/pa_property_tax_or_rent_rebate_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/pa/tax/property/property_tax_or_rent_rebate/pa_property_tax_or_rent_rebate_income.yaml index 5e60ce8d7b7..ddb6de2bf2b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/pa/tax/property/property_tax_or_rent_rebate/pa_property_tax_or_rent_rebate_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/pa/tax/property/property_tax_or_rent_rebate/pa_property_tax_or_rent_rebate_income.yaml @@ -119,7 +119,6 @@ person1: age: 65 ssi: 0 - gambling_winnings: 1_000 alimony_income: 2_000 workers_compensation: 3_000 disability_benefits: 4_000 @@ -132,7 +131,31 @@ members: [person1] state_code: PA output: - pa_property_tax_or_rent_rebate_income: 20_000 + pa_property_tax_or_rent_rebate_income: 19_000 + +- name: Case 7b, gambling winnings count once, net of losses up to the winnings. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + ssi: 0 + employment_income: 10_000 + gambling_winnings: 1_000 + gambling_losses: 400 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: PA + output: + # Federal AGI already holds the 1,000 of winnings (line 11b is not added + # again), and the 400 of losses come off. + adjusted_gross_income: 11_000 + pa_property_tax_or_rent_rebate_income: 10_600 - name: Case 8, CSRS exclusion is capped by each recipient's CSRS income. period: 2025 diff --git a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/deductions/va_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/deductions/va_itemized_deductions.yaml index 8928e81776f..541873951c3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/deductions/va_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/deductions/va_itemized_deductions.yaml @@ -66,3 +66,38 @@ state_code: VA output: va_itemized_deductions: 40_000 #20,000+20,000 + +- name: Gambling losses are Virginia itemized deductions below the limitation threshold. + absolute_error_margin: 0.01 + period: 2025 + input: + filing_status: SINGLE + adjusted_gross_income: 100_000 + gambling_winnings: 20_000 + gambling_losses: 30_000 + charitable_deduction: 10_000 + state_and_local_sales_or_income_tax: 0 + real_estate_taxes: 0 + state_code: VA + output: + wagering_losses_deduction: 20_000 + va_itemized_deductions: 30_000 + +- name: Above the threshold gambling losses stay in the total and are not reduced. + absolute_error_margin: 0.01 + period: 2025 + input: + filing_status: SINGLE + adjusted_gross_income: 400_000 + gambling_winnings: 20_000 + gambling_losses: 30_000 + charitable_deduction: 10_000 + state_and_local_sales_or_income_tax: 0 + real_estate_taxes: 0 + state_code: VA + output: + wagering_losses_deduction: 20_000 + # Worksheet line 1: 30,000. Line 2 (gambling losses): 20,000. Line 3: + # 10,000, 80% of which is 8,000. Line 8: 3% x (400,000 - 332,700) = + # 2,019. Deduction: 30,000 - 2,019. + va_itemized_deductions: 27_981 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_itemized_deduction_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_itemized_deduction_credit.yaml index 38850b7f5cd..ff8b7375da7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_itemized_deduction_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_itemized_deduction_credit.yaml @@ -25,3 +25,17 @@ state_code: WI output: wi_itemized_deduction_credit_potential: 0 + +- name: Gambling losses do not count for the Wisconsin itemized deduction credit. + absolute_error_margin: 0.01 + period: 2025 + input: + gambling_winnings: 20_000 + gambling_losses: 20_000 + charitable_deduction: 15_000 + wi_standard_deduction: 10_000 + state_code: WI + output: + wagering_losses_deduction: 20_000 + # 5% x (15,000 - 10,000); the 20,000 of gambling losses is left out. + wi_itemized_deduction_credit_potential: 250 diff --git a/policyengine_us/tests/unit/test_gambling_winnings_and_losses_properties.py b/policyengine_us/tests/unit/test_gambling_winnings_and_losses_properties.py new file mode 100644 index 00000000000..3c7e55e9bff --- /dev/null +++ b/policyengine_us/tests/unit/test_gambling_winnings_and_losses_properties.py @@ -0,0 +1,215 @@ +"""Properties of the federal treatment of gambling winnings and losses. + +26 U.S.C. 61(a) puts gambling winnings in gross income (Schedule 1 line 8b). +26 U.S.C. 165(d) lets an itemizer deduct wagering losses up to wagering gains +(Schedule A line 16), and P.L. 119-21 section 70114 allows 90% of the losses +for taxable years beginning after 2025. A dependent's gambling belongs on the +dependent's own return. + +YAML cases check single households. These tests check relations between +households, which a YAML case cannot state, at every point of a winnings x +losses x other itemized deductions grid. Each year uses one vectorized +simulation; the grid point with no gambling is the baseline for the others. + +- The deduction equals min(share x losses, winnings), with the share restated + here from the statute (1 through 2025, 0.9 from 2026). +- It is non-negative, never exceeds the winnings or the share of losses, and + never falls as either rises. +- Adjusted gross income rises by exactly the winnings. +- The deduction is in itemized deductions once, and an itemizer's taxable + income is AGI less those deductions. +- Income tax never falls as winnings rise and never rises as losses rise. +- Gambling never lowers taxable income or income tax, including when winnings + equal losses. It raises taxable income by at most the winnings, and by + exactly the winnings less the deduction for a filer who itemizes either way. +- A dependent's winnings and losses change nothing on the filer's return. + +Before PolicyEngine/policyengine-us#9637 was fixed, gross income left the +winnings out while itemizers still deducted the losses, so gambling lowered +tax; the deduction had no 90% share; and it counted a dependent's gambling. +""" + +import itertools + +import numpy as np +import pytest + +from policyengine_us import Simulation + +AMOUNTS = [0, 1, 999, 5_000, 10_000, 25_000, 30_000, 250_000] +# A charitable deduction of 30,000 exceeds every standard deduction, so those +# filers itemize with or without gambling. +OTHER_ITEMIZED = [0, 30_000] +AXES = [AMOUNTS, AMOUNTS, OTHER_ITEMIZED] +GRID = list(itertools.product(*AXES)) +SHAPE = tuple(len(axis) for axis in AXES) +WINNINGS, LOSSES, OTHER = ( + np.array([point[i] for point in GRID], dtype=float) for i in range(len(AXES)) +) +# Winnings and losses of a dependent child; the first household has none. +DEPENDENT_GAMBLING = [ + (0, 0), + (10_000, 10_000), + (30_000, 25_000), + (250_000, 0), + (5_000, 250_000), +] +YEARS = [2024, 2025, 2026] +# Share of wagering losses section 165(d) allows (P.L. 119-21 section 70114). +LOSS_SHARE = {2024: 1.0, 2025: 1.0, 2026: 0.9} +WAGES = 60_000 +VARIABLES = [ + "adjusted_gross_income", + "wagering_losses_deduction", + "itemized_taxable_income_deductions", + "tax_unit_itemizes", + "taxable_income", + "income_tax", +] +# PolicyEngine computes in float32, whose spacing near 300,000 is 3 cents. +ATOL = 0.05 + + +def calculate(year): + """Grid filers, then parents whose dependent child has the gambling.""" + situation = {"people": {}, "tax_units": {}, "households": {}} + + def add_household(name, members, other_itemized): + situation["tax_units"][f"t_{name}"] = { + "members": members, + "charitable_deduction": {year: float(other_itemized)}, + # No estimated sales tax deduction, so deductions are exact. + "salt_deduction": {year: 0}, + } + situation["households"][f"h_{name}"] = { + "members": members, + "state_code": {year: "TX"}, + } + + for i, (winnings, losses, other) in enumerate(GRID): + situation["people"][f"filer_{i}"] = { + "age": {year: 40}, + "employment_income": {year: WAGES}, + "gambling_winnings": {year: winnings}, + "gambling_losses": {year: losses}, + } + add_household(f"grid_{i}", [f"filer_{i}"], other) + for j, (winnings, losses) in enumerate(DEPENDENT_GAMBLING): + situation["people"][f"parent_{j}"] = { + "age": {year: 40}, + "employment_income": {year: WAGES}, + } + situation["people"][f"child_{j}"] = { + "age": {year: 17}, + "gambling_winnings": {year: winnings}, + "gambling_losses": {year: losses}, + } + add_household(f"dependent_{j}", [f"parent_{j}", f"child_{j}"], 0) + simulation = Simulation(situation=situation) + values = { + variable: np.asarray(simulation.calculate(variable, year)) + for variable in VARIABLES + } + grid = {variable: value[: len(GRID)] for variable, value in values.items()} + dependents = {variable: value[len(GRID) :] for variable, value in values.items()} + return grid, dependents + + +@pytest.fixture(scope="module") +def results(): + return {year: calculate(year) for year in YEARS} + + +def baseline(values): + """Each grid point's value with no gambling and the same other deductions.""" + table = values.reshape(SHAPE) + return np.broadcast_to(table[:1, :1, :], SHAPE).reshape(-1) + + +@pytest.mark.parametrize("year", YEARS) +def test_deduction_is_the_section_165d_amount(results, year): + grid, _ = results[year] + np.testing.assert_allclose( + grid["wagering_losses_deduction"], + np.minimum(LOSS_SHARE[year] * LOSSES, WINNINGS), + atol=ATOL, + ) + + +@pytest.mark.parametrize("year", YEARS) +def test_deduction_is_bounded_and_monotone(results, year): + grid, _ = results[year] + deduction = grid["wagering_losses_deduction"] + assert np.all(deduction >= 0) + assert np.all(deduction <= WINNINGS + ATOL) + assert np.all(deduction <= LOSS_SHARE[year] * LOSSES + ATOL) + table = deduction.reshape(SHAPE) + assert np.all(np.diff(table, axis=0) >= -ATOL), "falls as winnings rise" + assert np.all(np.diff(table, axis=1) >= -ATOL), "falls as losses rise" + + +@pytest.mark.parametrize("year", YEARS) +def test_winnings_are_in_adjusted_gross_income(results, year): + grid, _ = results[year] + np.testing.assert_allclose( + grid["adjusted_gross_income"], WAGES + WINNINGS, atol=ATOL + ) + + +@pytest.mark.parametrize("year", YEARS) +def test_deduction_is_in_itemized_deductions_once(results, year): + grid, _ = results[year] + deduction = grid["wagering_losses_deduction"] + # No income here reaches the section 68 limitation. + np.testing.assert_allclose( + grid["itemized_taxable_income_deductions"], OTHER + deduction, atol=ATOL + ) + itemizes = grid["tax_unit_itemizes"] + assert itemizes.any() and not itemizes.all() + np.testing.assert_allclose( + grid["taxable_income"][itemizes], + (WAGES + WINNINGS - OTHER - deduction)[itemizes], + atol=ATOL, + ) + + +@pytest.mark.parametrize("year", YEARS) +def test_income_tax_is_monotone_in_winnings_and_losses(results, year): + grid, _ = results[year] + table = grid["income_tax"].reshape(SHAPE) + assert np.all(np.diff(table, axis=0) >= -ATOL), "falls as winnings rise" + assert np.all(np.diff(table, axis=1) <= ATOL), "rises as losses rise" + + +@pytest.mark.parametrize("year", YEARS) +def test_gambling_never_lowers_taxable_income_or_income_tax(results, year): + grid, _ = results[year] + change = grid["taxable_income"] - baseline(grid["taxable_income"]) + assert np.all(change >= -ATOL), "gambling lowered taxable income" + assert np.all(change <= WINNINGS + ATOL), "taxed more than the winnings" + tax_change = grid["income_tax"] - baseline(grid["income_tax"]) + assert np.all(tax_change >= -ATOL), "gambling lowered income tax" + # Equal winnings and losses are the case the issue reported. + equal = WINNINGS == LOSSES + assert np.all(tax_change[equal] >= -ATOL) + # A filer who itemizes either way pays tax on the winnings less the + # deduction. + itemizes_either_way = OTHER > 0 + assert np.all(grid["tax_unit_itemizes"][itemizes_either_way]) + net_gain = WINNINGS - grid["wagering_losses_deduction"] + np.testing.assert_allclose( + change[itemizes_either_way], net_gain[itemizes_either_way], atol=ATOL + ) + + +@pytest.mark.parametrize("year", YEARS) +def test_a_dependents_gambling_does_not_change_the_filers_return(results, year): + _, dependents = results[year] + for variable in VARIABLES: + values = dependents[variable] + # The first household's child has no gambling. + np.testing.assert_allclose( + values.astype(float), float(values[0]), atol=ATOL, err_msg=variable + ) + assert np.all(dependents["wagering_losses_deduction"] == 0) + assert np.all(dependents["adjusted_gross_income"] == WAGES) diff --git a/policyengine_us/variables/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.py b/policyengine_us/variables/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.py index db1e3293763..d1e221ac6c8 100644 --- a/policyengine_us/variables/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.py +++ b/policyengine_us/variables/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.py @@ -6,11 +6,23 @@ class wagering_losses_deduction(Variable): entity = TaxUnit label = "Wagering losses deduction" unit = USD - documentation = "Deduction from taxable income for gambling losses, capped at gambling winnings." + documentation = ( + "Itemized deduction for gambling losses (Schedule A line 16): the " + "allowed share of losses, up to gambling winnings." + ) definition_period = YEAR - reference = "https://www.law.cornell.edu/uscode/text/26/165#d" + reference = ( + "https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title26-section165&num=0&edition=prelim", + # P.L. 119-21 sec. 70114: 90% of losses from 2026 + "https://www.govinfo.gov/content/pkg/PLAW-119publ21/pdf/PLAW-119publ21.pdf#page=96", + "https://www.irs.gov/pub/irs-prior/i1040sca--2024.pdf#page=11", + ) def formula(tax_unit, period, parameters): - gambling_losses = add(tax_unit, period, ["gambling_losses"]) - gambling_winnings = add(tax_unit, period, ["gambling_winnings"]) - return min_(gambling_losses, gambling_winnings) + p = parameters(period).gov.irs.deductions.itemized.wagering_losses + # Losses are deductible only against gambling winnings reported on + # the return. A dependent's gambling is on the dependent's own + # return, as irs_gross_income leaves their winnings off this one. + losses = tax_unit_non_dep_add(tax_unit, period, ["gambling_losses"]) + winnings = tax_unit_non_dep_add(tax_unit, period, ["gambling_winnings"]) + return min_(p.rate * losses, winnings) diff --git a/policyengine_us/variables/gov/states/al/tax/income/deductions/itemized/al_gambling_loss_deduction.py b/policyengine_us/variables/gov/states/al/tax/income/deductions/itemized/al_gambling_loss_deduction.py new file mode 100644 index 00000000000..f13bd487aee --- /dev/null +++ b/policyengine_us/variables/gov/states/al/tax/income/deductions/itemized/al_gambling_loss_deduction.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class al_gambling_loss_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Alabama gambling loss deduction" + unit = USD + documentation = ( + "Alabama itemized deduction for gambling losses, to the extent of " + "gambling winnings and not subject to the 2% limit on miscellaneous " + "deductions. Alabama does not follow the federal 90% limit that " + "starts in 2026." + ) + definition_period = YEAR + reference = ( + # 2025 Form 40 booklet, Schedule A line 25 + "https://www.revenue.alabama.gov/wp-content/uploads/2026/01/25f40bk.pdf#page=21", + # Ala. Admin. Code r. 810-3-17-.01 + "https://admincode.legislature.state.al.us/api/rule/810-3-17-.01", + # ALDOR summary of P.L. 119-21: section 165(d), "Tied to Federal: No" + # PDF pages 9-10 + "https://www.revenue.alabama.gov/wp-content/uploads/2025/11/OBBBA-Executive-Summary_FinalwAppendixA_10.31.25.pdf#page=9", + ) + defined_for = StateCode.AL + + def formula(tax_unit, period, parameters): + # Dependents report their gambling on their own returns. + losses = tax_unit_non_dep_add(tax_unit, period, ["gambling_losses"]) + winnings = tax_unit_non_dep_add(tax_unit, period, ["gambling_winnings"]) + return min_(losses, winnings) diff --git a/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.py b/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.py index 80c39a22960..7c8618fdac5 100644 --- a/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.py +++ b/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.py @@ -28,6 +28,7 @@ def formula(tax_unit, period, parameters): "charitable_deduction", "charitable_deduction_for_non_itemizers", "misc_deduction", + "wagering_losses_deduction", ) ] deductions += [ @@ -35,6 +36,7 @@ def formula(tax_unit, period, parameters): "real_estate_taxes", "ca_charitable_deduction", "ca_misc_deduction", + "ca_wagering_losses_deduction", ] # Federal investment interest is nested in interest_deduction. return add(tax_unit, period, deductions) - add( diff --git a/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_wagering_losses_deduction.py b/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_wagering_losses_deduction.py new file mode 100644 index 00000000000..a2e8638a613 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_wagering_losses_deduction.py @@ -0,0 +1,34 @@ +from policyengine_us.model_api import * + + +class ca_wagering_losses_deduction(Variable): + value_type = float + entity = TaxUnit + label = "California wagering losses deduction" + unit = USD + documentation = ( + "California itemized deduction for gambling losses, up to gambling " + "winnings. California does not apply the federal 90% limit that " + "starts in 2026. California Lottery winnings are exempt and " + "California Lottery losses are not deductible; the gambling inputs " + "do not separate them, so they are treated as other gambling." + ) + definition_period = YEAR + reference = ( + # 2025 Form 540 booklet: Schedule CA (540) line 8b (California + # Lottery winnings), Part II line 16 (gambling losses) and the + # Itemized Deductions Worksheet + # PDF pages 62, 67-68 + "https://www.ftb.ca.gov/forms/2025/2025-540-booklet.pdf#page=62", + # California conforms to the Internal Revenue Code as of January 1, + # 2025, before P.L. 119-21. + "https://www.ftb.ca.gov/tax-pros/law/conformity.html", + ) + defined_for = StateCode.CA + + def formula(tax_unit, period, parameters): + # 26 U.S.C. 165(d) before P.L. 119-21: all losses, up to the gains. + # Dependents report their gambling on their own returns. + losses = tax_unit_non_dep_add(tax_unit, period, ["gambling_losses"]) + winnings = tax_unit_non_dep_add(tax_unit, period, ["gambling_winnings"]) + return min_(losses, winnings) diff --git a/policyengine_us/variables/gov/states/dc/tax/income/deductions/dc_itemized_deductions.py b/policyengine_us/variables/gov/states/dc/tax/income/deductions/dc_itemized_deductions.py index 93343decc14..e50ec510f36 100644 --- a/policyengine_us/variables/gov/states/dc/tax/income/deductions/dc_itemized_deductions.py +++ b/policyengine_us/variables/gov/states/dc/tax/income/deductions/dc_itemized_deductions.py @@ -10,6 +10,8 @@ class dc_itemized_deductions(Variable): reference = ( "https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/52926_D-40_12.21.21_Final_Rev011122.pdf#page=18", "https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2022_D-40_Booklet_Final_blk_01_23_23_Ordc.pdf#page=17", + # D.C. Code 47-1803.03(b-4)(2)(B): deductions outside the phase-out + "https://code.dccouncil.gov/us/dc/council/code/sections/47-1803.03", ) defined_for = StateCode.DC @@ -24,6 +26,8 @@ def formula(tax_unit, period, parameters): EXEMPT_ITEMS = [ "medical_expense_deduction", "casualty_loss_deduction", + # Losses described in section 165(d) of the Internal Revenue Code. + "wagering_losses_deduction", ] exempt_deds = add(tax_unit, period, EXEMPT_ITEMS) nonexempt_deds = max_(0, dc_itm_deds - exempt_deds) diff --git a/policyengine_us/variables/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.py b/policyengine_us/variables/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.py index a7d2ed4f785..eeecae99e3a 100644 --- a/policyengine_us/variables/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.py +++ b/policyengine_us/variables/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.py @@ -13,6 +13,7 @@ ], "interest_deduction": ["deductible_interest_expense"], "casualty_loss_deduction": ["casualty_loss"], + "wagering_losses_deduction": ["gambling_losses"], } diff --git a/policyengine_us/variables/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.py b/policyengine_us/variables/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.py index b63c15e4543..fc8ddff3bcd 100644 --- a/policyengine_us/variables/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.py +++ b/policyengine_us/variables/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.py @@ -9,6 +9,8 @@ class hi_reduced_itemized_deductions(Variable): reference = ( "https://files.hawaii.gov/tax/forms/2022/n11ins.pdf#page=15", "https://files.hawaii.gov/tax/forms/2022/n11ins.pdf#page=32", # total itemized deduction worksheet + # 2025 Total Itemized Deductions Worksheet, lines 2d and 4 + "https://files.hawaii.gov/tax/forms/2025/n11ins.pdf#page=34", ) definition_period = YEAR defined_for = StateCode.HI @@ -24,6 +26,8 @@ def formula(tax_unit, period, parameters): "hi_medical_expense_deduction", "investment_interest_expense", "hi_casualty_loss_deduction", + # Line 2d: gambling losses included in Worksheet A-6, line 30. + "wagering_losses_deduction", ], ) @@ -53,4 +57,7 @@ def formula(tax_unit, period, parameters): ) reduced_deductions = max_(0, total_deductions - smaller_reduced_ded) eligible = partial_deductions_less_than_total & agi_over_threshold - return eligible * reduced_deductions + # Worksheet lines 4 and 8: when the deductions outside the limit are + # not less than the total, or income is not over the threshold, the + # deduction is not limited and line 1 is deducted in full. + return where(eligible, reduced_deductions, total_deductions) diff --git a/policyengine_us/variables/gov/states/ks/tax/income/deductions/ks_itemized_deductions.py b/policyengine_us/variables/gov/states/ks/tax/income/deductions/ks_itemized_deductions.py index fd0b8dee13f..7d6e7331d6c 100644 --- a/policyengine_us/variables/gov/states/ks/tax/income/deductions/ks_itemized_deductions.py +++ b/policyengine_us/variables/gov/states/ks/tax/income/deductions/ks_itemized_deductions.py @@ -10,6 +10,7 @@ class ks_itemized_deductions(Variable): reference = ( "https://www.ksrevenue.gov/pdf/ip21.pdf", "https://www.ksrevenue.gov/pdf/ip22.pdf", + "https://kslegislature.gov/b2025_26/laws/079_000_0000_chapter/079_032_0000_article/079_032_0120_section/079_032_0120_k/", ) defined_for = StateCode.KS @@ -25,4 +26,8 @@ def formula(tax_unit, period, parameters): # compute itemized deduction maximum itm_deds_less_salt = tax_unit("itemized_deductions_less_salt", period) uncapped_property_taxes = add(tax_unit, period, ["real_estate_taxes"]) - return itm_deds_less_salt + uncapped_property_taxes + # K.S.A. 79-32,120(a) limits Kansas itemized deductions to charitable + # contributions, medical care, qualified residence interest and + # property taxes, so federal wagering losses are not one of them. + wagering_losses = tax_unit("wagering_losses_deduction", period) + return itm_deds_less_salt - wagering_losses + uncapped_property_taxes diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/mi_wagering_losses_deduction.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/mi_wagering_losses_deduction.py new file mode 100644 index 00000000000..40c384104f1 --- /dev/null +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/mi_wagering_losses_deduction.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class mi_wagering_losses_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Michigan wagering losses deduction" + unit = USD + documentation = ( + "Michigan subtraction, from 2021, for the wagering losses a casual " + "gambler deducts as an itemized deduction on the federal return." + ) + definition_period = YEAR + reference = ( + # 2021 PA 168, MCL 206.30 + "https://www.legislature.mi.gov/Laws/MCL?objectName=mcl-206-30", + "https://www.michigan.gov/taxes/rep-legal/notices/notice-new-tax-treatment-of-wagering-losses-for-casual-gamblers-under-the-michigan-income-tax-act", + # 2025 MI-1040 booklet, Schedule 1 line 23 + "https://www.michigan.gov/taxes/-/media/Project/Websites/taxes/Forms/IIT/TY2025/MI-1040-Book.pdf#page=16", + # 2025 Taxpayer Assistance Manual: the federal 90% limit carries over + "https://www.michigan.gov/taxes/-/media/Project/Websites/taxes/Tax-Professional/2025-Taxpayer-Assistance-Manual.pdf#page=99", + ) + defined_for = StateCode.MI + + def formula(tax_unit, period, parameters): + # Only the losses claimed as an itemized deduction on the federal + # return count, so a filer who takes the federal standard deduction + # has none. + itemizes = tax_unit("tax_unit_itemizes", period) + return itemizes * tax_unit("wagering_losses_deduction", period) diff --git a/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py b/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py index bbd8191185d..e6a4f08de02 100644 --- a/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py +++ b/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py @@ -12,6 +12,8 @@ class mn_itemized_deductions(Variable): "https://www.revenue.state.mn.us/sites/default/files/2023-12/m1_inst_21.pdf", "https://www.revenue.state.mn.us/sites/default/files/2023-12/m1_22.pdf", "https://www.revenue.state.mn.us/sites/default/files/2024-02/m1-inst-22.pdf", + # Minn. Stat. 290.0122, subd. 2(d) and subd. 8 + "https://www.revisor.mn.gov/statutes/cite/290.0122", ) defined_for = StateCode.MN @@ -27,10 +29,16 @@ def formula(tax_unit, period, parameters): mn_itm_deds = itm_deds_less_salt + capped_property_taxes # ... calculate itemized deductions offset p = parameters(period).gov.states.mn.tax.income.deductions.itemized + # Minn. Stat. 290.0122, subd. 2(d)(3) leaves the subd. 8 losses, + # which include section 165(d) wagering losses, out of the limitation. exempt_deds = add( tax_unit, period, - ["medical_expense_deduction", "casualty_loss_deduction"], + [ + "medical_expense_deduction", + "casualty_loss_deduction", + "wagering_losses_deduction", + ], ) net_deds = max_(0, mn_itm_deds - exempt_deds) filing_status = tax_unit("filing_status", period) diff --git a/policyengine_us/variables/gov/states/ms/tax/income/deductions/itemized/ms_itemized_deductions_unit.py b/policyengine_us/variables/gov/states/ms/tax/income/deductions/itemized/ms_itemized_deductions_unit.py index 0cbb0cdbd17..4137155500c 100644 --- a/policyengine_us/variables/gov/states/ms/tax/income/deductions/itemized/ms_itemized_deductions_unit.py +++ b/policyengine_us/variables/gov/states/ms/tax/income/deductions/itemized/ms_itemized_deductions_unit.py @@ -12,6 +12,10 @@ class ms_itemized_deductions_unit(Variable): "https://www.dor.ms.gov/sites/default/files/tax-forms/individual/80100221.pdf#page=15", "https://www.dor.ms.gov/sites/default/files/tax-forms/individual/80108228.pdf", # Line 7 "https://law.justia.com/codes/mississippi/title-27/chapter-7/article-1/section-27-7-17/", + # 2025 instructions: Schedule A line 7b (gaming losses), and the 3% + # tax on winnings reported by Mississippi casinos + # PDF pages 16, 25 + "https://www.dor.ms.gov/sites/default/files/tax-forms/individual/80100251%202.pdf#page=16", ) defined_for = StateCode.MS @@ -20,6 +24,12 @@ class ms_itemized_deductions_unit(Variable): "misc_deduction", "ms_real_estate_tax_deduction", ] + # Winnings reported by Mississippi casinos bear a separate 3% tax and are + # not Mississippi income, and Mississippi gaming losses come off the + # itemized deductions (Schedule A line 7b). Mississippi income here + # leaves out all gambling winnings, including those from other states, + # so the federal wagering losses deduction is left out as well. + subtracts = ["wagering_losses_deduction"] # Mississippi allows itemized deductions for gaming establishments and gender transition procedures # which are currently not modeled diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_wagering_losses_deduction.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_wagering_losses_deduction.py new file mode 100644 index 00000000000..01364571cd1 --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_wagering_losses_deduction.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class mt_wagering_losses_deduction(Variable): + value_type = float + entity = Person + label = "Montana wagering losses deduction" + unit = USD + documentation = ( + "The person's part of the federal wagering losses deduction, which " + "Montana allows as an itemized deduction. When spouses file " + "separately, the spouse who reports the gambling winnings claims " + "the losses." + ) + definition_period = YEAR + reference = ( + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=39", + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=13", + ) + defined_for = StateCode.MT + + def formula(person, period, parameters): + deduction = person.tax_unit("wagering_losses_deduction", period) + # The federal deduction counts the head's and spouse's gambling. + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + winnings = head_or_spouse * person("gambling_winnings", period) + total_winnings = person.tax_unit.sum(winnings) + share = np.zeros_like(total_winnings) + mask = total_winnings > 0 + share[mask] = winnings[mask] / total_winnings[mask] + return deduction * share diff --git a/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_itemized_deductions_max.py b/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_itemized_deductions_max.py index 69366a1932e..3f4b1896f50 100644 --- a/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_itemized_deductions_max.py +++ b/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/ny_itemized_deductions_max.py @@ -20,6 +20,7 @@ class ny_itemized_deductions_max(Variable): - State/local income taxes are NOT deductible (only sales + property) - Miscellaneous deductions still allowed with 2% AGI floor - Casualty losses not limited to federally declared disasters + - Gambling losses up to winnings, without the 90% limit from 2026 - NY-specific college tuition deduction addition per § 615(d) """ adds = [ @@ -31,6 +32,7 @@ class ny_itemized_deductions_max(Variable): "ny_salt_deduction", "ny_misc_deduction", "ny_casualty_loss_deduction", + "ny_wagering_losses_deduction", # NY-specific addition per Tax Law § 615(d) "ny_college_tuition_deduction", ] diff --git a/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/phase_out/ny_itemized_deductions_phase_out.py b/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/phase_out/ny_itemized_deductions_phase_out.py index 27565cc41af..d1efd56543c 100644 --- a/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/phase_out/ny_itemized_deductions_phase_out.py +++ b/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/phase_out/ny_itemized_deductions_phase_out.py @@ -28,19 +28,20 @@ class ny_itemized_deductions_phase_out(Variable): itemized deductions before the limitation. In PolicyEngine this is ny_itemized_deductions_max minus the NY-only college tuition addition (form line 48/43, which is added after line 40 and is not on this - worksheet). Form line 39 ("other itemized deductions": gambling losses, - estate tax on income in respect of a decedent, amortizable bond premium, - federal disaster loss, etc.) is not modeled in PolicyEngine and is therefore - treated as zero. + worksheet). Of form line 39 ("other itemized deductions"), gambling losses + (line 29) are ny_wagering_losses_deduction; the rest (estate tax on income + in respect of a decedent, amortizable bond premium, federal disaster loss, + etc.) is not modeled in PolicyEngine and is therefore treated as zero. Worksheet line 2 (L2) = form lines 4, 14, 16a, 20, 29, 30, 37, i.e. the deductions NOT subject to the limitation (26 U.S.C. 68(c)): - line 4 medical/dental -> medical_expense_deduction - line 14 investment interest -> investment_interest_expense - line 20 casualty/theft loss -> ny_casualty_loss_deduction - - lines 16a/29/30/37 (qualified contributions, gambling losses, - income-producing-property casualty, federal disaster loss) are not - separately modeled in PolicyEngine and are treated as zero. + - line 29 gambling losses -> ny_wagering_losses_deduction + - lines 16a/30/37 (qualified contributions, income-producing-property + casualty, federal disaster loss) are not separately modeled in + PolicyEngine and are treated as zero. L3 = L1 - L2 (worksheet line 3) is therefore the mortgage interest, real estate taxes, charitable gifts, and 2%-floor miscellaneous deductions - @@ -61,11 +62,13 @@ def formula(tax_unit, period, parameters): l1 = itemized_max - college_tuition # Worksheet line 2 (L2): deductions not subject to the limitation - # (26 U.S.C. 68(c)) - medical, investment interest, casualty/theft. + # (26 U.S.C. 68(c)) - medical, investment interest, casualty/theft, + # gambling losses. medical = tax_unit("medical_expense_deduction", period) investment_interest = add(tax_unit, period, ["investment_interest_expense"]) casualty = tax_unit("ny_casualty_loss_deduction", period) - l2 = medical + investment_interest + casualty + wagering = tax_unit("ny_wagering_losses_deduction", period) + l2 = medical + investment_interest + casualty + wagering # Worksheet line 3 (L3): deductions subject to the limitation. Floored at # zero to implement the worksheet's line-3 stop ("If line 2 is not less diff --git a/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/pre_tcja/ny_wagering_losses_deduction.py b/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/pre_tcja/ny_wagering_losses_deduction.py new file mode 100644 index 00000000000..706560dda75 --- /dev/null +++ b/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/deductions/itemized/pre_tcja/ny_wagering_losses_deduction.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ny_wagering_losses_deduction(Variable): + value_type = float + entity = TaxUnit + label = "NY wagering losses deduction" + unit = USD + definition_period = YEAR + reference = ( + "https://www.nysenate.gov/legislation/laws/TAX/615", + # Form IT-196 instructions, line 29: gambling losses + "https://www.tax.ny.gov/pdf/2025/inc/it196i_2025.pdf#page=16", + ) + defined_for = StateCode.NY + documentation = """ + NY Tax Law § 615 requires itemized deductions to be computed using + pre-TCJA federal rules. New York allows gambling losses up to gambling + winnings under the federal rules that applied to tax year 2017, so the + federal 90% limit that starts in 2026 does not apply. + """ + + def formula(tax_unit, period, parameters): + # Dependents report their gambling on their own returns. + losses = tax_unit_non_dep_add(tax_unit, period, ["gambling_losses"]) + winnings = tax_unit_non_dep_add(tax_unit, period, ["gambling_winnings"]) + return min_(losses, winnings) diff --git a/policyengine_us/variables/gov/states/pa/tax/income/taxable_income/pa_gambling_loss_offset.py b/policyengine_us/variables/gov/states/pa/tax/income/taxable_income/pa_gambling_loss_offset.py new file mode 100644 index 00000000000..cd19f2c68b8 --- /dev/null +++ b/policyengine_us/variables/gov/states/pa/tax/income/taxable_income/pa_gambling_loss_offset.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class pa_gambling_loss_offset(Variable): + value_type = float + entity = Person + label = "Pennsylvania gambling losses offset against winnings" + unit = USD + documentation = ( + "The cost of tickets, bets and other wagers that Pennsylvania " + "subtracts from the same person's gambling and lottery winnings " + "(PA-40 Schedule T). Spouses may not use each other's costs, and the " + "federal 90% limit does not apply. Noncash Pennsylvania Lottery " + "prizes, which Pennsylvania does not tax, are not separated in the " + "gambling inputs." + ) + definition_period = YEAR + reference = ( + # 72 P.S. 7303(a)(7) + "https://www.legis.state.pa.us/WU01/LI/LI/US/PDF/1971/0/0002..PDF#page=123", + # 2025 PA-40 Schedule T and its instructions + # PDF pages 1, 3 + "https://www.pa.gov/content/dam/copapwp-pagov/en/revenue/documents/formsandpublications/formsforindividuals/pit/documents/2025/2025_pa-40t.pdf#page=1", + ) + defined_for = StateCode.PA + + def formula(person, period, parameters): + winnings = person("gambling_winnings", period) + losses = person("gambling_losses", period) + return min_(losses, winnings) diff --git a/policyengine_us/variables/gov/states/pa/tax/property/property_tax_or_rent_rebate/pa_property_tax_or_rent_rebate_income.py b/policyengine_us/variables/gov/states/pa/tax/property/property_tax_or_rent_rebate/pa_property_tax_or_rent_rebate_income.py index 1bd76724a54..58698b23e1e 100644 --- a/policyengine_us/variables/gov/states/pa/tax/property/property_tax_or_rent_rebate/pa_property_tax_or_rent_rebate_income.py +++ b/policyengine_us/variables/gov/states/pa/tax/property/property_tax_or_rent_rebate/pa_property_tax_or_rent_rebate_income.py @@ -17,6 +17,10 @@ class pa_property_tax_or_rent_rebate_income(Variable): "https://www.pa.gov/content/dam/copapwp-pagov/en/revenue/documents/" "formsandpublications/formsforindividuals/ptrr/documents/" "2025_pa-1000_inst.pdf#page=9", + # PA-1000 booklet, line 11b: net gambling and lottery winnings + "https://www.pa.gov/content/dam/copapwp-pagov/en/revenue/documents/" + "formsandpublications/formsforindividuals/ptrr/documents/" + "dfo-03.pdf#page=40", ) defined_for = StateCode.PA @@ -57,13 +61,18 @@ def formula(tax_unit, period, parameters): person, period, [ - "gambling_winnings", "alimony_income", "workers_compensation", "disability_benefits", ], ) ) + # Line 11b counts net gambling and lottery winnings: losses offset the + # winnings but may not exceed them. The winnings are already in + # federal adjusted gross income. + gambling_loss_offset = tax_unit.sum( + head_or_spouse * person("pa_gambling_loss_offset", period) + ) life_insurance_benefits = tax_unit.sum( head_or_spouse * person("life_insurance_benefits", period) ) @@ -84,6 +93,7 @@ def formula(tax_unit, period, parameters): + p.benefit_income_rate * half_counted_benefits + tax_exempt_income + pa_1000_line_11_income + - gambling_loss_offset + taxable_life_insurance_benefits + csrs_income - csrs_exclusion, diff --git a/policyengine_us/variables/gov/states/va/tax/income/deductions/va_reduced_itemized_deductions.py b/policyengine_us/variables/gov/states/va/tax/income/deductions/va_reduced_itemized_deductions.py index cd57fbba606..567c3261b23 100644 --- a/policyengine_us/variables/gov/states/va/tax/income/deductions/va_reduced_itemized_deductions.py +++ b/policyengine_us/variables/gov/states/va/tax/income/deductions/va_reduced_itemized_deductions.py @@ -16,7 +16,8 @@ def formula(tax_unit, period, parameters): # Part A: If AGI from federal return is over a certain amount, then # limitations to the itemized deduction are applied # Line 1 - sum of medical exepens ded., capped state and local tax, - # interest ded., charitable ded., and casualty loss ded. + # interest ded., charitable ded., casualty loss ded., and gambling + # losses (Schedule A line 16a) applicable_ded = add( tax_unit, period, diff --git a/policyengine_us/variables/gov/states/wi/tax/income/credits/itemized_deduction/wi_itemized_deduction_credit_potential.py b/policyengine_us/variables/gov/states/wi/tax/income/credits/itemized_deduction/wi_itemized_deduction_credit_potential.py index da76fe63638..8bda47e387d 100644 --- a/policyengine_us/variables/gov/states/wi/tax/income/credits/itemized_deduction/wi_itemized_deduction_credit_potential.py +++ b/policyengine_us/variables/gov/states/wi/tax/income/credits/itemized_deduction/wi_itemized_deduction_credit_potential.py @@ -11,11 +11,18 @@ class wi_itemized_deduction_credit_potential(Variable): "https://www.revenue.wi.gov/TaxForms2021/2021-Form1f.pdf#page=4", "https://www.revenue.wi.gov/TaxForms2022/2022-Form1f.pdf#page=4", "https://docs.legis.wisconsin.gov/misc/lfb/informational_papers/january_2023/0002_individual_income_tax_informational_paper_2.pdf#page=19", + # Publication 600: gambling losses are not deductible and may not + # be used in computing the itemized deduction credit. + # PDF pages 4, 6, 9-10 + "https://www.revenue.wi.gov/DOR%20Publications/pb600.pdf#page=4", ) defined_for = StateCode.WI def formula(tax_unit, period, parameters): - wi_itmded = tax_unit("itemized_deductions_less_salt", period) + # Wisconsin allows no deduction or credit for gambling losses. + wi_itmded = tax_unit("itemized_deductions_less_salt", period) - tax_unit( + "wagering_losses_deduction", period + ) wi_stdded = tax_unit("wi_standard_deduction", period) excess_itmded = max_(0, wi_itmded - wi_stdded) p = parameters(period).gov.states.wi.tax.income From bcabc13b93a0259dbb93d663f9d66802b4bdd277 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 10 Oct 2026 15:37:44 -0400 Subject: [PATCH 2/4] Keep wagering losses outside the limitation in the Minnesota HF1938 reform's formula Co-Authored-By: Claude Opus 5.5 --- policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py b/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py index 78aed52cd19..412c8f636b1 100644 --- a/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py +++ b/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py @@ -115,10 +115,17 @@ def formula(tax_unit, period, parameters): mn_itm_deds = itm_deds_less_salt + capped_property_taxes # ... calculate itemized deductions offset p = parameters(period).gov.states.mn.tax.income.deductions.itemized + # As in the baseline: Minn. Stat. 290.0122, subd. 2(d)(3) leaves + # the subd. 8 losses, including wagering losses, out of the + # limitation. exempt_deds = add( tax_unit, period, - ["medical_expense_deduction", "casualty_loss_deduction"], + [ + "medical_expense_deduction", + "casualty_loss_deduction", + "wagering_losses_deduction", + ], ) net_deds = max_(0, mn_itm_deds - exempt_deds) net_deds_offset = p.reduction.alternate.rate * net_deds From f7f555818f774e004bd9fa03586c0786eca1a7e6 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 10 Oct 2026 16:40:50 -0400 Subject: [PATCH 3/4] Address review r1: dependents in Alabama and Iowa, Delaware allocation, Kentucky 2018, Montana allocation - Alabama and pre-2023 Iowa gross income count the head's and spouse's gambling winnings (new person variables), not a dependent's. - Delaware allocates wagering losses over the head's and spouse's losses only. - Kentucky allowed no wagering losses for 2018 (2019 Ky. Acts ch. 151). - Montana allocates each spouse's own losses first. - Document what the gambling inputs hold; move the integration cases into the deduction's YAML file; add section 68 cases; fix reference titles. Co-Authored-By: Claude Opus 5.5 --- .../tax/income/agi/gross_income_sources.yaml | 4 +- .../income/deductions/itemized/sources.yaml | 6 +- .../ia/tax/income/gross_income/sources.yaml | 2 + .../itemized/wagering_losses_allowed.yaml | 18 +++ .../itemized/reduction/applicable.yaml | 2 +- ...d_taxable_income_deductions_reduction.yaml | 47 +++++++ .../itemizing/wagering_losses_deduction.yaml | 133 ++++++++++++++++++ .../gambling_winnings_and_losses.yaml | 131 ----------------- .../baseline/gov/irs/irs_gross_income.yaml | 18 +++ .../gov/states/al/tax/income/al_agi.yaml | 23 +++ .../itemized/de_itemized_deductions_indv.yaml | 35 +++++ .../states/ia/tax/income/ia_gross_income.yaml | 25 ++++ .../ky_itemized_deductions_unit.yaml | 34 +++++ .../mt_wagering_losses_deduction.yaml | 56 ++++++++ .../al/tax/income/al_gambling_winnings.py | 24 ++++ .../itemized/de_itemized_deductions_indv.py | 5 + .../income/net_income/ia_gambling_winnings.py | 24 ++++ .../deductions/ky_itemized_deductions_unit.py | 14 +- .../general/mt_wagering_losses_deduction.py | 30 ++-- .../income/person/gambling_losses.py | 9 ++ .../income/person/gambling_winnings.py | 12 ++ 21 files changed, 503 insertions(+), 149 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ky/tax/income/deductions/itemized/wagering_losses_allowed.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/gambling_winnings_and_losses.yaml create mode 100644 policyengine_us/variables/gov/states/al/tax/income/al_gambling_winnings.py create mode 100644 policyengine_us/variables/gov/states/ia/tax/income/net_income/ia_gambling_winnings.py diff --git a/policyengine_us/parameters/gov/states/al/tax/income/agi/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/al/tax/income/agi/gross_income_sources.yaml index cff5b2322c4..8705dc2a6e8 100644 --- a/policyengine_us/parameters/gov/states/al/tax/income/agi/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/al/tax/income/agi/gross_income_sources.yaml @@ -20,8 +20,8 @@ values: - farm_operations_income - farm_rent_income # Prizes and awards: contests, lotteries and gambling winnings (Form 40 - # page 2, Part I, other income). - - gambling_winnings + # page 2, Part I, other income), of the head and spouse. + - al_gambling_winnings metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/deductions/itemized/sources.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/deductions/itemized/sources.yaml index a2ec70cd98c..77bd496ee52 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/deductions/itemized/sources.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/deductions/itemized/sources.yaml @@ -25,7 +25,5 @@ metadata: href: https://files.hawaii.gov/tax/forms/2018/n11ins.pdf#page=19 - title: Hawaii Income Tax Law, Chapter 235, Section 235-2.4 href: https://files.hawaii.gov/tax/legal/hrs/hrs_235.pdf#page=10 - - title: 2025 Hawaii N-11 Instructions, Worksheet A-6 line 30 - Gambling losses - href: https://files.hawaii.gov/tax/forms/2025/n11ins.pdf#page=19 - - title: 2025 Hawaii N-11 Instructions Itemized Deductions - href: https://files.hawaii.gov/tax/forms/current/n11ins.pdf#page=17 + - title: "2025 Hawaii N-11 Instructions Itemized Deductions #page 17,19" + href: https://files.hawaii.gov/tax/forms/2025/n11ins.pdf#page=17 diff --git a/policyengine_us/parameters/gov/states/ia/tax/income/gross_income/sources.yaml b/policyengine_us/parameters/gov/states/ia/tax/income/gross_income/sources.yaml index 1abc47597d6..7739e4c5f7e 100644 --- a/policyengine_us/parameters/gov/states/ia/tax/income/gross_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/ia/tax/income/gross_income/sources.yaml @@ -16,6 +16,8 @@ values: - farm_operations_income - taxable_unemployment_compensation - miscellaneous_income + # IA 1040 line 13, gambling winnings, of the head and spouse. + - ia_gambling_winnings metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/ky/tax/income/deductions/itemized/wagering_losses_allowed.yaml b/policyengine_us/parameters/gov/states/ky/tax/income/deductions/itemized/wagering_losses_allowed.yaml new file mode 100644 index 00000000000..1c9c01f00e6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ky/tax/income/deductions/itemized/wagering_losses_allowed.yaml @@ -0,0 +1,18 @@ +description: Kentucky allows the federal wagering losses deduction as an itemized deduction if this is true. +values: + 2000-01-01: true + # For 2018 Kentucky disallowed every section 165 loss. + 2018-01-01: false + # 2019 Ky. Acts ch. 151, sec. 37 restored wagering losses allowed under + # section 165(d), for taxable years beginning on or after January 1, 2019 + # (sec. 83). + 2019-01-01: true +metadata: + unit: bool + period: year + label: Kentucky wagering losses itemized deduction allowed + reference: + - title: "2019 Ky. Acts ch. 151, sec. 37 (KRS 141.019(2)(b)) and sec. 83 #page 60,112" + href: https://apps.legislature.ky.gov/law/acts/19RS/documents/0151.pdf#page=60 + - title: TY2018 Kentucky Publication 1345, itemized deductions obsolete for tax year 2018 + href: https://revenue.ky.gov/Software-Developer/Software%20Development%20Documents/TY2018%20KY%20Publication%201345-Handbook%20for%20Electronic%20Filing.pdf#page=9 diff --git a/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/applicable.yaml b/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/applicable.yaml index 47a20326b85..b80e5a27698 100644 --- a/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/applicable.yaml +++ b/policyengine_us/parameters/gov/states/va/tax/income/deductions/itemized/reduction/applicable.yaml @@ -14,7 +14,7 @@ metadata: period: year label: Virginia itemized deductions reduction applicable deduction sources reference: - - title: 2025 Virginia Schedule A Itemized Deductions, line 16a and Limited Itemized Deduction Worksheet line 1 + - title: "2025 Virginia Schedule A Itemized Deductions, line 16a and Limited Itemized Deduction Worksheet line 1 #page 1-2" href: https://www.tax.virginia.gov/sites/default/files/taxforms/individual-income-tax/2025/schedule-2025.pdf#page=1 - title: 2024 Virginia Schedule A Itemized Deductions href: https://www.tax.virginia.gov/sites/default/files/taxforms/individual-income-tax/2024/schedule-2024.pdf#page=2 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/itemized_taxable_income_deductions_reduction.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/itemized_taxable_income_deductions_reduction.yaml index 965f6ed655c..28bbca5664c 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/itemized_taxable_income_deductions_reduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/itemized_taxable_income_deductions_reduction.yaml @@ -164,3 +164,50 @@ # Excess over the 37 percent bracket: 900_000 - 640_600 = 259_400 # Lesser: 200_000; reduction: 200_000 * 2 / 37 = 10_810.81 itemized_taxable_income_deductions_reduction: 10_810.81 + +# Wagering losses (section 165(d)) are itemized deductions. Before 2018 +# section 68(c) kept them out of the 80 percent base; from 2026 the reduction +# counts them like any other itemized deduction. +- name: 2017 single filer - wagering losses are outside the 80 percent base + period: 2017 + absolute_error_margin: 0.01 + input: + adjusted_gross_income: 400_000 + filing_status: SINGLE + gambling_winnings: 20_000 + gambling_losses: 20_000 + charitable_deduction: 10_000 + interest_deduction: 0 + salt_deduction: 0 + casualty_loss_deduction: 0 + misc_deduction: 0 + medical_expense_deduction: 0 + output: + wagering_losses_deduction: 20_000 + # Line 1: 30_000. Line 2: 20_000. Line 3: 10_000. Line 4: 8_000. + # Line 7: 400_000 - 261_500 = 138_500. Line 8: 4_155. + # Line 9: smaller of 8_000 or 4_155. + itemized_taxable_income_deductions_reduction: 4_155 + itemized_taxable_income_deductions: 25_845 + +- name: 2026 single filer - the reduction counts wagering losses + period: 2026 + absolute_error_margin: 0.01 + input: + adjusted_gross_income: 1_000_000 + filing_status: SINGLE + gambling_winnings: 30_000 + gambling_losses: 30_000 + charitable_deduction: 0 + interest_deduction: 0 + salt_deduction: 0 + casualty_loss_deduction: 0 + misc_deduction: 0 + medical_expense_deduction: 0 + output: + # 90% of 30_000 + wagering_losses_deduction: 27_000 + # Excess over the 37 percent bracket: 1_000_000 - 640_600 = 359_400 + # Lesser: 27_000; reduction: 27_000 * 2 / 37 = 1_459.46 + itemized_taxable_income_deductions_reduction: 1_459.46 + itemized_taxable_income_deductions: 25_540.54 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.yaml index bada2192326..ae37d552290 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/itemizing/wagering_losses_deduction.yaml @@ -161,3 +161,136 @@ output: # The parent's own 2,000, not min(11,000, 15,000). wagering_losses_deduction: 2_000 + +# Integration with gross income, itemizing and income tax. Gambling winnings +# are gross income (26 U.S.C. 61(a); Schedule 1 line 8b), and the losses are +# an itemized deduction up to the winnings (26 U.S.C. 165(d); Schedule A line +# 16), 90% of the losses from 2026 (P.L. 119-21 sec. 70114). The cases follow +# PolicyEngine/policyengine-us#9637: a single filer aged 40 in Texas with +# 60,000 of wages. The state and local tax deduction is set to zero so each +# figure can be computed by hand. + +- name: 2024, no gambling. + absolute_error_margin: 0.01 + period: 2024 + input: + age: 40 + employment_income: 60_000 + salt_deduction: 0 + state_code: TX + output: + adjusted_gross_income: 60_000 + # 60,000 - 14,600 standard deduction + taxable_income: 45_400 + # 10% x 11,600 + 12% x 33,800 + income_tax: 5_216 + +- name: 2024, winnings are income and losses below the standard deduction do not help. + absolute_error_margin: 0.01 + period: 2024 + input: + age: 40 + employment_income: 60_000 + gambling_winnings: 10_000 + gambling_losses: 8_000 + salt_deduction: 0 + state_code: TX + output: + irs_gross_income: 70_000 + adjusted_gross_income: 70_000 + wagering_losses_deduction: 8_000 + itemized_taxable_income_deductions: 8_000 + tax_unit_itemizes: false + # 70,000 - 14,600 + taxable_income: 55_400 + # 1,160 + 12% x 35,550 + 22% x 8,250 + income_tax: 7_241 + +- name: 2024, an itemizer deducts losses against the winnings in income. + absolute_error_margin: 0.01 + period: 2024 + input: + age: 40 + employment_income: 60_000 + gambling_winnings: 30_000 + gambling_losses: 25_000 + salt_deduction: 0 + state_code: TX + output: + adjusted_gross_income: 90_000 + wagering_losses_deduction: 25_000 + itemized_taxable_income_deductions: 25_000 + tax_unit_itemizes: true + # 90,000 - 25,000 + taxable_income: 65_000 + # 1,160 + 4,266 + 22% x 17,850 + income_tax: 9_353 + +- name: 2024, equal winnings and losses still raise tax by replacing the standard deduction. + absolute_error_margin: 0.01 + period: 2024 + input: + age: 40 + employment_income: 60_000 + gambling_winnings: 20_000 + gambling_losses: 20_000 + salt_deduction: 0 + state_code: TX + output: + adjusted_gross_income: 80_000 + wagering_losses_deduction: 20_000 + tax_unit_itemizes: true + # 80,000 - 20,000, against 45,400 with no gambling + taxable_income: 60_000 + # 1,160 + 4,266 + 22% x 12,850 + income_tax: 8_253 + +- name: 2026, the itemizer deducts 90% of losses. + absolute_error_margin: 0.01 + period: 2026 + input: + age: 40 + employment_income: 60_000 + gambling_winnings: 30_000 + gambling_losses: 25_000 + salt_deduction: 0 + state_code: TX + output: + adjusted_gross_income: 90_000 + # 90% of 25,000 + wagering_losses_deduction: 22_500 + itemized_taxable_income_deductions: 22_500 + tax_unit_itemizes: true + # 90,000 - 22,500 + taxable_income: 67_500 + # 10% x 12,400 + 12% x 38,000 + 22% x 17,100 + income_tax: 9_562 + +- name: A dependent's winnings and losses do not change the parent's return. + absolute_error_margin: 0.01 + period: 2024 + input: + people: + parent: + age: 40 + employment_income: 60_000 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 30_000 + gambling_losses: 25_000 + tax_units: + tax_unit: + members: [parent, child] + salt_deduction: 0 + households: + household: + members: [parent, child] + state_code: TX + output: + irs_gross_income: [60_000, 0] + adjusted_gross_income: 60_000 + wagering_losses_deduction: 0 + tax_unit_itemizes: false + # 60,000 - 21,900 head of household standard deduction + taxable_income: 38_100 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/gambling_winnings_and_losses.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/gambling_winnings_and_losses.yaml deleted file mode 100644 index 0eef3f1d758..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/gambling_winnings_and_losses.yaml +++ /dev/null @@ -1,131 +0,0 @@ -# Gambling winnings are gross income (26 U.S.C. 61(a); Schedule 1 line 8b). -# Gambling losses are an itemized deduction up to the winnings (26 U.S.C. -# 165(d); Schedule A line 16), 90% of the losses from 2026 (P.L. 119-21 -# sec. 70114). The cases follow PolicyEngine/policyengine-us#9637: a single -# filer aged 40 in Texas with 60,000 of wages. The state and local tax -# deduction is set to zero so each figure can be computed by hand. - -- name: 2024, no gambling. - absolute_error_margin: 0.01 - period: 2024 - input: - age: 40 - employment_income: 60_000 - salt_deduction: 0 - state_code: TX - output: - adjusted_gross_income: 60_000 - # 60,000 - 14,600 standard deduction - taxable_income: 45_400 - # 10% x 11,600 + 12% x 33,800 - income_tax: 5_216 - -- name: 2024, winnings are income and losses below the standard deduction do not help. - absolute_error_margin: 0.01 - period: 2024 - input: - age: 40 - employment_income: 60_000 - gambling_winnings: 10_000 - gambling_losses: 8_000 - salt_deduction: 0 - state_code: TX - output: - irs_gross_income: 70_000 - adjusted_gross_income: 70_000 - wagering_losses_deduction: 8_000 - itemized_taxable_income_deductions: 8_000 - tax_unit_itemizes: false - # 70,000 - 14,600 - taxable_income: 55_400 - # 1,160 + 12% x 35,550 + 22% x 8,250 - income_tax: 7_241 - -- name: 2024, an itemizer deducts losses against the winnings in income. - absolute_error_margin: 0.01 - period: 2024 - input: - age: 40 - employment_income: 60_000 - gambling_winnings: 30_000 - gambling_losses: 25_000 - salt_deduction: 0 - state_code: TX - output: - adjusted_gross_income: 90_000 - wagering_losses_deduction: 25_000 - itemized_taxable_income_deductions: 25_000 - tax_unit_itemizes: true - # 90,000 - 25,000 - taxable_income: 65_000 - # 1,160 + 4,266 + 22% x 17,850 - income_tax: 9_353 - -- name: 2024, equal winnings and losses still raise tax by replacing the standard deduction. - absolute_error_margin: 0.01 - period: 2024 - input: - age: 40 - employment_income: 60_000 - gambling_winnings: 20_000 - gambling_losses: 20_000 - salt_deduction: 0 - state_code: TX - output: - adjusted_gross_income: 80_000 - wagering_losses_deduction: 20_000 - tax_unit_itemizes: true - # 80,000 - 20,000, against 45,400 with no gambling - taxable_income: 60_000 - # 1,160 + 4,266 + 22% x 12,850 - income_tax: 8_253 - -- name: 2026, the itemizer deducts 90% of losses. - absolute_error_margin: 0.01 - period: 2026 - input: - age: 40 - employment_income: 60_000 - gambling_winnings: 30_000 - gambling_losses: 25_000 - salt_deduction: 0 - state_code: TX - output: - adjusted_gross_income: 90_000 - # 90% of 25,000 - wagering_losses_deduction: 22_500 - itemized_taxable_income_deductions: 22_500 - tax_unit_itemizes: true - # 90,000 - 22,500 - taxable_income: 67_500 - # 10% x 12,400 + 12% x 38,000 + 22% x 17,100 - income_tax: 9_562 - -- name: A dependent's winnings and losses do not change the parent's return. - absolute_error_margin: 0.01 - period: 2024 - input: - people: - parent: - age: 40 - employment_income: 60_000 - child: - age: 17 - is_tax_unit_dependent: true - gambling_winnings: 30_000 - gambling_losses: 25_000 - tax_units: - tax_unit: - members: [parent, child] - salt_deduction: 0 - households: - household: - members: [parent, child] - state_code: TX - output: - irs_gross_income: [60_000, 0] - adjusted_gross_income: 60_000 - wagering_losses_deduction: 0 - tax_unit_itemizes: false - # 60,000 - 21,900 head of household standard deduction - taxable_income: 38_100 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/irs_gross_income.yaml b/policyengine_us/tests/policy/baseline/gov/irs/irs_gross_income.yaml index 5e241bbd3ee..ce70da66e59 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/irs_gross_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/irs_gross_income.yaml @@ -94,3 +94,21 @@ members: [parent, child] output: irs_gross_income: [0, 0] + +- name: Gambling winnings are gross income for the filer, not a dependent's on this return. + period: 2024 + input: + people: + parent: + is_tax_unit_head: true + gambling_winnings: 10_000 + gambling_losses: 4_000 + child: + is_tax_unit_dependent: true + gambling_winnings: 5_000 + tax_units: + tax_unit: + members: [parent, child] + output: + # The full winnings, not reduced by losses. + irs_gross_income: [10_000, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/al_agi.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/al_agi.yaml index 61f8a63a5c7..ac6be51d557 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/al_agi.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/al_agi.yaml @@ -79,3 +79,26 @@ state_code: AL output: al_agi: 70_000 + +- name: A dependent's gambling winnings are not in the parent's Alabama AGI. + absolute_error_margin: 0.01 + period: 2025 + input: + people: + parent: + age: 40 + gambling_winnings: 2_000 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 20_000 + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: AL + output: + al_gambling_winnings: [2_000, 0] + al_agi: 2_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.yaml b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.yaml index 547b1136b91..c460bfcd3f0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.yaml @@ -226,3 +226,38 @@ output: de_itemized_deductions_unit: 8_000 de_itemized_deductions_indv: [6_000, 2_000] + +- name: A dependent's gambling losses do not change the spouses' wagering allocation. + absolute_error_margin: 0.01 + period: 2025 + input: + people: + head: + age: 40 + employment_income: 40_000 + gambling_winnings: 10_000 + gambling_losses: 6_000 + spouse: + age: 40 + employment_income: 50_000 + gambling_losses: 2_000 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 10_000 + gambling_losses: 8_000 + tax_units: + tax_unit: + members: [head, spouse, child] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse, child] + state_code: DE + output: + de_itemized_deductions_unit: 8_000 + # The head's 6,000 and the spouse's 2,000; the child's 8,000 is on the + # child's own return. + de_itemized_deductions_indv: [6_000, 2_000, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_gross_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_gross_income.yaml index 7337123adcd..b2c25a9d95a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_gross_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_gross_income.yaml @@ -5,3 +5,28 @@ state_code: IA output: ia_gross_income: 100_000 + +- name: Gambling winnings are Iowa gross income on the 2021 return (IA 1040 line 13). + absolute_error_margin: 0.01 + period: 2021 + input: + people: + parent: + age: 40 + irs_employment_income: 60_000 + gambling_winnings: 10_000 + child: + age: 17 + is_tax_unit_dependent: true + gambling_winnings: 5_000 + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: IA + output: + ia_gambling_winnings: [10_000, 0] + # The child's winnings are on the child's own return. + ia_gross_income: [70_000, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/deductions/ky_itemized_deductions_unit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/deductions/ky_itemized_deductions_unit.yaml index c43befc6998..3a938a4225f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/deductions/ky_itemized_deductions_unit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/deductions/ky_itemized_deductions_unit.yaml @@ -17,3 +17,37 @@ medical_expense_deduction: 2 output: ky_itemized_deductions_unit: 8 + +- name: Kentucky allowed no wagering losses for 2018. + absolute_error_margin: 0.01 + period: 2018 + input: + gambling_winnings: 30_000 + gambling_losses: 30_000 + charitable_deduction: 4_000 + state_code: KY + output: + wagering_losses_deduction: 30_000 + ky_itemized_deductions_unit: 4_000 + +- name: Kentucky allows wagering losses from 2019. + absolute_error_margin: 0.01 + period: 2019 + input: + gambling_winnings: 30_000 + gambling_losses: 30_000 + charitable_deduction: 4_000 + state_code: KY + output: + ky_itemized_deductions_unit: 34_000 + +- name: Kentucky follows the 90% share from 2026. + absolute_error_margin: 0.01 + period: 2026 + input: + gambling_winnings: 30_000 + gambling_losses: 30_000 + charitable_deduction: 4_000 + state_code: KY + output: + ky_itemized_deductions_unit: 31_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_wagering_losses_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_wagering_losses_deduction.yaml index 7562dc3b96f..e466004d8e4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_wagering_losses_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_wagering_losses_deduction.yaml @@ -52,3 +52,59 @@ output: wagering_losses_deduction: 8_000 mt_wagering_losses_deduction: [8_000, 0, 0] + +- name: When both Montana spouses have winnings, each claims their own losses. + absolute_error_margin: 0.01 + period: 2023 + input: + people: + head: + age: 40 + gambling_winnings: 10_000 + gambling_losses: 8_000 + spouse: + age: 40 + gambling_winnings: 10_000 + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: MT + output: + wagering_losses_deduction: 8_000 + mt_wagering_losses_deduction: [8_000, 0] + +- name: Montana losses beyond a spouse's own winnings go to the spouse with winnings left. + absolute_error_margin: 0.01 + period: 2023 + input: + people: + head: + age: 40 + gambling_winnings: 4_000 + gambling_losses: 9_000 + spouse: + age: 40 + gambling_winnings: 10_000 + gambling_losses: 1_000 + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: MT + output: + # The return deducts min(10,000, 14,000) = 10,000. The head takes 4,000 + # against their own winnings and the spouse 1,000; the other 5,000 falls + # on the spouse's remaining 9,000 of winnings. + wagering_losses_deduction: 10_000 + mt_wagering_losses_deduction: [4_000, 6_000] diff --git a/policyengine_us/variables/gov/states/al/tax/income/al_gambling_winnings.py b/policyengine_us/variables/gov/states/al/tax/income/al_gambling_winnings.py new file mode 100644 index 00000000000..377b8043315 --- /dev/null +++ b/policyengine_us/variables/gov/states/al/tax/income/al_gambling_winnings.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class al_gambling_winnings(Variable): + value_type = float + entity = Person + label = "Alabama gambling winnings" + unit = USD + documentation = ( + "Gambling winnings reported on the Alabama return of the tax unit's " + "head or spouse. A dependent who must file reports their own " + "winnings on their own return." + ) + definition_period = YEAR + reference = ( + # 2025 Form 40 booklet: who must file, and taxable income + # PDF pages 5, 7 + "https://www.revenue.alabama.gov/wp-content/uploads/2026/01/25f40bk.pdf#page=5", + ) + defined_for = StateCode.AL + + def formula(person, period, parameters): + is_dependent = person("is_tax_unit_dependent", period) + return ~is_dependent * person("gambling_winnings", period) diff --git a/policyengine_us/variables/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.py b/policyengine_us/variables/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.py index eeecae99e3a..15096c6f5f3 100644 --- a/policyengine_us/variables/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.py +++ b/policyengine_us/variables/gov/states/de/tax/income/deductions/itemized/de_itemized_deductions_indv.py @@ -15,6 +15,9 @@ "casualty_loss_deduction": ["casualty_loss"], "wagering_losses_deduction": ["gambling_losses"], } +# Deductions that count only the head's and spouse's expenses, so a +# dependent's expense leaves nothing unallocated. +FILER_ONLY_DEDUCTIONS = ("wagering_losses_deduction",) def _share(numerator, denominator): @@ -65,6 +68,8 @@ def formula(person, period, parameters): continue amount = person.tax_unit(deduction, period) expense = add(person, period, expense_sources) + if deduction in FILER_ONLY_DEDUCTIONS: + expense = head_or_spouse * expense total_expense = person.tax_unit.sum(expense) allocated += amount * _share(head_or_spouse * expense, total_expense) # Prorate what could not be specifically allocated. diff --git a/policyengine_us/variables/gov/states/ia/tax/income/net_income/ia_gambling_winnings.py b/policyengine_us/variables/gov/states/ia/tax/income/net_income/ia_gambling_winnings.py new file mode 100644 index 00000000000..a9d014f7c58 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/tax/income/net_income/ia_gambling_winnings.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ia_gambling_winnings(Variable): + value_type = float + entity = Person + label = "Iowa gambling winnings" + unit = USD + documentation = ( + "Gambling winnings reported on IA 1040 line 13 by the tax unit's " + "head or spouse, for the returns before 2023 that start from Iowa " + "gross income. A dependent reports their own winnings on their own " + "return." + ) + definition_period = YEAR + reference = ( + "https://revenue.iowa.gov/sites/default/files/2022-01/IA1040%2841-001%29.pdf#page=1", + "https://revenue.iowa.gov/sites/default/files/2023-01/2022IA1040%2841001%29.pdf#page=1", + ) + defined_for = StateCode.IA + + def formula(person, period, parameters): + is_dependent = person("is_tax_unit_dependent", period) + return ~is_dependent * person("gambling_winnings", period) diff --git a/policyengine_us/variables/gov/states/ky/tax/income/deductions/ky_itemized_deductions_unit.py b/policyengine_us/variables/gov/states/ky/tax/income/deductions/ky_itemized_deductions_unit.py index 7adcc1154a8..3ba86e2e5b5 100644 --- a/policyengine_us/variables/gov/states/ky/tax/income/deductions/ky_itemized_deductions_unit.py +++ b/policyengine_us/variables/gov/states/ky/tax/income/deductions/ky_itemized_deductions_unit.py @@ -10,8 +10,18 @@ class ky_itemized_deductions_unit(Variable): reference = ( "https://revenue.ky.gov/Forms/Form%20740%20Schedule%20A%202022.pdf", "https://law.justia.com/codes/kentucky/2022/chapter-141/section-141-019/", # (2)(i) + # 2019 Ky. Acts ch. 151, sec. 37: wagering losses allowed from 2019 + # PDF pages 60, 112 + "https://apps.legislature.ky.gov/law/acts/19RS/documents/0151.pdf#page=60", ) defined_for = StateCode.KY - adds = ["itemized_deductions_less_salt"] - subtracts = ["medical_expense_deduction"] + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.ky.tax.income.deductions.itemized + deductions = tax_unit("itemized_deductions_less_salt", period) - tax_unit( + "medical_expense_deduction", period + ) + if p.wagering_losses_allowed: + return deductions + # KRS 141.019(2) excluded every section 165 loss for 2018. + return deductions - tax_unit("wagering_losses_deduction", period) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_wagering_losses_deduction.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_wagering_losses_deduction.py index 01364571cd1..fd79d28733d 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_wagering_losses_deduction.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_wagering_losses_deduction.py @@ -8,24 +8,36 @@ class mt_wagering_losses_deduction(Variable): unit = USD documentation = ( "The person's part of the federal wagering losses deduction, which " - "Montana allows as an itemized deduction. When spouses file " - "separately, the spouse who reports the gambling winnings claims " - "the losses." + "Montana allows as an itemized deduction. Each spouse takes their " + "own losses against their own winnings; losses beyond that go to " + "the spouse with winnings left to absorb them, since the spouse who " + "reports the winnings claims the losses." ) definition_period = YEAR reference = ( - "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=39", + # 2023 Form 2 instructions: allocating deductions between spouses, + # and gambling losses + # PDF pages 13, 39 + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=13", "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=13", ) defined_for = StateCode.MT def formula(person, period, parameters): deduction = person.tax_unit("wagering_losses_deduction", period) + p = parameters(period).gov.irs.deductions.itemized.wagering_losses # The federal deduction counts the head's and spouse's gambling. head_or_spouse = person("is_tax_unit_head_or_spouse", period) winnings = head_or_spouse * person("gambling_winnings", period) - total_winnings = person.tax_unit.sum(winnings) - share = np.zeros_like(total_winnings) - mask = total_winnings > 0 - share[mask] = winnings[mask] / total_winnings[mask] - return deduction * share + losses = head_or_spouse * person("gambling_losses", period) + # Losses the person can deduct against their own winnings. + own = min_(p.rate * losses, winnings) + # What is left of the return's deduction falls on winnings that the + # winner's own losses did not cover. + remaining = max_(deduction - person.tax_unit.sum(own), 0) + unused_winnings = winnings - own + total_unused = person.tax_unit.sum(unused_winnings) + share = np.zeros_like(total_unused) + mask = total_unused > 0 + share[mask] = unused_winnings[mask] / total_unused[mask] + return own + remaining * share diff --git a/policyengine_us/variables/household/income/person/gambling_losses.py b/policyengine_us/variables/household/income/person/gambling_losses.py index b93b6bb0f64..6d40dbbfc19 100644 --- a/policyengine_us/variables/household/income/person/gambling_losses.py +++ b/policyengine_us/variables/household/income/person/gambling_losses.py @@ -6,4 +6,13 @@ class gambling_losses(Variable): entity = Person label = "Gambling losses" unit = USD + documentation = ( + "Losses from wagering transactions of a person who does not gamble " + "as a trade or business, such as the cost of losing bets and of " + "non-winning lottery and raffle tickets (Schedule A (Form 1040) " + "line 16), before any limit. This input does not separate losses " + "by where the wager was placed, so state rules that depend on it " + "(a state lottery, in-state licensed gaming) are not modeled." + ) definition_period = YEAR + reference = "https://www.irs.gov/pub/irs-prior/i1040sca--2024.pdf#page=11" diff --git a/policyengine_us/variables/household/income/person/gambling_winnings.py b/policyengine_us/variables/household/income/person/gambling_winnings.py index 9b3c9b21f1e..c946902f1ac 100644 --- a/policyengine_us/variables/household/income/person/gambling_winnings.py +++ b/policyengine_us/variables/household/income/person/gambling_winnings.py @@ -6,4 +6,16 @@ class gambling_winnings(Variable): entity = Person label = "Gambling winnings" unit = USD + documentation = ( + "Gambling winnings of a person who does not gamble as a trade or " + "business, as reported on Schedule 1 (Form 1040) line 8b: the full " + "winnings, including lottery and raffle prizes, not reduced by " + "losses. This input does not separate winnings by source or by " + "prize, so state rules that depend on them (a state's own lottery, " + "prizes under a threshold, noncash prizes) are not modeled." + ) definition_period = YEAR + reference = ( + "https://www.irs.gov/pub/irs-prior/f1040s1--2024.pdf#page=1", + "https://www.irs.gov/pub/irs-prior/i1040gi--2025.pdf#page=91", + ) From 4bfb615ab7d5ec6a1aa9dcf07b25f6348e75c774 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 11 Oct 2026 10:10:54 -0400 Subject: [PATCH 4/4] Clarify gambling property-test coverage and trim Hawaii test whitespace --- .../itemized/hi_reduced_itemized_deductions.yaml | 1 - .../unit/test_gambling_winnings_and_losses_properties.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.yaml index 0afcdac5fed..05bb4f44a11 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/deductions/itemized/hi_reduced_itemized_deductions.yaml @@ -93,4 +93,3 @@ # Smaller of 80% x (10,000 - 4,000) = 4,800 and 3% x (266,800 - 166,800) # = 3,000. hi_reduced_itemized_deductions: 7_000 - diff --git a/policyengine_us/tests/unit/test_gambling_winnings_and_losses_properties.py b/policyengine_us/tests/unit/test_gambling_winnings_and_losses_properties.py index 3c7e55e9bff..3707061a2fc 100644 --- a/policyengine_us/tests/unit/test_gambling_winnings_and_losses_properties.py +++ b/policyengine_us/tests/unit/test_gambling_winnings_and_losses_properties.py @@ -6,10 +6,10 @@ for taxable years beginning after 2025. A dependent's gambling belongs on the dependent's own return. -YAML cases check single households. These tests check relations between -households, which a YAML case cannot state, at every point of a winnings x -losses x other itemized deductions grid. Each year uses one vectorized -simulation; the grid point with no gambling is the baseline for the others. +YAML cases check specific households. These tests reuse a generated grid to +check relations between households at every point of winnings x losses x +other itemized deductions. Each year uses one vectorized simulation; the grid +point with no gambling is the baseline for the others. - The deduction equals min(share x losses, winnings), with the share restated here from the statute (1 through 2025, 0.9 from 2026).