policyengine-us 1.351.3__py3-none-any.whl → 1.351.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of policyengine-us might be problematic. Click here for more details.

@@ -63,9 +63,6 @@ from .ctc import (
63
63
  create_ctc_older_child_supplement_reform,
64
64
  create_ctc_additional_bracket_reform,
65
65
  )
66
- from .second_earner import (
67
- create_second_earner_tax_reform,
68
- )
69
66
  from .snap import (
70
67
  create_abolish_snap_deductions_reform,
71
68
  create_abolish_snap_net_income_test_reform,
@@ -192,9 +189,6 @@ def create_structural_reforms_from_parameters(parameters, period):
192
189
  ctc_older_child_supplement = create_ctc_older_child_supplement_reform(
193
190
  parameters, period
194
191
  )
195
- second_earner_tax_reform = create_second_earner_tax_reform(
196
- parameters, period
197
- )
198
192
  abolish_snap_deductions = create_abolish_snap_deductions_reform(
199
193
  parameters, period
200
194
  )
@@ -301,7 +295,6 @@ def create_structural_reforms_from_parameters(parameters, period):
301
295
  salt_phase_out,
302
296
  repeal_state_dependent_exemptions,
303
297
  ctc_older_child_supplement,
304
- second_earner_tax_reform,
305
298
  abolish_snap_deductions,
306
299
  abolish_snap_net_income_test,
307
300
  dc_property_tax_credit,
@@ -55,21 +55,3 @@
55
55
  state_code: CA
56
56
  output:
57
57
  spm_unit_income_decile: 10
58
-
59
- - name: Zero weight SPM unit does not get assigned a decile
60
- period: 2024
61
- input:
62
- people:
63
- person1:
64
- age: 30
65
- spm_units:
66
- spm_unit1:
67
- members: [person1]
68
- spm_unit_oecd_equiv_net_income: 25_000
69
- spm_unit_weight: 0
70
- households:
71
- household1:
72
- members: [person1]
73
- state_code: CA
74
- output:
75
- spm_unit_income_decile: 0
@@ -1,4 +1,5 @@
1
1
  from policyengine_us.model_api import *
2
+ from microdf import MicroSeries
2
3
 
3
4
 
4
5
  class spm_unit_income_decile(Variable):
@@ -9,8 +10,6 @@ class spm_unit_income_decile(Variable):
9
10
  definition_period = YEAR
10
11
 
11
12
  def formula(spm_unit, period, parameters):
12
- from microdf import MicroSeries
13
-
14
13
  income = spm_unit("spm_unit_oecd_equiv_net_income", period)
15
14
  weights = spm_unit("spm_unit_weight", period) * spm_unit.nb_persons()
16
15
  return MicroSeries(income, weights=weights).decile_rank()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: policyengine-us
3
- Version: 1.351.3
3
+ Version: 1.351.5
4
4
  Summary: Add your description here.
5
5
  Author-email: PolicyEngine <hello@policyengine.org>
6
6
  License-File: LICENSE
@@ -3014,7 +3014,7 @@ policyengine_us/params_on_demand/gov/hhs/medicaid/geography/medicaid_rating_area
3014
3014
  policyengine_us/reforms/__init__.py,sha256=FPV8k2633kzUhbKUK8jC6yJONbnZ5n9zLAq2UL57KH4,113
3015
3015
  policyengine_us/reforms/dc_kccatc.py,sha256=LyGMfEKe-0TgQ-2vCYGOD8W-EGEW8_DgIqCQP89qDyg,4283
3016
3016
  policyengine_us/reforms/dc_tax_threshold_joint_ratio.py,sha256=G-5E1EJFGZ3VeUl_fuyj82nMIttHRNRdlT-x98koJrk,1633
3017
- policyengine_us/reforms/reforms.py,sha256=GqiKd7dRYZS4vF-S9sra72FY_XWDZHTh7xOjjK5RY-Q,11932
3017
+ policyengine_us/reforms/reforms.py,sha256=9DUPk18pt7__WmlGSOLHU12Ym7XDdKCuaeqnEEidVyQ,11733
3018
3018
  policyengine_us/reforms/taxsim.py,sha256=bXNFWfjBX5USld1C7fziT6BBmRy-avz00QtL8WmCHy0,5276
3019
3019
  policyengine_us/reforms/winship.py,sha256=_q74Af1nkmoh0-M6PZJ2FcJAn6v5zf5sAEgvxjwHwyA,3069
3020
3020
  policyengine_us/reforms/additional_tax_bracket/__init__.py,sha256=087GDzojnzkbARUgGTQDMNVWJzjtNZvBGr46jfu1kXc,89
@@ -3083,8 +3083,6 @@ policyengine_us/reforms/reconciliation/reconciliation_charitable_deduction.py,sh
3083
3083
  policyengine_us/reforms/reconciliation/reconciliation_qbid_with_floor.py,sha256=EQWZ6d550cvFa1OTT9H2c6-076k0ooP1JKJqA77sjBU,2596
3084
3084
  policyengine_us/reforms/salt_phase_out/__init__.py,sha256=hrFYpSJFxELcG5l2xg38-3lT5oAqBpTGAxG8U5Jcd7E,73
3085
3085
  policyengine_us/reforms/salt_phase_out/salt_phase_out_reform.py,sha256=OfNb_kkd8ohfjchIStNaGtaphK-3eBPufWA2QTLzGlo,1823
3086
- policyengine_us/reforms/second_earner/__init__.py,sha256=pTtUV6BuWBPjUyp_Bj6YDbN0pyygzFw4aiMwYSlYggI,79
3087
- policyengine_us/reforms/second_earner/second_earner_tax_reform.py,sha256=iv33aMPnTModp0A3yRrI5ITrQUDLD5GuXEtPX_t7Quk,32572
3088
3086
  policyengine_us/reforms/snap/__init__.py,sha256=p98y33zLWFe0CMvINQzRAa6av-yHuejyBFYbciOEC4c,178
3089
3087
  policyengine_us/reforms/snap/abolish_snap_deductions.py,sha256=Ad4J4_qiCXa-ORIxWRCD372ITJiCRzdvqRedHOXX5dw,1032
3090
3088
  policyengine_us/reforms/snap/abolish_snap_net_income_test.py,sha256=KoWaDtPkYr5mLt-xcMT6UkmVcCo0UDRYaMVRfiCm9Rs,1166
@@ -5009,7 +5007,7 @@ policyengine_us/tests/policy/baseline/household/income/spm_unit/spm_unit_is_in_s
5009
5007
  policyengine_us/tests/policy/baseline/household/income/spm_unit/spm_unit_market_income.yaml,sha256=gd9JLw32eDURuKYPjxwQZhyRV_6JBWcAm8qk83Tpuus,276
5010
5008
  policyengine_us/tests/policy/baseline/household/income/spm_unit/spm_unit_net_income.yaml,sha256=lZorN8LQYPCNpHDriLdLbaJ8vg3kHHK_UIVcbo7tkdk,218
5011
5009
  policyengine_us/tests/policy/baseline/household/income/tax_unit/spouse_separate_adjusted_gross_income.yaml,sha256=zNhFBR3IFmCJjnScfTvpVfmUv3Xl-yIXKlFA3pNjwsg,373
5012
- policyengine_us/tests/policy/baseline/income/spm_unit_income_decile.yaml,sha256=aPql88ytCKKZp_bxmH8yGgC8_4DW465xYyNqUsas6i0,1648
5010
+ policyengine_us/tests/policy/baseline/income/spm_unit_income_decile.yaml,sha256=1wLKnDqXKVBadZKYVGYlA1NpsS8VgHAlnV9JU97IRf4,1263
5013
5011
  policyengine_us/tests/policy/contrib/dc_kccatc.yaml,sha256=v4woAJveF3mZH6d4W3xAYlejcTIHTEQZM4nnenGNq-8,1786
5014
5012
  policyengine_us/tests/policy/contrib/dc_single_joint_threshold_ratio.yaml,sha256=vDMmkKdvjCtR8uweKDptp1gt05OI78Pm7GoIL0Apxxg,632
5015
5013
  policyengine_us/tests/policy/contrib/reported_state_income_tax.yaml,sha256=697RFAYWbmvD4LdQA-RHnIJ8nuu9wwEc2IRejdJ4QAQ,232
@@ -5052,7 +5050,6 @@ policyengine_us/tests/policy/contrib/reconciliation/reconciliation_cdcc.yaml,sha
5052
5050
  policyengine_us/tests/policy/contrib/reconciliation/reconciliation_charitable_deduction.yaml,sha256=FeuKCLKePa4G-bWVcCGiK5CFmxK3nwppH3xEqKCRZ50,2336
5053
5051
  policyengine_us/tests/policy/contrib/reconciliation/reconciliation_qbid_with_floor.yaml,sha256=GrZzqHljo8pYanbg3HQ0UapuVEgXkteq9gazH13wmxY,1386
5054
5052
  policyengine_us/tests/policy/contrib/salt_phase_out/salt_phase_out_reform.yaml,sha256=xOwKAjQm-c191Ig2JoosB541CrQ8Xl4SSfXqUvvZmps,3602
5055
- policyengine_us/tests/policy/contrib/second_earner/second_earner_tax_reform.yaml,sha256=FAEAJplFE6y93Yo2y6ikOCjn6afbKzE168cU32_PcV0,10836
5056
5053
  policyengine_us/tests/policy/contrib/snap/abolish_snap_deductions.yaml,sha256=5pgcUuafSNIF2dWsBHMebB7YSrRq9svD0SkzJcvy6po,467
5057
5054
  policyengine_us/tests/policy/contrib/snap/abolish_snap_net_income_test.yaml,sha256=8zy1seb0mfTruajlBK01Vl1vajlABDQak0P-lWmwG98,427
5058
5055
  policyengine_us/tests/policy/contrib/snap_ea/mid_year_snap_ea_reform.py,sha256=ABpm6JVBoziFM3hKvil1xLkWOiz60c9UmcTl8rz_40E,410
@@ -8094,7 +8091,7 @@ policyengine_us/variables/household/income/spm_unit/spm_unit_capped_housing_subs
8094
8091
  policyengine_us/variables/household/income/spm_unit/spm_unit_energy_subsidy.py,sha256=4sikpqROToak71R57YEFthjxabRoVo0tK1XVMSMtxQ4,488
8095
8092
  policyengine_us/variables/household/income/spm_unit/spm_unit_energy_subsidy_reported.py,sha256=4FYjIyyXCK1Wsiakq1aFs9mItOGy4rrcTWOH4tbIrHU,271
8096
8093
  policyengine_us/variables/household/income/spm_unit/spm_unit_fips.py,sha256=5QDrBrIraBnRRSXwZfsTO-sIYLwdLORTiNdwBiUOalo,295
8097
- policyengine_us/variables/household/income/spm_unit/spm_unit_income_decile.py,sha256=q2lPNxCvp1fUqIGGtdWpScTTRhGBuOADwLj0zL8semY,593
8094
+ policyengine_us/variables/household/income/spm_unit/spm_unit_income_decile.py,sha256=P7RIRqa1L-Nn-Rt_i0IkWN1NAbtiRmz2g9XUoNTYDDw,584
8098
8095
  policyengine_us/variables/household/income/spm_unit/spm_unit_is_in_deep_spm_poverty.py,sha256=epHelbN5RdzUM3DIVy_ON8Mf8N7Lc_-zxZ7CeJn-pq8,428
8099
8096
  policyengine_us/variables/household/income/spm_unit/spm_unit_is_in_spm_poverty.py,sha256=0fVppPyrvQuu4hBHbl44TfXrEaKyqX5oJqKMZHc9fcY,414
8100
8097
  policyengine_us/variables/household/income/spm_unit/spm_unit_market_income.py,sha256=GpSFUcSEsBYWVBZBR3VmdMgIMMMTHYCizvalPzlF0rk,228
@@ -8122,8 +8119,8 @@ policyengine_us/variables/input/farm_income.py,sha256=BEKxYmHNNnWJAAvULl5qZJigy5
8122
8119
  policyengine_us/variables/input/geography.py,sha256=XmBlgXhzBoLRKk6R8taVZHqUw1eU8MbNeGS9iJ7_l44,4506
8123
8120
  policyengine_us/variables/input/self_employment_income.py,sha256=PwsGz8R4lRikKWUYOhsC0qosNNLXq4f5SQmfw4S3mk8,511
8124
8121
  policyengine_us/variables/input/self_employment_income_before_lsr.py,sha256=E8fcX9Nlyqz8dziHhQv_euutdmoIwFMMWePUwbbwv_w,379
8125
- policyengine_us-1.351.3.dist-info/METADATA,sha256=H83YtzILLEf2FVwXIgv5wrjoIGHRIw1gHsnTMIou1YM,1693
8126
- policyengine_us-1.351.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8127
- policyengine_us-1.351.3.dist-info/entry_points.txt,sha256=MLaqNyNTbReALyKNkde85VkuFFpdPWAcy8VRG1mjczc,57
8128
- policyengine_us-1.351.3.dist-info/licenses/LICENSE,sha256=2N5ReRelkdqkR9a-KP-y-shmcD5P62XoYiG-miLTAzo,34519
8129
- policyengine_us-1.351.3.dist-info/RECORD,,
8122
+ policyengine_us-1.351.5.dist-info/METADATA,sha256=G7kIwoeS_BGXfygItInB6H8iTnl5VtB_6jtHffJJnt4,1693
8123
+ policyengine_us-1.351.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8124
+ policyengine_us-1.351.5.dist-info/entry_points.txt,sha256=MLaqNyNTbReALyKNkde85VkuFFpdPWAcy8VRG1mjczc,57
8125
+ policyengine_us-1.351.5.dist-info/licenses/LICENSE,sha256=2N5ReRelkdqkR9a-KP-y-shmcD5P62XoYiG-miLTAzo,34519
8126
+ policyengine_us-1.351.5.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- from .second_earner_tax_reform import (
2
- create_second_earner_tax_reform,
3
- )
@@ -1,820 +0,0 @@
1
- from policyengine_us.model_api import *
2
-
3
-
4
- def create_second_earner_tax() -> Reform:
5
-
6
- class is_primary_earner(Variable):
7
- value_type = bool
8
- entity = Person
9
- label = "Whether this person is the primary earner in their tax unit"
10
- definition_period = YEAR
11
-
12
- def formula(person, period, parameters):
13
- earned_income = person("earned_income", period)
14
- is_tax_unit_head_or_spouse = person(
15
- "is_tax_unit_head_or_spouse", period
16
- )
17
- is_tax_unit_head = person("is_tax_unit_head", period)
18
- is_tax_unit_dependent = person("is_tax_unit_dependent", period)
19
-
20
- # Add dependent income to head's income
21
- dependent_income = (earned_income * is_tax_unit_dependent).sum()
22
- earner_income = earned_income * is_tax_unit_head_or_spouse
23
- earner_income = where(
24
- is_tax_unit_head,
25
- earner_income + dependent_income,
26
- earner_income,
27
- )
28
-
29
- max_income = person.tax_unit.max(earner_income)
30
- return (earner_income == max_income) & (
31
- (
32
- earner_income
33
- > person.tax_unit.max(
34
- where(~is_tax_unit_head, earner_income, 0)
35
- )
36
- )
37
- | is_tax_unit_head
38
- )
39
-
40
- class taxable_income_person(Variable):
41
- value_type = float
42
- entity = Person
43
- label = "IRS taxable income for each person"
44
- unit = USD
45
- definition_period = YEAR
46
-
47
- def formula(person, period, parameters):
48
- agi = person("adjusted_gross_income_person", period)
49
- exemption_amount = person.tax_unit("exemptions", period)
50
- is_joint = person.tax_unit("tax_unit_is_joint", period)
51
- exemptions = where(
52
- is_joint, exemption_amount / 2, exemption_amount
53
- )
54
- deductions = person("taxable_income_deductions_person", period)
55
- return max_(0, agi - exemptions - deductions)
56
-
57
- class income_tax_main_rates(Variable):
58
- value_type = float
59
- entity = TaxUnit
60
- definition_period = YEAR
61
- label = "Income tax main rates"
62
- reference = "https://www.law.cornell.edu/uscode/text/26/1"
63
- unit = USD
64
-
65
- def formula(tax_unit, period, parameters):
66
- person = tax_unit.members
67
- full_taxable_income = person("taxable_income_person", period)
68
- is_tax_unit_head_or_spouse = person(
69
- "is_tax_unit_head_or_spouse", period
70
- )
71
- cg_exclusion = (
72
- tax_unit("capital_gains_excluded_from_taxable_income", period)
73
- / 2
74
- ) * is_tax_unit_head_or_spouse
75
- taxinc = max_(0, full_taxable_income - cg_exclusion)
76
- p = parameters(period).gov.irs.income
77
- bracket_tops = p.bracket.thresholds
78
- bracket_rates = p.bracket.rates
79
- filing_status = tax_unit("filing_status", period)
80
-
81
- # Determine primary and secondary earner incomes based on income size
82
- is_tax_unit_dependent = person("is_tax_unit_dependent", period)
83
-
84
- # Add dependent income to head's income
85
- dependent_income = (taxinc * is_tax_unit_dependent).sum()
86
- earner_taxinc = taxinc * is_tax_unit_head_or_spouse
87
-
88
- is_primary_earner = person("is_primary_earner", period)
89
- is_secondary_earner = (
90
- is_tax_unit_head_or_spouse & ~is_primary_earner
91
- )
92
-
93
- taxable_income_primary_earner = where(
94
- is_primary_earner, earner_taxinc + dependent_income, 0
95
- ).sum()
96
- taxable_income_secondary_earner = where(
97
- is_secondary_earner, earner_taxinc, 0
98
- ).sum()
99
-
100
- # Calculate primary earner tax using actual filing status
101
- primary_earner_tax = 0
102
- bracket_bottom = 0
103
- for i in range(1, len(list(bracket_rates.__iter__())) + 1):
104
- b = str(i)
105
- bracket_top = bracket_tops[b][filing_status]
106
- primary_earner_tax += bracket_rates[b] * amount_between(
107
- taxable_income_primary_earner, bracket_bottom, bracket_top
108
- )
109
- bracket_bottom = bracket_top
110
-
111
- # Calculate secondary earner tax using single filing status
112
- secondary_earner_tax = 0
113
- bracket_bottom = 0
114
- single_status = "SINGLE"
115
- for i in range(1, len(list(bracket_rates.__iter__())) + 1):
116
- b = str(i)
117
- bracket_top = bracket_tops[b][single_status]
118
- secondary_earner_tax += bracket_rates[b] * amount_between(
119
- taxable_income_secondary_earner,
120
- bracket_bottom,
121
- bracket_top,
122
- )
123
- bracket_bottom = bracket_top
124
-
125
- return primary_earner_tax + secondary_earner_tax
126
-
127
- class basic_standard_deduction_person(Variable):
128
- value_type = float
129
- entity = Person
130
- label = "Basic standard deduction"
131
- definition_period = YEAR
132
- unit = USD
133
- reference = "https://www.law.cornell.edu/uscode/text/26/63#c_2"
134
-
135
- def formula(person, period, parameters):
136
- std = parameters(period).gov.irs.deductions.standard
137
- filing_status = person.tax_unit("filing_status", period)
138
- separate_filer_itemizes = person.tax_unit(
139
- "separate_filer_itemizes", period
140
- )
141
- dependent_elsewhere = person.tax_unit(
142
- "head_is_dependent_elsewhere", period
143
- )
144
- # Determine primary and secondary earners
145
- is_tax_unit_head_or_spouse = person(
146
- "is_tax_unit_head_or_spouse", period
147
- )
148
- is_primary_earner = person("is_primary_earner", period)
149
- is_secondary_earner = (
150
- is_tax_unit_head_or_spouse & ~is_primary_earner
151
- )
152
-
153
- # Calculate primary earner deduction using actual filing status
154
- primary_deduction = std.amount[filing_status]
155
-
156
- # Calculate secondary earner deduction using single filing status
157
- secondary_deduction = std.amount["SINGLE"]
158
- # Combine deductions based on earner status
159
- standard_deduction = where(
160
- is_primary_earner,
161
- primary_deduction,
162
- where(is_secondary_earner, secondary_deduction, 0),
163
- )
164
-
165
- standard_deduction_if_dependent = min_(
166
- standard_deduction,
167
- max_(
168
- std.dependent.additional_earned_income
169
- + person.tax_unit("tax_unit_earned_income", period),
170
- std.dependent.amount,
171
- ),
172
- )
173
-
174
- return select(
175
- [
176
- separate_filer_itemizes,
177
- dependent_elsewhere,
178
- True,
179
- ],
180
- [
181
- 0,
182
- standard_deduction_if_dependent,
183
- standard_deduction,
184
- ],
185
- )
186
-
187
- class additional_standard_deduction_person(Variable):
188
- value_type = float
189
- entity = Person
190
- label = "Additional standard deduction for each person"
191
- unit = USD
192
- definition_period = YEAR
193
- reference = "https://www.law.cornell.edu/uscode/text/26/63#f"
194
-
195
- def formula(person, period, parameters):
196
- std = parameters(period).gov.irs.deductions.standard
197
- filing_status = person.tax_unit("filing_status", period)
198
- is_blind = person("is_blind", period).astype(int)
199
- age_threshold = parameters(
200
- period
201
- ).gov.irs.deductions.standard.aged_or_blind.age_threshold
202
- is_aged = (person("age", period) >= age_threshold).astype(int)
203
- aged_blind = is_blind + is_aged
204
- primary_earner = person("is_primary_earner", period)
205
- amount = where(
206
- primary_earner,
207
- std.aged_or_blind.amount[filing_status],
208
- std.aged_or_blind.amount["SINGLE"],
209
- )
210
- return aged_blind * amount
211
-
212
- class bonus_guaranteed_deduction_person(Variable):
213
- value_type = float
214
- entity = Person
215
- label = "Bonus guaranteed deduction"
216
- unit = USD
217
- definition_period = YEAR
218
- reference = "https://waysandmeans.house.gov/malliotakis-steel-lead-legislation-to-provide-tax-relief-to-working-families/"
219
-
220
- def formula(person, period, parameters):
221
- filing_status = person.tax_unit("filing_status", period)
222
- wftca = parameters(
223
- period
224
- ).gov.contrib.congress.wftca.bonus_guaranteed_deduction
225
- primary_earner = person("is_primary_earner", period)
226
- amount = where(
227
- primary_earner,
228
- wftca.amount[filing_status],
229
- wftca.amount["SINGLE"],
230
- )
231
- agi = person("adjusted_gross_income_person", period)
232
- threshold = where(
233
- primary_earner,
234
- wftca.phase_out.threshold[filing_status],
235
- wftca.phase_out.threshold["SINGLE"],
236
- )
237
- income_in_phase_out_region = max_(agi - threshold, 0)
238
- reduction = wftca.phase_out.rate * income_in_phase_out_region
239
- return max_(amount - reduction, 0)
240
-
241
- class standard_deduction_person(Variable):
242
- value_type = float
243
- entity = Person
244
- label = "Standard deduction for each person"
245
- unit = USD
246
- definition_period = YEAR
247
- reference = "https://www.law.cornell.edu/uscode/text/26/63#c"
248
-
249
- def formula(person, period, parameters):
250
- basic_deduction = person("basic_standard_deduction_person", period)
251
- additional_deduction = person(
252
- "additional_standard_deduction_person", period
253
- )
254
- bonus_deduction = person(
255
- "bonus_guaranteed_deduction_person", period
256
- )
257
- return basic_deduction + additional_deduction + bonus_deduction
258
-
259
- class taxable_income_deductions_person(Variable):
260
- value_type = float
261
- entity = Person
262
- label = "Taxable income deductions for each person"
263
- unit = USD
264
- definition_period = YEAR
265
-
266
- def formula(person, period, parameters):
267
- itemizes = person.tax_unit("tax_unit_itemizes", period)
268
- is_joint = person.tax_unit("tax_unit_is_joint", period)
269
- deductions_if_itemizing_amount = person.tax_unit(
270
- "taxable_income_deductions_if_itemizing", period
271
- )
272
- deductions_if_itemizing = where(
273
- is_joint,
274
- deductions_if_itemizing_amount / 2,
275
- deductions_if_itemizing_amount,
276
- )
277
- standard_deduction = person("standard_deduction_person", period)
278
- qbid = person("qualified_business_income_deduction_person", period)
279
- return where(
280
- itemizes, deductions_if_itemizing, standard_deduction + qbid
281
- )
282
-
283
- class net_capital_gain_person(Variable):
284
- value_type = float
285
- entity = Person
286
- label = "Net capital gain"
287
- unit = USD
288
- documentation = (
289
- "The excess of net long-term capital gain over net short-term capital"
290
- 'loss, plus qualified dividends (the definition of "net capital gain"'
291
- "which applies to 26 U.S.C. § 1(h) from § 1(h)(11))."
292
- )
293
- definition_period = YEAR
294
- reference = dict(
295
- title="26 U.S. Code § 1222(11)",
296
- href="https://www.law.cornell.edu/uscode/text/26/1222#11",
297
- )
298
-
299
- def formula(person, period, parameters):
300
- lt_capital_gain = person("long_term_capital_gains", period)
301
- st_capital_loss = -person("short_term_capital_gains", period)
302
- net_cap_gain = max_(0, lt_capital_gain - st_capital_loss)
303
- qual_div_income = person("qualified_dividend_income", period)
304
- return net_cap_gain + qual_div_income
305
-
306
- class adjusted_net_capital_gain_person(Variable):
307
- value_type = float
308
- entity = Person
309
- label = "Adjusted net capital gain"
310
- unit = USD
311
- documentation = "The excess of net long-term capital gain over net short-term capital loss."
312
- definition_period = YEAR
313
- reference = dict(
314
- title="26 U.S. Code § 1(h)(3)",
315
- href="https://www.law.cornell.edu/uscode/text/26/1#h_3",
316
- )
317
- defined_for = "is_tax_unit_head_or_spouse"
318
-
319
- def formula(person, period, parameters):
320
- net_capital_gain = person("net_capital_gain_person", period)
321
- # The law actually uses the original definition of 'net capital gain' which does not include
322
- # qualified dividend income, but separately adds qualified dividends here. The definition of
323
- # 'net capital gain' in the variable 'net_capital_gain' actually has some very specific exclusion
324
- # criteria for particular types of dividends and companies, so it's not an *exact* fit to the
325
- # definition here, but it's a good enough approximation. See 26 U.S. Code § 1(h)(11)(B) for the
326
- # definition of 'net capital gain' for the above variable, and 26 U.S. Code § 1(h)(3) for the definition
327
- # of adjusted net capital gain (this variable).
328
- qualified_dividend_income = person(
329
- "qualified_dividend_income", period
330
- )
331
- is_joint = person.tax_unit("tax_unit_is_joint", period)
332
- divisor = where(is_joint, 2, 1)
333
- unrecaptured_s_1250_gain = (
334
- person.tax_unit("unrecaptured_section_1250_gain", period)
335
- / divisor
336
- )
337
- cg_28_pct_rate_gain = (
338
- person.tax_unit("capital_gains_28_percent_rate_gain", period)
339
- / divisor
340
- )
341
- net_gains_less_dividends = max_(
342
- 0,
343
- net_capital_gain - qualified_dividend_income,
344
- )
345
- reduced_capital_gains = max_(
346
- net_gains_less_dividends
347
- - (unrecaptured_s_1250_gain + cg_28_pct_rate_gain),
348
- 0,
349
- )
350
- return reduced_capital_gains + qualified_dividend_income
351
-
352
- class capital_gains_tax(Variable):
353
- value_type = float
354
- entity = TaxUnit
355
- label = "Maximum income tax after capital gains tax"
356
- unit = USD
357
- definition_period = YEAR
358
-
359
- def formula(tax_unit, period, parameters):
360
- person = tax_unit.members
361
- net_cg = person("net_capital_gain_person", period)
362
- taxable_income = person("taxable_income_person", period)
363
- adjusted_net_cg = min_(
364
- person("adjusted_net_capital_gain_person", period),
365
- taxable_income,
366
- ) # ANCG is referred to in all cases as ANCG or taxable income if less.
367
-
368
- cg = parameters(period).gov.irs.capital_gains
369
-
370
- excluded_cg = tax_unit(
371
- "capital_gains_excluded_from_taxable_income", period
372
- )
373
- non_cg_taxable_income = max_(0, taxable_income - excluded_cg)
374
-
375
- filing_status = tax_unit("filing_status", period)
376
- is_tax_unit_head_or_spouse = person(
377
- "is_tax_unit_head_or_spouse", period
378
- )
379
- is_primary_earner = person("is_primary_earner", period)
380
- is_secondary_earner = (
381
- is_tax_unit_head_or_spouse & ~is_primary_earner
382
- )
383
- is_tax_unit_dependent = person("is_tax_unit_dependent", period)
384
- # Split capital gains between primary and secondary earners
385
- primary_cg = where(is_primary_earner, adjusted_net_cg, 0)
386
- secondary_cg = where(is_secondary_earner, adjusted_net_cg, 0)
387
- dependent_cg = where(
388
- is_tax_unit_dependent, adjusted_net_cg, 0
389
- ).sum()
390
- primary_cg += dependent_cg # Add dependent gains to primary earner
391
-
392
- # Calculate primary earner capital gains tax (using filing status thresholds)
393
- first_threshold_primary = cg.brackets.thresholds["1"][
394
- filing_status
395
- ]
396
- second_threshold_primary = cg.brackets.thresholds["2"][
397
- filing_status
398
- ]
399
-
400
- # Calculate secondary earner capital gains tax (using single thresholds)
401
- first_threshold_secondary = cg.brackets.thresholds["1"]["SINGLE"]
402
- second_threshold_secondary = cg.brackets.thresholds["2"]["SINGLE"]
403
-
404
- # Calculate brackets for primary earner
405
- primary_cg_in_first = clip(primary_cg, 0, first_threshold_primary)
406
- primary_cg_in_second = clip(
407
- primary_cg - first_threshold_primary,
408
- 0,
409
- second_threshold_primary - first_threshold_primary,
410
- )
411
- primary_cg_in_third = max_(
412
- 0, primary_cg - second_threshold_primary
413
- )
414
-
415
- # Calculate brackets for secondary earner
416
- secondary_cg_in_first = clip(
417
- secondary_cg, 0, first_threshold_secondary
418
- )
419
- secondary_cg_in_second = clip(
420
- secondary_cg - first_threshold_secondary,
421
- 0,
422
- second_threshold_secondary - first_threshold_secondary,
423
- )
424
- secondary_cg_in_third = max_(
425
- 0, secondary_cg - second_threshold_secondary
426
- )
427
-
428
- # Calculate total capital gains tax
429
- main_cg_tax = (
430
- (primary_cg_in_first + secondary_cg_in_first)
431
- * cg.brackets.rates["1"]
432
- + (primary_cg_in_second + secondary_cg_in_second)
433
- * cg.brackets.rates["2"]
434
- + (primary_cg_in_third + secondary_cg_in_third)
435
- * cg.brackets.rates["3"]
436
- )
437
- is_joint = tax_unit("tax_unit_is_joint", period)
438
- divisor = where(is_joint, 2, 1)
439
- unrecaptured_s_1250_gain = (
440
- tax_unit("unrecaptured_section_1250_gain", period) / divisor
441
- )
442
- qualified_dividends = (
443
- add(tax_unit, period, ["qualified_dividend_income"]) / divisor
444
- )
445
- max_taxable_unrecaptured_gain = min_(
446
- unrecaptured_s_1250_gain,
447
- max_(0, net_cg - qualified_dividends),
448
- )
449
- unrecaptured_gain_deduction = max_(
450
- non_cg_taxable_income + net_cg - taxable_income,
451
- 0,
452
- )
453
- taxable_unrecaptured_gain = max_(
454
- max_taxable_unrecaptured_gain - unrecaptured_gain_deduction,
455
- 0,
456
- )
457
-
458
- unrecaptured_gain_tax = (
459
- cg.unrecaptured_s_1250_rate * taxable_unrecaptured_gain
460
- )
461
-
462
- remaining_cg_tax = (
463
- tax_unit("capital_gains_28_percent_rate_gain", period)
464
- * cg.other_cg_rate
465
- ) / divisor
466
- return tax_unit.sum(
467
- main_cg_tax + unrecaptured_gain_tax + remaining_cg_tax
468
- )
469
-
470
- class amt_excluded_deductions_person(Variable):
471
- value_type = float
472
- entity = Person
473
- definition_period = YEAR
474
- label = "AMT taxable income excluded deductions"
475
- unit = USD
476
- reference = "https://www.law.cornell.edu/uscode/text/26/55#b_2"
477
-
478
- def formula(person, period, parameters):
479
- itemizing = person.tax_unit("tax_unit_itemizes", period)
480
- standard_deduction = person("standard_deduction_person", period)
481
- is_joint = person.tax_unit("tax_unit_is_joint", period)
482
- divisor = where(is_joint, 2, 1)
483
- salt_deduction = (
484
- person.tax_unit("salt_deduction", period) / divisor
485
- )
486
- return where(itemizing, salt_deduction, standard_deduction)
487
-
488
- class amt_income_person(Variable):
489
- value_type = float
490
- entity = Person
491
- definition_period = YEAR
492
- label = "AMT taxable income"
493
- unit = USD
494
- reference = "https://www.law.cornell.edu/uscode/text/26/55#b_2"
495
- defined_for = "is_tax_unit_head_or_spouse"
496
-
497
- def formula(person, period, parameters):
498
- taxable_income = person("taxable_income_person", period)
499
- deductions = person("amt_excluded_deductions_person", period)
500
- is_joint = person.tax_unit("tax_unit_is_joint", period)
501
- divisor = where(is_joint, 2, 1)
502
- separate_addition = (
503
- person.tax_unit("amt_separate_addition", period) / divisor
504
- )
505
- return taxable_income + deductions + separate_addition
506
-
507
- class alternative_minimum_tax(Variable):
508
- value_type = float
509
- entity = TaxUnit
510
- definition_period = YEAR
511
- label = "Alternative Minimum Tax"
512
- unit = USD
513
- documentation = "Alternative Minimum Tax (AMT) liability"
514
-
515
- def formula(tax_unit, period, parameters):
516
- person = tax_unit.members
517
- amt_income = person("amt_income_person", period)
518
- # Form 6251, Part II top
519
- p = parameters(period).gov.irs.income.amt
520
- phase_out = p.exemption.phase_out
521
- filing_status = tax_unit("filing_status", period)
522
-
523
- # Split calculations for primary and secondary earners
524
- is_primary_earner = person("is_primary_earner", period)
525
- is_secondary_earner = (
526
- person("is_tax_unit_head_or_spouse", period)
527
- & ~is_primary_earner
528
- )
529
- is_tax_unit_dependent = person("is_tax_unit_dependent", period)
530
-
531
- # Primary earner uses filing status thresholds
532
- primary_base_exemption = p.exemption.amount[filing_status]
533
- primary_phase_out_start = phase_out.start[filing_status]
534
-
535
- # Secondary earner uses single thresholds
536
- secondary_base_exemption = p.exemption.amount["SINGLE"]
537
- secondary_phase_out_start = phase_out.start["SINGLE"]
538
-
539
- # Calculate income for each earner
540
- primary_income = where(is_primary_earner, amt_income, 0)
541
- secondary_income = where(is_secondary_earner, amt_income, 0)
542
- dependent_income = where(
543
- is_tax_unit_dependent, amt_income, 0
544
- ).sum()
545
- primary_income += (
546
- dependent_income # Add dependent income to primary
547
- )
548
-
549
- # Calculate exemption amounts
550
- primary_excess = max_(0, primary_income - primary_phase_out_start)
551
- secondary_excess = max_(
552
- 0, secondary_income - secondary_phase_out_start
553
- )
554
-
555
- primary_exemption = max_(
556
- 0, primary_base_exemption - phase_out.rate * primary_excess
557
- )
558
- secondary_exemption = max_(
559
- 0, secondary_base_exemption - phase_out.rate * secondary_excess
560
- )
561
-
562
- age_head = tax_unit("age_head", period)
563
- child = parameters(period).gov.irs.dependent.ineligible_age
564
- young_head = (age_head != 0) & (age_head < child.non_student)
565
- no_or_young_spouse = (
566
- tax_unit("age_spouse", period) < child.non_student
567
- )
568
- adj_earnings = person("adjusted_earnings", period)
569
- child_amount = p.exemption.child.amount
570
-
571
- kiddie_tax_exemption_cap_applies = young_head & no_or_young_spouse
572
- exemption_cap = where(
573
- kiddie_tax_exemption_cap_applies,
574
- adj_earnings + child_amount,
575
- np.inf,
576
- )
577
- primary_exemption = min_(primary_exemption, exemption_cap)
578
- secondary_exemption = min_(secondary_exemption, exemption_cap)
579
-
580
- # Calculate taxable income
581
- taxable_income = person("taxable_income_person", period)
582
- # Do not add back deduction for filers subject to the kiddie tax
583
- primary_applied_income = where(
584
- kiddie_tax_exemption_cap_applies,
585
- where(is_primary_earner, taxable_income, 0),
586
- primary_income,
587
- )
588
- secondary_applied_income = where(
589
- kiddie_tax_exemption_cap_applies,
590
- where(is_secondary_earner, taxable_income, 0),
591
- secondary_income,
592
- )
593
-
594
- primary_reduced_income = max_(
595
- 0, primary_applied_income - primary_exemption
596
- )
597
- secondary_reduced_income = max_(
598
- 0, secondary_applied_income - secondary_exemption
599
- )
600
-
601
- # Calculate bracket fractions
602
- primary_bracket_fraction = where(
603
- filing_status == filing_status.possible_values.SEPARATE,
604
- 0.5,
605
- 1.0,
606
- )
607
- secondary_bracket_fraction = (
608
- 1.0 # Single always uses full brackets
609
- )
610
-
611
- # Calculate tax thresholds
612
- primary_tax_threshold = (
613
- p.brackets.thresholds[-1] * primary_bracket_fraction
614
- )
615
- secondary_tax_threshold = (
616
- p.brackets.thresholds[-1] * secondary_bracket_fraction
617
- )
618
-
619
- lower_rate = p.brackets.rates[0]
620
- higher_rate = p.brackets.rates[1]
621
-
622
- # Calculate tax for primary earner
623
- primary_lower_tax = (
624
- min_(primary_reduced_income, primary_tax_threshold)
625
- * lower_rate
626
- )
627
- primary_higher_tax = (
628
- max_(0, primary_reduced_income - primary_tax_threshold)
629
- * higher_rate
630
- )
631
-
632
- # Calculate tax for secondary earner
633
- secondary_lower_tax = (
634
- min_(secondary_reduced_income, secondary_tax_threshold)
635
- * lower_rate
636
- )
637
- secondary_higher_tax = (
638
- max_(0, secondary_reduced_income - secondary_tax_threshold)
639
- * higher_rate
640
- )
641
-
642
- # Combine taxes
643
- reduced_income_tax = (
644
- primary_lower_tax
645
- + primary_higher_tax
646
- + secondary_lower_tax
647
- + secondary_higher_tax
648
- )
649
-
650
- dwks10, dwks13, dwks14, dwks19, e24515 = [
651
- add(tax_unit, period, [variable])
652
- for variable in [
653
- "dwks10",
654
- "dwks13",
655
- "dwks14",
656
- "dwks19",
657
- "unrecaptured_section_1250_gain",
658
- ]
659
- ]
660
- form_6251_part_iii_required = np.any(
661
- [
662
- variable > 0
663
- for variable in [
664
- dwks10,
665
- dwks13,
666
- dwks14,
667
- dwks19,
668
- e24515,
669
- ]
670
- ]
671
- )
672
-
673
- # Complete Form 6251, Part III
674
- line37 = dwks13
675
- line38 = e24515
676
- line39 = min_(line37 + line38, dwks10)
677
- line40 = min_(
678
- primary_reduced_income + secondary_reduced_income, line39
679
- )
680
- line41 = max_(
681
- 0, primary_reduced_income + secondary_reduced_income - line40
682
- )
683
- line42 = p.brackets.calc(line41)
684
- line44 = dwks14
685
-
686
- # Apply different thresholds for primary/secondary for capital gains
687
- cg = parameters(period).gov.irs.capital_gains.brackets
688
- primary_line45 = max_(
689
- 0, cg.thresholds["1"][filing_status] - line44
690
- )
691
- secondary_line45 = max_(0, cg.thresholds["1"]["SINGLE"] - line44)
692
-
693
- line46 = min_(
694
- primary_reduced_income + secondary_reduced_income, line37
695
- )
696
- primary_line47 = min_(primary_line45, line46)
697
- secondary_line47 = min_(secondary_line45, line46)
698
-
699
- cgtax1 = (
700
- primary_line47 * cg.rates["1"]
701
- + secondary_line47 * cg.rates["1"]
702
- )
703
-
704
- line48 = line46 - (primary_line47 + secondary_line47)
705
- line51 = dwks19
706
-
707
- primary_line52 = primary_line45 + line51
708
- secondary_line52 = secondary_line45 + line51
709
-
710
- primary_line53 = max_(
711
- 0, cg.thresholds["2"][filing_status] - primary_line52
712
- )
713
- secondary_line53 = max_(
714
- 0, cg.thresholds["2"]["SINGLE"] - secondary_line52
715
- )
716
-
717
- primary_line54 = min_(line48, primary_line53)
718
- secondary_line54 = min_(line48, secondary_line53)
719
-
720
- cgtax2 = (
721
- primary_line54 * cg.rates["2"]
722
- + secondary_line54 * cg.rates["2"]
723
- )
724
-
725
- line56 = (
726
- primary_line47
727
- + secondary_line47
728
- + primary_line54
729
- + secondary_line54
730
- )
731
- line57 = where(line41 == line56, 0, line46 - line56)
732
- linex2 = where(
733
- line41 == line56,
734
- 0,
735
- max_(0, primary_line54 + secondary_line54 - line48),
736
- )
737
- cgtax3 = line57 * cg.rates["3"]
738
-
739
- line61 = where(
740
- line38 == 0,
741
- 0,
742
- p.capital_gains.capital_gain_excess_tax_rate
743
- * max_(
744
- 0,
745
- (
746
- primary_reduced_income
747
- + secondary_reduced_income
748
- - line41
749
- - line56
750
- - line57
751
- - linex2
752
- ),
753
- ),
754
- )
755
- line62 = line42 + cgtax1 + cgtax2 + cgtax3 + line61
756
- line64 = min_(reduced_income_tax, line62)
757
- line31 = where(
758
- form_6251_part_iii_required, line64, reduced_income_tax
759
- )
760
-
761
- # Form 6251, Part II bottom
762
- is_joint = tax_unit("tax_unit_is_joint", period)
763
- divisor = where(is_joint, 2, 1)
764
- line32 = tax_unit("foreign_tax_credit", period) / divisor
765
- line33 = line31 - line32
766
- regular_tax_before_credits = (
767
- tax_unit("regular_tax_before_credits", period) / divisor
768
- )
769
- lump_sum_distributions = (
770
- tax_unit("form_4972_lumpsum_distributions", period) / divisor
771
- )
772
- capital_gains = tax_unit("capital_gains_tax", period)
773
- tax_before_credits = regular_tax_before_credits + capital_gains
774
-
775
- return tax_unit.sum(
776
- max_(
777
- 0,
778
- line33
779
- - max_(
780
- 0,
781
- (tax_before_credits - line32 - lump_sum_distributions),
782
- ),
783
- )
784
- )
785
-
786
- class reform(Reform):
787
- def apply(self):
788
- self.update_variable(taxable_income_person)
789
- self.update_variable(income_tax_main_rates)
790
- self.update_variable(basic_standard_deduction_person)
791
- self.update_variable(standard_deduction_person)
792
- self.update_variable(taxable_income_deductions_person)
793
- self.update_variable(is_primary_earner)
794
- self.update_variable(capital_gains_tax)
795
- self.update_variable(net_capital_gain_person)
796
- self.update_variable(adjusted_net_capital_gain_person)
797
- self.update_variable(alternative_minimum_tax)
798
- self.update_variable(amt_income_person)
799
- self.update_variable(amt_excluded_deductions_person)
800
- self.update_variable(bonus_guaranteed_deduction_person)
801
- self.update_variable(additional_standard_deduction_person)
802
-
803
- return reform
804
-
805
-
806
- def create_second_earner_tax_reform(parameters, period, bypass: bool = False):
807
- if bypass:
808
- return create_second_earner_tax()
809
-
810
- p = parameters(period).gov.contrib.second_earner_reform
811
-
812
- if p.in_effect:
813
- return create_second_earner_tax()
814
- else:
815
- return None
816
-
817
-
818
- second_earner_tax_reform = create_second_earner_tax_reform(
819
- None, None, bypass=True
820
- )
@@ -1,371 +0,0 @@
1
- - name: Two people, both with income in the first bracket
2
- period: 2023
3
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
4
- input:
5
- gov.contrib.second_earner_reform.in_effect: true
6
- people:
7
- person1:
8
- is_tax_unit_head_or_spouse: true
9
- taxable_income_person: 20_000
10
- person2:
11
- is_tax_unit_head_or_spouse: true
12
- taxable_income_person: 1_000
13
- tax_units:
14
- tax_unit:
15
- members: [person1, person2]
16
- capital_gains_excluded_from_taxable_income: 0
17
- filing_status: JOINT
18
- output:
19
- income_tax_main_rates: 2_100
20
-
21
- - name: Two people, spouse in second single bracket
22
- period: 2023
23
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
24
- input:
25
- gov.contrib.second_earner_reform.in_effect: true
26
- people:
27
- person1:
28
- is_tax_unit_head_or_spouse: true
29
- taxable_income_person: 20_000
30
- person2:
31
- is_tax_unit_head_or_spouse: true
32
- taxable_income_person: 15_000
33
- tax_units:
34
- tax_unit:
35
- members: [person1, person2]
36
- capital_gains_excluded_from_taxable_income: 0
37
- filing_status: JOINT
38
- output:
39
- income_tax_main_rates: 3_580
40
-
41
- - name: Two people, spouse in second single bracket - reform not applied
42
- period: 2023
43
- input:
44
- gov.contrib.second_earner_reform.in_effect: false
45
- people:
46
- person1:
47
- is_tax_unit_head_or_spouse: true
48
- person2:
49
- is_tax_unit_head_or_spouse: true
50
- tax_units:
51
- tax_unit:
52
- members: [person1, person2]
53
- capital_gains_excluded_from_taxable_income: 0
54
- filing_status: JOINT
55
- taxable_income: 45_000
56
- output:
57
- income_tax_main_rates: 4_960
58
-
59
-
60
- - name: Spouse with higher income becomes primary earner
61
- period: 2023
62
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
63
- input:
64
- gov.contrib.second_earner_reform.in_effect: true
65
- people:
66
- person1:
67
- is_tax_unit_head_or_spouse: true
68
- taxable_income_person: 20_000
69
- person2:
70
- is_tax_unit_head_or_spouse: true
71
- taxable_income_person: 40_000
72
- is_primary_earner: true
73
- tax_units:
74
- tax_unit:
75
- members: [person1, person2]
76
- capital_gains_excluded_from_taxable_income: 0
77
- filing_status: JOINT
78
- output:
79
- income_tax_main_rates: 6_540
80
-
81
- - name: One person with one dependent taxes as head of household
82
- period: 2023
83
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
84
- input:
85
- gov.contrib.second_earner_reform.in_effect: true
86
- people:
87
- person1:
88
- taxable_income_person: 40_000
89
- person2:
90
- age: 10
91
- tax_units:
92
- tax_unit:
93
- members: [person1, person2]
94
- capital_gains_excluded_from_taxable_income: 0
95
- output:
96
- income_tax_main_rates: 4_486
97
-
98
- - name: One person alone is taxed as single
99
- period: 2023
100
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
101
- input:
102
- gov.contrib.second_earner_reform.in_effect: true
103
- people:
104
- person1:
105
- taxable_income_person: 15_000
106
- tax_units:
107
- tax_unit:
108
- members: [person1]
109
- capital_gains_excluded_from_taxable_income: 0
110
- output:
111
- income_tax_main_rates: 1_580
112
-
113
- - name: Joint couple with one dependent, cg exclusion included
114
- period: 2023
115
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
116
- input:
117
- gov.contrib.second_earner_reform.in_effect: true
118
- people:
119
- person1:
120
- age: 40
121
- taxable_income_person: 30_000
122
- person2:
123
- age: 40
124
- taxable_income_person: 15_000
125
- person3:
126
- age: 16
127
- taxable_income_person: 1_000
128
- tax_units:
129
- tax_unit:
130
- members: [person1, person2, person3]
131
- capital_gains_excluded_from_taxable_income: 2_000
132
- output:
133
- income_tax_main_rates: 4_620
134
-
135
- - name: Integration, joint household with one depedent, reform not applied
136
- period: 2023
137
- input:
138
- gov.contrib.second_earner_reform.in_effect: false
139
- people:
140
- person1:
141
- age: 40
142
- employment_income: 50_000
143
- person2:
144
- age: 40
145
- employment_income: 40_000
146
- person3:
147
- age: 16
148
- employment_income: 1_000
149
- tax_units:
150
- tax_unit:
151
- members: [person1, person2, person3]
152
- output:
153
- adjusted_gross_income: 90_000
154
- adjusted_gross_income_person: [50_000, 40_000, 0]
155
- exemptions: 0
156
- taxable_income_deductions: 27_700
157
- taxable_income: 62_300
158
- income_tax_main_rates: 7_036
159
-
160
- - name: Integration, joint household with one depedent, reform applied
161
- period: 2023
162
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
163
- input:
164
- gov.contrib.second_earner_reform.in_effect: true
165
- people:
166
- person1:
167
- age: 40
168
- employment_income: 50_000
169
- person2:
170
- age: 40
171
- employment_income: 40_000
172
- person3:
173
- age: 16
174
- employment_income: 1_000
175
- tax_units:
176
- tax_unit:
177
- members: [person1, person2, person3]
178
- output:
179
- adjusted_gross_income: 90_000
180
- adjusted_gross_income_person: [50_000, 40_000, 0]
181
- taxable_income: 62_300
182
- exemptions: 0
183
- taxable_income_deductions: 27_700
184
- taxable_income_deductions_person: [27_700, 13_850, 0]
185
- taxable_income_person: [22_300, 26_150, 0]
186
- income_tax_main_rates: 5_154
187
-
188
-
189
- - name: Two people both without income
190
- period: 2024
191
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
192
- input:
193
- gov.contrib.second_earner_reform.in_effect: true
194
- people:
195
- person1:
196
- age: 40
197
- person2:
198
- age: 40
199
- tax_units:
200
- tax_unit:
201
- members: [person1, person2]
202
- filing_status: JOINT
203
- output:
204
- basic_standard_deduction_person: [29_200, 14_600]
205
-
206
- - name: Taxable income deductions - standard deduction case
207
- period: 2024
208
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
209
- input:
210
- gov.contrib.second_earner_reform.in_effect: true
211
- people:
212
- person1:
213
- age: 40
214
- earned_income: 50_000
215
- person2:
216
- age: 40
217
- earned_income: 30_000
218
- tax_units:
219
- tax_unit:
220
- members: [person1, person2]
221
- filing_status: JOINT
222
- tax_unit_itemizes: false
223
- output:
224
- taxable_income_deductions_person: [29_200, 14_600]
225
-
226
- - name: Taxable income deductions - itemizing case
227
- period: 2024
228
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
229
- input:
230
- gov.contrib.second_earner_reform.in_effect: true
231
- people:
232
- person1:
233
- age: 40
234
- earned_income: 50_000
235
- person2:
236
- age: 40
237
- earned_income: 30_000
238
- tax_units:
239
- tax_unit:
240
- members: [person1, person2]
241
- filing_status: JOINT
242
- tax_unit_itemizes: true
243
- taxable_income_deductions_if_itemizing: 40_000
244
- output:
245
- taxable_income_deductions_person: [20_000, 20_000]
246
-
247
- - name: Integration test - joint household with one dependent
248
- period: 2024
249
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
250
- input:
251
- gov.contrib.second_earner_reform.in_effect: true
252
- people:
253
- person1: # Head
254
- age: 40
255
- employment_income: 50_000
256
- person2: # Spouse
257
- age: 40
258
- employment_income: 30_000
259
- person3: # Dependent
260
- age: 16
261
- employment_income: 1_000
262
- tax_units:
263
- tax_unit:
264
- members: [person1, person2, person3]
265
- filing_status: JOINT
266
- output:
267
- # Income variables
268
- adjusted_gross_income: 80_000
269
- adjusted_gross_income_person: [50_000, 30_000, 0]
270
- taxable_income: 50_800 # AGI minus standard deduction
271
- taxable_income_person: [20_800, 15_400, 0] # Individual taxable incomes
272
- # Deduction variables
273
- basic_standard_deduction: 29_200
274
- basic_standard_deduction_person: [29_200, 14_600, 0] # Head gets joint, spouse gets single
275
- taxable_income_deductions: 29_200
276
- taxable_income_deductions_person: [29_200, 14_600, 0]
277
- # Tax variables
278
- income_tax_main_rates: 3_696
279
-
280
- - name: Capital gains tax test, two people with CG taxes
281
- period: 2024
282
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
283
- input:
284
- gov.contrib.second_earner_reform.in_effect: true
285
- people:
286
- person1:
287
- age: 40
288
- adjusted_net_capital_gain_person: 150_000
289
- taxable_income_person: 150_000
290
- is_tax_unit_head_or_spouse: true
291
- qualified_dividend_income: 11_000
292
- person2:
293
- age: 40
294
- is_tax_unit_head_or_spouse: true
295
- adjusted_net_capital_gain_person: 100_000
296
- taxable_income_person: 100_000
297
- tax_units:
298
- tax_unit:
299
- members: [person1, person2]
300
- filing_status: JOINT
301
- output:
302
- capital_gains_tax: 16_338.75
303
-
304
- - name: AMT test
305
- period: 2024
306
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
307
- input:
308
- gov.contrib.second_earner_reform.in_effect: true
309
- people:
310
- person1:
311
- age: 40
312
- amt_income_person: 150_000
313
- is_primary_earner: true
314
- person2:
315
- age: 40
316
- amt_income_person: 100_000
317
- tax_units:
318
- tax_unit:
319
- members: [person1, person2]
320
- filing_status: JOINT
321
- output:
322
- alternative_minimum_tax: 8_060
323
-
324
-
325
- - name: Counterfactual integration test - single household with one dependent - reform not applied
326
- period: 2024
327
- input:
328
- gov.contrib.second_earner_reform.in_effect: false
329
- people:
330
- person1:
331
- age: 40
332
- employment_income: 150_000
333
- person2:
334
- age: 10
335
- tax_units:
336
- tax_unit:
337
- members: [person1, person2]
338
- output:
339
- # Income variables
340
- adjusted_gross_income: 150_000
341
- taxable_income: 128_100
342
- # Deduction variables
343
- basic_standard_deduction: 21_900
344
- taxable_income_deductions: 21_900
345
- # Tax variables
346
- income_tax_main_rates: 22_093
347
-
348
-
349
- - name: Integration test - single household with one dependent - nothing should change
350
- period: 2024
351
- reforms: policyengine_us.reforms.second_earner.second_earner_tax_reform.second_earner_tax_reform
352
- input:
353
- gov.contrib.second_earner_reform.in_effect: true
354
- people:
355
- person1:
356
- age: 40
357
- employment_income: 150_000
358
- person2:
359
- age: 10
360
- tax_units:
361
- tax_unit:
362
- members: [person1, person2]
363
- output:
364
- # Income variables
365
- adjusted_gross_income: 150_000
366
- taxable_income: 128_100
367
- # Deduction variables
368
- basic_standard_deduction: 21_900
369
- taxable_income_deductions: 21_900
370
- # Tax variables
371
- income_tax_main_rates: 22_093