Skip to content

Commit

Permalink
Add TCJA-related documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
martinholmer committed Apr 9, 2024
1 parent 8df45d4 commit 2d361d7
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ parts:
- file: recipes/recipe04_pandas
- file: recipes/recipe05
- file: recipes/recipe06
- file: usage/tcja_after_2025
- caption: About
chapters:
- file: about/history
Expand Down
59 changes: 59 additions & 0 deletions docs/usage/ext.json
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}
}
133 changes: 133 additions & 0 deletions docs/usage/tcja_after_2025.md
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`](./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.
143 changes: 143 additions & 0 deletions extend_tcja.py
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

Check warning on line 14 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L12-L14

Added lines #L12 - L14 were not covered by tests

TCJA_CATEGORY = None # set to None to generate all TCJA temporary provisions
TCJA_PARAMETERS = {

Check warning on line 17 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L16-L17

Added lines #L16 - L17 were not covered by tests
# 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():

Check warning on line 83 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L83

Added line #L83 was not covered by tests
"""
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]

Check warning on line 90 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L88-L90

Added lines #L88 - L90 were not covered by tests
# specify extend-TCJA-beyond-2025 reform
# ... get 2025 parameter values
pol.set_year(2025)
pdata = dict(pol.items())

Check warning on line 94 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L93-L94

Added lines #L93 - L94 were not covered by tests
# ... 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('{')

Check warning on line 101 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L96-L101

Added lines #L96 - L101 were not covered by tests
# ... 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):

Check warning on line 108 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L103-L108

Added lines #L103 - L108 were not covered by tests
# 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')

Check warning on line 114 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L110-L114

Added lines #L110 - L114 were not covered by tests
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')

Check warning on line 121 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L117-L121

Added lines #L117 - L121 were not covered by tests
else: # if parameter is not indexed
pval = pdata[pname][0]
if isinstance(pval, numpy.ndarray):

Check warning on line 124 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L123-L124

Added lines #L123 - L124 were not covered by tests
# 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')

Check warning on line 130 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L126-L130

Added lines #L126 - L130 were not covered by tests
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

Check warning on line 138 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L133-L138

Added lines #L133 - L138 were not covered by tests
# end main function code


if __name__ == '__main__':
sys.exit(main())

Check warning on line 143 in extend_tcja.py

View check run for this annotation

Codecov / codecov/patch

extend_tcja.py#L142-L143

Added lines #L142 - L143 were not covered by tests
7 changes: 7 additions & 0 deletions taxcalc.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: setuptools
Requires-Dist: numpy
Requires-Dist: pandas
Requires-Dist: bokeh
Requires-Dist: numba
Requires-Dist: requests
Requires-Dist: paramtools

| | |
| --- | --- |
Expand Down

0 comments on commit 2d361d7

Please sign in to comment.