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 a Policy object's last budget year be flexible #2856

Merged
merged 12 commits into from
Dec 18, 2024

Conversation

martinholmer
Copy link
Collaborator

@martinholmer martinholmer commented Dec 16, 2024

The LAST_BUDGET_YEAR, which is a constant attribute of the Policy class, is currently set to 2034. There is a need to be able to instantiate Policy objects that have their last budget year different from LAST_BUDGET_YEAR. The main need is to be able to use TMD input data that include weights and growfactors extending out to 2074. For much of 2024 the only way to use the TMD data to simulate beyond 2034 was to create a customized version of Tax-Calculator using the code on the thru74 branch in PR #2755.

Recently, @jdebacker had the vision to see that there was a way to revise Tax-Calculator code so that by default it would use LAST_BUDGET_YEAR but the code would have the flexibility to allow users to specify Policy objects with last budget year greater (or less) than LAST_BUDGET_YEAR. @jdebacker worked with @hdoupe to revise ParamTools, which is the foundation of the Policy class, so that it would be possible to add this flexibility. Then in PR #2846, @jdebacker implemented the code changes for the Python API made possible with the new ParamTools 0.19.0 version. This PR builds on @jdebacker's PR #2846.

The remaining minor task of using the new Python API in taxcalcio.py to make the Tax-Calculator CLI tool, tc, have the same last budget year flexibility is being handled by @martinholmer, who is a frequent CLI user.

.

The new flexibility added in this PR is illustrated below with two different examples:

  • estimating 2070 income tax revenue under a 2060 reform that increased aggregate wages using the Python API is demonstrated in this comment
  • estimating 2070 income tax revenue under current-law policy using the CLI tool, tc, is demonstrated in this comment

Also, the 2070 results generated in these two examples were compared to 2070 results generated by a custom Tax-Calculator package constructed using the thru74 branch (in PR #2755. The results were identical as expected.

@martinholmer martinholmer marked this pull request as draft December 16, 2024 23:25
@martinholmer martinholmer changed the title Make last budget year flexible Make a Policy object's last budget year flexible Dec 16, 2024
Copy link

codecov bot commented Dec 16, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.42%. Comparing base (57e0f62) to head (43464dd).
Report is 13 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2856   +/-   ##
=======================================
  Coverage   99.42%   99.42%           
=======================================
  Files          13       13           
  Lines        2618     2625    +7     
=======================================
+ Hits         2603     2610    +7     
  Misses         15       15           
Flag Coverage Δ
unittests 99.42% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
taxcalc/__init__.py 100.00% <100.00%> (ø)
taxcalc/consumption.py 100.00% <100.00%> (ø)
taxcalc/growdiff.py 100.00% <100.00%> (ø)
taxcalc/parameters.py 100.00% <100.00%> (ø)
taxcalc/policy.py 100.00% <100.00%> (ø)
taxcalc/taxcalcio.py 100.00% <100.00%> (ø)

@martinholmer martinholmer changed the title Make a Policy object's last budget year flexible Make a Policy object's last budget year be flexible Dec 17, 2024
@martinholmer
Copy link
Collaborator Author

This comment illustrates how to use the new features in PR #2856 with the Python API.
This example uses the TMD data files to estimate 2070 income taxes after a 2060 reform that is assumed to increase wages.

(taxcalc-dev) tmd% pushd ~/work/Tax-Calculator; make clean; make package; git branch; popd
---[SNIP]---
Successfully installed taxcalc-4.3.5
* flexible-last-budget-year
  master
  thru74


(taxcalc-dev) tmd% tc --version
Tax-Calculator 4.3.5a on Python 3.11


(taxcalc-dev) tmd% cat iitax2070complex.py
"""
Script for testing Python API to Tax-Calculator when using TMD input data.
"""

from pathlib import Path
import taxcalc as tc

TAX_CALC_YEAR = 2070
REFORM_YEAR = TAX_CALC_YEAR - 10
USE_REFORM = True
REFORM = {"II_em": {REFORM_YEAR: 30e3}}
USE_ASSUMP_GDF = True
ASSUMP_GDF = {"AWAGE": {(REFORM_YEAR+1): 0.02, (REFORM_YEAR+2): 0.0}}
USE_ASSUMP_CON = True
ASSUMP_CON = {"MPC_e18400": {TAX_CALC_YEAR: 0.2}}

ID_PATH = Path(".") / "tmd.csv"
WT_PATH = Path(".") / "tmd_weights.csv.gz"
GF_PATH = Path(".") / "tmd_growfactors.csv"

# show nature of testing
print("TAX_CALC_YEAR=", TAX_CALC_YEAR)
print("NUM_YEARS=", tc.Policy.number_of_years(TAX_CALC_YEAR))
print("USE_ASSUMP_GDF=", USE_ASSUMP_GDF)
if USE_ASSUMP_GDF:
    print("ASSUMP_GDF=", ASSUMP_GDF)
print("USE_REFORM=", USE_REFORM)
if USE_REFORM:
    print("REFORM=", REFORM)
print("USE_ASSUMP_CON=", USE_ASSUMP_CON)
if USE_ASSUMP_CON:
    print("ASSUMP_CON=", ASSUMP_CON)

# construct GrowFactors object
tmd_gf = tc.GrowFactors(growfactors_filename=str(GF_PATH))  # ,callnum=-1)
if USE_ASSUMP_GDF:
    gdiff = tc.GrowDiff(last_budget_year=TAX_CALC_YEAR)
    gdiff.update_growdiff(ASSUMP_GDF)
    gdiff.apply_to(tmd_gf)

# construct Policy object
pol = tc.Policy(gfactors=tmd_gf, last_budget_year=TAX_CALC_YEAR)
assert gdiff.num_years == pol.num_years, "gdiff/pol num years difference"
if USE_REFORM:
    pol.implement_reform(REFORM)

# construct Records object
rec = tc.Records.tmd_constructor(
    data_path=ID_PATH,
    weights_path=WT_PATH,
    growfactors=tmd_gf,
)

# construct Consumption object
con = tc.Consumption(last_budget_year=TAX_CALC_YEAR)
assert con.num_years == pol.num_years, "con/pol num years difference"
if USE_ASSUMP_CON:
    con.update_consumption(ASSUMP_CON)

# construct Calculator object and calculate iitax for TAX_CALC_YEAR
cal = tc.Calculator(policy=pol, records=rec, consumption=con)
cal.advance_to_year(TAX_CALC_YEAR)
cal.calc_all()
print("weighted_iitax_in_2070($B)=", cal.weighted_total("iitax") * 1e-9)
_, mtr_inctax, _ = cal.mtr(calc_all_already_called=True,
                           wrt_full_compensation=False)
print("unweighted_mean_iitax_mtr(%)=", mtr_inctax.mean() * 100)


(taxcalc-dev) tmd% python iitax2070complex.py
TAX_CALC_YEAR= 2070
NUM_YEARS= 58
USE_ASSUMP_GDF= True
ASSUMP_GDF= {'AWAGE': {2061: 0.02, 2062: 0.0}}
USE_REFORM= True
REFORM= {'II_em': {2060: 30000.0}}
USE_ASSUMP_CON= True
ASSUMP_CON= {'MPC_e18400': {2070: 0.2}}
weighted_iitax_in_2070($B)= 16266.357432433406
unweighted_mean_iitax_mtr(%)= 22.30313711942477

@martinholmer
Copy link
Collaborator Author

This comment illustrates how to use the new features in PR #2856 with the CLI tool, tc.
This example uses the TMD data files to estimate 2070 income taxes under current-law policy. The CLI result is then compared to the results generated by a script using the Python API to ensure both produce the same result.

(taxcalc-dev) tmd% pushd ~/work/Tax-Calculator; make clean; make package; git branch; popd
---[SNIP]---
Successfully installed taxcalc-4.3.5
* flexible-last-budget-year
  master
  thru74


(taxcalc-dev) tmd% tc --version
Tax-Calculator 4.3.5a on Python 3.11


(taxcalc-dev) tmd% tc tmd.csv 2070
You loaded data for 2021.
Tax-Calculator startup automatically extrapolated your data to 2070.


(taxcalc-dev) tmd% awk -F, 'NR>1{t+=$3*$4}END{print t*1e-9}' tmd-70-\#-\#-\#.csv
16823.2


(taxcalc-dev) tmd% cat iitax2070simple.py
"""
Script for testing Python API to Tax-Calculator when using TMD input data.
"""

from pathlib import Path
import taxcalc as tc

TAX_CALC_YEAR = 2070

ID_PATH = Path(".") / "tmd.csv"
WT_PATH = Path(".") / "tmd_weights.csv.gz"
GF_PATH = Path(".") / "tmd_growfactors.csv"

# show nature of testing
print("TAX_CALC_YEAR=", TAX_CALC_YEAR)
print("NUM_YEARS=", tc.Policy.number_of_years(TAX_CALC_YEAR))

# construct GrowFactors object
tmd_gf = tc.GrowFactors(growfactors_filename=str(GF_PATH))

# construct Policy object
pol = tc.Policy(gfactors=tmd_gf, last_budget_year=TAX_CALC_YEAR)

# construct Records object
rec = tc.Records.tmd_constructor(
    data_path=ID_PATH,
    weights_path=WT_PATH,
    growfactors=tmd_gf,
)

# construct Consumption object
con = tc.Consumption(last_budget_year=TAX_CALC_YEAR)
assert con.num_years == pol.num_years, "con/pol num years difference"

# construct Calculator object and calculate iitax for TAX_CALC_YEAR
cal = tc.Calculator(policy=pol, records=rec, consumption=con)
cal.advance_to_year(TAX_CALC_YEAR)
cal.calc_all()
print("weighted_iitax_in_2070($B)=", cal.weighted_total("iitax") * 1e-9)


(taxcalc-dev) tmd% python iitax2070simple.py
TAX_CALC_YEAR= 2070
NUM_YEARS= 58
weighted_iitax_in_2070($B)= 16823.15713887123

@martinholmer martinholmer marked this pull request as ready for review December 17, 2024 21:53
Co-authored-by: jdebacker <no-reply>
@jdebacker
Copy link
Member

@martinholmer Thanks for improving upon PR #2846. Everything looks good here and I've confirmed all local tests and CLI examples. Merging.

@jdebacker jdebacker merged commit 870db89 into PSLmodels:master Dec 18, 2024
13 of 16 checks passed
@martinholmer martinholmer deleted the flexible-last-budget-year branch December 18, 2024 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants