Skip to content
Open
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
4 changes: 4 additions & 0 deletions changelog_entry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- bump: minor
changes:
fixed:
- Mississippi income tax now correctly applies federal $3,000 capital loss limitation instead of allowing unlimited capital losses to offset ordinary income
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ values:
- irs_employment_income # Wages, salaries, tips, etc.
- self_employment_income
- partnership_s_corp_income
- capital_gains
- loss_limited_net_capital_gains_person # Federal Schedule D with $3,000 capital loss limit applied
- rental_income
- farm_income
- interest_income
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,33 @@
ms_total_exemptions_joint: [12_000, 0]
ms_taxable_income_joint: [12_892, 11_307]
ms_income_tax: 197

- name: MS joint with capital losses should use federal $3,000 limit
absolute_error_margin: 100
period: 2024
input:
people:
person1:
age: 40
short_term_capital_gains: -4_835_234
long_term_capital_gains: 2_450_480.75
taxable_interest_income: 202_089.485
is_tax_unit_head: true
person2:
age: 40
short_term_capital_gains: -4_835_234
long_term_capital_gains: 2_450_480.75
taxable_interest_income: 202_089.485
is_tax_unit_spouse: true
tax_units:
tax_unit:
members: [person1, person2]
spm_units:
spm_unit:
members: [person1, person2]
households:
household:
members: [person1, person2]
state_fips: 28
output:
ms_income_tax: 17_136
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Unit tests for loss_limited_net_capital_gains_person
# This variable allocates the tax unit's loss-limited capital gains
# proportionally to each person based on their share of total net capital gains/losses.
# Loss limit is $3,000 ($1,500 for married filing separately).
# Inputs are person-level: long_term_capital_gains and short_term_capital_gains

- name: Single person with positive capital gains - no limitation applied
period: 2024
input:
long_term_capital_gains: 10_000
filing_status: SINGLE
output:
loss_limited_net_capital_gains_person: 10_000

- name: Single person with small loss within limit - no limitation applied
period: 2024
input:
long_term_capital_gains: -2_000
filing_status: SINGLE
output:
loss_limited_net_capital_gains_person: -2_000

- name: Single person with loss exceeding limit - limited to -3000
period: 2024
input:
long_term_capital_gains: -10_000
filing_status: SINGLE
output:
# Loss is limited to -$3,000 for single filers
loss_limited_net_capital_gains_person: -3_000

- name: Joint filers both with losses - limited to -3000 and allocated proportionally
period: 2024
input:
people:
person1:
long_term_capital_gains: -6_000
person2:
long_term_capital_gains: -4_000
tax_units:
tax_unit:
members: [person1, person2]
filing_status: JOINT
output:
# Total loss is -$10,000, limited to -$3,000
# person1 has 60% of losses (-6000/-10000), person2 has 40% (-4000/-10000)
# person1: -3000 * 0.6 = -1800
# person2: -3000 * 0.4 = -1200
loss_limited_net_capital_gains_person: [-1_800, -1_200]

- name: Married filing separately with loss - limited to -1500
period: 2024
input:
long_term_capital_gains: -5_000
filing_status: SEPARATE
output:
# Loss limit is $1,500 for married filing separately
loss_limited_net_capital_gains_person: -1_500

- name: Zero capital gains - returns zero
period: 2024
input:
long_term_capital_gains: 0
short_term_capital_gains: 0
filing_status: SINGLE
output:
loss_limited_net_capital_gains_person: 0

- name: Tax unit with net positive - each person keeps their original amount
period: 2024
input:
people:
person1:
long_term_capital_gains: 8_000
person2:
long_term_capital_gains: -2_000
tax_units:
tax_unit:
members: [person1, person2]
filing_status: JOINT
output:
# Total is +$6,000 (positive), so no loss limitation applies
# Each person keeps their original capital gains
loss_limited_net_capital_gains_person: [8_000, -2_000]

- name: Head of household with loss exceeding limit
period: 2024
input:
long_term_capital_gains: -7_500
filing_status: HEAD_OF_HOUSEHOLD
output:
# Loss limit is $3,000 for head of household
loss_limited_net_capital_gains_person: -3_000

- name: Surviving spouse with loss exceeding limit
period: 2024
input:
long_term_capital_gains: -12_000
filing_status: SURVIVING_SPOUSE
output:
# Loss limit is $3,000 for surviving spouse
loss_limited_net_capital_gains_person: -3_000

- name: Joint filers with unequal losses - proportional allocation
period: 2024
input:
people:
person1:
long_term_capital_gains: -9_000
person2:
long_term_capital_gains: -1_000
tax_units:
tax_unit:
members: [person1, person2]
filing_status: JOINT
output:
# Total loss is -$10,000, limited to -$3,000
# person1 has 90% of losses (-9000/-10000), person2 has 10% (-1000/-10000)
# person1: -3000 * 0.9 = -2700
# person2: -3000 * 0.1 = -300
loss_limited_net_capital_gains_person: [-2_700, -300]

- name: Loss exactly at limit - no adjustment needed
period: 2024
input:
long_term_capital_gains: -3_000
filing_status: SINGLE
output:
loss_limited_net_capital_gains_person: -3_000

- name: Mixed short and long term gains
period: 2024
input:
long_term_capital_gains: 5_000
short_term_capital_gains: 3_000
filing_status: SINGLE
output:
# Total gains: 5000 + 3000 = 8000 (positive, no limitation)
loss_limited_net_capital_gains_person: 8_000
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from policyengine_us.model_api import *


class loss_limited_net_capital_gains_person(Variable):
value_type = float
entity = Person
label = "Loss-limited capital gains (person's share)"
unit = USD
definition_period = YEAR
documentation = (
"Capital gains with federal capital loss limitation applied. "
"This allocates the tax unit's loss_limited_net_capital_gains "
"proportionally to each person based on their share of total net "
"capital gains/losses."
)
reference = (
"https://www.irs.gov/pub/irs-pdf/f1040sd.pdf "
"Federal Schedule D limits capital losses to $3,000 ($1,500 if married filing separately). "
"States that use federal AGI or federal Schedule D amounts should use this variable."
)

def formula(person, period, parameters):
# Get person's net capital gains
person_capital_gains = person("capital_gains", period)

# Get tax unit totals
tax_unit = person.tax_unit
tax_unit_capital_gains = tax_unit.sum(person_capital_gains)
tax_unit_loss_limited = tax_unit(
"loss_limited_net_capital_gains", period
)

# If no capital gains in the tax unit, return 0
# If gains (positive), each person keeps their full amount
# If losses, allocate the loss-limited amount proportionally
is_loss = tax_unit_capital_gains < 0

# Calculate each person's proportion of the tax unit's capital gains
# Avoid division by zero
proportion = where(
tax_unit_capital_gains != 0,
person_capital_gains / tax_unit_capital_gains,
0,
)

# For losses: allocate loss_limited amount proportionally
# For gains or zero: return person's original capital gains
return where(
is_loss,
tax_unit_loss_limited * proportion,
person_capital_gains,
)
Loading