taxcalc 4.3.0__py3-none-any.whl → 4.3.2__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 -1
- taxcalc/calcfunctions.py +4 -12
- taxcalc/calculator.py +6 -6
- taxcalc/cli/tc.py +26 -10
- taxcalc/data.py +13 -5
- taxcalc/growfactors.py +1 -1
- taxcalc/policy.py +16 -3
- taxcalc/policy_current_law.json +0 -26
- taxcalc/records.py +13 -4
- taxcalc/reforms/ext.json +1 -1
- taxcalc/taxcalcio.py +17 -6
- taxcalc/tests/test_benefits.py +3 -3
- taxcalc/tests/test_calcfunctions.py +4 -5
- taxcalc/tests/test_calculator.py +1 -36
- taxcalc/tests/test_taxcalcio.py +1 -1
- {taxcalc-4.3.0.dist-info → taxcalc-4.3.2.dist-info}/METADATA +1 -1
- {taxcalc-4.3.0.dist-info → taxcalc-4.3.2.dist-info}/RECORD +21 -21
- {taxcalc-4.3.0.dist-info → taxcalc-4.3.2.dist-info}/WHEEL +1 -1
- {taxcalc-4.3.0.dist-info → taxcalc-4.3.2.dist-info}/LICENSE +0 -0
- {taxcalc-4.3.0.dist-info → taxcalc-4.3.2.dist-info}/entry_points.txt +0 -0
- {taxcalc-4.3.0.dist-info → taxcalc-4.3.2.dist-info}/top_level.txt +0 -0
taxcalc/__init__.py
CHANGED
taxcalc/calcfunctions.py
CHANGED
@@ -1217,7 +1217,7 @@ def TaxInc(c00100, standard, c04470, c04600, MARS, e00900, c03260, e26270,
|
|
1217
1217
|
PT_binc_w2_wages, PT_ubia_property, PT_qbid_rt,
|
1218
1218
|
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
1219
1219
|
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800,
|
1220
|
-
PT_qbid_ps, PT_qbid_prt, qbided
|
1220
|
+
PT_qbid_ps, PT_qbid_prt, qbided):
|
1221
1221
|
"""
|
1222
1222
|
Calculates taxable income, c04800, and
|
1223
1223
|
qualified business income deduction, qbided.
|
@@ -1275,8 +1275,6 @@ def TaxInc(c00100, standard, c04470, c04600, MARS, e00900, c03260, e26270,
|
|
1275
1275
|
QBID phaseout rate
|
1276
1276
|
qbided: float
|
1277
1277
|
Qualified Business Income (QBI) deduction
|
1278
|
-
PT_qbid_limit_switch: bool
|
1279
|
-
QBID wage and capital limitations switch
|
1280
1278
|
|
1281
1279
|
Returns
|
1282
1280
|
-------
|
@@ -1300,9 +1298,7 @@ def TaxInc(c00100, standard, c04470, c04600, MARS, e00900, c03260, e26270,
|
|
1300
1298
|
upper_thd = lower_thd + pre_qbid_taxinc_gap
|
1301
1299
|
if PT_SSTB_income == 1 and pre_qbid_taxinc >= upper_thd:
|
1302
1300
|
qbided = 0.
|
1303
|
-
|
1304
|
-
# limitations.
|
1305
|
-
elif PT_qbid_limit_switch:
|
1301
|
+
else:
|
1306
1302
|
wage_cap = PT_binc_w2_wages * PT_qbid_w2_wages_rt
|
1307
1303
|
alt_cap = (PT_binc_w2_wages * PT_qbid_alt_w2_wages_rt +
|
1308
1304
|
PT_ubia_property * PT_qbid_alt_property_rt)
|
@@ -1323,12 +1319,8 @@ def TaxInc(c00100, standard, c04470, c04600, MARS, e00900, c03260, e26270,
|
|
1323
1319
|
prt = (pre_qbid_taxinc - lower_thd) / pre_qbid_taxinc_gap
|
1324
1320
|
adj = prt * (qbid_adjusted - cap_adjusted)
|
1325
1321
|
qbided = qbid_adjusted - adj
|
1326
|
-
|
1327
|
-
|
1328
|
-
# QBID limitations.
|
1329
|
-
else:
|
1330
|
-
qbided = qbid_before_limits
|
1331
|
-
# apply taxinc cap (assuning cap rate is equal to PT_qbid_rt)
|
1322
|
+
|
1323
|
+
# apply taxinc cap (assuming cap rate is equal to PT_qbid_rt)
|
1332
1324
|
net_cg = e00650 + c01000 # per line 34 in 2018 Pub 535 Worksheet 12-A
|
1333
1325
|
taxinc_cap = PT_qbid_rt * max(0., pre_qbid_taxinc - net_cg)
|
1334
1326
|
qbided = min(qbided, taxinc_cap)
|
taxcalc/calculator.py
CHANGED
@@ -698,7 +698,8 @@ class Calculator():
|
|
698
698
|
self.policy_param('FICA_ss_trt_employee') +
|
699
699
|
self.policy_param('FICA_mc_trt_employer') +
|
700
700
|
self.policy_param('FICA_mc_trt_employee')),
|
701
|
-
0.5 * (self.policy_param('FICA_mc_trt_employer') +
|
701
|
+
0.5 * (self.policy_param('FICA_mc_trt_employer') +
|
702
|
+
self.policy_param('FICA_mc_trt_employee')))
|
702
703
|
else:
|
703
704
|
adj = 0.0
|
704
705
|
# compute marginal tax rates
|
@@ -1189,11 +1190,10 @@ class Calculator():
|
|
1189
1190
|
for pname in baseline.keys():
|
1190
1191
|
upda_value = getattr(updated, pname)
|
1191
1192
|
base_value = getattr(baseline, pname)
|
1193
|
+
is_array = isinstance(upda_value, np.ndarray)
|
1192
1194
|
if (
|
1193
|
-
(
|
1194
|
-
|
1195
|
-
(not isinstance(upda_value, np.ndarray) and
|
1196
|
-
upda_value != base_value)
|
1195
|
+
(is_array and not np.allclose(upda_value, base_value))
|
1196
|
+
or (is_array == False and upda_value != base_value)
|
1197
1197
|
):
|
1198
1198
|
params_with_diff.append(pname)
|
1199
1199
|
if params_with_diff:
|
@@ -1248,7 +1248,7 @@ class Calculator():
|
|
1248
1248
|
else: # if baseline is GrowDiff object
|
1249
1249
|
# each GrowDiff parameter has zero as default value
|
1250
1250
|
doc += ' baseline_value: 0.0\n'
|
1251
|
-
|
1251
|
+
del mdata_base
|
1252
1252
|
return doc
|
1253
1253
|
|
1254
1254
|
# begin main logic of reform_documentation
|
taxcalc/cli/tc.py
CHANGED
@@ -138,11 +138,23 @@ def cli_tc_main():
|
|
138
138
|
default=False,
|
139
139
|
action="store_true")
|
140
140
|
args = parser.parse_args()
|
141
|
-
#
|
141
|
+
# check Python version
|
142
|
+
pyv = sys.version_info
|
143
|
+
pymin = tc.__min_python3_version__
|
144
|
+
pymax = tc.__max_python3_version__
|
145
|
+
if pyv[0] != 3 or pyv[1] < pymin or pyv[1] > pymax: # pragma: no cover
|
146
|
+
pyreq = f'at least Python 3.{pymin} and at most Python 3.{pymax}'
|
147
|
+
sys.stderr.write(
|
148
|
+
f'ERROR: Tax-Calculator requires {pyreq}\n'
|
149
|
+
f' but Python {pyv[0]}.{pyv[1]} is installed\n'
|
150
|
+
)
|
151
|
+
return 1
|
152
|
+
# show Tax-Calculator version and quit if --version option is specified
|
142
153
|
if args.version:
|
143
|
-
|
154
|
+
pyver = f'Python 3.{pyv[1]}'
|
155
|
+
sys.stdout.write(f'Tax-Calculator {tc.__version__} on {pyver}\n')
|
144
156
|
return 0
|
145
|
-
# write test input and expected output files if --test option specified
|
157
|
+
# write test input and expected output files if --test option is specified
|
146
158
|
if args.test:
|
147
159
|
_write_expected_test_output()
|
148
160
|
inputfn = TEST_INPUT_FILENAME
|
@@ -181,7 +193,7 @@ def cli_tc_main():
|
|
181
193
|
dumpvar_set = None
|
182
194
|
if args.dvars and (args.dump or args.sqldb):
|
183
195
|
if os.path.exists(args.dvars):
|
184
|
-
with open(args.dvars) as dfile:
|
196
|
+
with open(args.dvars, 'r', encoding='utf-8') as dfile:
|
185
197
|
dump_vars_str = dfile.read()
|
186
198
|
dumpvar_set = tcio.custom_dump_variables(dump_vars_str)
|
187
199
|
if tcio.errmsg:
|
@@ -213,8 +225,8 @@ def cli_tc_main():
|
|
213
225
|
# end of cli_tc_main function code
|
214
226
|
|
215
227
|
|
216
|
-
EXPECTED_TEST_OUTPUT_FILENAME = 'test-{
|
217
|
-
ACTUAL_TEST_OUTPUT_FILENAME = 'test-{
|
228
|
+
EXPECTED_TEST_OUTPUT_FILENAME = f'test-{str(TEST_TAXYEAR)[2:]}-out.csv'
|
229
|
+
ACTUAL_TEST_OUTPUT_FILENAME = f'test-{str(TEST_TAXYEAR)[2:]}-#-#-#.csv'
|
218
230
|
|
219
231
|
|
220
232
|
def _write_expected_test_output():
|
@@ -226,14 +238,14 @@ def _write_expected_test_output():
|
|
226
238
|
'1, 2, 3, 1, 40000, 40000, 0, 0, 3000, 4000\n'
|
227
239
|
'2, 2, 3, 1,200000, 200000, 0, 0, 15000, 20000\n'
|
228
240
|
)
|
229
|
-
with open(TEST_INPUT_FILENAME, 'w') as ifile:
|
241
|
+
with open(TEST_INPUT_FILENAME, 'w', encoding='utf-8') as ifile:
|
230
242
|
ifile.write(input_data)
|
231
243
|
expected_output_data = (
|
232
244
|
'RECID,YEAR,WEIGHT,INCTAX,LSTAX,PAYTAX\n'
|
233
245
|
'1,2018,0.00,131.88,0.00,6120.00\n'
|
234
246
|
'2,2018,0.00,28879.00,0.00,21721.60\n'
|
235
247
|
)
|
236
|
-
with open(EXPECTED_TEST_OUTPUT_FILENAME, 'w') as ofile:
|
248
|
+
with open(EXPECTED_TEST_OUTPUT_FILENAME, 'w', encoding='utf-8') as ofile:
|
237
249
|
ofile.write(expected_output_data)
|
238
250
|
|
239
251
|
|
@@ -242,8 +254,12 @@ def _compare_test_output_files():
|
|
242
254
|
Private function that compares expected and actual tc --test output files;
|
243
255
|
returns 0 if pass test, otherwise returns 1.
|
244
256
|
"""
|
245
|
-
explines = open(
|
246
|
-
|
257
|
+
explines = open(
|
258
|
+
EXPECTED_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8'
|
259
|
+
).readlines()
|
260
|
+
actlines = open(
|
261
|
+
ACTUAL_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8'
|
262
|
+
).readlines()
|
247
263
|
if ''.join(explines) == ''.join(actlines):
|
248
264
|
sys.stdout.write('PASSED TEST\n')
|
249
265
|
retcode = 0
|
taxcalc/data.py
CHANGED
@@ -42,6 +42,13 @@ class Data():
|
|
42
42
|
NOTE: when using custom weights, set this argument to a DataFrame.
|
43
43
|
NOTE: assumes weights are integers that are 100 times the real weights.
|
44
44
|
|
45
|
+
weights_scale: float
|
46
|
+
specifies the weights scaling factor used to convert contents
|
47
|
+
of weights file into the s006 variable. PUF and CPS input data
|
48
|
+
generated in the taxdata repository use a weights_scale of 0.01,
|
49
|
+
while TMD input data generated in the tax-microdata repository
|
50
|
+
use a 1.0 weights_scale value.
|
51
|
+
|
45
52
|
Raises
|
46
53
|
------
|
47
54
|
ValueError:
|
@@ -66,7 +73,8 @@ class Data():
|
|
66
73
|
VARINFO_FILE_NAME = None
|
67
74
|
VARINFO_FILE_PATH = None
|
68
75
|
|
69
|
-
def __init__(self, data, start_year, gfactors=None,
|
76
|
+
def __init__(self, data, start_year, gfactors=None,
|
77
|
+
weights=None, weights_scale=0.01):
|
70
78
|
# initialize data variable info sets and read variable information
|
71
79
|
self.INTEGER_READ_VARS = set()
|
72
80
|
self.MUST_READ_VARS = set()
|
@@ -97,6 +105,7 @@ class Data():
|
|
97
105
|
self.gfactors = gfactors
|
98
106
|
# read sample weights
|
99
107
|
self.WT = None
|
108
|
+
self.weights_scale = weights_scale
|
100
109
|
if self.__aging_data:
|
101
110
|
self._read_weights(weights)
|
102
111
|
# ... weights must be same size as data
|
@@ -114,7 +123,7 @@ class Data():
|
|
114
123
|
assert wt_colname in self.WT.columns, (
|
115
124
|
f'no weights for start year {self.current_year}'
|
116
125
|
)
|
117
|
-
self.s006 = self.WT[wt_colname] *
|
126
|
+
self.s006 = self.WT[wt_colname] * self.weights_scale
|
118
127
|
|
119
128
|
@property
|
120
129
|
def data_year(self):
|
@@ -152,7 +161,7 @@ class Data():
|
|
152
161
|
assert wt_colname in self.WT.columns, (
|
153
162
|
f'no weights for new year {self.current_year}'
|
154
163
|
)
|
155
|
-
self.s006 = self.WT[wt_colname] *
|
164
|
+
self.s006 = self.WT[wt_colname] * self.weights_scale
|
156
165
|
|
157
166
|
# ----- begin private methods of Data class -----
|
158
167
|
|
@@ -260,7 +269,6 @@ class Data():
|
|
260
269
|
Read sample weights from file or
|
261
270
|
use specified DataFrame as weights or
|
262
271
|
create empty DataFrame if None.
|
263
|
-
NOTE: assumes weights are integers equal to 100 times the real weight.
|
264
272
|
"""
|
265
273
|
if weights is None:
|
266
274
|
return
|
@@ -276,7 +284,7 @@ class Data():
|
|
276
284
|
msg = 'weights is not None or a string or a Pandas DataFrame'
|
277
285
|
raise ValueError(msg)
|
278
286
|
assert isinstance(WT, pd.DataFrame)
|
279
|
-
setattr(self, 'WT', WT.astype(np.
|
287
|
+
setattr(self, 'WT', WT.astype(np.float64))
|
280
288
|
del WT
|
281
289
|
|
282
290
|
def _extrapolate(self, year):
|
taxcalc/growfactors.py
CHANGED
@@ -38,7 +38,7 @@ class GrowFactors():
|
|
38
38
|
which is for use with puf and cps data from the taxdata repository.
|
39
39
|
"""
|
40
40
|
|
41
|
-
PACKAGE_FILE_NAMES = ['growfactors.csv'
|
41
|
+
PACKAGE_FILE_NAMES = ['growfactors.csv']
|
42
42
|
FILE_PATH = os.path.abspath(os.path.dirname(__file__))
|
43
43
|
|
44
44
|
VALID_NAMES = set(['ABOOK', 'ACGNS', 'ACPIM', 'ACPIU',
|
taxcalc/policy.py
CHANGED
@@ -7,6 +7,7 @@ Tax-Calculator federal tax policy Policy class.
|
|
7
7
|
|
8
8
|
import os
|
9
9
|
import json
|
10
|
+
from pathlib import Path
|
10
11
|
import numpy as np
|
11
12
|
from taxcalc.parameters import Parameters
|
12
13
|
from taxcalc.growfactors import GrowFactors
|
@@ -80,7 +81,7 @@ class Policy(Parameters):
|
|
80
81
|
# (3) specify which Policy parameters are wage (rather than price) indexed
|
81
82
|
WAGE_INDEXED_PARAMS = ['SS_Earnings_c', 'SS_Earnings_thd']
|
82
83
|
|
83
|
-
def __init__(self, gfactors=None,
|
84
|
+
def __init__(self, gfactors=None, **kwargs):
|
84
85
|
# put JSON contents of DEFAULTS_FILE_NAME into self._vals dictionary
|
85
86
|
super().__init__()
|
86
87
|
# handle gfactors argument
|
@@ -92,7 +93,6 @@ class Policy(Parameters):
|
|
92
93
|
raise ValueError('gfactors is not None or a GrowFactors instance')
|
93
94
|
# read default parameters and initialize
|
94
95
|
syr = Policy.JSON_START_YEAR
|
95
|
-
lyr = Policy.LAST_BUDGET_YEAR
|
96
96
|
nyrs = Policy.DEFAULT_NUM_YEARS
|
97
97
|
self._inflation_rates = None
|
98
98
|
self._wage_growth_rates = None
|
@@ -101,6 +101,19 @@ class Policy(Parameters):
|
|
101
101
|
Policy.REDEFINED_PARAMS,
|
102
102
|
Policy.WAGE_INDEXED_PARAMS, **kwargs)
|
103
103
|
|
104
|
+
@staticmethod
|
105
|
+
def tmd_constructor(growfactors_path): # pragma: no cover
|
106
|
+
"""
|
107
|
+
Static method returns a Policy object instantiated with TMD
|
108
|
+
input data. This convenience method works in a analogous way
|
109
|
+
to Policy(), which returns a Policy object instantiated with
|
110
|
+
non-TMD input data.
|
111
|
+
"""
|
112
|
+
assert isinstance(growfactors_path, Path)
|
113
|
+
gf_filename = str(growfactors_path)
|
114
|
+
tmd_growfactors = GrowFactors(growfactors_filename=gf_filename)
|
115
|
+
return Policy(gfactors=tmd_growfactors)
|
116
|
+
|
104
117
|
@staticmethod
|
105
118
|
def read_json_reform(obj):
|
106
119
|
"""
|
@@ -129,7 +142,7 @@ class Policy(Parameters):
|
|
129
142
|
Policy.DEFAULTS_FILE_PATH,
|
130
143
|
Policy.DEFAULTS_FILE_NAME
|
131
144
|
)
|
132
|
-
with open(path) as f:
|
145
|
+
with open(path, 'r', encoding='utf-8') as f:
|
133
146
|
defaults = json.loads(f.read()) # pylint: disable=protected-access
|
134
147
|
return [k for k in defaults if k != "schema"]
|
135
148
|
|
taxcalc/policy_current_law.json
CHANGED
@@ -18379,32 +18379,6 @@
|
|
18379
18379
|
"cps": false
|
18380
18380
|
}
|
18381
18381
|
},
|
18382
|
-
"PT_qbid_limit_switch": {
|
18383
|
-
"title": "QBID wage and capital limitations switch.",
|
18384
|
-
"description": "A value of True imposes wage/capital limitations. Note that neither the PUF nor CPS have data on wage expenses or capital income, and therefore all taxpayers are fully subject to the QBID limitations. A value of False assumes sufficient wage and capital income to avoid QBID limitations.",
|
18385
|
-
"notes": "",
|
18386
|
-
"section_1": "Personal Income",
|
18387
|
-
"section_2": "Pass-Through",
|
18388
|
-
"indexable": false,
|
18389
|
-
"indexed": false,
|
18390
|
-
"type": "bool",
|
18391
|
-
"value": [
|
18392
|
-
{
|
18393
|
-
"year": 2013,
|
18394
|
-
"value": true
|
18395
|
-
}
|
18396
|
-
],
|
18397
|
-
"validators": {
|
18398
|
-
"range": {
|
18399
|
-
"min": false,
|
18400
|
-
"max": true
|
18401
|
-
}
|
18402
|
-
},
|
18403
|
-
"compatible_data": {
|
18404
|
-
"puf": false,
|
18405
|
-
"cps": false
|
18406
|
-
}
|
18407
|
-
},
|
18408
18382
|
"PT_qbid_ps": {
|
18409
18383
|
"title": "QBID phaseout taxable income start",
|
18410
18384
|
"description": "QBID begins to decrease when pre-QBID taxable income is above this level.",
|
taxcalc/records.py
CHANGED
@@ -53,7 +53,7 @@ class Records(Data):
|
|
53
53
|
None creates empty sample-weights DataFrame;
|
54
54
|
default value is filename of the PUF weights.
|
55
55
|
NOTE: when using custom weights, set this argument to a DataFrame.
|
56
|
-
NOTE:
|
56
|
+
NOTE: see weights_scale documentation below.
|
57
57
|
|
58
58
|
adjust_ratios: string or Pandas DataFrame or None
|
59
59
|
string describes CSV file in which adjustment ratios reside;
|
@@ -69,6 +69,13 @@ class Records(Data):
|
|
69
69
|
any smoothing of stair-step provisions in income tax law;
|
70
70
|
default value is false.
|
71
71
|
|
72
|
+
weights_scale: float
|
73
|
+
specifies the weights scaling factor used to convert contents
|
74
|
+
of weights file into the s006 variable. PUF and CPS input data
|
75
|
+
generated in the taxdata repository use a weights_scale of 0.01,
|
76
|
+
while TMD input data generated in the tax-microdata repository
|
77
|
+
use a 1.0 weights_scale value.
|
78
|
+
|
72
79
|
Raises
|
73
80
|
------
|
74
81
|
ValueError:
|
@@ -127,11 +134,12 @@ class Records(Data):
|
|
127
134
|
gfactors=GrowFactors(),
|
128
135
|
weights=PUF_WEIGHTS_FILENAME,
|
129
136
|
adjust_ratios=PUF_RATIOS_FILENAME,
|
130
|
-
exact_calculations=False
|
137
|
+
exact_calculations=False,
|
138
|
+
weights_scale=0.01):
|
131
139
|
# pylint: disable=no-member,too-many-branches
|
132
140
|
if isinstance(weights, str):
|
133
141
|
weights = os.path.join(Records.CODE_PATH, weights)
|
134
|
-
super().__init__(data, start_year, gfactors, weights)
|
142
|
+
super().__init__(data, start_year, gfactors, weights, weights_scale)
|
135
143
|
if data is None:
|
136
144
|
return # because there are no data
|
137
145
|
# read adjustment ratios
|
@@ -228,7 +236,7 @@ class Records(Data):
|
|
228
236
|
data_path: Path,
|
229
237
|
weights_path: Path,
|
230
238
|
growfactors_path: Path,
|
231
|
-
exact_calculations=False
|
239
|
+
exact_calculations=False,
|
232
240
|
): # pragma: no cover
|
233
241
|
"""
|
234
242
|
Static method returns a Records object instantiated with TMD
|
@@ -250,6 +258,7 @@ class Records(Data):
|
|
250
258
|
gfactors=GrowFactors(growfactors_filename=str(growfactors_path)),
|
251
259
|
adjust_ratios=None,
|
252
260
|
exact_calculations=exact_calculations,
|
261
|
+
weights_scale=1.0,
|
253
262
|
)
|
254
263
|
|
255
264
|
def increment_year(self):
|
taxcalc/reforms/ext.json
CHANGED
taxcalc/taxcalcio.py
CHANGED
@@ -355,7 +355,8 @@ class TaxCalcIO():
|
|
355
355
|
weights=wghts,
|
356
356
|
gfactors=gfactors_ref,
|
357
357
|
adjust_ratios=None,
|
358
|
-
exact_calculations=exact_calculations
|
358
|
+
exact_calculations=exact_calculations,
|
359
|
+
weights_scale=1.0,
|
359
360
|
)
|
360
361
|
recs_base = Records(
|
361
362
|
data=pd.read_csv(input_data),
|
@@ -363,7 +364,8 @@ class TaxCalcIO():
|
|
363
364
|
weights=wghts,
|
364
365
|
gfactors=gfactors_base,
|
365
366
|
adjust_ratios=None,
|
366
|
-
exact_calculations=exact_calculations
|
367
|
+
exact_calculations=exact_calculations,
|
368
|
+
weights_scale=1.0,
|
367
369
|
)
|
368
370
|
else: # if not {cps|tmd}_input_data but aging_input_data: puf
|
369
371
|
recs = Records(
|
@@ -548,8 +550,17 @@ class TaxCalcIO():
|
|
548
550
|
outdf = self.minimal_output()
|
549
551
|
column_order = outdf.columns
|
550
552
|
assert len(outdf.index) == self.calc.array_len
|
551
|
-
|
552
|
-
|
553
|
+
if self.tmd_input_data: # pragma: no cover
|
554
|
+
if "s006" in outdf:
|
555
|
+
weights = outdf["s006"].round(5)
|
556
|
+
outdf = outdf.round(2)
|
557
|
+
if "s006" in outdf:
|
558
|
+
outdf["s006"] = weights
|
559
|
+
outdf.to_csv(self._output_filename, columns=column_order,
|
560
|
+
index=False)
|
561
|
+
else:
|
562
|
+
outdf.to_csv(self._output_filename, columns=column_order,
|
563
|
+
index=False, float_format='%.2f')
|
553
564
|
del outdf
|
554
565
|
gc.collect()
|
555
566
|
|
@@ -786,8 +797,8 @@ class TaxCalcIO():
|
|
786
797
|
vardata = calcx.array(varname)
|
787
798
|
if varname in recs_vinfo.INTEGER_VARS:
|
788
799
|
odf[varname] = vardata
|
789
|
-
else:
|
790
|
-
odf[varname] = vardata.round(
|
800
|
+
else: # specify precision that can handle small TMD area weights
|
801
|
+
odf[varname] = vardata.round(5)
|
791
802
|
odf = odf.copy()
|
792
803
|
# specify mtr values in percentage terms
|
793
804
|
if 'mtr_inctax' in varset:
|
taxcalc/tests/test_benefits.py
CHANGED
@@ -77,9 +77,9 @@ def test_benefits(tests_path, cps_fullsample):
|
|
77
77
|
if diffs:
|
78
78
|
msg = 'CPS BENEFITS RESULTS DIFFER\n'
|
79
79
|
msg += '-------------------------------------------------\n'
|
80
|
-
msg += '--- NEW RESULTS IN benefits_actual.
|
81
|
-
msg += '--- if new OK, copy benefits_actual.
|
82
|
-
msg += '--- benefits_expect.
|
80
|
+
msg += '--- NEW RESULTS IN benefits_actual.csv FILE ---\n'
|
81
|
+
msg += '--- if new OK, copy benefits_actual.csv to ---\n'
|
82
|
+
msg += '--- benefits_expect.csv ---\n'
|
83
83
|
msg += '--- and rerun test. ---\n'
|
84
84
|
msg += '-------------------------------------------------\n'
|
85
85
|
raise ValueError(msg)
|
@@ -551,7 +551,6 @@ PT_qbid_alt_w2_wages_rt = 0.25
|
|
551
551
|
PT_qbid_alt_property_rt = 0.025
|
552
552
|
PT_qbid_ps = [9e99, 9e99, 9e99, 9e99, 9e99]
|
553
553
|
PT_qbid_prt = 0.0
|
554
|
-
PT_qbid_limit_switch = True # will want to test with False also
|
555
554
|
|
556
555
|
# Input variable values for tests
|
557
556
|
c00100 = [527860.66, 337675.10, 603700.00, 90700.00]
|
@@ -579,7 +578,7 @@ tuple0 = (
|
|
579
578
|
PT_binc_w2_wages[0], PT_ubia_property[0], PT_qbid_rt,
|
580
579
|
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
581
580
|
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[0],
|
582
|
-
PT_qbid_ps, PT_qbid_prt, qbided[0]
|
581
|
+
PT_qbid_ps, PT_qbid_prt, qbided[0])
|
583
582
|
expected0 = (490860.66, 0)
|
584
583
|
tuple1 = (
|
585
584
|
c00100[1], standard[1], c04470[1], c04600[1], MARS[1], e00900[1],
|
@@ -588,7 +587,7 @@ tuple1 = (
|
|
588
587
|
PT_binc_w2_wages[1], PT_ubia_property[1], PT_qbid_rt,
|
589
588
|
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
590
589
|
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[1],
|
591
|
-
PT_qbid_ps, PT_qbid_prt, qbided[1]
|
590
|
+
PT_qbid_ps, PT_qbid_prt, qbided[1])
|
592
591
|
expected1 = (284400.08, 4275.02)
|
593
592
|
tuple2 = (
|
594
593
|
c00100[2], standard[2], c04470[2], c04600[2], MARS[2], e00900[2],
|
@@ -597,7 +596,7 @@ tuple2 = (
|
|
597
596
|
PT_binc_w2_wages[2], PT_ubia_property[2], PT_qbid_rt,
|
598
597
|
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
599
598
|
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[2],
|
600
|
-
PT_qbid_ps, PT_qbid_prt, qbided[2]
|
599
|
+
PT_qbid_ps, PT_qbid_prt, qbided[2])
|
601
600
|
expected2 = (579300.00, 0)
|
602
601
|
tuple3 = (
|
603
602
|
c00100[3], standard[3], c04470[3], c04600[3], MARS[3], e00900[3],
|
@@ -607,7 +606,7 @@ tuple3 = (
|
|
607
606
|
PT_binc_w2_wages[3], PT_ubia_property[3], PT_qbid_rt,
|
608
607
|
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
609
608
|
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[3],
|
610
|
-
PT_qbid_ps, PT_qbid_prt, qbided[3]
|
609
|
+
PT_qbid_ps, PT_qbid_prt, qbided[3])
|
611
610
|
expected3 = (57500.00, 1200)
|
612
611
|
|
613
612
|
|
taxcalc/tests/test_calculator.py
CHANGED
@@ -845,6 +845,7 @@ def test_itemded_component_amounts(year, cvname, hcname, puf_fullsample):
|
|
845
845
|
raise ValueError(msg)
|
846
846
|
|
847
847
|
|
848
|
+
@pytest.mark.qbid
|
848
849
|
def test_qbid_calculation():
|
849
850
|
"""
|
850
851
|
Test Calculator's QBID calculations using the six example filing units
|
@@ -886,42 +887,6 @@ def test_qbid_calculation():
|
|
886
887
|
assert np.allclose(tc_df.qbided, tpc_df.qbid)
|
887
888
|
|
888
889
|
|
889
|
-
def test_qbid_limit_switch():
|
890
|
-
"""
|
891
|
-
Test Calculator's switch to implement wage/capital limitations
|
892
|
-
on QBI deduction.
|
893
|
-
"""
|
894
|
-
cy = 2019
|
895
|
-
ref = {"PT_qbid_limit_switch": {2019: False}}
|
896
|
-
|
897
|
-
# filing unit has $500,000 in wages and $100,000 in QBI. Since
|
898
|
-
# the household is above the taxable income limitation threshold,
|
899
|
-
# with full wage/capital limitations, it does not receive a QBI
|
900
|
-
# deduction. With sufficent wage/capital to avoid the limitation,
|
901
|
-
# the filing unit receives a deduction of:
|
902
|
-
# $100,000 * 20% = $20,000.
|
903
|
-
VARS = 'RECID,MARS,e00200s,e00200p,e00200,e26270,e02000\n'
|
904
|
-
FUNIT = '1,2,250000,250000,500000,100000,100000'
|
905
|
-
|
906
|
-
funit_df = pd.read_csv(StringIO(VARS + FUNIT))
|
907
|
-
recs = Records(data=funit_df, start_year=cy,
|
908
|
-
gfactors=None, weights=None)
|
909
|
-
|
910
|
-
calc_base = Calculator(policy=Policy(), records=recs)
|
911
|
-
calc_base.calc_all()
|
912
|
-
|
913
|
-
qbid_base = calc_base.array('qbided')
|
914
|
-
assert np.equal(qbid_base, 0)
|
915
|
-
|
916
|
-
pol_ref = Policy()
|
917
|
-
pol_ref.implement_reform(ref)
|
918
|
-
calc_ref = Calculator(policy=pol_ref, records=recs)
|
919
|
-
calc_ref.calc_all()
|
920
|
-
|
921
|
-
qbid_ref = calc_ref.array('qbided')
|
922
|
-
assert np.equal(qbid_ref, 20000)
|
923
|
-
|
924
|
-
|
925
890
|
def test_calc_all_benefits_amounts(cps_subsample):
|
926
891
|
'''
|
927
892
|
Testing how benefits are handled in the calc_all method
|
taxcalc/tests/test_taxcalcio.py
CHANGED
@@ -88,7 +88,7 @@ def fixture_reformfile1():
|
|
88
88
|
"II_em": { // personal exemption amount (see indexing changes below)
|
89
89
|
"2016": 6000,
|
90
90
|
"2018": 7500,
|
91
|
-
"
|
91
|
+
"2021": 9000},
|
92
92
|
"II_em-indexed": { // personal exemption amount indexing status
|
93
93
|
"2016": false, // values in future years are same as this year value
|
94
94
|
"2018": true // values in future years indexed with this year as base
|
@@ -1,32 +1,32 @@
|
|
1
|
-
taxcalc/__init__.py,sha256=
|
2
|
-
taxcalc/calcfunctions.py,sha256=
|
3
|
-
taxcalc/calculator.py,sha256=
|
1
|
+
taxcalc/__init__.py,sha256=Le7YP1qsAQ16R7VeiMWC2bpbsC6aiPiO2-a_Ce8gyUc,536
|
2
|
+
taxcalc/calcfunctions.py,sha256=XrEHKMnjOQQHSryk8FXbRDo5Xd8grDgrTJ1q_7DDehQ,146696
|
3
|
+
taxcalc/calculator.py,sha256=6MTDHhXitefwKHwzAQ_7RgPbZDpCWWHTOqWX_bjeA_A,63709
|
4
4
|
taxcalc/conftest.py,sha256=nO4J7qu1sTHgjqrzhpRMvfMJUrNm6GP_IsSuuDt_MeQ,141
|
5
5
|
taxcalc/consumption.json,sha256=D4Iz625yka_LSlq313hoy01qGtNrpN5QYAHqd9QQfVA,8102
|
6
6
|
taxcalc/consumption.py,sha256=IS-pB2I0JW3pdXB0vHvqA14AVnkP-TDNYFMx8MmQYIg,3327
|
7
7
|
taxcalc/cps.csv.gz,sha256=SS6tSduU_Eu0EJwzpslnmqMsQQQucVMzzITfH-SeV40,9851074
|
8
8
|
taxcalc/cps_weights.csv.gz,sha256=T3YcFdlgwQduzc1KklxT9CQXTO6Puj682RHxfFpK4IA,13044422
|
9
|
-
taxcalc/data.py,sha256=
|
9
|
+
taxcalc/data.py,sha256=KnVxSbYUF-wn_ZKCo1EHOLOVVK6ldis8vL_EB8oSR2c,11723
|
10
10
|
taxcalc/decorators.py,sha256=uCZGHrq90k5Gr5YA_1tuWkCMEiOPbqXp6wxCWp6cDfM,11332
|
11
11
|
taxcalc/growdiff.json,sha256=im6mp7NZfpROismsNTjwLLAwIEltZsFfV6EKFEG3dKo,15037
|
12
12
|
taxcalc/growdiff.py,sha256=lW0tvVh2WtOOznf1AdAyDzvB-WLb8sgyogCbAOUqXw0,2905
|
13
13
|
taxcalc/growfactors.csv,sha256=OQArKySPTSweIGV9v17WrenfcQa6ABrbTpIWZUqL2Uk,12281
|
14
|
-
taxcalc/growfactors.py,sha256=
|
14
|
+
taxcalc/growfactors.py,sha256=MNb2XbAV_RbJDjbZp7iMvC6dHabAe97wdbXWEqdAmaQ,6534
|
15
15
|
taxcalc/parameters.py,sha256=57RVKpx0i4J0L6lqdgykakO9ASHx9JnkI2tK7yDmvto,31175
|
16
|
-
taxcalc/policy.py,sha256=
|
17
|
-
taxcalc/policy_current_law.json,sha256=
|
16
|
+
taxcalc/policy.py,sha256=65xHrz5M7OJu7k3M4Zh9WUv6hpe6Qic3c-_OkbZmnEA,6878
|
17
|
+
taxcalc/policy_current_law.json,sha256=eARPB7EpnQgNi5GMX94krF9ZHS_AyTEJjwQljCnkc_Y,658683
|
18
18
|
taxcalc/puf_ratios.csv,sha256=FjEj41SyyW5Fp7JTVptQGKjnu43rfl3uOc9-019bE_s,3439
|
19
19
|
taxcalc/puf_weights.csv.gz,sha256=LouhxTQJ0ow-Yn63PjMElB5ICXO9AybLXeEt3gP5AY4,12988069
|
20
|
-
taxcalc/records.py,sha256=
|
20
|
+
taxcalc/records.py,sha256=deFglkxmHQxtmJ-HCBHLAbLePzgdJjt-qYYNC6jQKfg,18104
|
21
21
|
taxcalc/records_variables.json,sha256=os84mC_BjkdeJffkM1OXFxiJTWztxVgQS6d-GDBHpBk,42903
|
22
|
-
taxcalc/taxcalcio.py,sha256=
|
22
|
+
taxcalc/taxcalcio.py,sha256=axkVEPPuBhmnRGxxnE_4JGcatsqPHhC3_sOnWoYfP2k,34843
|
23
23
|
taxcalc/utils.py,sha256=aNIEYbm37pQoayt_rXrr9iKoodoE-DH8EFL2A0rSokk,62468
|
24
24
|
taxcalc/utilsprvt.py,sha256=iIyWp9-N3_XWjQj2jV2CWnJy7vrNlKB2_vIMwYjgbWY,1323
|
25
25
|
taxcalc/assumptions/ASSUMPTIONS.md,sha256=cFQqWn1nScaladVaQ7xNm1jDY8CsGdLmqZEzUZeRrb8,1917
|
26
26
|
taxcalc/assumptions/README.md,sha256=30lU4iLAI9gm9MgtiJtLIlyYM7YeTjkHcjtp8UDgZZo,806
|
27
27
|
taxcalc/assumptions/economic_assumptions_template.json,sha256=LmJjBD4NIIBQpICAmaD2hAj0q3yOVtybljg1ZnwUwic,2601
|
28
28
|
taxcalc/cli/__init__.py,sha256=cyZ0tdx41j_vV_B6GAkqJmNKKG-B0wUC0ThC75lJlk4,104
|
29
|
-
taxcalc/cli/tc.py,sha256=
|
29
|
+
taxcalc/cli/tc.py,sha256=vk9yr8avP3AG8b8X8IpEZxKMfZ4FacE9XvrwmnKw3yM,12083
|
30
30
|
taxcalc/reforms/2017_law.json,sha256=u-xaPSvt5ubfZw1Nb-jNhTNcOPBUJeAX2kJVoEyMgC4,5860
|
31
31
|
taxcalc/reforms/2017_law.out.csv,sha256=CtaYN_oYuxwaPZyEjB6tkfuCxe6VSc9No1VirFLuGQI,470
|
32
32
|
taxcalc/reforms/ARPA.json,sha256=1H9LuJ_QitXRO9e8R3PWizajJgdioIzbGFdvdlt9FVg,3119
|
@@ -54,7 +54,7 @@ taxcalc/reforms/Trump2017.json,sha256=DZjCJQZYe98Skyss7z_Jhj8HJld_FPZeQGxwzGgQIn
|
|
54
54
|
taxcalc/reforms/Trump2017.out.csv,sha256=SQTnFgXOo2QldcSYourBPiK3GsqZa3S3PHkSXQ2MAsA,474
|
55
55
|
taxcalc/reforms/cases.csv,sha256=JQ0LSnNeyl6xSgW5mimGUJMr7xwCWTOpiOpfwx2ETsg,570
|
56
56
|
taxcalc/reforms/clp.out.csv,sha256=5wFsG1tFqGFLVwtL_jKJVC3uzA3auB_n-IAfb7XX96s,355
|
57
|
-
taxcalc/reforms/ext.json,sha256=
|
57
|
+
taxcalc/reforms/ext.json,sha256=yj1HKhLZ93cXob0yoQlLotrKFwNiAHjdpKSi7nYuA_8,3025
|
58
58
|
taxcalc/reforms/growfactors_ext.csv,sha256=E0szWXtgV5jcpiyvREOz1yXw_poPIBC77bBQI1rlFxM,17733
|
59
59
|
taxcalc/reforms/ptaxes0.json,sha256=QkvqCVkI23sF7FvTHqaUYNpEJYuHNChbKwH0mH7Otp4,1718
|
60
60
|
taxcalc/reforms/ptaxes0.out.csv,sha256=kGn0h67vBzgkEiEhuYjvpspQ-KnndN9gDVVnsIe7S7w,473
|
@@ -84,9 +84,9 @@ taxcalc/tests/pufcsv_mtr_expect.txt,sha256=De-wjocJ8X7fEacaSf7iut5PPCwWWGXPgISb0
|
|
84
84
|
taxcalc/tests/reforms.json,sha256=vGJrvfKJ7h5iAWF-vV9NmY8Z9HP_iereiYiYNcfhBMo,19212
|
85
85
|
taxcalc/tests/reforms_expect.csv,sha256=G28eVkH5KNyFkIKPutEfMidG8sdEXnxSu9QNFCM8Cw4,1468
|
86
86
|
taxcalc/tests/test_4package.py,sha256=xIZ0M9cIe9LVQ1AEgmqKfwiMTH9l4JP1d79Ky9p1mM8,2096
|
87
|
-
taxcalc/tests/test_benefits.py,sha256=
|
88
|
-
taxcalc/tests/test_calcfunctions.py,sha256=
|
89
|
-
taxcalc/tests/test_calculator.py,sha256=
|
87
|
+
taxcalc/tests/test_benefits.py,sha256=cseQyLYxyjBBWJq1yLY0uXzS3FwhIM9oEP4DbZof81M,3387
|
88
|
+
taxcalc/tests/test_calcfunctions.py,sha256=r_6LcQAZBEu6KT-3VJir3rUG0W7GPbhDkIr88dPmb08,31677
|
89
|
+
taxcalc/tests/test_calculator.py,sha256=eSo9c__ublncgjYXHagdeJ9HjlV5ZrlqrE1CPtbi85o,36020
|
90
90
|
taxcalc/tests/test_compare.py,sha256=iYLxopqiKM3H1CHxAbzdi74oydkGb3vq6QgcYVr0qaI,10958
|
91
91
|
taxcalc/tests/test_compatible_data.py,sha256=sG3REUSIL4_yO4JbX3s1pC7SWlvw1gvaswAibB5EiVY,13389
|
92
92
|
taxcalc/tests/test_consumption.py,sha256=14EP69vsMYfLlpZ8UkpN3JSNS54Xp1KvIN5A1fO1k9g,6000
|
@@ -102,7 +102,7 @@ taxcalc/tests/test_pufcsv.py,sha256=FuNwf9dR6sPppuBAYI8EPedMGJ5UjCitpq6eJa9EKsA,
|
|
102
102
|
taxcalc/tests/test_records.py,sha256=CmYLJOH63vlm4K96z6Q1nzb1bK_F_rPKehZ0MFKTI4o,8323
|
103
103
|
taxcalc/tests/test_reforms.py,sha256=HEG8YA_F9lmHX4j_0vWzXtTJZc6l6vt8Nu8cjEIUYDo,15855
|
104
104
|
taxcalc/tests/test_responses.py,sha256=-t0-Yr2X8Y1e1KZ4oF6dlt4Ze5jbn8_JQalAee3KPzk,1625
|
105
|
-
taxcalc/tests/test_taxcalcio.py,sha256
|
105
|
+
taxcalc/tests/test_taxcalcio.py,sha256=-O9uhV2spiUvBN2XUS4kVOUUFCsW6Ynl6XNw4dJSCVo,24979
|
106
106
|
taxcalc/tests/test_utils.py,sha256=sA2ozKkMRbKyCsiXdeYU5K7w2a1us1Cf5pL9a2NmYpk,29139
|
107
107
|
taxcalc/validation/CSV_INPUT_VARS.md,sha256=MqlZZGt_a1n8JAU-nY5MjnTmjz1pMOuhtpVYIGUgl38,1433
|
108
108
|
taxcalc/validation/CSV_OUTPUT_VARS.md,sha256=wr8oyCJDXcxl4Lu0H_wMofUQYhEIyHDif6vkbas1FGE,3000
|
@@ -131,9 +131,9 @@ taxcalc/validation/taxsim35/expected_differences/b21-taxdiffs-expect.csv,sha256=
|
|
131
131
|
taxcalc/validation/taxsim35/expected_differences/c17-taxdiffs-expect.csv,sha256=YhgojbLowH3yujdYu7SGkdvBZmTgpugu4wYc1Be069M,1125
|
132
132
|
taxcalc/validation/taxsim35/expected_differences/c18-taxdiffs-expect.csv,sha256=g9J4BPbTySV-h-RcLvReJq9v1jscgiRSSZzi0taEA-k,1225
|
133
133
|
taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv,sha256=Ceh15N_Xr3L7cpYjzGa-8NLCV3obc8PNHEhE5ZxSPhI,1238
|
134
|
-
taxcalc-4.3.
|
135
|
-
taxcalc-4.3.
|
136
|
-
taxcalc-4.3.
|
137
|
-
taxcalc-4.3.
|
138
|
-
taxcalc-4.3.
|
139
|
-
taxcalc-4.3.
|
134
|
+
taxcalc-4.3.2.dist-info/LICENSE,sha256=m5epLdB-_NXiY7NsEDgcHP4jDtJ4vOlRf5S3Jb-jraY,1299
|
135
|
+
taxcalc-4.3.2.dist-info/METADATA,sha256=hT0IPjp6gznKRBIPPev8X5eIT3CiWMEWtb893zJnnlI,3183
|
136
|
+
taxcalc-4.3.2.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
|
137
|
+
taxcalc-4.3.2.dist-info/entry_points.txt,sha256=a3ZE1piRv683p27fOLdWZvVJXESkoslTOp5iXV7uVco,50
|
138
|
+
taxcalc-4.3.2.dist-info/top_level.txt,sha256=Wh8wTDHkA_cm4dn8IoUCviDyGgVQqwEQKPJnl8z6d4c,8
|
139
|
+
taxcalc-4.3.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|