Recipe 2: Estimating Behavioral Response to ReformΒΆ

This is an advanced recipe that should be followed only after mastering the basic recipe. This recipe shows how to analyze the behavioral responses to a tax reform using the Behavioral-Responses behresp package.

import taxcalc as tc
import behresp

# use publicly-available CPS input file
recs = tc.Records.cps_constructor()

# specify baseline Calculator object representing current-law policy
pol = tc.Policy()
calc1 = tc.Calculator(policy=pol, records=recs)

CYR = 2020

# calculate aggregate current-law income tax liabilities for cyr
calc1.advance_to_year(CYR)
calc1.calc_all()
itax_rev1 = calc1.weighted_total('iitax')

# specify Calculator object for static analysis of reform policy
pol.implement_reform(tc.Policy.read_json_reform('github://PSLmodels:[email protected]/docs/recipes/_static/reformA.json'))
calc2 = tc.Calculator(policy=pol, records=recs)

# calculate reform income tax liabilities for cyr under static assumptions
calc2.advance_to_year(CYR)
calc2.calc_all()
itax_rev2sa = calc2.weighted_total('iitax')

# specify assumed non-zero response-function substitution elasticity
response_elasticities = {'sub': 0.25}

# specify Calculator object for analysis of reform with behavioral responses
calc2 = tc.Calculator(policy=pol, records=recs)
calc2.advance_to_year(CYR)
_, df2br = behresp.response(calc1, calc2, response_elasticities)

# calculate reform income tax liabilities for CYR with behavioral response
itax_rev2br = (df2br['iitax'] * df2br['s006']).sum()

# print total income tax revenue estimates for CYR
# (estimates in billons of dollars)
print('{}_CURRENT_LAW_P__itax_rev($B)= {:.3f}'.format(CYR, itax_rev1 * 1e-9))
print('{}_REFORM_STATIC__itax_rev($B)= {:.3f}'.format(CYR, itax_rev2sa * 1e-9))
print('{}_REFORM_DYNAMIC_itax_rev($B)= {:.3f}'.format(CYR, itax_rev2br * 1e-9))
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-2-e3f4917dd976> in <module>
     17 
     18 # specify Calculator object for static analysis of reform policy
---> 19 pol.implement_reform(tc.Policy.read_json_reform('github://PSLmodels:[email protected]/docs/recipes/_static/reformA.json'))
     20 calc2 = tc.Calculator(policy=pol, records=recs)
     21 

~/work/Tax-Calculator/Tax-Calculator/taxcalc/policy.py in implement_reform(self, reform, print_warnings, raise_errors)
    119         """
    120         # need to do conversion:
--> 121         return self._update(reform, print_warnings, raise_errors)
    122 
    123     @staticmethod

~/work/Tax-Calculator/Tax-Calculator/taxcalc/parameters.py in _update(self, revision, print_warnings, raise_errors)
    663                     None
    664                 )
--> 665         return self.adjust(
    666             new_params,
    667             print_warnings=print_warnings,

~/work/Tax-Calculator/Tax-Calculator/taxcalc/parameters.py in adjust(self, params_or_path, print_warnings, raise_errors, **kwargs)
    174             # defer related-parameter validation until all intermediate updates
    175             # are complete.
--> 176             with self.transaction(
    177                 defer_validation=True,
    178                 raise_errors=True,

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/contextlib.py in __enter__(self)
    111         del self.args, self.kwds, self.func
    112         try:
--> 113             return next(self.gen)
    114         except StopIteration:
    115             raise RuntimeError("generator didn't yield") from None

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/site-packages/paramtools/parameters.py in transaction(self, defer_validation, raise_errors, ignore_warnings)
    420             - `raise_errors`: Either raise errors or simply store the error messages.
    421         """
--> 422         _data = copy.deepcopy(self._data)
    423         _ops = dict(self.operators)
    424         _state = dict(self.view_state())

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
    170                     y = x
    171                 else:
--> 172                     y = _reconstruct(x, memo, *rv)
    173 
    174     # If is its own copy, don't memoize.

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    294             for key, value in dictiter:
    295                 key = deepcopy(key, memo)
--> 296                 value = deepcopy(value, memo)
    297                 y[key] = value
    298         else:

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
    170                     y = x
    171                 else:
--> 172                     y = _reconstruct(x, memo, *rv)
    173 
    174     # If is its own copy, don't memoize.

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    294             for key, value in dictiter:
    295                 key = deepcopy(key, memo)
--> 296                 value = deepcopy(value, memo)
    297                 y[key] = value
    298         else:

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
    144     copier = _deepcopy_dispatch.get(cls)
    145     if copier is not None:
--> 146         y = copier(x, memo)
    147     else:
    148         if issubclass(cls, type):

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/copy.py in _deepcopy_list(x, memo, deepcopy)
    203     append = y.append
    204     for a in x:
--> 205         append(deepcopy(a, memo))
    206     return y
    207 d[list] = _deepcopy_list

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
    170                     y = x
    171                 else:
--> 172                     y = _reconstruct(x, memo, *rv)
    173 
    174     # If is its own copy, don't memoize.

/usr/share/miniconda/envs/taxcalc-dev/lib/python3.8/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    262     if deep and args:
    263         args = (deepcopy(arg, memo) for arg in args)
--> 264     y = func(*args)
    265     if deep:
    266         memo[id(x)] = y

KeyboardInterrupt: 

Create multi-year diagnostic tables for

  1. baseline,

  2. reform excluding behavioral responses, and

  3. reform including behavioral responses

NUM_YEARS = 3  # number of diagnostic table years beginning with CYR
dtable1 = calc1.diagnostic_table(NUM_YEARS)
dtable2 = calc2.diagnostic_table(NUM_YEARS)
dvar_list3 = list()
year_list3 = list()
for year in range(CYR, CYR + NUM_YEARS):
    calc1.advance_to_year(year)
    calc2.advance_to_year(year)
    _, df2br = behresp.response(calc1, calc2, response_elasticities)
    dvar_list3.append(df2br)
    year_list3.append(year)
dtable3 = tc.create_diagnostic_table(dvar_list3, year_list3)

Diagnostic table for baseline:

dtable1
2020 2021 2022
Returns (#m) 205.440 208.140 210.820
AGI ($b) 11475.571 11691.366 12219.492
Itemizers (#m) 30.950 29.170 30.670
Itemized Deduction ($b) 824.019 760.366 809.757
Standard Deduction Filers (#m) 174.490 178.960 180.140
Standard Deduction ($b) 3188.464 3289.501 3344.937
Personal Exemption ($b) 0.000 0.000 0.000
Taxable Income ($b) 8513.062 8731.100 9177.528
Regular Tax ($b) 1505.162 1544.527 1635.569
AMT Income ($b) 10856.448 11122.136 11611.624
AMT Liability ($b) 0.923 0.883 0.902
AMT Filers (#m) 0.420 0.440 0.440
Tax before Credits ($b) 1506.085 1545.410 1636.472
Refundable Credits ($b) 103.539 867.141 102.528
Nonrefundable Credits ($b) 94.954 3.935 98.942
Reform Surtaxes ($b) 0.000 0.000 0.000
Other Taxes ($b) 13.895 12.309 13.109
Ind Income Tax ($b) 1321.487 686.642 1448.110
Payroll Taxes ($b) 1186.745 1213.929 1267.083
Combined Liability ($b) 2508.233 1900.571 2715.194
With Income Tax <= 0 (#m) 101.340 136.280 102.410
With Combined Tax <= 0 (#m) 69.360 106.330 71.670
UBI Benefits ($b) 0.000 0.000 0.000
Total Benefits, Consumption Value ($b) 3650.123 3871.611 4112.506
Total Benefits Cost ($b) 3650.123 3871.611 4112.506

Diagnostic table for reform, excluding behavioral responses:

dtable2
2020 2021 2022
Returns (#m) 205.440 208.140 210.820
AGI ($b) 11475.571 11691.366 12219.492
Itemizers (#m) 30.860 29.100 30.580
Itemized Deduction ($b) 821.244 757.934 807.273
Standard Deduction Filers (#m) 174.580 179.040 180.230
Standard Deduction ($b) 3190.011 3290.859 3346.410
Personal Exemption ($b) 387.209 394.699 403.152
Taxable Income ($b) 8274.064 8486.881 8927.069
Regular Tax ($b) 1511.260 1550.256 1643.269
AMT Income ($b) 10859.047 11124.396 11613.962
AMT Liability ($b) 0.978 0.964 0.978
AMT Filers (#m) 0.450 0.450 0.460
Tax before Credits ($b) 1512.239 1551.220 1644.247
Refundable Credits ($b) 106.802 867.141 106.097
Nonrefundable Credits ($b) 89.372 3.728 93.371
Reform Surtaxes ($b) 0.000 0.000 0.000
Other Taxes ($b) 13.895 12.309 13.109
Ind Income Tax ($b) 1329.959 692.660 1457.889
Payroll Taxes ($b) 1186.745 1213.929 1267.083
Combined Liability ($b) 2516.705 1906.589 2724.972
With Income Tax <= 0 (#m) 103.730 138.010 104.890
With Combined Tax <= 0 (#m) 69.930 107.270 72.360
UBI Benefits ($b) 0.000 0.000 0.000
Total Benefits, Consumption Value ($b) 3650.123 3871.611 4112.506
Total Benefits Cost ($b) 3650.123 3871.611 4112.506

Diagnostic table for reform, including behavioral responses:

dtable3
2020 2021 2022
Returns (#m) 205.440 208.140 210.820
AGI ($b) 11445.873 11659.522 12185.655
Itemizers (#m) 30.830 29.070 30.560
Itemized Deduction ($b) 819.497 756.391 805.450
Standard Deduction Filers (#m) 174.620 179.060 180.260
Standard Deduction ($b) 3190.774 3291.311 3347.043
Personal Exemption ($b) 387.209 394.699 403.152
Taxable Income ($b) 8245.048 8455.598 8893.866
Regular Tax ($b) 1498.246 1536.636 1628.637
AMT Income ($b) 10830.848 11093.908 11581.700
AMT Liability ($b) 0.990 0.984 1.007
AMT Filers (#m) 0.440 0.450 0.460
Tax before Credits ($b) 1499.236 1537.620 1629.644
Refundable Credits ($b) 106.529 867.114 105.817
Nonrefundable Credits ($b) 89.619 3.744 93.623
Reform Surtaxes ($b) 0.000 0.000 0.000
Other Taxes ($b) 13.579 12.004 12.784
Ind Income Tax ($b) 1316.667 678.766 1442.988
Payroll Taxes ($b) 1185.888 1212.854 1266.008
Combined Liability ($b) 2502.555 1891.620 2708.996
With Income Tax <= 0 (#m) 103.580 137.980 104.690
With Combined Tax <= 0 (#m) 69.730 107.250 72.170
UBI Benefits ($b) 0.000 0.000 0.000
Total Benefits, Consumption Value ($b) 3650.123 3871.611 4112.506
Total Benefits Cost ($b) 3650.123 3871.611 4112.506