-
-
Notifications
You must be signed in to change notification settings - Fork 160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New growth rate handles #383
Changes from 8 commits
a1cae0b
4810352
99e2703
5be1fa2
c12d12e
92fd174
23242ee
37dd2f2
c82fab8
1af0f21
e18d403
d30853f
0fefa3d
9ff134a
5081114
3e76343
d2d3753
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
from .policy import Policy | ||
from .records import Records | ||
from .behavior import Behavior | ||
from .growth import * | ||
|
||
all_cols = set() | ||
|
||
|
@@ -26,18 +27,24 @@ def add_df(alldfs, df): | |
class Calculator(object): | ||
|
||
def __init__(self, policy=None, records=None, | ||
sync_years=True, behavior=None, **kwargs): | ||
sync_years=True, behavior=None, growth=None, **kwargs): | ||
|
||
if isinstance(policy, Policy): | ||
self._policy = policy | ||
else: | ||
msg = 'Must supply tax parameters as a Policy object' | ||
raise ValueError(msg) | ||
|
||
if isinstance(behavior, Behavior): | ||
self.behavior = behavior | ||
else: | ||
self.behavior = Behavior(start_year=policy.start_year) | ||
|
||
if isinstance(growth, Growth): | ||
self.growth = growth | ||
else: | ||
self.growth = Growth(start_year=policy.start_year) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm.. this idiom seems bad to me (used for both Growth and Behavior). If someone passes a Growth object for
|
||
|
||
if isinstance(records, Records): | ||
self._records = records | ||
elif isinstance(records, str): | ||
|
@@ -139,6 +146,11 @@ def calc_all_test(self): | |
return totaldf | ||
|
||
def increment_year(self): | ||
adjustment(self, self.growth.factor_adjustment, | ||
self.policy.current_year + 1) | ||
target(self, self.growth._factor_target, | ||
self.policy._inflation_rates, | ||
self.policy.current_year + 1) | ||
self.records.increment_year() | ||
self.policy.set_year(self.policy.current_year + 1) | ||
self.behavior.set_year(self.policy.current_year) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Amy-Xu could you take a crack at filling these in? Here is a suggestion, although please feel free to modify these. long_name: "Deviation from CBO forecast of baseline economic growth (percentage point)" description: "The data underlying this model are extrapolated to roughly match the CBO's projection of the economy's development over the 10-year federal budget window, with each type of economic data extrapolated at a different growth rate. This parameter allows a factor to be subtracted or added to those growth rates for the construction of the economic baseline. For example if you supply .02 (or 2%), then 0.02 will be added to the wage and salary growth rate, interest income growth rate, dividend growth rate, schedule E income growth rate, and all other growth rates used to extrapolate the underlying dataset." long_name: "Replacement for CBO real GDP growth in economic baseline (percent)". description: "The data underlying this model are extrapolated to roughly match the CBO's projection of the economy's development over the 10-year federal budget window, with each type of economic data extrapolated at a different growth rate. One of the growth rates taken from the CBO is GDP growth. This parameter allows you to specify a real GDP growth rate, and all other rates will be modified to maintain the distance between them and GDP growth in the CBO baseline. For example, if the CBO growth rate for one year is 0.02 and the user enters 0.018 for this parameter, then 0.002 will be subtracted from every growth rate in the construction of the economic baseline, including wage and salary growth, interest income growth, dividend growth, and many others. |
||
"_factor_adjustment":{ | ||
"long_name": "", | ||
"description": "", | ||
"irs_ref": "", | ||
"start_year": 2013, | ||
"col_var": "", | ||
"row_var": "", | ||
"row_label": ["2013"], | ||
"cpi_inflated": false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't need the cpi_inflated attribute for this param. |
||
"col_label": "", | ||
"value": [[0.0]] | ||
}, | ||
"_factor_target":{ | ||
"long_name": "", | ||
"description": "", | ||
"irs_ref": "", | ||
"start_year": 2013, | ||
"col_var": "", | ||
"row_var": "", | ||
"row_label": ["2013"], | ||
"cpi_inflated": false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't need the cpi_inflated attribute for this param. |
||
"col_label": "", | ||
"value": [[0.0]] | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import copy | ||
import json | ||
import os | ||
import numpy as np | ||
from .policy import Policy | ||
from .parameters_base import ParametersBase | ||
|
||
|
||
class Growth(ParametersBase): | ||
|
||
JSON_START_YEAR = Policy.JSON_START_YEAR | ||
DEFAULTS_FILENAME = 'growth.json' | ||
DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS | ||
DEFAULT_INFLATION_RATES = {2013: 0.015, 2014: 0.020, 2015: 0.022, | ||
2016: 0.020, 2017: 0.021, 2018: 0.022, | ||
2019: 0.023, 2020: 0.024, 2021: 0.024, | ||
2022: 0.024, 2023: 0.024, 2024: 0.024} | ||
|
||
def __init__(self, growth_dict=None, | ||
start_year=JSON_START_YEAR, | ||
num_years=DEFAULT_NUM_YEARS, | ||
inflation_rates=DEFAULT_INFLATION_RATES): | ||
if growth_dict: | ||
if not isinstance(growth_dict, dict): | ||
raise ValueError('growth_dict is not a dictionary') | ||
self._vals = growth_dict | ||
else: # if None, read defaults | ||
self._vals = self._params_dict_from_json_file() | ||
|
||
self.initialize(start_year, num_years) | ||
|
||
def update_economic_growth(self, reform): | ||
'''Update economic growth rates/targets | ||
for a reform, a dictionary | ||
consisting of year: modification dictionaries. For example: | ||
{2014: {'_BE_inc': [0.4, 0.3]}}''' | ||
self.set_default_vals() | ||
if self.current_year != self.start_year: | ||
self.set_year(self.start_year) | ||
|
||
for year in reform: | ||
if year != self.start_year: | ||
self.set_year(year) | ||
self._update({year: reform[year]}) | ||
|
||
|
||
def adjustment(calc, percentage, year): | ||
records = calc.records | ||
records.BF.AGDPN[year] += percentage * abs(records.BF.AGDPN[year] - 1) | ||
records.BF.ATXPY[year] += percentage * abs(records.BF.ATXPY[year] - 1) | ||
records.BF.AWAGE[year] += percentage * abs(records.BF.AWAGE[year] - 1) | ||
records.BF.ASCHCI[year] += percentage * abs(records.BF.ASCHCI[year] - 1) | ||
records.BF.ASCHCL[year] += percentage * abs(records.BF.ASCHCL[year] - 1) | ||
records.BF.ASCHF[year] += percentage * abs(records.BF.ASCHF[year] - 1) | ||
records.BF.AINTS[year] += percentage * abs(records.BF.AINTS[year] - 1) | ||
records.BF.ADIVS[year] += percentage * abs(records.BF.ADIVS[year] - 1) | ||
records.BF.ACGNS[year] += percentage * abs(records.BF.ACGNS[year] - 1) | ||
records.BF.ASCHEI[year] += percentage * abs(records.BF.ASCHEI[year] - 1) | ||
records.BF.ASCHEL[year] += percentage * abs(records.BF.ASCHEL[year] - 1) | ||
records.BF.ABOOK[year] += percentage * abs(records.BF.ABOOK[year] - 1) | ||
records.BF.ACPIU[year] += percentage * abs(records.BF.ACPIU[year] - 1) | ||
records.BF.ACPIM[year] += percentage * abs(records.BF.ACPIM[year] - 1) | ||
records.BF.ASOCSEC[year] += percentage * abs(records.BF.ASOCSEC[year] - 1) | ||
records.BF.AUCOMP[year] += percentage * abs(records.BF.AUCOMP[year] - 1) | ||
records.BF.AIPD[year] += percentage * abs(records.BF.AIPD[year] - 1) | ||
|
||
|
||
def target(calc, target, inflation, year): | ||
# 2013 is the start year of all parameter arrays. Hard coded for now. | ||
# Need to be fixed later | ||
records = calc.records | ||
default_year = calc.policy.JSON_START_YEAR | ||
if year >= default_year and target[year - default_year] != 0: | ||
# user inputs theoretically should be based on GDP | ||
g = abs(records.BF.AGDPN[year] - 1) | ||
ratio = (target[year - default_year] + | ||
inflation[year - default_year]) / g | ||
|
||
# apply this ratio to all the dollar amount factors | ||
records.BF.AGDPN[year] = ratio * abs(records.BF.AGDPN[year] - 1) + 1 | ||
records.BF.ATXPY[year] = ratio * abs(records.BF.ATXPY[year] - 1) + 1 | ||
records.BF.AWAGE[year] = ratio * abs(records.BF.AWAGE[year] - 1) + 1 | ||
records.BF.ASCHCI[year] = ratio * abs(records.BF.ASCHCI[year] - 1) + 1 | ||
records.BF.ASCHCL[year] = ratio * abs(records.BF.ASCHCL[year] - 1) + 1 | ||
records.BF.ASCHF[year] = ratio * abs(records.BF.ASCHF[year] - 1) + 1 | ||
records.BF.AINTS[year] = ratio * abs(records.BF.AINTS[year] - 1) + 1 | ||
records.BF.ADIVS[year] = ratio * abs(records.BF.ADIVS[year] - 1) + 1 | ||
records.BF.ACGNS[year] = ratio * abs(records.BF.ACGNS[year] - 1) + 1 | ||
records.BF.ASCHEI[year] = ratio * abs(records.BF.ASCHEI[year] - 1) + 1 | ||
records.BF.ASCHEL[year] = ratio * abs(records.BF.ASCHEL[year] - 1) + 1 | ||
records.BF.ABOOK[year] = ratio * abs(records.BF.ABOOK[year] - 1) + 1 | ||
records.BF.ACPIU[year] = ratio * abs(records.BF.ACPIU[year] - 1) + 1 | ||
records.BF.ACPIM[year] = ratio * abs(records.BF.ACPIM[year] - 1) + 1 | ||
records.BF.ASOCSEC[year] = (ratio * | ||
abs(records.BF.ASOCSEC[year] - 1) + 1) | ||
records.BF.AUCOMP[year] = ratio * abs(records.BF.AUCOMP[year] - 1) + 1 | ||
records.BF.AIPD[year] = ratio * abs(records.BF.AIPD[year] - 1) + 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggest:
(and any other functions needed here)