taxcalc 4.2.1__py3-none-any.whl → 4.3.0__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.
Files changed (123) hide show
  1. taxcalc/__init__.py +1 -1
  2. taxcalc/assumptions/ASSUMPTIONS.md +53 -0
  3. taxcalc/assumptions/README.md +17 -0
  4. taxcalc/assumptions/economic_assumptions_template.json +77 -0
  5. taxcalc/calcfunctions.py +7 -4
  6. taxcalc/data.py +10 -5
  7. taxcalc/policy.py +1 -1
  8. taxcalc/policy_current_law.json +4649 -288
  9. taxcalc/records.py +20 -15
  10. taxcalc/reforms/2017_law.json +125 -0
  11. taxcalc/reforms/2017_law.out.csv +10 -0
  12. taxcalc/reforms/ARPA.json +78 -0
  13. taxcalc/reforms/ARPA.out.csv +10 -0
  14. taxcalc/reforms/BrownKhanna.json +23 -0
  15. taxcalc/reforms/BrownKhanna.out.csv +10 -0
  16. taxcalc/reforms/CARES.json +40 -0
  17. taxcalc/reforms/CARES.out.csv +10 -0
  18. taxcalc/reforms/ConsolidatedAppropriationsAct2021.json +15 -0
  19. taxcalc/reforms/ConsolidatedAppropriationsAct2021.out.csv +10 -0
  20. taxcalc/reforms/Larson2019.json +36 -0
  21. taxcalc/reforms/Larson2019.out.csv +10 -0
  22. taxcalc/reforms/README.md +22 -0
  23. taxcalc/reforms/REFORMS.md +92 -0
  24. taxcalc/reforms/Renacci.json +61 -0
  25. taxcalc/reforms/Renacci.out.csv +10 -0
  26. taxcalc/reforms/SandersDeFazio.json +15 -0
  27. taxcalc/reforms/SandersDeFazio.out.csv +10 -0
  28. taxcalc/reforms/TCJA.json +160 -0
  29. taxcalc/reforms/TCJA.md +48 -0
  30. taxcalc/reforms/TCJA.out.csv +10 -0
  31. taxcalc/reforms/Trump2016.json +71 -0
  32. taxcalc/reforms/Trump2016.out.csv +10 -0
  33. taxcalc/reforms/Trump2017.json +51 -0
  34. taxcalc/reforms/Trump2017.out.csv +10 -0
  35. taxcalc/reforms/archive/Clinton2016.json +56 -0
  36. taxcalc/reforms/archive/RyanBrady.json +104 -0
  37. taxcalc/reforms/archive/TCJA_House.json +144 -0
  38. taxcalc/reforms/archive/TCJA_House_Amended.json +152 -0
  39. taxcalc/reforms/archive/TCJA_Reconciliation.json +187 -0
  40. taxcalc/reforms/archive/TCJA_Senate.json +116 -0
  41. taxcalc/reforms/archive/TCJA_Senate_111417.json +169 -0
  42. taxcalc/reforms/archive/TCJA_Senate_120117.json +174 -0
  43. taxcalc/reforms/cases.csv +10 -0
  44. taxcalc/reforms/clp.out.csv +10 -0
  45. taxcalc/reforms/ext.json +59 -0
  46. taxcalc/reforms/growfactors_ext.csv +65 -0
  47. taxcalc/reforms/ptaxes0.json +37 -0
  48. taxcalc/reforms/ptaxes0.out.csv +10 -0
  49. taxcalc/reforms/ptaxes1.json +21 -0
  50. taxcalc/reforms/ptaxes1.out.csv +10 -0
  51. taxcalc/reforms/ptaxes2.json +18 -0
  52. taxcalc/reforms/ptaxes2.out.csv +10 -0
  53. taxcalc/reforms/ptaxes3.json +28 -0
  54. taxcalc/reforms/ptaxes3.out.csv +10 -0
  55. taxcalc/taxcalcio.py +44 -22
  56. taxcalc/tests/benefits_expect.csv +169 -0
  57. taxcalc/tests/cmpi_cps_expect.txt +132 -0
  58. taxcalc/tests/cmpi_puf_expect.txt +132 -0
  59. taxcalc/tests/conftest.py +143 -0
  60. taxcalc/tests/cpscsv_agg_expect.csv +26 -0
  61. taxcalc/tests/puf_var_correl_coeffs_2016.csv +80 -0
  62. taxcalc/tests/puf_var_wght_means_by_year.csv +80 -0
  63. taxcalc/tests/pufcsv_agg_expect.csv +26 -0
  64. taxcalc/tests/pufcsv_mtr_expect.txt +63 -0
  65. taxcalc/tests/reforms.json +649 -0
  66. taxcalc/tests/reforms_expect.csv +65 -0
  67. taxcalc/tests/test_4package.py +67 -0
  68. taxcalc/tests/test_benefits.py +86 -0
  69. taxcalc/tests/test_calcfunctions.py +871 -0
  70. taxcalc/tests/test_calculator.py +1021 -0
  71. taxcalc/tests/test_compare.py +336 -0
  72. taxcalc/tests/test_compatible_data.py +338 -0
  73. taxcalc/tests/test_consumption.py +144 -0
  74. taxcalc/tests/test_cpscsv.py +163 -0
  75. taxcalc/tests/test_data.py +133 -0
  76. taxcalc/tests/test_decorators.py +332 -0
  77. taxcalc/tests/test_growdiff.py +102 -0
  78. taxcalc/tests/test_growfactors.py +94 -0
  79. taxcalc/tests/test_parameters.py +617 -0
  80. taxcalc/tests/test_policy.py +1557 -0
  81. taxcalc/tests/test_puf_var_stats.py +194 -0
  82. taxcalc/tests/test_pufcsv.py +385 -0
  83. taxcalc/tests/test_records.py +234 -0
  84. taxcalc/tests/test_reforms.py +386 -0
  85. taxcalc/tests/test_responses.py +41 -0
  86. taxcalc/tests/test_taxcalcio.py +755 -0
  87. taxcalc/tests/test_utils.py +792 -0
  88. taxcalc/validation/CSV_INPUT_VARS.md +29 -0
  89. taxcalc/validation/CSV_OUTPUT_VARS.md +63 -0
  90. taxcalc/validation/README.md +68 -0
  91. taxcalc/validation/taxsim35/Differences_Explained.md +54 -0
  92. taxcalc/validation/taxsim35/README.md +139 -0
  93. taxcalc/validation/taxsim35/expected_differences/a17-taxdiffs-expect.csv +25 -0
  94. taxcalc/validation/taxsim35/expected_differences/a18-taxdiffs-expect.csv +25 -0
  95. taxcalc/validation/taxsim35/expected_differences/a19-taxdiffs-expect.csv +25 -0
  96. taxcalc/validation/taxsim35/expected_differences/a20-taxdiffs-expect.csv +25 -0
  97. taxcalc/validation/taxsim35/expected_differences/a21-taxdiffs-expect.csv +25 -0
  98. taxcalc/validation/taxsim35/expected_differences/b17-taxdiffs-expect.csv +25 -0
  99. taxcalc/validation/taxsim35/expected_differences/b18-taxdiffs-expect.csv +25 -0
  100. taxcalc/validation/taxsim35/expected_differences/b19-taxdiffs-expect.csv +25 -0
  101. taxcalc/validation/taxsim35/expected_differences/b20-taxdiffs-expect.csv +25 -0
  102. taxcalc/validation/taxsim35/expected_differences/b21-taxdiffs-expect.csv +25 -0
  103. taxcalc/validation/taxsim35/expected_differences/c17-taxdiffs-expect.csv +25 -0
  104. taxcalc/validation/taxsim35/expected_differences/c18-taxdiffs-expect.csv +25 -0
  105. taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv +25 -0
  106. taxcalc/validation/taxsim35/input_setup.py +67 -0
  107. taxcalc/validation/taxsim35/main_comparison.py +183 -0
  108. taxcalc/validation/taxsim35/prepare_taxcalc_input.py +161 -0
  109. taxcalc/validation/taxsim35/process_taxcalc_output.py +140 -0
  110. taxcalc/validation/taxsim35/taxsim_emulation.json +49 -0
  111. taxcalc/validation/taxsim35/taxsim_input.py +321 -0
  112. taxcalc/validation/taxsim35/tc_sims.py +98 -0
  113. taxcalc/validation/taxsim35/tests_35.py +80 -0
  114. taxcalc/validation/tests_35.sh +13 -0
  115. {taxcalc-4.2.1.dist-info → taxcalc-4.3.0.dist-info}/METADATA +3 -4
  116. taxcalc-4.3.0.dist-info/RECORD +139 -0
  117. {taxcalc-4.2.1.dist-info → taxcalc-4.3.0.dist-info}/WHEEL +1 -1
  118. taxcalc/tmd_growfactors.csv +0 -55
  119. taxcalc/tmd_weights.csv.gz +0 -0
  120. taxcalc-4.2.1.dist-info/RECORD +0 -34
  121. {taxcalc-4.2.1.dist-info → taxcalc-4.3.0.dist-info}/LICENSE +0 -0
  122. {taxcalc-4.2.1.dist-info → taxcalc-4.3.0.dist-info}/entry_points.txt +0 -0
  123. {taxcalc-4.2.1.dist-info → taxcalc-4.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,871 @@
1
+ """
2
+ Tests for Tax-Calculator calcfunctions.py logic.
3
+ """
4
+ # CODING-STYLE CHECKS:
5
+ # pycodestyle test_calcfunctions.py
6
+ # pylint --disable=locally-disabled test_calcfunctions.py
7
+
8
+ import os
9
+ import re
10
+ import ast
11
+ from taxcalc import Records # pylint: disable=import-error
12
+ from taxcalc import calcfunctions
13
+ import numpy as np
14
+ import pytest
15
+
16
+
17
+ class GetFuncDefs(ast.NodeVisitor):
18
+ """
19
+ Return information about each function defined in the functions.py file.
20
+ """
21
+ def __init__(self):
22
+ """
23
+ GetFuncDefs class constructor
24
+ """
25
+ self.fname = ''
26
+ self.fnames = list() # function name (fname) list
27
+ self.fargs = dict() # lists of function arguments indexed by fname
28
+ self.cvars = dict() # lists of calc vars in function indexed by fname
29
+ self.rvars = dict() # lists of function return vars indexed by fname
30
+
31
+ def visit_Module(self, node): # pylint: disable=invalid-name
32
+ """
33
+ visit the specified Module node
34
+ """
35
+ self.generic_visit(node)
36
+ return (self.fnames, self.fargs, self.cvars, self.rvars)
37
+
38
+ def visit_FunctionDef(self, node): # pylint: disable=invalid-name
39
+ """
40
+ visit the specified FunctionDef node
41
+ """
42
+ self.fname = node.name
43
+ self.fnames.append(self.fname)
44
+ self.fargs[self.fname] = list()
45
+ for anode in ast.iter_child_nodes(node.args):
46
+ self.fargs[self.fname].append(anode.arg)
47
+ self.cvars[self.fname] = list()
48
+ for bodynode in node.body:
49
+ if isinstance(bodynode, ast.Return):
50
+ continue # skip function's Return node
51
+ for bnode in ast.walk(bodynode):
52
+ if isinstance(bnode, ast.Name):
53
+ if isinstance(bnode.ctx, ast.Store):
54
+ if bnode.id not in self.cvars[self.fname]:
55
+ self.cvars[self.fname].append(bnode.id)
56
+ self.generic_visit(node)
57
+
58
+ def visit_Return(self, node): # pylint: disable=invalid-name
59
+ """
60
+ visit the specified Return node
61
+ """
62
+ if isinstance(node.value, ast.Tuple):
63
+ self.rvars[self.fname] = [r_v.id for r_v in node.value.elts]
64
+ elif isinstance(node.value, ast.BinOp):
65
+ self.rvars[self.fname] = [] # no vars returned; only an expression
66
+ else:
67
+ self.rvars[self.fname] = [node.value.id]
68
+ self.generic_visit(node)
69
+
70
+
71
+ def test_calc_and_used_vars(tests_path):
72
+ """
73
+ Runs two kinds of tests on variables used in the calcfunctions.py file:
74
+
75
+ (1) Checks that each var in Records.CALCULATED_VARS is actually calculated
76
+
77
+ If test (1) fails, a variable in Records.CALCULATED_VARS was not
78
+ calculated in any function in the calcfunctions.py file. With the
79
+ exception of a few variables listed in this test, all
80
+ Records.CALCULATED_VARS must be calculated in the calcfunctions.py file.
81
+
82
+ (2) Check that each variable that is calculated in a function and
83
+ returned by that function is an argument of that function.
84
+ """
85
+ # pylint: disable=too-many-locals
86
+ funcpath = os.path.join(tests_path, '..', 'calcfunctions.py')
87
+ gfd = GetFuncDefs()
88
+ fnames, fargs, cvars, rvars = gfd.visit(ast.parse(open(funcpath).read()))
89
+ # Test (1):
90
+ # .. create set of vars that are actually calculated in calcfunctions.py
91
+ all_cvars = set()
92
+ for fname in fnames:
93
+ if fname == 'BenefitSurtax':
94
+ continue # because BenefitSurtax is not really a function
95
+ all_cvars.update(set(cvars[fname]))
96
+ # .. add to all_cvars set variables calculated in Records class
97
+ all_cvars.update(set(['num', 'sep', 'exact']))
98
+ # .. add to all_cvars set variables calculated elsewhere
99
+ all_cvars.update(set(['mtr_paytax', 'mtr_inctax']))
100
+ all_cvars.update(set(['benefit_cost_total', 'benefit_value_total']))
101
+ # .. check that each var in Records.CALCULATED_VARS is in the all_cvars set
102
+ records_varinfo = Records(data=None)
103
+ found_error1 = False
104
+ if not records_varinfo.CALCULATED_VARS <= all_cvars:
105
+ msg1 = ('all Records.CALCULATED_VARS not calculated '
106
+ 'in calcfunctions.py\n')
107
+ for var in records_varinfo.CALCULATED_VARS - all_cvars:
108
+ found_error1 = True
109
+ msg1 += 'VAR NOT CALCULATED: {}\n'.format(var)
110
+ # Test (2):
111
+ faux_functions = ['EITCamount', 'ComputeBenefit', 'BenefitPrograms',
112
+ 'BenefitSurtax', 'BenefitLimitation']
113
+ found_error2 = False
114
+ msg2 = 'calculated & returned variables are not function arguments\n'
115
+ for fname in fnames:
116
+ if fname in faux_functions:
117
+ continue # because fname is not a genuine function
118
+ crvars_set = set(cvars[fname]) & set(rvars[fname])
119
+ if not crvars_set <= set(fargs[fname]):
120
+ found_error2 = True
121
+ for var in crvars_set - set(fargs[fname]):
122
+ msg2 += 'FUNCTION,VARIABLE: {} {}\n'.format(fname, var)
123
+ # Report errors for the two tests:
124
+ if found_error1 and found_error2:
125
+ raise ValueError('{}\n{}'.format(msg1, msg2))
126
+ if found_error1:
127
+ raise ValueError(msg1)
128
+ if found_error2:
129
+ raise ValueError(msg2)
130
+
131
+
132
+ def test_function_args_usage(tests_path):
133
+ """
134
+ Checks each function argument in calcfunctions.py for use in its
135
+ function body.
136
+ """
137
+ funcfilename = os.path.join(tests_path, '..', 'calcfunctions.py')
138
+ with open(funcfilename, 'r') as funcfile:
139
+ fcontent = funcfile.read()
140
+ fcontent = re.sub('#.*', '', fcontent) # remove all '#...' comments
141
+ fcontent = re.sub('\n', ' ', fcontent) # replace EOL character with space
142
+ funcs = fcontent.split('def ') # list of function text
143
+ msg = 'FUNCTION ARGUMENT(S) NEVER USED:\n'
144
+ found_error = False
145
+ for func in funcs[1:]: # skip first item in list, which is imports, etc.
146
+ fcode = func.split('return ')[0] # fcode is between def and return
147
+ match = re.search(r'^(.+?)\((.*?)\):(.*)$', fcode)
148
+ if match is None:
149
+ msg = ('Could not find function name, arguments, '
150
+ 'and code portions in the following text:\n')
151
+ msg += '--------------------------------------------------------\n'
152
+ msg += '{}\n'.format(fcode)
153
+ msg += '--------------------------------------------------------\n'
154
+ raise ValueError(msg)
155
+ fname = match.group(1)
156
+ fargs = match.group(2).split(',') # list of function arguments
157
+ fbody = match.group(3)
158
+ if fname == 'Taxes':
159
+ continue # because Taxes has part of fbody in return statement
160
+ for farg in fargs:
161
+ arg = farg.strip()
162
+ if fbody.find(arg) < 0:
163
+ found_error = True
164
+ msg += 'FUNCTION,ARGUMENT= {} {}\n'.format(fname, arg)
165
+ if found_error:
166
+ raise ValueError(msg)
167
+
168
+
169
+ def test_DependentCare(skip_jit):
170
+ """
171
+ Tests the DependentCare function
172
+ """
173
+
174
+ test_tuple = (3, 2, 100000, 1, [250000, 500000, 250000, 500000, 250000],
175
+ .2, 7165, 5000, 0)
176
+ test_value = calcfunctions.DependentCare(*test_tuple)
177
+ expected_value = 25196
178
+
179
+ assert np.allclose(test_value, expected_value)
180
+
181
+
182
+ STD_in = [6000, 12000, 6000, 12000, 12000]
183
+ STD_Aged_in = [1500, 1200, 1500, 1500, 1500]
184
+ Charity_max_in = [300, 600, 300, 300, 300]
185
+ tuple1 = (0, 1000, STD_in, 45, 44, STD_Aged_in, 1000, 2, 0, 0, 0, 2,
186
+ False, 0, 0, 0, Charity_max_in)
187
+ tuple2 = (0, 1000, STD_in, 66, 44, STD_Aged_in, 1000, 2, 0, 1, 1, 2,
188
+ True, 200, 100000, 1, Charity_max_in)
189
+ tuple3 = (0, 1000, STD_in, 44, 66, STD_Aged_in, 1000, 2, 0, 0, 0, 2,
190
+ True, 700, 100000, 1, Charity_max_in)
191
+ tuple4 = (0, 1200, STD_in, 66, 67, STD_Aged_in, 1000, 2, 0, 0, 0, 2,
192
+ True, 0, 100000, 1, Charity_max_in)
193
+ tuple5 = (0, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 1, 0, 0, 0, 2,
194
+ True, 0, 100000, 1, Charity_max_in)
195
+ tuple6 = (0, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 1, 0, 0, 0, 2,
196
+ True, 0, 100000, 1, Charity_max_in)
197
+ tuple7 = (0, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 3, 1, 0, 0, 2,
198
+ True, 0, 100000, 1, Charity_max_in)
199
+ tuple8 = (1, 200, STD_in, 44, 0, STD_Aged_in, 1000, 3, 0, 0, 0, 2,
200
+ True, 0, 100000, 1, Charity_max_in)
201
+ tuple9 = (1, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 3, 0, 0, 0, 2,
202
+ True, 0,100000, 1, Charity_max_in)
203
+ expected = [12000, 15800, 13800, 14400, 6000, 6000, 0, 1000, 1350]
204
+
205
+
206
+ @pytest.mark.stded
207
+ @pytest.mark.parametrize(
208
+ 'test_tuple,expected_value', [
209
+ (tuple1, expected[0]), (tuple2, expected[1]),
210
+ (tuple3, expected[2]), (tuple4, expected[3]),
211
+ (tuple5, expected[4]), (tuple6, expected[5]),
212
+ (tuple7, expected[6]), (tuple8, expected[7]),
213
+ (tuple9, expected[8])], ids=[
214
+ 'Married, young', 'Married, allow charity',
215
+ 'Married, allow charity, over limit',
216
+ 'Married, two old', 'Single 1', 'Single 2', 'Married, Single',
217
+ 'Marrid, Single, dep, under earn',
218
+ 'Married, Single, dep, over earn'])
219
+ def test_StdDed(test_tuple, expected_value, skip_jit):
220
+ """
221
+ Tests the StdDed function
222
+ """
223
+ avalue = calcfunctions.StdDed(*test_tuple)
224
+ assert np.allclose(avalue, expected_value), f"{avalue} != {expected_value}"
225
+
226
+
227
+ tuple1 = (120000, 10000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
228
+ 400, 0, 0, 0, 0, 0, 0, None, None, None, None, None, None,
229
+ None, None, None, None, None)
230
+ tuple2 = (120000, 10000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
231
+ 400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
232
+ None, None, None, None, None, None)
233
+ tuple3 = (120000, 150000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
234
+ 400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
235
+ None, None, None, None, None, None)
236
+ tuple4 = (120000, 500000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 400000,
237
+ 400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
238
+ None, None, None, None, None, None)
239
+ tuple5 = (120000, 10000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
240
+ 400, 300, 0, 0, 0, 0, 0, None, None, None, None, None,
241
+ None, None, None, None, None, None)
242
+ tuple6 = (120000, 10000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
243
+ 400, 0, 0, 0, 0, -40000, 0, None, None, None, None, None,
244
+ None, None, None, None, None, None)
245
+ expected1 = (0, 4065, 4065, 0, 0, 3252, 25000, 10000, 15000, 10100,
246
+ 17000)
247
+ expected2 = (15000, 6146.25, 4065, 2081.25, 1040.625, 4917, 38959.375,
248
+ 21167.5, 17791.875, 21380, 19820)
249
+ expected3 = (15000, 22202.25, 21453, 749.25, 374.625, 16773, 179625.375,
250
+ 161833.5, 17791.875, 161380, 19820)
251
+ expected4 = (15000, 46067.85, 31953, 749.25, 374.625, 30138.6,
252
+ 529625.375, 511833.5, 17791.875, 511380, 19820)
253
+ expected5 = (300, 4065, 4065, 0, 0, 3285.3, 25300, 10279.1875, 15000,
254
+ 10382, 17000)
255
+ expected6 = (-40000, 4065, 4065, 0, 0, 3252, 0, 0, 15000, 10100, 17000)
256
+
257
+ @pytest.mark.parametrize(
258
+ 'test_tuple,expected_value', [
259
+ (tuple1, expected1),
260
+ (tuple2, expected2),
261
+ (tuple3, expected3),
262
+ (tuple4, expected4),
263
+ (tuple5, expected5),
264
+ (tuple6, expected6)], ids=[
265
+ 'case 1', 'case 2', 'case 3', 'case 4', 'case 5', 'case 6'])
266
+ def test_EI_PayrollTax(test_tuple, expected_value, skip_jit):
267
+ """
268
+ Tests the EI_PayrollTax function
269
+ """
270
+ test_value = calcfunctions.EI_PayrollTax(*test_tuple)
271
+ print('Test value = ', test_value)
272
+
273
+ assert np.allclose(test_value, expected_value)
274
+
275
+
276
+ def test_AfterTaxIncome(skip_jit):
277
+ '''
278
+ Tests the AfterTaxIncome function
279
+ '''
280
+ test_tuple = (1000, 5000, 4000)
281
+ test_value = calcfunctions.AfterTaxIncome(*test_tuple)
282
+ expected_value = 4000
283
+ assert np.allclose(test_value, expected_value)
284
+
285
+
286
+ def test_ExpandIncome(skip_jit):
287
+ '''
288
+ Tests the ExpandIncome function
289
+ '''
290
+ test_tuple = (10000, 1000, 500, 100, 200, 300, 400, 20, 500, 50, 250, 10,
291
+ 20, 30, 40, 60, 70, 80, 1500, 2000, 16380)
292
+ test_value = calcfunctions.ExpandIncome(*test_tuple)
293
+ expected_value = 16380
294
+ assert np.allclose(test_value, expected_value)
295
+
296
+
297
+ tuple1 = (1, 1, 2, 0, 0, 1000)
298
+ tuple2 = (0, 1, 2, 0, 0, 1000)
299
+ tuple3 = (1, 1, 2, 100, 0, 1000)
300
+ tuple4 = (0, 2, 1, 100, 200, 1000)
301
+ tuple5 = (0, 1, 3, 100, 300, 1000)
302
+ expected1 = (0, 1000)
303
+ expected2 = (0, 1000)
304
+ expected3 = (0, 1000)
305
+ expected4 = (200, 1200)
306
+ expected5 = (300, 1300)
307
+
308
+
309
+ @pytest.mark.parametrize(
310
+ 'test_tuple,expected_value', [
311
+ (tuple1, expected1), (tuple2, expected2), (tuple3, expected3),
312
+ (tuple4, expected4), (tuple5, expected5)])
313
+ def test_LumpSumTax(test_tuple, expected_value, skip_jit):
314
+ '''
315
+ Tests LumpSumTax function
316
+ '''
317
+ test_value = calcfunctions.LumpSumTax(*test_tuple)
318
+ assert np.allclose(test_value, expected_value)
319
+
320
+
321
+ FST_AGI_thd_lo_in = [1000000, 1000000, 500000, 1000000, 1000000]
322
+ FST_AGI_thd_hi_in = [2000000, 2000000, 1000000, 2000000, 2000000]
323
+ tuple1 = (1100000, 1, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
324
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
325
+ tuple2 = (2100000, 1, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
326
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
327
+ tuple3 = (1100000, 1, 1000, 100, 100, 0, FST_AGI_thd_lo_in,
328
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
329
+ tuple4 = (1100000, 2, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
330
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
331
+ tuple5 = (2100000, 2, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
332
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
333
+ tuple6 = (1100000, 2, 1000, 100, 100, 0, FST_AGI_thd_lo_in,
334
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
335
+ tuple7 = (510000, 3, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
336
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
337
+ tuple8 = (1100000, 3, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
338
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
339
+ tuple9 = (510000, 3, 1000, 100, 100, 0, FST_AGI_thd_lo_in,
340
+ FST_AGI_thd_hi_in, 100, 200, 2000, 300)
341
+ expected1 = (10915, 11115, 12915, 11215)
342
+ expected2 = (209150, 209350, 211150, 209450)
343
+ expected3 = (0, 200, 2000, 300)
344
+ expected4 = (10915, 11115, 12915, 11215)
345
+ expected5 = (209150, 209350, 211150, 209450)
346
+ expected6 = (0, 200, 2000, 300)
347
+ expected7 = (1003, 1203, 3003, 1303)
348
+ expected8 = (109150, 109350, 111150, 109450)
349
+ expected9 = (0, 200, 2000, 300)
350
+
351
+
352
+ @pytest.mark.parametrize(
353
+ 'test_tuple,expected_value', [
354
+ (tuple1, expected1), (tuple2, expected2), (tuple3, expected3),
355
+ (tuple4, expected4), (tuple5, expected5), (tuple6, expected6),
356
+ (tuple7, expected7), (tuple8, expected8), (tuple9, expected9)])
357
+ def test_FairShareTax(test_tuple, expected_value, skip_jit):
358
+ '''
359
+ Tests FairShareTax function
360
+ '''
361
+ test_value = calcfunctions.FairShareTax(*test_tuple)
362
+ assert np.allclose(test_value, expected_value)
363
+
364
+
365
+ II_credit_ARPA = [0, 0, 0, 0, 0]
366
+ II_credit_ps_ARPA = [0, 0, 0, 0, 0]
367
+ II_credit_nr_ARPA = [0, 0, 0, 0, 0]
368
+ II_credit_nr_ps_ARPA = [0, 0, 0, 0, 0]
369
+ RRC_ps_ARPA = [75000, 150000, 75000, 112500, 150000]
370
+ RRC_pe_ARPA = [80000, 160000, 80000, 120000, 160000]
371
+ RRC_c_unit_ARPA = [0, 0, 0, 0, 0]
372
+ II_credit_CARES = [0, 0, 0, 0, 0]
373
+ II_credit_ps_CARES = [0, 0, 0, 0, 0]
374
+ II_credit_nr_CARES = [0, 0, 0, 0, 0]
375
+ II_credit_nr_ps_CARES = [0, 0, 0, 0, 0]
376
+ RRC_ps_CARES = [75000, 150000, 75000, 112500, 75000]
377
+ RRC_pe_CARES = [0, 0, 0, 0, 0]
378
+ RRC_c_unit_CARES = [1200, 2400, 1200, 1200, 1200]
379
+ tuple1 = (1, 50000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
380
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
381
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
382
+ tuple2 = (1, 76000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
383
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
384
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
385
+ tuple3 = (1, 90000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
386
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
387
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
388
+ tuple4 = (2, 50000, 3, 1, II_credit_ARPA, II_credit_ps_ARPA, 0,
389
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
390
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
391
+ tuple5 = (2, 155000, 4, 2, II_credit_ARPA, II_credit_ps_ARPA, 0,
392
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
393
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
394
+ tuple6 = (2, 170000, 4, 2, II_credit_ARPA, II_credit_ps_ARPA, 0,
395
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
396
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
397
+ tuple7 = (4, 50000, 2, 1, II_credit_ARPA, II_credit_ps_ARPA, 0,
398
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
399
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
400
+ tuple8 = (4, 117000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
401
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
402
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
403
+ tuple9 = (4, 130000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
404
+ II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
405
+ RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
406
+ tuple10 = (1, 50000, 1, 0, II_credit_CARES, II_credit_ps_CARES, 0,
407
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
408
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
409
+ tuple11 = (1, 97000, 2, 1, II_credit_CARES, II_credit_ps_CARES, 0,
410
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
411
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
412
+ tuple12 = (1, 150000, 2, 1, II_credit_CARES, II_credit_ps_CARES, 0,
413
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
414
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
415
+ tuple13 = (2, 50000, 4, 2, II_credit_CARES, II_credit_ps_CARES, 0,
416
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
417
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
418
+ tuple14 = (2, 160000, 5, 3, II_credit_CARES, II_credit_ps_CARES, 0,
419
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
420
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
421
+ tuple15 = (2, 300000, 2, 0, II_credit_CARES, II_credit_ps_CARES, 0,
422
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
423
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
424
+ tuple16 = (4, 50000, 3, 2, II_credit_CARES, II_credit_ps_CARES, 0,
425
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
426
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
427
+ tuple17 = (4, 130000, 2, 1, II_credit_CARES, II_credit_ps_CARES, 0,
428
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
429
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
430
+ tuple18 = (4, 170000, 3, 2, II_credit_CARES, II_credit_ps_CARES, 0,
431
+ II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
432
+ RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
433
+ expected1 = (0, 0, 1400)
434
+ expected2 = (0, 0, 1120)
435
+ expected3 = (0, 0, 0)
436
+ expected4 = (0, 0, 4200)
437
+ expected5 = (0, 0, 2800)
438
+ expected6 = (0, 0, 0)
439
+ expected7 = (0, 0, 2800)
440
+ expected8 = (0, 0, 560)
441
+ expected9 = (0, 0, 0)
442
+ expected10 = (0, 0, 1200)
443
+ expected11 = (0, 0, 600)
444
+ expected12 = (0, 0, 0)
445
+ expected13 = (0, 0, 3400)
446
+ expected14 = (0, 0, 3400)
447
+ expected15 = (0, 0, 0)
448
+ expected16 = (0, 0, 2200)
449
+ expected17 = (0, 0, 825)
450
+ expected18 = (0, 0, 0)
451
+
452
+
453
+ @pytest.mark.parametrize(
454
+ 'test_tuple,expected_value', [
455
+ (tuple1, expected1), (tuple2, expected2), (tuple3, expected3),
456
+ (tuple4, expected4), (tuple5, expected5), (tuple6, expected6),
457
+ (tuple7, expected7), (tuple8, expected8), (tuple9, expected9),
458
+ (tuple10, expected10), (tuple11, expected11), (tuple12, expected12),
459
+ (tuple13, expected13), (tuple14, expected14), (tuple15, expected15),
460
+ (tuple16, expected16), (tuple17, expected17), (tuple18, expected18)])
461
+ def test_PersonalTaxCredit(test_tuple, expected_value, skip_jit):
462
+ """
463
+ Tests the PersonalTaxCredit function
464
+ """
465
+ test_value = calcfunctions.PersonalTaxCredit(*test_tuple)
466
+ assert np.allclose(test_value, expected_value)
467
+
468
+
469
+ # MARS = 4
470
+ # Kids = 3+
471
+ basic_frac = 0.0
472
+ phasein_rate = 0.45
473
+ earnings = 19330
474
+ max_amount = 6660
475
+ phaseout_start = 19330
476
+ agi = 19330
477
+ phaseout_rate = 0.2106
478
+ tuple1 = (basic_frac, phasein_rate, earnings, max_amount,
479
+ phaseout_start, agi, phaseout_rate)
480
+ expected1 = 6660
481
+
482
+
483
+ @pytest.mark.parametrize(
484
+ 'test_tuple,expected_value', [
485
+ (tuple1, expected1)])
486
+ def test_EITCamount(test_tuple, expected_value, skip_jit):
487
+ '''
488
+ Tests FairShareTax function
489
+ '''
490
+ test_value = calcfunctions.EITCamount(*test_tuple)
491
+ assert np.allclose(test_value, expected_value)
492
+
493
+
494
+ MARS = 4
495
+ DSI = 0
496
+ EIC = 3
497
+ c00100 = 19330
498
+ e00300 = 0
499
+ e00400 = 0
500
+ e00600 = 0
501
+ c01000 = 0
502
+ e02000 = 0
503
+ e26270 = 0
504
+ age_head = 0
505
+ age_spouse = 0
506
+ earned = 19330
507
+ earned_p = 19330
508
+ earned_s = 0
509
+ EITC_ps = [8790, 19330, 19330, 19330]
510
+ EITC_MinEligAge = 25
511
+ EITC_MaxEligAge = 64
512
+ EITC_ps_MarriedJ = [5890, 5890, 5890, 5890]
513
+ EITC_rt = [0.0765, 0.34, 0.4, 0.45]
514
+ EITC_c = [538, 3584, 5920, 6660]
515
+ EITC_prt = [0.0765, 0.1598, 0.2106, 0.2106]
516
+ EITC_basic_frac = 0.0
517
+ EITC_InvestIncome_c = 3650
518
+ EITC_excess_InvestIncome_rt = 9e+99
519
+ EITC_indiv = False
520
+ EITC_sep_filers_elig = False
521
+ e02300 = 10200
522
+ UI_thd = [150000, 150000, 150000, 150000, 150000]
523
+ UI_em = 10200
524
+ c59660 = 0 # this will be 6660 after the EITC calculation
525
+ tuple1 = (MARS, DSI, EIC, c00100, e00300, e00400, e00600, c01000,
526
+ e02000, e26270, age_head, age_spouse, earned, earned_p, earned_s,
527
+ EITC_ps, EITC_MinEligAge, EITC_MaxEligAge, EITC_ps_MarriedJ,
528
+ EITC_rt, EITC_c, EITC_prt, EITC_basic_frac,
529
+ EITC_InvestIncome_c, EITC_excess_InvestIncome_rt,
530
+ EITC_indiv, EITC_sep_filers_elig, c59660)
531
+ expected1 = 6660
532
+
533
+
534
+ @pytest.mark.parametrize(
535
+ 'test_tuple,expected_value', [
536
+ (tuple1, expected1)])
537
+ def test_EITC(test_tuple, expected_value, skip_jit):
538
+ '''
539
+ Tests FairShareTax function
540
+ '''
541
+ test_value = calcfunctions.EITC(*test_tuple)
542
+ assert np.allclose(test_value, expected_value)
543
+
544
+
545
+ # Parameter values for tests
546
+ PT_qbid_rt = 0.2
547
+ PT_qbid_taxinc_thd = [160700.0, 321400.0, 160725.0, 160700.0, 321400.0]
548
+ PT_qbid_taxinc_gap = [50000.0, 100000.0, 50000.0, 50000.0, 100000.0]
549
+ PT_qbid_w2_wages_rt = 0.5
550
+ PT_qbid_alt_w2_wages_rt = 0.25
551
+ PT_qbid_alt_property_rt = 0.025
552
+ PT_qbid_ps = [9e99, 9e99, 9e99, 9e99, 9e99]
553
+ PT_qbid_prt = 0.0
554
+ PT_qbid_limit_switch = True # will want to test with False also
555
+
556
+ # Input variable values for tests
557
+ c00100 = [527860.66, 337675.10, 603700.00, 90700.00]
558
+ standard = [0.00, 0.00, 24400.00, 0.00]
559
+ c04470 = [37000.00, 49000.00, 0.00, 32000.00]
560
+ c04600 = [0.00, 0.00, 0.00, 0.00]
561
+ MARS = [2, 2, 2, 4]
562
+ e00900 = [352000.00, 23000.00, 0.00, 0.00]
563
+ c03260 = [13516.17, 1624.90, 0.00, 0.00]
564
+ e26270 = [0.00, 0.00, 11000.00, 6000.00]
565
+ e02100 = [0.00, 0.00, 0.00, 0.00]
566
+ e27200 = [0.00, 0.00, 0.00, 0.00]
567
+ e00650 = [5000.00, 8000.00, 3000.00, 9000.00]
568
+ c01000 = [7000.00, 4000.00, -3000.00, -3000.00]
569
+ PT_SSTB_income = [0, 1, 1, 1]
570
+ PT_binc_w2_wages = [0.00, 0.00, 0.00, 0.00]
571
+ PT_ubia_property = [0.00, 0.00, 0.00, 0.00]
572
+ c04800 = [0.0, 0.0, 0.0, 0.0] # unimportant for function
573
+ qbided = [0.0, 0.0, 0.0, 0.0] # unimportant for function
574
+
575
+ tuple0 = (
576
+ c00100[0], standard[0], c04470[0], c04600[0], MARS[0], e00900[0],
577
+ c03260[0], e26270[0],
578
+ e02100[0], e27200[0], e00650[0], c01000[0], PT_SSTB_income[0],
579
+ PT_binc_w2_wages[0], PT_ubia_property[0], PT_qbid_rt,
580
+ PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
581
+ PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[0],
582
+ PT_qbid_ps, PT_qbid_prt, qbided[0], PT_qbid_limit_switch)
583
+ expected0 = (490860.66, 0)
584
+ tuple1 = (
585
+ c00100[1], standard[1], c04470[1], c04600[1], MARS[1], e00900[1],
586
+ c03260[1], e26270[1],
587
+ e02100[1], e27200[1], e00650[1], c01000[1], PT_SSTB_income[1],
588
+ PT_binc_w2_wages[1], PT_ubia_property[1], PT_qbid_rt,
589
+ PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
590
+ PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[1],
591
+ PT_qbid_ps, PT_qbid_prt, qbided[1], PT_qbid_limit_switch)
592
+ expected1 = (284400.08, 4275.02)
593
+ tuple2 = (
594
+ c00100[2], standard[2], c04470[2], c04600[2], MARS[2], e00900[2],
595
+ c03260[2], e26270[2],
596
+ e02100[2], e27200[2], e00650[2], c01000[2], PT_SSTB_income[2],
597
+ PT_binc_w2_wages[2], PT_ubia_property[2], PT_qbid_rt,
598
+ PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
599
+ PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[2],
600
+ PT_qbid_ps, PT_qbid_prt, qbided[2], PT_qbid_limit_switch)
601
+ expected2 = (579300.00, 0)
602
+ tuple3 = (
603
+ c00100[3], standard[3], c04470[3], c04600[3], MARS[3], e00900[3],
604
+ c03260[3], e26270[3],
605
+
606
+ e02100[3], e27200[3], e00650[3], c01000[3], PT_SSTB_income[3],
607
+ PT_binc_w2_wages[3], PT_ubia_property[3], PT_qbid_rt,
608
+ PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
609
+ PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[3],
610
+ PT_qbid_ps, PT_qbid_prt, qbided[3], PT_qbid_limit_switch)
611
+ expected3 = (57500.00, 1200)
612
+
613
+
614
+ @pytest.mark.parametrize(
615
+ 'test_tuple,expected_value', [
616
+ (tuple0, expected0),
617
+ (tuple1, expected1),
618
+ (tuple2, expected2),
619
+ (tuple3, expected3)])
620
+ def test_TaxInc(test_tuple, expected_value, skip_jit):
621
+ """
622
+ Tests the TaxInc function
623
+ """
624
+ test_value = calcfunctions.TaxInc(*test_tuple)
625
+ assert np.allclose(test_value, expected_value)
626
+
627
+
628
+ # parameterization represents 2021 law
629
+ age_head = 45
630
+ age_spouse = 0
631
+ nu18 = 0
632
+ n24 = 0
633
+ MARS = 4
634
+ c00100 = 1000
635
+ XTOT = 3
636
+ num = 1
637
+ c05800 = 0
638
+ e07260 = 0
639
+ CR_ResidentialEnergy_hc = 0.0
640
+ e07300 = 0
641
+ CR_ForeignTax_hc = 0.0
642
+ c07180 = 0
643
+ c07230 = 0
644
+ e07240 = 0
645
+ CR_RetirementSavings_hc = 0.0
646
+ c07200 = 0
647
+ CTC_c = 2000
648
+ CTC_ps = [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]
649
+ CTC_prt = 0.05
650
+ exact = False
651
+ ODC_c = 500
652
+ CTC_c_under6_bonus = 0.0
653
+ nu06 = 0
654
+ CTC_refundable = True
655
+ CTC_include17 = True
656
+ c07220 = 0 # actual value will be returned from function
657
+ odc = 0 # actual value will be returned from function
658
+ codtc_limited = 0 # actual value will be returned from function
659
+ tuple0 = (
660
+ age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
661
+ c05800, e07260, CR_ResidentialEnergy_hc,
662
+ e07300, CR_ForeignTax_hc,
663
+ c07180,
664
+ c07230,
665
+ e07240, CR_RetirementSavings_hc,
666
+ c07200,
667
+ CTC_c, CTC_ps, CTC_prt, exact, ODC_c,
668
+ CTC_c_under6_bonus, nu06,
669
+ CTC_refundable, CTC_include17,
670
+ c07220, odc, codtc_limited)
671
+ # output tuple is : (c07220, odc, codtc_limited)
672
+ expected0 = (0, 1000, 0)
673
+
674
+
675
+ @pytest.mark.parametrize(
676
+ 'test_tuple,expected_value', [
677
+ (tuple0, expected0)])
678
+ def test_ChildDepTaxCredit_2021(test_tuple, expected_value, skip_jit):
679
+ """
680
+ Tests the ChildDepTaxCredit function
681
+ """
682
+ test_value = calcfunctions.ChildDepTaxCredit(*test_tuple)
683
+ assert np.allclose(test_value, expected_value)
684
+
685
+ # parameterization represents 2022 law
686
+ age_head = 45
687
+ age_spouse = 0
688
+ nu18 = 0
689
+ n24 = 0
690
+ MARS = 4
691
+ c00100 = 1000
692
+ XTOT = 3
693
+ num = 1
694
+ c05800 = 0
695
+ e07260 = 0
696
+ CR_ResidentialEnergy_hc = 0.0
697
+ e07300 = 0
698
+ CR_ForeignTax_hc = 0.0
699
+ c07180 = 0
700
+ c07230 = 0
701
+ e07240 = 0
702
+ CR_RetirementSavings_hc = 0.0
703
+ c07200 = 0
704
+ CTC_c = 2000
705
+ CTC_ps = [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]
706
+ CTC_prt = 0.05
707
+ exact = False
708
+ ODC_c = 500
709
+ CTC_c_under6_bonus = 0.0
710
+ nu06 = 0
711
+ CTC_refundable = False
712
+ CTC_include17 = False
713
+ c07220 = 0 # actual value will be returned from function
714
+ odc = 0 # actual value will be returned from function
715
+ codtc_limited = 0 # actual value will be returned from function
716
+ tuple0 = (
717
+ age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
718
+ c05800, e07260, CR_ResidentialEnergy_hc,
719
+ e07300, CR_ForeignTax_hc,
720
+ c07180,
721
+ c07230,
722
+ e07240, CR_RetirementSavings_hc,
723
+ c07200,
724
+ CTC_c, CTC_ps, CTC_prt, exact, ODC_c,
725
+ CTC_c_under6_bonus, nu06,
726
+ CTC_refundable, CTC_include17,
727
+ c07220, odc, codtc_limited)
728
+ # output tuple is : (c07220, odc, codtc_limited)
729
+ expected0 = (0, 0, 1000)
730
+
731
+
732
+ @pytest.mark.parametrize(
733
+ 'test_tuple,expected_value', [
734
+ (tuple0, expected0)])
735
+ def test_ChildDepTaxCredit_2022(test_tuple, expected_value, skip_jit):
736
+ """
737
+ Tests the ChildDepTaxCredit function
738
+ """
739
+ test_value = calcfunctions.ChildDepTaxCredit(*test_tuple)
740
+ assert np.allclose(test_value, expected_value)
741
+
742
+ # parameterization represents 2021 law
743
+ CTC_new_c = 1000
744
+ CTC_new_rt = 0
745
+ CTC_new_c_under6_bonus = 600
746
+ CTC_new_ps = [75000, 150000, 75000, 125000, 150000]
747
+ CTC_new_prt = 0.05
748
+ CTC_new_for_all = True
749
+ CTC_include17 = True
750
+ CTC_new_refund_limited = False
751
+ CTC_new_refund_limit_payroll_rt = 0.0
752
+ CTC_new_refund_limited_all_payroll = False
753
+ payrolltax = 0
754
+ exact = 0
755
+ n24 = 0
756
+ nu06 = 0
757
+ age_head = 45
758
+ age_spouse = 0
759
+ nu18 = 0
760
+ num = 1
761
+ c00100 = 1000
762
+ MARS = 4
763
+ ptax_oasdi = 0
764
+ c09200 = 0
765
+ ctc_new = 0 # actual value will be returned from function
766
+ tuple0 = (
767
+ CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
768
+ CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
769
+ CTC_new_refund_limited, CTC_new_refund_limit_payroll_rt,
770
+ CTC_new_refund_limited_all_payroll, payrolltax, exact,
771
+ n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
772
+ c09200, ctc_new)
773
+ # output tuple is : (ctc_new)
774
+ expected0 = (0)
775
+
776
+ @pytest.mark.parametrize(
777
+ 'test_tuple,expected_value', [
778
+ (tuple0, expected0)])
779
+ def test_CTCnew_2021(test_tuple, expected_value, skip_jit):
780
+ """
781
+ Tests the CTCnew function
782
+ """
783
+ test_value = calcfunctions.CTC_new(*test_tuple)
784
+ assert np.allclose(test_value, expected_value)
785
+
786
+ # parameterization represents 2022 law
787
+ CTC_new_c = 0
788
+ CTC_new_rt = 0
789
+ CTC_new_c_under6_bonus = 0
790
+ CTC_new_ps = [0, 0, 0, 0, 0]
791
+ CTC_new_prt = 0
792
+ CTC_new_for_all = False
793
+ CTC_include17 = False
794
+ CTC_new_refund_limited = False
795
+ CTC_new_refund_limit_payroll_rt = 0.0
796
+ CTC_new_refund_limited_all_payroll = False
797
+ payrolltax = 0
798
+ exact = 0
799
+ n24 = 0
800
+ nu06 = 0
801
+ age_head = 45
802
+ age_spouse = 0
803
+ nu18 = 0
804
+ num = 1
805
+ c00100 = 1000
806
+ MARS = 4
807
+ ptax_oasdi = 0
808
+ c09200 = 0
809
+ ctc_new = 0 # actual value will be returned from function
810
+ tuple0 = (
811
+ CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
812
+ CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
813
+ CTC_new_refund_limited, CTC_new_refund_limit_payroll_rt,
814
+ CTC_new_refund_limited_all_payroll, payrolltax, exact,
815
+ n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
816
+ c09200, ctc_new)
817
+ # output tuple is : (ctc_new)
818
+ expected0 = (0)
819
+
820
+ @pytest.mark.parametrize(
821
+ 'test_tuple,expected_value', [
822
+ (tuple0, expected0)])
823
+ def test_CTCnew_2022(test_tuple, expected_value, skip_jit):
824
+ """
825
+ Tests the CTCnew function
826
+ """
827
+ test_value = calcfunctions.CTC_new(*test_tuple)
828
+ assert np.allclose(test_value, expected_value)
829
+
830
+
831
+
832
+ ymod1 = 19330 + 10200
833
+ c02500 = 0
834
+ c02900 = 0
835
+ XTOT = 0
836
+ MARS = 4
837
+ sep = 1
838
+ DSI = 0
839
+ exact = False
840
+ nu18 = 0
841
+ taxable_ubi = 0
842
+ II_em = 0.0
843
+ II_em_ps = [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]
844
+ II_prt = 0.02
845
+ II_no_em_nu18 = False
846
+ e02300 = 10200
847
+ UI_thd = [150000, 150000, 150000, 150000, 150000]
848
+ UI_em = 10200
849
+ c00100 = 0 # calculated in function
850
+ pre_c04600 = 0 # calculated in functio
851
+ c04600 = 0 # calculated in functio
852
+
853
+ tuple0 = (
854
+ ymod1, c02500, c02900, XTOT, MARS, sep, DSI, exact, nu18, taxable_ubi,
855
+ II_em, II_em_ps, II_prt, II_no_em_nu18,
856
+ e02300, UI_thd, UI_em, c00100, pre_c04600, c04600)
857
+ # returned tuple is (c00100, pre_c04600, c04600)
858
+ expected0 = (19330, 0, 0)
859
+
860
+
861
+ @pytest.mark.parametrize(
862
+ 'test_tuple,expected_value', [
863
+ (tuple0, expected0)])
864
+ def test_AGI(test_tuple, expected_value, skip_jit):
865
+ """
866
+ Tests the TaxInc function
867
+ """
868
+ test_value = calcfunctions.AGI(*test_tuple)
869
+ print('Returned from agi function: ', test_value)
870
+ assert np.allclose(test_value, expected_value)
871
+