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/de-fs4-own-personal-credit-column.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Keep each spouse's own Delaware personal credit in their own Filing Status 4 column per the PIT-RES line 27a example, allocating only dependent credits between columns, so the post-credit filing-status election no longer favors combined-separate filing through an impermissible credit shift.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
state_code: DE
output:
# 2 exemptions × $110 = $220, all to spouse (more capacity)
de_personal_credit_indv: [0, 220]
# Each spouse's own $110 stays in their column (PIT-RES line 27a
# example: "$110 in each column if Filing Status 4"); only dependent
# credits are splittable, and this couple has none.
de_personal_credit_indv: [110, 110]

- name: all credits to higher-capacity column (head)
period: 2025
Expand All @@ -44,7 +47,9 @@
state_code: DE
output:
# 4 exemptions × $110 = $440, all to head (more capacity)
de_personal_credit_indv: [440, 0, 0, 0]
# Own $110 per spouse is fixed; only the two dependents' credits are
# allocable, so the head column can receive at most 110 + 220 = 330.
de_personal_credit_indv: [330, 110, 0, 0]

- name: tied capacity splits evenly
period: 2025
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
- name: DE FS4 does not shift a spouse's own personal credit across columns (taxsim #839)
absolute_error_margin: 2
period: 2025
input:
people:
head:
age: 31
employment_income: 5_490.84
spouse:
age: 32
employment_income: 20_000
c1:
age: 8
c2:
age: 15
marital_units:
marital_unit:
members: [head, spouse]
tax_units:
tax_unit:
members: [head, spouse, c1, c2]
households:
household:
members: [head, spouse, c1, c2]
state_code: DE
output:
# Each spouse's own $110 credit stays in their column (PIT-RES line 27a
# example: "$110 in each column if Filing Status 4"), so legal FS4
# (255.30) exceeds joint (~253) and the election lands on joint:
# tax 692.56 - 440 credits - 321.84 refundable EITC = -69.28, matching
# the TaxAct return (refund $68) and taxsimtest.
de_income_tax: -69.28
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,11 @@
members: [person1, person2, child1, child2]
state_fips: 10
output:
# Per-column: $550 of $660 pre-EITC credits used (line 27a+27b),
# then NR EITC (~$50) applied to higher-income column (line 30).
de_income_tax: 309
# With each spouse's own personal credit fixed to their column
# (PIT-RES line 27a example), legal FS4 leaves column A's credits
# unusable (column tax 0) for a total of 468.34, so the couple
# elects joint filing: 388.42.
de_income_tax: 388.42

- name: FS4 young couple one dependent - per-column personal credit cap (issue #8710)
# DE, MFJ, both age 20, one dependent, $21,790 taxable interest split 50/50,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,51 +11,58 @@ class de_personal_credit_indv(Variable):
defined_for = StateCode.DE

def formula(person, period, parameters):
# PIT-RES Line 27a: "split the total between Columns A and
# B in increments of $110." The form lets the taxpayer
# choose any split; we find the optimal split that maximises
# total credits used (i.e. minimises tax).
# PIT-RES Line 27a: "split the total between Columns A and B in
# increments of $110." The instructions' example pins down how:
# a married couple with no dependents enters "$110 in each column
# if Filing Status 4" - each spouse's own credit belongs to their
# own column, and only the DEPENDENT credits may be split between
# columns. We allocate the dependent increments to maximise total
# credits used (i.e. minimise tax); the taxpayer may choose any
# dependent split, so the optimal one is the tax-minimising one.
p = parameters(period).gov.states.de.tax.income.credits
is_head = person("is_tax_unit_head", period)
is_spouse = person("is_tax_unit_spouse", period)
is_head_or_spouse = is_head | is_spouse

credit_per = p.personal_credits.personal
person_tax = person("de_income_tax_before_non_refundable_credits_indv", period)
head_tax = person.tax_unit.sum(is_head * person_tax)
spouse_tax = person.tax_unit.sum(is_spouse * person_tax)

fixed = person("de_aged_personal_credit_indv", period) + person(
"de_cdcc_indv", period
)
head_fixed = person.tax_unit.sum(is_head * fixed)
spouse_fixed = person.tax_unit.sum(is_spouse * fixed)
# Each column's own $110 personal credit is fixed to that column.
head_fixed = person.tax_unit.sum(is_head * fixed) + credit_per
spouse_fixed = person.tax_unit.sum(is_spouse * fixed) + credit_per

head_capacity = max_(head_tax - head_fixed, 0)
spouse_capacity = max_(spouse_tax - spouse_fixed, 0)

credit_per = p.personal_credits.personal
total_units = person.tax_unit("exemptions_count", period)
total = credit_per * total_units
# Dependent increments: exemptions beyond the two spouses.
dep_units = max_(total_units - 2, 0)

# Optimal split: try proportional floor and ceil, pick
# Optimal dependent split: try proportional floor and ceil, pick
# whichever maximises effective credits (min of alloc vs
# capacity in each column).
# remaining capacity in each column).
total_capacity = head_capacity + spouse_capacity
ratio = where(total_capacity > 0, head_capacity / total_capacity, 0)

n_low = np.floor(total_units * ratio)
n_low = np.floor(dep_units * ratio)
n_high = n_low + 1
n_low = max_(min_(n_low, total_units), 0)
n_high = max_(min_(n_high, total_units), 0)
n_low = max_(min_(n_low, dep_units), 0)
n_high = max_(min_(n_high, dep_units), 0)

eff_low = min_(n_low * credit_per, head_capacity) + min_(
(total_units - n_low) * credit_per, spouse_capacity
(dep_units - n_low) * credit_per, spouse_capacity
)
eff_high = min_(n_high * credit_per, head_capacity) + min_(
(total_units - n_high) * credit_per, spouse_capacity
(dep_units - n_high) * credit_per, spouse_capacity
)

n_head = where(eff_high > eff_low, n_high, n_low)
head_alloc = n_head * credit_per
spouse_alloc = total - head_alloc
n_head_dep = where(eff_high > eff_low, n_high, n_low)
head_alloc = credit_per + n_head_dep * credit_per
spouse_alloc = credit_per + (dep_units - n_head_dep) * credit_per

return where(is_head, head_alloc, where(is_spouse, spouse_alloc, 0))
return is_head_or_spouse * where(is_head, head_alloc, spouse_alloc)
Loading