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.
Files changed (170) hide show
  1. taxsim_py-0.1.0/LICENSE +21 -0
  2. taxsim_py-0.1.0/MANIFEST.in +2 -0
  3. taxsim_py-0.1.0/PKG-INFO +145 -0
  4. taxsim_py-0.1.0/README.md +129 -0
  5. taxsim_py-0.1.0/parameters/README.md +11 -0
  6. taxsim_py-0.1.0/parameters/national/amt.yaml +614 -0
  7. taxsim_py-0.1.0/parameters/national/analytic_rate.yaml +67 -0
  8. taxsim_py-0.1.0/parameters/national/capital_gains.yaml +477 -0
  9. taxsim_py-0.1.0/parameters/national/credits.yaml +378 -0
  10. taxsim_py-0.1.0/parameters/national/dependent_ages.yaml +9 -0
  11. taxsim_py-0.1.0/parameters/national/eitc.csv +469 -0
  12. taxsim_py-0.1.0/parameters/national/eitc_misc.yaml +74 -0
  13. taxsim_py-0.1.0/parameters/national/income_tax.yaml +459 -0
  14. taxsim_py-0.1.0/parameters/national/itemized.yaml +112 -0
  15. taxsim_py-0.1.0/parameters/national/law60.yaml +638 -0
  16. taxsim_py-0.1.0/parameters/national/niit.yaml +117 -0
  17. taxsim_py-0.1.0/parameters/national/payroll_tax.yaml +444 -0
  18. taxsim_py-0.1.0/parameters/national/personal_exemption.yaml +122 -0
  19. taxsim_py-0.1.0/parameters/national/pre1987.yaml +304 -0
  20. taxsim_py-0.1.0/parameters/national/sales_tax_deduction.yaml +636 -0
  21. taxsim_py-0.1.0/parameters/national/social_security.yaml +19 -0
  22. taxsim_py-0.1.0/parameters/national/state_adjustments.yaml +34 -0
  23. taxsim_py-0.1.0/parameters/national/state_cpi_extrapolation.yaml +71 -0
  24. taxsim_py-0.1.0/parameters/national/state_socsec.yaml +68 -0
  25. taxsim_py-0.1.0/parameters/states/ak/income_tax.yaml +117 -0
  26. taxsim_py-0.1.0/parameters/states/al/income_tax.yaml +122 -0
  27. taxsim_py-0.1.0/parameters/states/ar/income_tax.yaml +495 -0
  28. taxsim_py-0.1.0/parameters/states/ar/low_income_table.csv +168 -0
  29. taxsim_py-0.1.0/parameters/states/ar/low_income_table_2022plus.csv +924 -0
  30. taxsim_py-0.1.0/parameters/states/az/income_tax.yaml +342 -0
  31. taxsim_py-0.1.0/parameters/states/ca/income_tax.yaml +755 -0
  32. taxsim_py-0.1.0/parameters/states/co/income_tax.yaml +253 -0
  33. taxsim_py-0.1.0/parameters/states/ct/income_tax.yaml +525 -0
  34. taxsim_py-0.1.0/parameters/states/dc/income_tax.yaml +633 -0
  35. taxsim_py-0.1.0/parameters/states/de/income_tax.yaml +358 -0
  36. taxsim_py-0.1.0/parameters/states/ga/income_tax.yaml +171 -0
  37. taxsim_py-0.1.0/parameters/states/hi/income_tax.yaml +571 -0
  38. taxsim_py-0.1.0/parameters/states/ia/income_tax.yaml +434 -0
  39. taxsim_py-0.1.0/parameters/states/id/income_tax.yaml +404 -0
  40. taxsim_py-0.1.0/parameters/states/il/income_tax.yaml +105 -0
  41. taxsim_py-0.1.0/parameters/states/in/income_tax.yaml +233 -0
  42. taxsim_py-0.1.0/parameters/states/ks/income_tax.yaml +416 -0
  43. taxsim_py-0.1.0/parameters/states/ky/income_tax.yaml +349 -0
  44. taxsim_py-0.1.0/parameters/states/la/income_tax.yaml +154 -0
  45. taxsim_py-0.1.0/parameters/states/ma/income_tax.yaml +360 -0
  46. taxsim_py-0.1.0/parameters/states/md/income_tax.yaml +487 -0
  47. taxsim_py-0.1.0/parameters/states/me/income_tax.yaml +598 -0
  48. taxsim_py-0.1.0/parameters/states/mi/income_tax.yaml +385 -0
  49. taxsim_py-0.1.0/parameters/states/mn/income_tax.yaml +1438 -0
  50. taxsim_py-0.1.0/parameters/states/mo/income_tax.yaml +246 -0
  51. taxsim_py-0.1.0/parameters/states/ms/income_tax.yaml +138 -0
  52. taxsim_py-0.1.0/parameters/states/mt/income_tax.yaml +350 -0
  53. taxsim_py-0.1.0/parameters/states/nc/income_tax.yaml +151 -0
  54. taxsim_py-0.1.0/parameters/states/nd/income_tax.yaml +76 -0
  55. taxsim_py-0.1.0/parameters/states/ne/income_tax.yaml +460 -0
  56. taxsim_py-0.1.0/parameters/states/nh/income_tax.yaml +19 -0
  57. taxsim_py-0.1.0/parameters/states/nj/income_tax.yaml +169 -0
  58. taxsim_py-0.1.0/parameters/states/nm/income_tax.yaml +334 -0
  59. taxsim_py-0.1.0/parameters/states/ny/income_tax.yaml +579 -0
  60. taxsim_py-0.1.0/parameters/states/oh/income_tax.yaml +106 -0
  61. taxsim_py-0.1.0/parameters/states/ok/income_tax.yaml +118 -0
  62. taxsim_py-0.1.0/parameters/states/or/income_tax.yaml +172 -0
  63. taxsim_py-0.1.0/parameters/states/pa/income_tax.yaml +46 -0
  64. taxsim_py-0.1.0/parameters/states/ri/income_tax.yaml +158 -0
  65. taxsim_py-0.1.0/parameters/states/sc/income_tax.yaml +87 -0
  66. taxsim_py-0.1.0/parameters/states/tn/income_tax.yaml +12 -0
  67. taxsim_py-0.1.0/parameters/states/tx/sales_tax_deduction.yaml +120 -0
  68. taxsim_py-0.1.0/parameters/states/ut/income_tax.yaml +97 -0
  69. taxsim_py-0.1.0/parameters/states/va/income_tax.yaml +85 -0
  70. taxsim_py-0.1.0/parameters/states/vt/income_tax.yaml +139 -0
  71. taxsim_py-0.1.0/parameters/states/wa/income_tax.yaml +13 -0
  72. taxsim_py-0.1.0/parameters/states/wi/income_tax.yaml +250 -0
  73. taxsim_py-0.1.0/parameters/states/wv/income_tax.yaml +73 -0
  74. taxsim_py-0.1.0/pyproject.toml +50 -0
  75. taxsim_py-0.1.0/setup.cfg +4 -0
  76. taxsim_py-0.1.0/setup.py +23 -0
  77. taxsim_py-0.1.0/src/taxsim_py/__init__.py +6 -0
  78. taxsim_py-0.1.0/src/taxsim_py/api.py +505 -0
  79. taxsim_py-0.1.0/src/taxsim_py/behavior.py +75 -0
  80. taxsim_py-0.1.0/src/taxsim_py/calculators/__init__.py +0 -0
  81. taxsim_py-0.1.0/src/taxsim_py/calculators/federal.py +1298 -0
  82. taxsim_py-0.1.0/src/taxsim_py/calculators/federal_law60.py +419 -0
  83. taxsim_py-0.1.0/src/taxsim_py/calculators/federal_pre1987.py +611 -0
  84. taxsim_py-0.1.0/src/taxsim_py/calculators/payroll.py +65 -0
  85. taxsim_py-0.1.0/src/taxsim_py/calculators/states/__init__.py +101 -0
  86. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ak.py +68 -0
  87. taxsim_py-0.1.0/src/taxsim_py/calculators/states/al.py +252 -0
  88. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ar.py +461 -0
  89. taxsim_py-0.1.0/src/taxsim_py/calculators/states/az.py +423 -0
  90. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ca.py +656 -0
  91. taxsim_py-0.1.0/src/taxsim_py/calculators/states/co.py +445 -0
  92. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ct.py +562 -0
  93. taxsim_py-0.1.0/src/taxsim_py/calculators/states/dc.py +484 -0
  94. taxsim_py-0.1.0/src/taxsim_py/calculators/states/de.py +268 -0
  95. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ga.py +275 -0
  96. taxsim_py-0.1.0/src/taxsim_py/calculators/states/hi.py +354 -0
  97. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ia.py +421 -0
  98. taxsim_py-0.1.0/src/taxsim_py/calculators/states/id.py +282 -0
  99. taxsim_py-0.1.0/src/taxsim_py/calculators/states/il.py +151 -0
  100. taxsim_py-0.1.0/src/taxsim_py/calculators/states/in_.py +263 -0
  101. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ks.py +430 -0
  102. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ky.py +288 -0
  103. taxsim_py-0.1.0/src/taxsim_py/calculators/states/la.py +254 -0
  104. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ma.py +420 -0
  105. taxsim_py-0.1.0/src/taxsim_py/calculators/states/md.py +379 -0
  106. taxsim_py-0.1.0/src/taxsim_py/calculators/states/me.py +563 -0
  107. taxsim_py-0.1.0/src/taxsim_py/calculators/states/mi.py +192 -0
  108. taxsim_py-0.1.0/src/taxsim_py/calculators/states/mn.py +1038 -0
  109. taxsim_py-0.1.0/src/taxsim_py/calculators/states/mo.py +273 -0
  110. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ms.py +175 -0
  111. taxsim_py-0.1.0/src/taxsim_py/calculators/states/mt.py +301 -0
  112. taxsim_py-0.1.0/src/taxsim_py/calculators/states/nc.py +422 -0
  113. taxsim_py-0.1.0/src/taxsim_py/calculators/states/nd.py +243 -0
  114. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ne.py +244 -0
  115. taxsim_py-0.1.0/src/taxsim_py/calculators/states/nh.py +32 -0
  116. taxsim_py-0.1.0/src/taxsim_py/calculators/states/nj.py +282 -0
  117. taxsim_py-0.1.0/src/taxsim_py/calculators/states/nm.py +267 -0
  118. taxsim_py-0.1.0/src/taxsim_py/calculators/states/no_income_tax.py +9 -0
  119. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ny.py +699 -0
  120. taxsim_py-0.1.0/src/taxsim_py/calculators/states/oh.py +205 -0
  121. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ok.py +271 -0
  122. taxsim_py-0.1.0/src/taxsim_py/calculators/states/or_.py +333 -0
  123. taxsim_py-0.1.0/src/taxsim_py/calculators/states/pa.py +86 -0
  124. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ri.py +271 -0
  125. taxsim_py-0.1.0/src/taxsim_py/calculators/states/sc.py +260 -0
  126. taxsim_py-0.1.0/src/taxsim_py/calculators/states/tn.py +48 -0
  127. taxsim_py-0.1.0/src/taxsim_py/calculators/states/ut.py +208 -0
  128. taxsim_py-0.1.0/src/taxsim_py/calculators/states/va.py +284 -0
  129. taxsim_py-0.1.0/src/taxsim_py/calculators/states/vt.py +246 -0
  130. taxsim_py-0.1.0/src/taxsim_py/calculators/states/wa.py +32 -0
  131. taxsim_py-0.1.0/src/taxsim_py/calculators/states/wi.py +416 -0
  132. taxsim_py-0.1.0/src/taxsim_py/calculators/states/wv.py +149 -0
  133. taxsim_py-0.1.0/src/taxsim_py/cli.py +71 -0
  134. taxsim_py-0.1.0/src/taxsim_py/engine/__init__.py +0 -0
  135. taxsim_py-0.1.0/src/taxsim_py/engine/amt.py +80 -0
  136. taxsim_py-0.1.0/src/taxsim_py/engine/brackets.py +65 -0
  137. taxsim_py-0.1.0/src/taxsim_py/engine/capital_gains.py +27 -0
  138. taxsim_py-0.1.0/src/taxsim_py/engine/credits.py +56 -0
  139. taxsim_py-0.1.0/src/taxsim_py/engine/detail.py +166 -0
  140. taxsim_py-0.1.0/src/taxsim_py/engine/eitc.py +86 -0
  141. taxsim_py-0.1.0/src/taxsim_py/engine/federal_state.py +175 -0
  142. taxsim_py-0.1.0/src/taxsim_py/engine/inputs.py +158 -0
  143. taxsim_py-0.1.0/src/taxsim_py/engine/niit.py +20 -0
  144. taxsim_py-0.1.0/src/taxsim_py/engine/payroll_tax.py +272 -0
  145. taxsim_py-0.1.0/src/taxsim_py/engine/sales_tax.py +55 -0
  146. taxsim_py-0.1.0/src/taxsim_py/engine/schema.py +74 -0
  147. taxsim_py-0.1.0/src/taxsim_py/engine/social_security.py +29 -0
  148. taxsim_py-0.1.0/src/taxsim_py/engine/state.py +286 -0
  149. taxsim_py-0.1.0/src/taxsim_py/engine/state_extrapolation.py +106 -0
  150. taxsim_py-0.1.0/src/taxsim_py/io/__init__.py +0 -0
  151. taxsim_py-0.1.0/src/taxsim_py/io/tables.py +71 -0
  152. taxsim_py-0.1.0/src/taxsim_py/prep/__init__.py +5 -0
  153. taxsim_py-0.1.0/src/taxsim_py/prep/cps_asec.py +243 -0
  154. taxsim_py-0.1.0/src/taxsim_py/validation/__init__.py +5 -0
  155. taxsim_py-0.1.0/src/taxsim_py/validation/independent.py +177 -0
  156. taxsim_py-0.1.0/src/taxsim_py.egg-info/PKG-INFO +145 -0
  157. taxsim_py-0.1.0/src/taxsim_py.egg-info/SOURCES.txt +168 -0
  158. taxsim_py-0.1.0/src/taxsim_py.egg-info/dependency_links.txt +1 -0
  159. taxsim_py-0.1.0/src/taxsim_py.egg-info/entry_points.txt +2 -0
  160. taxsim_py-0.1.0/src/taxsim_py.egg-info/requires.txt +5 -0
  161. taxsim_py-0.1.0/src/taxsim_py.egg-info/top_level.txt +1 -0
  162. taxsim_py-0.1.0/tests/test_api.py +258 -0
  163. taxsim_py-0.1.0/tests/test_benchmark_comparison.py +52 -0
  164. taxsim_py-0.1.0/tests/test_calculation_modes.py +509 -0
  165. taxsim_py-0.1.0/tests/test_cli.py +94 -0
  166. taxsim_py-0.1.0/tests/test_hawaii_recent.py +34 -0
  167. taxsim_py-0.1.0/tests/test_independent_models.py +203 -0
  168. taxsim_py-0.1.0/tests/test_law_based_checks.py +241 -0
  169. taxsim_py-0.1.0/tests/test_negative_capital_gains.py +51 -0
  170. taxsim_py-0.1.0/tests/test_parameter_provenance.py +54 -0
@@ -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.
@@ -0,0 +1,2 @@
1
+ graft parameters
2
+ global-exclude __pycache__ *.py[cod]
@@ -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.