-
-
Notifications
You must be signed in to change notification settings - Fork 160
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2466 from Peter-Metz/new_ppp
New ppp.py
- Loading branch information
Showing
4 changed files
with
116 additions
and
142 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,72 @@ | ||
""" | ||
Policy parameter projection script, which calculates future policy parameter | ||
values under TCJA and which should be used when the following happens: | ||
(1) the inflation factor values change in growfactors.csv, or | ||
(2) the last known historical values of policy parameters are updated, | ||
in which case the byear parameter (see below) should be incremented. | ||
Policy parameter projection script, which calculates policy parameter | ||
values that were changed by TCJA and will revert to their pre-TCJA | ||
values in 2026 (adjusted for inflation). The script should be run | ||
when the inflation factor values change in growfactors.csv. | ||
USAGE: $ python ppp.py | ||
OUTPUT: ppp.old -- contains old parameter values in policy_current_law.json | ||
ppp.new -- contains new parameter values that should now be used | ||
Note: running this script will write the new 2026 parameter values | ||
directly to policy_current_law.json. | ||
""" | ||
from taxcalc import Policy | ||
from taxcalc import * | ||
import json | ||
|
||
# specify year constants (only byear should vary) | ||
syear = Policy.JSON_START_YEAR | ||
pyear = 2017 # prior year before TCJA first implemented | ||
byear = 2019 # base year: year for last known historical parameter values | ||
fyear = 2026 # final year in which parameter values revert to pre-TCJA values | ||
params = Policy() | ||
|
||
# ensure proper relationship between year constants | ||
assert pyear == 2017 | ||
assert fyear == 2026 | ||
assert byear > pyear and byear < fyear | ||
# parameters that will revert | ||
long_params = ['II_brk7', 'II_brk6', 'II_brk5', 'II_brk4', | ||
'II_brk3', 'II_brk2', 'II_brk1', | ||
'PT_brk7', 'PT_brk6', 'PT_brk5', 'PT_brk4', | ||
'PT_brk3', 'PT_brk2', 'PT_brk1', | ||
'PT_qbid_taxinc_thd', | ||
'ALD_BusinessLosses_c', | ||
'STD', 'II_em', 'II_em_ps', | ||
'AMT_em', 'AMT_em_ps', 'AMT_em_pe', | ||
'ID_ps', 'ID_AllTaxes_c'] | ||
|
||
# specify current-law policy that includes TCJA inflation indexing rules | ||
clp = Policy() | ||
pdata = clp._vals | ||
# calculate the inflation factor used to calculate the | ||
# inflation-adjusted 2026 parameter values | ||
final_ifactor = 1.0 | ||
pyear = 2017 # prior year before TCJA first implemented | ||
fyear = 2026 # final year in which parameter values revert to | ||
# pre-TCJA values | ||
# construct final-year inflation factor from prior year | ||
# NOTE: pvalue[t+1] = pvalue[t] * ( 1 + irate[t] ) | ||
for year in range(pyear, fyear): | ||
final_ifactor *= 1 + \ | ||
params._inflation_rates[year - params.start_year] | ||
|
||
# identify policy parameters that have their values reverted in final year | ||
skip_list = ['_II_brk7', '_PT_brk7'] # because they are both "infinity" (9e99) | ||
fyr = fyear | ||
reverting_params = list() | ||
for pname in sorted(pdata.keys()): | ||
pdict = pdata[pname] | ||
if pdata[pname]['indexed'] and fyr in pdata[pname]['value_yrs']: | ||
if pname not in skip_list: | ||
reverting_params.append(pname) | ||
print('number_of_reverting_parameters= {}'.format(len(reverting_params))) | ||
long_param_vals = defaultdict(list) | ||
|
||
# write ppp.old containing existing values for reverting policy parameters | ||
old = open('ppp.old', 'w') | ||
for pname in reverting_params: | ||
old.write('*** {} ***\n'.format(pname)) | ||
# write parameter values for each year in [pyear,fyear] range | ||
for year in range(pyear, fyear + 1): | ||
value = pdata[pname]['value'][year - syear] | ||
old.write('{}: {}\n'.format(year, value)) | ||
old.close() | ||
for param in long_params: | ||
vos = params.select_eq(param, year=pyear) | ||
# use final_ifactor to inflate from 2017 to 2026 | ||
for vo in vos: | ||
long_param_vals[param].append( | ||
# Create new dict to avoid modifying the original | ||
dict( | ||
vo, | ||
value=min(9e99, round( | ||
vo["value"] * final_ifactor, 0)), | ||
year=fyear, | ||
) | ||
) | ||
|
||
# get TCJA parameter inflation rates for each year | ||
irate = clp.inflation_rates() | ||
# call adjust method for new 2026 values | ||
params.adjust(long_param_vals) | ||
params.clear_state() | ||
param_data = params.specification( | ||
meta_data=False, serializable=True, use_state=False, _auto=False) | ||
|
||
# construct final-year inflation factor from prior year | ||
# < NOTE: pvalue[t+1] = pvalue[t] * ( 1 + irate[t] ) > | ||
final_ifactor = 1.0 | ||
for year in range(pyear, fyear): | ||
final_ifactor *= 1 + irate[year - syear] | ||
# read existing policy_current_law.json | ||
with open('taxcalc/policy_current_law.json', 'r') as f: | ||
pcl = json.load(f) | ||
|
||
# construct intermediate-year inflation factors from base year | ||
# < NOTE: pvalue[t+1] = pvalue[t] * ( 1 + irate[t] ) > | ||
ifactor = dict() | ||
factor = 1.0 | ||
for year in range(byear, fyear): | ||
ifactor[year] = factor | ||
factor *= 1 + irate[year - syear] | ||
# replace 2026 values in policy_current_law.json | ||
for param in param_data: | ||
pcl[param]["value"] = param_data[param] | ||
|
||
# write or calculate policy parameter values for pyear through fyear | ||
new = open('ppp.new', 'w') | ||
for pname in reverting_params: | ||
new.write('*** {} ***\n'.format(pname)) | ||
# write parameter values for prior year | ||
value = pdata[pname]['value'][pyear - syear] | ||
new.write('{}: {}\n'.format(pyear, value)) | ||
# write parameter values for year after prior year up through base year | ||
for year in range(pyear + 1, byear + 1): | ||
value = pdata[pname]['value'][year - syear] | ||
new.write('{}: {}\n'.format(year, value)) | ||
# compute parameter values for intermediate years | ||
bvalue = pdata[pname]['value'][byear - syear] | ||
for year in range(byear + 1, fyear): | ||
if isinstance(bvalue, list): | ||
value = list() | ||
for idx in range(0, len(bvalue)): | ||
val = min(9e99, round(bvalue[idx] * ifactor[year], 2)) | ||
value.append(val) | ||
else: | ||
value = min(9e99, round(bvalue * ifactor[year], 2)) | ||
new.write('{}: {}\n'.format(year, value)) | ||
# compute final year parameter value | ||
pvalue = pdata[pname]['value'][pyear - syear] | ||
if isinstance(pvalue, list): | ||
value = list() | ||
for idx in range(0, len(pvalue)): | ||
val = min(9e99, round(pvalue[idx] * final_ifactor, 0)) | ||
value.append(val) | ||
else: | ||
value = min(9e99, round(pvalue * final_ifactor, 0)) | ||
new.write('{}: {}\n'.format(fyear, value)) | ||
new.close() | ||
# write new policy_current_law.json | ||
with open('taxcalc/policy_current_law.json', 'w') as pcl_old: | ||
json.dump(pcl, pcl_old, indent=4) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters