Skip to content
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

Make last budget year flexible #2846

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
609b2c8
Change 2034 to 2074 in parameter files
martinholmer May 27, 2024
d244bea
Merge in add-tc-timings
martinholmer May 28, 2024
95ed099
Merge in recent changes on master branch
martinholmer May 28, 2024
a07a280
Merge in recent changes on master branch
martinholmer Jun 4, 2024
f79fc6f
Merge in recent changes on master branch
martinholmer Jun 5, 2024
1c7ed7a
Merge in recent changes on master branch
martinholmer Jun 6, 2024
fb858c4
Merge in recent changes on master branch
martinholmer Jun 17, 2024
86bb49b
Merge in recent changes on master branch
martinholmer Jul 4, 2024
4290d9b
Merge in recent changes on master branch
martinholmer Jul 5, 2024
b4471e4
Merge in recent changes on master branch
martinholmer Jul 21, 2024
4a86216
revert years
jdebacker Jul 26, 2024
79250f4
Merge remote-tracking branch 'upstream/master' into pr-2755
jdebacker Jul 27, 2024
ed2ace3
trying new param tools
jdebacker Jul 30, 2024
17d07e5
Merge in recent changes on master branch
martinholmer Jul 31, 2024
62d8250
Merge in recent changes on master branch
martinholmer Aug 4, 2024
cc6a974
Include recent changes on master branch
martinholmer Sep 17, 2024
2d0c17e
Merge in recent changes on master branch
martinholmer Sep 26, 2024
278c4b0
Merge in recent changes on master branch
martinholmer Oct 1, 2024
28c00a4
Merge in recent changes on master branch
martinholmer Oct 4, 2024
f805fa1
Merge in recent changes on master branch
martinholmer Oct 12, 2024
959594b
Merge in recent changes on master branch
martinholmer Oct 27, 2024
2e4591a
Merge in recent changes on master branch
martinholmer Nov 8, 2024
9cda879
Merge in recent changes on master branch
martinholmer Nov 13, 2024
6a63aed
Merge 4.3.3 code into thru74 branch
martinholmer Nov 17, 2024
1afd3ca
merge in upstream changes
jdebacker Nov 23, 2024
f761159
allow flexible budget year end year
jdebacker Nov 23, 2024
0e57edd
clean up print command
jdebacker Nov 24, 2024
259cf72
consistent num years
jdebacker Nov 26, 2024
4340ef9
update default num years name
jdebacker Nov 26, 2024
4071d60
Merge remote-tracking branch 'upstream/master' into pr-2755
jdebacker Nov 27, 2024
8265926
pt 19
jdebacker Nov 28, 2024
828e932
consistency in meta.yaml
jdebacker Nov 29, 2024
d814a1d
consistency in meta.yaml
jdebacker Nov 29, 2024
db57101
Merge remote-tracking branch 'upstream/master' into pr-2755
jdebacker Dec 6, 2024
9c14ec8
update paramtools in setup.py
jdebacker Dec 6, 2024
8c8f123
Merge remote-tracking branch 'upstream/master' into pr-2755
jdebacker Dec 8, 2024
6f3372b
add pins to setup.py
jdebacker Dec 9, 2024
4531c93
Merge remote-tracking branch 'upstream/master' into pr-2755
jdebacker Dec 10, 2024
6cac8fc
update tmd constructor
jdebacker Dec 10, 2024
680d5c3
add pins to setup.py
jdebacker Dec 10, 2024
3d17daa
add requests to meta and env
jdebacker Dec 10, 2024
71b228e
test setup file
jdebacker Dec 10, 2024
92b8418
Merge remote-tracking branch 'upstream/master' into pr-2755
jdebacker Dec 13, 2024
502f5ae
fix typo
jdebacker Dec 13, 2024
a778167
add test of flexible end year
jdebacker Dec 14, 2024
2593f2b
add budget year end to command line args
jdebacker Dec 15, 2024
2cce10b
passing of tmd and year
jdebacker Dec 16, 2024
b310c19
use latests upstream changes
jdebacker Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions conda.recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,24 @@ build:
requirements:
build:
- "python>=3.10, <3.13"
- "numpy>=1.26,<1.27"
- "numpy>=1.26"
- "pandas>=2.2"
- "bokeh>=2.4"
- "paramtools>=0.18.3"
- "paramtools>=0.19.0"
- numba
- requests
- curl
- openpyxl
- behresp

run:
- "python>=3.10, <3.13"
- "numpy>=1.26,<1.27"
- "numpy>=1.26"
- "pandas>=2.2"
- "bokeh>=2.4"
- "paramtools>=0.18.3"
- "paramtools>=0.19.0"
- numba
- requests
- curl
- openpyxl
- behresp
Expand Down
6 changes: 4 additions & 2 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ channels:
- conda-forge
dependencies:
- "python>=3.10, <3.13"
- "numpy>=1.26,<1.27"
- "numpy>=1.26"
- "pandas>=2.2"
- "bokeh>=2.4"
- numba
- requests
- curl
- setuptools
- pytest
- pytest-xdist
- pycodestyle
Expand All @@ -18,4 +20,4 @@ dependencies:
- pip
- pip:
- jupyter-book
- "paramtools>=0.18.3"
- "paramtools>=0.19.0"
9 changes: 4 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@
"include_package_data": True,
"name": "taxcalc",
"install_requires": [
"setuptools",
"numpy",
"pandas",
"bokeh",
"numpy>=1.26",
"pandas>=2.2",
"bokeh>=2.4",
"numba",
"requests",
"paramtools>=0.18.3",
"paramtools>=0.19.0",
],
"classifiers": [
"Development Status :: 4 - Beta",
Expand Down
9 changes: 4 additions & 5 deletions taxcalc.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: setuptools
Requires-Dist: numpy
Requires-Dist: pandas
Requires-Dist: bokeh
Requires-Dist: numpy>=1.26
Requires-Dist: pandas>=2.2
Requires-Dist: bokeh>=2.4
Requires-Dist: numba
Requires-Dist: requests
Requires-Dist: paramtools>=0.18.3
Requires-Dist: paramtools>=0.19.0

| | |
| --- | --- |
Expand Down
7 changes: 6 additions & 1 deletion taxcalc.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pyproject.toml
pytest.ini
setup.py
tctest-nojit.sh
update_pcl.py
.github/FUNDING.yml
.github/workflows/build_and_test.yml
.github/workflows/check_jupyterbook.yml
Expand Down Expand Up @@ -172,6 +173,8 @@ taxcalc/reforms/ptaxes2.json
taxcalc/reforms/ptaxes2.out.csv
taxcalc/reforms/ptaxes3.json
taxcalc/reforms/ptaxes3.out.csv
taxcalc/reforms/rounding.json
taxcalc/reforms/rounding.out.csv
taxcalc/reforms/archive/Clinton2016.json
taxcalc/reforms/archive/RyanBrady.json
taxcalc/reforms/archive/TCJA_House.json
Expand Down Expand Up @@ -238,4 +241,6 @@ taxcalc/validation/taxsim35/expected_differences/b20-taxdiffs-expect.csv
taxcalc/validation/taxsim35/expected_differences/b21-taxdiffs-expect.csv
taxcalc/validation/taxsim35/expected_differences/c17-taxdiffs-expect.csv
taxcalc/validation/taxsim35/expected_differences/c18-taxdiffs-expect.csv
taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv
taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv
taxcalc/validation/taxsim35/expected_differences/c20-taxdiffs-expect.csv
taxcalc/validation/taxsim35/expected_differences/c21-taxdiffs-expect.csv
9 changes: 4 additions & 5 deletions taxcalc.egg-info/requires.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
setuptools
numpy
pandas
bokeh
numpy>=1.26
pandas>=2.2
bokeh>=2.4
numba
requests
paramtools>=0.18.3
paramtools>=0.19.0
3 changes: 2 additions & 1 deletion taxcalc/calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ def __init__(self, policy=None, records=None, verbose=False,
if self.__policy.current_year < self.__records.data_year:
self.__policy.set_year(self.__records.data_year)
if consumption is None:
self.__consumption = Consumption()
print("CONS policy num years = ", policy.NUM_YEARS)
self.__consumption = Consumption(policy.NUM_YEARS)
elif isinstance(consumption, Consumption):
self.__consumption = copy.deepcopy(consumption)
else:
Expand Down
13 changes: 13 additions & 0 deletions taxcalc/cli/tc.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ def cli_tc_main():
# parse command-line arguments:
usage_str = 'tc INPUT TAXYEAR {}{}{}{}{}'.format(
'[--help]\n',
(' '
'[--budgetend BUDGETENDYEAR]\n'),
(' '
'[--baseline BASELINE] [--reform REFORM] [--assump ASSUMP]\n'),
(' '
Expand Down Expand Up @@ -56,6 +58,15 @@ def cli_tc_main():
'are computed.'),
type=int,
default=0)
parser.add_argument('--budgetend',
help=('BUDGETENDYEAR is name of optional '
'calendar year that is the last year '
'of the budget window to be analyzed. '
'No --budget implies the budget window '
'extends until '
'Policy.DEFAULT_LAST_BUDGET_YEAR.'),
type=int,
default=None)
parser.add_argument('--baseline',
help=('BASELINE is name of optional JSON reform file. '
'No --baseline implies baseline policy is '
Expand Down Expand Up @@ -164,6 +175,7 @@ def cli_tc_main():
taxyear = args.TAXYEAR
# instantiate TaxCalcIO object and do tax analysis
tcio = tc.TaxCalcIO(input_data=inputfn, tax_year=taxyear,
budget_end_year=args.budgetend,
baseline=args.baseline,
reform=args.reform, assump=args.assump,
outdir=args.outdir)
Expand All @@ -179,6 +191,7 @@ def cli_tc_main():
if args.timings:
stime = time.time()
tcio.init(input_data=inputfn, tax_year=taxyear,
budget_end_year=args.budgetend,
baseline=args.baseline,
reform=args.reform, assump=args.assump,
aging_input_data=aging,
Expand Down
8 changes: 5 additions & 3 deletions taxcalc/consumption.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ class instance: Consumption
"""

JSON_START_YEAR = Policy.JSON_START_YEAR
DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS
NUM_YEARS = Policy.NUM_YEARS
DEFAULTS_FILE_NAME = 'consumption.json'
DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__))

def __init__(self):
def __init__(self, nyrs=NUM_YEARS):
# put JSON contents of DEFAULTS_FILE_NAME into self._vals dictionary
super().__init__()
print("CONS policy num years = ", nyrs)
self.initialize(Consumption.JSON_START_YEAR,
Consumption.DEFAULT_NUM_YEARS)
nyrs)

@staticmethod
def read_json_update(obj):
Expand Down
7 changes: 3 additions & 4 deletions taxcalc/growdiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ class instance: GrowDiff
"""

JSON_START_YEAR = Policy.JSON_START_YEAR
DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS
NUM_YEARS = Policy.NUM_YEARS
DEFAULTS_FILE_NAME = 'growdiff.json'
DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__))

def __init__(self):
super().__init__()
def __init__(self, nyrs=NUM_YEARS):
self.initialize(GrowDiff.JSON_START_YEAR,
GrowDiff.DEFAULT_NUM_YEARS)
nyrs)

@staticmethod
def read_json_update(obj, topkey):
Expand Down
1 change: 1 addition & 0 deletions taxcalc/growfactors.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def __init__(self, growfactors_filename=None):
# determine first_year and last_year from gfdf
self._first_year = min(gfdf.index)
self._last_year = max(gfdf.index)
print("IN Gfactors last year is ", self._last_year)
# set gfdf as attribute of class
self.gfdf = pd.DataFrame()
setattr(self, 'gfdf', gfdf.astype(np.float64))
Expand Down
7 changes: 6 additions & 1 deletion taxcalc/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def __init__(self, start_year=None, num_years=None, last_known_year=None,
self.DEFAULTS_FILE_NAME
)

self.LAST_BUDGET_YEAR = start_year + num_years - 1
if last_known_year is None:
self._last_known_year = start_year
else:
Expand All @@ -118,6 +119,10 @@ def __init__(self, start_year=None, num_years=None, last_known_year=None,
kwargs["initial_state"] = {
"year": start_year or self.JSON_START_YEAR
}
# Update defaults to user defined budget window
self.defaults = super().get_defaults()
label = self.defaults["schema"]["labels"]["year"]
label["validators"]["range"]["max"] = self.LAST_BUDGET_YEAR
super().__init__(**kwargs)

def adjust(
Expand Down Expand Up @@ -817,4 +822,4 @@ def is_paramtools_format(params: Union[TaxcalcReform, ParamToolsAdjustment]):
else:
# Not doing a specific check to see if the value is a list
# since it could be a list or just a scalar value.
return True
return True
18 changes: 11 additions & 7 deletions taxcalc/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ class instance: Policy
JSON_START_YEAR = 2013 # remains the same unless earlier data added
LAST_KNOWN_YEAR = 2025 # last year for which indexed param vals are known
# should increase LAST_KNOWN_YEAR by one every calendar year
LAST_BUDGET_YEAR = 2034 # last extrapolation year
# should increase LAST_BUDGET_YEAR by one every calendar year
DEFAULT_NUM_YEARS = LAST_BUDGET_YEAR - JSON_START_YEAR + 1
DEFAULT_LAST_BUDGET_YEAR = 2034 # last extrapolation year
NUM_YEARS = DEFAULT_LAST_BUDGET_YEAR - JSON_START_YEAR + 1

# NOTE: the following three data structures use internal parameter names:
# (1) specify which Policy parameters have been removed or renamed
Expand Down Expand Up @@ -80,7 +79,9 @@ class instance: Policy
# (3) specify which Policy parameters are wage (rather than price) indexed
WAGE_INDEXED_PARAMS = ['SS_Earnings_c', 'SS_Earnings_thd']

def __init__(self, gfactors=None, **kwargs):
def __init__(self, gfactors=None,
last_budget_year=DEFAULT_LAST_BUDGET_YEAR,
**kwargs):
# put JSON contents of DEFAULTS_FILE_NAME into self._vals dictionary
super().__init__()
# handle gfactors argument
Expand All @@ -92,7 +93,8 @@ def __init__(self, gfactors=None, **kwargs):
raise ValueError('gfactors is not None or a GrowFactors instance')
# read default parameters and initialize
syr = Policy.JSON_START_YEAR
nyrs = Policy.DEFAULT_NUM_YEARS
nyrs = last_budget_year - syr + 1
Policy.NUM_YEARS = nyrs
self._inflation_rates = None
self._wage_growth_rates = None
self.initialize(syr, nyrs, Policy.LAST_KNOWN_YEAR,
Expand All @@ -101,7 +103,8 @@ def __init__(self, gfactors=None, **kwargs):
Policy.WAGE_INDEXED_PARAMS, **kwargs)

@staticmethod
def tmd_constructor(growfactors: Path | GrowFactors): # pragma: no cover
def tmd_constructor(growfactors: Path | GrowFactors,
last_budget_year=DEFAULT_LAST_BUDGET_YEAR): # pragma: no cover
"""
Static method returns a Policy object instantiated with TMD
input data. This convenience method works in a analogous way
Expand All @@ -112,7 +115,8 @@ def tmd_constructor(growfactors: Path | GrowFactors): # pragma: no cover
growfactors = GrowFactors(growfactors_filename=str(growfactors))
else:
assert isinstance(growfactors, GrowFactors)
return Policy(gfactors=growfactors)
return Policy(gfactors=growfactors,
last_budget_year=last_budget_year)

@staticmethod
def read_json_reform(obj):
Expand Down
31 changes: 23 additions & 8 deletions taxcalc/taxcalcio.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@ class TaxCalcIO():
string is name of INPUT file that is CSV formatted containing
variable names in the Records USABLE_READ_VARS set, or
Pandas DataFrame is INPUT data containing variable names in
the Records USABLE_READ_VARS set. INPUT vsrisbles not in the
the Records USABLE_READ_VARS set. INPUT variables not in the
Records USABLE_READ_VARS set can be present but are ignored.

tax_year: integer
calendar year for which taxes will be computed for INPUT.

budget_end_year: integer
last calendar year in the budget window for which taxes will
be computed for INPUT.

baseline: None or string
None implies baseline policy is current-law policy, or
string is name of optional BASELINE file that is a JSON
Expand All @@ -64,8 +68,8 @@ class instance: TaxCalcIO
"""
# pylint: disable=too-many-instance-attributes

def __init__(self, input_data, tax_year, baseline, reform, assump,
outdir=None):
def __init__(self, input_data, tax_year, budget_end_year, baseline,
reform, assump, outdir=None):
# pylint: disable=too-many-arguments,too-many-locals
# pylint: disable=too-many-branches,too-many-statements
self.gf_reform = None
Expand Down Expand Up @@ -228,8 +232,8 @@ def __init__(self, input_data, tax_year, baseline, reform, assump,
self.param_dict = None
self.policy_dicts = []

def init(self, input_data, tax_year, baseline, reform, assump,
aging_input_data, exact_calculations):
def init(self, input_data, tax_year, budget_end_year, baseline,
reform, assump, aging_input_data, exact_calculations):
"""
TaxCalcIO class post-constructor method that completes initialization.

Expand All @@ -253,6 +257,11 @@ def init(self, input_data, tax_year, baseline, reform, assump,
basedict = Calculator.read_json_param_objects(baseline, None)
# get assumption sub-dictionaries
paramdict = Calculator.read_json_param_objects(None, assump)
# Set budget window end year
if budget_end_year is None:
budget_end_year = Policy.DEFAULT_LAST_BUDGET_YEAR
else:
Policy.DEFAULT_LAST_BUDGET_YEAR = budget_end_year
# get policy parameter dictionaries from --reform file(s)
policydicts = []
if self.specified_reform:
Expand Down Expand Up @@ -292,7 +301,10 @@ def init(self, input_data, tax_year, baseline, reform, assump,
self.gf_reform = copy.deepcopy(gfactors_ref)
# create Policy objects:
# ... the baseline Policy object
base = Policy(gfactors=gfactors_base)
print("GF BASE = ", gfactors_base.last_year, max(gfactors_base.gfdf.index))
print("GF BASE = ", gfactors_base.last_year)
base = Policy(gfactors=gfactors_base,
last_budget_year=budget_end_year)
try:
base.implement_reform(basedict['policy'],
print_warnings=True,
Expand All @@ -303,7 +315,8 @@ def init(self, input_data, tax_year, baseline, reform, assump,
self.errmsg += valerr_msg.__str__()
# ... the reform Policy object
if self.specified_reform:
pol = Policy(gfactors=gfactors_ref)
pol = Policy(gfactors=gfactors_ref,
last_budget_year=budget_end_year)
for poldict in policydicts:
try:
pol.implement_reform(poldict,
Expand All @@ -316,7 +329,8 @@ def init(self, input_data, tax_year, baseline, reform, assump,
except paramtools.ValidationError as valerr_msg:
self.errmsg += valerr_msg.__str__()
else:
pol = Policy(gfactors=gfactors_base)
pol = Policy(gfactors=gfactors_base,
last_budget_year=budget_end_year)
# create Consumption object
con = Consumption()
try:
Expand Down Expand Up @@ -393,6 +407,7 @@ def init(self, input_data, tax_year, baseline, reform, assump,
msg = msg.format(tax_year, recs.data_year)
self.errmsg += 'ERROR: {}\n'.format(msg)
# create Calculator objects
print("POLICY YEAR = ", pol.DEFAULT_LAST_BUDGET_YEAR)
self.calc = Calculator(policy=pol, records=recs,
verbose=True,
consumption=con,
Expand Down
Loading
Loading