-
-
Notifications
You must be signed in to change notification settings - Fork 160
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2734 from martinholmer/add-tcja-docs
- Loading branch information
Showing
7 changed files
with
373 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,3 +22,4 @@ comment: | |
ignore: | ||
- "setup.py" | ||
- "ppp.py" | ||
- "extend_tcja.py" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
TCJA after 2025 | ||
=============== | ||
|
||
Many provisions of the TCJA are temporary and are scheduled to end | ||
after 2025 under current-law policy. Tax policy parameters that are | ||
associated with expiring provisions and that are not inflation indexed | ||
will revert to their 2017 values in 2026. Tax policy parameters that | ||
are associated with expiring provisions and that are inflation indexed | ||
will revert to their 2017 values indexed to 2026 using a chained CPI-U | ||
inflation factor. For a list of the ending TCJA provisions, see this | ||
Congressional Research Service document: [Reference Table: Expiring | ||
Provisions in the "Tax Cuts and Jobs Act" (TCJA, P.L. 115-97)]( | ||
https://crsreports.congress.gov/product/pdf/R/R47846), which is dated | ||
November 21, 2023. | ||
|
||
This document describes how to use the PSLmodels Tax-Calculator | ||
command-line interface | ||
[tc](https://taxcalc.pslmodels.org/guide/cli.html) with any compatible | ||
input dataset to analyze the post-2025 effects of alternatives to | ||
current-law policy (which calls for all temporary TCJA provisions to | ||
expire). Compatible input datasets include: | ||
|
||
* the older `cps.csv` file included in the Tax-Calculator package | ||
|
||
* the older `puf.csv` file generated in the PSLmodels | ||
[taxdata](https://github.com/PSLmodels/taxdata) repository and | ||
available only to those with access to the 2011 IRS/SOI PUF | ||
|
||
* several newer CSV-formatted input files created in the PSLmodels | ||
[tax-microdata](https://github.com/PSLmodels/tax-microdata-benchmarking) | ||
repository that are based on the 2015 IRS/SOI PUF and on recent CPS | ||
data, and are available only to those with access to the 2015 | ||
IRS/SOI PUF | ||
|
||
Before reading the rest of this document, be sure you understand how | ||
to use the Tax-Calculator command-line tool | ||
[tc](https://taxcalc.pslmodels.org/guide/cli.html), particularly the | ||
`--baseline` and `--reform` command-line options. (For complete and | ||
up-to-date `tc` documentation, enter `tc --help` at the command | ||
prompt.) Omitting the `--baseline` option means the baseline policy | ||
is current-law policy. Omitting the `--reform` option means the | ||
reform policy is current-law policy. The `--tables` option produces | ||
tables comparing taxes under the baseline policy to taxes under the | ||
reform policy by income decile and in aggregate. | ||
|
||
The `--baseline` option is not commonly used, but it can be very | ||
helpful in analyzing reforms that take effect beginning in 2026. Such | ||
a reform could be analyzed relative to current-law policy (that is, | ||
with temporary TCJA provisions expiring after 2025) by omitting the | ||
`--baseline` option. But if such a reform were to be analyzed | ||
relative to extending all the temporary TCJA provisions beyond 2025, | ||
then the `--baseline ext.json` option would need to be used. The | ||
[`ext.json`](../../taxcalc/reforms/ext.json) file contains the 2026 | ||
tax policy reform provisions that would extend TCJA's temporary | ||
provisions beyond 2025. Before using this `ext.json` reform file, be | ||
sure to read how it is generated at the end of this document. | ||
|
||
Here are some concrete examples of using the `tc` tool to analyze a | ||
reform of interest to you that begins in 2026. The examples assume | ||
you have named your reform file `x.json` and that you are using one | ||
of the compatible input datasets describe above. The examples will | ||
call the input dataset `z.csv`. | ||
|
||
To analyze your reform relative to current-law policy (which means | ||
temporary TCJA provisions have expired beginning in 2026), you would | ||
execute this command: | ||
|
||
``` | ||
tc z.csv 2026 --exact --tables --reform x.json | ||
``` | ||
|
||
The tables would be in the `z-26-#-x-#-tab.text` output file generated | ||
by this `tc` run. If you want to do custom tabulations of the micro | ||
output data, use the `--dump`, `--dvars`, and `--sqldb` options as | ||
explained by the `tc --help` documentation. | ||
|
||
To analyze your reform relative to a reform that extends all TCJA | ||
temporary provisions beyond 2025, you would execute this command: | ||
|
||
``` | ||
tc z.csv 2026 --exact --tables --baseline ext.json --reform x.json | ||
``` | ||
|
||
The tables would be in the `z-26-ext-x-#-tab.text` output file | ||
generated by this `tc` run. | ||
|
||
Also, remember that you can simulate a _compound reform_ using the | ||
following syntax: | ||
|
||
``` | ||
tc z.csv 2026 --exact --tables --baseline ext.json --reform x.json+y.json | ||
``` | ||
|
||
where `y.json` contains a reform with additional provisions not | ||
included in your `x.json` reform file. The resulting table output | ||
would be in a file named `z-26-ext-x+y-#-tab.text`. | ||
|
||
And finally, you might consider creating a reform file called | ||
`end.json` that contains just the two characters `{}`. This is a null | ||
reform, which is equivalent to current-law policy, that could be used | ||
as follows: | ||
|
||
``` | ||
tc z.csv 2026 --exact --tables --baseline end.json --reform x.json | ||
``` | ||
|
||
The resulting table output would be named `z-26-end-x-#-tab.text` and | ||
have the same tabular output as the `z-26-#-x-#-tab.text` file. Some | ||
people may prefer `end` to `#` as a way of naming current-law policy | ||
in the context of discussing TCJA-related reforms. | ||
|
||
|
||
**How is the `ext.json` file generated?** | ||
|
||
The short answer is by using the | ||
[`extend_tcja.py`](../../extend_tcja.py) script. | ||
|
||
Reading the `extend_tcja.py` script will provide details on how the | ||
values in the `ext.json` file are generated. | ||
|
||
It is important to bear in mind that the `extend_tcja.py` script will | ||
generate a different `ext.json` file whenever the CBO economic | ||
projection (incorporated in the Tax-Calculator `growfactors.csv` file) | ||
change or whenever new historical values of policy parameters are | ||
added to the `policy_current_law.json` file thereby changing the | ||
`Policy.LAST_KNOWN_YEAR`. | ||
|
||
The 3.5.3 version of Tax-Calculator incorporates the February 2024 CBO | ||
economic projection and contains historical tax policy parameter values | ||
through 2022. Future versions of Tax-Calculator that use historical | ||
policy parameter values for 2023 and 2024 or use the February 2025 CBO | ||
economic projection will cause the `extend_tcja.py` script to generate | ||
somewhat different 2026 parameter values in the `ext.json` file. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
""" | ||
This script generates a JSON reform file, which could be called | ||
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 | ||
IMPORTANT NOTE: be sure to remove the trailing comma after the last item | ||
in the reform JSON object generated by this script. | ||
""" | ||
|
||
import sys | ||
import numpy | ||
import taxcalc | ||
|
||
TCJA_CATEGORY = None # set to None to generate all TCJA temporary provisions | ||
TCJA_PARAMETERS = { | ||
# category 1 ... | ||
"II_rt1": {"indexed": False, "category": 1}, | ||
"II_brk1": {"indexed": True, "category": 1}, | ||
"PT_rt1": {"indexed": False, "category": 1}, | ||
"PT_brk1": {"indexed": True, "category": 1}, | ||
"II_rt2": {"indexed": False, "category": 1}, | ||
"II_brk2": {"indexed": True, "category": 1}, | ||
"PT_rt2": {"indexed": False, "category": 1}, | ||
"PT_brk2": {"indexed": True, "category": 1}, | ||
"II_rt3": {"indexed": False, "category": 1}, | ||
"II_brk3": {"indexed": True, "category": 1}, | ||
"PT_rt3": {"indexed": False, "category": 1}, | ||
"PT_brk3": {"indexed": True, "category": 1}, | ||
"II_rt4": {"indexed": False, "category": 1}, | ||
"II_brk4": {"indexed": True, "category": 1}, | ||
"PT_rt4": {"indexed": False, "category": 1}, | ||
"PT_brk4": {"indexed": True, "category": 1}, | ||
"II_rt5": {"indexed": False, "category": 1}, | ||
"II_brk5": {"indexed": True, "category": 1}, | ||
"PT_rt5": {"indexed": False, "category": 1}, | ||
"PT_brk5": {"indexed": True, "category": 1}, | ||
"II_rt6": {"indexed": False, "category": 1}, | ||
"II_brk6": {"indexed": True, "category": 1}, | ||
"PT_rt6": {"indexed": False, "category": 1}, | ||
"PT_brk6": {"indexed": True, "category": 1}, | ||
"II_rt7": {"indexed": False, "category": 1}, | ||
"II_brk7": {"indexed": True, "category": 1}, | ||
"PT_rt7": {"indexed": False, "category": 1}, | ||
"PT_brk7": {"indexed": True, "category": 1}, | ||
# category 2 ... | ||
"CTC_c": {"indexed": False, "category": 2}, | ||
"ACTC_c": {"indexed": False, "category": 2}, | ||
"ODC_c": {"indexed": False, "category": 2}, | ||
"CTC_ps": {"indexed": False, "category": 2}, | ||
"ACTC_Income_thd": {"indexed": False, "category": 2}, | ||
# category 3 ... | ||
"AMT_em": {"indexed": True, "category": 3}, | ||
"AMT_em_ps": {"indexed": True, "category": 3}, | ||
"AMT_em_pe": {"indexed": True, "category": 3}, | ||
# category 4 ... | ||
"STD": {"indexed": True, "category": 4}, | ||
# category 5 ... | ||
"ID_AllTaxes_c": {"indexed": False, "category": 5}, | ||
"ID_Charity_crt_all": {"indexed": False, "category": 5}, | ||
"ID_Casualty_hc": {"indexed": False, "category": 5}, | ||
"ID_Miscellaneous_hc": {"indexed": False, "category": 5}, | ||
"ID_ps": {"indexed": True, "category": 5}, | ||
"ID_prt": {"indexed": False, "category": 5}, | ||
"ID_crt": {"indexed": False, "category": 5}, | ||
# category 6 ... | ||
"II_em": {"indexed": True, "category": 6}, | ||
"II_em_ps": {"indexed": True, "category": 6}, | ||
# category 7 ... | ||
"PT_qbid_rt": {"indexed": False, "category": 7}, | ||
"PT_qbid_taxinc_thd": {"indexed": True, "category": 7}, | ||
"PT_qbid_taxinc_gap": {"indexed": False, "category": 7}, | ||
"PT_qbid_w2_wages_rt": {"indexed": False, "category": 7}, | ||
"PT_qbid_alt_w2_wages_rt": {"indexed": False, "category": 7}, | ||
"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}, | ||
} | ||
|
||
|
||
def main(): | ||
""" | ||
High-level script logic. | ||
""" | ||
# calculate 2025-to-2026 parameters indexing factor | ||
pol = taxcalc.Policy() | ||
pirates = pol.inflation_rates() | ||
ifactor = 1.0 + pirates[2025-taxcalc.Policy.JSON_START_YEAR] | ||
# specify extend-TCJA-beyond-2025 reform | ||
# ... get 2025 parameter values | ||
pol.set_year(2025) | ||
pdata = dict(pol.items()) | ||
# ... 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}') | ||
if TCJA_CATEGORY: | ||
print(f'// ONLY TCJA PROVISIONS IN CATEGORY {TCJA_CATEGORY}') | ||
print('{') | ||
# ... set 2026 nonreverted values for the parameters set to revert | ||
for pname, pinfo in TCJA_PARAMETERS.items(): | ||
if TCJA_CATEGORY and pinfo['category'] != TCJA_CATEGORY: | ||
continue # skip this parameter | ||
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'{pval.tolist()}') | ||
sys.stdout.write('},\n') | ||
else: | ||
# handle scalar parameter | ||
pval = min(9e99, pval) | ||
sys.stdout.write(f' "{pname}": ') | ||
sys.stdout.write('{"2026": ') | ||
sys.stdout.write(f'{pval*ifactor:.2f}') | ||
sys.stdout.write('},\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'{pval.tolist()}') | ||
sys.stdout.write('},\n') | ||
else: | ||
# handle scalar parameter | ||
sys.stdout.write(f' "{pname}": ') | ||
sys.stdout.write('{"2026": ') | ||
sys.stdout.write(f'{pval:.2f}') | ||
sys.stdout.write('},\n') | ||
print('}') | ||
return 0 | ||
# end main function code | ||
|
||
|
||
if __name__ == '__main__': | ||
sys.exit(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// REFORM TO EXTEND TEMPORARY TCJA PROVISIONS BEYOND 2025 | ||
// USING TAX-CALCULATOR 3.5.3 | ||
// WITH 2025-to-2026 INDEXING FACTOR = 1.022000 | ||
{ | ||
"II_rt1": {"2026": 0.10}, | ||
"II_brk1": {"2026": [12170.98, 24341.94, 12170.98, 17353.27, 24341.94]}, | ||
"PT_rt1": {"2026": 0.10}, | ||
"PT_brk1": {"2026": [12170.98, 24341.94, 12170.98, 17353.27, 24341.94]}, | ||
"II_rt2": {"2026": 0.12}, | ||
"II_brk2": {"2026": [49483.44, 98966.89, 49483.44, 66214.83, 98966.89]}, | ||
"PT_rt2": {"2026": 0.12}, | ||
"PT_brk2": {"2026": [49483.44, 98966.89, 49483.44, 66214.83, 98966.89]}, | ||
"II_rt3": {"2026": 0.22}, | ||
"II_brk3": {"2026": [105511.38, 211022.75, 105511.38, 105481.77, 211022.75]}, | ||
"PT_rt3": {"2026": 0.22}, | ||
"PT_brk3": {"2026": [105511.38, 211022.75, 105511.38, 105481.77, 211022.75]}, | ||
"II_rt4": {"2026": 0.24}, | ||
"II_brk4": {"2026": [201428.14, 402856.25, 201428.14, 201428.14, 402856.25]}, | ||
"PT_rt4": {"2026": 0.24}, | ||
"PT_brk4": {"2026": [201428.14, 402856.25, 201428.14, 201428.14, 402856.25]}, | ||
"II_rt5": {"2026": 0.32}, | ||
"II_brk5": {"2026": [255797.72, 511595.46, 255797.72, 255797.72, 511595.46]}, | ||
"PT_rt5": {"2026": 0.32}, | ||
"PT_brk5": {"2026": [255797.72, 511595.46, 255797.72, 255797.72, 511595.46]}, | ||
"II_rt6": {"2026": 0.35}, | ||
"II_brk6": {"2026": [639523.94, 767393.2, 383696.6, 639523.94, 767393.2]}, | ||
"PT_rt6": {"2026": 0.35}, | ||
"PT_brk6": {"2026": [639523.94, 767393.2, 383696.6, 639523.94, 767393.2]}, | ||
"II_rt7": {"2026": 0.37}, | ||
"II_brk7": {"2026": [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]}, | ||
"PT_rt7": {"2026": 0.37}, | ||
"PT_brk7": {"2026": [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]}, | ||
"CTC_c": {"2026": 2000.00}, | ||
"ACTC_c": {"2026": 1600.00}, | ||
"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]}, | ||
"ID_AllTaxes_c": {"2026": [10000.0, 10000.0, 5000.0, 10000.0, 10000.0]}, | ||
"ID_Charity_crt_all": {"2026": 0.60}, | ||
"ID_Casualty_hc": {"2026": 1.00}, | ||
"ID_Miscellaneous_hc": {"2026": 1.00}, | ||
"ID_ps": {"2026": [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]}, | ||
"ID_prt": {"2026": 0.00}, | ||
"ID_crt": {"2026": 1.00}, | ||
"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_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} | ||
} |
Oops, something went wrong.