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-part-b-capital-loss.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Keep capital gains and losses out of Massachusetts Part B income, and count capital gain distributions reported without a federal Schedule D on Massachusetts Schedule D (Part C).
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
# Capital gains and losses go on Schedules B and D, never on Form 1,
# lines 3 through 10 (Part B). Expected values are computed line by line
# from the 2023 Form 1, Schedule B and Schedule D. A single filer with
# 60,000 of wages and no other 5.0% income has Part B taxable income of
# 60,000 - 2,000 (Form 1, line 11a) - 4,400 (line 18) = 53,600 (line 19).

- name: A long-term loss applied against short-term gains does not reduce Part B income
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
non_qualified_dividend_income: 1_000
short_term_capital_gains: 3_000
long_term_capital_gains: -1_000
tax_units:
tax_unit:
members: [head]
households:
household:
members: [head]
state_code: MA
output:
# Form 1, line 10 = line 3 = 60,000.
ma_part_b_gross_income: 60_000
ma_part_b_taxable_income: 53_600
# Schedule D, line 13 = -1,000; line 14 = Schedule B, line 25
# = min(1,000, 3,000) = 1,000; line 15 = -1,000 + 1,000 = 0.
# Schedule B: line 26 = 3,000 - 1,000 = 2,000 = line 28; line 31 = 1,000;
# line 32 omitted (Schedule D, line 15 is 0); line 35 = 1,000 + 2,000.
ma_part_a_agi: 3_000
# Schedule B, line 38 = line 9 = 1,000; line 39 = 3,000 - 1,000 = 2,000.
ma_part_a_taxable_dividend_income: 1_000
ma_part_a_taxable_capital_gains_income: 2_000
ma_part_c_agi: 0
# 5% x (53,600 + 1,000) + 8.5% x 2,000 = 2,730 + 170.
ma_income_tax_before_credits: 2_900

- name: A long-term loss applied against short-term gains without dividends
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
short_term_capital_gains: 3_000
long_term_capital_gains: -1_000
tax_units:
tax_unit:
members: [head]
households:
household:
members: [head]
state_code: MA
output:
ma_part_b_gross_income: 60_000
# Schedule B, line 25 = 1,000; line 28 = line 39 = 2,000.
ma_part_a_agi: 2_000
ma_part_a_taxable_capital_gains_income: 2_000
# 5% x 53,600 + 8.5% x 2,000 = 2,680 + 170.
ma_income_tax_before_credits: 2_850

- name: A long-term loss larger than the short-term gain does not reduce Part B income
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
non_qualified_dividend_income: 1_000
short_term_capital_gains: 1_000
long_term_capital_gains: -3_000
tax_units:
tax_unit:
members: [head]
households:
household:
members: [head]
state_code: MA
output:
ma_part_b_gross_income: 60_000
ma_part_b_taxable_income: 53_600
# Schedule D, line 14 = Schedule B, line 25 = min(3,000, 1,000) = 1,000;
# line 15 = -2,000. Line 32 worksheet: line 2 = min(1,000, 2,000) = 1,000;
# line 4 = 1,000; line 5 = 2,000; line 6 = 1,000. Schedule B,
# line 33 = 1,000 - 1,000 = 0; line 35 = 0 + 0. Schedule D, line 17
# = -2,000 + 1,000 = -1,000 is carried over (line 23).
ma_part_a_agi: 0
ma_part_c_agi: 0

- name: One spouse's short-term loss against the other spouse's long-term gain does not add to Part B income
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
long_term_capital_gains: 5_000
spouse:
age: 40
short_term_capital_gains: -2_000
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: MA
output:
# Form 1, line 10 = line 3 = 60,000; line 19 = 60,000 - 2,000 - 8,800.
ma_part_b_gross_income: 60_000
ma_part_b_taxable_income: 49_200
# Schedule B: line 19c = -2,000; line 20 = 0 (line 9 is 0); line 21
# = -2,000; line 22 = Schedule D, line 14 = min(2,000, 5,000) = 2,000.
# Schedule D, line 15 = 5,000 - 2,000 = 3,000 = line 21.
ma_part_a_agi: 0
ma_part_c_agi: 3_000
# 5% x 49,200 + 5% x 3,000 = 2,460 + 150.
ma_income_tax_before_credits: 2_610

- name: Capital gain distributions without a federal Schedule D are Part C income
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
non_sch_d_capital_gains: 5_000
tax_units:
tax_unit:
members: [head]
households:
household:
members: [head]
state_code: MA
output:
ma_part_b_gross_income: 60_000
ma_part_b_taxable_income: 53_600
# Schedule D, line 6 = 5,000 = lines 9, 11, 13, 15, 17, 19 and 21.
ma_part_c_gross_income: 5_000
ma_part_c_agi: 5_000
# 5% x 53,600 + 5% x 5,000 = 2,680 + 250.
ma_income_tax_before_credits: 2_930

- name: A short-term loss offsets capital gain distributions in Part C
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
non_sch_d_capital_gains: 5_000
short_term_capital_gains: -2_000
tax_units:
tax_unit:
members: [head]
households:
household:
members: [head]
state_code: MA
output:
ma_part_b_gross_income: 60_000
# Schedule B: line 19c = -2,000; line 20 = 0 (line 9 is 0); line 21
# = -2,000; line 22 = Schedule D, line 14 = min(2,000, 5,000) = 2,000.
# Schedule D, line 15 = 5,000 - 2,000 = 3,000.
ma_part_c_agi: 3_000
# 5% x 53,600 + 5% x 3,000 = 2,680 + 150.
ma_income_tax_before_credits: 2_830

- name: A long-term loss offsets capital gain distributions on Schedule D
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
non_sch_d_capital_gains: 5_000
long_term_capital_gains: -3_000
tax_units:
tax_unit:
members: [head]
households:
household:
members: [head]
state_code: MA
output:
ma_part_b_gross_income: 60_000
# Schedule D: line 1 = -3,000; line 6 = 5,000; line 9 = 2,000 = line 13
# = line 15 = line 21.
ma_part_c_agi: 2_000
# 5% x 53,600 + 5% x 2,000 = 2,680 + 100.
ma_income_tax_before_credits: 2_780

- name: Capital gain distributions that cover a long-term loss leave short-term gains whole
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 40
employment_income: 60_000
non_sch_d_capital_gains: 5_000
short_term_capital_gains: 3_000
long_term_capital_gains: -1_000
tax_units:
tax_unit:
members: [head]
households:
household:
members: [head]
state_code: MA
output:
ma_part_b_gross_income: 60_000
# Schedule D, line 13 = -1,000 + 5,000 = 4,000, so Schedule B, line 25
# is omitted: line 26 = line 24 = 3,000 = line 28 = line 39.
ma_part_a_agi: 3_000
ma_part_a_taxable_capital_gains_income: 3_000
ma_part_c_agi: 4_000
# 5% x 53,600 + 8.5% x 3,000 + 5% x 4,000 = 2,680 + 255 + 200.
ma_income_tax_before_credits: 3_135
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ def formula(tax_unit, period, parameters):
short_term_capital_loss,
),
)
long_term_capital_gains = add(tax_unit, period, ["long_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)

long_term_loss_against_short_term_gain = min_(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,23 @@ class ma_part_b_gross_income(Variable):
defined_for = StateCode.MA

def formula(tax_unit, period, parameters):
# M.G.L. c. 62 § 2(b)(2): Part B gross income is Massachusetts gross
# income not included in Part A or Part C gross income.
ma_gross_income = tax_unit("ma_gross_income", period)
ma_part_a_gross_income = tax_unit("ma_part_a_gross_income", period)
ma_part_c_gross_income = tax_unit("ma_part_c_gross_income", period)
return max_(
0,
ma_gross_income - ma_part_a_gross_income - ma_part_c_gross_income,
# ma_gross_income starts from irs_gross_income, which adds each
# filer's dividends and net capital gain floored at zero. Remove those
# same amounts: they go on Schedules B and D, and capital losses never
# reduce Part B income (§ 2(d)(1)(M) disallows IRC § 62(a)(3)).
# Subtracting Part A and Part C gross income instead would leave the
# difference between their loss netting and irs_gross_income's in Part B.
person = tax_unit.members
is_dependent = person("is_tax_unit_dependent", period)
dividends = max_(0, person("dividend_income", period))
capital_gains = max_(0, person("capital_gains", period))
# Capital gain distributions reported without a federal Schedule D
# go on Massachusetts Schedule D, line 6.
distributions = max_(0, person("non_sch_d_capital_gains", period))
part_a_and_c_income = tax_unit.sum(
where(is_dependent, 0, dividends + capital_gains + distributions)
)
return max_(0, ma_gross_income - part_a_and_c_income)
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ class ma_part_c_gross_income(Variable):
defined_for = StateCode.MA

def formula(tax_unit, period, parameters):
# Long-term capital gains
ltcg = add(tax_unit, period, ["long_term_capital_gains"])
# Long-term capital gains, with capital gain distributions reported
# without a federal Schedule D (Massachusetts Schedule D, line 6)
ltcg = add(
tax_unit, period, ["long_term_capital_gains", "non_sch_d_capital_gains"]
)
# Short-term capital gains (can be negative)
stcg = add(tax_unit, period, ["short_term_capital_gains"])
# Per MA Schedule B line 22, short-term losses offset long-term gains
Expand Down
Loading