taxcalc 5.2.0__py3-none-any.whl → 5.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.
- taxcalc/__init__.py +3 -3
- taxcalc/calcfunctions.py +2 -2
- taxcalc/calculator.py +3 -3
- taxcalc/cli/tc.py +15 -11
- taxcalc/data.py +1 -1
- taxcalc/decorators.py +9 -8
- taxcalc/growfactors.py +2 -1
- taxcalc/policy.py +6 -5
- taxcalc/policy_current_law.json +31 -631
- taxcalc/puf_ratios.csv +24 -24
- taxcalc/puf_weights.csv.gz +0 -0
- taxcalc/reforms/ARPA.out.csv +9 -9
- taxcalc/taxcalcio.py +41 -26
- taxcalc/tests/conftest.py +1 -1
- taxcalc/tests/puf_var_correl_coeffs_2016.csv +24 -24
- taxcalc/tests/puf_var_wght_means_by_year.csv +11 -11
- taxcalc/tests/pufcsv_agg_expect.csv +20 -20
- taxcalc/tests/pufcsv_mtr_expect.txt +21 -21
- taxcalc/tests/reforms.json +3 -1
- taxcalc/tests/reforms_expect.csv +48 -48
- taxcalc/tests/test_4package.py +8 -9
- taxcalc/tests/test_calculator.py +151 -151
- taxcalc/tests/test_compare.py +2 -2
- taxcalc/tests/test_consumption.py +2 -2
- taxcalc/tests/test_cpscsv.py +2 -2
- taxcalc/tests/test_decorators.py +57 -52
- taxcalc/tests/test_growdiff.py +2 -2
- taxcalc/tests/test_parameters.py +59 -53
- taxcalc/tests/test_policy.py +154 -154
- taxcalc/tests/test_puf_var_stats.py +1 -1
- taxcalc/tests/test_pufcsv.py +3 -3
- taxcalc/tests/test_records.py +5 -1
- taxcalc/tests/test_reforms.py +101 -99
- taxcalc/tests/test_taxcalcio.py +10 -4
- taxcalc/utils.py +3 -3
- {taxcalc-5.2.0.dist-info → taxcalc-5.3.0.dist-info}/METADATA +3 -6
- {taxcalc-5.2.0.dist-info → taxcalc-5.3.0.dist-info}/RECORD +41 -42
- taxcalc/reforms/clp.out.csv +0 -10
- {taxcalc-5.2.0.dist-info → taxcalc-5.3.0.dist-info}/WHEEL +0 -0
- {taxcalc-5.2.0.dist-info → taxcalc-5.3.0.dist-info}/entry_points.txt +0 -0
- {taxcalc-5.2.0.dist-info → taxcalc-5.3.0.dist-info}/licenses/LICENSE +0 -0
- {taxcalc-5.2.0.dist-info → taxcalc-5.3.0.dist-info}/top_level.txt +0 -0
taxcalc/tests/test_calculator.py
CHANGED
@@ -26,7 +26,7 @@ def test_make_calculator(cps_subsample):
|
|
26
26
|
assert pol.current_year == start_year
|
27
27
|
rec = Records.cps_constructor(data=cps_subsample)
|
28
28
|
consump = Consumption()
|
29
|
-
consump.update_consumption({
|
29
|
+
consump.update_consumption({"MPC_e20400": {sim_year: 0.05}})
|
30
30
|
assert consump.current_year == start_year
|
31
31
|
calc = Calculator(policy=pol, records=rec,
|
32
32
|
consumption=consump, verbose=True)
|
@@ -61,10 +61,10 @@ def test_make_calculator_with_policy_reform(cps_subsample):
|
|
61
61
|
# create a Policy object and apply a policy reform
|
62
62
|
pol = Policy()
|
63
63
|
reform = {
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
"II_em": {2013: 4000},
|
65
|
+
"II_em-indexed": {2013: False},
|
66
|
+
"STD_Aged": {2013: [1600, 1300, 1300, 1600, 1600]},
|
67
|
+
"STD_Aged-indexed": {2013: False}
|
68
68
|
}
|
69
69
|
pol.implement_reform(reform)
|
70
70
|
# create a Calculator object using this policy reform
|
@@ -72,14 +72,14 @@ def test_make_calculator_with_policy_reform(cps_subsample):
|
|
72
72
|
assert calc.reform_errors == {}
|
73
73
|
# check that Policy object embedded in Calculator object is correct
|
74
74
|
assert calc.current_year == year
|
75
|
-
assert calc.policy_param(
|
76
|
-
assert np.allclose(calc.policy_param(
|
75
|
+
assert calc.policy_param("II_em") == 4000
|
76
|
+
assert np.allclose(calc.policy_param("_II_em"),
|
77
77
|
np.array([4000] * pol.num_years))
|
78
78
|
exp_STD_Aged = [[1600, 1300, 1300,
|
79
79
|
1600, 1600]] * pol.num_years
|
80
|
-
assert np.allclose(calc.policy_param(
|
80
|
+
assert np.allclose(calc.policy_param("_STD_Aged"),
|
81
81
|
np.array(exp_STD_Aged))
|
82
|
-
assert np.allclose(calc.policy_param(
|
82
|
+
assert np.allclose(calc.policy_param("STD_Aged"),
|
83
83
|
np.array([1600, 1300, 1300, 1600, 1600]))
|
84
84
|
|
85
85
|
|
@@ -92,23 +92,23 @@ def test_make_calculator_with_multiyear_reform(cps_subsample):
|
|
92
92
|
# create a Policy object and apply a policy reform
|
93
93
|
pol = Policy()
|
94
94
|
reform = {
|
95
|
-
|
96
|
-
|
97
|
-
|
95
|
+
"II_em": {2015: 5000, 2016: 6000},
|
96
|
+
"II_em-indexed": {2015: False},
|
97
|
+
"STD_Aged": {2016: [1600, 1300, 1600, 1300, 1600]}
|
98
98
|
}
|
99
99
|
pol.implement_reform(reform)
|
100
100
|
# create a Calculator object using this policy-reform
|
101
101
|
calc = Calculator(policy=pol, records=rec)
|
102
102
|
# check that Policy object embedded in Calculator object is correct
|
103
103
|
assert calc.current_year == year
|
104
|
-
assert calc.policy_param(
|
104
|
+
assert calc.policy_param("II_em") == 3950
|
105
105
|
exp_II_em = [3900, 3950, 5000] + [6000] * (pol.num_years - 3)
|
106
|
-
assert np.allclose(calc.policy_param(
|
106
|
+
assert np.allclose(calc.policy_param("_II_em"),
|
107
107
|
np.array(exp_II_em))
|
108
108
|
calc.increment_year()
|
109
109
|
calc.increment_year()
|
110
110
|
assert calc.current_year == 2016
|
111
|
-
assert np.allclose(calc.policy_param(
|
111
|
+
assert np.allclose(calc.policy_param("STD_Aged"),
|
112
112
|
np.array([1600, 1300, 1600, 1300, 1600]))
|
113
113
|
|
114
114
|
|
@@ -141,44 +141,44 @@ def test_calculator_mtr(cps_subsample):
|
|
141
141
|
rec = Records.cps_constructor(data=cps_subsample)
|
142
142
|
calcx = Calculator(policy=Policy(), records=rec)
|
143
143
|
calcx.calc_all()
|
144
|
-
combinedx = calcx.array(
|
145
|
-
c00100x = calcx.array(
|
144
|
+
combinedx = calcx.array("combined")
|
145
|
+
c00100x = calcx.array("c00100")
|
146
146
|
calc = Calculator(policy=Policy(), records=rec)
|
147
|
-
recs_pre_e00200p = copy.deepcopy(calc.array(
|
148
|
-
(mtr_ptx, mtr_itx, mtr_cmb) = calc.mtr(variable_str=
|
147
|
+
recs_pre_e00200p = copy.deepcopy(calc.array("e00200p"))
|
148
|
+
(mtr_ptx, mtr_itx, mtr_cmb) = calc.mtr(variable_str="e00200p",
|
149
149
|
zero_out_calculated_vars=True)
|
150
|
-
recs_post_e00200p = calc.array(
|
150
|
+
recs_post_e00200p = calc.array("e00200p")
|
151
151
|
assert np.allclose(recs_post_e00200p, recs_pre_e00200p)
|
152
|
-
assert np.allclose(calc.array(
|
153
|
-
assert np.allclose(calc.array(
|
152
|
+
assert np.allclose(calc.array("combined"), combinedx)
|
153
|
+
assert np.allclose(calc.array("c00100"), c00100x)
|
154
154
|
assert np.array_equal(mtr_cmb, mtr_ptx) is False
|
155
155
|
assert np.array_equal(mtr_ptx, mtr_itx) is False
|
156
156
|
with pytest.raises(ValueError):
|
157
|
-
calc.mtr(variable_str=
|
158
|
-
(_, _, mtr_combined) = calc.mtr(variable_str=
|
157
|
+
calc.mtr(variable_str="bad_income_type")
|
158
|
+
(_, _, mtr_combined) = calc.mtr(variable_str="e00200s",
|
159
159
|
calc_all_already_called=True)
|
160
160
|
assert isinstance(mtr_combined, np.ndarray)
|
161
|
-
(_, _, mtr_combined) = calc.mtr(variable_str=
|
161
|
+
(_, _, mtr_combined) = calc.mtr(variable_str="e00650",
|
162
162
|
negative_finite_diff=True,
|
163
163
|
calc_all_already_called=True)
|
164
164
|
assert isinstance(mtr_combined, np.ndarray)
|
165
|
-
(_, _, mtr_combined) = calc.mtr(variable_str=
|
165
|
+
(_, _, mtr_combined) = calc.mtr(variable_str="e00900p",
|
166
166
|
calc_all_already_called=True)
|
167
167
|
assert isinstance(mtr_combined, np.ndarray)
|
168
|
-
(_, _, mtr_combined) = calc.mtr(variable_str=
|
168
|
+
(_, _, mtr_combined) = calc.mtr(variable_str="e01700",
|
169
169
|
calc_all_already_called=True)
|
170
170
|
assert isinstance(mtr_combined, np.ndarray)
|
171
|
-
(_, _, mtr_combined) = calc.mtr(variable_str=
|
171
|
+
(_, _, mtr_combined) = calc.mtr(variable_str="e26270",
|
172
172
|
calc_all_already_called=True)
|
173
173
|
assert isinstance(mtr_combined, np.ndarray)
|
174
|
-
(_, _, mtr_combined) = calc.mtr(variable_str=
|
174
|
+
(_, _, mtr_combined) = calc.mtr(variable_str="k1bx14p",
|
175
175
|
calc_all_already_called=True)
|
176
176
|
assert isinstance(mtr_combined, np.ndarray)
|
177
|
-
(_, _, mtr_combined) = calc.mtr(variable_str=
|
177
|
+
(_, _, mtr_combined) = calc.mtr(variable_str="e00200p",
|
178
178
|
calc_all_already_called=True)
|
179
179
|
assert np.allclose(mtr_combined, mtr_cmb)
|
180
|
-
assert np.allclose(calc.array(
|
181
|
-
assert np.allclose(calc.array(
|
180
|
+
assert np.allclose(calc.array("combined"), combinedx)
|
181
|
+
assert np.allclose(calc.array("c00100"), c00100x)
|
182
182
|
|
183
183
|
|
184
184
|
def test_make_calculator_increment_years_first(cps_subsample):
|
@@ -190,10 +190,10 @@ def test_make_calculator_increment_years_first(cps_subsample):
|
|
190
190
|
pol = Policy()
|
191
191
|
std5 = 2000
|
192
192
|
reform = {
|
193
|
-
|
194
|
-
|
193
|
+
"STD_Aged": {2015: [std5, std5, std5, std5, std5]},
|
194
|
+
"II_em": {2015: 5000,
|
195
195
|
2016: 6000},
|
196
|
-
|
196
|
+
"II_em-indexed": {2016: False}
|
197
197
|
}
|
198
198
|
pol.implement_reform(reform)
|
199
199
|
# create Calculator object with Policy object as modified by reform
|
@@ -211,10 +211,10 @@ def test_make_calculator_increment_years_first(cps_subsample):
|
|
211
211
|
[std5, std5, std5, std5, std5],
|
212
212
|
[std6, std6, std6, std6, std6],
|
213
213
|
[std7, std7, std7, std7, std7]])
|
214
|
-
act_STD_Aged = calc.policy_param(
|
214
|
+
act_STD_Aged = calc.policy_param("_STD_Aged")
|
215
215
|
assert np.allclose(act_STD_Aged[:5], exp_STD_Aged)
|
216
216
|
exp_II_em = np.array([3900, 3950, 5000, 6000, 6000])
|
217
|
-
act_II_em = calc.policy_param(
|
217
|
+
act_II_em = calc.policy_param("_II_em")
|
218
218
|
assert np.allclose(act_II_em[:5], exp_II_em)
|
219
219
|
|
220
220
|
|
@@ -227,21 +227,21 @@ def test_ID_StateLocal_HC_vs_CRT(cps_subsample):
|
|
227
227
|
rec = Records.cps_constructor(data=cps_subsample)
|
228
228
|
# specify state/local complete haircut reform policy and Calculator object
|
229
229
|
hc_policy = Policy()
|
230
|
-
hc_reform = {
|
230
|
+
hc_reform = {"ID_StateLocalTax_hc": {2013: 1.0}}
|
231
231
|
hc_policy.implement_reform(hc_reform)
|
232
232
|
hc_calc = Calculator(policy=hc_policy, records=rec)
|
233
233
|
hc_calc.calc_all()
|
234
234
|
# specify AGI cap reform policy and Calculator object
|
235
235
|
crt_policy = Policy()
|
236
|
-
crt_reform = {
|
236
|
+
crt_reform = {"ID_StateLocalTax_crt": {2013: 0.0}}
|
237
237
|
crt_policy.implement_reform(crt_reform)
|
238
238
|
crt_calc = Calculator(policy=crt_policy, records=rec)
|
239
239
|
crt_calc.calc_all()
|
240
240
|
# compare calculated tax results generated by the two reforms
|
241
|
-
assert np.allclose(hc_calc.array(
|
242
|
-
crt_calc.array(
|
243
|
-
assert np.allclose(hc_calc.array(
|
244
|
-
crt_calc.array(
|
241
|
+
assert np.allclose(hc_calc.array("payrolltax"),
|
242
|
+
crt_calc.array("payrolltax"))
|
243
|
+
assert np.allclose(hc_calc.array("iitax"),
|
244
|
+
crt_calc.array("iitax"))
|
245
245
|
|
246
246
|
|
247
247
|
def test_ID_RealEstate_HC_vs_CRT(cps_subsample):
|
@@ -253,31 +253,31 @@ def test_ID_RealEstate_HC_vs_CRT(cps_subsample):
|
|
253
253
|
rec = Records.cps_constructor(data=cps_subsample)
|
254
254
|
# specify real estate complete haircut reform policy and Calculator object
|
255
255
|
hc_policy = Policy()
|
256
|
-
hc_reform = {
|
256
|
+
hc_reform = {"ID_RealEstate_hc": {2013: 1.0}}
|
257
257
|
hc_policy.implement_reform(hc_reform)
|
258
258
|
hc_calc = Calculator(policy=hc_policy, records=rec)
|
259
259
|
hc_calc.calc_all()
|
260
260
|
# specify AGI cap reform policy and Calculator object
|
261
261
|
crt_policy = Policy()
|
262
|
-
crt_reform = {
|
262
|
+
crt_reform = {"ID_RealEstate_crt": {2013: 0.0}}
|
263
263
|
crt_policy.implement_reform(crt_reform)
|
264
264
|
crt_calc = Calculator(policy=crt_policy, records=rec)
|
265
265
|
crt_calc.calc_all()
|
266
266
|
# compare calculated tax results generated by the two reforms
|
267
|
-
assert np.allclose(hc_calc.array(
|
268
|
-
crt_calc.array(
|
269
|
-
assert np.allclose(hc_calc.array(
|
270
|
-
crt_calc.array(
|
267
|
+
assert np.allclose(hc_calc.array("payrolltax"),
|
268
|
+
crt_calc.array("payrolltax"))
|
269
|
+
assert np.allclose(hc_calc.array("iitax"),
|
270
|
+
crt_calc.array("iitax"))
|
271
271
|
|
272
272
|
|
273
273
|
RAWINPUT_FUNITS = 4
|
274
274
|
RAWINPUT_YEAR = 2015
|
275
275
|
RAWINPUT_CONTENTS = (
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
276
|
+
"RECID,MARS,unknown,e00300\n"
|
277
|
+
" 1, 2, 9, 0\n"
|
278
|
+
" 2, 1, 9, 0\n"
|
279
|
+
" 3, 4, 9, 0\n"
|
280
|
+
" 4, 3, 9, 0\n"
|
281
281
|
)
|
282
282
|
|
283
283
|
|
@@ -297,36 +297,36 @@ def test_calculator_using_nonstd_input():
|
|
297
297
|
sync_years=False) # keeps raw data unchanged
|
298
298
|
assert calc.current_year == RAWINPUT_YEAR
|
299
299
|
calc.calc_all()
|
300
|
-
assert calc.weighted_total(
|
300
|
+
assert calc.weighted_total("e00200") == 0
|
301
301
|
assert calc.total_weight() == 0
|
302
|
-
varlist = [
|
302
|
+
varlist = ["RECID", "MARS"]
|
303
303
|
dframe = calc.dataframe(varlist)
|
304
304
|
assert isinstance(dframe, pd.DataFrame)
|
305
305
|
assert dframe.shape == (RAWINPUT_FUNITS, len(varlist))
|
306
|
-
mars = calc.array(
|
306
|
+
mars = calc.array("MARS")
|
307
307
|
assert isinstance(mars, np.ndarray)
|
308
308
|
assert mars.shape == (RAWINPUT_FUNITS,)
|
309
309
|
exp_iitax = np.zeros((nonstd.array_length,))
|
310
|
-
assert np.allclose(calc.array(
|
310
|
+
assert np.allclose(calc.array("iitax"), exp_iitax)
|
311
311
|
mtr_ptax, _, _ = calc.mtr(wrt_full_compensation=False)
|
312
312
|
exp_mtr_ptax = np.zeros((nonstd.array_length,))
|
313
313
|
exp_mtr_ptax.fill(0.153)
|
314
314
|
assert np.allclose(mtr_ptax, exp_mtr_ptax)
|
315
315
|
# misc calls for code coverage
|
316
|
-
calc.incarray(
|
317
|
-
calc.policy_param(
|
316
|
+
calc.incarray("e00300", np.ones_like(calc.array("e00300")))
|
317
|
+
calc.policy_param("ID_c", param_value=50e3)
|
318
318
|
|
319
319
|
|
320
320
|
def test_bad_json_names(tests_path):
|
321
321
|
"""
|
322
|
-
Test that ValueError raised with assump or reform do not end in
|
322
|
+
Test that ValueError raised with assump or reform do not end in ".json"
|
323
323
|
"""
|
324
324
|
test_url = (
|
325
|
-
|
326
|
-
|
327
|
-
|
325
|
+
"https://raw.githubusercontent.com/PSLmodels/"
|
326
|
+
"Tax-Calculator/master/taxcalc/reforms/"
|
327
|
+
"2017_law.out.csv"
|
328
328
|
)
|
329
|
-
csvname = os.path.join(tests_path,
|
329
|
+
csvname = os.path.join(tests_path, "..", "growfactors.csv")
|
330
330
|
with pytest.raises(ValueError):
|
331
331
|
Calculator.read_json_param_objects(csvname, None)
|
332
332
|
with pytest.raises(ValueError):
|
@@ -418,9 +418,9 @@ def test_json_assump_url():
|
|
418
418
|
}
|
419
419
|
}
|
420
420
|
"""
|
421
|
-
assump_url = (
|
422
|
-
|
423
|
-
|
421
|
+
assump_url = ("https://raw.githubusercontent.com/PSLmodels/"
|
422
|
+
"Tax-Calculator/master/taxcalc/assumptions/"
|
423
|
+
"economic_assumptions_template.json")
|
424
424
|
params_str = Calculator.read_json_param_objects(None, assump_str)
|
425
425
|
assert params_str
|
426
426
|
params_url = Calculator.read_json_param_objects(None, assump_url)
|
@@ -452,19 +452,19 @@ def test_read_bad_json_assump_file():
|
|
452
452
|
with pytest.raises(ValueError):
|
453
453
|
Calculator.read_json_param_objects(None, badassump1)
|
454
454
|
with pytest.raises(ValueError):
|
455
|
-
Calculator.read_json_param_objects(None,
|
455
|
+
Calculator.read_json_param_objects(None, "unknown_file_name")
|
456
456
|
with pytest.raises(TypeError):
|
457
457
|
Calculator.read_json_param_objects(None, [])
|
458
458
|
|
459
459
|
|
460
460
|
def test_json_doesnt_exist():
|
461
461
|
"""
|
462
|
-
Test JSON file which doesn
|
462
|
+
Test JSON file which doesn"t exist
|
463
463
|
"""
|
464
464
|
with pytest.raises(ValueError):
|
465
|
-
Calculator.read_json_param_objects(None,
|
465
|
+
Calculator.read_json_param_objects(None, "./reforms/doesnt_exist.json")
|
466
466
|
with pytest.raises(ValueError):
|
467
|
-
Calculator.read_json_param_objects(
|
467
|
+
Calculator.read_json_param_objects("./reforms/doesnt_exist.json", None)
|
468
468
|
|
469
469
|
|
470
470
|
def test_calc_all():
|
@@ -502,13 +502,13 @@ def test_noreform_documentation():
|
|
502
502
|
gfs = GrowFactors()
|
503
503
|
actual_doc = Calculator.reform_documentation(params, gfs)
|
504
504
|
expected_doc = (
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
505
|
+
"REFORM DOCUMENTATION\n"
|
506
|
+
"Baseline Growth-Difference Assumption Values by Year:\n"
|
507
|
+
"none: no baseline GrowDiff assumptions specified\n"
|
508
|
+
"Response Growth-Difference Assumption Values by Year:\n"
|
509
|
+
"none: no response GrowDiff assumptions specified\n"
|
510
|
+
"Policy Reform Parameter Values by Year:\n"
|
511
|
+
"none: using current-law policy parameters\n"
|
512
512
|
)
|
513
513
|
assert actual_doc == expected_doc
|
514
514
|
|
@@ -551,14 +551,14 @@ def test_reform_documentation():
|
|
551
551
|
"""
|
552
552
|
params = Calculator.read_json_param_objects(reform_json, assump_json)
|
553
553
|
assert isinstance(params, dict)
|
554
|
-
second_reform = {
|
554
|
+
second_reform = {"II_em": {2019: 6500}}
|
555
555
|
gfs = GrowFactors()
|
556
556
|
doc = Calculator.reform_documentation(params, gfs, [second_reform])
|
557
557
|
assert isinstance(doc, str)
|
558
558
|
dump = False # set to True to print documentation and force test failure
|
559
559
|
if dump:
|
560
560
|
print(doc)
|
561
|
-
assert False,
|
561
|
+
assert False, "ERROR: reform_documentation above"
|
562
562
|
|
563
563
|
|
564
564
|
def test_distribution_tables(cps_subsample):
|
@@ -570,22 +570,22 @@ def test_distribution_tables(cps_subsample):
|
|
570
570
|
calc1 = Calculator(policy=pol, records=recs)
|
571
571
|
assert calc1.current_year == 2014
|
572
572
|
calc1.calc_all()
|
573
|
-
dt1, dt2 = calc1.distribution_tables(None,
|
573
|
+
dt1, dt2 = calc1.distribution_tables(None, "weighted_deciles")
|
574
574
|
assert isinstance(dt1, pd.DataFrame)
|
575
575
|
assert dt2 is None
|
576
|
-
dt1, dt2 = calc1.distribution_tables(calc1,
|
576
|
+
dt1, dt2 = calc1.distribution_tables(calc1, "weighted_deciles")
|
577
577
|
assert isinstance(dt1, pd.DataFrame)
|
578
578
|
assert isinstance(dt2, pd.DataFrame)
|
579
579
|
reform = {
|
580
|
-
|
581
|
-
|
582
|
-
|
580
|
+
"UBI_u18": {2014: 1000},
|
581
|
+
"UBI_1820": {2014: 1000},
|
582
|
+
"UBI_21": {2014: 1000}
|
583
583
|
}
|
584
584
|
pol.implement_reform(reform)
|
585
585
|
assert not pol.parameter_errors
|
586
586
|
calc2 = Calculator(policy=pol, records=recs)
|
587
587
|
calc2.calc_all()
|
588
|
-
dt1, dt2 = calc1.distribution_tables(calc2,
|
588
|
+
dt1, dt2 = calc1.distribution_tables(calc2, "weighted_deciles")
|
589
589
|
assert isinstance(dt1, pd.DataFrame)
|
590
590
|
assert isinstance(dt2, pd.DataFrame)
|
591
591
|
|
@@ -599,13 +599,13 @@ def test_difference_table(cps_subsample):
|
|
599
599
|
recs = Records.cps_constructor(data=cps_subsample)
|
600
600
|
calc1 = Calculator(policy=pol, records=recs)
|
601
601
|
assert calc1.current_year == cyr
|
602
|
-
reform = {
|
602
|
+
reform = {"SS_Earnings_c": {cyr: 9e99}}
|
603
603
|
pol.implement_reform(reform)
|
604
604
|
calc2 = Calculator(policy=pol, records=recs)
|
605
605
|
assert calc2.current_year == cyr
|
606
606
|
calc1.calc_all()
|
607
607
|
calc2.calc_all()
|
608
|
-
diff = calc1.difference_table(calc2,
|
608
|
+
diff = calc1.difference_table(calc2, "weighted_deciles", "iitax")
|
609
609
|
assert isinstance(diff, pd.DataFrame)
|
610
610
|
|
611
611
|
|
@@ -627,13 +627,13 @@ def test_mtr_graph(cps_subsample):
|
|
627
627
|
calc = Calculator(policy=Policy(), records=recs)
|
628
628
|
fig = calc.mtr_graph(calc,
|
629
629
|
mars=2,
|
630
|
-
income_measure=
|
631
|
-
mtr_measure=
|
630
|
+
income_measure="wages",
|
631
|
+
mtr_measure="ptax",
|
632
632
|
pop_quantiles=False)
|
633
633
|
assert fig
|
634
634
|
fig = calc.mtr_graph(calc,
|
635
|
-
income_measure=
|
636
|
-
mtr_measure=
|
635
|
+
income_measure="agi",
|
636
|
+
mtr_measure="itax",
|
637
637
|
pop_quantiles=True)
|
638
638
|
assert fig
|
639
639
|
|
@@ -644,9 +644,9 @@ def test_atr_graph(cps_subsample):
|
|
644
644
|
"""
|
645
645
|
recs = Records.cps_constructor(data=cps_subsample)
|
646
646
|
calc = Calculator(policy=Policy(), records=recs)
|
647
|
-
fig = calc.atr_graph(calc, mars=2, atr_measure=
|
647
|
+
fig = calc.atr_graph(calc, mars=2, atr_measure="itax")
|
648
648
|
assert fig
|
649
|
-
fig = calc.atr_graph(calc, atr_measure=
|
649
|
+
fig = calc.atr_graph(calc, atr_measure="ptax")
|
650
650
|
assert fig
|
651
651
|
|
652
652
|
|
@@ -683,7 +683,7 @@ def test_ce_aftertax_income(cps_subsample):
|
|
683
683
|
rec = Records.cps_constructor(data=cps_subsample)
|
684
684
|
pol = Policy()
|
685
685
|
calc1 = Calculator(policy=pol, records=rec)
|
686
|
-
pol.implement_reform({
|
686
|
+
pol.implement_reform({"SS_Earnings_c": {2013: 9e99}})
|
687
687
|
calc2 = Calculator(policy=pol, records=rec)
|
688
688
|
res = calc1.ce_aftertax_income(calc2)
|
689
689
|
assert isinstance(res, dict)
|
@@ -692,19 +692,19 @@ def test_ce_aftertax_income(cps_subsample):
|
|
692
692
|
@pytest.mark.itmded_vars
|
693
693
|
@pytest.mark.pre_release
|
694
694
|
@pytest.mark.requires_pufcsv
|
695
|
-
@pytest.mark.parametrize(
|
696
|
-
[(2018,
|
697
|
-
(2018,
|
698
|
-
(2018,
|
699
|
-
(2018,
|
700
|
-
(2018,
|
701
|
-
(2018,
|
702
|
-
(2017,
|
703
|
-
(2017,
|
704
|
-
(2017,
|
705
|
-
(2017,
|
706
|
-
(2017,
|
707
|
-
(2017,
|
695
|
+
@pytest.mark.parametrize("year, cvname, hcname",
|
696
|
+
[(2018, "c17000", "ID_Medical_hc"),
|
697
|
+
(2018, "c18300", "ID_AllTaxes_hc"),
|
698
|
+
(2018, "c19200", "ID_InterestPaid_hc"),
|
699
|
+
(2018, "c19700", "ID_Charity_hc"),
|
700
|
+
(2018, "c20500", "ID_Casualty_hc"),
|
701
|
+
(2018, "c20800", "ID_Miscellaneous_hc"),
|
702
|
+
(2017, "c17000", "ID_Medical_hc"),
|
703
|
+
(2017, "c18300", "ID_AllTaxes_hc"),
|
704
|
+
(2017, "c19200", "ID_InterestPaid_hc"),
|
705
|
+
(2017, "c19700", "ID_Charity_hc"),
|
706
|
+
(2017, "c20500", "ID_Casualty_hc"),
|
707
|
+
(2017, "c20800", "ID_Miscellaneous_hc")])
|
708
708
|
def test_itemded_component_amounts(year, cvname, hcname, puf_fullsample):
|
709
709
|
"""
|
710
710
|
Check that all c04470 components are adjusted to reflect the filing
|
@@ -722,16 +722,16 @@ def test_itemded_component_amounts(year, cvname, hcname, puf_fullsample):
|
|
722
722
|
# policy1 such that everybody itemizes deductions and all are allowed
|
723
723
|
policy1 = Policy()
|
724
724
|
reform1 = {
|
725
|
-
|
726
|
-
|
725
|
+
"STD_Aged": {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
|
726
|
+
"STD": {year: [0.0, 0.0, 0.0, 0.0, 0.0]}
|
727
727
|
}
|
728
728
|
policy1.implement_reform(reform1)
|
729
729
|
assert not policy1.parameter_errors
|
730
730
|
# policy2 such that everybody itemizes deductions but one is disallowed
|
731
731
|
policy2 = Policy()
|
732
732
|
reform2 = {
|
733
|
-
|
734
|
-
|
733
|
+
"STD_Aged": {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
|
734
|
+
"STD": {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
|
735
735
|
hcname: {year: 1.0}
|
736
736
|
}
|
737
737
|
policy2.implement_reform(reform2)
|
@@ -744,36 +744,36 @@ def test_itemded_component_amounts(year, cvname, hcname, puf_fullsample):
|
|
744
744
|
calc2.advance_to_year(year)
|
745
745
|
calc2.calc_all()
|
746
746
|
# confirm that nobody is taking the standard deduction
|
747
|
-
assert np.allclose(calc1.array(
|
748
|
-
assert np.allclose(calc2.array(
|
747
|
+
assert np.allclose(calc1.array("standard"), 0.)
|
748
|
+
assert np.allclose(calc2.array("standard"), 0.)
|
749
749
|
# calculate different in total itemized deductions
|
750
750
|
if year == 2017:
|
751
751
|
# pre-Pease limitation total itemized deductions
|
752
|
-
itmded1 = calc1.weighted_total(
|
753
|
-
itmded2 = calc2.weighted_total(
|
752
|
+
itmded1 = calc1.weighted_total("c21060") * 1e-9
|
753
|
+
itmded2 = calc2.weighted_total("c21060") * 1e-9
|
754
754
|
elif year == 2018:
|
755
755
|
# total itemized deductions (no Pease-like limitation)
|
756
|
-
itmded1 = calc1.weighted_total(
|
757
|
-
itmded2 = calc2.weighted_total(
|
756
|
+
itmded1 = calc1.weighted_total("c04470") * 1e-9
|
757
|
+
itmded2 = calc2.weighted_total("c04470") * 1e-9
|
758
758
|
else:
|
759
|
-
raise ValueError(f
|
759
|
+
raise ValueError(f"illegal year value = {year}")
|
760
760
|
difference_in_total_itmded = itmded1 - itmded2
|
761
761
|
# calculate itemized component amount
|
762
762
|
component_amt = calc1.weighted_total(cvname) * 1e-9
|
763
763
|
# confirm that component amount is equal to difference in total deductions
|
764
|
-
if year == 2017 and cvname ==
|
764
|
+
if year == 2017 and cvname == "c19700":
|
765
765
|
atol = 0.016
|
766
|
-
elif year == 2017 and cvname ==
|
766
|
+
elif year == 2017 and cvname == "c19200":
|
767
767
|
atol = 0.010
|
768
|
-
elif year == 2017 and cvname ==
|
768
|
+
elif year == 2017 and cvname == "c18300":
|
769
769
|
atol = 0.009
|
770
770
|
else:
|
771
771
|
atol = 0.00001
|
772
772
|
if not np.allclose(component_amt, difference_in_total_itmded, atol=atol):
|
773
773
|
msg = (
|
774
|
-
f
|
775
|
-
f
|
776
|
-
|
774
|
+
f"\n{cvname}={component_amt:.3f} != "
|
775
|
+
f"{difference_in_total_itmded:.3f}="
|
776
|
+
"difference_in_total_itemized_deductions"
|
777
777
|
)
|
778
778
|
raise ValueError(msg)
|
779
779
|
|
@@ -793,16 +793,16 @@ def test_qbid_calculation():
|
|
793
793
|
# and that the spouse has no business income and only earnings.
|
794
794
|
TPC_YEAR = 2018
|
795
795
|
TPC_VARS = (
|
796
|
-
|
797
|
-
|
796
|
+
"RECID,MARS,e00200s,e00200,e26270,e02000,PT_SSTB_income,"
|
797
|
+
"PT_binc_w2_wages,PT_ubia_property,pre_qbid_taxinc,qbid\n"
|
798
798
|
)
|
799
799
|
TPC_FUNITS = (
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
800
|
+
"1,2, 99000, 99000,75000,75000,1,20000,90000,150000,15000.00\n"
|
801
|
+
"2,2,349000,349000,75000,75000,1,20000,90000,400000, 1612.50\n"
|
802
|
+
"3,2,524000,524000,75000,75000,1,20000,90000,575000, 0.00\n"
|
803
|
+
"4,2, 99000, 99000,75000,75000,0,20000,90000,150000,15000.00\n"
|
804
|
+
"5,2,349000,349000,75000,75000,0,20000,90000,400000,10750.00\n"
|
805
|
+
"6,2,524000,524000,75000,75000,0,20000,90000,575000,10000.00\n"
|
806
806
|
)
|
807
807
|
# generate actual Calculator pre-qbid taxinc and qbid amounts
|
808
808
|
tpc_df = pd.read_csv(StringIO(TPC_VARS + TPC_FUNITS))
|
@@ -811,7 +811,7 @@ def test_qbid_calculation():
|
|
811
811
|
calc = Calculator(policy=Policy(), records=recs)
|
812
812
|
assert calc.current_year == TPC_YEAR
|
813
813
|
calc.calc_all()
|
814
|
-
varlist = [
|
814
|
+
varlist = ["RECID", "c00100", "standard", "c04470", "qbided"]
|
815
815
|
tc_df = calc.dataframe(varlist, all_vars=True)
|
816
816
|
# compare actual amounts with expected amounts from TPC publication
|
817
817
|
act_taxinc = tc_df.c00100 - np.maximum(tc_df.standard, tc_df.c04470)
|
@@ -821,11 +821,11 @@ def test_qbid_calculation():
|
|
821
821
|
|
822
822
|
|
823
823
|
def test_calc_all_benefits_amounts(cps_subsample):
|
824
|
-
|
824
|
+
"""
|
825
825
|
Testing how benefits are handled in the calc_all method
|
826
|
-
|
826
|
+
"""
|
827
827
|
# set a reform with a positive UBI amount
|
828
|
-
ubi_ref = {
|
828
|
+
ubi_ref = {"UBI_21": {2020: 1000}}
|
829
829
|
|
830
830
|
# create baseline calculator
|
831
831
|
pol = Policy()
|
@@ -843,14 +843,14 @@ def test_calc_all_benefits_amounts(cps_subsample):
|
|
843
843
|
|
844
844
|
# check that differences in benefits totals are equal to diffs in
|
845
845
|
# UBI
|
846
|
-
ubi_diff = (calc_ubi.weighted_total(
|
847
|
-
calc_base.weighted_total(
|
846
|
+
ubi_diff = (calc_ubi.weighted_total("ubi") -
|
847
|
+
calc_base.weighted_total("ubi")) / 1e9
|
848
848
|
benefit_cost_diff = (
|
849
|
-
calc_ubi.weighted_total(
|
850
|
-
calc_base.weighted_total(
|
849
|
+
calc_ubi.weighted_total("benefit_cost_total") -
|
850
|
+
calc_base.weighted_total("benefit_cost_total")) / 1e9
|
851
851
|
benefit_value_diff = (
|
852
|
-
calc_ubi.weighted_total(
|
853
|
-
calc_base.weighted_total(
|
852
|
+
calc_ubi.weighted_total("benefit_cost_total") -
|
853
|
+
calc_base.weighted_total("benefit_cost_total")) / 1e9
|
854
854
|
|
855
855
|
assert np.allclose(ubi_diff, benefit_cost_diff)
|
856
856
|
assert np.allclose(ubi_diff, benefit_value_diff)
|
@@ -875,8 +875,8 @@ def test_cg_top_rate():
|
|
875
875
|
"STD": {2019: [0, 0, 0, 0, 0]}}
|
876
876
|
|
877
877
|
# create one record just below the top CG bracket and one just above
|
878
|
-
VARS =
|
879
|
-
FUNITS =
|
878
|
+
VARS = "RECID,MARS,p23250\n"
|
879
|
+
FUNITS = "1,2,999999\n2,2,1000001\n"
|
880
880
|
|
881
881
|
pol_base = Policy()
|
882
882
|
pol_base.implement_reform(base)
|
@@ -895,23 +895,23 @@ def test_cg_top_rate():
|
|
895
895
|
calc_ref.calc_all()
|
896
896
|
|
897
897
|
# calculate MTRs wrt long term gains
|
898
|
-
mtr_base = calc_base.mtr(variable_str=
|
898
|
+
mtr_base = calc_base.mtr(variable_str="p23250",
|
899
899
|
calc_all_already_called=True,
|
900
900
|
wrt_full_compensation=False)
|
901
901
|
mtr_itax_base = mtr_base[1]
|
902
902
|
|
903
|
-
cg_rt3 = pol_base.to_array(
|
903
|
+
cg_rt3 = pol_base.to_array("CG_rt3", year=2019)
|
904
904
|
# check that MTR for both records is equal to CG_rt3
|
905
905
|
assert np.allclose(mtr_itax_base, cg_rt3)
|
906
906
|
|
907
907
|
# calculate MTRs under reform
|
908
|
-
mtr_ref = calc_ref.mtr(variable_str=
|
908
|
+
mtr_ref = calc_ref.mtr(variable_str="p23250",
|
909
909
|
calc_all_already_called=True,
|
910
910
|
wrt_full_compensation=False)
|
911
911
|
mtr_itax_ref = mtr_ref[1]
|
912
912
|
|
913
|
-
cg_rt3_ref = pol_ref.to_array(
|
914
|
-
cg_rt4_ref = pol_ref.to_array(param=
|
913
|
+
cg_rt3_ref = pol_ref.to_array("CG_rt3", year=2019)
|
914
|
+
cg_rt4_ref = pol_ref.to_array(param="CG_rt4", year=2019)
|
915
915
|
|
916
916
|
# check that MTR of houshold below top threshold is equal to
|
917
917
|
# CG_rt3
|