diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 76a9b21ae..c1c4ac08e 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -34,7 +34,7 @@ jobs: shell: bash -l {0} working-directory: ./ run: | - pytest -m 'not requires_pufcsv and not requires_tmdcsv and not pre_release and not local' --cov=./ --cov-report=xml + pytest -m 'not requires_pufcsv and not pre_release and not local' --cov=./ --cov-report=xml - name: Upload coverage to Codecov if: matrix.os == 'ubuntu-latest' && contains(github.repository, 'PSLmodels/Tax-Calculator') uses: codecov/codecov-action@v4 diff --git a/MANIFEST.in b/MANIFEST.in index e74b337ce..0ed740b96 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,5 +7,3 @@ include taxcalc/policy_current_law.json include taxcalc/puf_weights.csv.gz include taxcalc/puf_ratios.csv include taxcalc/records_variables.json -include taxcalc/tmd_weights.csv.gz -include taxcalc/tmd_growfactors.csv diff --git a/Makefile b/Makefile index dcf83aeb9..778d70226 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ help: @echo "clean : remove .pyc files and local taxcalc package" @echo "package : build and install local package" @echo "pytest-cps : generate report for and cleanup after" - @echo " pytest -m 'not requires_pufcsv and not requires_tmdcsv and not pre_release'" + @echo " pytest -m 'not requires_pufcsv and not pre_release'" @echo "pytest : generate report for and cleanup after" @echo " pytest -m 'not pre_release'" @echo "pytest-all : generate report for and cleanup after" @@ -51,7 +51,7 @@ endef .PHONY=pytest-cps pytest-cps: @$(pytest-setup) - @cd taxcalc ; pytest -n4 --disable-warnings --durations=0 --durations-min=2 -m "not requires_pufcsv and not requires_tmdcsv and not pre_release" + @cd taxcalc ; pytest -n4 --disable-warnings --durations=0 --durations-min=2 -m "not requires_pufcsv and not pre_release" @$(pytest-cleanup) .PHONY=pytest @@ -103,7 +103,7 @@ define coverage-cleanup rm -f .coverage htmlcov/* endef -COVMARK = "not requires_pufcsv and not requires_tmdcsv and not pre_release" +COVMARK = "not requires_pufcsv and not pre_release" OS := $(shell uname -s) diff --git a/codecov.yml b/codecov.yml index 70cbddd52..481a8d37d 100644 --- a/codecov.yml +++ b/codecov.yml @@ -21,5 +21,6 @@ comment: ignore: - "setup.py" + - "update_pcl.py" - "ppp.py" - "extend_tcja.py" diff --git a/docs/about/releases.md b/docs/about/releases.md index c6ce2af8f..3489c2659 100644 --- a/docs/about/releases.md +++ b/docs/about/releases.md @@ -3,6 +3,29 @@ Release history Go [here](https://github.com/PSLmodels/Tax-Calculator/pulls?q=is%3Apr+is%3Aclosed) for a complete commit history. + +2024-10-02 Release 4.3.0 +------------------------ +(last merged pull request is +[#2819](https://github.com/PSLmodels/Tax-Calculator/pull/2819)) + +**This is an enhancement and bug-fix release.** + +**API Changes** + +**New Features** +- Add known values of inflation-indexed policy parameters for 2023 [[#2806](https://github.com/PSLmodels/Tax-Calculator/pull/2806) by Martin Holmer] +- Enhance `Records.tmd_constructor` static method [[#2809](https://github.com/PSLmodels/Tax-Calculator/pull/2809) by Martin Holmer] +- Remove TMD data files from Tax-Calculator repository [[#2810](https://github.com/PSLmodels/Tax-Calculator/pull/2810) by Martin Holmer] +- Add known values of inflation-indexed policy parameters for 2024 [[#2816](https://github.com/PSLmodels/Tax-Calculator/pull/2816) by Martin Holmer] +- Enhance `extend_tcja.py` and update `reforms/ext.json` [[#2817](https://github.com/PSLmodels/Tax-Calculator/pull/2817) by Martin Holmer] +- Enhance `ppp.py` script [[#2819](https://github.com/PSLmodels/Tax-Calculator/pull/2819) by Martin Holmer] + +**Bug Fixes** +- Fix specification of domestic production deduction under TCJA [[#2807](https://github.com/PSLmodels/Tax-Calculator/pull/2807) by Martin Holmer] +- Fix `ALD_BusinessLosses_c` parameter values after 2025 [[#2818](https://github.com/PSLmodels/Tax-Calculator/pull/2818) by Martin Holmer] + + 2024-09-14 Release 4.2.2 ------------------------ (last merged pull request is diff --git a/docs/contributing/RELEASING.md b/docs/contributing/RELEASING.md index 59e43c0a0..8f6c3cf9d 100755 --- a/docs/contributing/RELEASING.md +++ b/docs/contributing/RELEASING.md @@ -1,10 +1,12 @@ Releasing Tax-Caclculator Packages ================================== -The following outlines the process to release Tax-Calculator Packages on Conda-Forge and creating a new branch to fix a bug in a previous release. +The following outlines the process to release Tax-Calculator Packages +on Conda-Forge and creating a new branch to fix a bug in a previous +release. Create new `taxcalc` packages -=========================== +============================= ``` --> on branch X-Y-Z, edit docs/about/releases.md to finalize X.Y.Z info @@ -13,6 +15,12 @@ Create new `taxcalc` packages --> merge master branch into X-Y-Z branch +--> run `python update_pcl.py` [to update policy_current_law.json if needed] + +--> run `python ppp.py` [to update policy_current_law.json if needed] + +--> run `python extend_tcja.py > ext.json` [to update reforms/ext.json] + --> run `make tctest-jit` [to make sure JIT decorators are not hiding bugs] --> run `make pytest-all` [or `pytest -m pre_release -n4` in taxcalc subdir] diff --git a/docs/index.md b/docs/index.md index 4f97f63b4..f9915742b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -57,7 +57,7 @@ The cross-model validation work with NBER's TAXSIM-27 model is described ## Latest release -{doc}`4.2.2 (2024-09-14) ` +{doc}`4.3.0 (2024-10-02) ` If you are already using Tax-Calculator, upgrade using the following command: diff --git a/docs/usage/data.md b/docs/usage/data.md index b55e19239..13d387f33 100644 --- a/docs/usage/data.md +++ b/docs/usage/data.md @@ -61,13 +61,16 @@ file. The [tax-microdata repository](https://github.com/PSLmodels/tax-microdata-benchmarking) -produces an input variables file (`tmd.csv`) and a -`tmd_weights.csv.gz` file that is included in the Tax-Calculator +produces an input variables file (`tmd.csv`), a national weights file +(`tmd_weights.csv.gz`), and a variable growth factors file +(`tmd_growfactors.csv`) that can be used with the Tax-Calculator package beginning with the 3.6.0 release. The `tmd.csv` file is available only to Tax-Calculator users who have purchased their own -version of the 2015 IRS-SOI PUF. For those users, the -`Records.tmd_constructor()` method creates a `Records` class object -containing the `tmd` variables and weights. +version of the 2015 IRS-SOI PUF. For those users, those three files +are avaiable from the tax-microdata repository. These three tmd files +can be used with the Tax-Calculator Python API (using the +`Records.tmd_constructor()` static method) or with the Tax-Calculator +CLI tool, `tc`. ## Using other data with Tax-Calculator diff --git a/extend_tcja.py b/extend_tcja.py index af3e3391d..7246e379a 100644 --- a/extend_tcja.py +++ b/extend_tcja.py @@ -3,10 +3,15 @@ extend_tcja.json, that can serve as an alternative baseline to current-law policy (which ends TCJA temporary provisions after 2025). -USAGE: (taxcalc-dev) ~% python extend_tcja.py +USAGE: (taxcalc-dev) Tax-Calculator% python extend_tcja.py > ext.json + THEN CHECK: % diff ext.json taxcalc/reforms/ext.json + IF DIFFS: % mv ext.json taxcalc/reforms/ext.json -IMPORTANT NOTE: be sure to remove the trailing comma after the last item - in the reform JSON object generated by this script. +WHEN TO USE: use this script to update reforms/ext.json in these situations: +(a) whenever inflation rates in the growfactors.csv files are changed +OR +(b) whenever inflation-indexed parameters are updated (usually as part + of changes that increase the value of Policy.LAST_KNOWN_YEAR). """ import sys @@ -76,7 +81,6 @@ "PT_qbid_alt_property_rt": {"indexed": False, "category": 7}, # category 8 ... "ALD_BusinessLosses_c": {"indexed": True, "category": 8}, - "ALD_DomesticProduction_hc": {"indexed": False, "category": 8}, } @@ -84,10 +88,13 @@ def main(): """ High-level script logic. """ + # identify last parameter name in TCJA_PARAMETERS + last_pname = list(TCJA_PARAMETERS.keys())[-1] # calculate 2025-to-2026 parameters indexing factor pol = taxcalc.Policy() pirates = pol.inflation_rates() - ifactor = 1.0 + pirates[2025-taxcalc.Policy.JSON_START_YEAR] + ifactor25 = 1.0 + pirates[2025-taxcalc.Policy.JSON_START_YEAR] + ifactor28 = 1.0 + pirates[2028-taxcalc.Policy.JSON_START_YEAR] # specify extend-TCJA-beyond-2025 reform # ... get 2025 parameter values pol.set_year(2025) @@ -95,45 +102,61 @@ def main(): # ... write reform header comments print( '// REFORM TO EXTEND TEMPORARY TCJA PROVISIONS BEYOND 2025') print(f'// USING TAX-CALCULATOR {taxcalc.__version__}') - print(f'// WITH 2025-to-2026 INDEXING FACTOR = {ifactor:.6f}') + print(f'// WITH 2025-to-2026 INDEXING FACTOR = {ifactor25:.6f}') + print(f'// AND 2028-to-2029 INDEXING FACTOR = {ifactor28:.6f}') if TCJA_CATEGORY: print(f'// ONLY TCJA PROVISIONS IN CATEGORY {TCJA_CATEGORY}') print('{') - # ... set 2026 nonreverted values for the parameters set to revert + # ... set 2026/29 nonreverted values for the parameters set to revert + left_brace = '{' + right_brace = '}' + year = 2026 for pname, pinfo in TCJA_PARAMETERS.items(): if TCJA_CATEGORY and pinfo['category'] != TCJA_CATEGORY: continue # skip this parameter + if pname == 'ALD_BusinessLosses_c': + ifactor = ifactor28 + year = 2029 + pol.set_year(2028) + pdata = dict(pol.items()) + else: + if year != 2026: + pol.set_year(2025) + pdata = dict(pol.items()) + ifactor = ifactor25 + year = 2026 + trailing_comma = '' if pname == last_pname else ',' if pinfo['indexed']: pval = pdata[pname][0] * ifactor if isinstance(pval, numpy.ndarray): # handle vector parameter pval = numpy.minimum(9e99, pval.round(2)) sys.stdout.write(f' "{pname}": ') - sys.stdout.write('{"2026": ') + sys.stdout.write(f'{left_brace}"{year}": ') sys.stdout.write(f'{pval.tolist()}') - sys.stdout.write('},\n') + sys.stdout.write(f'{right_brace}{trailing_comma}\n') else: # handle scalar parameter pval = min(9e99, pval) sys.stdout.write(f' "{pname}": ') - sys.stdout.write('{"2026": ') + sys.stdout.write(f'{left_brace}"{year}": ') sys.stdout.write(f'{pval*ifactor:.2f}') - sys.stdout.write('},\n') + sys.stdout.write(f'{right_brace}{trailing_comma}\n') else: # if parameter is not indexed pval = pdata[pname][0] if isinstance(pval, numpy.ndarray): # handle vector parameter pval = numpy.minimum(9e99, pval.round(2)) sys.stdout.write(f' "{pname}": ') - sys.stdout.write('{"2026": ') + sys.stdout.write(f'{left_brace}"{year}": ') sys.stdout.write(f'{pval.tolist()}') - sys.stdout.write('},\n') + sys.stdout.write(f'{right_brace}{trailing_comma}\n') else: # handle scalar parameter sys.stdout.write(f' "{pname}": ') - sys.stdout.write('{"2026": ') + sys.stdout.write(f'{left_brace}"{year}": ') sys.stdout.write(f'{pval:.2f}') - sys.stdout.write('},\n') + sys.stdout.write(f'{right_brace}{trailing_comma}\n') print('}') return 0 # end main function code diff --git a/ppp.py b/ppp.py index 9ff2df5c1..b31a6eb82 100644 --- a/ppp.py +++ b/ppp.py @@ -1,77 +1,138 @@ """ -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. +This 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). -USAGE: $ python ppp.py +USAGE: (taxcalc-dev) T-C% python ppp.py +THEN CHECK: % diff pcl.json taxcalc/policy_current_law.json +IF DIFFS OK % mv pcl.json taxcalc/policy_current_law.json -Note: running this script will write the new 2026 parameter values -directly to policy_current_law.json. So, if you want to compare -the new 2026 parameter values with the old 2026 parameter values, -be sure to copy policy_current_law.json before running this script. +WHEN TO USE: use this script to update taxcalc/policy_current_law.json +whenever post-2016 inflation rates in the growfactors.csv files are changed. """ -import json -import collections + +import sys +import re +from pathlib import Path from taxcalc import Policy -params = Policy() +REVERTING_PARAMS = { + 'ALD_BusinessLosses_c': 2029, + 'II_em': 2026, + 'II_em_ps': 2026, + 'STD': 2026, + 'ID_AllTaxes_c': 2026, + 'ID_ps': 2026, + 'II_brk1': 2026, + 'II_brk2': 2026, + 'II_brk3': 2026, + 'II_brk4': 2026, + 'II_brk5': 2026, + 'II_brk6': 2026, + 'II_brk7': 2026, + 'PT_brk1': 2026, + 'PT_brk2': 2026, + 'PT_brk3': 2026, + 'PT_brk4': 2026, + 'PT_brk5': 2026, + 'PT_brk6': 2026, + 'PT_brk7': 2026, + 'PT_qbid_taxinc_thd': 2026, + 'AMT_em': 2026, + 'AMT_em_ps': 2026, + 'AMT_em_pe': 2026, +} +MARS_VALUES = ['single', 'mjoint', 'mseparate', 'headhh', 'widow'] +PYEAR = 2017 # prior year before TCJA first implemented +FYEAR = 2026 # final year in which parameter values revert -# 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'] -# 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): - yindex = year - params.start_year - rate = params._inflation_rates[yindex] # pylint: disable=protected-access - FINAL_IFACTOR *= 1 + rate +def cumulative_ifactor(): + """ + Return PYEAR-to_FYEAR inflation factor. + """ + pol = Policy() + # calculate the inflation factor used to calculate the + # inflation-adjusted 2026 reverting parameter values + # NOTE: pvalue[t+1] = pvalue[t] * ( 1 + irate[t] ) + cum_ifactor = 1.0 + for year in range(PYEAR, FYEAR): + # pylint: disable=protected-access + rate = pol._inflation_rates[year - pol.start_year] + cum_ifactor *= 1.0 + rate + return cum_ifactor -long_param_vals = collections.defaultdict(list) -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, +def integrate_fragments(fragments): + """ + Integrate specified fragments with the policy_current_law.json text. + """ + p_c_l_path = Path('.') / 'taxcalc' / 'policy_current_law.json' + with open(p_c_l_path, 'r', encoding='utf-8') as ofile: + olines = ofile.readlines() + # pylint: disable=consider-using-with + nfile = open('pcl.json', 'w', encoding='utf-8') + re_param_line = re.compile(r'^\s{4}"(\w+)": {$') + re_ryear26_line = re.compile(r'^\s{16}"year": 2026,$') + re_ryear29_line = re.compile(r'^\s{16}"year": 2029,$') + re_value_line = re.compile(r'^\s{16}"value":') + writing_oline = True + pname_has_fragments = False + for oline in olines: + pmatch = re_param_line.search(oline) + if pmatch: + pname = pmatch.group(1) + pname_has_fragments = pname in fragments + if pname_has_fragments: + if fragments[pname][0]['year'] == 2026: + re_ryear_line = re_ryear26_line + else: + re_ryear_line = re_ryear29_line + idx = -1 + elif pname_has_fragments: + ymatch = re_ryear_line.search(oline) + if ymatch: + idx += 1 + if pname_has_fragments and idx >= 0: + if re_value_line.search(oline): + writing_oline = False + else: + writing_oline = True + if writing_oline: + nfile.write(oline) + else: + nfile.write( + f' "value": {fragments[pname][idx]["value"]}\n' ) - ) + nfile.close() + return 0 + + +def main(): + """ + High-level script logic. + """ + ifactor = cumulative_ifactor() + + # construct policy_current_law.json revert-year fragments + # for each reverting parameter in a fragments dictionary + fragments = {} + parameters = Policy() + for pname, ryear in REVERTING_PARAMS.items(): + vos = parameters.select_eq(pname, year=PYEAR) + frag_list = [] + for vo in vos: + rval = min(9e99, round(vo['value'] * ifactor, 0)) + frag_list.append({'year': ryear, 'value': rval}) + fragments[pname] = frag_list -# 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) + # integrate fragment info into existing policy_current_law.json + rcode = integrate_fragments(fragments) -# read existing policy_current_law.json -with open('taxcalc/policy_current_law.json', 'r', encoding='utf-8') as pcl_old: - pcl = json.load(pcl_old) + # return exit code returned by integrate_fragments function + return rcode +# end main function code -# replace 2026 values in the pcl dictionary -for param in param_data: - pcl[param]["value"] = param_data[param] -# write new pcl dictionary to policy_current_law.json -with open('taxcalc/policy_current_law.json', 'w', encoding='utf-8') as pcl_new: - json.dump(pcl, pcl_new, indent=4) - pcl_new.write('\n') +if __name__ == '__main__': + sys.exit(main()) diff --git a/pytest.ini b/pytest.ini index f40bfdba7..3f6fa6b8b 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,14 +3,14 @@ testpaths = taxcalc markers = requires_pufcsv - requires_tmdcsv pre_release - compatible_data local benefits - itmded_vars + compatible_data cpscsv_agg + extend_tcja + itmded_vars pufcsv_agg reforms rtr - extend_tcja + stded diff --git a/setup.py b/setup.py index 168700c24..1e437afc2 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ with open("README.md") as f: longdesc = f.read() -version = "4.2.2" +version = "4.3.0" config = { "description": "Tax Calculator", diff --git a/taxcalc.egg-info/PKG-INFO b/taxcalc.egg-info/PKG-INFO index 2ed490aa9..b93fe2de9 100644 --- a/taxcalc.egg-info/PKG-INFO +++ b/taxcalc.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: taxcalc -Version: 4.2.2 +Version: 4.3.0 Summary: taxcalc Home-page: https://github.com/PSLmodels/Tax-Calculator Download-URL: https://github.com/PSLmodels/Tax-Calculator diff --git a/taxcalc.egg-info/SOURCES.txt b/taxcalc.egg-info/SOURCES.txt index 1d6021c0a..6937d2e4c 100644 --- a/taxcalc.egg-info/SOURCES.txt +++ b/taxcalc.egg-info/SOURCES.txt @@ -121,8 +121,6 @@ taxcalc/puf_weights.csv.gz taxcalc/records.py taxcalc/records_variables.json taxcalc/taxcalcio.py -taxcalc/tmd_growfactors.csv -taxcalc/tmd_weights.csv.gz taxcalc/utils.py taxcalc/utilsprvt.py taxcalc.egg-info/PKG-INFO @@ -173,8 +171,6 @@ taxcalc/reforms/ptaxes2.json taxcalc/reforms/ptaxes2.out.csv taxcalc/reforms/ptaxes3.json taxcalc/reforms/ptaxes3.out.csv -taxcalc/reforms/rounding2022.json -taxcalc/reforms/rounding2022.out.csv taxcalc/reforms/archive/Clinton2016.json taxcalc/reforms/archive/RyanBrady.json taxcalc/reforms/archive/TCJA_House.json @@ -214,7 +210,6 @@ taxcalc/tests/test_records.py taxcalc/tests/test_reforms.py taxcalc/tests/test_responses.py taxcalc/tests/test_taxcalcio.py -taxcalc/tests/test_tmdcsv.py taxcalc/tests/test_utils.py taxcalc/validation/CSV_INPUT_VARS.md taxcalc/validation/CSV_OUTPUT_VARS.md diff --git a/taxcalc/__init__.py b/taxcalc/__init__.py index 99296938d..044f29d19 100644 --- a/taxcalc/__init__.py +++ b/taxcalc/__init__.py @@ -14,4 +14,4 @@ from taxcalc.utils import * from taxcalc.cli import * -__version__ = '4.2.2' +__version__ = '4.3.0' diff --git a/taxcalc/policy.py b/taxcalc/policy.py index c0aefa806..ad9b69d89 100644 --- a/taxcalc/policy.py +++ b/taxcalc/policy.py @@ -37,7 +37,7 @@ class instance: Policy DEFAULTS_FILE_NAME = 'policy_current_law.json' DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__)) JSON_START_YEAR = 2013 # remains the same unless earlier data added - LAST_KNOWN_YEAR = 2022 # last year for which indexed param vals are known + LAST_KNOWN_YEAR = 2024 # 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 diff --git a/taxcalc/policy_current_law.json b/taxcalc/policy_current_law.json index 2cc95f940..14fb6b27d 100644 --- a/taxcalc/policy_current_law.json +++ b/taxcalc/policy_current_law.json @@ -218,6 +218,14 @@ { "year": 2022, "value": 147000.0 + }, + { + "year": 2023, + "value": 160200.0 + }, + { + "year": 2024, + "value": 168600.0 } ], "validators": { @@ -953,26 +961,6 @@ { "year": 2018, "value": 1.0 - }, - { - "year": 2019, - "value": 1.0 - }, - { - "year": 2020, - "value": 1.0 - }, - { - "year": 2021, - "value": 1.0 - }, - { - "year": 2022, - "value": 1.0 - }, - { - "year": 2026, - "value": 0.0 } ], "validators": { @@ -1149,6 +1137,14 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 + }, + { + "year": 2024, + "value": 0.0 } ], "validators": { @@ -1211,6 +1207,14 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 + }, + { + "year": 2024, + "value": 0.0 } ], "validators": { @@ -1532,27 +1536,77 @@ "value": 540000.0 }, { - "year": 2026, + "year": 2023, + "MARS": "single", + "value": 289000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 578000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 289000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 289000.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 578000.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 305000.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 610000.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 305000.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 305000.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 610000.0 + }, + { + "year": 2029, "MARS": "single", "value": 9e+99 }, { - "year": 2026, + "year": 2029, "MARS": "mjoint", "value": 9e+99 }, { - "year": 2026, + "year": 2029, "MARS": "mseparate", "value": 9e+99 }, { - "year": 2026, + "year": 2029, "MARS": "headhh", "value": 9e+99 }, { - "year": 2026, + "year": 2029, "MARS": "widow", "value": 9e+99 } @@ -1618,6 +1672,14 @@ "year": 2022, "value": 0.0 }, + { + "year": 2023, + "value": 0.0 + }, + { + "year": 2024, + "value": 0.0 + }, { "year": 2026, "value": 5300.0 @@ -1894,6 +1956,56 @@ "MARS": "widow", "value": 9e+99 }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 + }, { "year": 2026, "MARS": "single", @@ -2243,6 +2355,56 @@ "MARS": "widow", "value": 25900.0 }, + { + "year": 2023, + "MARS": "single", + "value": 13850.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 27700.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 13850.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 20800.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 27700.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 14600.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 29200.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 14600.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 21900.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 29200.0 + }, { "year": 2026, "MARS": "single", @@ -2329,6 +2491,14 @@ { "year": 2022, "value": 1150.0 + }, + { + "year": 2023, + "value": 1250.0 + }, + { + "year": 2024, + "value": 1300.0 } ], "validators": { @@ -2601,6 +2771,56 @@ "year": 2022, "MARS": "widow", "value": 1750.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 1800.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 1500.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 1500.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 1800.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 1800.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 1950.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 1550.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 1550.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 1950.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 1950.0 } ], "validators": { @@ -3032,20 +3252,70 @@ "year": 2022, "MARS": "widow", "value": 0.0 - } - ], - "validators": { - "range": { - "min": 0, - "max": 9e+99 - } - }, - "compatible_data": { - "puf": true, - "cps": true - } - }, - "II_credit_ps": { + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 0.0 + } + ], + "validators": { + "range": { + "min": 0, + "max": 9e+99 + } + }, + "compatible_data": { + "puf": true, + "cps": true + } + }, + "II_credit_ps": { "title": "Personal refundable credit phaseout start", "description": "The personal refundable credit amount will be reduced for taxpayers with AGI higher than this threshold level.", "notes": "", @@ -3304,6 +3574,56 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -3602,6 +3922,56 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -3874,6 +4244,56 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -4713,6 +5133,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -5037,6 +5507,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -5361,6 +5881,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -5969,17 +6539,67 @@ "value": 9e+99 }, { - "year": 2022, + "year": 2022, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2022, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2022, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, "MARS": "mseparate", "value": 9e+99 }, { - "year": 2022, + "year": 2024, "MARS": "headhh", "value": 9e+99 }, { - "year": 2022, + "year": 2024, "MARS": "widow", "value": 9e+99 } @@ -6376,6 +6996,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -6775,6 +7445,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -7128,6 +7848,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -7401,6 +8171,56 @@ "MARS": "widow", "value": 9e+99 }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 + }, { "year": 2026, "MARS": "single", @@ -7806,67 +8626,117 @@ "value": 0.0 }, { - "year": 2020, + "year": 2020, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2020, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2020, + "MARS": "widow", + "value": 0.0 + }, + { + "year": 2021, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2021, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2021, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2021, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2021, + "MARS": "widow", + "value": 0.0 + }, + { + "year": 2022, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2022, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2022, "MARS": "mseparate", "value": 0.0 }, { - "year": 2020, + "year": 2022, "MARS": "headhh", "value": 0.0 }, { - "year": 2020, + "year": 2022, "MARS": "widow", "value": 0.0 }, { - "year": 2021, + "year": 2023, "MARS": "single", "value": 0.0 }, { - "year": 2021, + "year": 2023, "MARS": "mjoint", "value": 0.0 }, { - "year": 2021, + "year": 2023, "MARS": "mseparate", "value": 0.0 }, { - "year": 2021, + "year": 2023, "MARS": "headhh", "value": 0.0 }, { - "year": 2021, + "year": 2023, "MARS": "widow", "value": 0.0 }, { - "year": 2022, + "year": 2024, "MARS": "single", "value": 0.0 }, { - "year": 2022, + "year": 2024, "MARS": "mjoint", "value": 0.0 }, { - "year": 2022, + "year": 2024, "MARS": "mseparate", "value": 0.0 }, { - "year": 2022, + "year": 2024, "MARS": "headhh", "value": 0.0 }, { - "year": 2022, + "year": 2024, "MARS": "widow", "value": 0.0 } @@ -8281,6 +9151,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -8709,6 +9629,56 @@ "year": 2022, "MARS": "widow", "value": 83350.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 44625.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 89250.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 44625.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 59750.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 89250.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 47025.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 94050.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 47025.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 63000.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 94050.0 } ], "validators": { @@ -9007,6 +9977,56 @@ "year": 2022, "MARS": "widow", "value": 517200.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 492300.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 553850.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 276900.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 523050.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 553850.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 518900.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 583750.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 291850.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 551350.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 583750.0 } ], "validators": { @@ -9305,6 +10325,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -9573,62 +10643,112 @@ { "year": 2020, "MARS": "headhh", - "value": 53600.0 + "value": 53600.0 + }, + { + "year": 2020, + "MARS": "widow", + "value": 80000.0 + }, + { + "year": 2021, + "MARS": "single", + "value": 40400.0 + }, + { + "year": 2021, + "MARS": "mjoint", + "value": 80800.0 + }, + { + "year": 2021, + "MARS": "mseparate", + "value": 40400.0 + }, + { + "year": 2021, + "MARS": "headhh", + "value": 54100.0 + }, + { + "year": 2021, + "MARS": "widow", + "value": 80800.0 + }, + { + "year": 2022, + "MARS": "single", + "value": 41675.0 + }, + { + "year": 2022, + "MARS": "mjoint", + "value": 83350.0 + }, + { + "year": 2022, + "MARS": "mseparate", + "value": 41675.0 + }, + { + "year": 2022, + "MARS": "headhh", + "value": 55800.0 }, { - "year": 2020, + "year": 2022, "MARS": "widow", - "value": 80000.0 + "value": 83350.0 }, { - "year": 2021, + "year": 2023, "MARS": "single", - "value": 40400.0 + "value": 44625.0 }, { - "year": 2021, + "year": 2023, "MARS": "mjoint", - "value": 80800.0 + "value": 89250.0 }, { - "year": 2021, + "year": 2023, "MARS": "mseparate", - "value": 40400.0 + "value": 44625.0 }, { - "year": 2021, + "year": 2023, "MARS": "headhh", - "value": 54100.0 + "value": 59750.0 }, { - "year": 2021, + "year": 2023, "MARS": "widow", - "value": 80800.0 + "value": 89250.0 }, { - "year": 2022, + "year": 2024, "MARS": "single", - "value": 41675.0 + "value": 47025.0 }, { - "year": 2022, + "year": 2024, "MARS": "mjoint", - "value": 83350.0 + "value": 94050.0 }, { - "year": 2022, + "year": 2024, "MARS": "mseparate", - "value": 41675.0 + "value": 47025.0 }, { - "year": 2022, + "year": 2024, "MARS": "headhh", - "value": 55800.0 + "value": 63000.0 }, { - "year": 2022, + "year": 2024, "MARS": "widow", - "value": 83350.0 + "value": 94050.0 } ], "validators": { @@ -9927,6 +11047,56 @@ "year": 2022, "MARS": "widow", "value": 517200.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 492300.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 553850.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 276900.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 523050.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 553850.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 518900.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 583750.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 291850.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 551350.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 583750.0 } ], "validators": { @@ -10225,6 +11395,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -10339,6 +11559,14 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 + }, + { + "year": 2024, + "value": 0.0 } ], "validators": { @@ -10704,6 +11932,56 @@ "MARS": "widow", "value": 20550.0 }, + { + "year": 2023, + "MARS": "single", + "value": 11000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 22000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 11000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 15700.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 22000.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 11600.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 23200.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 11600.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 16550.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 23200.0 + }, { "year": 2026, "MARS": "single", @@ -11067,6 +12345,56 @@ "MARS": "widow", "value": 83550.0 }, + { + "year": 2023, + "MARS": "single", + "value": 44725.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 89450.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 44725.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 59850.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 89450.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 47150.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 94300.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 47150.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 63100.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 94300.0 + }, { "year": 2026, "MARS": "single", @@ -11423,12 +12751,62 @@ { "year": 2022, "MARS": "headhh", - "value": 89050.0 + "value": 89050.0 + }, + { + "year": 2022, + "MARS": "widow", + "value": 178150.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 95375.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 190750.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 95375.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 95350.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 190750.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 100525.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 201050.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 100525.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 100500.0 }, { - "year": 2022, + "year": 2024, "MARS": "widow", - "value": 178150.0 + "value": 201050.0 }, { "year": 2026, @@ -11793,6 +13171,56 @@ "MARS": "widow", "value": 340100.0 }, + { + "year": 2023, + "MARS": "single", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 364200.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 364200.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 191950.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 383900.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 191950.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 191950.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 383900.0 + }, { "year": 2026, "MARS": "single", @@ -12156,6 +13584,56 @@ "MARS": "widow", "value": 431900.0 }, + { + "year": 2023, + "MARS": "single", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 462500.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 462500.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 243725.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 487450.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 243725.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 243700.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 487450.0 + }, { "year": 2026, "MARS": "single", @@ -12519,6 +13997,56 @@ "MARS": "widow", "value": 647850.0 }, + { + "year": 2023, + "MARS": "single", + "value": 578125.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 693750.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 578125.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 578100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 693750.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 609350.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 731200.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 365600.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 609350.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 731200.0 + }, { "year": 2026, "MARS": "single", @@ -12882,6 +14410,56 @@ "MARS": "widow", "value": 9e+99 }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 + }, { "year": 2026, "MARS": "single", @@ -13271,6 +14849,56 @@ "MARS": "widow", "value": 20550.0 }, + { + "year": 2023, + "MARS": "single", + "value": 11000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 22000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 11000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 15700.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 22000.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 11600.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 23200.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 11600.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 16550.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 23200.0 + }, { "year": 2026, "MARS": "single", @@ -13627,12 +15255,62 @@ { "year": 2022, "MARS": "headhh", - "value": 55900.0 + "value": 55900.0 + }, + { + "year": 2022, + "MARS": "widow", + "value": 83550.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 44725.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 89450.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 44725.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 59850.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 89450.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 47150.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 94300.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 47150.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 63100.0 }, { - "year": 2022, + "year": 2024, "MARS": "widow", - "value": 83550.0 + "value": 94300.0 }, { "year": 2026, @@ -13997,6 +15675,56 @@ "MARS": "widow", "value": 178150.0 }, + { + "year": 2023, + "MARS": "single", + "value": 95375.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 190750.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 95375.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 95350.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 190750.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 100525.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 201050.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 100525.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 100500.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 201050.0 + }, { "year": 2026, "MARS": "single", @@ -14360,6 +16088,56 @@ "MARS": "widow", "value": 340100.0 }, + { + "year": 2023, + "MARS": "single", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 364200.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 364200.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 191950.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 383900.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 191950.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 191950.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 383900.0 + }, { "year": 2026, "MARS": "single", @@ -14723,6 +16501,56 @@ "MARS": "widow", "value": 431900.0 }, + { + "year": 2023, + "MARS": "single", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 462500.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 462500.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 243725.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 487450.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 243725.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 243700.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 487450.0 + }, { "year": 2026, "MARS": "single", @@ -15086,6 +16914,56 @@ "MARS": "widow", "value": 647850.0 }, + { + "year": 2023, + "MARS": "single", + "value": 578125.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 693750.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 578125.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 578100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 693750.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 609350.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 731200.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 365600.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 609350.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 731200.0 + }, { "year": 2026, "MARS": "single", @@ -15449,6 +17327,56 @@ "MARS": "widow", "value": 9e+99 }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 + }, { "year": 2026, "MARS": "single", @@ -15923,12 +17851,62 @@ { "year": 2022, "MARS": "headhh", - "value": 170050.0 + "value": 170050.0 + }, + { + "year": 2022, + "MARS": "widow", + "value": 340100.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 364200.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 182100.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 191950.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 383900.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 191950.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 191950.0 }, { - "year": 2022, + "year": 2024, "MARS": "widow", - "value": 340100.0 + "value": 191950.0 }, { "year": 2026, @@ -16686,6 +18664,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -17140,6 +19168,56 @@ "MARS": "widow", "value": 118100.0 }, + { + "year": 2023, + "MARS": "single", + "value": 81300.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 126500.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 63250.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 81300.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 126500.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 85700.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 133300.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 66650.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 85700.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 133300.0 + }, { "year": 2026, "MARS": "single", @@ -17463,6 +19541,56 @@ "MARS": "widow", "value": 1079800.0 }, + { + "year": 2023, + "MARS": "single", + "value": 578150.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 1156300.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 578150.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 578150.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 1156300.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 609350.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 1218700.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 609350.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 609350.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 1218700.0 + }, { "year": 2026, "MARS": "single", @@ -17549,6 +19677,14 @@ { "year": 2022, "value": 8200.0 + }, + { + "year": 2023, + "value": 8800.0 + }, + { + "year": 2024, + "value": 9250.0 } ], "validators": { @@ -17663,6 +19799,14 @@ { "year": 2022, "value": 206100.0 + }, + { + "year": 2023, + "value": 220700.0 + }, + { + "year": 2024, + "value": 232600.0 } ], "validators": { @@ -17752,6 +19896,14 @@ "year": 2022, "value": 776100.0 }, + { + "year": 2023, + "value": 831150.0 + }, + { + "year": 2024, + "value": 875950.0 + }, { "year": 2026, "value": 326410.0 @@ -18973,6 +21125,46 @@ "year": 2022, "EIC": "3+kids", "value": 6935.0 + }, + { + "year": 2023, + "EIC": "0kids", + "value": 600.0 + }, + { + "year": 2023, + "EIC": "1kid", + "value": 3995.0 + }, + { + "year": 2023, + "EIC": "2kids", + "value": 6604.0 + }, + { + "year": 2023, + "EIC": "3+kids", + "value": 7430.0 + }, + { + "year": 2024, + "EIC": "0kids", + "value": 632.0 + }, + { + "year": 2024, + "EIC": "1kid", + "value": 4213.0 + }, + { + "year": 2024, + "EIC": "2kids", + "value": 6960.0 + }, + { + "year": 2024, + "EIC": "3+kids", + "value": 7830.0 } ], "validators": { @@ -19441,6 +21633,46 @@ "year": 2022, "EIC": "3+kids", "value": 20130.0 + }, + { + "year": 2023, + "EIC": "0kids", + "value": 9800.0 + }, + { + "year": 2023, + "EIC": "1kid", + "value": 21560.0 + }, + { + "year": 2023, + "EIC": "2kids", + "value": 21560.0 + }, + { + "year": 2023, + "EIC": "3+kids", + "value": 21560.0 + }, + { + "year": 2024, + "EIC": "0kids", + "value": 10330.0 + }, + { + "year": 2024, + "EIC": "1kid", + "value": 22720.0 + }, + { + "year": 2024, + "EIC": "2kids", + "value": 22720.0 + }, + { + "year": 2024, + "EIC": "3+kids", + "value": 22720.0 } ], "validators": { @@ -19635,34 +21867,74 @@ "value": 5950.0 }, { - "year": 2021, + "year": 2021, + "EIC": "2kids", + "value": 5950.0 + }, + { + "year": 2021, + "EIC": "3+kids", + "value": 5950.0 + }, + { + "year": 2022, + "EIC": "0kids", + "value": 6130.0 + }, + { + "year": 2022, + "EIC": "1kid", + "value": 6130.0 + }, + { + "year": 2022, + "EIC": "2kids", + "value": 6130.0 + }, + { + "year": 2022, + "EIC": "3+kids", + "value": 6130.0 + }, + { + "year": 2023, + "EIC": "0kids", + "value": 6570.0 + }, + { + "year": 2023, + "EIC": "1kid", + "value": 6560.0 + }, + { + "year": 2023, "EIC": "2kids", - "value": 5950.0 + "value": 6560.0 }, { - "year": 2021, + "year": 2023, "EIC": "3+kids", - "value": 5950.0 + "value": 6560.0 }, { - "year": 2022, + "year": 2024, "EIC": "0kids", - "value": 6130.0 + "value": 6920.0 }, { - "year": 2022, + "year": 2024, "EIC": "1kid", - "value": 6130.0 + "value": 6920.0 }, { - "year": 2022, + "year": 2024, "EIC": "2kids", - "value": 6130.0 + "value": 6920.0 }, { - "year": 2022, + "year": 2024, "EIC": "3+kids", - "value": 6130.0 + "value": 6920.0 } ], "validators": { @@ -19797,6 +22069,14 @@ { "year": 2022, "value": 10300.0 + }, + { + "year": 2023, + "value": 11000.0 + }, + { + "year": 2024, + "value": 11600.0 } ], "validators": { @@ -19941,6 +22221,14 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 + }, + { + "year": 2024, + "value": 0.0 } ], "validators": { @@ -20661,6 +22949,56 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -21071,6 +23409,56 @@ "year": 2022, "MARS": "widow", "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 500000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 1000000.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 1000000.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 1000000.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 500000.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 1000000.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 1000000.0 } ], "validators": { @@ -21343,6 +23731,56 @@ "year": 2022, "MARS": "widow", "value": 2000000.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 2000000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 2000000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 2000000.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 2000000.0 + }, + { + "year": 2024, + "MARS": "single", + "value": 2000000.0 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 2000000.0 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 1000000.0 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 2000000.0 + }, + { + "year": 2024, + "MARS": "widow", + "value": 2000000.0 } ], "validators": { @@ -21641,6 +24079,56 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2024, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -21729,6 +24217,14 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 + }, + { + "year": 2024, + "value": 0.0 } ], "validators": { @@ -21791,6 +24287,14 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 + }, + { + "year": 2024, + "value": 0.0 } ], "validators": { @@ -21853,6 +24357,14 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 + }, + { + "year": 2024, + "value": 0.0 } ], "validators": { diff --git a/taxcalc/records.py b/taxcalc/records.py index a5e942561..dcebf687f 100644 --- a/taxcalc/records.py +++ b/taxcalc/records.py @@ -6,6 +6,7 @@ # pylint --disable=locally-disabled records.py import os +from pathlib import Path import numpy as np import pandas as pd from taxcalc.data import Data @@ -116,9 +117,6 @@ class instance: Records PUF_RATIOS_FILENAME = 'puf_ratios.csv' CPS_WEIGHTS_FILENAME = 'cps_weights.csv.gz' CPS_RATIOS_FILENAME = None - TMD_WEIGHTS_FILENAME = 'tmd_weights.csv.gz' - TMD_GROWFACTORS_FILENAME = 'tmd_growfactors.csv' - TMD_RATIOS_FILENAME = None CODE_PATH = os.path.abspath(os.path.dirname(__file__)) VARINFO_FILE_NAME = 'records_variables.json' VARINFO_FILE_PATH = CODE_PATH @@ -226,9 +224,12 @@ def cps_constructor(data=None, exact_calculations=exact_calculations) @staticmethod - def tmd_constructor(data, # path to tmd.csv file or dataframe - gfactors=GrowFactors(TMD_GROWFACTORS_FILENAME), - exact_calculations=False): # pragma: no cover + def tmd_constructor( + data_path: Path, + weights_path: Path, + growfactors_path: Path, + exact_calculations=False + ): # pragma: no cover """ Static method returns a Records object instantiated with TMD input data. This works in a analogous way to Records(), which @@ -239,14 +240,18 @@ def tmd_constructor(data, # path to tmd.csv file or dataframe eliminate the need to specify all the details of the PUF input data. """ - weights = os.path.join(Records.CODE_PATH, Records.TMD_WEIGHTS_FILENAME) - return Records(data=data, - start_year=Records.TMDCSV_YEAR, - gfactors=gfactors, - weights=weights, - adjust_ratios=Records.TMD_RATIOS_FILENAME, - exact_calculations=exact_calculations) - + assert isinstance(data_path, Path) + assert isinstance(weights_path, Path) + assert isinstance(growfactors_path, Path) + return Records( + data=pd.read_csv(data_path), + start_year=Records.TMDCSV_YEAR, + weights=pd.read_csv(weights_path), + gfactors=GrowFactors(growfactors_filename=str(growfactors_path)), + adjust_ratios=None, + exact_calculations=exact_calculations, + ) + def increment_year(self): """ Add one to current year, and also does @@ -277,7 +282,7 @@ def _extrapolate(self, year): """ # pylint: disable=too-many-statements,no-member # put values in local dictionary - gfv = dict() + gfv = {} for name in GrowFactors.VALID_NAMES: gfv[name] = self.gfactors.factor_value(name, year) # apply values to Records variables diff --git a/taxcalc/reforms/ext.json b/taxcalc/reforms/ext.json index a8a634549..7b67bbe76 100644 --- a/taxcalc/reforms/ext.json +++ b/taxcalc/reforms/ext.json @@ -1,31 +1,32 @@ // REFORM TO EXTEND TEMPORARY TCJA PROVISIONS BEYOND 2025 -// USING TAX-CALCULATOR 3.5.3 +// USING TAX-CALCULATOR 4.3.0 // WITH 2025-to-2026 INDEXING FACTOR = 1.022000 +// AND 2028-to-2029 INDEXING FACTOR = 1.019400 { "II_rt1": {"2026": 0.10}, - "II_brk1": {"2026": [12170.98, 24341.94, 12170.98, 17353.27, 24341.94]}, + "II_brk1": {"2026": [12157.51, 24315.02, 12157.51, 17345.41, 24315.02]}, "PT_rt1": {"2026": 0.10}, - "PT_brk1": {"2026": [12170.98, 24341.94, 12170.98, 17353.27, 24341.94]}, + "PT_brk1": {"2026": [12157.51, 24315.02, 12157.51, 17345.41, 24315.02]}, "II_rt2": {"2026": 0.12}, - "II_brk2": {"2026": [49483.44, 98966.89, 49483.44, 66214.83, 98966.89]}, + "II_brk2": {"2026": [49416.07, 98832.15, 49416.07, 66132.65, 98832.15]}, "PT_rt2": {"2026": 0.12}, - "PT_brk2": {"2026": [49483.44, 98966.89, 49483.44, 66214.83, 98966.89]}, + "PT_brk2": {"2026": [49416.07, 98832.15, 49416.07, 66132.65, 98832.15]}, "II_rt3": {"2026": 0.22}, - "II_brk3": {"2026": [105511.38, 211022.75, 105511.38, 105481.77, 211022.75]}, + "II_brk3": {"2026": [105356.33, 210712.67, 105356.33, 105330.13, 210712.67]}, "PT_rt3": {"2026": 0.22}, - "PT_brk3": {"2026": [105511.38, 211022.75, 105511.38, 105481.77, 211022.75]}, + "PT_brk3": {"2026": [105356.33, 210712.67, 105356.33, 105330.13, 210712.67]}, "II_rt4": {"2026": 0.24}, - "II_brk4": {"2026": [201428.14, 402856.25, 201428.14, 201428.14, 402856.25]}, + "II_brk4": {"2026": [201175.3, 402350.62, 201175.3, 201175.3, 402350.62]}, "PT_rt4": {"2026": 0.24}, - "PT_brk4": {"2026": [201428.14, 402856.25, 201428.14, 201428.14, 402856.25]}, + "PT_brk4": {"2026": [201175.3, 402350.62, 201175.3, 201175.3, 402350.62]}, "II_rt5": {"2026": 0.32}, - "II_brk5": {"2026": [255797.72, 511595.46, 255797.72, 255797.72, 511595.46]}, + "II_brk5": {"2026": [255438.67, 510877.34, 255438.67, 255412.47, 510877.34]}, "PT_rt5": {"2026": 0.32}, - "PT_brk5": {"2026": [255797.72, 511595.46, 255797.72, 255797.72, 511595.46]}, + "PT_brk5": {"2026": [255438.67, 510877.34, 255438.67, 255412.47, 510877.34]}, "II_rt6": {"2026": 0.35}, - "II_brk6": {"2026": [639523.94, 767393.2, 383696.6, 639523.94, 767393.2]}, + "II_brk6": {"2026": [638635.98, 766342.2, 383171.1, 638635.98, 766342.2]}, "PT_rt6": {"2026": 0.35}, - "PT_brk6": {"2026": [639523.94, 767393.2, 383696.6, 639523.94, 767393.2]}, + "PT_brk6": {"2026": [638635.98, 766342.2, 383171.1, 638635.98, 766342.2]}, "II_rt7": {"2026": 0.37}, "II_brk7": {"2026": [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]}, "PT_rt7": {"2026": 0.37}, @@ -35,10 +36,10 @@ "ODC_c": {"2026": 500.00}, "CTC_ps": {"2026": [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]}, "ACTC_Income_thd": {"2026": 2500.00}, - "AMT_em": {"2026": [89905.29, 139892.17, 69946.08, 89905.29, 139892.17]}, - "AMT_em_ps": {"2026": [639523.94, 1279047.88, 639523.94, 639523.94, 1279047.88]}, - "AMT_em_pe": {"2026": 939533.04}, - "STD": {"2026": [15339.57, 30679.14, 15339.57, 22979.74, 30679.14]}, + "AMT_em": {"2026": [89818.83, 139706.53, 69853.27, 89818.83, 139706.53]}, + "AMT_em_ps": {"2026": [638635.98, 1277271.94, 638635.98, 638635.98, 1277271.94]}, + "AMT_em_pe": {"2026": 938246.12}, + "STD": {"2026": [15301.69, 30603.38, 15301.69, 22952.54, 30603.38]}, "ID_AllTaxes_c": {"2026": [10000.0, 10000.0, 5000.0, 10000.0, 10000.0]}, "ID_Charity_crt_cash": {"2026": 0.60}, "ID_Casualty_hc": {"2026": 1.00}, @@ -49,11 +50,10 @@ "II_em": {"2026": 0.00}, "II_em_ps": {"2026": [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]}, "PT_qbid_rt": {"2026": 0.20}, - "PT_qbid_taxinc_thd": {"2026": [201428.14, 402856.25, 201428.14, 201428.14, 402856.25]}, + "PT_qbid_taxinc_thd": {"2026": [201175.3, 402350.62, 201175.3, 201175.3, 201175.3]}, "PT_qbid_taxinc_gap": {"2026": [50000.0, 100000.0, 50000.0, 50000.0, 100000.0]}, "PT_qbid_w2_wages_rt": {"2026": 0.50}, "PT_qbid_alt_w2_wages_rt": {"2026": 0.25}, "PT_qbid_alt_property_rt": {"2026": 0.03}, - "ALD_BusinessLosses_c": {"2026": [319821.19, 639642.39, 319821.19, 319821.19, 639642.39]}, - "ALD_DomesticProduction_hc": {"2026": 1.00} + "ALD_BusinessLosses_c": {"2029": [339091.08, 678182.18, 339091.08, 339091.08, 678182.18]} } diff --git a/taxcalc/reforms/rounding.json b/taxcalc/reforms/rounding.json new file mode 100644 index 000000000..db7186ae1 --- /dev/null +++ b/taxcalc/reforms/rounding.json @@ -0,0 +1,253 @@ +// Rounding of parameters to return to currnet law poliy +// This file is intended to update parameter values due to IRS rounding +// rules when moving from a historical baseline to current law policy +// by layering on intervening policy changes, as is done in the +// tests/test_reforms.py::test_round_trip_reforms test +// N.B. Only valid through 2022 - will overwrite changes in policy +// beyond that year (e.g., as in TCJA.json) + + +{ + "II_brk1": { + "2019": [9700, 19400, 9700, 13850, 19400], + "2020": [9875, 19750, 9875, 14100, 19750], + "2021": [9950, 19900, 9950, 14200, 19900], + "2022": [10275, 20550, 10275, 14650, 20550], + "2023": [11000, 22000, 11000, 15700, 22000] + }, + "II_brk2": { + "2019": [39475, 78950, 39475, 52850, 78950], + "2020": [40125, 80250, 40125, 53700, 80250], + "2021": [40525, 81050, 40525, 54200, 81050], + "2022": [41775, 83550, 41775, 55900, 83550], + "2023": [44725, 89450, 44725, 59850, 89450] + }, + "II_brk3": { + "2019": [84200, 168400, 84200, 84200, 168400], + "2020": [85525, 171050, 85525, 85500, 171050], + "2021": [86375, 172750, 86375, 86350, 172750], + "2022": [89075, 178150, 89075, 89050, 178150], + "2023": [95375, 190750, 95375, 95350, 190750] + }, + "II_brk4": { + "2019": [160725, 321450, 160725, 160700, 321450], + "2020": [163300, 326600, 163300, 163300, 326600], + "2021": [164925, 329850, 164925, 164900, 329850], + "2022": [170050, 340100, 170050, 170050, 340100], + "2023": [182100, 364200, 182100, 182100, 364200] + }, + "II_brk5": { + "2019": [204100, 408200, 204100, 204100, 408200], + "2020": [207350, 414700, 207350, 207350, 414700], + "2021": [209425, 418850, 209425, 209400, 418850], + "2022": [215950, 431900, 215950, 215950, 431900], + "2023": [231250, 462500, 231250, 231250, 462500] + }, + "II_brk6": { + "2019": [510300, 612350, 306175, 510300, 612350], + "2020": [518400, 622050, 311025, 518400, 622050], + "2021": [523600, 628300, 314150, 523600, 628300], + "2022": [539900, 647850, 323925, 539900, 647850], + "2023": [578125, 693750, 578125, 578100, 693750] + }, + "PT_brk1": { + "2019": [9700, 19400, 9700, 13850, 19400], + "2020": [9875, 19750, 9875, 14100, 19750], + "2021": [9950, 19900, 9950, 14200, 19900], + "2022": [10275, 20550, 10275, 14650, 20550], + "2023": [11000, 22000, 11000, 15700, 22000] + }, + "PT_brk2": { + "2019": [39475, 78950, 39475, 52850, 78950], + "2020": [40125, 80250, 40125, 53700, 80250], + "2021": [40525, 81050, 40525, 54200, 81050], + "2022": [41775, 83550, 41775, 55900, 83550], + "2023": [44725, 89450, 44725, 59850, 89450] + }, + "PT_brk3": { + "2019": [84200, 168400, 84200, 84200, 168400], + "2020": [85525, 171050, 85525, 85500, 171050], + "2021": [86375, 172750, 86375, 86350, 172750], + "2022": [89075, 178150, 89075, 89050, 178150], + "2023": [95375, 190750, 95375, 95350, 190750] + }, + "PT_brk4": { + "2019": [160725, 321450, 160725, 160700, 321450], + "2020": [163300, 326600, 163300, 163300, 326600], + "2021": [164925, 329850, 164925, 164900, 329850], + "2022": [170050, 340100, 170050, 170050, 340100], + "2023": [182100, 364200, 182100, 182100, 364200] + }, + "PT_brk5": { + "2019": [204100, 408200, 204100, 204100, 408200], + "2020": [207350, 414700, 207350, 207350, 414700], + "2021": [209425, 418850, 209425, 209400, 418850], + "2022": [215950, 431900, 215950, 215950, 431900], + "2023": [231250, 462500, 231250, 231250, 462500] + }, + "PT_brk6": { + "2019": [510300, 612350, 306175, 510300, 612350], + "2020": [518400, 622050, 311025, 518400, 622050], + "2021": [523600, 628300, 314150, 523600, 628300], + "2022": [539900, 647850, 323925, 539900, 647850], + "2023": [578125, 693750, 578125, 578100, 693750] + }, + "PT_qbid_taxinc_thd": { + "2019": [160700, 321400, 160725, 160700, 321400], + "2020": [163300, 326600, 163300, 163300, 326600], + "2021": [164900, 329800, 164900, 164900, 329800], + "2022": [170050, 340100, 170050, 170050, 340100], + "2023": [182100, 364200, 182100, 182100, 182100] + }, + "STD": { + "2019": [12200, 24400, 12200, 18350, 24400], + "2020": [12400, 24800, 12400, 18650, 24800], + "2021": [12550, 25100, 12550, 18800, 25100], + "2022": [12950, 25900, 12950, 19400, 25900], + "2023": [13850, 27700, 13850, 20800, 27700] + }, + "AMT_em": { + "2019": [71700, 111700, 55850, 71700, 111700], + "2020": [72900, 113400, 56700, 72900, 113400], + "2021": [73600, 114600, 57300, 73600, 114600], + "2022": [75900, 118100, 59050, 75900, 118100], + "2023": [81300, 126500, 63250, 81300, 126500] + }, + "AMT_em_ps": { + "2019": [510300, 1020600, 510300, 510300, 1020600], + "2020": [518400, 1036800, 518400, 518400, 1036800], + "2021": [523600, 1047200, 523600, 523600, 1047200], + "2022": [539900, 1079800, 539900, 539900, 1079800], + "2023": [578150, 1156300, 578150, 578150, 1156300] + }, + "AMT_em_pe": { + "2019": 733700, + "2020": 745200, + "2021": 752800, + "2022": 776100, + "2023": 831150 + }, + "ALD_BusinessLosses_c": { + "2019": [255000, 510000, 255000, 255000, 510000], + "2020": [259000, 518000, 259000, 259000, 518000], + "2021": [262000, 524000, 262000, 262000, 524000], + "2022": [270000, 540000, 270000, 270000, 540000], + "2023": [289000, 578000, 289000, 289000, 578000] + }, + "STD_Dep": { + "2019": 1100, + "2020": 1100, + "2021": 1100, + "2022": 1150, + "2023": 1250 + }, + "STD_Aged": { + "2019": [1650, 1300, 1300, 1650, 1300], + "2020": [1650, 1300, 1300, 1650, 1300], + "2021": [1700, 1350, 1350, 1700, 1350], + "2022": [1750, 1400, 1400, 1750, 1750], + "2023": [1800, 1500, 1500, 1800, 1800] + }, + "CG_brk1": { + "2019": [39375, 78750, 39375, 52750, 78750], + "2020": [40000, 80000, 40000, 53600, 80000], + "2021": [40400, 80800, 40400, 54100, 80800], + "2022": [41675, 83350, 41675, 55800, 83350], + "2023": [44625, 89250, 44625, 59750, 89250] + }, + "CG_brk2": { + "2019": [434550, 488850, 244425, 461700, 488850], + "2020": [441450, 496600, 248300, 469050, 496600], + "2021": [445850, 501600, 250800, 473750, 501600], + "2022": [459750, 517200, 258600, 488500, 517200], + "2023": [492300, 553850, 276900, 523050, 553850] + }, + "AMT_CG_brk1": { + "2019": [39375, 78750, 39375, 52750, 78750], + "2020": [40000, 80000, 40000, 53600, 80000], + "2021": [40400, 80800, 40400, 54100, 80800], + "2022": [41675, 83350, 41675, 55800, 83350], + "2023": [44625, 89250, 44625, 59750, 89250] + }, + "AMT_CG_brk2": { + "2019": [434550, 488850, 244425, 461700, 488850], + "2020": [441450, 496600, 248300, 469050, 496600], + "2021": [445850, 501600, 250800, 473750, 501600], + "2022": [459750, 517200, 258600, 488500, 517200], + "2023": [492300, 553850, 276900, 523050, 553850] + }, + "AMT_child_em": { + "2019": 7750, + "2020": 7900, + "2021": 7950, + "2022": 8200, + "2023": 8800 + }, + "AMT_brk1": { + "2019": 194800, + "2020": 197900, + "2021": 199900, + "2022": 206100, + "2023": 220700 + }, + "EITC_c": { + "2019": [529, 3526, 5828, 6557], + "2020": [538, 3584, 5920, 6660], + "2021": [1502, 3618, 5980, 6728], + "2022": [560, 3733, 6164, 6935], + "2023": [600, 3995, 6604, 7430] + }, + "EITC_ps": { + "2019": [8650, 19030, 19030, 19030], + "2020": [8790, 19330, 19330, 19330], + "2021": [11610, 19520, 19520, 19520], + "2022": [9160, 20130, 20130, 20130], + "2023": [9800, 21560, 21560, 21560] + }, + "EITC_ps_MarriedJ": { + "2019": [5800, 5790, 5790, 5790], + "2020": [5890, 5890, 5890, 5890], + "2021": [5940, 5950, 5950, 5950], + "2022": [6130, 6130, 6130, 6130], + "2023": [6570, 6560, 6560, 6560] + }, + "EITC_InvestIncome_c": { + "2019": 3600, + "2020": 3650, + "2021": 10000, + "2022": 10300, + "2023": 11000 + }, + "ETC_pe_Single": { + "2019": 68, + "2020": 69, + "2021": 90, + "2022": 90 + }, + "ETC_pe_Married": { + "2019": 136, + "2020": 138, + "2021": 180, + "2022": 180 + }, + "ACTC_c": { + "2023": 1600, + "2024": 1600, + "2025": 1600, + "2026": 1000 + }, + "FST_AGI_thd_lo": { + "2019": [1000000, 1000000, 500000, 1000000, 1000000], + "2020": [1000000, 1000000, 500000, 1000000, 1000000], + "2021": [1000000, 1000000, 500000, 1000000, 1000000], + "2022": [1000000, 1000000, 500000, 1000000, 1000000], + "2023": [1000000, 1000000, 500000, 1000000, 1000000] + }, + "FST_AGI_thd_hi": { + "2019": [2000000, 2000000, 1000000, 2000000, 2000000], + "2020": [2000000, 2000000, 1000000, 2000000, 2000000], + "2021": [2000000, 2000000, 1000000, 2000000, 2000000], + "2022": [2000000, 2000000, 1000000, 2000000, 2000000], + "2023": [2000000, 2000000, 1000000, 2000000, 2000000] + } +} diff --git a/taxcalc/reforms/rounding2022.out.csv b/taxcalc/reforms/rounding.out.csv similarity index 100% rename from taxcalc/reforms/rounding2022.out.csv rename to taxcalc/reforms/rounding.out.csv diff --git a/taxcalc/reforms/rounding2022.json b/taxcalc/reforms/rounding2022.json deleted file mode 100644 index fb07bc18a..000000000 --- a/taxcalc/reforms/rounding2022.json +++ /dev/null @@ -1,153 +0,0 @@ -// Rounding of parameters to return to currnet law poliy -// This file is intended to update parameter values due to IRS rounding -// rules when moving from a historical baseline to current law policy -// by layering on intervening policy changes, as is done in the -// tests/test_reforms.py::test_round_trip_reforms test -// N.B. Only valid through 2022 - will overwrite changes in policy -// beyond that year (e.g., as in TCJA.json) - - -{ - "II_brk1": {"2019": [9700, 19400, 9700, 13850, 19400], - "2020": [9875, 19750, 9875, 14100, 19750], - "2021": [9950, 19900, 9950, 14200, 19900], - "2022": [10275, 20550, 10275, 14650, 20550]}, - "II_brk2": {"2019": [39475, 78950, 39475, 52850, 78950], - "2020": [40125, 80250, 40125, 53700, 80250], - "2021": [40525, 81050, 40525, 54200, 81050], - "2022": [41775, 83550, 41775, 55900, 83550]}, - "II_brk3": {"2019": [84200, 168400, 84200, 84200, 168400], - "2020": [85525, 171050, 85525, 85500, 171050], - "2021": [86375, 172750, 86375, 86350, 172750], - "2022": [89075, 178150, 89075, 89050, 178150]}, - "II_brk4": {"2019": [160725, 321450, 160725, 160700, 321450], - "2020": [163300, 326600, 163300, 163300, 326600], - "2021": [164925, 329850, 164925, 164900, 329850], - "2022": [170050, 340100, 170050, 170050, 340100]}, - "II_brk5": {"2019": [204100, 408200, 204100, 204100, 408200], - "2020": [207350, 414700, 207350, 207350, 414700], - "2021": [209425, 418850, 209425, 209400, 418850], - "2022": [215950, 431900, 215950, 215950, 431900]}, - "II_brk6": {"2019": [510300, 612350, 306175, 510300, 612350], - "2020": [518400, 622050, 311025, 518400, 622050], - "2021": [523600, 628300, 314150, 523600, 628300], - "2022": [539900, 647850, 323925, 539900, 647850]}, - "PT_brk1": {"2019": [9700, 19400, 9700, 13850, 19400], - "2020": [9875, 19750, 9875, 14100, 19750], - "2021": [9950, 19900, 9950, 14200, 19900], - "2022": [10275, 20550, 10275, 14650, 20550]}, - "PT_brk2": {"2019": [39475, 78950, 39475, 52850, 78950], - "2020": [40125, 80250, 40125, 53700, 80250], - "2021": [40525, 81050, 40525, 54200, 81050], - "2022": [41775, 83550, 41775, 55900, 83550]}, - "PT_brk3": {"2019": [84200, 168400, 84200, 84200, 168400], - "2020": [85525, 171050, 85525, 85500, 171050], - "2021": [86375, 172750, 86375, 86350, 172750], - "2022": [89075, 178150, 89075, 89050, 178150]}, - "PT_brk4": {"2019": [160725, 321450, 160725, 160700, 321450], - "2020": [163300, 326600, 163300, 163300, 326600], - "2021": [164925, 329850, 164925, 164900, 329850], - "2022": [170050, 340100, 170050, 170050, 340100]}, - "PT_brk5": {"2019": [204100, 408200, 204100, 204100, 408200], - "2020": [207350, 414700, 207350, 207350, 414700], - "2021": [209425, 418850, 209425, 209400, 418850], - "2022": [215950, 431900, 215950, 215950, 431900]}, - "PT_brk6": {"2019": [510300, 612350, 306175, 510300, 612350], - "2020": [518400, 622050, 311025, 518400, 622050], - "2021": [523600, 628300, 314150, 523600, 628300], - "2022": [539900, 647850, 323925, 539900, 647850]}, - "PT_qbid_taxinc_thd": {"2019": [160700, 321400, 160725, 160700, 321400], - "2020": [163300, 326600, 163300, 163300, 326600], - "2021": [164900, 329800, 164900, 164900, 329800], - "2022": [170050, 340100, 170050, 170050, 340100]}, - "STD": {"2019": [12200, 24400, 12200, 18350, 24400], - "2020": [12400, 24800, 12400, 18650, 24800], - "2021": [12550, 25100, 12550, 18800, 25100], - "2022": [12950, 25900, 12950, 19400, 25900]}, - "AMT_em": {"2019": [71700, 111700, 55850, 71700, 111700], - "2020": [72900, 113400, 56700, 72900, 113400], - "2021": [73600, 114600, 57300, 73600, 114600], - "2022": [75900, 118100, 59050, 75900, 118100]}, - "AMT_em_ps": {"2019": [510300, 1020600, 510300, 510300, 1020600], - "2020": [518400, 1036800, 518400, 518400, 1036800], - "2021": [523600, 1047200, 523600, 523600, 1047200], - "2022": [539900, 1079800, 539900, 539900, 1079800]}, - "AMT_em_pe": {"2019": 733700, - "2020": 745200, - "2021": 752800, - "2022": 776100}, - "ALD_BusinessLosses_c": { - "2019": [255000, 510000, 255000, 255000, 510000], - "2020": [259000, 518000, 259000, 259000, 518000], - "2021": [262000, 524000, 262000, 262000, 524000], - "2022": [270000, 540000, 270000, 270000, 540000]}, - "STD_Dep": {"2019": 1100, "2020": 1100, "2021": 1100, "2022": 1150}, - "STD_Aged": {"2019": [1650, 1300, 1300, 1650, 1300], - "2020": [1650, 1300, 1300, 1650, 1300], - "2021": [1700, 1350, 1350, 1700, 1350], - "2022": [1750, 1400, 1400, 1750, 1750]}, - "CG_brk1": {"2019": [39375, 78750, 39375, 52750, 78750], - "2020": [40000, 80000, 40000, 53600, 80000], - "2021": [40400, 80800, 40400, 54100, 80800], - "2022": [41675, 83350, 41675, 55800, 83350]}, - "CG_brk2": {"2019": [434550, 488850, 244425, 461700, 488850], - "2020": [441450, 496600, 248300, 469050, 496600], - "2021": [445850, 501600, 250800, 473750, 501600], - "2022": [459750, 517200, 258600, 488500, 517200]}, - "AMT_CG_brk1": {"2019": [39375, 78750, 39375, 52750, 78750], - "2020": [40000, 80000, 40000, 53600, 80000], - "2021": [40400, 80800, 40400, 54100, 80800], - "2022": [41675, 83350, 41675, 55800, 83350]}, - "AMT_CG_brk2": {"2019": [434550, 488850, 244425, 461700, 488850], - "2020": [441450, 496600, 248300, 469050, 496600], - "2021": [445850, 501600, 250800, 473750, 501600], - "2022": [459750, 517200, 258600, 488500, 517200]}, - "AMT_child_em": { "2019": 7750, - "2020": 7900, - "2021": 7950, - "2022": 8200}, - "AMT_brk1": {"2019": 194800, - "2020": 197900, - "2021": 199900, - "2022": 206100}, - "EITC_c": {"2019": [529, 3526, 5828, 6557], - "2020": [538, 3584, 5920, 6660], - "2021": [1502.0, 3618.0, 5980.0, 6728.0], - "2022": [560, 3733, 6164, 6935]}, - "EITC_ps": {"2019": [8650, 19030, 19030, 19030], - "2020": [8790, 19330, 19330, 19330], - "2021": [11610, 19520, 19520, 19520], - "2022": [9160, 20130, 20130, 20130]}, - "EITC_ps_MarriedJ": {"2019": [5800, 5790, 5790, 5790], - "2020": [5890, 5890, 5890, 5890], - "2021": [5940, 5950, 5950, 5950], - "2022": [6130, 6130, 6130, 6130]}, - "EITC_InvestIncome_c": {"2019": 3600, - "2020": 3650, - "2021": 10000, - "2022": 10300}, - "ETC_pe_Single": {"2019": 68, - "2020": 69, - "2021": 90, - "2022": 90}, - "ETC_pe_Married": {"2019": 136, - "2020": 138, - "2021": 180, - "2022": 180}, - "ACTC_c": {"2023": 1600, - "2024": 1600, - "2025": 1600, - "2026": 1000}, - "FST_AGI_thd_lo": { - "2019": [1000000, 1000000, 500000, 1000000, 1000000], - "2020": [1000000, 1000000, 500000, 1000000, 1000000], - "2021": [1000000, 1000000, 500000, 1000000, 1000000], - "2022": [1000000, 1000000, 500000, 1000000, 1000000] - }, - "FST_AGI_thd_hi": { - "2019": [2000000, 2000000, 1000000, 2000000, 2000000], - "2020": [2000000, 2000000, 1000000, 2000000, 2000000], - "2021": [2000000, 2000000, 1000000, 2000000, 2000000], - "2022": [2000000, 2000000, 1000000, 2000000, 2000000] - } -} diff --git a/taxcalc/taxcalcio.py b/taxcalc/taxcalcio.py index 5296de83c..708bb6184 100644 --- a/taxcalc/taxcalcio.py +++ b/taxcalc/taxcalcio.py @@ -74,6 +74,8 @@ def __init__(self, input_data, tax_year, baseline, reform, assump, self.puf_input_data = False self.cps_input_data = False self.tmd_input_data = False + self.tmd_weights = None + self.tmd_gfactor = None if isinstance(input_data, str): # remove any leading directory path from INPUT filename fname = os.path.basename(input_data) @@ -90,6 +92,23 @@ def __init__(self, input_data, tax_year, baseline, reform, assump, if not self.cps_input_data and not os.path.isfile(input_data): msg = 'INPUT file could not be found' self.errmsg += 'ERROR: {}\n'.format(msg) + # if tmd_input_data is True, construct weights and gfactor paths + if self.tmd_input_data: # pragma: no cover + tmd_dir = os.path.dirname(input_data) + if 'TMD_AREA' in os.environ: + area = os.environ['TMD_AREA'] + wfile = f'{area}_tmd_weights.csv.gz' + inp = f'{fname[:-4]}_{area}-{str(tax_year)[2:]}' + else: # using national weights + wfile = 'tmd_weights.csv.gz' + self.tmd_weights = os.path.join(tmd_dir, wfile) + self.tmd_gfactor = os.path.join(tmd_dir, 'tmd_growfactors.csv') + if not os.path.isfile(self.tmd_weights): + msg = f'weights file {self.tmd_weights} could not be found' + self.errmsg += 'ERROR: {}\n'.format(msg) + if not os.path.isfile(self.tmd_gfactor): + msg = f'gfactor file {self.tmd_gfactor} could not be found' + self.errmsg += 'ERROR: {}\n'.format(msg) elif isinstance(input_data, pd.DataFrame): inp = 'df-{}'.format(str(tax_year)[2:]) else: @@ -123,7 +142,7 @@ def __init__(self, input_data, tax_year, baseline, reform, assump, elif isinstance(reform, str): self.specified_reform = True # split any compound reform into list of simple reforms - refnames = list() + refnames = [] reforms = reform.split('+') for rfm in reforms: # remove any leading directory path from rfm filename @@ -206,7 +225,7 @@ def __init__(self, input_data, tax_year, baseline, reform, assump, self.calc = None self.calc_base = None self.param_dict = None - self.policy_dicts = list() + self.policy_dicts = [] def init(self, input_data, tax_year, baseline, reform, assump, aging_input_data, exact_calculations): @@ -234,7 +253,7 @@ def init(self, input_data, tax_year, baseline, reform, assump, # get assumption sub-dictionaries paramdict = Calculator.read_json_param_objects(None, assump) # get policy parameter dictionaries from --reform file(s) - policydicts = list() + policydicts = [] if self.specified_reform: reforms = reform.split('+') for ref in reforms: @@ -252,9 +271,7 @@ def init(self, input_data, tax_year, baseline, reform, assump, self.errmsg += valerr_msg.__str__() # create GrowFactors base object that incorporates gdiff_baseline if self.tmd_input_data: - gfactors_base = GrowFactors( # pragma: no cover - Records.TMD_GROWFACTORS_FILENAME - ) + gfactors_base = GrowFactors(self.tmd_gfactor) # pragma: no cover else: gfactors_base = GrowFactors() gdiff_baseline.apply_to(gfactors_base) @@ -266,9 +283,7 @@ def init(self, input_data, tax_year, baseline, reform, assump, self.errmsg += valerr_msg.__str__() # create GrowFactors ref object that has all gdiff objects applied if self.tmd_input_data: - gfactors_ref = GrowFactors( # pragma: no cover - Records.TMD_GROWFACTORS_FILENAME - ) + gfactors_ref = GrowFactors(self.tmd_gfactor) # pragma: no cover else: gfactors_ref = GrowFactors() gdiff_baseline.apply_to(gfactors_ref) @@ -332,18 +347,25 @@ def init(self, input_data, tax_year, baseline, reform, assump, gfactors=gfactors_base, exact_calculations=exact_calculations ) - elif self.tmd_input_data: - recs = Records.tmd_constructor( - data=input_data, + elif self.tmd_input_data: # pragma: no cover + wghts = pd.read_csv(self.tmd_weights) + recs = Records( + data=pd.read_csv(input_data), + start_year=Records.TMDCSV_YEAR, + weights=wghts, gfactors=gfactors_ref, + adjust_ratios=None, exact_calculations=exact_calculations - ) # pragma: no cover - recs_base = Records.tmd_constructor( - data=input_data, + ) + recs_base = Records( + data=pd.read_csv(input_data), + start_year=Records.TMDCSV_YEAR, + weights=wghts, gfactors=gfactors_base, + adjust_ratios=None, exact_calculations=exact_calculations - ) # pragma: no cover - else: # if not {cps|tmd}_input_data but aging_input_data + ) + else: # if not {cps|tmd}_input_data but aging_input_data: puf recs = Records( data=input_data, gfactors=gfactors_ref, @@ -541,7 +563,7 @@ def write_doc_file(self): doc = Calculator.reform_documentation(self.param_dict, self.policy_dicts[1:]) doc_fname = self._output_filename.replace('.csv', '-doc.text') - with open(doc_fname, 'w') as dfile: + with open(doc_fname, 'w', encoding='utf-8') as dfile: dfile.write(doc) def write_sqldb_file(self, dump_varset, mtr_paytax, mtr_inctax, @@ -575,7 +597,7 @@ def write_tables_file(self): tab_fname = self._output_filename.replace('.csv', '-tab.text') # skip tables if there are not some positive weights if self.calc_base.total_weight() <= 0.: - with open(tab_fname, 'w') as tfile: + with open(tab_fname, 'w', encoding='utf-8') as tfile: msg = 'No tables because sum of weights is not positive\n' tfile.write(msg) return @@ -597,7 +619,7 @@ def write_tables_file(self): diff = nontax + change # using expanded_income under baseline policy diffdf = pd.DataFrame(data=np.column_stack(diff), columns=all_vars) # write each kind of distributional table - with open(tab_fname, 'w') as tfile: + with open(tab_fname, 'w', encoding='utf-8') as tfile: TaxCalcIO.write_decile_table(distdf, tfile, tkind='Reform Totals') tfile.write('\n') TaxCalcIO.write_decile_table(diffdf, tfile, tkind='Differences') @@ -730,7 +752,7 @@ def write_empty_graph_file(fname, title, reason): '{}\n' '{}\n' '\n').format(title, reason) - with open(fname, 'w') as gfile: + with open(fname, 'w', encoding='utf-8') as gfile: gfile.write(txt) def minimal_output(self): @@ -738,7 +760,7 @@ def minimal_output(self): Extract minimal output and return it as Pandas DataFrame. """ varlist = ['RECID', 'YEAR', 'WEIGHT', 'INCTAX', 'LSTAX', 'PAYTAX'] - odict = dict() + odict = {} scalc = self.calc odict['RECID'] = scalc.array('RECID') # id for tax filing unit odict['YEAR'] = self.tax_year() # tax calculation year diff --git a/taxcalc/tests/cpscsv_agg_expect.csv b/taxcalc/tests/cpscsv_agg_expect.csv index 1cb1e1a1d..62c315997 100644 --- a/taxcalc/tests/cpscsv_agg_expect.csv +++ b/taxcalc/tests/cpscsv_agg_expect.csv @@ -1,26 +1,26 @@ ,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026 Returns (#m),187.1,199.2,201.9,204.5,207.1,209.7,212.3,214.9,217.5,220.1 -AGI ($b),9087.6,10714.8,11167.0,11573.2,13174.9,13543.8,14390.3,15077.5,15785.3,16457.7 -Itemizers (#m),62.8,23.9,25.0,27.5,31.2,31.2,29.8,29.4,30.4,81.1 -Itemized Deduction ($b),1218.6,612.0,655.1,745.4,862.7,881.9,887.6,913.8,963.1,2180.7 -Standard Deduction Filers (#m),124.3,175.3,176.9,176.9,175.8,178.5,182.5,185.5,187.2,139.1 -Standard Deduction ($b),1092.1,2951.3,3026.1,3080.8,3091.9,3231.4,3549.4,3806.5,3937.8,1613.3 -Personal Exemption ($b),1383.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2081.6 -Taxable Income ($b),6230.6,7959.2,8322.8,8615.4,10049.9,10332.2,10948.3,11426.3,11990.0,11782.5 -Regular Tax ($b),1108.0,1380.0,1449.0,1497.4,1762.8,1837.4,1937.4,2016.4,2123.2,2339.6 -AMT Income ($b),8319.8,10212.6,10630.3,10965.7,12473.9,12821.8,13658.8,14318.8,14984.7,15074.1 -AMT Liability ($b),8.1,0.4,0.4,0.5,1.4,0.7,0.7,0.6,0.6,17.2 +AGI ($b),9087.6,10714.8,11167.0,11573.2,13174.9,13543.8,14390.3,15077.5,15785.2,16487.0 +Itemizers (#m),62.8,23.9,25.0,27.5,31.2,31.2,30.0,29.6,30.6,81.1 +Itemized Deduction ($b),1218.6,612.0,655.1,745.4,862.7,881.9,891.8,917.9,968.3,2181.6 +Standard Deduction Filers (#m),124.3,175.3,176.9,176.9,175.8,178.5,182.3,185.3,186.9,139.0 +Standard Deduction ($b),1092.1,2951.3,3026.1,3080.8,3091.9,3231.4,3534.5,3791.7,3921.6,1610.3 +Personal Exemption ($b),1383.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2081.5 +Taxable Income ($b),6230.6,7959.2,8322.8,8615.4,10049.9,10332.2,10954.0,11432.4,11996.4,11810.2 +Regular Tax ($b),1108.0,1380.0,1449.0,1497.4,1762.8,1837.4,1939.0,2018.1,2125.0,2347.7 +AMT Income ($b),8319.8,10212.6,10630.3,10965.7,12473.9,12821.8,13655.8,14315.8,14980.8,15102.6 +AMT Liability ($b),8.1,0.4,0.4,0.5,1.4,0.7,0.7,0.6,0.6,17.1 AMT Filers (#m),2.6,0.1,0.1,0.1,0.2,0.1,0.1,0.1,0.1,4.1 -Tax before Credits ($b),1116.0,1380.4,1449.4,1497.9,1764.3,1838.0,1938.1,2017.0,2123.8,2356.8 -Refundable Credits ($b),70.8,102.5,102.7,655.0,827.1,98.5,106.4,111.6,112.1,97.7 -Nonrefundable Credits ($b),32.7,97.2,99.2,99.2,0.0,107.7,108.3,109.3,111.2,29.9 +Tax before Credits ($b),1116.0,1380.4,1449.4,1497.9,1764.3,1838.0,1939.7,2018.7,2125.6,2364.9 +Refundable Credits ($b),70.8,102.5,102.7,655.0,827.1,98.5,106.2,111.4,111.9,97.5 +Nonrefundable Credits ($b),32.7,97.2,99.2,99.2,0.0,107.7,108.4,109.4,111.3,30.0 Reform Surtaxes ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 Other Taxes ($b),5.5,10.7,11.3,12.6,13.9,14.4,16.5,17.6,18.8,19.9 -Ind Income Tax ($b),1018.1,1191.4,1258.9,756.3,951.0,1646.2,1740.0,1813.7,1919.2,2249.0 -Payroll Taxes ($b),1040.8,1141.6,1194.9,1217.9,1318.7,1421.6,1506.7,1582.0,1656.7,1730.7 -Combined Liability ($b),2059.0,2333.0,2453.8,1974.2,2269.7,3067.8,3246.6,3395.7,3575.9,3979.7 -With Income Tax <= 0 (#m),88.1,96.2,97.0,135.4,127.8,96.1,97.9,99.2,99.6,97.4 -With Combined Tax <= 0 (#m),62.8,65.4,66.4,98.2,97.7,67.9,69.3,70.5,71.3,70.7 +Ind Income Tax ($b),1018.1,1191.4,1258.9,756.3,951.0,1646.2,1741.7,1815.6,1921.2,2257.4 +Payroll Taxes ($b),1040.8,1141.6,1194.9,1217.9,1318.7,1421.6,1509.2,1585.1,1659.9,1734.1 +Combined Liability ($b),2059.0,2333.0,2453.8,1974.2,2269.7,3067.8,3250.9,3400.7,3581.1,3991.5 +With Income Tax <= 0 (#m),88.1,96.2,97.0,135.4,127.8,96.1,97.8,99.1,99.5,97.3 +With Combined Tax <= 0 (#m),62.8,65.4,66.4,98.2,97.7,67.9,69.3,70.4,71.3,70.6 UBI Benefits ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "Total Benefits, Consumption Value ($b)",2790.7,3225.5,3429.9,3617.0,3993.0,4069.6,4390.5,4696.3,4983.2,5266.5 Total Benefits Cost ($b),2790.7,3225.5,3429.9,3617.0,3993.0,4069.6,4390.5,4696.3,4983.2,5266.5 diff --git a/taxcalc/tests/puf_var_wght_means_by_year.csv b/taxcalc/tests/puf_var_wght_means_by_year.csv index 034ea783c..4f4d61834 100644 --- a/taxcalc/tests/puf_var_wght_means_by_year.csv +++ b/taxcalc/tests/puf_var_wght_means_by_year.csv @@ -1,10 +1,10 @@ ,description,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034 -c00100,Federal AGI, 50840, 54457, 54942, 55071, 58024, 60318, 61591, 63130, 73017, 72224, 75917, 77963, 80251, 82363, 84515, 86850, 89344, 91950, 94677, 98306, 99812, 102616 +c00100,Federal AGI, 50840, 54457, 54942, 55071, 58024, 60318, 61591, 63130, 73017, 72224, 75916, 77963, 80250, 82362, 84514, 86849, 89344, 91950, 94677, 98306, 99812, 102616 c02500,OASDI benefits in AGI, 1295, 1394, 1416, 1479, 1501, 1587, 1690, 1832, 2005, 2129, 2428, 2659, 2844, 3028, 3214, 3413, 3619, 3833, 4055, 4308, 4459, 4698 c04470,Post-phase-out itemized deduction, 5908, 6037, 6150, 6383, 6563, 6803, 7011, 7493, 7881, 8018, 8324, 8672, 8950, 9288, 9614, 9940, 10266, 10611, 10970, 11450, 11641, 12004 c04600,Post-phase-out personal exemption, 7105, 7131, 7163, 7217, 7149, 7247, 7380, 7471, 7481, 7806, 8373, 8834, 9054, 9248, 9434, 9612, 9797, 9988, 10186, 10398, 10579, 10791 -c04800,Federal regular taxable income, 35753, 39297, 39663, 39591, 42568, 44523, 45416, 46476, 55959, 54603, 57322, 58386, 60072, 61575, 63147, 64912, 66832, 68828, 70916, 73686, 74836, 76970 -c05200,Regular tax on taxable income, 7671, 8731, 8725, 8584, 9499, 10001, 10138, 10475, 13361, 12576, 13165, 13230, 13561, 13847, 14165, 14544, 14965, 15398, 15840, 16404, 16817, 17279 +c04800,Federal regular taxable income, 35753, 39297, 39663, 39591, 42568, 44523, 45416, 46476, 55959, 54603, 57321, 58385, 60072, 61575, 63147, 64911, 66831, 68828, 70916, 73686, 74835, 76970 +c05200,Regular tax on taxable income, 7671, 8731, 8725, 8584, 9499, 10001, 10138, 10475, 13361, 12576, 13165, 13230, 13561, 13847, 14165, 14544, 14965, 15398, 15840, 16404, 16816, 17278 c07180,Child care credit, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 16 c07220,Child tax credit (adjusted), 158, 155, 147, 143, 139, 134, 129, 124, 359, 116, 107, 101, 97, 94, 91, 88, 85, 82, 80, 77, 74, 72 c09600,Federal AMT liability, 212, 227, 240, 251, 268, 280, 288, 317, 351, 339, 347, 357, 371, 387, 400, 415, 430, 446, 458, 487, 496, 513 @@ -67,7 +67,7 @@ e87530,Adjusted qualified lifetime learning expenses for all students, 93, eitc,Federal EITC, 376, 369, 364, 352, 342, 340, 341, 347, 324, 335, 363, 385, 391, 395, 399, 403, 407, 411, 417, 425, 429, 436 elderly_dependents,number of dependents age 65+ in filing unit excluding taxpayer and spouse, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 g20500,Itemizable gross (before 10% AGI disregard) casualty or theft loss, 29, 30, 31, 32, 33, 35, 36, 38, 40, 41, 42, 44, 47, 48, 50, 52, 55, 57, 60, 63, 62, 66 -iitax,Federal income tax liability, 6550, 7474, 7521, 7477, 8281, 8755, 8952, 6544, 9149, 11189, 11708, 11835, 12204, 12533, 12876, 13267, 13691, 14122, 14560, 15122, 15521, 15974 +iitax,Federal income tax liability, 6550, 7474, 7521, 7477, 8281, 8755, 8952, 6544, 9149, 11189, 11708, 11835, 12203, 12533, 12876, 13267, 13691, 14122, 14560, 15122, 15521, 15974 k1bx14p,Partner self-employment earnings/loss for taxpayer (included in e26270 total), -213, -239, -187, -162, -144, -139, -133, -129, -156, -168, -183, -181, -178, -175, -168, -158, -146, -124, -103, -67, -149, -123 k1bx14s,Partner self-employment earnings/loss for spouse (included in e26270 total), -7, -9, 0, 2, 8, 10, 11, 11, 13, 14, 14, 14, 15, 16, 18, 21, 25, 27, 31, 34, 28, 33 nu06,Number of dependents under 6 years old, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -75,6 +75,6 @@ nu13,Number of dependents under 13 years old, 0, 0, 0, 0 p08000,Other tax credits (but not including Sch R credit), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 p22250,Sch D: Net short-term capital gains/losses, -120, -173, -172, -151, -195, -212, -202, -267, -481, -308, -330, -304, -299, -292, -288, -288, -290, -293, -284, -286, -326, -335 p23250,Sch D: Net long-term capital gains/losses, 2284, 3191, 3138, 2776, 3680, 3912, 3596, 4616, 8212, 5153, 5389, 4987, 4839, 4662, 4598, 4612, 4669, 4756, 4864, 5023, 5090, 5224 -payrolltax,Payroll taxes (ee+er) for OASDI+HI, 5193, 5382, 5440, 5516, 5676, 5834, 6009, 6042, 6437, 6824, 7146, 7406, 7654, 7894, 8123, 8356, 8597, 8851, 9119, 9479, 9575, 9841 +payrolltax,Payroll taxes (ee+er) for OASDI+HI, 5193, 5382, 5440, 5516, 5676, 5834, 6009, 6042, 6437, 6824, 7161, 7425, 7674, 7914, 8144, 8377, 8619, 8873, 9142, 9503, 9599, 9866 pencon_p,Contributions to defined-contribution pension plans for taxpayer, 856, 897, 916, 941, 963, 996, 1029, 1030, 1107, 1185, 1239, 1282, 1326, 1368, 1408, 1448, 1491, 1532, 1578, 1638, 1655, 1698 pencon_s,Contributions to defined-contribution pension plans for spouse, 393, 410, 421, 424, 440, 452, 466, 466, 500, 535, 558, 577, 595, 612, 629, 645, 661, 678, 695, 720, 738, 756 diff --git a/taxcalc/tests/pufcsv_agg_expect.csv b/taxcalc/tests/pufcsv_agg_expect.csv index d3b8c3a4a..8b7b27a3e 100644 --- a/taxcalc/tests/pufcsv_agg_expect.csv +++ b/taxcalc/tests/pufcsv_agg_expect.csv @@ -1,26 +1,26 @@ ,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026 Returns (#m),190.9,194.3,197.3,200.1,202.9,205.6,208.4,211.2,214.0,216.8 -AGI ($b),11078.7,11816.6,12247.2,12722.3,14930.0,14973.9,15955.0,16597.5,17310.2,17852.5 -Itemizers (#m),45.7,19.4,20.0,21.0,22.6,22.8,21.6,21.1,21.2,51.9 -Itemized Deduction ($b),1274.3,602.7,633.9,692.3,761.9,782.7,786.5,805.6,831.9,2047.9 -Standard Deduction Filers (#m),145.2,174.8,177.2,178.5,179.6,182.8,186.8,190.0,192.8,164.8 -Standard Deduction ($b),1239.3,2865.3,2954.5,3025.8,3081.1,3234.0,3549.8,3811.2,3966.7,1856.2 -Personal Exemption ($b),1365.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1959.2 -Taxable Income ($b),8112.2,9179.2,9520.5,9907.3,12003.2,11927.7,12692.4,13124.8,13697.6,13377.8 -Regular Tax ($b),1656.8,1712.3,1778.2,1838.3,2281.5,2282.7,2421.7,2488.0,2599.2,2792.6 -AMT Income ($b),10512.4,11343.5,11749.7,12180.1,14330.8,14356.1,15324.3,15944.7,16632.8,16934.0 -AMT Liability ($b),51.3,22.1,23.0,25.1,27.8,27.4,28.8,30.3,31.8,85.1 +AGI ($b),11078.7,11816.6,12247.2,12722.3,14930.0,14973.9,15955.0,16597.4,17310.1,18001.3 +Itemizers (#m),45.7,19.4,20.0,21.0,22.6,22.8,21.7,21.2,21.3,52.0 +Itemized Deduction ($b),1274.3,602.7,633.9,692.3,761.9,782.7,788.7,808.1,835.2,2047.5 +Standard Deduction Filers (#m),145.2,174.8,177.2,178.5,179.6,182.8,186.7,190.0,192.6,164.8 +Standard Deduction ($b),1239.3,2865.3,2954.5,3025.8,3081.1,3234.0,3537.5,3798.4,3952.6,1853.9 +Personal Exemption ($b),1365.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1959.0 +Taxable Income ($b),8112.2,9179.2,9520.5,9907.3,12003.2,11927.7,12697.8,13130.7,13703.8,13460.3 +Regular Tax ($b),1656.8,1712.3,1778.2,1838.3,2281.5,2282.7,2423.4,2489.9,2601.1,2816.2 +AMT Income ($b),10512.4,11343.5,11749.7,12180.1,14330.8,14356.1,15323.1,15943.0,16630.5,17082.5 +AMT Liability ($b),51.3,22.1,23.0,25.1,27.8,27.4,28.8,30.3,31.8,87.9 AMT Filers (#m),5.7,0.2,0.2,0.3,0.4,0.3,0.3,0.3,0.3,7.4 -Tax before Credits ($b),1708.1,1734.4,1801.1,1863.4,2309.4,2310.1,2450.5,2518.3,2631.0,2877.6 -Refundable Credits ($b),102.9,117.5,118.5,642.0,802.6,119.2,127.0,133.0,135.2,121.9 -Nonrefundable Credits ($b),67.0,127.3,129.2,128.5,47.6,141.0,143.3,143.9,145.7,77.7 +Tax before Credits ($b),1708.1,1734.4,1801.1,1863.4,2309.4,2310.1,2452.2,2520.2,2632.9,2904.0 +Refundable Credits ($b),102.9,117.5,118.5,642.0,802.6,119.2,126.9,132.8,135.0,121.7 +Nonrefundable Credits ($b),67.0,127.3,129.2,128.5,47.6,141.0,143.3,144.0,145.7,77.7 Reform Surtaxes ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -Other Taxes ($b),40.0,44.8,43.6,52.9,84.9,61.5,66.5,65.2,66.0,64.2 -Ind Income Tax ($b),1578.2,1534.3,1597.0,1145.8,1544.0,2111.5,2246.7,2306.7,2416.1,2742.2 -Payroll Taxes ($b),1083.8,1133.3,1185.4,1209.0,1306.0,1403.4,1489.3,1563.9,1637.9,1711.0 -Combined Liability ($b),2662.0,2667.7,2782.4,2354.8,2850.0,3514.9,3736.0,3870.6,4054.0,4453.2 -With Income Tax <= 0 (#m),92.8,98.6,99.7,131.7,125.0,100.3,101.9,103.4,104.4,101.0 -With Combined Tax <= 0 (#m),63.4,65.6,66.8,102.1,94.5,68.9,70.2,71.6,72.6,72.4 +Other Taxes ($b),40.0,44.8,43.6,52.9,84.9,61.5,66.5,65.2,66.0,66.3 +Ind Income Tax ($b),1578.2,1534.3,1597.0,1145.8,1544.0,2111.5,2248.5,2308.6,2418.2,2770.9 +Payroll Taxes ($b),1083.8,1133.3,1185.4,1209.0,1306.0,1403.4,1492.6,1568.0,1642.1,1715.4 +Combined Liability ($b),2662.0,2667.7,2782.4,2354.8,2850.0,3514.9,3741.1,3876.6,4060.3,4486.3 +With Income Tax <= 0 (#m),92.8,98.6,99.7,131.7,125.0,100.3,101.8,103.4,104.3,100.9 +With Combined Tax <= 0 (#m),63.4,65.6,66.8,102.1,94.5,68.9,70.2,71.6,72.6,72.3 UBI Benefits ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "Total Benefits, Consumption Value ($b)",1052.3,1104.9,1175.3,1243.9,1476.4,1411.5,1569.5,1707.8,1818.1,1924.4 Total Benefits Cost ($b),1052.3,1104.9,1175.3,1243.9,1476.4,1411.5,1569.5,1707.8,1818.1,1924.4 diff --git a/taxcalc/tests/test_policy.py b/taxcalc/tests/test_policy.py index 5751321df..41ba8db3e 100644 --- a/taxcalc/tests/test_policy.py +++ b/taxcalc/tests/test_policy.py @@ -43,7 +43,7 @@ def test_incorrect_class_instantiation(): Test incorrect instantiation of Policy class object. """ with pytest.raises(ValueError): - Policy(gfactors=list()) + Policy(gfactors=[]) def test_correct_class_instantiation(): @@ -54,7 +54,7 @@ def test_correct_class_instantiation(): assert pol pol.implement_reform({}) with pytest.raises(pt.ValidationError): - pol.implement_reform(list()) + pol.implement_reform([]) with pytest.raises(pt.ValidationError): pol.implement_reform({2099: {'II_em': 99000}}) pol.set_year(2019) @@ -621,7 +621,7 @@ def generate_section_dictionary(md_text): structured like the VALID_SECTION dictionary (see below) and extracted from the specified html_text. """ - sdict = dict() + sdict = {} for line in md_text.splitlines(): # This is shown as an empty case in current law policy and # validation. @@ -647,7 +647,6 @@ def generate_section_dictionary(md_text): 'As A Percent Of Deductible Expenses') cgqd_tax_same = ('Tax All Capital Gains And Dividends The Same ' 'As Regular Taxable Income') - # pylint: disable=bad-continuation valid_dict = { '': { # empty section_1 implies parameter not displayed in Tax-Brain '': 0 @@ -737,11 +736,11 @@ def generate_section_dictionary(md_text): } # check validity of parameter section titles in policy_current_law.json path = os.path.join(tests_path, '..', 'policy_current_law.json') - with open(path, 'r') as clpfile: + with open(path, 'r', encoding='utf-8') as clpfile: clpdict = json.load(clpfile) clpdict.pop("schema", None) # ... make sure ever clpdict section title is in valid_dict - clp_dict = dict() # dictionary of clp section titles structured like valid + clp_dict = {} # dictionary of clp section titles structured like valid for pname in clpdict: param = clpdict[pname] assert isinstance(param, dict) @@ -754,28 +753,28 @@ def generate_section_dictionary(md_text): if sec2title not in clp_dict[sec1title]: clp_dict[sec1title][sec2title] = 0 # ... make sure every valid_dict section title is in clpdict - for sec1title in valid_dict: - assert isinstance(valid_dict[sec1title], dict) + for sec1title, secdict in valid_dict.items(): + assert isinstance(secdict, dict) assert sec1title in clp_dict - for sec2title in valid_dict[sec1title]: + for sec2title in secdict: assert sec2title in clp_dict[sec1title] # check validity of parameter section titles in docs/uguide.htmx skeleton path = os.path.join(tests_path, '..', '..', 'docs', 'guide', 'policy_params.md') - with open(path, 'r') as md_file: + with open(path, 'r', encoding='utf-8') as md_file: md_text = md_file.read() md_dict = generate_section_dictionary(md_text) # ... make sure every md_dict section title is in valid_dict - for sec1title in md_dict: - assert isinstance(md_dict[sec1title], dict) + for sec1title,secdict in md_dict.items(): + assert isinstance(secdict, dict) assert sec1title in valid_dict - for sec2title in md_dict[sec1title]: + for sec2title in secdict: assert sec2title in valid_dict[sec1title] # ... make sure every valid_dict section title is in md_dict - for sec1title in valid_dict: - assert isinstance(valid_dict[sec1title], dict) + for sec1title, secdict in valid_dict.items(): + assert isinstance(secdict, dict) assert sec1title in md_dict - for sec2title in valid_dict[sec1title]: + for sec2title in secdict: assert sec2title in md_dict[sec1title] @@ -785,7 +784,7 @@ def test_description_punctuation(tests_path): """ # read JSON file into a dictionary path = os.path.join(tests_path, '..', 'policy_current_law.json') - with open(path, 'r') as jsonfile: + with open(path, 'r', encoding='utf-8') as jsonfile: dct = json.load(jsonfile) dct.pop("schema", None) all_desc_ok = True @@ -931,8 +930,8 @@ def test_index_offset_reform(): policy2 = Policy() policy2.implement_reform(reform2) # caused T-C crash before PR#2364 # extract from policy1 and policy2 the parameter values of CTC_c - pvalue1 = dict() - pvalue2 = dict() + pvalue1 = {} + pvalue2 = {} for cyr in [2019, 2020, 2021]: policy1.set_year(cyr) pvalue1[cyr] = policy1.CTC_c[0] @@ -945,8 +944,7 @@ def test_index_offset_reform(): # ... indexing of CTC_c begins shows up first in 2021 parameter values assert pvalue1[2021] > pvalue1[2020] assert pvalue2[2021] > pvalue2[2020] - # ... calculate expected pvalue2[2021] from offset and pvalue1 values - indexrate1 = pvalue1[2021] / pvalue1[2020] - 1. + # ... calculate expected pvalue2[2021] from inflation rates and offset syear = Policy.JSON_START_YEAR expindexrate = cpiu_rates[2020 - syear] + offset expvalue = round(pvalue2[2020] * (1. + expindexrate), 2) @@ -1032,525 +1030,509 @@ def test_raise_errors_regression(): assert pol.errors -class TestAdjust: +def test_simple_adj(): """ - Test update and indexing rules as defined in the Parameters docstring. - - Each test implements a Tax-Calculator style reform and a pt styled - reform, checks that the updated values are equal, and then, tests that - values were extended and indexed (or not indexed) correctly. + Test updating a 2D parameter that is indexed to inflation. """ - - def test_simple_adj(self): - """ - Test updating a 2D parameter that is indexed to inflation. - """ - pol1 = Policy() - pol1.implement_reform( - { - "EITC_c": { - 2020: [10000, 10001, 10002, 10003], - 2023: [20000, 20001, 20002, 20003], - } - } - ) - - pol2 = Policy() - pol2.adjust( - { - "EITC_c": [ - {"year": 2020, "EIC": "0kids", "value": 10000}, - {"year": 2020, "EIC": "1kid", "value": 10001}, - {"year": 2020, "EIC": "2kids", "value": 10002}, - {"year": 2020, "EIC": "3+kids", "value": 10003}, - {"year": 2023, "EIC": "0kids", "value": 20000}, - {"year": 2023, "EIC": "1kid", "value": 20001}, - {"year": 2023, "EIC": "2kids", "value": 20002}, - {"year": 2023, "EIC": "3+kids", "value": 20003}, - ] - } - ) - cmp_policy_objs(pol1, pol2) - - pol0 = Policy() - pol0.set_year(2019) - pol2.set_year(2019) - - assert np.allclose(pol0.EITC_c, pol2.EITC_c) - - pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) - val2020 = np.array([[10000, 10001, 10002, 10003]]) - val2023 = np.array([[20000, 20001, 20002, 20003]]) - - exp = np.vstack([ - val2020, - val2020 * (1 + pol2.inflation_rates(year=2020)), - ( - val2020 * (1 + pol2.inflation_rates(year=2020)) - ).round(2) * (1 + pol2.inflation_rates(year=2021)), - val2023, - val2023 * (1 + pol2.inflation_rates(year=2023)), - ]).round(2) - np.testing.assert_allclose(pol2.EITC_c, exp) - - def test_adj_without_index_1(self): - """ - Test update indexed parameter after turning off its - indexed status. - """ - pol1 = Policy() - pol1.implement_reform( - { - "EITC_c": { - 2020: [10000, 10001, 10002, 10003], - 2023: [20000, 20001, 20002, 20003], - }, - "EITC_c-indexed": {2019: False}, - } - ) - - pol2 = Policy() - pol2.adjust( - { - "EITC_c": [ - {"year": 2020, "EIC": "0kids", "value": 10000}, - {"year": 2020, "EIC": "1kid", "value": 10001}, - {"year": 2020, "EIC": "2kids", "value": 10002}, - {"year": 2020, "EIC": "3+kids", "value": 10003}, - {"year": 2023, "EIC": "0kids", "value": 20000}, - {"year": 2023, "EIC": "1kid", "value": 20001}, - {"year": 2023, "EIC": "2kids", "value": 20002}, - {"year": 2023, "EIC": "3+kids", "value": 20003}, - ], - "EITC_c-indexed": [{"year": 2019, "value": False}], + pol1 = Policy() + pol1.implement_reform( + { + "EITC_c": { + 2020: [10000, 10001, 10002, 10003], + 2023: [20000, 20001, 20002, 20003], } - ) - cmp_policy_objs(pol1, pol2) + } + ) + pol2 = Policy() + pol2.adjust( + { + "EITC_c": [ + {"year": 2020, "EIC": "0kids", "value": 10000}, + {"year": 2020, "EIC": "1kid", "value": 10001}, + {"year": 2020, "EIC": "2kids", "value": 10002}, + {"year": 2020, "EIC": "3+kids", "value": 10003}, + {"year": 2023, "EIC": "0kids", "value": 20000}, + {"year": 2023, "EIC": "1kid", "value": 20001}, + {"year": 2023, "EIC": "2kids", "value": 20002}, + {"year": 2023, "EIC": "3+kids", "value": 20003}, + ] + } + ) + cmp_policy_objs(pol1, pol2) - pol0 = Policy() - pol0.set_year(2019) - pol2.set_year(2019) + pol0 = Policy() + pol0.set_year(2019) + pol2.set_year(2019) - assert np.allclose(pol0.EITC_c, pol2.EITC_c) + assert np.allclose(pol0.EITC_c, pol2.EITC_c) - pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) + pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) + val2020 = np.array([[10000, 10001, 10002, 10003]]) + val2023 = np.array([[20000, 20001, 20002, 20003]]) - val2020 = np.array([[10000, 10001, 10002, 10003]]) - val2023 = np.array([[20000, 20001, 20002, 20003]]) + exp = np.vstack([ + val2020, + val2020 * (1 + pol2.inflation_rates(year=2020)), + ( + val2020 * (1 + pol2.inflation_rates(year=2020)) + ).round(2) * (1 + pol2.inflation_rates(year=2021)), + val2023, + val2023 * (1 + pol2.inflation_rates(year=2023)), + ]).round(2) + np.testing.assert_allclose(pol2.EITC_c, exp) - exp = np.vstack([ - val2020, - val2020, - val2020, - val2023, - val2023, - ]).round(2) - np.testing.assert_allclose(pol2.EITC_c, exp) - def test_adj_without_index_2(self): - """ - Test updating an indexed parameter, making it unindexed, - and then adjusting it again. - """ - pol1 = Policy() - pol1.implement_reform( - { - "EITC_c": { - 2020: [10000, 10001, 10002, 10003], - 2023: [20000, 20001, 20002, 20003], - }, - "EITC_c-indexed": {2022: False}, - } - ) +def test_adj_without_index_1(): + """ + Test update indexed parameter after turning off its indexed status. + """ + pol1 = Policy() + pol1.implement_reform( + { + "EITC_c": { + 2020: [10000, 10001, 10002, 10003], + 2023: [20000, 20001, 20002, 20003], + }, + "EITC_c-indexed": {2019: False}, + } + ) + pol2 = Policy() + pol2.adjust( + { + "EITC_c": [ + {"year": 2020, "EIC": "0kids", "value": 10000}, + {"year": 2020, "EIC": "1kid", "value": 10001}, + {"year": 2020, "EIC": "2kids", "value": 10002}, + {"year": 2020, "EIC": "3+kids", "value": 10003}, + {"year": 2023, "EIC": "0kids", "value": 20000}, + {"year": 2023, "EIC": "1kid", "value": 20001}, + {"year": 2023, "EIC": "2kids", "value": 20002}, + {"year": 2023, "EIC": "3+kids", "value": 20003}, + ], + "EITC_c-indexed": [{"year": 2019, "value": False}], + } + ) + cmp_policy_objs(pol1, pol2) - pol2 = Policy() - pol2.adjust( - { - "EITC_c": [ - {"year": 2020, "EIC": "0kids", "value": 10000}, - {"year": 2020, "EIC": "1kid", "value": 10001}, - {"year": 2020, "EIC": "2kids", "value": 10002}, - {"year": 2020, "EIC": "3+kids", "value": 10003}, - {"year": 2023, "EIC": "0kids", "value": 20000}, - {"year": 2023, "EIC": "1kid", "value": 20001}, - {"year": 2023, "EIC": "2kids", "value": 20002}, - {"year": 2023, "EIC": "3+kids", "value": 20003}, - ], - "EITC_c-indexed": [{"year": 2022, "value": False}], - } - ) - cmp_policy_objs(pol1, pol2) + pol0 = Policy() + pol0.set_year(2019) + pol2.set_year(2019) - pol0 = Policy() - pol0.set_year(2019) - pol2.set_year(2019) + assert np.allclose(pol0.EITC_c, pol2.EITC_c) - assert np.allclose(pol0.EITC_c, pol2.EITC_c) + pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) - pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) + val2020 = np.array([[10000, 10001, 10002, 10003]]) + val2023 = np.array([[20000, 20001, 20002, 20003]]) - val2020 = np.array([[10000, 10001, 10002, 10003]]) - val2023 = np.array([[20000, 20001, 20002, 20003]]) + exp = np.vstack([ + val2020, + val2020, + val2020, + val2023, + val2023, + ]).round(2) + np.testing.assert_allclose(pol2.EITC_c, exp) - exp = np.vstack([ - val2020, - val2020 * (1 + pol2.inflation_rates(year=2020)), - ( - val2020 * (1 + pol2.inflation_rates(year=2020)) - ).round(2) * (1 + pol2.inflation_rates(year=2021)), - val2023, - val2023, - ]).round(2) - np.testing.assert_allclose(pol2.EITC_c, exp) - def test_activate_index(self): - """ - Test changing a non-indexed parameter to an indexed parameter. - """ - pol1 = Policy() - pol1.implement_reform({ - "CTC_c": {2022: 2000}, - "CTC_c-indexed": {2022: True} - }) - - pol2 = Policy() - pol2.adjust( - { - "CTC_c": [{"year": 2022, "value": 2000}], - "CTC_c-indexed": [{"year": 2022, "value": True}], - } - ) - cmp_policy_objs(pol1, pol2) +def test_adj_without_index_2(): + """ + Test updating an indexed parameter, making it unindexed, + and then adjusting it again. + """ + pol1 = Policy() + pol1.implement_reform( + { + "EITC_c": { + 2020: [10000, 10001, 10002, 10003], + 2023: [20000, 20001, 20002, 20003], + }, + "EITC_c-indexed": {2022: False}, + } + ) + pol2 = Policy() + pol2.adjust( + { + "EITC_c": [ + {"year": 2020, "EIC": "0kids", "value": 10000}, + {"year": 2020, "EIC": "1kid", "value": 10001}, + {"year": 2020, "EIC": "2kids", "value": 10002}, + {"year": 2020, "EIC": "3+kids", "value": 10003}, + {"year": 2023, "EIC": "0kids", "value": 20000}, + {"year": 2023, "EIC": "1kid", "value": 20001}, + {"year": 2023, "EIC": "2kids", "value": 20002}, + {"year": 2023, "EIC": "3+kids", "value": 20003}, + ], + "EITC_c-indexed": [{"year": 2022, "value": False}], + } + ) + cmp_policy_objs(pol1, pol2) - pol0 = Policy() - pol0.set_year(year=2021) - pol2.set_state(year=[2021, 2022, 2023]) - exp = np.array([ - pol0.CTC_c[0], - 2000, - 2000 * (1 + pol2.inflation_rates(year=2022)) - ]).round(2) + pol0 = Policy() + pol0.set_year(2019) + pol2.set_year(2019) - np.testing.assert_allclose(pol2.CTC_c, exp) + assert np.allclose(pol0.EITC_c, pol2.EITC_c) - def test_apply_cpi_offset(self): - """ - Test applying the parameter_indexing_CPI_offset parameter - without any other parameters. - """ - pol1 = Policy() - pol1.implement_reform( - {"parameter_indexing_CPI_offset": {2021: -0.001}} - ) + pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) - pol2 = Policy() - pol2.adjust( - {"parameter_indexing_CPI_offset": [ - {"year": 2021, "value": -0.001} - ]} - ) + val2020 = np.array([[10000, 10001, 10002, 10003]]) + val2023 = np.array([[20000, 20001, 20002, 20003]]) - cmp_policy_objs(pol1, pol2) + exp = np.vstack([ + val2020, + val2020 * (1 + pol2.inflation_rates(year=2020)), + ( + val2020 * (1 + pol2.inflation_rates(year=2020)) + ).round(2) * (1 + pol2.inflation_rates(year=2021)), + val2023, + val2023, + ]).round(2) + np.testing.assert_allclose(pol2.EITC_c, exp) - pol0 = Policy() - pol0.implement_reform({"parameter_indexing_CPI_offset": {2021: 0}}) - init_rates = pol0.inflation_rates() - new_rates = pol2.inflation_rates() +def test_activate_index(): + """ + Test changing a non-indexed parameter to an indexed parameter. + """ + pol1 = Policy() + pol1.implement_reform({ + "CTC_c": {2022: 2000}, + "CTC_c-indexed": {2022: True} + }) + pol2 = Policy() + pol2.adjust( + { + "CTC_c": [{"year": 2022, "value": 2000}], + "CTC_c-indexed": [{"year": 2022, "value": True}], + } + ) + cmp_policy_objs(pol1, pol2) - start_ix = 2021 - pol2.start_year + pol0 = Policy() + pol0.set_year(year=2021) + pol2.set_state(year=[2021, 2022, 2023]) + exp = np.array([ + pol0.CTC_c[0], + 2000, + 2000 * (1 + pol2.inflation_rates(year=2022)) + ]).round(2) - exp_rates = copy.deepcopy(new_rates) - exp_rates[start_ix:] -= pol2._parameter_indexing_CPI_offset[start_ix:] - np.testing.assert_allclose(init_rates, exp_rates) + np.testing.assert_allclose(pol2.CTC_c, exp) - # make sure values prior to 2021 were not affected. - cmp_policy_objs(pol0, pol2, year_range=range(pol2.start_year, 2021)) - pol2.set_state(year=[2022, 2023]) - np.testing.assert_equal( - (pol2.EITC_c[1] / pol2.EITC_c[0] - 1).round(4), - (pol0.inflation_rates(year=2022) + (-0.001)).round(4), - ) +def test_apply_cpi_offset(): + """ + Test applying the parameter_indexing_CPI_offset parameter + without any other parameters. + """ + pol1 = Policy() + pol1.implement_reform( + {"parameter_indexing_CPI_offset": {2021: -0.001}} + ) + pol2 = Policy() + pol2.adjust( + {"parameter_indexing_CPI_offset": [ + {"year": 2021, "value": -0.001} + ]} + ) + cmp_policy_objs(pol1, pol2) - def test_multiple_cpi_swaps(self): - """ - Test changing a parameter's indexed status multiple times. - """ - pol1 = Policy() - pol1.implement_reform( - { - "II_em": {2016: 6000, 2018: 7500, 2020: 9000}, - "II_em-indexed": {2016: False, 2018: True}, - } - ) + pol0 = Policy() + pol0.implement_reform({"parameter_indexing_CPI_offset": {2021: 0}}) - pol2 = Policy() - pol2.adjust( - { - "II_em": [ - {"year": 2016, "value": 6000}, - {"year": 2018, "value": 7500}, - {"year": 2020, "value": 9000}, - ], - "II_em-indexed": [ - {"year": 2016, "value": False}, - {"year": 2018, "value": True}, - ], - } - ) + init_rates = pol0.inflation_rates() + new_rates = pol2.inflation_rates() - cmp_policy_objs(pol1, pol2) + start_ix = 2021 - pol2.start_year - # check inflation is not applied. - pol2.set_state(year=[2016, 2017]) - np.testing.assert_equal( - pol2.II_em[0], pol2.II_em[1] - ) + exp_rates = copy.deepcopy(new_rates) + exp_rates[start_ix:] -= pol2._parameter_indexing_CPI_offset[start_ix:] + np.testing.assert_allclose(init_rates, exp_rates) - # check inflation rate is applied. - pol2.set_state(year=[2018, 2019]) - np.testing.assert_equal( - (pol2.II_em[1] / pol2.II_em[0] - 1).round(4), - pol2.inflation_rates(year=2018), - ) + # make sure values prior to 2021 were not affected. + cmp_policy_objs(pol0, pol2, year_range=range(pol2.start_year, 2021)) - # check inflation rate applied for rest of window. - window = list(range(2020, pol2.end_year + 1)) - pol2.set_state(year=window) - np.testing.assert_equal( - (pol2.II_em[1:] / pol2.II_em[:-1] - 1).round(4), - [pol2.inflation_rates(year=year) for year in window[:-1]], - ) + test_year = Policy.LAST_KNOWN_YEAR + pol2.set_state(year=[test_year, test_year + 1]) + np.testing.assert_equal( + (pol2.EITC_c[1] / pol2.EITC_c[0] - 1).round(4), + (pol0.inflation_rates(year=test_year) + (-0.001)).round(4), + ) - def test_multiple_cpi_swaps2(self): - """ - Test changing the indexed status of multiple parameters multiple - times. - """ - pol1 = Policy() - pol1.implement_reform( - { - "II_em": {2016: 6000, 2018: 7500, 2020: 9000}, - "II_em-indexed": {2016: False, 2018: True}, - "SS_Earnings_c": {2016: 300000, 2018: 500000}, - "SS_Earnings_c-indexed": {2017: False, 2019: True}, - "AMT_em-indexed": {2017: False, 2020: True}, - } - ) - pol2 = Policy() - pol2.adjust( - { - "SS_Earnings_c": [ - {"year": 2016, "value": 300000}, - {"year": 2018, "value": 500000}, - ], - "SS_Earnings_c-indexed": [ - {"year": 2017, "value": False}, - {"year": 2019, "value": True}, - ], - "AMT_em-indexed": [ - {"year": 2017, "value": False}, - {"year": 2020, "value": True}, - ], - "II_em": [ - {"year": 2016, "value": 6000}, - {"year": 2018, "value": 7500}, - {"year": 2020, "value": 9000}, - ], - "II_em-indexed": [ - {"year": 2016, "value": False}, - {"year": 2018, "value": True}, - ], - } - ) +def test_multiple_cpi_swaps(): + """ + Test changing a parameter's indexed status multiple times. + """ + pol1 = Policy() + pol1.implement_reform( + { + "II_em": {2016: 6000, 2018: 7500, 2020: 9000}, + "II_em-indexed": {2016: False, 2018: True}, + } + ) + pol2 = Policy() + pol2.adjust( + { + "II_em": [ + {"year": 2016, "value": 6000}, + {"year": 2018, "value": 7500}, + {"year": 2020, "value": 9000}, + ], + "II_em-indexed": [ + {"year": 2016, "value": False}, + {"year": 2018, "value": True}, + ], + } + ) + cmp_policy_objs(pol1, pol2) - cmp_policy_objs(pol1, pol2) + # check inflation is not applied. + pol2.set_state(year=[2016, 2017]) + np.testing.assert_equal( + pol2.II_em[0], pol2.II_em[1] + ) - # Test SS_Earnings_c - # check inflation is still applied from 2016 to 2017. - pol2.set_state(year=[2016, 2017]) - np.testing.assert_equal( - (pol2.SS_Earnings_c[1] / pol2.SS_Earnings_c[0] - 1).round(4), - pol2.wage_growth_rates(year=2016), - ) + # check inflation rate is applied. + pol2.set_state(year=[2018, 2019]) + np.testing.assert_equal( + (pol2.II_em[1] / pol2.II_em[0] - 1).round(4), + pol2.inflation_rates(year=2018), + ) - # check inflation rate is not applied after adjustment in 2018. - pol2.set_state(year=[2018, 2019]) - np.testing.assert_equal( - pol2.SS_Earnings_c[0], pol2.SS_Earnings_c[1] - ) + # check inflation rate applied for rest of window. + window = list(range(2020, pol2.end_year + 1)) + pol2.set_state(year=window) + np.testing.assert_equal( + (pol2.II_em[1:] / pol2.II_em[:-1] - 1).round(4), + [pol2.inflation_rates(year=year) for year in window[:-1]], + ) - # check inflation rate applied for rest of window. - window = list(range(2019, pol2.end_year + 1)) - pol2.set_state(year=window) - np.testing.assert_equal( - (pol2.SS_Earnings_c[1:] / pol2.SS_Earnings_c[:-1] - 1).round(4), - [pol2.wage_growth_rates(year=year) for year in window[:-1]], - ) - # Test AMT - # Check values for 2017 through 2020 are equal. - pol2.set_state(year=[2017, 2018, 2019, 2020]) - for i in (1, 2, 3): - np.testing.assert_equal( - pol2.AMT_em[0], pol2.AMT_em[i] - ) - - # check inflation rate applied for rest of window. - window = list(range(2020, pol2.end_year + 1)) - pol2.set_state(year=window) - # repeat inflation rates accross matrix so they can be compared to the - # rates derived from AMT_em, a 5 * N matrix. - exp_rates = [pol2.inflation_rates(year=year) for year in window[:-1]] - exp_rates = np.tile([exp_rates], (5, 1)).transpose() - np.testing.assert_equal( - (pol2.AMT_em[1:] / pol2.AMT_em[:-1] - 1).round(4), - exp_rates, - ) +def test_multiple_cpi_swaps2(): + """ + Test changing the indexed status of multiple parameters multiple times. + """ + pol1 = Policy() + pol1.implement_reform( + { + "II_em": {2016: 6000, 2018: 7500, 2020: 9000}, + "II_em-indexed": {2016: False, 2018: True}, + "SS_Earnings_c": {2016: 300000, 2018: 500000}, + "SS_Earnings_c-indexed": {2017: False, 2019: True}, + "AMT_em-indexed": {2017: False, 2020: True}, + } + ) + pol2 = Policy() + pol2.adjust( + { + "SS_Earnings_c": [ + {"year": 2016, "value": 300000}, + {"year": 2018, "value": 500000}, + ], + "SS_Earnings_c-indexed": [ + {"year": 2017, "value": False}, + {"year": 2019, "value": True}, + ], + "AMT_em-indexed": [ + {"year": 2017, "value": False}, + {"year": 2020, "value": True}, + ], + "II_em": [ + {"year": 2016, "value": 6000}, + {"year": 2018, "value": 7500}, + {"year": 2020, "value": 9000}, + ], + "II_em-indexed": [ + {"year": 2016, "value": False}, + {"year": 2018, "value": True}, + ], + } + ) + cmp_policy_objs(pol1, pol2) + + # Test SS_Earnings_c + # check inflation is still applied from 2016 to 2017. + pol2.set_state(year=[2016, 2017]) + np.testing.assert_equal( + (pol2.SS_Earnings_c[1] / pol2.SS_Earnings_c[0] - 1).round(4), + pol2.wage_growth_rates(year=2016), + ) - # Test II_em - # check inflation is not applied. - pol2.set_state(year=[2016, 2017]) - np.testing.assert_equal( - pol2.II_em[0], pol2.II_em[1] - ) + # check inflation rate is not applied after adjustment in 2018. + pol2.set_state(year=[2018, 2019]) + np.testing.assert_equal( + pol2.SS_Earnings_c[0], pol2.SS_Earnings_c[1] + ) - # check inflation rate is applied. - pol2.set_state(year=[2018, 2019]) - np.testing.assert_equal( - (pol2.II_em[1] / pol2.II_em[0] - 1).round(4), - pol2.inflation_rates(year=2018), - ) + # check inflation rate applied for rest of window. + window = list(range(2019, pol2.end_year + 1)) + pol2.set_state(year=window) + np.testing.assert_equal( + (pol2.SS_Earnings_c[1:] / pol2.SS_Earnings_c[:-1] - 1).round(4), + [pol2.wage_growth_rates(year=year) for year in window[:-1]], + ) - # check inflation rate applied for rest of window. - window = list(range(2020, pol2.end_year + 1)) - pol2.set_state(year=window) + # Test AMT + # Check values for 2017 through 2020 are equal. + pol2.set_state(year=[2017, 2018, 2019, 2020]) + for i in (1, 2, 3): np.testing.assert_equal( - (pol2.II_em[1:] / pol2.II_em[:-1] - 1).round(4), - [pol2.inflation_rates(year=year) for year in window[:-1]], - ) - - def test_adj_CPI_offset_and_index_status(self): - """ - Test changing parameter_indexing_CPI_offset and another - parameter simultaneously. - """ - pol1 = Policy() - pol1.implement_reform({ - "CTC_c-indexed": {2020: True}, - "parameter_indexing_CPI_offset": {2020: -0.005}}, - ) - - pol2 = Policy() - pol2.adjust( - { - "parameter_indexing_CPI_offset": - [{"year": 2020, "value": -0.005}], - "CTC_c-indexed": [{"year": 2020, "value": True}], - } + pol2.AMT_em[0], pol2.AMT_em[i] ) - cmp_policy_objs(pol1, pol2) - - # Check no difference prior to 2020 - pol0 = Policy() - pol0.implement_reform({"parameter_indexing_CPI_offset": {2020: 0}}) - cmp_policy_objs( - pol0, - pol2, - year_range=range(pol2.start_year, 2020 + 1), - exclude=["parameter_indexing_CPI_offset"] - ) + # check inflation rate applied for rest of window. + window = list(range(2020, pol2.end_year + 1)) + pol2.set_state(year=window) + # repeat inflation rates accross matrix so they can be compared to the + # rates derived from AMT_em, a 5 * N matrix. + exp_rates = [pol2.inflation_rates(year=year) for year in window[:-1]] + exp_rates = np.tile([exp_rates], (5, 1)).transpose() + np.testing.assert_equal( + (pol2.AMT_em[1:] / pol2.AMT_em[:-1] - 1).round(4), + exp_rates, + ) - pol2.set_state(year=[2021, 2022]) - np.testing.assert_equal( - (pol2.CTC_c[1] / pol2.CTC_c[0] - 1).round(4), - round(pol0.inflation_rates(year=2021) + (-0.005), 4), - ) + # Test II_em + # check inflation is not applied. + pol2.set_state(year=[2016, 2017]) + np.testing.assert_equal( + pol2.II_em[0], pol2.II_em[1] + ) - def test_adj_related_parameters_and_index_status(self): - """ - Test changing two related parameters simulataneously and - one of their indexed statuses. - """ + # check inflation rate is applied. + pol2.set_state(year=[2018, 2019]) + np.testing.assert_equal( + (pol2.II_em[1] / pol2.II_em[0] - 1).round(4), + pol2.inflation_rates(year=2018), + ) - pol = Policy() - pol.adjust( - { - "II_brk7-indexed": [{"year": 2020, "value": True}], - # Update II_brk5 in 2026 to make reform valid after reset. - "II_brk5": [{"value": 330000, "MARS": "single", "year": 2026}], - "II_brk6": [{"value": 316700, "MARS": "single", "year": 2020}], - "II_brk7": [{"value": 445400, "MARS": "single", "year": 2020}], - } - ) + # check inflation rate applied for rest of window. + window = list(range(2020, pol2.end_year + 1)) + pol2.set_state(year=window) + np.testing.assert_equal( + (pol2.II_em[1:] / pol2.II_em[:-1] - 1).round(4), + [pol2.inflation_rates(year=year) for year in window[:-1]], + ) - # Check no difference prior to 2020 - pol0 = Policy() - cmp_policy_objs( - pol0, - pol, - year_range=range(pol.start_year, 2019 + 1), - ) - res = ( - (pol.sel["II_brk6"]["MARS"] == "single") - & (pol.sel["II_brk6"]["year"] == 2020) - ) - assert res.isel[0]["value"] == [316700] - res = ( - (pol.sel["II_brk7"]["MARS"] == "single") - & (pol.sel["II_brk7"]["year"] == 2020) - ) - assert res.isel[0]["value"] == [445400] +def test_adj_CPI_offset_and_index_status(): + """ + Test changing parameter_indexing_CPI_offset and another + parameter simultaneously. + """ + pol1 = Policy() + pol1.implement_reform({ + "CTC_c-indexed": {2020: True}, + "parameter_indexing_CPI_offset": {2020: -0.005}}, + ) + pol2 = Policy() + pol2.adjust( + { + "parameter_indexing_CPI_offset": + [{"year": 2020, "value": -0.005}], + "CTC_c-indexed": [{"year": 2020, "value": True}], + } + ) + cmp_policy_objs(pol1, pol2) + + # Check no difference prior to 2020 + pol0 = Policy() + pol0.implement_reform({"parameter_indexing_CPI_offset": {2020: 0}}) + cmp_policy_objs( + pol0, + pol2, + year_range=range(pol2.start_year, 2020 + 1), + exclude=["parameter_indexing_CPI_offset"] + ) - II_brk7 = pol.to_array("II_brk7", year=[2021, 2022]) - II_brk7_single = II_brk7[:, 0] - np.testing.assert_equal( - (II_brk7_single[1] / II_brk7_single[0] - 1).round(4), - pol.inflation_rates(year=2021), - ) + pol2.set_state(year=[2021, 2022]) + np.testing.assert_equal( + (pol2.CTC_c[1] / pol2.CTC_c[0] - 1).round(4), + round(pol0.inflation_rates(year=2021) + (-0.005), 4), + ) - def test_indexed_status_parsing(self): - pol1 = Policy() - pol1.implement_reform({"EITC_c-indexed": {pol1.start_year: False}}) +def test_adj_related_parameters_and_index_status(): + """ + Test changing two related parameters simulataneously and + one of their indexed statuses. + """ + pol = Policy() + pol.adjust( + { + "II_brk7-indexed": [{"year": 2020, "value": True}], + # Update II_brk5 in 2026 to make reform valid after reset. + "II_brk5": [{"value": 330000, "MARS": "single", "year": 2026}], + "II_brk6": [{"value": 316700, "MARS": "single", "year": 2020}], + "II_brk7": [{"value": 445400, "MARS": "single", "year": 2020}], + } + ) - pol2 = Policy() - pol2.adjust({"EITC_c-indexed": False}) + # Check no difference prior to 2020 + pol0 = Policy() + cmp_policy_objs( + pol0, + pol, + year_range=range(pol.start_year, 2019 + 1), + ) - cmp_policy_objs(pol1, pol2) + res = ( + (pol.sel["II_brk6"]["MARS"] == "single") + & (pol.sel["II_brk6"]["year"] == 2020) + ) + assert res.isel[0]["value"] == [316700] + res = ( + (pol.sel["II_brk7"]["MARS"] == "single") + & (pol.sel["II_brk7"]["year"] == 2020) + ) + assert res.isel[0]["value"] == [445400] - with pytest.raises(pt.ValidationError): - pol2.adjust({"EITC_c-indexed": 123}) + II_brk7 = pol.to_array("II_brk7", year=[2021, 2022]) + II_brk7_single = II_brk7[:, 0] + np.testing.assert_equal( + (II_brk7_single[1] / II_brk7_single[0] - 1).round(4), + pol.inflation_rates(year=2021), + ) - def test_cpi_offset_does_not_affect_wage_indexed_params(self): - """ - Test adjusting parameter_indexing_CPI_offset does not affect unknown - values of wage indexed parameters like SS_Earnings_c. - """ - base_reform = { - "parameter_indexing_CPI_offset": {2021: -0.001}, - "SS_Earnings_c": {2024: 300000}, - } - pol0 = Policy() - pol0.implement_reform(base_reform) +def test_indexed_status_parsing(): + """ + Test parsing. + """ + pol1 = Policy() + pol1.implement_reform({"EITC_c-indexed": {pol1.start_year: False}}) + pol2 = Policy() + pol2.adjust({"EITC_c-indexed": False}) + cmp_policy_objs(pol1, pol2) - pol1 = Policy() - pol1.implement_reform(base_reform) - pol1.implement_reform(dict(base_reform, SS_Earnings_c={2025: 500000})) + with pytest.raises(pt.ValidationError): + pol2.adjust({"EITC_c-indexed": 123}) - exp_before_2025 = pol0.to_array( - "SS_Earnings_c", year=list(range(2021, 2024 + 1)) - ) - act_before_2025 = pol1.to_array( - "SS_Earnings_c", year=list(range(2021, 2024 + 1)) - ) - np.testing.assert_equal(act_before_2025, exp_before_2025) +def test_cpi_offset_does_not_affect_wage_indexed_params(): + """ + Test adjusting parameter_indexing_CPI_offset does not affect unknown + values of wage indexed parameters like SS_Earnings_c. + """ + base_reform = { + "parameter_indexing_CPI_offset": {2021: -0.001}, + "SS_Earnings_c": {2024: 300000}, + } + pol0 = Policy() + pol0.implement_reform(base_reform) + pol1 = Policy() + pol1.implement_reform(base_reform) + pol1.implement_reform(dict(base_reform, SS_Earnings_c={2025: 500000})) + + exp_before_2025 = pol0.to_array( + "SS_Earnings_c", year=list(range(2021, 2024 + 1)) + ) + act_before_2025 = pol1.to_array( + "SS_Earnings_c", year=list(range(2021, 2024 + 1)) + ) + np.testing.assert_equal(act_before_2025, exp_before_2025) def test_two_sets_of_tax_brackets(): diff --git a/taxcalc/tests/test_reforms.py b/taxcalc/tests/test_reforms.py index 5f63f7f44..d34c7ace6 100644 --- a/taxcalc/tests/test_reforms.py +++ b/taxcalc/tests/test_reforms.py @@ -97,41 +97,42 @@ def test_round_trip_reforms(fyear, tests_path): rtr_pol = Policy() # Revert to 2017 law reform_file = os.path.join(tests_path, '..', 'reforms', '2017_law.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings assert not rtr_pol.errors # Layer on TCJA reform_file = os.path.join(tests_path, '..', 'reforms', 'TCJA.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings assert not rtr_pol.errors # Layer on the CARES Act reform_file = os.path.join(tests_path, '..', 'reforms', 'CARES.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) # Layer on the Consolidated Appropriations Act of 2021 - reform_file = os.path.join(tests_path, '..', 'reforms', - 'ConsolidatedAppropriationsAct2021.json') - with open(reform_file, 'r') as rfile: + reform_file = os.path.join( + tests_path, '..', 'reforms', 'ConsolidatedAppropriationsAct2021.json' + ) + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings assert not rtr_pol.errors # Layer on ARPA reform_file = os.path.join(tests_path, '..', 'reforms', 'ARPA.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings assert not rtr_pol.errors - # Layer on 2022 rounding from IRS - reform_file = os.path.join(tests_path, '..', 'reforms', 'rounding2022.json') - with open(reform_file, 'r') as rfile: + # Layer on rounding from IRS through Policy.LAST_KNOWN_YEAR + reform_file = os.path.join(tests_path, '..', 'reforms', 'rounding.json') + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings @@ -142,9 +143,9 @@ def test_round_trip_reforms(fyear, tests_path): assert clp_mdata.keys() == rtr_mdata.keys() fail_dump = False if fail_dump: - rtr_fails = open('fails_rtr', 'w') - clp_fails = open('fails_clp', 'w') - fail_params = list() + rtr_fails = open('fails_rtr', 'w', encoding='utf-8') + clp_fails = open('fails_clp', 'w', encoding='utf-8') + fail_params = [] msg = '\nRound-trip-reform and current-law-policy param values differ for:' for pname in clp_mdata.keys(): rtr_val = rtr_mdata[pname] @@ -364,7 +365,7 @@ def test_ext_reform(tests_path): end.set_year(2026) ext = Policy() reform_file = os.path.join(tests_path, '..', 'reforms', 'ext.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() ext.implement_reform(Policy.read_json_reform(rtext)) assert not ext.parameter_warnings @@ -382,4 +383,4 @@ def test_ext_reform(tests_path): iitax_ext = calc_ext.array('iitax') rdiff = iitax_ext - iitax_end weighted_sum_rdiff = (rdiff * calc_end.array('s006')).sum() * 1.0e-9 - assert np.allclose([weighted_sum_rdiff], [-224.45], rtol=0.0, atol=0.01) + assert np.allclose([weighted_sum_rdiff], [-230.805], rtol=0.0, atol=0.01) diff --git a/taxcalc/tests/test_tmdcsv.py b/taxcalc/tests/test_tmdcsv.py deleted file mode 100644 index 6eb350f5c..000000000 --- a/taxcalc/tests/test_tmdcsv.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Tests of Tax-Calculator using tmd.csv input. - -Note that the tmd.csv file that is required to run this program has -been constructed in the PSLmodels tax-microdata repository using the -2015 IRS SOI PUF file and recent Census CPS data. If you have -acquired from IRS the 2015 SOI PUF file and want to execute this program, -contact the Tax-Calculator development team to discuss your options. - -Read Tax-Calculator/TESTING.md for details. -""" -# CODING-STYLE CHECKS: -# pycodestyle test_tmdcsv.py -# pylint --disable=locally-disabled test_tmdcsv.py - -import pytest -# pylint: disable=import-error -from taxcalc import Policy, Records, Calculator - - -@pytest.mark.requires_tmdcsv -def test_tmd_input(tmd_fullsample): - """ - Test Tax-Calculator using full-sample tmd.csv file. - """ - taxyear = 2022 - # create a Policy object with current-law policy parameters - pol = Policy() - # create a Records object containing all tmd.csv input records - recs = Records.tmd_constructor(data=tmd_fullsample) - # create a Calculator object using current-law policy and tmd records - calc = Calculator(policy=pol, records=recs) - calc.advance_to_year(taxyear) - calc.calc_all() - assert calc.data_year == Records.TMDCSV_YEAR - assert calc.current_year == taxyear - inctax = calc.weighted_total('iitax') - assert inctax > 0 diff --git a/taxcalc/tmd_growfactors.csv b/taxcalc/tmd_growfactors.csv deleted file mode 100644 index bea7ae2f0..000000000 --- a/taxcalc/tmd_growfactors.csv +++ /dev/null @@ -1,55 +0,0 @@ -YEAR,ATXPY,ASCHF,ABOOK,ACPIU,ACPIM,AWAGE,ASCHCI,ASCHCL,ASCHEI,ASCHEL,AINTS,ADIVS,ACGNS,ASOCSEC,AUCOMP,AIPD,ABENOTHER,ABENMCARE,ABENMCAID,ABENSSI,ABENSNAP,ABENWIC,ABENHOUSING,ABENTANF,ABENVET -2021,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2022,1.014347,1.742914,1.047552,1.072290,1.040311,1.175282,1.022527,1.022546,1.047553,1.047566,1.049118,1.003358,0.592565,0.855490,0.152665,1.022138,1.030159,1.048769,1.047573,0.999851,1.000000,1.002545,1.034942,1.000000,1.000000 -2023,1.050108,0.653145,1.091056,1.054020,1.004761,1.050035,1.013156,1.013121,1.091037,1.091047,1.026196,1.126711,1.052500,1.085497,0.748857,1.058072,1.030193,1.050822,1.048715,1.000448,1.000000,1.003807,1.034968,1.000000,1.000000 -2024,1.046242,0.895528,1.007166,1.025500,1.014070,1.040377,1.039700,1.039630,1.007187,1.007157,1.156028,1.023049,0.932271,1.052921,1.337549,1.054081,1.030334,1.048426,1.051767,0.997760,1.000000,1.002528,1.034951,1.000000,1.000000 -2025,1.040442,0.963117,1.020457,1.021980,0.958663,1.038977,1.037682,1.037745,1.020415,1.020444,1.091746,1.025380,0.977470,1.031721,1.154874,1.047914,1.030635,1.046248,1.052213,1.002245,1.000000,1.003783,1.034897,1.000000,1.000000 -2026,1.039294,0.987094,1.014705,1.020740,1.014023,1.035978,1.037783,1.037762,1.014711,1.014716,1.098184,1.019802,0.970235,1.030992,1.035291,1.046856,1.030633,1.072236,1.000000,0.999552,1.000000,1.002513,1.034808,1.000000,1.000000 -2027,1.037119,0.998822,1.017535,1.019460,1.013312,1.033569,1.034140,1.034138,1.017568,1.017583,1.066606,1.013266,0.993714,1.031791,1.045541,1.044372,1.030788,1.000000,1.000000,1.000000,1.000000,1.002506,1.034863,1.000000,1.000000 -2028,1.036799,1.006582,1.023966,1.019420,1.013356,1.033042,1.031594,1.031580,1.023985,1.023930,1.050716,1.021542,1.009158,1.033440,1.043558,1.043967,1.030942,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2029,1.035913,1.010333,1.028149,1.019660,1.013612,1.033365,1.030869,1.030888,1.028085,1.028143,1.030130,1.032091,1.018962,1.033664,1.045739,1.042825,1.031131,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2030,1.036423,1.010180,1.024121,1.019770,1.013855,1.033210,1.030563,1.030595,1.024170,1.024128,1.036979,1.032934,1.024538,1.034401,1.043738,1.043174,1.031330,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2031,1.036362,1.010259,1.024733,1.019910,1.014016,1.032812,1.031233,1.031240,1.024699,1.024734,1.039197,1.032793,1.027842,1.036645,1.038241,1.042951,1.031510,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2032,1.036409,1.009979,1.028000,1.019990,1.014306,1.032126,1.032334,1.032295,1.028004,1.027983,1.040140,1.032610,1.029719,1.036435,1.031319,1.042807,1.031644,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2033,1.035793,1.008195,1.028130,1.020020,1.014309,1.031481,1.033961,1.033991,1.028128,1.028110,1.031669,1.032460,1.030798,1.037554,1.028443,1.042009,1.031857,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2034,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2035,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2036,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2037,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2038,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2039,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2040,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2041,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2042,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2043,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2044,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2045,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2046,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2047,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2048,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2049,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2050,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2051,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2052,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2053,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2054,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2055,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2056,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2057,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2058,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2059,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2060,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2061,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2062,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2063,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2064,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2065,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2066,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2067,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2068,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2069,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2070,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2071,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2072,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2073,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 -2074,1.035385,1.008203,1.029710,1.020000,1.014443,1.030912,1.033294,1.033253,1.029705,1.029722,1.027096,1.032231,1.031308,1.037480,1.029528,1.041408,1.032059,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000,1.000000 diff --git a/taxcalc/tmd_weights.csv.gz b/taxcalc/tmd_weights.csv.gz deleted file mode 100644 index e92f8b47f..000000000 Binary files a/taxcalc/tmd_weights.csv.gz and /dev/null differ diff --git a/update_pcl.py b/update_pcl.py new file mode 100644 index 000000000..da533fdc9 --- /dev/null +++ b/update_pcl.py @@ -0,0 +1,469 @@ +""" +This script uses known values of inflation-indexed policy parameters after +2022 to write an updated version of the taxcalc/policy_current_law.json file. + +USAGE: (taxcalc-dev) T-C% python update_pcl.py +THEN CHECK: % diff pcl.json taxcalc/policy_current_law.json +IF DIFFS OK: % mv pcl.json taxcalc/policy_current_law.json + +WHEN TO USE: use this script to update taxcalc/policy_current_law.json +whenever post-2016 inflation rates in the growfactors.csv files are changed. +""" + +import os +import sys +import json + + +LIST_MARS_ZERO = [ + {'year': 2023, 'MARS': 'single', 'value': 0.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 0.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 0.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 0.0}, + {'year': 2023, 'MARS': 'widow', 'value': 0.0}, + + {'year': 2024, 'MARS': 'single', 'value': 0.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 0.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 0.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 0.0}, + {'year': 2024, 'MARS': 'widow', 'value': 0.0}, +] +LIST_MARS_INF = [ + {'year': 2023, 'MARS': 'single', 'value': 9e99}, + {'year': 2023, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2023, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2023, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2023, 'MARS': 'widow', 'value': 9e99}, + + {'year': 2024, 'MARS': 'single', 'value': 9e99}, + {'year': 2024, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2024, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2024, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2024, 'MARS': 'widow', 'value': 9e99}, +] +LIST_SCALAR_ZERO = [ + {'year': 2023, 'value': 0.0}, + + {'year': 2024, 'value': 0.0}, +] +NEW_KNOWN_ITEMS = { + # PAYROLL TAX PARAMETER SOURCES: + # - SSA Office of the Chief Actuary: Contribution and Benefit Base + # https://www.ssa.gov/OACT/COLA/cbb.html + 'SS_Earnings_c': [ + {'year': 2023, 'value': 160200.0}, + + {'year': 2024, 'value': 168600.0}, + ], + # INCOME TAX PARAMETER SOURCES: + # - IRS Rev. Proc. 2022-38 containing 2023 policy parameter values is at: + # https://www.irs.gov/pub/irs-drop/rp-22-38.pdf + # - IRS Rev. Proc. 2023-34 containing 2024 policy parameter values is at: + # https://www.irs.gov/pub/irs-drop/rp-23-34.pdf + 'II_brk1': [ + {'year': 2023, 'MARS': 'single', 'value': 11000.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 22000.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 11000.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 15700.0}, + {'year': 2023, 'MARS': 'widow', 'value': 22000.0}, + + {'year': 2024, 'MARS': 'single', 'value': 11600.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 23200.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 11600.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 16550.0}, + {'year': 2024, 'MARS': 'widow', 'value': 23200.0}, + ], + 'II_brk2': [ + {'year': 2023, 'MARS': 'single', 'value': 44725.}, + {'year': 2023, 'MARS': 'mjoint', 'value': 89450.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 44725.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 59850.0}, + {'year': 2023, 'MARS': 'widow', 'value': 89450.0}, + + {'year': 2024, 'MARS': 'single', 'value': 47150.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 94300.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 47150.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 63100.0}, + {'year': 2024, 'MARS': 'widow', 'value': 94300.0}, + ], + 'II_brk3': [ + {'year': 2023, 'MARS': 'single', 'value': 95375.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 190750.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 95375.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 95350.0}, + {'year': 2023, 'MARS': 'widow', 'value': 190750.0}, + + {'year': 2024, 'MARS': 'single', 'value': 100525.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 201050.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 100525.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 100500.0}, + {'year': 2024, 'MARS': 'widow', 'value': 201050.0}, + ], + 'II_brk4': [ + {'year': 2023, 'MARS': 'single', 'value': 182100.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 364200.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 182100.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 182100.0}, + {'year': 2023, 'MARS': 'widow', 'value': 364200.0}, + + {'year': 2024, 'MARS': 'single', 'value': 191950.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 383900.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 191950.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 191950.0}, + {'year': 2024, 'MARS': 'widow', 'value': 383900.0}, + ], + 'II_brk5': [ + {'year': 2023, 'MARS': 'single', 'value': 231250.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 462500.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 231250.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 231250.0}, + {'year': 2023, 'MARS': 'widow', 'value': 462500.0}, + + {'year': 2024, 'MARS': 'single', 'value': 243725.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 487450.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 243725.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 243700.0}, + {'year': 2024, 'MARS': 'widow', 'value': 487450.0}, + ], + 'II_brk6': [ + {'year': 2023, 'MARS': 'single', 'value': 578125.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 693750.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 578125.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 578100.0}, + {'year': 2023, 'MARS': 'widow', 'value': 693750.0}, + + {'year': 2024, 'MARS': 'single', 'value': 609350.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 731200.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 365600.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 609350.0}, + {'year': 2024, 'MARS': 'widow', 'value': 731200.0}, + ], + 'II_brk7': [ + {'year': 2023, 'MARS': 'single', 'value': 9e99}, + {'year': 2023, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2023, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2023, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2023, 'MARS': 'widow', 'value': 9e99}, + + {'year': 2024, 'MARS': 'single', 'value': 9e99}, + {'year': 2024, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2024, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2024, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2024, 'MARS': 'widow', 'value': 9e99}, + ], + 'CG_brk1': [ + {'year': 2023, 'MARS': 'single', 'value': 44625.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 89250.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 44625.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 59750.0}, + {'year': 2023, 'MARS': 'widow', 'value': 89250.0}, + + {'year': 2024, 'MARS': 'single', 'value': 47025.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 94050.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 47025.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 63000.0}, + {'year': 2024, 'MARS': 'widow', 'value': 94050.0}, + ], + 'CG_brk2': [ + {'year': 2023, 'MARS': 'single', 'value': 492300.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 553850.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 276900.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 523050.0}, + {'year': 2023, 'MARS': 'widow', 'value': 553850.0}, + + {'year': 2024, 'MARS': 'single', 'value': 518900.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 583750.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 291850.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 551350.0}, + {'year': 2024, 'MARS': 'widow', 'value': 583750.0}, + ], + 'CG_brk3': [ + {'year': 2023, 'MARS': 'single', 'value': 9e99}, + {'year': 2023, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2023, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2023, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2023, 'MARS': 'widow', 'value': 9e99}, + + {'year': 2024, 'MARS': 'single', 'value': 9e99}, + {'year': 2024, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2024, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2024, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2024, 'MARS': 'widow', 'value': 9e99}, + ], + 'EITC_c': [ + {'year': 2023, 'EIC': '0kids', 'value': 600.0}, + {'year': 2023, 'EIC': '1kid', 'value': 3995.0}, + {'year': 2023, 'EIC': '2kids', 'value': 6604.0}, + {'year': 2023, 'EIC': '3+kids', 'value': 7430.0}, + + {'year': 2024, 'EIC': '0kids', 'value': 632.0}, + {'year': 2024, 'EIC': '1kid', 'value': 4213.0}, + {'year': 2024, 'EIC': '2kids', 'value': 6960.0}, + {'year': 2024, 'EIC': '3+kids', 'value': 7830.0}, + ], + 'EITC_ps': [ + {'year': 2023, 'EIC': '0kids', 'value': 9800.0}, + {'year': 2023, 'EIC': '1kid', 'value': 21560.0}, + {'year': 2023, 'EIC': '2kids', 'value': 21560.0}, + {'year': 2023, 'EIC': '3+kids', 'value': 21560.0}, + + {'year': 2024, 'EIC': '0kids', 'value': 10330.0}, + {'year': 2024, 'EIC': '1kid', 'value': 22720.0}, + {'year': 2024, 'EIC': '2kids', 'value': 22720.0}, + {'year': 2024, 'EIC': '3+kids', 'value': 22720.0}, + ], + 'EITC_ps_MarriedJ': [ + {'year': 2023, 'EIC': '0kids', 'value': 6570.0}, + {'year': 2023, 'EIC': '1kid', 'value': 6560.0}, + {'year': 2023, 'EIC': '2kids', 'value': 6560.0}, + {'year': 2023, 'EIC': '3+kids', 'value': 6560.0}, + + {'year': 2024, 'EIC': '0kids', 'value': 6920.0}, + {'year': 2024, 'EIC': '1kid', 'value': 6920.0}, + {'year': 2024, 'EIC': '2kids', 'value': 6920.0}, + {'year': 2024, 'EIC': '3+kids', 'value': 6920.0}, + ], + 'EITC_InvestIncome_c': [ + {'year': 2023, 'value': 11000.0}, + + {'year': 2024, 'value': 11600.0}, + ], + 'AMT_brk1': [ + {'year': 2023, 'value': 220700.0}, + + {'year': 2024, 'value': 232600.0}, + ], + 'AMT_em': [ + {'year': 2023, 'MARS': 'single', 'value': 81300.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 126500.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 63250.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 81300.0}, + {'year': 2023, 'MARS': 'widow', 'value': 126500.0}, + + {'year': 2024, 'MARS': 'single', 'value': 85700.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 133300.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 66650.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 85700.0}, + {'year': 2024, 'MARS': 'widow', 'value': 133300.0}, + ], + 'AMT_em_ps': [ + {'year': 2023, 'MARS': 'single', 'value': 578150.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 1156300.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 578150.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 578150.0}, + {'year': 2023, 'MARS': 'widow', 'value': 1156300.0}, + + {'year': 2024, 'MARS': 'single', 'value': 609350.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 1218700.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 609350.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 609350.0}, + {'year': 2024, 'MARS': 'widow', 'value': 1218700.0}, + ], + 'AMT_em_pe': [ + {"year": 2023, "value": 831150.0}, + + {"year": 2024, "value": 875950.0}, + ], + 'AMT_child_em': [ + {'year': 2023, 'value': 8800.0}, + + {'year': 2024, 'value': 9250.0}, + ], + 'STD': [ + {'year': 2023, 'MARS': 'single', 'value': 13850.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 27700.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 13850.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 20800.0}, + {'year': 2023, 'MARS': 'widow', 'value': 27700.0}, + + {'year': 2024, 'MARS': 'single', 'value': 14600.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 29200.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 14600.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 21900.0}, + {'year': 2024, 'MARS': 'widow', 'value': 29200.0}, + ], + 'STD_Dep': [ + {'year': 2023, 'value': 1250.0}, + + {'year': 2024, 'value': 1300.0}, + ], + 'STD_Aged': [ + {'year': 2023, 'MARS': 'single', 'value': 1800.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 1500.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 1500.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 1800.0}, + {'year': 2023, 'MARS': 'widow', 'value': 1800.0}, + + {'year': 2024, 'MARS': 'single', 'value': 1950.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 1550.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 1550.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 1950.0}, + {'year': 2024, 'MARS': 'widow', 'value': 1950.0}, + ], + 'PT_qbid_taxinc_thd': [ + {'year': 2023, 'MARS': 'single', 'value': 182100.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 364200.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 182100.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 182100.0}, + {'year': 2023, 'MARS': 'widow', 'value': 182100.0}, + + {'year': 2024, 'MARS': 'single', 'value': 191950.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 383900.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 191950.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 191950.0}, + {'year': 2024, 'MARS': 'widow', 'value': 191950.0}, + ], + 'ALD_BusinessLosses_c': [ + {'year': 2023, 'MARS': 'single', 'value': 289000.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 578000.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 289000.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 289000.0}, + {'year': 2023, 'MARS': 'widow', 'value': 578000.0}, + + {'year': 2024, 'MARS': 'single', 'value': 305000.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 610000.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 305000.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 305000.0}, + {'year': 2024, 'MARS': 'widow', 'value': 610000.0}, + ], + 'FST_AGI_thd_lo': [ # not part of current-law policy, but needs to be here + {'year': 2023, 'MARS': 'single', 'value': 1000000.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 1000000.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 500000.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 1000000.0}, + {'year': 2023, 'MARS': 'widow', 'value': 1000000.0}, + + {'year': 2024, 'MARS': 'single', 'value': 1000000.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 1000000.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 500000.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 1000000.0}, + {'year': 2024, 'MARS': 'widow', 'value': 1000000.0}, + + # each year's values are the same as for the prior year + ], + 'FST_AGI_thd_hi': [ # not part of current-law policy, but needs to be here + {'year': 2023, 'MARS': 'single', 'value': 2000000.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 2000000.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 1000000.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 2000000.0}, + {'year': 2023, 'MARS': 'widow', 'value': 2000000.0}, + + {'year': 2024, 'MARS': 'single', 'value': 2000000.0}, + {'year': 2024, 'MARS': 'mjoint', 'value': 2000000.0}, + {'year': 2024, 'MARS': 'mseparate', 'value': 1000000.0}, + {'year': 2024, 'MARS': 'headhh', 'value': 2000000.0}, + {'year': 2024, 'MARS': 'widow', 'value': 2000000.0}, + + # each year's values are the same as for the prior year + ], + # ITEMS NOT PART OF CURRENT-LAW POLICY IN 2022-2025 PERIOD: + 'ALD_Dependents_Child_c': LIST_SCALAR_ZERO, + 'ALD_Dependents_Elder_c': LIST_SCALAR_ZERO, + 'II_em': LIST_SCALAR_ZERO, + 'II_em_ps': LIST_MARS_INF, + 'II_credit': LIST_MARS_ZERO, + 'II_credit_ps': LIST_MARS_ZERO, + 'II_credit_nr': LIST_MARS_ZERO, + 'II_credit_nr_ps': LIST_MARS_ZERO, + 'ID_Medical_c': LIST_MARS_INF, + 'ID_StateLocalTax_c': LIST_MARS_INF, + 'ID_RealEstate_c': LIST_MARS_INF, + 'ID_InterestPaid_c': LIST_MARS_INF, + 'ID_Charity_c': LIST_MARS_INF, + 'ID_Casualty_c': LIST_MARS_INF, + 'ID_Miscellaneous_c': LIST_MARS_INF, + 'ID_ps': LIST_MARS_INF, + 'ID_BenefitSurtax_em': LIST_MARS_ZERO, + 'ID_c': LIST_MARS_INF, + 'CG_ec': LIST_SCALAR_ZERO, + 'PT_qbid_ps': LIST_MARS_INF, + 'RPTC_c': LIST_SCALAR_ZERO, + 'CTC_new_ps': LIST_MARS_ZERO, + 'AGI_surtax_thd': LIST_MARS_INF, + 'UBI_u18': LIST_SCALAR_ZERO, + 'UBI_1820': LIST_SCALAR_ZERO, + 'UBI_21': LIST_SCALAR_ZERO, +} +for num in range(1, 7 + 1): + NEW_KNOWN_ITEMS[f'PT_brk{num}'] = NEW_KNOWN_ITEMS[f'II_brk{num}'] +for num in range(1, 3 + 1): + NEW_KNOWN_ITEMS[f'AMT_CG_brk{num}'] = NEW_KNOWN_ITEMS[f'CG_brk{num}'] + + +CHECK_FOR_MISSING = False + + +def check_for_missing(pdict): + """ + Prints to sdtout indexed parameters with missing values in or before 2022. + """ + first_year = 2013 + last_known_year = 2022 + for pname, pinfo in pdict.items(): + if pname == 'schema': + continue + if not pinfo['indexed']: + continue + years_used = [] + plist = pinfo['value'] + for item in plist: + year = item['year'] + if year <= last_known_year: + if year not in years_used: + years_used.append(year) + for year in range(first_year, last_known_year + 1): + if year not in years_used: + print(f'MISSING INDEXED VALUE FOR {pname} IN {year}') + + +def main(): + """ + High-level script logic. + """ + # read existing policy_current_law.json into a Python dictionary + fname = os.path.join('taxcalc', 'policy_current_law.json') + with open(fname, 'r', encoding='utf-8') as jfile: + pdict = json.load(jfile) + + # optionally check for missing indexed parameters in years <= 2022 + if CHECK_FOR_MISSING: + check_for_missing(pdict) + return 1 + + # add parameter values to dictionary + for pname, pinfo in pdict.items(): + if pname == 'schema': + continue + if not pinfo['indexed']: + continue + if pname not in NEW_KNOWN_ITEMS: + print(f'NO NEW_KNOWN_ITEMS FOR {pname}') + continue + plist = pdict[pname]['value'] + # ... see if adding values before existing plist items for 2026 + bindex = None + for itm in plist: + if itm['year'] == 2026: + bindex = plist.index(itm) + break + # ... add new items to plist for this pname + for item in NEW_KNOWN_ITEMS[pname]: + if item in plist: + continue + if bindex: + plist.insert(bindex, item) + bindex += 1 + else: + plist.append(item) + + # write updated dictionary to pcl.json file + with open('pcl.json', 'w', encoding='utf-8') as jfile: + jfile.write(json.dumps(pdict, indent=4) + '\n') + + # return no-error exit code + return 0 +# end main function code + + +if __name__ == '__main__': + sys.exit(main())