Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/state-gross-income-estate-income.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Count a beneficiary's estate and trust income in Alabama AGI, Iowa gross income (which Iowa's tax uses through tax year 2022), Mississippi AGI, New Jersey gross income, New Mexico modified gross income, and Oklahoma gross household income for the sales tax and property tax credits.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ values:
- partnership_s_corp_income
- farm_operations_income
- farm_rent_income
# Form 40, Part I, line 5: rents, royalties, partnerships, S corporations,
# trusts and estates (Alabama Schedule E, Part II).
- estate_income

metadata:
unit: list
Expand All @@ -35,7 +38,12 @@ metadata:
href: https://www.taxformfinder.org/forms/2023/2023-alabama-form-40.pdf#page=2
- title: 2024 Alabama Income Tax Instructions
href: https://www.revenue.alabama.gov/wp-content/uploads/2025/01/24f40bk.pdf#page=7
- title: 2025 Alabama Income Tax Instructions
# Examples of income to report (page 7), Part I line 4, other income
# (page 14), and Part I line 5, rents, royalties, partnerships, estates,
# trusts, etc. (page 15).
- title: "2025 Alabama Income Tax Instructions, Form 40 Booklet #page 7,14-15"
href: https://www.revenue.alabama.gov/wp-content/uploads/2026/01/25f40bk.pdf#page=7
- title: 2025 Alabama Income Tax Instructions Form 40 Booklet, Part 1, Line 4 (Other Income)
href: https://www.revenue.alabama.gov/wp-content/uploads/2026/01/25f40bk.pdf#page=14
- title: Code of Alabama 1975 Section 40-18-25(b) (income and deductions of beneficiaries of estates and trusts)
href: https://alison.legislature.state.al.us/code-of-alabama?section=40-18-25
- title: Ala. Admin. Code r. 810-3-25-.11 (Alabama taxable income of beneficiaries for taxable years beginning after December 31, 2004)
href: https://admincode.legislature.state.al.us/administrative-code/810-3-25
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ values:
- taxable_roth_conversions
- partnership_s_corp_income
- rental_income
# Line 10: rents, royalties, partnerships, estates, etc. (federal Schedule E)
- estate_income
- farm_operations_income
- taxable_unemployment_compensation
- miscellaneous_income
Expand All @@ -23,9 +25,10 @@ metadata:
reference:
- title: 2021 IA1040 Iowa Income Tax Return, Lines 1-14
href: https://revenue.iowa.gov/sites/default/files/2022-01/IA1040%2841-001%29.pdf#page=1
- title: 2021 IA1040 Income Tax Return instructions
# Line 10, rents, royalties, partnerships, estates, etc., is on page 19.
- title: "2021 IA1040 Income Tax Return instructions #page 12,19"
href: https://revenue.iowa.gov/media/2650/download?inline#page=12
- title: 2022 IA1040 Iowa Income Tax Return, Lines 1-14
href: https://revenue.iowa.gov/sites/default/files/2023-01/2022IA1040%2841001%29.pdf#page=1
- title: 2022 IA1040 Income Tax Return instructions
- title: "2022 IA1040 Income Tax Return instructions #page 11,19"
href: https://revenue.iowa.gov/media/2721/download?inline#page=11
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ values:
- partnership_s_corp_income
- loss_limited_net_capital_gains_person
- rental_income
# Line 41: rental real estates, royalties, partnerships, S corporations,
# trusts, etc. (income or loss from federal Schedule E)
- estate_income
- farm_operations_income
- interest_income
- qualified_dividend_income
Expand All @@ -31,5 +34,5 @@ metadata:
href: https://www.dor.ms.gov/sites/default/files/tax-forms/individual/80100231.pdf#page=11 # Line 38 - 48
- title: Mississippi Income Tax Instructions 2024
href: https://www.dor.ms.gov/sites/default/files/Forms/Individual/80100241.pdf#page=10
- title: Mississippi Income Tax Instructions 2025
- title: "Mississippi Income Tax Instructions 2025 #page 10-11"
href: https://www.dor.ms.gov/sites/default/files/tax-forms/individual/80100251%202.pdf#page=10
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
description: New Jersey classifies net gains or income derived through estates or trusts as Category (h) and disregards the net if negative under the same-category rule.
values:
2021-01-01:
- estate_income # Line 26: Income from estates and trusts (Schedule NJK-1)
metadata:
unit: list
period: year
label: NJ Category (h) - Estates and trusts
reference:
- title: N.J.S. 54A:5-1(h)
href: https://law.justia.com/codes/new-jersey/title-54a/section-54a-5-1/
# Net losses by category of income (page 9) and line 26, income from
# estates and trusts (page 21).
- title: "2025 NJ-1040 Instructions #page 9,21"
href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=9
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ values:
- self_employment_income
- sstb_self_employment_income
- veterans_benefits
# NMSA 1978 § 7-2-2(L)(15): income from an interest in an estate or a trust
- estate_income
# income such as gambling winnings, insurance settlements, scholarships,
# grants, trust income and inheritance,
# grants and inheritance,
metadata:
unit: list
label: New Mexico modified gross income elements
reference:
- title: New Mexico Income Tax Act, Chapter 7 - Taxation, 7-2-2. Definitions, L
href: https://nmonesource.com/nmos/nmsa/en/item/4340/index.do#!fragment/zoupio-_Toc140503656/BQCwhgziBcwMYgK4DsDWszIQewE4BUBTADwBdoAvbRABwEtsBaAfX2zgEYAWABgFYeAZgBsfYQEoANMmylCEAIqJCuAJ7QA5BskRCYXAiUr1WnXoMgAynlIAhdQCUAogBknANQCCAOQDCTyVIwACNoUnZxcSA
- title: 2025 PIT-RC instructions, line 11 (income from an estate or trust)
href: https://taxsim.nber.org/historical_state_tax_forms/NM/2025/NM_PIT_RC_INST.PDF#page=4
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ values:
- long_term_capital_gains
- interest_income
- rental_income
# Forms 538-S and 538-H, line 11: gross (positive) income from rentals,
# royalties, partnerships, estates and trusts.
- estate_income
- dividend_income
- pension_income
- debt_relief
Expand All @@ -37,5 +40,9 @@ metadata:
href: https://oklahoma.gov/content/dam/ok/en/tax/documents/forms/individuals/past-year/2023/511-Pkt.pdf
- title: 2024 Form 511 instructions
href: https://oklahoma.gov/content/dam/ok/en/tax/documents/forms/individuals/past-year/2024/511-Pkt-2024.pdf
- title: 2025 Form 511 instructions
href: https://oklahoma.gov/content/dam/ok/en/tax/documents/forms/individuals/current/511-Pkt.pdf
- title: 2025 Form 511 packet, Form 538-S, Part 3 (gross income lines 9 to 14)
href: https://oklahoma.gov/content/dam/ok/en/tax/documents/forms/individuals/current/511-Pkt.pdf#page=51
- title: 2025 Form 538-H, line 11 (gross positive income from rentals, royalties, partnerships, estates and trusts)
href: https://oklahoma.gov/content/dam/ok/en/tax/documents/forms/individuals/current/538-H.pdf#page=1
- title: Okla. Admin. Code 710:50-15-96(c) (gross household income is the gross income of every type)
href: https://www.law.cornell.edu/regulations/oklahoma/OAC-710-50-15-96
177 changes: 177 additions & 0 deletions policyengine_us/tests/core/test_state_estate_income_invariants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
"""Invariants for estate and trust income in state-built income concepts.

Six states build an income concept from their own source list rather than
from federal AGI, and each state's form puts a beneficiary's estate or trust
income on a line the list already covers:

- Alabama AGI: Form 40, Part I, line 5. Code of Ala. § 40-18-25(b) follows
federal Subchapter J for a beneficiary's income and deductions, so the
Schedule E amount enters signed.
- Iowa gross income, tax years 2021 and 2022: IA 1040 line 10, "the income or
loss from federal Schedule E".
- Mississippi AGI: Form 80-105 line 41, "the income or loss from activities
reported on Federal Schedule E".
- New Jersey gross income: N.J.S. 54A:5-1(h), a category of its own, so
N.J.S. 54A:5-2 disregards a net loss.
- New Mexico modified gross income: NMSA 1978 § 7-2-2(L)(15), "undiminished
by losses".
- Oklahoma gross household income: Forms 538-S and 538-H line 11, "gross
(positive) income".

Hypothesis draws batches of single filers with wages, interest, partnership
income of either sign and an estate or trust amount of either sign; a seeded
population adds breadth. Each batch runs as one vectorized simulation holding
three copies of every filer in every state: no estate income, the estate
amount, and the same amount entered as rental income instead. For every filer:

1. Signed pass-through (Alabama, Iowa, Mississippi): the concept moves by
exactly the estate amount, loss or gain.
2. Floored pass-through (New Jersey, New Mexico, Oklahoma): the concept moves
by exactly max(estate amount, 0), so a loss never lowers it and never
offsets wages, interest or partnership income.
3. Differential against the existing rental line: the estate amount moves the
concept exactly as the same amount of rental income does, loss or gain.
Each state puts both on the same form line or under the same loss rule.

The identities hold for this income mix. The federal EITC is set to zero
because Oklahoma counts it (Form 538-S line 9) and an estate loss changes it.
"""

import numpy as np
from hypothesis import HealthCheck, given, settings
from hypothesis import strategies as st

from policyengine_us import Simulation

TOLERANCE = 0.01 # dollars

# (state, variable, year, whether an estate or trust loss passes through)
CONCEPTS = [
("AL", "al_agi", 2025, True),
("IA", "ia_gross_income", 2022, True),
("MS", "ms_agi", 2025, True),
("NJ", "nj_gross_income", 2025, False),
("NM", "nm_modified_gross_income", 2025, False),
("OK", "ok_gross_income", 2025, False),
]
YEARS = sorted({year for _, _, year, _ in CONCEPTS})
VARIANTS = ("none", "estate", "rental")

amounts = st.one_of(
st.just(0.0),
st.integers(-200_000, -1).map(float),
st.integers(1, 400_000).map(float),
)


@st.composite
def filers(draw):
return {
"wages": float(draw(st.integers(0, 300_000))),
"interest": float(draw(st.integers(0, 40_000))),
"partnership": float(draw(st.integers(-50_000, 100_000))),
"estate": draw(amounts),
}


SEED = 20261010


def _seeded_filers(n=60):
rng = np.random.default_rng(SEED)
drawn = [
{
"wages": float(rng.integers(0, 300_001)),
"interest": float(rng.integers(0, 40_001)),
"partnership": float(rng.integers(-50_000, 100_001)),
"estate": float(
rng.choice(
[0, rng.integers(-200_000, 0), rng.integers(1, 400_001)],
p=[0.1, 0.4, 0.5],
)
),
}
for _ in range(n)
]
edges = [
# Nothing but an estate or trust loss.
{"wages": 0.0, "interest": 0.0, "partnership": 0.0, "estate": -40_000.0},
# Nothing but estate or trust income.
{"wages": 0.0, "interest": 0.0, "partnership": 0.0, "estate": 25_000.0},
# An estate loss beside partnership income of the same size.
{"wages": 50_000.0, "interest": 0.0, "partnership": 8_000.0, "estate": -8_000.0},
# An estate gain beside a partnership loss of the same size.
{"wages": 50_000.0, "interest": 0.0, "partnership": -8_000.0, "estate": 8_000.0},
] # fmt: skip
return drawn + edges


def _situation(units):
def every_year(value):
return {year: value for year in YEARS}

people, tax_units, households = {}, {}, {}
for state, _, _, _ in CONCEPTS:
for variant in VARIANTS:
for i, unit in enumerate(units):
name = f"{state}_{variant}_{i}"
people[name] = {
"age": every_year(45),
"employment_income": every_year(unit["wages"]),
"taxable_interest_income": every_year(unit["interest"]),
"partnership_s_corp_income": every_year(unit["partnership"]),
"estate_income": every_year(
unit["estate"] if variant == "estate" else 0.0
),
"rental_income": every_year(
unit["estate"] if variant == "rental" else 0.0
),
}
tax_units[name] = {"members": [name], "eitc": every_year(0)}
households[name] = {
"members": [name],
"state_code": every_year(state),
}
return {"people": people, "tax_units": tax_units, "households": households}


def _check(units):
sim = Simulation(situation=_situation(units))
n = len(units)
estate = np.array([unit["estate"] for unit in units])
for index, (state, variable, year, loss_passes_through) in enumerate(CONCEPTS):
# One person per tax unit and household, in insertion order, so a
# person-level and a tax-unit-level concept index the same way.
values = np.asarray(sim.calculate(variable, year), dtype=float)
start = index * len(VARIANTS) * n
none, with_estate, with_rental = (
values[start + k * n : start + (k + 1) * n] for k in range(len(VARIANTS))
)
expected = estate if loss_passes_through else np.maximum(estate, 0)

# 1 and 2. Pass-through, signed or floored.
np.testing.assert_allclose(
with_estate - none, expected, atol=TOLERANCE, err_msg=f"{state} {variable}"
)

# 3. Differential against the rental line.
np.testing.assert_allclose(
with_estate,
with_rental,
atol=TOLERANCE,
err_msg=f"{state} {variable} against rental income",
)


@settings(
max_examples=4,
deadline=None,
suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large],
)
@given(st.lists(filers(), min_size=1, max_size=10))
def test_state_estate_income_invariants(units):
_check(units)


def test_state_estate_income_invariants_seeded_population():
_check(_seeded_filers())
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,27 @@
# AGI leaves all of them on the child's return.
adjusted_gross_income: 40_000
al_agi: 48_500

- name: A beneficiary's estate or trust income is in Alabama AGI
period: 2025
input:
state_code: AL
irs_employment_income: 30_000
estate_income: 5_000
output:
# Form 40, Part I, line 5 carries Schedule E estate and trust income:
# 30,000 + 5,000.
al_agi: 35_000

- name: A beneficiary's estate or trust loss on Schedule E reduces Alabama AGI
period: 2025
input:
state_code: AL
irs_employment_income: 30_000
estate_income: -5_000
output:
# Code of Ala. § 40-18-25(b) follows federal Subchapter J for a
# beneficiary's income and deductions, so depreciation, depletion and
# amortization apportioned to the beneficiary can exceed the income:
# 30,000 - 5,000.
al_agi: 25_000
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,24 @@
state_code: IA
output:
ia_gross_income: 100_000

- name: Estate and trust income is included in Iowa gross income
period: 2022
input:
irs_employment_income: 30_000
estate_income: 5_000
state_code: IA
output:
# 2022 IA 1040 line 10 reports federal Schedule E income, which includes
# estates and trusts: 30,000 + 5,000.
ia_gross_income: 35_000

- name: An estate or trust loss on federal Schedule E reduces Iowa gross income
period: 2022
input:
irs_employment_income: 30_000
estate_income: -5_000
state_code: IA
output:
# Line 10 is "the income or loss from federal Schedule E": 30,000 - 5,000.
ia_gross_income: 25_000
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,25 @@
# 2,119.43) plus health insurance 3,000. The spouse has no adjustment.
ms_agi_adjustments: [5_119.43, 0]
ms_agi: [24_880.57, 20_000]

- name: Estate and trust income is included in Mississippi AGI
period: 2025
input:
irs_employment_income: 30_000
estate_income: 5_000
state_code: MS
output:
# Form 80-105 line 41 reports federal Schedule E income, which includes
# trusts: 30,000 + 5,000, with no adjustments.
ms_agi: 35_000

- name: An estate or trust loss on federal Schedule E reduces Mississippi AGI
period: 2025
input:
irs_employment_income: 30_000
estate_income: -5_000
state_code: MS
output:
# Line 41 is "the income or loss from activities reported on Federal
# Schedule E": 30,000 - 5,000.
ms_agi: 25_000
Loading
Loading