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/ma-schedule-b-loss-order.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Apply Massachusetts Schedule B short-term and long-term losses to dividends before long-term gains, and tax Part A on the dividends left (lines 20, 22 and 33).
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
# Massachusetts Schedule B applies a short-term loss first against up to
# $2,000 of dividends (line 20), then against long-term gains (line 22).
# Expected tax values in the first five cases match the NBER TAXSIM-35 MA
# tax before credits (staxbc) for the same returns. The later cases are
# computed line by line from the 2022 and 2023 Schedules B and D.
# With 60,000 of wages and no other 5.0% income, Part B taxable income is
# 60,000 - 2,000 (Form 1, line 11a) - 8,800 (joint exemption) = 49,200.

- name: Short-term loss below the dividends leaves the net dividends as Part A income
period: 2022
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
qualified_dividend_income: 1_205
short_term_capital_gains: -1_106
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
ma_short_term_loss_against_dividends: 1_106
ma_part_a_agi: 99
ma_part_a_adjusted_dividends: 99
ma_part_a_taxable_dividend_income: 99
ma_part_c_agi: 0
# 5% x (49,200 Part B + 99 Part A).
ma_income_tax_before_credits: 2_464.95

- name: The short-term loss applied against dividends is capped at $2,000
period: 2022
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
qualified_dividend_income: 3_000
short_term_capital_gains: -2_500
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
ma_short_term_loss_against_dividends: 2_000
ma_part_a_taxable_dividend_income: 1_000
ma_income_tax_before_credits: 2_510

- name: A long-term loss also reduces the dividends taxed in Part A
period: 2022
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
qualified_dividend_income: 1_205
long_term_capital_gains: -1_000
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
ma_long_term_loss_against_dividends: 1_000
ma_part_a_taxable_dividend_income: 205
ma_income_tax_before_credits: 2_470.25

- name: Only the short-term loss left after the dividends offsets long-term gains
period: 2022
absolute_error_margin: 0.01
input:
people:
head:
age: 40
qualified_dividend_income: 10_000
short_term_capital_gains: -5_000
long_term_capital_gains: 50_000
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
ma_short_term_loss_against_dividends: 2_000
ma_part_a_agi: 8_000
# The $8,800 exemption is unused in Part B: $8,000 goes to the dividends
# and $800 to the long-term gains.
ma_part_a_taxable_dividend_income: 0
ma_part_a_cg_excess_exemption: 800
# 50,000 - (5,000 - 2,000)
ma_part_c_agi: 47_000
ma_part_c_taxable_income: 46_200
ma_income_tax_before_credits: 2_310

- name: Massachusetts bank interest does not absorb the short-term loss
period: 2022
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
taxable_interest_income: 10_000
qualified_dividend_income: 500
short_term_capital_gains: -1_500
long_term_capital_gains: 5_000
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
ma_short_term_loss_against_dividends: 500
ma_part_a_agi: 0
# 5,000 - (1,500 - 500)
ma_part_c_agi: 4_000
# 5% x (59,000 Part B + 0 Part A + 4,000 Part C).
ma_income_tax_before_credits: 3_150

- name: A short-term loss above the long-term gain leaves only the rest of the gain in Part C
period: 2022
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
qualified_dividend_income: 3_000
short_term_capital_gains: -5_000
long_term_capital_gains: 4_000
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
# Schedule B: line 19c = -5,000; line 20 = min(3,000, 5,000, 2,000)
# = 2,000; line 21 = -5,000 + 2,000 = -3,000.
ma_short_term_loss_against_dividends: 2_000
# Schedule B, line 33 = 3,000 - 2,000 = 1,000 (line 38 = 1,000).
ma_part_a_taxable_dividend_income: 1_000
# Schedule D: line 13 = 4,000; line 14 = Schedule B, line 22
# = min(3,000, 4,000) = 3,000; line 15 = 4,000 - 3,000 = 1,000.
ma_part_c_agi: 1_000
# 5% x (49,200 + 1,000) + 5% x 1,000 = 2,510 + 50.
ma_income_tax_before_credits: 2_560

- name: A short-term loss above a smaller long-term gain leaves no Part C income
period: 2022
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
qualified_dividend_income: 3_000
short_term_capital_gains: -5_000
long_term_capital_gains: 1_000
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
# Schedule B: line 20 = 2,000; line 21 = -3,000.
ma_short_term_loss_against_dividends: 2_000
ma_part_a_taxable_dividend_income: 1_000
# Schedule D: line 14 = Schedule B, line 22 = min(3,000, 1,000)
# = 1,000; line 15 = 1,000 - 1,000 = 0. Schedule B, line 23
# carries over -3,000 + 1,000 = -2,000.
ma_part_c_agi: 0
# 5% x (49,200 + 1,000).
ma_income_tax_before_credits: 2_510

- name: Short-term and long-term losses share the $2,000 cap against dividends
period: 2022
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
qualified_dividend_income: 3_000
short_term_capital_gains: -1_500
long_term_capital_gains: -1_000
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
# Schedule B: line 20 = min(3,000, 1,500, 2,000) = 1,500; line 21 = 0.
ma_short_term_loss_against_dividends: 1_500
# Schedule D, line 15 = -1,000. Line 32 worksheet: line 2 =
# min(3,000, 2,000) = 2,000; line 4 = 2,000 - 1,500 = 500;
# line 5 = 1,000; line 6 = min(500, 1,000) = 500.
ma_long_term_loss_against_dividends: 500
# Schedule B, line 33 = 3,000 - 1,500 - 500 = 1,000.
ma_part_a_adjusted_dividends: 1_000
ma_part_a_taxable_dividend_income: 1_000
ma_part_c_agi: 0
# 5% x (49,200 + 1,000).
ma_income_tax_before_credits: 2_510

- name: Short-term gains in 2023 are taxed at 8.5% and the long-term gain stays in Part C
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
qualified_dividend_income: 1_000
short_term_capital_gains: 2_000
long_term_capital_gains: 4_000
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
# Schedule B: line 19c = 2,000, so lines 20 through 23 are omitted.
ma_short_term_loss_against_dividends: 0
ma_long_term_loss_against_dividends: 0
# Line 33 = 1,000; line 34 = line 28 = 2,000; line 37 = 3,000;
# line 38 = line 9 = 1,000; line 39 = 3,000 - 1,000 = 2,000.
ma_part_a_adjusted_dividends: 1_000
ma_part_a_taxable_dividend_income: 1_000
ma_part_a_taxable_capital_gains_income: 2_000
# Schedule D: line 14 = 0; line 15 = 4,000; line 21 = 4,000.
ma_part_c_agi: 4_000
# 5% x (49,200 + 1,000) + 8.5% x 2,000 + 5% x 4,000
# = 2,510 + 170 + 200.
ma_income_tax_before_credits: 2_880

- name: Capital gain distributions that cover a long-term loss leave no loss for the dividends
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
qualified_dividend_income: 1_000
non_sch_d_capital_gains: 5_000
long_term_capital_gains: -3_000
spouse:
age: 40
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
# Schedule D: line 1 = -3,000; line 6 = 5,000; line 9 = 2,000 = line 13
# = line 15. Line 15 is not a loss, so Schedule B, line 32 is omitted.
ma_long_term_loss_against_dividends: 0
# Schedule B, line 33 = line 31 = 1,000 = line 38.
ma_part_a_adjusted_dividends: 1_000
ma_part_a_taxable_dividend_income: 1_000
ma_part_c_agi: 2_000
# 5% x (49,200 + 1,000) + 5% x 2,000 = 2,510 + 100.
ma_income_tax_before_credits: 2_610
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from policyengine_us.model_api import *


class ma_long_term_loss_against_dividends(Variable):
value_type = float
entity = TaxUnit
label = "MA long-term capital losses applied against dividends"
documentation = (
"Massachusetts Schedule B, line 32: long-term losses left after "
"short-term gains, up to $2,000 of dividends less the short-term "
"losses already applied in line 20."
)
unit = USD
definition_period = YEAR
reference = (
# (c)(2)(b) and (c)(4)
"https://malegislature.gov/Laws/GeneralLaws/PartI/TitleIX/Chapter62/Section2",
"https://taxsim.nber.org/historical_state_tax_forms/MA/2024/dor-2024-inc-sch-b-(form-1).pdf#page=2",
"https://www.mass.gov/doc/2024-form-1-instructions/download#page=25",
)
defined_for = StateCode.MA

def formula(tax_unit, period, parameters):
short_term_capital_gains = add(tax_unit, period, ["short_term_capital_gains"])
nonnegative_short_term_capital_gains = max_(0, short_term_capital_gains)
# Massachusetts Schedule D, line 13 includes capital gain
# distributions reported without a federal Schedule D (line 6).
long_term_capital_gains = add(
tax_unit, period, ["long_term_capital_gains", "non_sch_d_capital_gains"]
)
long_term_capital_loss = max_(0, -long_term_capital_gains)
# Schedule B, line 25: long-term losses first offset short-term gains.
remaining_long_term_loss = max_(
0, long_term_capital_loss - nonnegative_short_term_capital_gains
)
dividends = add(tax_unit, period, ["dividend_income"])
short_term_loss_applied = tax_unit(
"ma_short_term_loss_against_dividends", period
)
cap = parameters(
period
).gov.states.ma.tax.income.capital_gains.deductible_against_interest_dividends
remaining_cap = max_(0, min_(dividends, cap) - short_term_loss_applied)
return min_(remaining_cap, remaining_long_term_loss)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from policyengine_us.model_api import *


class ma_part_a_adjusted_dividends(Variable):
value_type = float
entity = TaxUnit
label = "MA Part A adjusted dividends"
documentation = (
"Massachusetts Schedule B, line 33: dividends less the short-term "
"(line 20) and long-term (line 32) losses applied against them."
)
unit = USD
definition_period = YEAR
reference = "https://taxsim.nber.org/historical_state_tax_forms/MA/2024/dor-2024-inc-sch-b-(form-1).pdf#page=2"
defined_for = StateCode.MA

def formula(tax_unit, period, parameters):
dividends = add(tax_unit, period, ["dividend_income"])
losses_applied = add(
tax_unit,
period,
[
"ma_short_term_loss_against_dividends",
"ma_long_term_loss_against_dividends",
],
)
return max_(0, dividends - losses_applied)
Loading
Loading