taxcalc 4.2.2__py3-none-any.whl → 4.3.1__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/records.py CHANGED
@@ -6,6 +6,7 @@ Tax-Calculator tax-filing-unit Records class.
6
6
  # pylint --disable=locally-disabled records.py
7
7
 
8
8
  import os
9
+ from pathlib import Path
9
10
  import numpy as np
10
11
  import pandas as pd
11
12
  from taxcalc.data import Data
@@ -52,7 +53,7 @@ class Records(Data):
52
53
  None creates empty sample-weights DataFrame;
53
54
  default value is filename of the PUF weights.
54
55
  NOTE: when using custom weights, set this argument to a DataFrame.
55
- NOTE: assumes weights are integers that are 100 times the real weights.
56
+ NOTE: see weights_scale documentation below.
56
57
 
57
58
  adjust_ratios: string or Pandas DataFrame or None
58
59
  string describes CSV file in which adjustment ratios reside;
@@ -68,6 +69,13 @@ class Records(Data):
68
69
  any smoothing of stair-step provisions in income tax law;
69
70
  default value is false.
70
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
+
71
79
  Raises
72
80
  ------
73
81
  ValueError:
@@ -116,9 +124,6 @@ class Records(Data):
116
124
  PUF_RATIOS_FILENAME = 'puf_ratios.csv'
117
125
  CPS_WEIGHTS_FILENAME = 'cps_weights.csv.gz'
118
126
  CPS_RATIOS_FILENAME = None
119
- TMD_WEIGHTS_FILENAME = 'tmd_weights.csv.gz'
120
- TMD_GROWFACTORS_FILENAME = 'tmd_growfactors.csv'
121
- TMD_RATIOS_FILENAME = None
122
127
  CODE_PATH = os.path.abspath(os.path.dirname(__file__))
123
128
  VARINFO_FILE_NAME = 'records_variables.json'
124
129
  VARINFO_FILE_PATH = CODE_PATH
@@ -129,11 +134,12 @@ class Records(Data):
129
134
  gfactors=GrowFactors(),
130
135
  weights=PUF_WEIGHTS_FILENAME,
131
136
  adjust_ratios=PUF_RATIOS_FILENAME,
132
- exact_calculations=False):
137
+ exact_calculations=False,
138
+ weights_scale=0.01):
133
139
  # pylint: disable=no-member,too-many-branches
134
140
  if isinstance(weights, str):
135
141
  weights = os.path.join(Records.CODE_PATH, weights)
136
- super().__init__(data, start_year, gfactors, weights)
142
+ super().__init__(data, start_year, gfactors, weights, weights_scale)
137
143
  if data is None:
138
144
  return # because there are no data
139
145
  # read adjustment ratios
@@ -226,9 +232,12 @@ class Records(Data):
226
232
  exact_calculations=exact_calculations)
227
233
 
228
234
  @staticmethod
229
- def tmd_constructor(data, # path to tmd.csv file or dataframe
230
- gfactors=GrowFactors(TMD_GROWFACTORS_FILENAME),
231
- exact_calculations=False): # pragma: no cover
235
+ def tmd_constructor(
236
+ data_path: Path,
237
+ weights_path: Path,
238
+ growfactors_path: Path,
239
+ exact_calculations=False,
240
+ ): # pragma: no cover
232
241
  """
233
242
  Static method returns a Records object instantiated with TMD
234
243
  input data. This works in a analogous way to Records(), which
@@ -239,14 +248,19 @@ class Records(Data):
239
248
  eliminate the need to specify all the details of the PUF input
240
249
  data.
241
250
  """
242
- weights = os.path.join(Records.CODE_PATH, Records.TMD_WEIGHTS_FILENAME)
243
- return Records(data=data,
244
- start_year=Records.TMDCSV_YEAR,
245
- gfactors=gfactors,
246
- weights=weights,
247
- adjust_ratios=Records.TMD_RATIOS_FILENAME,
248
- exact_calculations=exact_calculations)
249
-
251
+ assert isinstance(data_path, Path)
252
+ assert isinstance(weights_path, Path)
253
+ assert isinstance(growfactors_path, Path)
254
+ return Records(
255
+ data=pd.read_csv(data_path),
256
+ start_year=Records.TMDCSV_YEAR,
257
+ weights=pd.read_csv(weights_path),
258
+ gfactors=GrowFactors(growfactors_filename=str(growfactors_path)),
259
+ adjust_ratios=None,
260
+ exact_calculations=exact_calculations,
261
+ weights_scale=1.0,
262
+ )
263
+
250
264
  def increment_year(self):
251
265
  """
252
266
  Add one to current year, and also does
@@ -277,7 +291,7 @@ class Records(Data):
277
291
  """
278
292
  # pylint: disable=too-many-statements,no-member
279
293
  # put values in local dictionary
280
- gfv = dict()
294
+ gfv = {}
281
295
  for name in GrowFactors.VALID_NAMES:
282
296
  gfv[name] = self.gfactors.factor_value(name, year)
283
297
  # apply values to Records variables
taxcalc/reforms/ext.json CHANGED
@@ -1,31 +1,32 @@
1
1
  // REFORM TO EXTEND TEMPORARY TCJA PROVISIONS BEYOND 2025
2
- // USING TAX-CALCULATOR 3.5.3
2
+ // USING TAX-CALCULATOR 4.3.1
3
3
  // WITH 2025-to-2026 INDEXING FACTOR = 1.022000
4
+ // AND 2028-to-2029 INDEXING FACTOR = 1.019400
4
5
  {
5
6
  "II_rt1": {"2026": 0.10},
6
- "II_brk1": {"2026": [12170.98, 24341.94, 12170.98, 17353.27, 24341.94]},
7
+ "II_brk1": {"2026": [12157.51, 24315.02, 12157.51, 17345.41, 24315.02]},
7
8
  "PT_rt1": {"2026": 0.10},
8
- "PT_brk1": {"2026": [12170.98, 24341.94, 12170.98, 17353.27, 24341.94]},
9
+ "PT_brk1": {"2026": [12157.51, 24315.02, 12157.51, 17345.41, 24315.02]},
9
10
  "II_rt2": {"2026": 0.12},
10
- "II_brk2": {"2026": [49483.44, 98966.89, 49483.44, 66214.83, 98966.89]},
11
+ "II_brk2": {"2026": [49416.07, 98832.15, 49416.07, 66132.65, 98832.15]},
11
12
  "PT_rt2": {"2026": 0.12},
12
- "PT_brk2": {"2026": [49483.44, 98966.89, 49483.44, 66214.83, 98966.89]},
13
+ "PT_brk2": {"2026": [49416.07, 98832.15, 49416.07, 66132.65, 98832.15]},
13
14
  "II_rt3": {"2026": 0.22},
14
- "II_brk3": {"2026": [105511.38, 211022.75, 105511.38, 105481.77, 211022.75]},
15
+ "II_brk3": {"2026": [105356.33, 210712.67, 105356.33, 105330.13, 210712.67]},
15
16
  "PT_rt3": {"2026": 0.22},
16
- "PT_brk3": {"2026": [105511.38, 211022.75, 105511.38, 105481.77, 211022.75]},
17
+ "PT_brk3": {"2026": [105356.33, 210712.67, 105356.33, 105330.13, 210712.67]},
17
18
  "II_rt4": {"2026": 0.24},
18
- "II_brk4": {"2026": [201428.14, 402856.25, 201428.14, 201428.14, 402856.25]},
19
+ "II_brk4": {"2026": [201175.3, 402350.62, 201175.3, 201175.3, 402350.62]},
19
20
  "PT_rt4": {"2026": 0.24},
20
- "PT_brk4": {"2026": [201428.14, 402856.25, 201428.14, 201428.14, 402856.25]},
21
+ "PT_brk4": {"2026": [201175.3, 402350.62, 201175.3, 201175.3, 402350.62]},
21
22
  "II_rt5": {"2026": 0.32},
22
- "II_brk5": {"2026": [255797.72, 511595.46, 255797.72, 255797.72, 511595.46]},
23
+ "II_brk5": {"2026": [255438.67, 510877.34, 255438.67, 255412.47, 510877.34]},
23
24
  "PT_rt5": {"2026": 0.32},
24
- "PT_brk5": {"2026": [255797.72, 511595.46, 255797.72, 255797.72, 511595.46]},
25
+ "PT_brk5": {"2026": [255438.67, 510877.34, 255438.67, 255412.47, 510877.34]},
25
26
  "II_rt6": {"2026": 0.35},
26
- "II_brk6": {"2026": [639523.94, 767393.2, 383696.6, 639523.94, 767393.2]},
27
+ "II_brk6": {"2026": [638635.98, 766342.2, 383171.1, 638635.98, 766342.2]},
27
28
  "PT_rt6": {"2026": 0.35},
28
- "PT_brk6": {"2026": [639523.94, 767393.2, 383696.6, 639523.94, 767393.2]},
29
+ "PT_brk6": {"2026": [638635.98, 766342.2, 383171.1, 638635.98, 766342.2]},
29
30
  "II_rt7": {"2026": 0.37},
30
31
  "II_brk7": {"2026": [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]},
31
32
  "PT_rt7": {"2026": 0.37},
@@ -35,10 +36,10 @@
35
36
  "ODC_c": {"2026": 500.00},
36
37
  "CTC_ps": {"2026": [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]},
37
38
  "ACTC_Income_thd": {"2026": 2500.00},
38
- "AMT_em": {"2026": [89905.29, 139892.17, 69946.08, 89905.29, 139892.17]},
39
- "AMT_em_ps": {"2026": [639523.94, 1279047.88, 639523.94, 639523.94, 1279047.88]},
40
- "AMT_em_pe": {"2026": 939533.04},
41
- "STD": {"2026": [15339.57, 30679.14, 15339.57, 22979.74, 30679.14]},
39
+ "AMT_em": {"2026": [89818.83, 139706.53, 69853.27, 89818.83, 139706.53]},
40
+ "AMT_em_ps": {"2026": [638635.98, 1277271.94, 638635.98, 638635.98, 1277271.94]},
41
+ "AMT_em_pe": {"2026": 938246.12},
42
+ "STD": {"2026": [15301.69, 30603.38, 15301.69, 22952.54, 30603.38]},
42
43
  "ID_AllTaxes_c": {"2026": [10000.0, 10000.0, 5000.0, 10000.0, 10000.0]},
43
44
  "ID_Charity_crt_cash": {"2026": 0.60},
44
45
  "ID_Casualty_hc": {"2026": 1.00},
@@ -49,11 +50,10 @@
49
50
  "II_em": {"2026": 0.00},
50
51
  "II_em_ps": {"2026": [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]},
51
52
  "PT_qbid_rt": {"2026": 0.20},
52
- "PT_qbid_taxinc_thd": {"2026": [201428.14, 402856.25, 201428.14, 201428.14, 402856.25]},
53
+ "PT_qbid_taxinc_thd": {"2026": [201175.3, 402350.62, 201175.3, 201175.3, 201175.3]},
53
54
  "PT_qbid_taxinc_gap": {"2026": [50000.0, 100000.0, 50000.0, 50000.0, 100000.0]},
54
55
  "PT_qbid_w2_wages_rt": {"2026": 0.50},
55
56
  "PT_qbid_alt_w2_wages_rt": {"2026": 0.25},
56
57
  "PT_qbid_alt_property_rt": {"2026": 0.03},
57
- "ALD_BusinessLosses_c": {"2026": [319821.19, 639642.39, 319821.19, 319821.19, 639642.39]},
58
- "ALD_DomesticProduction_hc": {"2026": 1.00}
58
+ "ALD_BusinessLosses_c": {"2029": [339091.08, 678182.18, 339091.08, 339091.08, 678182.18]}
59
59
  }
taxcalc/taxcalcio.py CHANGED
@@ -74,6 +74,8 @@ class TaxCalcIO():
74
74
  self.puf_input_data = False
75
75
  self.cps_input_data = False
76
76
  self.tmd_input_data = False
77
+ self.tmd_weights = None
78
+ self.tmd_gfactor = None
77
79
  if isinstance(input_data, str):
78
80
  # remove any leading directory path from INPUT filename
79
81
  fname = os.path.basename(input_data)
@@ -90,6 +92,23 @@ class TaxCalcIO():
90
92
  if not self.cps_input_data and not os.path.isfile(input_data):
91
93
  msg = 'INPUT file could not be found'
92
94
  self.errmsg += 'ERROR: {}\n'.format(msg)
95
+ # if tmd_input_data is True, construct weights and gfactor paths
96
+ if self.tmd_input_data: # pragma: no cover
97
+ tmd_dir = os.path.dirname(input_data)
98
+ if 'TMD_AREA' in os.environ:
99
+ area = os.environ['TMD_AREA']
100
+ wfile = f'{area}_tmd_weights.csv.gz'
101
+ inp = f'{fname[:-4]}_{area}-{str(tax_year)[2:]}'
102
+ else: # using national weights
103
+ wfile = 'tmd_weights.csv.gz'
104
+ self.tmd_weights = os.path.join(tmd_dir, wfile)
105
+ self.tmd_gfactor = os.path.join(tmd_dir, 'tmd_growfactors.csv')
106
+ if not os.path.isfile(self.tmd_weights):
107
+ msg = f'weights file {self.tmd_weights} could not be found'
108
+ self.errmsg += 'ERROR: {}\n'.format(msg)
109
+ if not os.path.isfile(self.tmd_gfactor):
110
+ msg = f'gfactor file {self.tmd_gfactor} could not be found'
111
+ self.errmsg += 'ERROR: {}\n'.format(msg)
93
112
  elif isinstance(input_data, pd.DataFrame):
94
113
  inp = 'df-{}'.format(str(tax_year)[2:])
95
114
  else:
@@ -123,7 +142,7 @@ class TaxCalcIO():
123
142
  elif isinstance(reform, str):
124
143
  self.specified_reform = True
125
144
  # split any compound reform into list of simple reforms
126
- refnames = list()
145
+ refnames = []
127
146
  reforms = reform.split('+')
128
147
  for rfm in reforms:
129
148
  # remove any leading directory path from rfm filename
@@ -206,7 +225,7 @@ class TaxCalcIO():
206
225
  self.calc = None
207
226
  self.calc_base = None
208
227
  self.param_dict = None
209
- self.policy_dicts = list()
228
+ self.policy_dicts = []
210
229
 
211
230
  def init(self, input_data, tax_year, baseline, reform, assump,
212
231
  aging_input_data, exact_calculations):
@@ -234,7 +253,7 @@ class TaxCalcIO():
234
253
  # get assumption sub-dictionaries
235
254
  paramdict = Calculator.read_json_param_objects(None, assump)
236
255
  # get policy parameter dictionaries from --reform file(s)
237
- policydicts = list()
256
+ policydicts = []
238
257
  if self.specified_reform:
239
258
  reforms = reform.split('+')
240
259
  for ref in reforms:
@@ -252,9 +271,7 @@ class TaxCalcIO():
252
271
  self.errmsg += valerr_msg.__str__()
253
272
  # create GrowFactors base object that incorporates gdiff_baseline
254
273
  if self.tmd_input_data:
255
- gfactors_base = GrowFactors( # pragma: no cover
256
- Records.TMD_GROWFACTORS_FILENAME
257
- )
274
+ gfactors_base = GrowFactors(self.tmd_gfactor) # pragma: no cover
258
275
  else:
259
276
  gfactors_base = GrowFactors()
260
277
  gdiff_baseline.apply_to(gfactors_base)
@@ -266,9 +283,7 @@ class TaxCalcIO():
266
283
  self.errmsg += valerr_msg.__str__()
267
284
  # create GrowFactors ref object that has all gdiff objects applied
268
285
  if self.tmd_input_data:
269
- gfactors_ref = GrowFactors( # pragma: no cover
270
- Records.TMD_GROWFACTORS_FILENAME
271
- )
286
+ gfactors_ref = GrowFactors(self.tmd_gfactor) # pragma: no cover
272
287
  else:
273
288
  gfactors_ref = GrowFactors()
274
289
  gdiff_baseline.apply_to(gfactors_ref)
@@ -332,18 +347,27 @@ class TaxCalcIO():
332
347
  gfactors=gfactors_base,
333
348
  exact_calculations=exact_calculations
334
349
  )
335
- elif self.tmd_input_data:
336
- recs = Records.tmd_constructor(
337
- data=input_data,
350
+ elif self.tmd_input_data: # pragma: no cover
351
+ wghts = pd.read_csv(self.tmd_weights)
352
+ recs = Records(
353
+ data=pd.read_csv(input_data),
354
+ start_year=Records.TMDCSV_YEAR,
355
+ weights=wghts,
338
356
  gfactors=gfactors_ref,
339
- exact_calculations=exact_calculations
340
- ) # pragma: no cover
341
- recs_base = Records.tmd_constructor(
342
- data=input_data,
357
+ adjust_ratios=None,
358
+ exact_calculations=exact_calculations,
359
+ weights_scale=1.0,
360
+ )
361
+ recs_base = Records(
362
+ data=pd.read_csv(input_data),
363
+ start_year=Records.TMDCSV_YEAR,
364
+ weights=wghts,
343
365
  gfactors=gfactors_base,
344
- exact_calculations=exact_calculations
345
- ) # pragma: no cover
346
- else: # if not {cps|tmd}_input_data but aging_input_data
366
+ adjust_ratios=None,
367
+ exact_calculations=exact_calculations,
368
+ weights_scale=1.0,
369
+ )
370
+ else: # if not {cps|tmd}_input_data but aging_input_data: puf
347
371
  recs = Records(
348
372
  data=input_data,
349
373
  gfactors=gfactors_ref,
@@ -526,8 +550,17 @@ class TaxCalcIO():
526
550
  outdf = self.minimal_output()
527
551
  column_order = outdf.columns
528
552
  assert len(outdf.index) == self.calc.array_len
529
- outdf.to_csv(self._output_filename, columns=column_order,
530
- index=False, float_format='%.2f')
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')
531
564
  del outdf
532
565
  gc.collect()
533
566
 
@@ -541,7 +574,7 @@ class TaxCalcIO():
541
574
  doc = Calculator.reform_documentation(self.param_dict,
542
575
  self.policy_dicts[1:])
543
576
  doc_fname = self._output_filename.replace('.csv', '-doc.text')
544
- with open(doc_fname, 'w') as dfile:
577
+ with open(doc_fname, 'w', encoding='utf-8') as dfile:
545
578
  dfile.write(doc)
546
579
 
547
580
  def write_sqldb_file(self, dump_varset, mtr_paytax, mtr_inctax,
@@ -575,7 +608,7 @@ class TaxCalcIO():
575
608
  tab_fname = self._output_filename.replace('.csv', '-tab.text')
576
609
  # skip tables if there are not some positive weights
577
610
  if self.calc_base.total_weight() <= 0.:
578
- with open(tab_fname, 'w') as tfile:
611
+ with open(tab_fname, 'w', encoding='utf-8') as tfile:
579
612
  msg = 'No tables because sum of weights is not positive\n'
580
613
  tfile.write(msg)
581
614
  return
@@ -597,7 +630,7 @@ class TaxCalcIO():
597
630
  diff = nontax + change # using expanded_income under baseline policy
598
631
  diffdf = pd.DataFrame(data=np.column_stack(diff), columns=all_vars)
599
632
  # write each kind of distributional table
600
- with open(tab_fname, 'w') as tfile:
633
+ with open(tab_fname, 'w', encoding='utf-8') as tfile:
601
634
  TaxCalcIO.write_decile_table(distdf, tfile, tkind='Reform Totals')
602
635
  tfile.write('\n')
603
636
  TaxCalcIO.write_decile_table(diffdf, tfile, tkind='Differences')
@@ -730,7 +763,7 @@ class TaxCalcIO():
730
763
  '<head><title>{}</title></head>\n'
731
764
  '<body><center<h1>{}</h1></center></body>\n'
732
765
  '</html>\n').format(title, reason)
733
- with open(fname, 'w') as gfile:
766
+ with open(fname, 'w', encoding='utf-8') as gfile:
734
767
  gfile.write(txt)
735
768
 
736
769
  def minimal_output(self):
@@ -738,7 +771,7 @@ class TaxCalcIO():
738
771
  Extract minimal output and return it as Pandas DataFrame.
739
772
  """
740
773
  varlist = ['RECID', 'YEAR', 'WEIGHT', 'INCTAX', 'LSTAX', 'PAYTAX']
741
- odict = dict()
774
+ odict = {}
742
775
  scalc = self.calc
743
776
  odict['RECID'] = scalc.array('RECID') # id for tax filing unit
744
777
  odict['YEAR'] = self.tax_year() # tax calculation year
@@ -764,8 +797,8 @@ class TaxCalcIO():
764
797
  vardata = calcx.array(varname)
765
798
  if varname in recs_vinfo.INTEGER_VARS:
766
799
  odf[varname] = vardata
767
- else:
768
- odf[varname] = vardata.round(2) # rounded to nearest cent
800
+ else: # specify precision that can handle small TMD area weights
801
+ odf[varname] = vardata.round(5)
769
802
  odf = odf.copy()
770
803
  # specify mtr values in percentage terms
771
804
  if 'mtr_inctax' in varset:
@@ -1,26 +1,26 @@
1
1
  ,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026
2
2
  Returns (#m),187.1,199.2,201.9,204.5,207.1,209.7,212.3,214.9,217.5,220.1
3
- AGI ($b),9087.6,10714.8,11167.0,11573.2,13174.9,13543.8,14390.3,15077.5,15785.3,16457.7
4
- Itemizers (#m),62.8,23.9,25.0,27.5,31.2,31.2,29.8,29.4,30.4,81.1
5
- Itemized Deduction ($b),1218.6,612.0,655.1,745.4,862.7,881.9,887.6,913.8,963.1,2180.7
6
- Standard Deduction Filers (#m),124.3,175.3,176.9,176.9,175.8,178.5,182.5,185.5,187.2,139.1
7
- Standard Deduction ($b),1092.1,2951.3,3026.1,3080.8,3091.9,3231.4,3549.4,3806.5,3937.8,1613.3
8
- Personal Exemption ($b),1383.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2081.6
9
- Taxable Income ($b),6230.6,7959.2,8322.8,8615.4,10049.9,10332.2,10948.3,11426.3,11990.0,11782.5
10
- Regular Tax ($b),1108.0,1380.0,1449.0,1497.4,1762.8,1837.4,1937.4,2016.4,2123.2,2339.6
11
- AMT Income ($b),8319.8,10212.6,10630.3,10965.7,12473.9,12821.8,13658.8,14318.8,14984.7,15074.1
12
- AMT Liability ($b),8.1,0.4,0.4,0.5,1.4,0.7,0.7,0.6,0.6,17.2
3
+ AGI ($b),9087.6,10714.8,11167.0,11573.2,13174.9,13543.8,14390.3,15077.5,15785.2,16487.0
4
+ Itemizers (#m),62.8,23.9,25.0,27.5,31.2,31.2,30.0,29.6,30.6,81.1
5
+ Itemized Deduction ($b),1218.6,612.0,655.1,745.4,862.7,881.9,891.8,917.9,968.3,2181.6
6
+ Standard Deduction Filers (#m),124.3,175.3,176.9,176.9,175.8,178.5,182.3,185.3,186.9,139.0
7
+ Standard Deduction ($b),1092.1,2951.3,3026.1,3080.8,3091.9,3231.4,3534.5,3791.7,3921.6,1610.3
8
+ Personal Exemption ($b),1383.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2081.5
9
+ Taxable Income ($b),6230.6,7959.2,8322.8,8615.4,10049.9,10332.2,10954.0,11432.4,11996.4,11810.2
10
+ Regular Tax ($b),1108.0,1380.0,1449.0,1497.4,1762.8,1837.4,1939.0,2018.1,2125.0,2347.7
11
+ AMT Income ($b),8319.8,10212.6,10630.3,10965.7,12473.9,12821.8,13655.8,14315.8,14980.8,15102.6
12
+ AMT Liability ($b),8.1,0.4,0.4,0.5,1.4,0.7,0.7,0.6,0.6,17.1
13
13
  AMT Filers (#m),2.6,0.1,0.1,0.1,0.2,0.1,0.1,0.1,0.1,4.1
14
- Tax before Credits ($b),1116.0,1380.4,1449.4,1497.9,1764.3,1838.0,1938.1,2017.0,2123.8,2356.8
15
- Refundable Credits ($b),70.8,102.5,102.7,655.0,827.1,98.5,106.4,111.6,112.1,97.7
16
- Nonrefundable Credits ($b),32.7,97.2,99.2,99.2,0.0,107.7,108.3,109.3,111.2,29.9
14
+ Tax before Credits ($b),1116.0,1380.4,1449.4,1497.9,1764.3,1838.0,1939.7,2018.7,2125.6,2364.9
15
+ Refundable Credits ($b),70.8,102.5,102.7,655.0,827.1,98.5,106.2,111.4,111.9,97.5
16
+ Nonrefundable Credits ($b),32.7,97.2,99.2,99.2,0.0,107.7,108.4,109.4,111.3,30.0
17
17
  Reform Surtaxes ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
18
18
  Other Taxes ($b),5.5,10.7,11.3,12.6,13.9,14.4,16.5,17.6,18.8,19.9
19
- Ind Income Tax ($b),1018.1,1191.4,1258.9,756.3,951.0,1646.2,1740.0,1813.7,1919.2,2249.0
20
- Payroll Taxes ($b),1040.8,1141.6,1194.9,1217.9,1318.7,1421.6,1506.7,1582.0,1656.7,1730.7
21
- Combined Liability ($b),2059.0,2333.0,2453.8,1974.2,2269.7,3067.8,3246.6,3395.7,3575.9,3979.7
22
- With Income Tax <= 0 (#m),88.1,96.2,97.0,135.4,127.8,96.1,97.9,99.2,99.6,97.4
23
- With Combined Tax <= 0 (#m),62.8,65.4,66.4,98.2,97.7,67.9,69.3,70.5,71.3,70.7
19
+ Ind Income Tax ($b),1018.1,1191.4,1258.9,756.3,951.0,1646.2,1741.7,1815.6,1921.2,2257.4
20
+ Payroll Taxes ($b),1040.8,1141.6,1194.9,1217.9,1318.7,1421.6,1509.2,1585.1,1659.9,1734.1
21
+ Combined Liability ($b),2059.0,2333.0,2453.8,1974.2,2269.7,3067.8,3250.9,3400.7,3581.1,3991.5
22
+ With Income Tax <= 0 (#m),88.1,96.2,97.0,135.4,127.8,96.1,97.8,99.1,99.5,97.3
23
+ With Combined Tax <= 0 (#m),62.8,65.4,66.4,98.2,97.7,67.9,69.3,70.4,71.3,70.6
24
24
  UBI Benefits ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
25
25
  "Total Benefits, Consumption Value ($b)",2790.7,3225.5,3429.9,3617.0,3993.0,4069.6,4390.5,4696.3,4983.2,5266.5
26
26
  Total Benefits Cost ($b),2790.7,3225.5,3429.9,3617.0,3993.0,4069.6,4390.5,4696.3,4983.2,5266.5
@@ -1,10 +1,10 @@
1
1
  ,description,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034
2
- c00100,Federal AGI, 50840, 54457, 54942, 55071, 58024, 60318, 61591, 63130, 73017, 72224, 75917, 77963, 80251, 82363, 84515, 86850, 89344, 91950, 94677, 98306, 99812, 102616
2
+ c00100,Federal AGI, 50840, 54457, 54942, 55071, 58024, 60318, 61591, 63130, 73017, 72224, 75916, 77963, 80250, 82362, 84514, 86849, 89344, 91950, 94677, 98306, 99812, 102616
3
3
  c02500,OASDI benefits in AGI, 1295, 1394, 1416, 1479, 1501, 1587, 1690, 1832, 2005, 2129, 2428, 2659, 2844, 3028, 3214, 3413, 3619, 3833, 4055, 4308, 4459, 4698
4
4
  c04470,Post-phase-out itemized deduction, 5908, 6037, 6150, 6383, 6563, 6803, 7011, 7493, 7881, 8018, 8324, 8672, 8950, 9288, 9614, 9940, 10266, 10611, 10970, 11450, 11641, 12004
5
5
  c04600,Post-phase-out personal exemption, 7105, 7131, 7163, 7217, 7149, 7247, 7380, 7471, 7481, 7806, 8373, 8834, 9054, 9248, 9434, 9612, 9797, 9988, 10186, 10398, 10579, 10791
6
- c04800,Federal regular taxable income, 35753, 39297, 39663, 39591, 42568, 44523, 45416, 46476, 55959, 54603, 57322, 58386, 60072, 61575, 63147, 64912, 66832, 68828, 70916, 73686, 74836, 76970
7
- c05200,Regular tax on taxable income, 7671, 8731, 8725, 8584, 9499, 10001, 10138, 10475, 13361, 12576, 13165, 13230, 13561, 13847, 14165, 14544, 14965, 15398, 15840, 16404, 16817, 17279
6
+ c04800,Federal regular taxable income, 35753, 39297, 39663, 39591, 42568, 44523, 45416, 46476, 55959, 54603, 57321, 58385, 60072, 61575, 63147, 64911, 66831, 68828, 70916, 73686, 74835, 76970
7
+ c05200,Regular tax on taxable income, 7671, 8731, 8725, 8584, 9499, 10001, 10138, 10475, 13361, 12576, 13165, 13230, 13561, 13847, 14165, 14544, 14965, 15398, 15840, 16404, 16816, 17278
8
8
  c07180,Child care credit, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 16
9
9
  c07220,Child tax credit (adjusted), 158, 155, 147, 143, 139, 134, 129, 124, 359, 116, 107, 101, 97, 94, 91, 88, 85, 82, 80, 77, 74, 72
10
10
  c09600,Federal AMT liability, 212, 227, 240, 251, 268, 280, 288, 317, 351, 339, 347, 357, 371, 387, 400, 415, 430, 446, 458, 487, 496, 513
@@ -67,7 +67,7 @@ e87530,Adjusted qualified lifetime learning expenses for all students, 93,
67
67
  eitc,Federal EITC, 376, 369, 364, 352, 342, 340, 341, 347, 324, 335, 363, 385, 391, 395, 399, 403, 407, 411, 417, 425, 429, 436
68
68
  elderly_dependents,number of dependents age 65+ in filing unit excluding taxpayer and spouse, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
69
69
  g20500,Itemizable gross (before 10% AGI disregard) casualty or theft loss, 29, 30, 31, 32, 33, 35, 36, 38, 40, 41, 42, 44, 47, 48, 50, 52, 55, 57, 60, 63, 62, 66
70
- iitax,Federal income tax liability, 6550, 7474, 7521, 7477, 8281, 8755, 8952, 6544, 9149, 11189, 11708, 11835, 12204, 12533, 12876, 13267, 13691, 14122, 14560, 15122, 15521, 15974
70
+ iitax,Federal income tax liability, 6550, 7474, 7521, 7477, 8281, 8755, 8952, 6544, 9149, 11189, 11708, 11835, 12203, 12533, 12876, 13267, 13691, 14122, 14560, 15122, 15521, 15974
71
71
  k1bx14p,Partner self-employment earnings/loss for taxpayer (included in e26270 total), -213, -239, -187, -162, -144, -139, -133, -129, -156, -168, -183, -181, -178, -175, -168, -158, -146, -124, -103, -67, -149, -123
72
72
  k1bx14s,Partner self-employment earnings/loss for spouse (included in e26270 total), -7, -9, 0, 2, 8, 10, 11, 11, 13, 14, 14, 14, 15, 16, 18, 21, 25, 27, 31, 34, 28, 33
73
73
  nu06,Number of dependents under 6 years old, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -75,6 +75,6 @@ nu13,Number of dependents under 13 years old, 0, 0, 0, 0
75
75
  p08000,Other tax credits (but not including Sch R credit), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
76
76
  p22250,Sch D: Net short-term capital gains/losses, -120, -173, -172, -151, -195, -212, -202, -267, -481, -308, -330, -304, -299, -292, -288, -288, -290, -293, -284, -286, -326, -335
77
77
  p23250,Sch D: Net long-term capital gains/losses, 2284, 3191, 3138, 2776, 3680, 3912, 3596, 4616, 8212, 5153, 5389, 4987, 4839, 4662, 4598, 4612, 4669, 4756, 4864, 5023, 5090, 5224
78
- payrolltax,Payroll taxes (ee+er) for OASDI+HI, 5193, 5382, 5440, 5516, 5676, 5834, 6009, 6042, 6437, 6824, 7146, 7406, 7654, 7894, 8123, 8356, 8597, 8851, 9119, 9479, 9575, 9841
78
+ payrolltax,Payroll taxes (ee+er) for OASDI+HI, 5193, 5382, 5440, 5516, 5676, 5834, 6009, 6042, 6437, 6824, 7161, 7425, 7674, 7914, 8144, 8377, 8619, 8873, 9142, 9503, 9599, 9866
79
79
  pencon_p,Contributions to defined-contribution pension plans for taxpayer, 856, 897, 916, 941, 963, 996, 1029, 1030, 1107, 1185, 1239, 1282, 1326, 1368, 1408, 1448, 1491, 1532, 1578, 1638, 1655, 1698
80
80
  pencon_s,Contributions to defined-contribution pension plans for spouse, 393, 410, 421, 424, 440, 452, 466, 466, 500, 535, 558, 577, 595, 612, 629, 645, 661, 678, 695, 720, 738, 756
@@ -1,26 +1,26 @@
1
1
  ,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026
2
2
  Returns (#m),190.9,194.3,197.3,200.1,202.9,205.6,208.4,211.2,214.0,216.8
3
- AGI ($b),11078.7,11816.6,12247.2,12722.3,14930.0,14973.9,15955.0,16597.5,17310.2,17852.5
4
- Itemizers (#m),45.7,19.4,20.0,21.0,22.6,22.8,21.6,21.1,21.2,51.9
5
- Itemized Deduction ($b),1274.3,602.7,633.9,692.3,761.9,782.7,786.5,805.6,831.9,2047.9
6
- Standard Deduction Filers (#m),145.2,174.8,177.2,178.5,179.6,182.8,186.8,190.0,192.8,164.8
7
- Standard Deduction ($b),1239.3,2865.3,2954.5,3025.8,3081.1,3234.0,3549.8,3811.2,3966.7,1856.2
8
- Personal Exemption ($b),1365.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1959.2
9
- Taxable Income ($b),8112.2,9179.2,9520.5,9907.3,12003.2,11927.7,12692.4,13124.8,13697.6,13377.8
10
- Regular Tax ($b),1656.8,1712.3,1778.2,1838.3,2281.5,2282.7,2421.7,2488.0,2599.2,2792.6
11
- AMT Income ($b),10512.4,11343.5,11749.7,12180.1,14330.8,14356.1,15324.3,15944.7,16632.8,16934.0
12
- AMT Liability ($b),51.3,22.1,23.0,25.1,27.8,27.4,28.8,30.3,31.8,85.1
3
+ AGI ($b),11078.7,11816.6,12247.2,12722.3,14930.0,14973.9,15955.0,16597.4,17310.1,18001.3
4
+ Itemizers (#m),45.7,19.4,20.0,21.0,22.6,22.8,21.7,21.2,21.3,52.0
5
+ Itemized Deduction ($b),1274.3,602.7,633.9,692.3,761.9,782.7,788.7,808.1,835.2,2047.5
6
+ Standard Deduction Filers (#m),145.2,174.8,177.2,178.5,179.6,182.8,186.7,190.0,192.6,164.8
7
+ Standard Deduction ($b),1239.3,2865.3,2954.5,3025.8,3081.1,3234.0,3537.5,3798.4,3952.6,1853.9
8
+ Personal Exemption ($b),1365.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1959.0
9
+ Taxable Income ($b),8112.2,9179.2,9520.5,9907.3,12003.2,11927.7,12697.8,13130.7,13703.8,13460.3
10
+ Regular Tax ($b),1656.8,1712.3,1778.2,1838.3,2281.5,2282.7,2423.4,2489.9,2601.1,2816.2
11
+ AMT Income ($b),10512.4,11343.5,11749.7,12180.1,14330.8,14356.1,15323.1,15943.0,16630.5,17082.5
12
+ AMT Liability ($b),51.3,22.1,23.0,25.1,27.8,27.4,28.8,30.3,31.8,87.9
13
13
  AMT Filers (#m),5.7,0.2,0.2,0.3,0.4,0.3,0.3,0.3,0.3,7.4
14
- Tax before Credits ($b),1708.1,1734.4,1801.1,1863.4,2309.4,2310.1,2450.5,2518.3,2631.0,2877.6
15
- Refundable Credits ($b),102.9,117.5,118.5,642.0,802.6,119.2,127.0,133.0,135.2,121.9
16
- Nonrefundable Credits ($b),67.0,127.3,129.2,128.5,47.6,141.0,143.3,143.9,145.7,77.7
14
+ Tax before Credits ($b),1708.1,1734.4,1801.1,1863.4,2309.4,2310.1,2452.2,2520.2,2632.9,2904.0
15
+ Refundable Credits ($b),102.9,117.5,118.5,642.0,802.6,119.2,126.9,132.8,135.0,121.7
16
+ Nonrefundable Credits ($b),67.0,127.3,129.2,128.5,47.6,141.0,143.3,144.0,145.7,77.7
17
17
  Reform Surtaxes ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
18
- Other Taxes ($b),40.0,44.8,43.6,52.9,84.9,61.5,66.5,65.2,66.0,64.2
19
- Ind Income Tax ($b),1578.2,1534.3,1597.0,1145.8,1544.0,2111.5,2246.7,2306.7,2416.1,2742.2
20
- Payroll Taxes ($b),1083.8,1133.3,1185.4,1209.0,1306.0,1403.4,1489.3,1563.9,1637.9,1711.0
21
- Combined Liability ($b),2662.0,2667.7,2782.4,2354.8,2850.0,3514.9,3736.0,3870.6,4054.0,4453.2
22
- With Income Tax <= 0 (#m),92.8,98.6,99.7,131.7,125.0,100.3,101.9,103.4,104.4,101.0
23
- With Combined Tax <= 0 (#m),63.4,65.6,66.8,102.1,94.5,68.9,70.2,71.6,72.6,72.4
18
+ Other Taxes ($b),40.0,44.8,43.6,52.9,84.9,61.5,66.5,65.2,66.0,66.3
19
+ Ind Income Tax ($b),1578.2,1534.3,1597.0,1145.8,1544.0,2111.5,2248.5,2308.6,2418.2,2770.9
20
+ Payroll Taxes ($b),1083.8,1133.3,1185.4,1209.0,1306.0,1403.4,1492.6,1568.0,1642.1,1715.4
21
+ Combined Liability ($b),2662.0,2667.7,2782.4,2354.8,2850.0,3514.9,3741.1,3876.6,4060.3,4486.3
22
+ With Income Tax <= 0 (#m),92.8,98.6,99.7,131.7,125.0,100.3,101.8,103.4,104.3,100.9
23
+ With Combined Tax <= 0 (#m),63.4,65.6,66.8,102.1,94.5,68.9,70.2,71.6,72.6,72.3
24
24
  UBI Benefits ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
25
25
  "Total Benefits, Consumption Value ($b)",1052.3,1104.9,1175.3,1243.9,1476.4,1411.5,1569.5,1707.8,1818.1,1924.4
26
26
  Total Benefits Cost ($b),1052.3,1104.9,1175.3,1243.9,1476.4,1411.5,1569.5,1707.8,1818.1,1924.4
@@ -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.txt FILE ---\n'
81
- msg += '--- if new OK, copy benefits_actual.txt to ---\n'
82
- msg += '--- benefits_expect.txt ---\n'
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], PT_qbid_limit_switch)
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], PT_qbid_limit_switch)
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], PT_qbid_limit_switch)
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], PT_qbid_limit_switch)
609
+ PT_qbid_ps, PT_qbid_prt, qbided[3])
611
610
  expected3 = (57500.00, 1200)
612
611
 
613
612
 
@@ -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