taxsim-py 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- taxsim_py-0.1.0/LICENSE +21 -0
- taxsim_py-0.1.0/MANIFEST.in +2 -0
- taxsim_py-0.1.0/PKG-INFO +145 -0
- taxsim_py-0.1.0/README.md +129 -0
- taxsim_py-0.1.0/parameters/README.md +11 -0
- taxsim_py-0.1.0/parameters/national/amt.yaml +614 -0
- taxsim_py-0.1.0/parameters/national/analytic_rate.yaml +67 -0
- taxsim_py-0.1.0/parameters/national/capital_gains.yaml +477 -0
- taxsim_py-0.1.0/parameters/national/credits.yaml +378 -0
- taxsim_py-0.1.0/parameters/national/dependent_ages.yaml +9 -0
- taxsim_py-0.1.0/parameters/national/eitc.csv +469 -0
- taxsim_py-0.1.0/parameters/national/eitc_misc.yaml +74 -0
- taxsim_py-0.1.0/parameters/national/income_tax.yaml +459 -0
- taxsim_py-0.1.0/parameters/national/itemized.yaml +112 -0
- taxsim_py-0.1.0/parameters/national/law60.yaml +638 -0
- taxsim_py-0.1.0/parameters/national/niit.yaml +117 -0
- taxsim_py-0.1.0/parameters/national/payroll_tax.yaml +444 -0
- taxsim_py-0.1.0/parameters/national/personal_exemption.yaml +122 -0
- taxsim_py-0.1.0/parameters/national/pre1987.yaml +304 -0
- taxsim_py-0.1.0/parameters/national/sales_tax_deduction.yaml +636 -0
- taxsim_py-0.1.0/parameters/national/social_security.yaml +19 -0
- taxsim_py-0.1.0/parameters/national/state_adjustments.yaml +34 -0
- taxsim_py-0.1.0/parameters/national/state_cpi_extrapolation.yaml +71 -0
- taxsim_py-0.1.0/parameters/national/state_socsec.yaml +68 -0
- taxsim_py-0.1.0/parameters/states/ak/income_tax.yaml +117 -0
- taxsim_py-0.1.0/parameters/states/al/income_tax.yaml +122 -0
- taxsim_py-0.1.0/parameters/states/ar/income_tax.yaml +495 -0
- taxsim_py-0.1.0/parameters/states/ar/low_income_table.csv +168 -0
- taxsim_py-0.1.0/parameters/states/ar/low_income_table_2022plus.csv +924 -0
- taxsim_py-0.1.0/parameters/states/az/income_tax.yaml +342 -0
- taxsim_py-0.1.0/parameters/states/ca/income_tax.yaml +755 -0
- taxsim_py-0.1.0/parameters/states/co/income_tax.yaml +253 -0
- taxsim_py-0.1.0/parameters/states/ct/income_tax.yaml +525 -0
- taxsim_py-0.1.0/parameters/states/dc/income_tax.yaml +633 -0
- taxsim_py-0.1.0/parameters/states/de/income_tax.yaml +358 -0
- taxsim_py-0.1.0/parameters/states/ga/income_tax.yaml +171 -0
- taxsim_py-0.1.0/parameters/states/hi/income_tax.yaml +571 -0
- taxsim_py-0.1.0/parameters/states/ia/income_tax.yaml +434 -0
- taxsim_py-0.1.0/parameters/states/id/income_tax.yaml +404 -0
- taxsim_py-0.1.0/parameters/states/il/income_tax.yaml +105 -0
- taxsim_py-0.1.0/parameters/states/in/income_tax.yaml +233 -0
- taxsim_py-0.1.0/parameters/states/ks/income_tax.yaml +416 -0
- taxsim_py-0.1.0/parameters/states/ky/income_tax.yaml +349 -0
- taxsim_py-0.1.0/parameters/states/la/income_tax.yaml +154 -0
- taxsim_py-0.1.0/parameters/states/ma/income_tax.yaml +360 -0
- taxsim_py-0.1.0/parameters/states/md/income_tax.yaml +487 -0
- taxsim_py-0.1.0/parameters/states/me/income_tax.yaml +598 -0
- taxsim_py-0.1.0/parameters/states/mi/income_tax.yaml +385 -0
- taxsim_py-0.1.0/parameters/states/mn/income_tax.yaml +1438 -0
- taxsim_py-0.1.0/parameters/states/mo/income_tax.yaml +246 -0
- taxsim_py-0.1.0/parameters/states/ms/income_tax.yaml +138 -0
- taxsim_py-0.1.0/parameters/states/mt/income_tax.yaml +350 -0
- taxsim_py-0.1.0/parameters/states/nc/income_tax.yaml +151 -0
- taxsim_py-0.1.0/parameters/states/nd/income_tax.yaml +76 -0
- taxsim_py-0.1.0/parameters/states/ne/income_tax.yaml +460 -0
- taxsim_py-0.1.0/parameters/states/nh/income_tax.yaml +19 -0
- taxsim_py-0.1.0/parameters/states/nj/income_tax.yaml +169 -0
- taxsim_py-0.1.0/parameters/states/nm/income_tax.yaml +334 -0
- taxsim_py-0.1.0/parameters/states/ny/income_tax.yaml +579 -0
- taxsim_py-0.1.0/parameters/states/oh/income_tax.yaml +106 -0
- taxsim_py-0.1.0/parameters/states/ok/income_tax.yaml +118 -0
- taxsim_py-0.1.0/parameters/states/or/income_tax.yaml +172 -0
- taxsim_py-0.1.0/parameters/states/pa/income_tax.yaml +46 -0
- taxsim_py-0.1.0/parameters/states/ri/income_tax.yaml +158 -0
- taxsim_py-0.1.0/parameters/states/sc/income_tax.yaml +87 -0
- taxsim_py-0.1.0/parameters/states/tn/income_tax.yaml +12 -0
- taxsim_py-0.1.0/parameters/states/tx/sales_tax_deduction.yaml +120 -0
- taxsim_py-0.1.0/parameters/states/ut/income_tax.yaml +97 -0
- taxsim_py-0.1.0/parameters/states/va/income_tax.yaml +85 -0
- taxsim_py-0.1.0/parameters/states/vt/income_tax.yaml +139 -0
- taxsim_py-0.1.0/parameters/states/wa/income_tax.yaml +13 -0
- taxsim_py-0.1.0/parameters/states/wi/income_tax.yaml +250 -0
- taxsim_py-0.1.0/parameters/states/wv/income_tax.yaml +73 -0
- taxsim_py-0.1.0/pyproject.toml +50 -0
- taxsim_py-0.1.0/setup.cfg +4 -0
- taxsim_py-0.1.0/setup.py +23 -0
- taxsim_py-0.1.0/src/taxsim_py/__init__.py +6 -0
- taxsim_py-0.1.0/src/taxsim_py/api.py +505 -0
- taxsim_py-0.1.0/src/taxsim_py/behavior.py +75 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/__init__.py +0 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/federal.py +1298 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/federal_law60.py +419 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/federal_pre1987.py +611 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/payroll.py +65 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/__init__.py +101 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ak.py +68 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/al.py +252 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ar.py +461 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/az.py +423 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ca.py +656 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/co.py +445 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ct.py +562 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/dc.py +484 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/de.py +268 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ga.py +275 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/hi.py +354 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ia.py +421 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/id.py +282 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/il.py +151 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/in_.py +263 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ks.py +430 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ky.py +288 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/la.py +254 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ma.py +420 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/md.py +379 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/me.py +563 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/mi.py +192 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/mn.py +1038 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/mo.py +273 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ms.py +175 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/mt.py +301 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/nc.py +422 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/nd.py +243 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ne.py +244 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/nh.py +32 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/nj.py +282 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/nm.py +267 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/no_income_tax.py +9 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ny.py +699 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/oh.py +205 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ok.py +271 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/or_.py +333 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/pa.py +86 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ri.py +271 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/sc.py +260 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/tn.py +48 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/ut.py +208 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/va.py +284 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/vt.py +246 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/wa.py +32 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/wi.py +416 -0
- taxsim_py-0.1.0/src/taxsim_py/calculators/states/wv.py +149 -0
- taxsim_py-0.1.0/src/taxsim_py/cli.py +71 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/__init__.py +0 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/amt.py +80 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/brackets.py +65 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/capital_gains.py +27 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/credits.py +56 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/detail.py +166 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/eitc.py +86 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/federal_state.py +175 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/inputs.py +158 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/niit.py +20 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/payroll_tax.py +272 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/sales_tax.py +55 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/schema.py +74 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/social_security.py +29 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/state.py +286 -0
- taxsim_py-0.1.0/src/taxsim_py/engine/state_extrapolation.py +106 -0
- taxsim_py-0.1.0/src/taxsim_py/io/__init__.py +0 -0
- taxsim_py-0.1.0/src/taxsim_py/io/tables.py +71 -0
- taxsim_py-0.1.0/src/taxsim_py/prep/__init__.py +5 -0
- taxsim_py-0.1.0/src/taxsim_py/prep/cps_asec.py +243 -0
- taxsim_py-0.1.0/src/taxsim_py/validation/__init__.py +5 -0
- taxsim_py-0.1.0/src/taxsim_py/validation/independent.py +177 -0
- taxsim_py-0.1.0/src/taxsim_py.egg-info/PKG-INFO +145 -0
- taxsim_py-0.1.0/src/taxsim_py.egg-info/SOURCES.txt +168 -0
- taxsim_py-0.1.0/src/taxsim_py.egg-info/dependency_links.txt +1 -0
- taxsim_py-0.1.0/src/taxsim_py.egg-info/entry_points.txt +2 -0
- taxsim_py-0.1.0/src/taxsim_py.egg-info/requires.txt +5 -0
- taxsim_py-0.1.0/src/taxsim_py.egg-info/top_level.txt +1 -0
- taxsim_py-0.1.0/tests/test_api.py +258 -0
- taxsim_py-0.1.0/tests/test_benchmark_comparison.py +52 -0
- taxsim_py-0.1.0/tests/test_calculation_modes.py +509 -0
- taxsim_py-0.1.0/tests/test_cli.py +94 -0
- taxsim_py-0.1.0/tests/test_hawaii_recent.py +34 -0
- taxsim_py-0.1.0/tests/test_independent_models.py +203 -0
- taxsim_py-0.1.0/tests/test_law_based_checks.py +241 -0
- taxsim_py-0.1.0/tests/test_negative_capital_gains.py +51 -0
- taxsim_py-0.1.0/tests/test_parameter_provenance.py +54 -0
taxsim_py-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jon Rothbaum
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
taxsim_py-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: taxsim-py
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A dataframe-oriented Python implementation of NBER TAXSIM
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/jrothbaum/taxsim_py
|
|
7
|
+
Project-URL: Documentation, https://jrothbaum.github.io/taxsim_py/
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: polars>=1.28.1
|
|
12
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
13
|
+
Provides-Extra: readstat
|
|
14
|
+
Requires-Dist: polars-readstat>=0.20.2; extra == "readstat"
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
THIS IS STILL IN DEVELOPMENT AND NOT ON PYPI YET
|
|
18
|
+
|
|
19
|
+
# taxsim-py
|
|
20
|
+
|
|
21
|
+
`taxsim-py` is a dataframe-oriented Python implementation of NBER TAXSIM,
|
|
22
|
+
independent of and not affiliated with NBER. It calculates federal income tax,
|
|
23
|
+
payroll tax, and state income tax for household records, using Polars
|
|
24
|
+
`DataFrame` or `LazyFrame` inputs and clear variable names (TAXSIM's `v1`-style
|
|
25
|
+
names only on request).
|
|
26
|
+
|
|
27
|
+
**[Documentation](https://jrothbaum.github.io/taxsim_py/)** ·
|
|
28
|
+
**[Try the calculator in your browser](https://jrothbaum.github.io/taxsim_py/calculator/)**
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
Python 3.9 or newer: `pip install taxsim-py` or `uv add taxsim-py`. From a
|
|
33
|
+
checkout: `uv sync --group dev --group test`.
|
|
34
|
+
|
|
35
|
+
## Basic use
|
|
36
|
+
|
|
37
|
+
Every row needs `mstat` and `state` (TAXSIM codes, or Census FIPS with
|
|
38
|
+
`state_id_type="fips"`). Include `year` in the data or pass `year=`.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import polars as pl
|
|
42
|
+
|
|
43
|
+
from taxsim_py import calculate_taxes
|
|
44
|
+
|
|
45
|
+
households = pl.DataFrame(
|
|
46
|
+
{
|
|
47
|
+
"year": [2021, 2021],
|
|
48
|
+
"state": [6, 36], # California, New York
|
|
49
|
+
"mstat": [1, 2], # single, married filing jointly
|
|
50
|
+
"page": [45, 50],
|
|
51
|
+
"pwages": [50_000, 80_000],
|
|
52
|
+
"swages": [0, 40_000],
|
|
53
|
+
"depx": [0, 2],
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
taxes = calculate_taxes(households)
|
|
58
|
+
print(taxes.select("fiitax", "fica", "siitax"))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The result is the input plus `fiitax` (federal income tax), `fica` (payroll
|
|
62
|
+
taxes), `siitax` (state income tax) and other outputs, and `frate`/`srate`
|
|
63
|
+
(marginal rates) when requested. Missing inputs default to zero (`dep13`,
|
|
64
|
+
`dep17` and `dep18` default to `depx`). `idtl=2` adds detailed federal and state
|
|
65
|
+
worksheets, `taxsim_names=True` renames them to TAXSIM's labels, and
|
|
66
|
+
`keep_intermediate=True` keeps every intermediate column for auditing.
|
|
67
|
+
|
|
68
|
+
## Calculation modes
|
|
69
|
+
|
|
70
|
+
`statutory` (default) uses the canonical parameter tables and reviewed
|
|
71
|
+
corrections to TAXSIM. `calculation_mode="taxsim"` reproduces the compiled
|
|
72
|
+
TAXSIM, for replication and comparison; it is not recommended for new analysis.
|
|
73
|
+
|
|
74
|
+
## In the browser
|
|
75
|
+
|
|
76
|
+
`web/index.html` is a calculator that runs taxsim-py in the browser through Pyodide:
|
|
77
|
+
a form for one household, and a CSV upload for many. Nothing is sent to a server.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
uv run python scripts/build_web.py # builds the wheel into web/
|
|
81
|
+
python -m http.server -d web # then open http://localhost:8000
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
From JavaScript or Python, `taxsim_py.calculate_row({...})` takes a dict of TAXSIM
|
|
85
|
+
inputs and returns a dict of inputs plus results.
|
|
86
|
+
|
|
87
|
+
## Command line
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
taxsim-py households.csv taxes.parquet
|
|
91
|
+
taxsim-py households.dta # CSV on standard output
|
|
92
|
+
taxsim-py households.csv taxes.csv --mode taxsim --batch-rows 50000 --workers 4
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
File types come from the extensions: `csv`, `tsv`, `parquet`, `arrow`, `ndjson`,
|
|
96
|
+
and Stata (`dta`), SPSS (`sav`, `zsav`) and SAS (`sas7bdat`, read only) with the
|
|
97
|
+
optional reader (`pip install "taxsim-py[readstat]"`, which adds
|
|
98
|
+
[polars-readstat](https://github.com/jrothbaum/polars_readstat)). Use
|
|
99
|
+
`--input-format`/`--output-format` when the extension is not useful and
|
|
100
|
+
`--lowercase` for SAS files with uppercase names. The same readers are
|
|
101
|
+
`taxsim_py.io.tables.read_table` and `write_table`.
|
|
102
|
+
|
|
103
|
+
## What is supported
|
|
104
|
+
|
|
105
|
+
- **Years:** federal tax 1960-2025 and state tax 1977-2025, all actual law. Other
|
|
106
|
+
years raise an error.
|
|
107
|
+
- **States:** all 50 states and DC (TAXSIM codes 1-51; 0 means no state). States
|
|
108
|
+
without an income tax return 0, except Washington's Working Families credit in
|
|
109
|
+
statutory mode.
|
|
110
|
+
- **Inputs:** TAXSIM's 35 inputs, with the same meanings and units, plus the
|
|
111
|
+
optional `children_under_3`, `children_under_4` and `children_under_7`. Two
|
|
112
|
+
conventions: `psemp`/`ssemp` get no qualified business income deduction (use
|
|
113
|
+
`pbusinc`/`pprofinc`), and `pensions` is the kind of pension each state exempts.
|
|
114
|
+
- **Accuracy:** in `taxsim` mode, to the cent against the compiled TAXSIM on the
|
|
115
|
+
validation matrix (`scripts/validate_federal.py`, `scripts/validate_states.py`),
|
|
116
|
+
apart from logged TAXSIM errors. `statutory` mode follows the law where TAXSIM is
|
|
117
|
+
wrong ([Statutory corrections](docs/statutory_corrections.md)); its remaining
|
|
118
|
+
differences from PolicyEngine-US (2022-2025) are in the
|
|
119
|
+
[PolicyEngine comparison](docs/policyengine_recent_state_comparison.md).
|
|
120
|
+
- **Not modelled:** items TAXSIM has no input for, such as 2025 deductions for tips,
|
|
121
|
+
overtime and car-loan interest, and Washington's capital gains tax.
|
|
122
|
+
- **Speed:** on a mixed 42-state batch, 1,000,000 rows including marginal rates
|
|
123
|
+
take about 7.4 s and 2.8 GiB. The compiled TAXSIM takes 17.2 s for the same
|
|
124
|
+
calculation.
|
|
125
|
+
`batch_rows` and `max_year_workers` limit memory. See [Performance](docs/performance.md).
|
|
126
|
+
|
|
127
|
+
## Tests
|
|
128
|
+
|
|
129
|
+
`uv run pytest -q` runs the test suite, `uv run scripts/validate_all.py` the full
|
|
130
|
+
validation matrix, and `uv run scripts/compare_cps.py PATH/TO/cps_2011 --tax-year
|
|
131
|
+
2021` a CPS comparison with the compiled TAXSIM (from the `policyengine-taxsim`
|
|
132
|
+
test dependency).
|
|
133
|
+
|
|
134
|
+
## Documentation
|
|
135
|
+
|
|
136
|
+
Start with the [user guide](docs/index.md) (build it with `uvx --with mkdocs-material mkdocs serve`). Reference and working notes: [Architecture](docs/architecture.md),
|
|
137
|
+
[Statutory corrections](docs/statutory_corrections.md),
|
|
138
|
+
[Performance](docs/performance.md),
|
|
139
|
+
[PolicyEngine comparison](docs/policyengine_recent_state_comparison.md),
|
|
140
|
+
[Pending issues](docs/pending_issues.md) and
|
|
141
|
+
[Parameter tables](parameters/README.md).
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT; see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
THIS IS STILL IN DEVELOPMENT AND NOT ON PYPI YET
|
|
2
|
+
|
|
3
|
+
# taxsim-py
|
|
4
|
+
|
|
5
|
+
`taxsim-py` is a dataframe-oriented Python implementation of NBER TAXSIM,
|
|
6
|
+
independent of and not affiliated with NBER. It calculates federal income tax,
|
|
7
|
+
payroll tax, and state income tax for household records, using Polars
|
|
8
|
+
`DataFrame` or `LazyFrame` inputs and clear variable names (TAXSIM's `v1`-style
|
|
9
|
+
names only on request).
|
|
10
|
+
|
|
11
|
+
**[Documentation](https://jrothbaum.github.io/taxsim_py/)** ·
|
|
12
|
+
**[Try the calculator in your browser](https://jrothbaum.github.io/taxsim_py/calculator/)**
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
Python 3.9 or newer: `pip install taxsim-py` or `uv add taxsim-py`. From a
|
|
17
|
+
checkout: `uv sync --group dev --group test`.
|
|
18
|
+
|
|
19
|
+
## Basic use
|
|
20
|
+
|
|
21
|
+
Every row needs `mstat` and `state` (TAXSIM codes, or Census FIPS with
|
|
22
|
+
`state_id_type="fips"`). Include `year` in the data or pass `year=`.
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
import polars as pl
|
|
26
|
+
|
|
27
|
+
from taxsim_py import calculate_taxes
|
|
28
|
+
|
|
29
|
+
households = pl.DataFrame(
|
|
30
|
+
{
|
|
31
|
+
"year": [2021, 2021],
|
|
32
|
+
"state": [6, 36], # California, New York
|
|
33
|
+
"mstat": [1, 2], # single, married filing jointly
|
|
34
|
+
"page": [45, 50],
|
|
35
|
+
"pwages": [50_000, 80_000],
|
|
36
|
+
"swages": [0, 40_000],
|
|
37
|
+
"depx": [0, 2],
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
taxes = calculate_taxes(households)
|
|
42
|
+
print(taxes.select("fiitax", "fica", "siitax"))
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The result is the input plus `fiitax` (federal income tax), `fica` (payroll
|
|
46
|
+
taxes), `siitax` (state income tax) and other outputs, and `frate`/`srate`
|
|
47
|
+
(marginal rates) when requested. Missing inputs default to zero (`dep13`,
|
|
48
|
+
`dep17` and `dep18` default to `depx`). `idtl=2` adds detailed federal and state
|
|
49
|
+
worksheets, `taxsim_names=True` renames them to TAXSIM's labels, and
|
|
50
|
+
`keep_intermediate=True` keeps every intermediate column for auditing.
|
|
51
|
+
|
|
52
|
+
## Calculation modes
|
|
53
|
+
|
|
54
|
+
`statutory` (default) uses the canonical parameter tables and reviewed
|
|
55
|
+
corrections to TAXSIM. `calculation_mode="taxsim"` reproduces the compiled
|
|
56
|
+
TAXSIM, for replication and comparison; it is not recommended for new analysis.
|
|
57
|
+
|
|
58
|
+
## In the browser
|
|
59
|
+
|
|
60
|
+
`web/index.html` is a calculator that runs taxsim-py in the browser through Pyodide:
|
|
61
|
+
a form for one household, and a CSV upload for many. Nothing is sent to a server.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv run python scripts/build_web.py # builds the wheel into web/
|
|
65
|
+
python -m http.server -d web # then open http://localhost:8000
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
From JavaScript or Python, `taxsim_py.calculate_row({...})` takes a dict of TAXSIM
|
|
69
|
+
inputs and returns a dict of inputs plus results.
|
|
70
|
+
|
|
71
|
+
## Command line
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
taxsim-py households.csv taxes.parquet
|
|
75
|
+
taxsim-py households.dta # CSV on standard output
|
|
76
|
+
taxsim-py households.csv taxes.csv --mode taxsim --batch-rows 50000 --workers 4
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
File types come from the extensions: `csv`, `tsv`, `parquet`, `arrow`, `ndjson`,
|
|
80
|
+
and Stata (`dta`), SPSS (`sav`, `zsav`) and SAS (`sas7bdat`, read only) with the
|
|
81
|
+
optional reader (`pip install "taxsim-py[readstat]"`, which adds
|
|
82
|
+
[polars-readstat](https://github.com/jrothbaum/polars_readstat)). Use
|
|
83
|
+
`--input-format`/`--output-format` when the extension is not useful and
|
|
84
|
+
`--lowercase` for SAS files with uppercase names. The same readers are
|
|
85
|
+
`taxsim_py.io.tables.read_table` and `write_table`.
|
|
86
|
+
|
|
87
|
+
## What is supported
|
|
88
|
+
|
|
89
|
+
- **Years:** federal tax 1960-2025 and state tax 1977-2025, all actual law. Other
|
|
90
|
+
years raise an error.
|
|
91
|
+
- **States:** all 50 states and DC (TAXSIM codes 1-51; 0 means no state). States
|
|
92
|
+
without an income tax return 0, except Washington's Working Families credit in
|
|
93
|
+
statutory mode.
|
|
94
|
+
- **Inputs:** TAXSIM's 35 inputs, with the same meanings and units, plus the
|
|
95
|
+
optional `children_under_3`, `children_under_4` and `children_under_7`. Two
|
|
96
|
+
conventions: `psemp`/`ssemp` get no qualified business income deduction (use
|
|
97
|
+
`pbusinc`/`pprofinc`), and `pensions` is the kind of pension each state exempts.
|
|
98
|
+
- **Accuracy:** in `taxsim` mode, to the cent against the compiled TAXSIM on the
|
|
99
|
+
validation matrix (`scripts/validate_federal.py`, `scripts/validate_states.py`),
|
|
100
|
+
apart from logged TAXSIM errors. `statutory` mode follows the law where TAXSIM is
|
|
101
|
+
wrong ([Statutory corrections](docs/statutory_corrections.md)); its remaining
|
|
102
|
+
differences from PolicyEngine-US (2022-2025) are in the
|
|
103
|
+
[PolicyEngine comparison](docs/policyengine_recent_state_comparison.md).
|
|
104
|
+
- **Not modelled:** items TAXSIM has no input for, such as 2025 deductions for tips,
|
|
105
|
+
overtime and car-loan interest, and Washington's capital gains tax.
|
|
106
|
+
- **Speed:** on a mixed 42-state batch, 1,000,000 rows including marginal rates
|
|
107
|
+
take about 7.4 s and 2.8 GiB. The compiled TAXSIM takes 17.2 s for the same
|
|
108
|
+
calculation.
|
|
109
|
+
`batch_rows` and `max_year_workers` limit memory. See [Performance](docs/performance.md).
|
|
110
|
+
|
|
111
|
+
## Tests
|
|
112
|
+
|
|
113
|
+
`uv run pytest -q` runs the test suite, `uv run scripts/validate_all.py` the full
|
|
114
|
+
validation matrix, and `uv run scripts/compare_cps.py PATH/TO/cps_2011 --tax-year
|
|
115
|
+
2021` a CPS comparison with the compiled TAXSIM (from the `policyengine-taxsim`
|
|
116
|
+
test dependency).
|
|
117
|
+
|
|
118
|
+
## Documentation
|
|
119
|
+
|
|
120
|
+
Start with the [user guide](docs/index.md) (build it with `uvx --with mkdocs-material mkdocs serve`). Reference and working notes: [Architecture](docs/architecture.md),
|
|
121
|
+
[Statutory corrections](docs/statutory_corrections.md),
|
|
122
|
+
[Performance](docs/performance.md),
|
|
123
|
+
[PolicyEngine comparison](docs/policyengine_recent_state_comparison.md),
|
|
124
|
+
[Pending issues](docs/pending_issues.md) and
|
|
125
|
+
[Parameter tables](parameters/README.md).
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT; see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Parameter tables
|
|
2
|
+
|
|
3
|
+
The YAML and CSV files here are the canonical, law-oriented tables used by the
|
|
4
|
+
default `calculation_mode="statutory"`.
|
|
5
|
+
|
|
6
|
+
`calculation_mode="taxsim"` reproduces the compiled TAXSIM. Most differences are
|
|
7
|
+
formula, sequencing or intermediate-value behaviors, not alternate table values,
|
|
8
|
+
so they are centralized behavior switches in `src/taxsim_py/behavior.py` instead
|
|
9
|
+
of duplicate parameter files. If a TAXSIM-specific number is genuinely needed, add
|
|
10
|
+
it as a named override next to the canonical value with its source and years; never
|
|
11
|
+
change the canonical value just to make an oracle comparison pass.
|