diff --git a/changelog.d/irs-index-tax-year-cpi.fixed.md b/changelog.d/irs-index-tax-year-cpi.fixed.md new file mode 100644 index 00000000000..420fa3b7fa5 --- /dev/null +++ b/changelog.d/irs-index-tax-year-cpi.fixed.md @@ -0,0 +1 @@ +Correct IRS September–August inflation windows and separate CBO tax-year projections while preserving published amounts; calculate dependent deduction limits from statutory bases, separate Vermont and Wisconsin unchained CPI schedules, preserve CBO calendar forecast anchors, and encode published 2026 Wisconsin and California tax amounts. Update observed chained and seasonally adjusted CPI-U through August 2026. diff --git a/policyengine_us/parameters/gov/bls/cpi/c_cpi_u.yaml b/policyengine_us/parameters/gov/bls/cpi/c_cpi_u.yaml index f9f7cc3021e..148074018ad 100644 --- a/policyengine_us/parameters/gov/bls/cpi/c_cpi_u.yaml +++ b/policyengine_us/parameters/gov/bls/cpi/c_cpi_u.yaml @@ -320,25 +320,27 @@ values: 2026-04-01: 184.499 2026-05-01: 185.589 2026-06-01: 184.992 - # CBO projections from CBO Feb 2026 forecast for future periods. - # CBO projects the average C-CPI-U over the 12mo ending August, - # which determines tax parameters for the following year. - 2027-02-01: 187.2 # 2028 value. - 2028-02-01: 191.1 # 2029 value. - 2029-02-01: 194.9 # 2030 value. - 2030-02-01: 198.8 # 2031 value. - 2031-02-01: 202.7 # 2032 value. - 2032-02-01: 206.7 # 2033 value. - 2033-02-01: 210.8 # 2034 value. - 2034-02-01: 214.9 # 2035 value. - 2035-02-01: 219.2 # 2036 value. + 2026-07-01: 185.162 + 2026-08-01: 185.739 + # CBO's February 2026 projections of each calendar year's average C-CPI-U. + # Tax parameters use the average over the 12 months ending August instead; + # CBO's projections of that average are in tax_year_projection/c_cpi_u.yaml. + 2027-02-01: 187.2 # Calendar year 2027 average. + 2028-02-01: 191.1 # Calendar year 2028 average. + 2029-02-01: 194.9 # Calendar year 2029 average. + 2030-02-01: 198.8 # Calendar year 2030 average. + 2031-02-01: 202.7 # Calendar year 2031 average. + 2032-02-01: 206.7 # Calendar year 2032 average. + 2033-02-01: 210.8 # Calendar year 2033 average. + 2034-02-01: 214.9 # Calendar year 2034 average. + 2035-02-01: 219.2 # Calendar year 2035 average. # Values for 2036-2100 are set programmatically in uprating_extensions.py metadata: economy: false unit: currency-USD label: Chained CPI-U reference: - - title: BLS | Chained CPI-U, U.S. city average, all items (SUUR0000SA0), monthly values through June 2026 + - title: BLS | Chained CPI-U, U.S. city average, all items (SUUR0000SA0), monthly values through August 2026 href: https://data.bls.gov/timeseries/SUUR0000SA0 - title: CBO | Tax Parameters and Effective Marginal Tax Rates | June 2024 # Source: https://www.cbo.gov/data/budget-economic-data#10 diff --git a/policyengine_us/parameters/gov/bls/cpi/cpi_u.yaml b/policyengine_us/parameters/gov/bls/cpi/cpi_u.yaml index 2a76d76e7ec..3361530da39 100644 --- a/policyengine_us/parameters/gov/bls/cpi/cpi_u.yaml +++ b/policyengine_us/parameters/gov/bls/cpi/cpi_u.yaml @@ -1363,23 +1363,27 @@ values: 2026-04-01: 332.407 2026-05-01: 333.979 2026-06-01: 332.568 - # CBO projections from CBO Feb 2026 forecast for future periods. - 2027-02-01: 340.3 # 2028 value. - 2028-02-01: 348.3 # 2029 value. - 2029-02-01: 356.3 # 2030 value. - 2030-02-01: 364.3 # 2031 value. - 2031-02-01: 372.6 # 2032 value. - 2032-02-01: 381.0 # 2033 value. - 2033-02-01: 389.6 # 2034 value. - 2034-02-01: 398.4 # 2035 value. - 2035-02-01: 407.3 # 2036 value. + 2026-07-01: 332.813 + 2026-08-01: 334.131 + # CBO's February 2026 projections of each calendar year's average CPI-U. + # Tax parameters use the average over the 12 months ending August instead; + # CBO's projections of that average are in tax_year_projection/cpi_u.yaml. + 2027-02-01: 340.3 # Calendar year 2027 average. + 2028-02-01: 348.3 # Calendar year 2028 average. + 2029-02-01: 356.3 # Calendar year 2029 average. + 2030-02-01: 364.3 # Calendar year 2030 average. + 2031-02-01: 372.6 # Calendar year 2031 average. + 2032-02-01: 381.0 # Calendar year 2032 average. + 2033-02-01: 389.6 # Calendar year 2033 average. + 2034-02-01: 398.4 # Calendar year 2034 average. + 2035-02-01: 407.3 # Calendar year 2035 average. # Values for 2036-2100 are set programmatically in uprating_extensions.py metadata: unit: currency-USD label: CPI-U economy: false reference: - - title: BLS | CPI-U, U.S. city average, all items, seasonally adjusted (CUSR0000SA0), monthly values through June 2026 + - title: BLS | CPI-U, U.S. city average, all items, seasonally adjusted (CUSR0000SA0), monthly values through August 2026 href: https://data.bls.gov/timeseries/CUSR0000SA0 - title: CBO | Tax Parameters and Effective Marginal Tax Rates | June 2024 # Source: https://www.cbo.gov/data/budget-economic-data#10 diff --git a/policyengine_us/parameters/gov/bls/cpi/cpi_u_nsa.yaml b/policyengine_us/parameters/gov/bls/cpi/cpi_u_nsa.yaml new file mode 100644 index 00000000000..d8ada5ca9b6 --- /dev/null +++ b/policyengine_us/parameters/gov/bls/cpi/cpi_u_nsa.yaml @@ -0,0 +1,371 @@ +description: The Bureau of Labor Statistics publishes this monthly Consumer Price Index for All Urban Consumers, not seasonally adjusted. +values: + # BLS series CUUR0000SA0 (U.S. city average, all items, 1982-84=100), as + # the BLS public data API returned it on 2026-10-06. Published to one + # decimal through 2006 and three decimals from 2007. + 1997-01-01: 159.1 + 1997-02-01: 159.6 + 1997-03-01: 160.0 + 1997-04-01: 160.2 + 1997-05-01: 160.1 + 1997-06-01: 160.3 + 1997-07-01: 160.5 + 1997-08-01: 160.8 + 1997-09-01: 161.2 + 1997-10-01: 161.6 + 1997-11-01: 161.5 + 1997-12-01: 161.3 + 1998-01-01: 161.6 + 1998-02-01: 161.9 + 1998-03-01: 162.2 + 1998-04-01: 162.5 + 1998-05-01: 162.8 + 1998-06-01: 163.0 + 1998-07-01: 163.2 + 1998-08-01: 163.4 + 1998-09-01: 163.6 + 1998-10-01: 164.0 + 1998-11-01: 164.0 + 1998-12-01: 163.9 + 1999-01-01: 164.3 + 1999-02-01: 164.5 + 1999-03-01: 165.0 + 1999-04-01: 166.2 + 1999-05-01: 166.2 + 1999-06-01: 166.2 + 1999-07-01: 166.7 + 1999-08-01: 167.1 + 1999-09-01: 167.9 + 1999-10-01: 168.2 + 1999-11-01: 168.3 + 1999-12-01: 168.3 + 2000-01-01: 168.8 + 2000-02-01: 169.8 + 2000-03-01: 171.2 + 2000-04-01: 171.3 + 2000-05-01: 171.5 + 2000-06-01: 172.4 + 2000-07-01: 172.8 + 2000-08-01: 172.8 + 2000-09-01: 173.7 + 2000-10-01: 174.0 + 2000-11-01: 174.1 + 2000-12-01: 174.0 + 2001-01-01: 175.1 + 2001-02-01: 175.8 + 2001-03-01: 176.2 + 2001-04-01: 176.9 + 2001-05-01: 177.7 + 2001-06-01: 178.0 + 2001-07-01: 177.5 + 2001-08-01: 177.5 + 2001-09-01: 178.3 + 2001-10-01: 177.7 + 2001-11-01: 177.4 + 2001-12-01: 176.7 + 2002-01-01: 177.1 + 2002-02-01: 177.8 + 2002-03-01: 178.8 + 2002-04-01: 179.8 + 2002-05-01: 179.8 + 2002-06-01: 179.9 + 2002-07-01: 180.1 + 2002-08-01: 180.7 + 2002-09-01: 181.0 + 2002-10-01: 181.3 + 2002-11-01: 181.3 + 2002-12-01: 180.9 + 2003-01-01: 181.7 + 2003-02-01: 183.1 + 2003-03-01: 184.2 + 2003-04-01: 183.8 + 2003-05-01: 183.5 + 2003-06-01: 183.7 + 2003-07-01: 183.9 + 2003-08-01: 184.6 + 2003-09-01: 185.2 + 2003-10-01: 185.0 + 2003-11-01: 184.5 + 2003-12-01: 184.3 + 2004-01-01: 185.2 + 2004-02-01: 186.2 + 2004-03-01: 187.4 + 2004-04-01: 188.0 + 2004-05-01: 189.1 + 2004-06-01: 189.7 + 2004-07-01: 189.4 + 2004-08-01: 189.5 + 2004-09-01: 189.9 + 2004-10-01: 190.9 + 2004-11-01: 191.0 + 2004-12-01: 190.3 + 2005-01-01: 190.7 + 2005-02-01: 191.8 + 2005-03-01: 193.3 + 2005-04-01: 194.6 + 2005-05-01: 194.4 + 2005-06-01: 194.5 + 2005-07-01: 195.4 + 2005-08-01: 196.4 + 2005-09-01: 198.8 + 2005-10-01: 199.2 + 2005-11-01: 197.6 + 2005-12-01: 196.8 + 2006-01-01: 198.3 + 2006-02-01: 198.7 + 2006-03-01: 199.8 + 2006-04-01: 201.5 + 2006-05-01: 202.5 + 2006-06-01: 202.9 + 2006-07-01: 203.5 + 2006-08-01: 203.9 + 2006-09-01: 202.9 + 2006-10-01: 201.8 + 2006-11-01: 201.5 + 2006-12-01: 201.8 + 2007-01-01: 202.416 + 2007-02-01: 203.499 + 2007-03-01: 205.352 + 2007-04-01: 206.686 + 2007-05-01: 207.949 + 2007-06-01: 208.352 + 2007-07-01: 208.299 + 2007-08-01: 207.917 + 2007-09-01: 208.490 + 2007-10-01: 208.936 + 2007-11-01: 210.177 + 2007-12-01: 210.036 + 2008-01-01: 211.080 + 2008-02-01: 211.693 + 2008-03-01: 213.528 + 2008-04-01: 214.823 + 2008-05-01: 216.632 + 2008-06-01: 218.815 + 2008-07-01: 219.964 + 2008-08-01: 219.086 + 2008-09-01: 218.783 + 2008-10-01: 216.573 + 2008-11-01: 212.425 + 2008-12-01: 210.228 + 2009-01-01: 211.143 + 2009-02-01: 212.193 + 2009-03-01: 212.709 + 2009-04-01: 213.240 + 2009-05-01: 213.856 + 2009-06-01: 215.693 + 2009-07-01: 215.351 + 2009-08-01: 215.834 + 2009-09-01: 215.969 + 2009-10-01: 216.177 + 2009-11-01: 216.330 + 2009-12-01: 215.949 + 2010-01-01: 216.687 + 2010-02-01: 216.741 + 2010-03-01: 217.631 + 2010-04-01: 218.009 + 2010-05-01: 218.178 + 2010-06-01: 217.965 + 2010-07-01: 218.011 + 2010-08-01: 218.312 + 2010-09-01: 218.439 + 2010-10-01: 218.711 + 2010-11-01: 218.803 + 2010-12-01: 219.179 + 2011-01-01: 220.223 + 2011-02-01: 221.309 + 2011-03-01: 223.467 + 2011-04-01: 224.906 + 2011-05-01: 225.964 + 2011-06-01: 225.722 + 2011-07-01: 225.922 + 2011-08-01: 226.545 + 2011-09-01: 226.889 + 2011-10-01: 226.421 + 2011-11-01: 226.230 + 2011-12-01: 225.672 + 2012-01-01: 226.665 + 2012-02-01: 227.663 + 2012-03-01: 229.392 + 2012-04-01: 230.085 + 2012-05-01: 229.815 + 2012-06-01: 229.478 + 2012-07-01: 229.104 + 2012-08-01: 230.379 + 2012-09-01: 231.407 + 2012-10-01: 231.317 + 2012-11-01: 230.221 + 2012-12-01: 229.601 + 2013-01-01: 230.280 + 2013-02-01: 232.166 + 2013-03-01: 232.773 + 2013-04-01: 232.531 + 2013-05-01: 232.945 + 2013-06-01: 233.504 + 2013-07-01: 233.596 + 2013-08-01: 233.877 + 2013-09-01: 234.149 + 2013-10-01: 233.546 + 2013-11-01: 233.069 + 2013-12-01: 233.049 + 2014-01-01: 233.916 + 2014-02-01: 234.781 + 2014-03-01: 236.293 + 2014-04-01: 237.072 + 2014-05-01: 237.900 + 2014-06-01: 238.343 + 2014-07-01: 238.250 + 2014-08-01: 237.852 + 2014-09-01: 238.031 + 2014-10-01: 237.433 + 2014-11-01: 236.151 + 2014-12-01: 234.812 + 2015-01-01: 233.707 + 2015-02-01: 234.722 + 2015-03-01: 236.119 + 2015-04-01: 236.599 + 2015-05-01: 237.805 + 2015-06-01: 238.638 + 2015-07-01: 238.654 + 2015-08-01: 238.316 + 2015-09-01: 237.945 + 2015-10-01: 237.838 + 2015-11-01: 237.336 + 2015-12-01: 236.525 + 2016-01-01: 236.916 + 2016-02-01: 237.111 + 2016-03-01: 238.132 + 2016-04-01: 239.261 + 2016-05-01: 240.229 + 2016-06-01: 241.018 + 2016-07-01: 240.628 + 2016-08-01: 240.849 + 2016-09-01: 241.428 + 2016-10-01: 241.729 + 2016-11-01: 241.353 + 2016-12-01: 241.432 + 2017-01-01: 242.839 + 2017-02-01: 243.603 + 2017-03-01: 243.801 + 2017-04-01: 244.524 + 2017-05-01: 244.733 + 2017-06-01: 244.955 + 2017-07-01: 244.786 + 2017-08-01: 245.519 + 2017-09-01: 246.819 + 2017-10-01: 246.663 + 2017-11-01: 246.669 + 2017-12-01: 246.524 + 2018-01-01: 247.867 + 2018-02-01: 248.991 + 2018-03-01: 249.554 + 2018-04-01: 250.546 + 2018-05-01: 251.588 + 2018-06-01: 251.989 + 2018-07-01: 252.006 + 2018-08-01: 252.146 + 2018-09-01: 252.439 + 2018-10-01: 252.885 + 2018-11-01: 252.038 + 2018-12-01: 251.233 + 2019-01-01: 251.712 + 2019-02-01: 252.776 + 2019-03-01: 254.202 + 2019-04-01: 255.548 + 2019-05-01: 256.092 + 2019-06-01: 256.143 + 2019-07-01: 256.571 + 2019-08-01: 256.558 + 2019-09-01: 256.759 + 2019-10-01: 257.346 + 2019-11-01: 257.208 + 2019-12-01: 256.974 + 2020-01-01: 257.971 + 2020-02-01: 258.678 + 2020-03-01: 258.115 + 2020-04-01: 256.389 + 2020-05-01: 256.394 + 2020-06-01: 257.797 + 2020-07-01: 259.101 + 2020-08-01: 259.918 + 2020-09-01: 260.280 + 2020-10-01: 260.388 + 2020-11-01: 260.229 + 2020-12-01: 260.474 + 2021-01-01: 261.582 + 2021-02-01: 263.014 + 2021-03-01: 264.877 + 2021-04-01: 267.054 + 2021-05-01: 269.195 + 2021-06-01: 271.696 + 2021-07-01: 273.003 + 2021-08-01: 273.567 + 2021-09-01: 274.310 + 2021-10-01: 276.589 + 2021-11-01: 277.948 + 2021-12-01: 278.802 + 2022-01-01: 281.148 + 2022-02-01: 283.716 + 2022-03-01: 287.504 + 2022-04-01: 289.109 + 2022-05-01: 292.296 + 2022-06-01: 296.311 + 2022-07-01: 296.276 + 2022-08-01: 296.171 + 2022-09-01: 296.808 + 2022-10-01: 298.012 + 2022-11-01: 297.711 + 2022-12-01: 296.797 + 2023-01-01: 299.170 + 2023-02-01: 300.840 + 2023-03-01: 301.836 + 2023-04-01: 303.363 + 2023-05-01: 304.127 + 2023-06-01: 305.109 + 2023-07-01: 305.691 + 2023-08-01: 307.026 + 2023-09-01: 307.789 + 2023-10-01: 307.671 + 2023-11-01: 307.051 + 2023-12-01: 306.746 + 2024-01-01: 308.417 + 2024-02-01: 310.326 + 2024-03-01: 312.332 + 2024-04-01: 313.548 + 2024-05-01: 314.069 + 2024-06-01: 314.175 + 2024-07-01: 314.540 + 2024-08-01: 314.796 + 2024-09-01: 315.301 + 2024-10-01: 315.664 + 2024-11-01: 315.493 + 2024-12-01: 315.605 + 2025-01-01: 317.671 + 2025-02-01: 319.082 + 2025-03-01: 319.799 + 2025-04-01: 320.795 + 2025-05-01: 321.465 + 2025-06-01: 322.561 + 2025-07-01: 323.048 + 2025-08-01: 323.976 + 2025-09-01: 324.800 + # BLS published no October 2025 value (footnote X: "Data unavailable + # due to the 2025 lapse in appropriations"). Parameter lookups at + # October 2025 return September's value; see + # get_average_for_12_months_ending_august for how windows treat the gap. + 2025-11-01: 324.122 + 2025-12-01: 324.054 + 2026-01-01: 325.252 + 2026-02-01: 326.785 + 2026-03-01: 330.213 + 2026-04-01: 333.020 + 2026-05-01: 335.123 + 2026-06-01: 333.952 + 2026-07-01: 333.918 + 2026-08-01: 334.980 +metadata: + unit: currency-USD + label: CPI-U, not seasonally adjusted + economy: false + reference: + - title: BLS | CPI-U, U.S. city average, all items, not seasonally adjusted (CUUR0000SA0), January 1997 through August 2026 + href: https://data.bls.gov/timeseries/CUUR0000SA0 diff --git a/policyengine_us/parameters/gov/bls/cpi/tax_year_projection/c_cpi_u.yaml b/policyengine_us/parameters/gov/bls/cpi/tax_year_projection/c_cpi_u.yaml new file mode 100644 index 00000000000..4cede88a163 --- /dev/null +++ b/policyengine_us/parameters/gov/bls/cpi/tax_year_projection/c_cpi_u.yaml @@ -0,0 +1,28 @@ +description: The Congressional Budget Office projects this average of the Chained Consumer Price Index for All Urban Consumers over the 12 months ending the August before each tax year, the index that adjusts federal tax parameters for that year. +values: + # Keyed by tax year: the 2028 value averages September 2026 through + # August 2027. Windows with BLS observations use c_cpi_u.yaml instead. + 2027-01-01: 181.654 + 2028-01-01: 185.881 + 2029-01-01: 189.775 + 2030-01-01: 193.6 + 2031-01-01: 197.44 + 2032-01-01: 201.335 + 2033-01-01: 205.302 + 2034-01-01: 209.346 + 2035-01-01: 213.471 + 2036-01-01: 217.68 + # Values for 2037-2100 are set programmatically in uprating_extensions.py. +metadata: + unit: /1 + period: year + label: CBO tax-year Chained CPI-U projection + economy: false + reference: + - title: 26 U.S. Code § 1(f)(6) - C-CPI-U + href: https://www.law.cornell.edu/uscode/text/26/1#f_6 + - title: CBO | Tax Parameters and Effective Marginal Tax Rates | February 2026 + # Sheet 1. Tax Parameters, row 153: Chained consumer price index, all + # urban consumers (C-CPIU), under "Inflation indexes for tax year + # (average CPI over the 12 months ending the previous August)". + href: https://www.cbo.gov/system/files/2026-02/53724-2026-02-Tax-Parameters.xlsx diff --git a/policyengine_us/parameters/gov/bls/cpi/tax_year_projection/cpi_u.yaml b/policyengine_us/parameters/gov/bls/cpi/tax_year_projection/cpi_u.yaml new file mode 100644 index 00000000000..e4b45465a4a --- /dev/null +++ b/policyengine_us/parameters/gov/bls/cpi/tax_year_projection/cpi_u.yaml @@ -0,0 +1,26 @@ +description: The Congressional Budget Office projects this average of the Consumer Price Index for All Urban Consumers over the 12 months ending the August before each tax year. +values: + # Keyed by tax year: the 2028 value averages September 2026 through + # August 2027. Windows with BLS observations use cpi_u.yaml instead. + 2027-01-01: 328.701 + 2028-01-01: 337.382 + 2029-01-01: 345.443 + 2030-01-01: 353.398 + 2031-01-01: 361.404 + 2032-01-01: 369.57 + 2033-01-01: 377.913 + 2034-01-01: 386.443 + 2035-01-01: 395.162 + 2036-01-01: 404.081 + # Values for 2037-2100 are set programmatically in uprating_extensions.py. +metadata: + unit: /1 + period: year + label: CBO tax-year CPI-U projection + economy: false + reference: + - title: CBO | Tax Parameters and Effective Marginal Tax Rates | February 2026 + # Sheet 1. Tax Parameters, row 152: Consumer price index, all urban + # consumers (CPIU), under "Inflation indexes for tax year (average CPI + # over the 12 months ending the previous August)". + href: https://www.cbo.gov/system/files/2026-02/53724-2026-02-Tax-Parameters.xlsx diff --git a/policyengine_us/parameters/gov/irs/deductions/standard/dependent/amount.yaml b/policyengine_us/parameters/gov/irs/deductions/standard/dependent/amount.yaml index 8e71e18153f..266a13ab354 100644 --- a/policyengine_us/parameters/gov/irs/deductions/standard/dependent/amount.yaml +++ b/policyengine_us/parameters/gov/irs/deductions/standard/dependent/amount.yaml @@ -7,27 +7,18 @@ values: 2024-01-01: 1_300 2025-01-01: 1_350 2026-01-01: 1_350 - # CBO forecast. - 2027-01-01: 1_400 - 2028-01-01: 1_450 - 2029-01-01: 1_450 - 2030-01-01: 1_500 - 2031-01-01: 1_500 - 2032-01-01: 1_550 - 2033-01-01: 1_600 - 2034-01-01: 1_600 - 2035-01-01: 1_650 - 2036-01-01: 1_700 metadata: unit: currency-USD period: year label: Dependent standard deduction floor - # Values after the CBO horizon are computed in + # Values after the last IRS publication are computed in # parameters/uprating_extensions.py per 26 U.S.C. 63(c)(4)(B)(i): the # statutory $500 increased by the 1(f)(3) cost-of-living adjustment with - # calendar year 1987 as the base year, each increase rounded down to the - # next lowest multiple of $50 under 1(f)(7)(A). Those values supersede - # this uprating rule, which describes the index and rounding. + # calendar year 1987 as the base year (C-CPI-U for the 12 months ending + # August 31 of the prior year), each increase rounded down to the next + # lowest multiple of $50 under 1(f)(7)(A). Applied to CBO's projected + # index, this reproduces every CBO projection of the floor. Those values + # supersede this uprating rule, which describes the index and rounding. uprating: parameter: gov.irs.uprating rounding: @@ -54,5 +45,3 @@ metadata: href: https://www.irs.gov/pub/irs-drop/rp-19-44.pdf#page=13 - title: Rev. Proc. 2018-57, sec. 3.16(2) (tax year 2019) href: https://www.irs.gov/pub/irs-drop/rp-18-57.pdf#page=16 - - title: CBO Tax Parameters and Effective Marginal Tax Rates, Feb 2026, sheet 1, row 68 (dependent filers, unearned), tax years 2027-2036 - href: https://www.cbo.gov/system/files/2026-02/53724-2026-02-Tax-Parameters.xlsx diff --git a/policyengine_us/parameters/gov/states/ca/cpi.yaml b/policyengine_us/parameters/gov/states/ca/cpi.yaml index 67bcfdf10ca..20e91643ac8 100644 --- a/policyengine_us/parameters/gov/states/ca/cpi.yaml +++ b/policyengine_us/parameters/gov/states/ca/cpi.yaml @@ -1,4 +1,4 @@ -description: California CPI (from the current year's June) +description: California CPI from the current year's June, with forecast proxies after the last published observation. values: 2019-01-01: 280.956 2020-01-01: 284.835 @@ -7,11 +7,14 @@ values: 2023-01-01: 332.035 2024-01-01: 342.856 2025-01-01: 353.044 + 2026-01-01: 364.969 metadata: unit: currency-USD period: year label: California income tax CPI uprating + # The existing national CPI forecast proxy is a modeling assumption for future years. + # Published California June values take precedence. uprating: gov.irs.uprating reference: - title: California Consumer Price Index (1955-2026), All Urban Consumers, June values diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/credits/renter/income_cap.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/credits/renter/income_cap.yaml index 2ed14a3a3bc..967edec64ba 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/credits/renter/income_cap.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/credits/renter/income_cap.yaml @@ -5,30 +5,35 @@ SINGLE: 2023-01-01: 50_746 2024-01-01: 52_421 2025-01-01: 53_994 + 2026-01-01: 55_830 SEPARATE: 2021-01-01: 45_448 2022-01-01: 49_220 2023-01-01: 50_746 2024-01-01: 52_421 2025-01-01: 53_994 + 2026-01-01: 55_830 SURVIVING_SPOUSE: 2021-01-01: 90_896 2022-01-01: 98_440 2023-01-01: 101_492 2024-01-01: 104_842 2025-01-01: 107_987 + 2026-01-01: 111_660 JOINT: 2021-01-01: 90_896 2022-01-01: 98_440 2023-01-01: 101_492 2024-01-01: 104_842 2025-01-01: 107_987 + 2026-01-01: 111_660 HEAD_OF_HOUSEHOLD: 2021-01-01: 90_896 2022-01-01: 98_440 2023-01-01: 101_492 2024-01-01: 104_842 2025-01-01: 107_987 + 2026-01-01: 111_660 metadata: period: year @@ -40,6 +45,8 @@ metadata: # single/separate: $25,000 starting in 1998 indexed by California CPI # surviving_spouse/joint/head: $50,000 starting in 1998 indexed by California CPI reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: Cal. Rev. & Tax. Code § 17053.5 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=RTC§ionNum=17053.5 - title: 2021 California Form 540 instructions diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/deductions/standard/amount.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/deductions/standard/amount.yaml index 8d2e9cc8d8c..f59e8c7c2e0 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/deductions/standard/amount.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/deductions/standard/amount.yaml @@ -8,6 +8,8 @@ metadata: breakdown: - filing_status reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: 2021 Form 540 California Resident Income Tax Return href: https://www.ftb.ca.gov/forms/2021/2021-540.pdf#page=2 - title: 2022 Form 540 California Resident Income Tax Return @@ -29,6 +31,7 @@ JOINT: 2023-01-01: 10_726 2024-01-01: 11_080 2025-01-01: 11_412 + 2026-01-01: 11_800 HEAD_OF_HOUSEHOLD: values: 2021-01-01: 9_606 @@ -36,6 +39,7 @@ HEAD_OF_HOUSEHOLD: 2023-01-01: 10_726 2024-01-01: 11_080 2025-01-01: 11_412 + 2026-01-01: 11_800 SURVIVING_SPOUSE: values: 2021-01-01: 9_606 @@ -43,6 +47,7 @@ SURVIVING_SPOUSE: 2023-01-01: 10_726 2024-01-01: 11_080 2025-01-01: 11_412 + 2026-01-01: 11_800 SINGLE: values: 2021-01-01: 4_803 @@ -50,6 +55,7 @@ SINGLE: 2023-01-01: 5_363 2024-01-01: 5_540 2025-01-01: 5_706 + 2026-01-01: 5_900 SEPARATE: values: 2021-01-01: 4_803 @@ -57,3 +63,4 @@ SEPARATE: 2023-01-01: 5_363 2024-01-01: 5_540 2025-01-01: 5_706 + 2026-01-01: 5_900 diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/exemptions/amount.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/exemptions/amount.yaml index 297f5ee0d9b..3d81ca2b8b0 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/exemptions/amount.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/exemptions/amount.yaml @@ -6,6 +6,7 @@ values: 2023-01-01: 144 2024-01-01: 149 2025-01-01: 153 + 2026-01-01: 158 metadata: period: year @@ -13,6 +14,8 @@ metadata: label: California income exemption amount uprating: gov.states.ca.cpi reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: 2021 Form 540 California Resident Income Tax Return href: https://www.ftb.ca.gov/forms/2021/2021-540.pdf#page=1 - title: 2022 Form 540 California Resident Income Tax Return @@ -25,4 +28,3 @@ metadata: href: https://www.ftb.ca.gov/forms/2025/2025-540.pdf#page=1 - title: Cal. Rev. & Tax. Code § 17054 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17054.&nodeTreePath=3.20.2&lawCode=RTC - # Index according to federal tax parameter rules until we add California CPI trend. diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/exemptions/dependent_amount.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/exemptions/dependent_amount.yaml index 9eb0ae150b9..46f4c313d67 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/exemptions/dependent_amount.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/exemptions/dependent_amount.yaml @@ -6,6 +6,7 @@ values: 2023-01-01: 446 2024-01-01: 461 2025-01-01: 475 + 2026-01-01: 491 metadata: period: year @@ -13,6 +14,8 @@ metadata: label: California dependent exemption amount uprating: gov.states.ca.cpi reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: 2021 Form 540 California Resident Income Tax Return href: https://www.ftb.ca.gov/forms/2021/2021-540.pdf#page=2 - title: 2022 Form 540 California Resident Income Tax Return @@ -25,4 +28,3 @@ metadata: href: https://www.ftb.ca.gov/forms/2025/2025-540.pdf#page=2 - title: Cal. Rev. & Tax. Code § 17054 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17054.&nodeTreePath=3.20.2&lawCode=RTC - # Index according to federal tax parameter rules until we add California CPI trend. diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/rates/head_of_household.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/rates/head_of_household.yaml index d30bf8988a7..047a87869b9 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/rates/head_of_household.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/rates/head_of_household.yaml @@ -1,4 +1,4 @@ -description: California taxes income at these rates for head of household filers. +description: California taxes income at these rates for head of household filers. brackets: - threshold: 0000-01-01: 0 @@ -11,6 +11,7 @@ brackets: 2023-01-01: 20_839 2024-01-01: 21_527 2025-01-01: 22_173 + 2026-01-01: 22_927 metadata: uprating: gov.states.ca.cpi rate: @@ -22,6 +23,7 @@ brackets: 2023-01-01: 49_371 2024-01-01: 51_000 2025-01-01: 52_530 + 2026-01-01: 54_316 metadata: uprating: gov.states.ca.cpi rate: @@ -33,6 +35,7 @@ brackets: 2023-01-01: 63_644 2024-01-01: 65_744 2025-01-01: 67_716 + 2026-01-01: 70_018 metadata: uprating: gov.states.ca.cpi rate: @@ -44,6 +47,7 @@ brackets: 2023-01-01: 78_765 2024-01-01: 81_364 2025-01-01: 83_805 + 2026-01-01: 86_654 metadata: uprating: gov.states.ca.cpi rate: @@ -55,6 +59,7 @@ brackets: 2023-01-01: 93_037 2024-01-01: 96_107 2025-01-01: 98_990 + 2026-01-01: 102_356 metadata: uprating: gov.states.ca.cpi rate: @@ -66,6 +71,7 @@ brackets: 2023-01-01: 474_824 2024-01-01: 490_493 2025-01-01: 505_208 + 2026-01-01: 522_385 metadata: uprating: gov.states.ca.cpi rate: @@ -77,6 +83,7 @@ brackets: 2023-01-01: 569_790 2024-01-01: 588_593 2025-01-01: 606_251 + 2026-01-01: 626_864 metadata: uprating: gov.states.ca.cpi rate: @@ -88,6 +95,7 @@ brackets: 2023-01-01: 949_649 2024-01-01: 980_987 2025-01-01: 1_010_417 + 2026-01-01: 1_044_771 metadata: uprating: gov.states.ca.cpi rate: @@ -99,7 +107,9 @@ metadata: threshold_period: year type: marginal_rate label: California head of household income tax rate - reference: + reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: California Income Tax Rate Schedules for 2021 href: https://www.ftb.ca.gov/forms/2021/2021-540-tax-rate-schedules.pdf - title: California Income Tax Rate Schedules for 2022 @@ -112,4 +122,3 @@ metadata: href: https://www.ftb.ca.gov/forms/2025/2025-540-tax-rate-schedules.pdf - title: Cal. Rev. & Tax. Code § 17041 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17041.&lawCode=RTC - # Index according to federal tax parameter rules until we add California CPI trend. diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/rates/joint.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/rates/joint.yaml index db176716116..4b4b12d3344 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/rates/joint.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/rates/joint.yaml @@ -11,6 +11,7 @@ brackets: 2023-01-01: 20_824 2024-01-01: 21_512 2025-01-01: 22_158 + 2026-01-01: 22_912 metadata: uprating: gov.states.ca.cpi rate: @@ -22,6 +23,7 @@ brackets: 2023-01-01: 49_368 2024-01-01: 50_998 2025-01-01: 52_528 + 2026-01-01: 54_314 metadata: uprating: gov.states.ca.cpi rate: @@ -33,6 +35,7 @@ brackets: 2023-01-01: 77_918 2024-01-01: 80_490 2025-01-01: 82_904 + 2026-01-01: 85_722 metadata: uprating: gov.states.ca.cpi rate: @@ -44,6 +47,7 @@ brackets: 2023-01-01: 108_162 2024-01-01: 111_732 2025-01-01: 115_084 + 2026-01-01: 118_996 metadata: uprating: gov.states.ca.cpi rate: @@ -55,6 +59,7 @@ brackets: 2023-01-01: 136_700 2024-01-01: 141_212 2025-01-01: 145_448 + 2026-01-01: 150_394 metadata: uprating: gov.states.ca.cpi rate: @@ -66,6 +71,7 @@ brackets: 2023-01-01: 698_274 2024-01-01: 721_318 2025-01-01: 742_958 + 2026-01-01: 768_218 metadata: uprating: gov.states.ca.cpi rate: @@ -77,6 +83,7 @@ brackets: 2023-01-01: 837_922 2024-01-01: 865_574 2025-01-01: 891_542 + 2026-01-01: 921_854 metadata: uprating: gov.states.ca.cpi rate: @@ -88,6 +95,7 @@ brackets: 2023-01-01: 1_396_542 2024-01-01: 1_442_628 2025-01-01: 1_485_906 + 2026-01-01: 1_536_426 metadata: uprating: gov.states.ca.cpi rate: @@ -100,6 +108,8 @@ metadata: type: marginal_rate label: California joint income tax rate reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: California Income Tax Rate Schedules for 2021 href: https://www.ftb.ca.gov/forms/2021/2021-540-tax-rate-schedules.pdf - title: California Income Tax Rate Schedules for 2022 @@ -112,4 +122,3 @@ metadata: href: https://www.ftb.ca.gov/forms/2025/2025-540-tax-rate-schedules.pdf - title: Cal. Rev. & Tax. Code § 17041 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17041.&lawCode=RTC - # Index according to federal tax parameter rules until we add California CPI trend. diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/rates/separate.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/rates/separate.yaml index c5e1ae6154b..1649d690820 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/rates/separate.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/rates/separate.yaml @@ -11,6 +11,7 @@ brackets: 2023-01-01: 10_412 2024-01-01: 10_756 2025-01-01: 11_079 + 2026-01-01: 11_456 metadata: uprating: gov.states.ca.cpi rate: @@ -22,6 +23,7 @@ brackets: 2023-01-01: 24_684 2024-01-01: 25_499 2025-01-01: 26_264 + 2026-01-01: 27_157 metadata: uprating: gov.states.ca.cpi rate: @@ -33,6 +35,7 @@ brackets: 2023-01-01: 38_959 2024-01-01: 40_245 2025-01-01: 41_452 + 2026-01-01: 42_861 metadata: uprating: gov.states.ca.cpi rate: @@ -44,6 +47,7 @@ brackets: 2023-01-01: 54_081 2024-01-01: 55_866 2025-01-01: 57_542 + 2026-01-01: 59_498 metadata: uprating: gov.states.ca.cpi rate: @@ -55,6 +59,7 @@ brackets: 2023-01-01: 68_350 2024-01-01: 70_606 2025-01-01: 72_724 + 2026-01-01: 75_197 metadata: uprating: gov.states.ca.cpi rate: @@ -66,6 +71,7 @@ brackets: 2023-01-01: 349_137 2024-01-01: 360_659 2025-01-01: 371_479 + 2026-01-01: 384_109 metadata: uprating: gov.states.ca.cpi rate: @@ -77,6 +83,7 @@ brackets: 2023-01-01: 418_961 2024-01-01: 432_787 2025-01-01: 445_771 + 2026-01-01: 460_927 metadata: uprating: gov.states.ca.cpi rate: @@ -88,6 +95,7 @@ brackets: 2023-01-01: 698_271 2024-01-01: 721_314 2025-01-01: 742_953 + 2026-01-01: 768_213 metadata: uprating: gov.states.ca.cpi rate: @@ -100,6 +108,8 @@ metadata: type: marginal_rate label: California separate income tax rate reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: California Income Tax Rate Schedules for 2021 href: https://www.ftb.ca.gov/forms/2021/2021-540-tax-rate-schedules.pdf - title: California Income Tax Rate Schedules for 2022 @@ -112,4 +122,3 @@ metadata: href: https://www.ftb.ca.gov/forms/2025/2025-540-tax-rate-schedules.pdf - title: Cal. Rev. & Tax. Code § 17041 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17041.&lawCode=RTC - # Index according to federal tax parameter rules until we add California CPI trend. diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/rates/single.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/rates/single.yaml index 356ddee849b..28fd7e9112d 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/rates/single.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/rates/single.yaml @@ -11,6 +11,7 @@ brackets: 2023-01-01: 10_412 2024-01-01: 10_756 2025-01-01: 11_079 + 2026-01-01: 11_456 metadata: uprating: gov.states.ca.cpi rate: @@ -22,6 +23,7 @@ brackets: 2023-01-01: 24_684 2024-01-01: 25_499 2025-01-01: 26_264 + 2026-01-01: 27_157 metadata: uprating: gov.states.ca.cpi rate: @@ -33,6 +35,7 @@ brackets: 2023-01-01: 38_959 2024-01-01: 40_245 2025-01-01: 41_452 + 2026-01-01: 42_861 metadata: uprating: gov.states.ca.cpi rate: @@ -44,6 +47,7 @@ brackets: 2023-01-01: 54_081 2024-01-01: 55_866 2025-01-01: 57_542 + 2026-01-01: 59_498 metadata: uprating: gov.states.ca.cpi rate: @@ -55,6 +59,7 @@ brackets: 2023-01-01: 68_350 2024-01-01: 70_606 2025-01-01: 72_724 + 2026-01-01: 75_197 metadata: uprating: gov.states.ca.cpi rate: @@ -66,6 +71,7 @@ brackets: 2023-01-01: 349_137 2024-01-01: 360_659 2025-01-01: 371_479 + 2026-01-01: 384_109 metadata: uprating: gov.states.ca.cpi rate: @@ -77,6 +83,7 @@ brackets: 2023-01-01: 418_961 2024-01-01: 432_787 2025-01-01: 445_771 + 2026-01-01: 460_927 metadata: uprating: gov.states.ca.cpi rate: @@ -88,6 +95,7 @@ brackets: 2023-01-01: 698_271 2024-01-01: 721_314 2025-01-01: 742_953 + 2026-01-01: 768_213 metadata: uprating: gov.states.ca.cpi rate: @@ -100,6 +108,8 @@ metadata: type: marginal_rate label: California single income tax rate reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: California Income Tax Rate Schedules for 2021 href: https://www.ftb.ca.gov/forms/2021/2021-540-tax-rate-schedules.pdf - title: California Income Tax Rate Schedules for 2022 @@ -112,4 +122,3 @@ metadata: href: https://www.ftb.ca.gov/forms/2025/2025-540-tax-rate-schedules.pdf - title: Cal. Rev. & Tax. Code § 17041 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17041.&lawCode=RTC - # Index according to federal tax parameter rules until we add California CPI trend. diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/rates/surviving_spouse.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/rates/surviving_spouse.yaml index 1553538f47b..8a25ba78f64 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/rates/surviving_spouse.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/rates/surviving_spouse.yaml @@ -11,6 +11,7 @@ brackets: 2023-01-01: 20_824 2024-01-01: 21_512 2025-01-01: 22_158 + 2026-01-01: 22_912 metadata: uprating: gov.states.ca.cpi rate: @@ -22,6 +23,7 @@ brackets: 2023-01-01: 49_368 2024-01-01: 50_998 2025-01-01: 52_528 + 2026-01-01: 54_314 metadata: uprating: gov.states.ca.cpi rate: @@ -33,6 +35,7 @@ brackets: 2023-01-01: 77_918 2024-01-01: 80_490 2025-01-01: 82_904 + 2026-01-01: 85_722 metadata: uprating: gov.states.ca.cpi rate: @@ -44,6 +47,7 @@ brackets: 2023-01-01: 108_162 2024-01-01: 111_732 2025-01-01: 115_084 + 2026-01-01: 118_996 metadata: uprating: gov.states.ca.cpi rate: @@ -55,6 +59,7 @@ brackets: 2023-01-01: 136_700 2024-01-01: 141_212 2025-01-01: 145_448 + 2026-01-01: 150_394 metadata: uprating: gov.states.ca.cpi rate: @@ -66,6 +71,7 @@ brackets: 2023-01-01: 698_274 2024-01-01: 721_318 2025-01-01: 742_958 + 2026-01-01: 768_218 metadata: uprating: gov.states.ca.cpi rate: @@ -77,6 +83,7 @@ brackets: 2023-01-01: 837_922 2024-01-01: 865_574 2025-01-01: 891_542 + 2026-01-01: 921_854 metadata: uprating: gov.states.ca.cpi rate: @@ -88,6 +95,7 @@ brackets: 2023-01-01: 1_396_542 2024-01-01: 1_442_628 2025-01-01: 1_485_906 + 2026-01-01: 1_536_426 metadata: uprating: gov.states.ca.cpi rate: @@ -100,6 +108,8 @@ metadata: type: marginal_rate label: California surviving spouse income tax rate reference: + - title: 2026 California indexing (FTB Tax News, October 2026) + href: https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 - title: California Income Tax Rate Schedules for 2021 href: https://www.ftb.ca.gov/forms/2021/2021-540-tax-rate-schedules.pdf - title: California Income Tax Rate Schedules for 2022 @@ -112,4 +122,3 @@ metadata: href: https://www.ftb.ca.gov/forms/2025/2025-540-tax-rate-schedules.pdf - title: Cal. Rev. & Tax. Code § 17041 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17041.&lawCode=RTC - # Index according to federal tax parameter rules until we add California CPI trend. diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/deductions/standard/additional.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/deductions/standard/additional.yaml index 00f4c0e40df..70e5bf3dc5e 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/deductions/standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/deductions/standard/additional.yaml @@ -1,13 +1,10 @@ +# Values after the last published anchor are computed estimates until VT publishes them. description: Vermont provides this additional standard deduction amount for each aged or blind head or spouse. metadata: label: Vermont additional aged or blind, head or spouse, standard deduction amount period: year unit: currency-USD - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null reference: - title: 2021 VERMONT Income Tax Return Form Instructions-Taxable Income Line 4 href: https://tax.vermont.gov/sites/tax/files/documents/Income-Booklet-2021.pdf#page=10 diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/deductions/standard/base.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/deductions/standard/base.yaml index 67926f7a02e..90410ea634c 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/deductions/standard/base.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/deductions/standard/base.yaml @@ -1,11 +1,8 @@ +# Values after the last published anchor are computed estimates until VT publishes them. description: Vermont provides this standard deduction based on filing status. metadata: propagate_metadata_to_children: true - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null label: Vermont standard deduction period: year unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/exemption/personal.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/exemption/personal.yaml index efbaabd3fa7..acf7812a8b1 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/exemption/personal.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/exemption/personal.yaml @@ -1,3 +1,4 @@ +# Values after the last published anchor are computed estimates until VT publishes them. description: Vermont provides the following personal exemption amount. values: 2021-01-01: 4_350 @@ -9,11 +10,7 @@ metadata: unit: currency-USD period: year label: Vermont personal exemption amount - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null reference: # Legal code specifies $4,150. Date unknown. - title: Legal Code Titl. 32 V.S.A. § 5811(21)(C)(i) diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/rates/head_of_household.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/rates/head_of_household.yaml index 89a0cbd4519..9fbec6c0cb5 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/rates/head_of_household.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/rates/head_of_household.yaml @@ -5,6 +5,8 @@ metadata: rate_unit: /1 label: Vermont income tax rates head of household filers reference: + - title: 2026 Preliminary Vermont Tax Rates (estimated tax instructions, not final schedule) + href: https://tax.vermont.gov/sites/tax/files/documents/IN-114-Instr-2026.pdf#page=2 # Law does not specify inflation adjusted thresholds for each year - title: Vermont §5822. Tax on income of individuals, estates, and trusts href: https://legislature.vermont.gov/statutes/section/32/151/05822 @@ -17,7 +19,7 @@ metadata: - title: Vermont 2024 Income Tax Return Booklet Forms and Instructions href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2024.pdf#page=1 - title: Vermont 2025 Income Tax Rate Schedules - href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2025.pdf#page=1 + href: https://tax.vermont.gov/sites/tax/files/documents/TaxRateSched-2025.pdf#page=1 brackets: - threshold: 2021-01-01: 0 @@ -30,12 +32,9 @@ brackets: 2023-01-01: 60_850 2024-01-01: 64_200 2025-01-01: 66_200 + 2026-01-01: 68_000 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2021-01-01: 0.066 - threshold: @@ -45,12 +44,9 @@ brackets: 2023-01-01: 157_150 2024-01-01: 165_700 2025-01-01: 171_000 + 2026-01-01: 175_500 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2021-01-01: 0.076 - threshold: @@ -60,11 +56,8 @@ brackets: 2023-01-01: 254_500 2024-01-01: 268_300 2025-01-01: 276_850 + 2026-01-01: 284_150 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2021-01-01: 0.0875 diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/rates/joint.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/rates/joint.yaml index 28687429d7d..b8f907b31ac 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/rates/joint.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/rates/joint.yaml @@ -5,6 +5,8 @@ metadata: rate_unit: /1 label: Vermont State income tax rates for joint filers reference: + - title: 2026 Preliminary Vermont Tax Rates (estimated tax instructions, not final schedule) + href: https://tax.vermont.gov/sites/tax/files/documents/IN-114-Instr-2026.pdf#page=2 # Law does not specify inflation adjusted thresholds for each year - title: Vermont §5822. Tax on income of individuals, estates, and trusts href: https://legislature.vermont.gov/statutes/section/32/151/05822 @@ -17,7 +19,7 @@ metadata: - title: Vermont 2024 Income Tax Return Booklet Forms and Instructions href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2024.pdf#page=1 - title: Vermont 2025 Income Tax Rate Schedules - href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2025.pdf#page=1 + href: https://tax.vermont.gov/sites/tax/files/documents/TaxRateSched-2025.pdf#page=1 brackets: - threshold: 2021-01-01: 0 @@ -30,12 +32,9 @@ brackets: 2023-01-01: 75_850 2024-01-01: 79_950 2025-01-01: 82_500 + 2026-01-01: 84_700 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2021-01-01: 0.066 - threshold: @@ -45,12 +44,9 @@ brackets: 2023-01-01: 183_400 2024-01-01: 193_300 2025-01-01: 199_450 + 2026-01-01: 204_750 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2021-01-01: 0.076 - threshold: @@ -60,11 +56,8 @@ brackets: 2023-01-01: 279_450 2024-01-01: 294_600 2025-01-01: 304_000 + 2026-01-01: 312_050 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2021-01-01: 0.0875 diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/rates/separate.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/rates/separate.yaml index 473711b6f8c..6df2537f06c 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/rates/separate.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/rates/separate.yaml @@ -5,6 +5,8 @@ metadata: rate_unit: /1 label: Vermont income tax rates separate filers reference: + - title: 2026 Preliminary Vermont Tax Rates (estimated tax instructions, not final schedule) + href: https://tax.vermont.gov/sites/tax/files/documents/IN-114-Instr-2026.pdf#page=2 # Law does not specify inflation adjusted thresholds for each year - title: Vermont §5822. Tax on income of individuals, estates, and trusts href: https://legislature.vermont.gov/statutes/section/32/151/05822 @@ -17,7 +19,7 @@ metadata: - title: Vermont 2024 Income Tax Return Booklet Forms and Instructions href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2024.pdf#page=1 - title: Vermont 2025 Income Tax Rate Schedules - href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2025.pdf#page=1 + href: https://tax.vermont.gov/sites/tax/files/documents/TaxRateSched-2025.pdf#page=1 brackets: - threshold: 2021-01-01: 0 @@ -30,12 +32,9 @@ brackets: 2023-01-01: 37_925 2024-01-01: 39_975 2025-01-01: 41_250 + 2026-01-01: 42_350 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2022-01-01: 0.066 - threshold: @@ -45,12 +44,9 @@ brackets: 2023-01-01: 91_700 2024-01-01: 96_650 2025-01-01: 99_725 + 2026-01-01: 102_375 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2022-01-01: 0.076 - threshold: @@ -60,11 +56,8 @@ brackets: 2023-01-01: 139_725 2024-01-01: 147_300 2025-01-01: 152_000 + 2026-01-01: 156_025 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2022-01-01: 0.0875 diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/rates/single.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/rates/single.yaml index 31acac1ca86..f4ea4752198 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/rates/single.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/rates/single.yaml @@ -5,6 +5,8 @@ metadata: rate_unit: /1 label: Vermont income tax rates single filers reference: + - title: 2026 Preliminary Vermont Tax Rates (estimated tax instructions, not final schedule) + href: https://tax.vermont.gov/sites/tax/files/documents/IN-114-Instr-2026.pdf#page=2 # Law does not specify inflation adjusted thresholds for each year - title: Vermont §5822. Tax on income of individuals, estates, and trusts href: https://legislature.vermont.gov/statutes/section/32/151/05822 @@ -17,7 +19,7 @@ metadata: - title: Vermont 2024 Income Tax Return Booklet Forms and Instructions href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2024.pdf#page=1 - title: Vermont 2025 Income Tax Rate Schedules - href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2025.pdf#page=1 + href: https://tax.vermont.gov/sites/tax/files/documents/TaxRateSched-2025.pdf#page=1 brackets: - threshold: 2021-01-01: 0 @@ -30,12 +32,9 @@ brackets: 2023-01-01: 45_400 2024-01-01: 47_900 2025-01-01: 49_400 + 2026-01-01: 50_750 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2022-01-01: 0.066 - threshold: @@ -45,12 +44,9 @@ brackets: 2023-01-01: 110_050 2024-01-01: 116_000 2025-01-01: 119_700 + 2026-01-01: 122_850 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2022-01-01: 0.076 - threshold: @@ -60,11 +56,8 @@ brackets: 2023-01-01: 229_550 2024-01-01: 242_000 2025-01-01: 249_700 + 2026-01-01: 256_300 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2022-01-01: 0.0875 diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/rates/surviving_spouse.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/rates/surviving_spouse.yaml index 13ec5f954d7..3e39255d97b 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/rates/surviving_spouse.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/rates/surviving_spouse.yaml @@ -5,6 +5,8 @@ metadata: rate_unit: /1 label: Vermont income tax rates surviving spouse filers reference: + - title: 2026 Preliminary Vermont Tax Rates (estimated tax instructions, not final schedule) + href: https://tax.vermont.gov/sites/tax/files/documents/IN-114-Instr-2026.pdf#page=2 # Law does not specify inflation adjusted thresholds for each year - title: Vermont §5822. Tax on income of individuals, estates, and trusts href: https://legislature.vermont.gov/statutes/section/32/151/05822 @@ -17,7 +19,7 @@ metadata: - title: Vermont 2024 Income Tax Return Booklet Forms and Instructions href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2024.pdf#page=1 - title: Vermont 2025 Income Tax Rate Schedules - href: https://tax.vermont.gov/sites/tax/files/documents/RateSched-2025.pdf#page=1 + href: https://tax.vermont.gov/sites/tax/files/documents/TaxRateSched-2025.pdf#page=1 brackets: - threshold: 2021-01-01: 0 @@ -30,12 +32,9 @@ brackets: 2023-01-01: 75_850 2024-01-01: 79_950 2025-01-01: 82_500 + 2026-01-01: 84_700 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2022-01-01: 0.066 - threshold: @@ -45,12 +44,9 @@ brackets: 2023-01-01: 183_400 2024-01-01: 193_300 2025-01-01: 199_450 + 2026-01-01: 204_750 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2021-01-01: 0.076 - threshold: @@ -60,11 +56,8 @@ brackets: 2023-01-01: 279_450 2024-01-01: 294_600 2025-01-01: 304_000 + 2026-01-01: 312_050 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: downwards - interval: 50 + uprating: null rate: 2021-01-01: 0.0875 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/max.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/max.yaml index 356fbb3d41f..d2129277fdd 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/max.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/max.yaml @@ -5,15 +5,13 @@ metadata: - filing_status period: year unit: currency-USD - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + # Wisconsin indexes from statutory bases using prior-August NSA CPI-U. + uprating: null propagate_metadata_to_children: true reference: - # The legal code includes uprating. - - title: Wisconsin Statutes 71.07 (9)(b)(5) + - title: Wisconsin Statutes 71.05(22)(dp) - Standard deduction limits + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dp + - title: Wisconsin Statutes 71.05(22)(dt) - Standard deduction indexing href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dt - title: eFile.com, Wisconsin Tax Brackets, Rates, Forms, and Standard Deductions (third party, archived January 2025; the only cited source for 2021) href: https://web.archive.org/web/20250119123144/https://www.efile.com/wisconsin-tax-brackets-rates-and-forms/ @@ -25,45 +23,70 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: 2025 Form 1-ES instructions, Standard Deduction Table href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=3 - - title: 2026 Form 1-ES instructions, 2026 Standard Deduction schedules - href: https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=2 - title: 2024 Form 1 instructions, Standard Deduction Table href: https://www.revenue.wi.gov/TaxForms2024/2024-Form1-inst.pdf#page=35 - title: 2025 Form 1 instructions, Standard Deduction Table href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-inst.pdf#page=35 - + - title: 2026 Form 1-ES instructions, Standard Deduction Schedules + href: https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=2 + SINGLE: - 2021-01-01: 11_200 - 2022-01-01: 11_790 - 2023-01-01: 12_760 - 2024-01-01: 13_230 - 2025-01-01: 13_560 - 2026-01-01: 13_960 + values: + 2021-01-01: 11_200 + 2022-01-01: 11_790 + 2023-01-01: 12_760 + 2024-01-01: 13_230 + 2025-01-01: 13_560 + 2026-01-01: 13_960 + metadata: + wisconsin_indexing: + base: 7_200 + base_year: 1999 JOINT: - 2021-01-01: 20_730 - 2022-01-01: 21_820 - 2023-01-01: 23_620 - 2024-01-01: 24_490 - 2025-01-01: 25_110 - 2026-01-01: 25_840 + values: + 2021-01-01: 20_730 + 2022-01-01: 21_820 + 2023-01-01: 23_620 + 2024-01-01: 24_490 + 2025-01-01: 25_110 + 2026-01-01: 25_840 + metadata: + wisconsin_indexing: + base: 19_010 + base_year: 2015 SURVIVING_SPOUSE: - 2021-01-01: 20_730 - 2022-01-01: 21_820 - 2023-01-01: 23_620 - 2024-01-01: 24_490 - 2025-01-01: 25_110 - 2026-01-01: 25_840 + values: + 2021-01-01: 20_730 + 2022-01-01: 21_820 + 2023-01-01: 23_620 + 2024-01-01: 24_490 + 2025-01-01: 25_110 + 2026-01-01: 25_840 + metadata: + wisconsin_indexing: + base: 19_010 + base_year: 2015 SEPARATE: - 2021-01-01: 9_850 - 2022-01-01: 10_370 - 2023-01-01: 11_220 - 2024-01-01: 11_630 - 2025-01-01: 11_930 - 2026-01-01: 12_280 + values: + 2021-01-01: 9_850 + 2022-01-01: 10_370 + 2023-01-01: 11_220 + 2024-01-01: 11_630 + 2025-01-01: 11_930 + 2026-01-01: 12_280 + metadata: + wisconsin_indexing: + base: 9_030 + base_year: 2015 HEAD_OF_HOUSEHOLD: - 2021-01-01: 14_470 - 2022-01-01: 15_230 - 2023-01-01: 16_480 - 2024-01-01: 17_090 - 2025-01-01: 17_520 - 2026-01-01: 18_030 + values: + 2021-01-01: 14_470 + 2022-01-01: 15_230 + 2023-01-01: 16_480 + 2024-01-01: 17_090 + 2025-01-01: 17_520 + 2026-01-01: 18_030 + metadata: + wisconsin_indexing: + base: 9_300 + base_year: 1999 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/head_of_household.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/head_of_household.yaml index 2cd5ab896ef..77000aea155 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/head_of_household.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/head_of_household.yaml @@ -2,7 +2,7 @@ description: Wisconsin phases out its standard deduction for head of household f metadata: type: marginal_rate threshold_period: year - threshold_unit: currency-USD + threshold_unit: currency-USD rate_unit: /1 label: Wisconsin standard deduction head of household phase out reference: @@ -16,13 +16,12 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: 2025 Form 1-ES instructions, Standard Deduction Table href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=3 - - title: 2026 Form 1-ES instructions, 2026 Standard Deduction schedules + - title: Wisconsin Statutes 71.05(22)(dp) - Standard deduction limits + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dp + - title: Wisconsin Statutes 71.05(22)(dt) - Standard deduction indexing + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dt + - title: 2026 Form 1-ES instructions, Standard Deduction Schedules href: https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=2 - # The legal code provides inflaton unadjusted amounts - - title: Wisconsin Statutes 71.07 (9)(b)(5) - href: https://docs.legis.wisconsin.gov/2023/statutes/statutes/71/i/05/22/dm - # Form 1 instructions give only a standard deduction table. The Form 1-ES instructions - # and the Tax Exemption Devices reports state the phase-out starts and rates. brackets: - threshold: @@ -38,11 +37,10 @@ brackets: 2025-01-01: 19_550 2026-01-01: 20_120 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 10_380 + base_year: 1999 rate: 2021-01-01: 0.22515 - threshold: @@ -54,6 +52,8 @@ brackets: 2025-01-01: 57_210 2026-01-01: 58_827 metadata: - uprating: gov.irs.uprating + uprating: null + wisconsin_indexing: + kind: head_of_household_crossover rate: 2021-01-01: 0.12 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/joint.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/joint.yaml index 19724f899aa..f200a0ea1b5 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/joint.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/joint.yaml @@ -2,7 +2,7 @@ description: Wisconsin phases out its standard deduction for joint filers accord metadata: type: marginal_rate threshold_period: year - threshold_unit: currency-USD + threshold_unit: currency-USD rate_unit: /1 label: Wisconsin standard deduction joint phase out reference: @@ -16,13 +16,12 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: 2025 Form 1-ES instructions, Standard Deduction Table href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=3 - - title: 2026 Form 1-ES instructions, 2026 Standard Deduction schedules + - title: Wisconsin Statutes 71.05(22)(dp) - Standard deduction limits + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dp + - title: Wisconsin Statutes 71.05(22)(dt) - Standard deduction indexing + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dt + - title: 2026 Form 1-ES instructions, Standard Deduction Schedules href: https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=2 - # The legal code provides inflaton unadjusted amounts - - title: Wisconsin Statutes 71.07 (9)(b)(5) - href: https://docs.legis.wisconsin.gov/2023/statutes/statutes/71/i/05/22/dm - # Form 1 instructions give only a standard deduction table. The Form 1-ES instructions - # and the Tax Exemption Devices reports state the phase-out starts and rates. brackets: - threshold: @@ -38,10 +37,9 @@ brackets: 2025-01-01: 28_210 2026-01-01: 29_040 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 21_360 + base_year: 2015 rate: 2021-01-01: 0.19778 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/separate.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/separate.yaml index bb94f04721d..438166f2188 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/separate.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/separate.yaml @@ -16,13 +16,12 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: 2025 Form 1-ES instructions, Standard Deduction Table href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=3 - - title: 2026 Form 1-ES instructions, 2026 Standard Deduction schedules + - title: Wisconsin Statutes 71.05(22)(dp) - Standard deduction limits + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dp + - title: Wisconsin Statutes 71.05(22)(dt) - Standard deduction indexing + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dt + - title: 2026 Form 1-ES instructions, Standard Deduction Schedules href: https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=2 - # The legal code provides inflaton unadjusted amounts - - title: Wisconsin Statutes 71.07 (9)(b)(5) - href: https://docs.legis.wisconsin.gov/2023/statutes/statutes/71/i/05/22/dm - # Form 1 instructions give only a standard deduction table. The Form 1-ES instructions - # and the Tax Exemption Devices reports state the phase-out starts and rates. brackets: - threshold: @@ -38,10 +37,9 @@ brackets: 2025-01-01: 13_390 2026-01-01: 13_780 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 10_140 + base_year: 2015 rate: 2021-01-01: 0.19778 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/single.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/single.yaml index b0af1234aa3..5bbb6f117e4 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/single.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/deductions/standard/phase_out/single.yaml @@ -2,7 +2,7 @@ description: Wisconsin phases out its standard deduction for single filers accor metadata: type: marginal_rate threshold_period: year - threshold_unit: currency-USD + threshold_unit: currency-USD rate_unit: /1 label: Wisconsin standard deduction single phase out reference: @@ -16,13 +16,12 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: 2025 Form 1-ES instructions, Standard Deduction Table href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=3 - - title: 2026 Form 1-ES instructions, 2026 Standard Deduction schedules + - title: Wisconsin Statutes 71.05(22)(dp) - Standard deduction limits + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dp + - title: Wisconsin Statutes 71.05(22)(dt) - Standard deduction indexing + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22/dt + - title: 2026 Form 1-ES instructions, Standard Deduction Schedules href: https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=2 - # The legal code provides inflaton unadjusted amounts - - title: Wisconsin Statutes 71.07 (9)(b)(5) - href: https://docs.legis.wisconsin.gov/2023/statutes/statutes/71/i/05/22/dm - # Form 1 instructions give only a standard deduction table. The Form 1-ES instructions - # and the Tax Exemption Devices reports state the phase-out starts and rates. brackets: - threshold: @@ -38,10 +37,9 @@ brackets: 2025-01-01: 19_550 2026-01-01: 20_120 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 10_380 + base_year: 1999 rate: 2021-01-01: 0.12 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/rates/head_of_household.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/rates/head_of_household.yaml index 3bb39ed9f66..1a8c19c93c4 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/rates/head_of_household.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/rates/head_of_household.yaml @@ -6,6 +6,10 @@ metadata: rate_unit: /1 label: Wisconsin head of household income tax rate reference: + - title: Wisconsin Statutes 71.06(2e)(bm) and (c) - Bracket indexing and rounding + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/06/2e + - title: 2025 Form 1-ES instructions, Tax Rate Schedules + href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=4 - title: eFile.com, Wisconsin Tax Brackets, Rates, Forms, and Standard Deductions (third party, archived January 2025; the only cited source for 2021) href: https://web.archive.org/web/20250119123144/https://www.efile.com/wisconsin-tax-brackets-rates-and-forms/ - title: Wisconsin Department of Revenue, Tax Exemption Devices 2023-25, Individual Income Tax (2022 tax year) @@ -14,7 +18,6 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: State of Wisconsin Department of Revenue href: https://www.revenue.wi.gov/Pages/FAQS/pcs-taxrates.aspx - # The tax form only shows the tax brackets, not the exact rates. - title: 2023 I-010 Form 1 instructions href: https://www.revenue.wi.gov/TaxForms2023/2023-Form1-Inst.pdf#page=39 - title: 2024 Form 1 instructions @@ -40,11 +43,10 @@ brackets: 2025-01-01: 14_680 2026-01-01: 15_110 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 14_680 + base_year: 2024 rate: 2021-01-01: 0.0465 2023-01-01: 0.044 @@ -57,11 +59,10 @@ brackets: 2025-01-01: 50_480 2026-01-01: 51_950 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 50_480 + base_year: 2024 rate: 2021-01-01: 0.053 - threshold: @@ -73,10 +74,9 @@ brackets: 2025-01-01: 323_290 2026-01-01: 332_720 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 323_290 + base_year: 2024 rate: 2021-01-01: 0.0765 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/rates/joint.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/rates/joint.yaml index f24804ab687..87fbdaa74c4 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/rates/joint.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/rates/joint.yaml @@ -6,6 +6,10 @@ metadata: rate_unit: /1 label: Wisconsin joint income tax rate reference: + - title: Wisconsin Statutes 71.06(2e)(bm) and (c) - Bracket indexing and rounding + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/06/2e + - title: 2025 Form 1-ES instructions, Tax Rate Schedules + href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=4 - title: eFile.com, Wisconsin Tax Brackets, Rates, Forms, and Standard Deductions (third party, archived January 2025; the only cited source for 2021) href: https://web.archive.org/web/20250119123144/https://www.efile.com/wisconsin-tax-brackets-rates-and-forms/ - title: Wisconsin Department of Revenue, Tax Exemption Devices 2023-25, Individual Income Tax (2022 tax year) @@ -14,7 +18,6 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: State of Wisconsin Department of Revenue href: https://www.revenue.wi.gov/Pages/FAQS/pcs-taxrates.aspx - # The tax form only shows the tax brackets, not the exact rates. - title: 2023 I-010 Form 1 instructions href: https://www.revenue.wi.gov/TaxForms2023/2023-Form1-Inst.pdf#page=39 - title: 2024 Form 1 instructions @@ -40,11 +43,10 @@ brackets: 2025-01-01: 19_580 2026-01-01: 20_150 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 19_580 + base_year: 2024 rate: 2021-01-01: 0.0465 2023-01-01: 0.044 @@ -57,11 +59,10 @@ brackets: 2025-01-01: 67_300 2026-01-01: 69_260 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 67_300 + base_year: 2024 rate: 2021-01-01: 0.053 - threshold: @@ -73,10 +74,9 @@ brackets: 2025-01-01: 431_060 2026-01-01: 443_630 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 431_060 + base_year: 2024 rate: 2021-01-01: 0.0765 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/rates/separate.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/rates/separate.yaml index 31b6b84fd76..0d1952fa76a 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/rates/separate.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/rates/separate.yaml @@ -6,6 +6,10 @@ metadata: rate_unit: /1 label: Wisconsin separate income tax rate reference: + - title: Wisconsin Statutes 71.06(2e)(bm) and (c) - Bracket indexing and rounding + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/06/2e + - title: 2025 Form 1-ES instructions, Tax Rate Schedules + href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=4 - title: eFile.com, Wisconsin Tax Brackets, Rates, Forms, and Standard Deductions (third party, archived January 2025; the only cited source for 2021) href: https://web.archive.org/web/20250119123144/https://www.efile.com/wisconsin-tax-brackets-rates-and-forms/ - title: Wisconsin Department of Revenue, Tax Exemption Devices 2023-25, Individual Income Tax (2022 tax year) @@ -14,7 +18,6 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: State of Wisconsin Department of Revenue href: https://www.revenue.wi.gov/Pages/FAQS/pcs-taxrates.aspx - # The tax form only shows the tax brackets, not the exact rates. - title: 2023 I-010 Form 1 instructions href: https://www.revenue.wi.gov/TaxForms2023/2023-Form1-Inst.pdf#page=39 - title: 2024 Form 1 instructions @@ -40,11 +43,10 @@ brackets: 2025-01-01: 9_790 2026-01-01: 10_080 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 9_790 + base_year: 2024 rate: 2021-01-01: 0.0465 2023-01-01: 0.044 @@ -57,11 +59,10 @@ brackets: 2025-01-01: 33_650 2026-01-01: 34_630 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 33_650 + base_year: 2024 rate: 2021-01-01: 0.053 - threshold: @@ -73,10 +74,9 @@ brackets: 2025-01-01: 215_530 2026-01-01: 221_820 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 215_530 + base_year: 2024 rate: 2021-01-01: 0.0765 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/rates/single.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/rates/single.yaml index 00bdc32bd70..572dce1d2fe 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/rates/single.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/rates/single.yaml @@ -6,6 +6,10 @@ metadata: rate_unit: /1 label: Wisconsin single income tax rate reference: + - title: Wisconsin Statutes 71.06(2e)(bm) and (c) - Bracket indexing and rounding + href: https://docs.legis.wisconsin.gov/statutes/statutes/71/i/06/2e + - title: 2025 Form 1-ES instructions, Tax Rate Schedules + href: https://www.revenue.wi.gov/TaxForms2025/2025-Form1-ES-Inst.pdf#page=4 - title: eFile.com, Wisconsin Tax Brackets, Rates, Forms, and Standard Deductions (third party, archived January 2025; the only cited source for 2021) href: https://web.archive.org/web/20250119123144/https://www.efile.com/wisconsin-tax-brackets-rates-and-forms/ - title: Wisconsin Department of Revenue, Tax Exemption Devices 2023-25, Individual Income Tax (2022 tax year) @@ -14,7 +18,6 @@ metadata: href: https://www.revenue.wi.gov/DORReports/25sumrpt.pdf#page=9 - title: State of Wisconsin Department of Revenue href: https://www.revenue.wi.gov/Pages/FAQS/pcs-taxrates.aspx - # The tax form only shows the tax brackets, not the exact rates. - title: 2023 I-010 Form 1 instructions href: https://www.revenue.wi.gov/TaxForms2023/2023-Form1-Inst.pdf#page=39 - title: 2024 Form 1 instructions @@ -40,11 +43,10 @@ brackets: 2025-01-01: 14_680 2026-01-01: 15_110 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 14_680 + base_year: 2024 rate: 2021-01-01: 0.0465 2023-01-01: 0.044 @@ -57,11 +59,10 @@ brackets: 2025-01-01: 50_480 2026-01-01: 51_950 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 50_480 + base_year: 2024 rate: 2021-01-01: 0.053 - threshold: @@ -73,10 +74,9 @@ brackets: 2025-01-01: 323_290 2026-01-01: 332_720 metadata: - uprating: - parameter: gov.irs.uprating - rounding: - type: nearest - interval: 10 + uprating: null + wisconsin_indexing: + base: 323_290 + base_year: 2024 rate: 2021-01-01: 0.0765 diff --git a/policyengine_us/parameters/uprating_extensions.py b/policyengine_us/parameters/uprating_extensions.py index 3cc564105a8..7bc1136acfe 100644 --- a/policyengine_us/parameters/uprating_extensions.py +++ b/policyengine_us/parameters/uprating_extensions.py @@ -22,18 +22,11 @@ ) -def get_irs_cpi(parameters: ParameterNode, year: int) -> float: - """Calculate IRS CPI based on Chained CPI-U average from Sep to Aug.""" - cpi = parameters.gov.bls.cpi.c_cpi_u - end = instant(f"{year}-08-01") - start = end.offset(-MONTHS_IN_YEAR, MONTH) - monthly_cpi_values = [] - for month in range(MONTHS_IN_YEAR): - monthly_cpi_values += [cpi(start.offset(month, MONTH))] - return sum(monthly_cpi_values) / MONTHS_IN_YEAR - - -def get_average_for_12_months_ending_august(cpi: Parameter, year: int) -> float: +def get_average_for_12_months_ending_august( + cpi: Parameter, + year: int, + projection: Parameter, +) -> float: """Average a monthly price index over the 12 months ending August 31. Covers September of ``year - 1`` through August of ``year``: the @@ -41,14 +34,29 @@ def get_average_for_12_months_ending_august(cpi: Parameter, year: int) -> float: ORS 315.273(5). The BLS index series hold monthly observations through the latest BLS - release, then annual projection points at February instants; a monthly - refresh that reaches a February replaces that instant's projection with - the observed value. Windows with observed months average them, carrying - the last observation flat through any unobserved tail; windows with no - observed month read the year's annual projection point, whose - February instant necessarily lies beyond the last observation and so - can only hold a projection. No branch reads an instant a refresh could - have turned from projection into observation. + release, then (for the seasonally adjusted and chained series) CBO's + calendar-year averages at February instants; a monthly refresh that + reaches a February replaces that instant's projection with the observed + value. Windows with no observed month read ``projection``, CBO's + projection of this 12-month average keyed by the tax year it indexes + (``year + 1``); a calendar-year average would run about four months of + inflation high. + + Windows with observed months average them, and complete any month + without an observation with the latest value published before it. Those + completed months are estimates, not observations, and the model's + completion policy rather than a statutory or agency rule: + + - a month BLS did not publish inside the observed range takes the prior + month's value (October 2025, lost to the 2025 lapse in + appropriations, takes September 2025's); + - each month after the last observation takes the last observation, so + the unobserved tail of the latest window is held flat. + + The levels averaged are those in the parameter file, one vintage per + month. Where BLS revises a series after first publication (the C-CPI-U + moves from initial to interim to final estimates), that vintage need not + be the one a statute reads; see ``get_irs_cpi``. """ # February instants can hold annual projections, so only non-February # instants identify the end of the observed monthly series (one month @@ -59,20 +67,42 @@ def get_average_for_12_months_ending_august(cpi: Parameter, year: int) -> float: if not value.instant_str.endswith("-02-01") ) window_start = instant(f"{year - 1}-09-01") + if window_start > last_observation: + return projection(f"{year + 1}-01-01") window_months = [ window_start.offset(month, MONTH) for month in range(MONTHS_IN_YEAR) ] - observed = [month for month in window_months if month <= last_observation] - if not observed: - # Since #7394 the projection points cite CBO's calendar-year - # averages, which run about 0.7% above the 12-months-ending-August - # averages this window stands for, so projected windows read slightly - # high until that series is fixed (#9608). - return cpi(f"{year}-02-01") - unobserved_tail = MONTHS_IN_YEAR - len(observed) + # A parameter lookup returns the latest value dated on or before the + # month, which is the completion policy above for a month inside the + # observed range; capping the month at the last observation extends it + # to the tail. return ( - sum(cpi(month) for month in observed) + cpi(observed[-1]) * unobserved_tail - ) / MONTHS_IN_YEAR + sum(cpi(min(month, last_observation)) for month in window_months) + / MONTHS_IN_YEAR + ) + + +def get_irs_cpi(parameters: ParameterNode, year: int) -> float: + """The C-CPI-U for a calendar year under 26 U.S.C. 1(f)(6)(B). + + The average over the 12 months ending August 31 of ``year``, which + indexes tax parameters for ``year + 1``. + + 1(f)(6)(A) fixes the vintage: the C-CPI-U values to use are the latest + ones as of the date BLS publishes the initial August value for ``year``. + c_cpi_u.yaml holds one vintage per month, whichever was current when the + month was entered, and BLS revises C-CPI-U values after first + publication (August 2025 is 179.656 in the file and was 179.839 in the + BLS data API on 2026-10-06). So for a past year this reconstructs the + statutory index from the file's vintages, not necessarily from the + statutory vintage. Amounts the IRS has published are encoded in the + parameter files and take precedence for their own years; this index + only extends them. + """ + cpi = parameters.gov.bls.cpi + return get_average_for_12_months_ending_august( + cpi.c_cpi_u, year, cpi.tax_year_projection.c_cpi_u + ) def get_or_ctc_cola(parameters: ParameterNode, tax_year: int) -> float: @@ -83,9 +113,11 @@ def get_or_ctc_cola(parameters: ParameterNode, tax_year: int) -> float: ending August 31 of the prior calendar year exceeds the monthly averaged index for the second quarter of calendar year 2022. """ - cpi = parameters.gov.bls.cpi.cpi_u - base = sum(cpi(f"2022-{month:02d}-01") for month in (4, 5, 6)) / 3 - window = get_average_for_12_months_ending_august(cpi, tax_year - 1) + cpi = parameters.gov.bls.cpi + base = sum(cpi.cpi_u(f"2022-{month:02d}-01") for month in (4, 5, 6)) / 3 + window = get_average_for_12_months_ending_august( + cpi.cpi_u, tax_year - 1, cpi.tax_year_projection.cpi_u + ) return max(window / base - 1, 0) @@ -103,13 +135,14 @@ def get_irs_cola_denominator(parameters: ParameterNode, base_year: int) -> float "1(f)(3)(C) replaces this denominator with the C-CPI-U for base " f"years after 2016; got {base_year}." ) - cpi = parameters.gov.bls.cpi.cpi_u - chained_2016 = get_average_for_12_months_ending_august( - parameters.gov.bls.cpi.c_cpi_u, 2016 + cpi = parameters.gov.bls.cpi + cpi_2016, cpi_base_year = ( + get_average_for_12_months_ending_august( + cpi.cpi_u, year, cpi.tax_year_projection.cpi_u + ) + for year in (2016, base_year) ) - cpi_2016 = get_average_for_12_months_ending_august(cpi, 2016) - cpi_base_year = get_average_for_12_months_ending_august(cpi, base_year) - return cpi_base_year * chained_2016 / cpi_2016 + return cpi_base_year * get_irs_cpi(parameters, 2016) / cpi_2016 def get_irs_cola( @@ -123,9 +156,7 @@ def get_irs_cola( preceding ``tax_year`` exceeds the denominator for ``base_year``; see ``get_irs_cola_denominator``. """ - chained = get_average_for_12_months_ending_august( - parameters.gov.bls.cpi.c_cpi_u, tax_year - 1 - ) + chained = get_irs_cpi(parameters, tax_year - 1) return max(chained / get_irs_cola_denominator(parameters, base_year) - 1, 0) @@ -149,8 +180,8 @@ def extend_dependent_standard_deduction_parameters( 2016, and 1(f)(7)(A) rounds each increase down to the next lowest multiple of $50. Each year is computed from the statutory base rather than chained from the last rounded value, which can lag the statute by - a full $50 step; IRS and CBO values encoded in the YAML take precedence - for their own years. + a full $50 step; IRS values encoded in the YAML take precedence for + their own years. """ ROUNDING_INTERVAL = 50 dependent = parameters.gov.irs.deductions.standard.dependent @@ -282,6 +313,137 @@ def month_index(date: Instant) -> float: return anchors[-1][1] +def extend_nsa_cpi_u_projections(parameters: ParameterNode) -> None: + """Append calendar-year CPI-U forecast points to the independent NSA series. + + BLS CUUR0000SA0 observations take precedence. After the last observation, + use the existing CBO calendar-year CPI-U forecast and monthly interpolation + policy as a proxy for future NSA months; CBO does not forecast individual + August observations. These appended February points are forecasts, not BLS + observations. Vermont uses the separate CBO tax-year averages instead. + """ + cpi = parameters.gov.bls.cpi + nsa = cpi.cpi_u_nsa + last_observation = max(instant(value.instant_str) for value in nsa.values_list) + for value in sorted(cpi.cpi_u.values_list, key=lambda value: value.instant_str): + date = instant(value.instant_str) + if date > last_observation and value.instant_str.endswith("-02-01"): + nsa.update(start=date, value=value.value) + + +def get_vt_cpi(parameters: ParameterNode, tax_year: int) -> float: + """Vermont's unchained NSA CPI-U average under 32 V.S.A. 5811 and 5822.""" + cpi = parameters.gov.bls.cpi + return get_average_for_12_months_ending_august( + cpi.cpi_u_nsa, tax_year - 1, cpi.tax_year_projection.cpi_u + ) + + +def extend_vt_cpi_u_indexed_amounts(parameters: ParameterNode, end_year: int) -> None: + """Extend Vermont amounts from statutory bases, preserving published anchors. + + 32 V.S.A. 5811(21)(C)-(D) and 5822(a)-(b) substitute unchained CPI-U + in the federal September-August window. The 2017 base window is inferred + from agency amounts, not expressly specified in the statute. That window + and rounding reproduce published 2021-2025 deductions and 2024-2026 + brackets. Earlier agency rounding differs in some years, so historical + anchors are retained. + The 2026 bracket anchors are explicitly labelled preliminary in the YAML; + 2026 deductions and exemptions are calculated estimates pending publication. + """ + tax = parameters.gov.states.vt.tax.income + standard = tax.deductions.standard + amounts = [(standard.additional, 1_000, 50), (tax.exemption.personal, 4_150, 50)] + for status, base in ( + ("SINGLE", 6_000), + ("SEPARATE", 6_000), + ("HEAD_OF_HOUSEHOLD", 9_000), + ("JOINT", 12_000), + ("SURVIVING_SPOUSE", 12_000), + ): + amounts.append((standard.base.children[status], base, 50)) + for status, bases in ( + ("single", (38_700, 93_700, 195_450)), + ("head_of_household", (51_850, 133_850, 216_700)), + ("joint", (64_600, 156_150, 237_950)), + ("surviving_spouse", (64_600, 156_150, 237_950)), + ("separate", (32_300, 78_075, 118_975)), + ): + scale = getattr(tax.rates, status) + for bracket, base in zip(scale.brackets[1:], bases): + amounts.append( + (bracket.threshold, base, 25 if status == "separate" else 50) + ) + denominator = get_vt_cpi(parameters, 2018) + for parameter, base, interval in amounts: + first_year = 1 + max( + int(value.instant_str[:4]) for value in parameter.values_list + ) + for year in range(first_year, end_year + 1): + cola = max(get_vt_cpi(parameters, year) / denominator - 1, 0) + value = base + math.floor(base * cola / interval) * interval + parameter.update(start=instant(f"{year}-01-01"), value=float(value)) + + +def round_wi_amount(amount: float) -> float: + """Wis. Stat. 71.05(22)(dt), 71.06(2e)(c): nearest $10, $5 ties upward.""" + return float( + (Decimal(str(amount)) / 10).quantize(Decimal(1), rounding=ROUND_HALF_UP) * 10 + ) + + +def get_wi_august_cpi(parameters: ParameterNode, tax_year: int) -> float: + """Prior-August NSA CPI-U; unobserved August levels are forecast proxies.""" + return get_projected_cpi_u_for_month( + parameters.gov.bls.cpi.cpi_u_nsa, instant(f"{tax_year - 1}-08-01") + ) + + +def extend_wi_cpi_u_indexed_amounts(parameters: ParameterNode, end_year: int) -> None: + """Apply Wisconsin's statutory bases, August index, rounding and no decrease. + + 71.05(22)(dp)-(dt) uses August 1999 for single/head amounts and August + 2015 for joint/separate amounts. 71.06(2e)(bm) indexes the Act 15 bracket + bases against August 2024. Only years beyond each published anchor are + generated. The dependent limitation in 71.05(22)(f) uses federal indexing + and is outside this helper. + """ + tax = parameters.gov.states.wi.tax.income + for parameter in tax.get_descendants(): + if not isinstance(parameter, Parameter): + continue + rule = parameter.metadata.get("wisconsin_indexing") + if not rule or "base" not in rule: + continue + first_year = 1 + max( + int(value.instant_str[:4]) for value in parameter.values_list + ) + base_index = parameters.gov.bls.cpi.cpi_u_nsa(f"{rule['base_year']}-08-01") + for year in range(first_year, end_year + 1): + unrounded = ( + Decimal(str(rule["base"])) + * Decimal(str(get_wi_august_cpi(parameters, year))) + / Decimal(str(base_index)) + ) + value = max(parameter(f"{year - 1}-01-01"), round_wi_amount(unrounded)) + parameter.update(start=instant(f"{year}-01-01"), value=value) + + standard = tax.deductions.standard + crossover = standard.phase_out.head_of_household.brackets[2].threshold + first_year = 1 + max(int(value.instant_str[:4]) for value in crossover.values_list) + for year in range(first_year, end_year + 1): + date = f"{year}-01-01" + difference = standard.max.HEAD_OF_HOUSEHOLD(date) - standard.max.SINGLE(date) + rate_difference = standard.phase_out.head_of_household.brackets[1].rate( + date + ) - standard.phase_out.single.brackets[1].rate(date) + value = ( + standard.phase_out.single.brackets[1].threshold(date) + + difference / rate_difference + ) + crossover.update(start=instant(date), value=float(math.floor(value + 0.5))) + + def get_la_cpi_u_percentage_increase(cpi: ParameterNode, year: int) -> float: """The CPI-U percentage increase for calendar ``year``, as BLS reports it. @@ -663,25 +825,27 @@ def set_all_uprating_parameters(parameters: ParameterNode) -> ParameterNode: """ END_YEAR = 2100 - # IRS uprating - special case that computes from CPI - IRS_UPRATING_START_YEAR = 2010 - IRS_LAST_PROJECTED_YEAR = 2035 + # CBO's tax-year CPI projections (January values, last projection year + # 2036) cover 12-month windows with no BLS observation. Extend them first + # so every IRS uprating year below has a window average. + for projection in ( + parameters.gov.bls.cpi.tax_year_projection.c_cpi_u, + parameters.gov.bls.cpi.tax_year_projection.cpi_u, + ): + extend_parameter_values( + projection, + last_projected_year=2036, + end_year=END_YEAR, + period_month=1, + period_day=1, + ) + # IRS uprating: the 26 U.S.C. 1(f)(6)(B) C-CPI-U for the calendar year + # before each tax year. + IRS_UPRATING_START_YEAR = 2010 uprating_index = parameters.gov.irs.uprating - - # Calculate the growth rate from the last two years of CPI projections - cpi_second_to_last = get_irs_cpi(parameters, IRS_LAST_PROJECTED_YEAR - 2) - cpi_last = get_irs_cpi(parameters, IRS_LAST_PROJECTED_YEAR - 1) - growth_rate = cpi_last / cpi_second_to_last - - # Apply IRS uprating for year in range(IRS_UPRATING_START_YEAR, END_YEAR + 1): - if year <= IRS_LAST_PROJECTED_YEAR: - # Use actual CPI values through the last projected year - irs_cpi = get_irs_cpi(parameters, year - 1) - else: - # For all years after LAST_PROJECTED_YEAR, apply the constant growth rate - irs_cpi = uprating_index(f"{year - 1}-01-01") * growth_rate + irs_cpi = get_irs_cpi(parameters, year - 1) uprating_index.update(period=f"year:{year}-01-01:1", value=irs_cpi) uprating_index.update(start=instant(f"{END_YEAR}-01-01"), value=irs_cpi) @@ -738,19 +902,19 @@ def set_all_uprating_parameters(parameters: ParameterNode) -> ParameterNode: period_day=1, ) - # CPI-U (February values, last projection year 2034) + # CPI-U (February values, last projection year 2035) extend_parameter_values( parameters.gov.bls.cpi.cpi_u, - last_projected_year=2034, + last_projected_year=2035, end_year=END_YEAR, period_month=2, period_day=1, ) - # Chained CPI-U (February values, last projection year 2034) + # Chained CPI-U (February values, last projection year 2035) extend_parameter_values( parameters.gov.bls.cpi.c_cpi_u, - last_projected_year=2034, + last_projected_year=2035, end_year=END_YEAR, period_month=2, period_day=1, @@ -826,10 +990,16 @@ def set_all_uprating_parameters(parameters: ParameterNode) -> ParameterNode: # Oregon Kids' Credit dollar amounts follow the ORS 315.273(5) # cost-of-living schedule (unchained CPI-U over a 2022 Q2 base), computed - # from the statutory base amounts. Must run after the CPI-U extension - # above so projected windows are available. + # from the statutory base amounts. Must run after the tax-year CPI + # projection extension above so projected windows are available. extend_or_ctc_parameters(parameters, end_year=END_YEAR) + # Independent state schedules use unchained NSA observations and keep + # published anchors; future monthly NSA values are explicitly forecasts. + extend_nsa_cpi_u_projections(parameters) + extend_vt_cpi_u_indexed_amounts(parameters, end_year=END_YEAR) + extend_wi_cpi_u_indexed_amounts(parameters, end_year=END_YEAR) + # Louisiana's standard deduction and age-65 retirement income exemption # follow R.S. 47:294(B) and 47:44.1(A): the prior year's amount times the # prior calendar year's CPI-U increase. Must run after the CPI-U extension @@ -838,8 +1008,8 @@ def set_all_uprating_parameters(parameters: ParameterNode) -> ParameterNode: # The limits on a dependent's standard deduction follow 26 U.S.C. # 63(c)(4)'s chained CPI-U schedule, computed from the statutory 1987 and - # 1997 bases. Must run after the Chained CPI-U extension above so - # projected windows are available. + # 1997 bases. Must run after the tax-year CPI projection extension above + # so projected windows are available. extend_dependent_standard_deduction_parameters(parameters, end_year=END_YEAR) # The educator expense cap follows 26 U.S.C. 62(d)(3)'s chained CPI-U diff --git a/policyengine_us/tests/core/test_state_uprating_rounding.py b/policyengine_us/tests/core/test_state_uprating_rounding.py index 4fb2ed19fbe..f8df551ae84 100644 --- a/policyengine_us/tests/core/test_state_uprating_rounding.py +++ b/policyengine_us/tests/core/test_state_uprating_rounding.py @@ -1,16 +1,105 @@ """Regression coverage for state parameter uprating and rounding.""" from math import isinf +from decimal import Decimal, ROUND_FLOOR, ROUND_HALF_UP +from pathlib import Path +from types import SimpleNamespace import pytest +from policyengine_core.parameters import Parameter, ParameterNode, load_parameter_file +from policyengine_us.parameters.uprating_extensions import ( + extend_vt_cpi_u_indexed_amounts, + extend_wi_cpi_u_indexed_amounts, + get_irs_cpi, + round_wi_amount, +) from policyengine_us.system import system as SYSTEM +PARAMETER_DIR = Path(__file__).parents[2] / "parameters" + + def _thresholds(scale, period, bracket_indexes=(1, 2, 3)): return tuple(scale.brackets[index].threshold(period) for index in bracket_indexes) +def _observed_september_august_average(cpi, ending_year): + """Average twelve actual monthly records without using an indexing helper.""" + months = [ + *(f"{ending_year - 1}-{month:02d}-01" for month in range(9, 13)), + *(f"{ending_year}-{month:02d}-01" for month in range(1, 9)), + ] + observations = { + value.instant_str: Decimal(str(value.value)) for value in cpi.values_list + } + # A missing month raises KeyError rather than silently completing the window. + return sum(observations[month] for month in months) / Decimal(12) + + +def _wi_independent_indexed_amount(base, index, base_index, prior): + """Apply the statutory ratio, $10 half-up rounding, and prior-year floor.""" + unrounded = Decimal(str(base)) * Decimal(str(index)) / Decimal(str(base_index)) + rounded = int(unrounded.quantize(Decimal("1E1"), rounding=ROUND_HALF_UP)) + return max(prior, rounded) + + +def _raw_state_indexing_parameters(*states, cpi=None): + """Use published source trees so the extensions actually generate new years.""" + state_nodes = { + state: SimpleNamespace( + tax=SimpleNamespace( + income=ParameterNode( + f"gov.states.{state}.tax.income", + directory_path=str( + PARAMETER_DIR / f"gov/states/{state}/tax/income" + ), + ) + ) + ) + for state in states + } + return SimpleNamespace( + gov=SimpleNamespace( + bls=SimpleNamespace( + cpi=SYSTEM.parameters.gov.bls.cpi.clone() if cpi is None else cpi + ), + states=SimpleNamespace(**state_nodes), + ) + ) + + +def _indexed_state_values(parameters, years): + indexed = [] + states = parameters.gov.states + if hasattr(states, "vt"): + tax = states.vt.tax.income + standard = tax.deductions.standard + indexed.extend(standard.base.children.values()) + indexed.extend((standard.additional, tax.exemption.personal)) + for status in ( + "single", + "head_of_household", + "joint", + "surviving_spouse", + "separate", + ): + scale = getattr(tax.rates, status) + indexed.extend(bracket.threshold for bracket in scale.brackets[1:]) + if hasattr(states, "wi"): + indexed.extend( + parameter + for parameter in states.wi.tax.income.get_descendants() + if isinstance(parameter, Parameter) + and parameter.metadata.get("wisconsin_indexing") + ) + return { + (parameter.name, year): parameter(f"{year}-01-01") + for parameter in indexed + for year in years + } + + def test_ar_income_tax_bounds_round_to_nearest_100_after_last_published_year(): # A.C.A. 26-51-201(d)(1): bracket amounts are indexed "rounding to the # nearest one hundred dollars ($100)". Expected values follow the loaded @@ -95,41 +184,86 @@ def test_sc_dependent_deductions_round_down_to_ten_dollars(): def test_sc_income_tax_rounding_applies_to_threshold_not_rates(): scale = SYSTEM.parameters.gov.states.sc.tax.income.rates + uprating = SYSTEM.parameters.gov.irs.uprating + factor = Decimal(str(uprating("2027-01-01"))) / Decimal(str(uprating("2026-01-01"))) + expected_threshold = int( + (Decimal(30_000) * factor).quantize(Decimal("1E1"), rounding=ROUND_FLOOR) + ) - assert scale.brackets[1].threshold("2027-01-01") == 30_890 + assert scale.brackets[1].threshold("2026-01-01") == 30_000 + assert scale.brackets[1].threshold("2027-01-01") == expected_threshold assert scale.brackets[1].rate("2027-01-01") == pytest.approx(0.0521) assert scale.brackets[2].rate("2027-01-01") == pytest.approx(0.06) -def test_vt_standard_deductions_round_down_to_fifty_dollars(): +def test_vt_deductions_and_exemption_preserve_published_2025(): + # 2025 Vermont Income Tax Return Booklet, p. 11, and IN-111 line 5e. standard = SYSTEM.parameters.gov.states.vt.tax.income.deductions.standard - base = standard.base("2026-01-01") + base = standard.base("2025-01-01") - assert standard.additional("2026-01-01") == 1_250 + assert standard.additional("2025-01-01") == 1_250 expected = { - "JOINT": 15_600, - "HEAD_OF_HOUSEHOLD": 11_700, - "SURVIVING_SPOUSE": 15_600, - "SINGLE": 7_800, - "SEPARATE": 7_800, + "JOINT": 15_300, + "HEAD_OF_HOUSEHOLD": 11_450, + "SURVIVING_SPOUSE": 15_300, + "SINGLE": 7_650, + "SEPARATE": 7_650, } assert {status: base[status] for status in expected} == expected + assert ( + SYSTEM.parameters.gov.states.vt.tax.income.exemption.personal("2025-01-01") + == 5_300 + ) + + +def test_vt_2026_deductions_and_exemption_use_observed_unchained_cpi(): + # These 2026 amounts are calculated estimates pending Vermont publication. + # 32 V.S.A. 5811(21)(C)-(D): $6,000/$9,000/$12,000 standard deductions, + # $1,000 additional deduction, and $4,150 exemption. The 2017 base window + # reproduces published amounts; each increase rounds down to $50. + nsa = load_parameter_file(str(PARAMETER_DIR / "gov/bls/cpi/cpi_u_nsa.yaml")) + numerator = _observed_september_august_average(nsa, 2025) + denominator = _observed_september_august_average(nsa, 2017) + assert float(numerator) == pytest.approx(319.205) + assert float(denominator) == pytest.approx(243.391833333333) + cola = numerator / denominator - 1 + + def expected_amount(statutory_base): + increase = (Decimal(statutory_base) * cola / 50).to_integral_value( + rounding=ROUND_FLOOR + ) * 50 + return statutory_base + int(increase) + + tax = SYSTEM.parameters.gov.states.vt.tax.income + base = tax.deductions.standard.base("2026-01-01") + for status, statutory_base in ( + ("SINGLE", 6_000), + ("SEPARATE", 6_000), + ("HEAD_OF_HOUSEHOLD", 9_000), + ("JOINT", 12_000), + ("SURVIVING_SPOUSE", 12_000), + ): + assert base[status] == expected_amount(statutory_base), status + assert tax.deductions.standard.additional("2026-01-01") == expected_amount(1_000) + assert tax.exemption.personal("2026-01-01") == expected_amount(4_150) @pytest.mark.parametrize( ("filing_status", "expected"), ( - ("head_of_household", (67_700, 174_850, 283_100)), - ("joint", (84_350, 203_950, 310_850)), - ("separate", (42_150, 101_950, 155_400)), - ("single", (50_500, 122_400, 255_350)), - ("surviving_spouse", (84_350, 203_950, 310_850)), + ("head_of_household", (68_000, 175_500, 284_150)), + ("joint", (84_700, 204_750, 312_050)), + ("separate", (42_350, 102_375, 156_025)), + ("single", (50_750, 122_850, 256_300)), + ("surviving_spouse", (84_700, 204_750, 312_050)), ), ) -def test_vt_income_tax_thresholds_round_down_to_fifty_dollars( +def test_vt_income_tax_thresholds_preserve_published_preliminary_2026( filing_status, expected, ): + # IN-114-Instr-2026, p. 2, explicitly labels these rates preliminary. + # MFS thresholds use $25 increments, as §1(f)(7)(B) prescribes. scale = getattr( SYSTEM.parameters.gov.states.vt.tax.income.rates, filing_status, @@ -139,54 +273,163 @@ def test_vt_income_tax_thresholds_round_down_to_fifty_dollars( @pytest.mark.parametrize( - ("filing_status", "published_2026"), + ("filing_status", "published_2026", "statutory_base", "base_index"), ( # 2026 Form 1-ES instructions, 2026 Standard Deduction schedules. - ("head_of_household", 20_120), - ("joint", 29_040), - ("separate", 13_780), - ("single", 20_120), + ("head_of_household", 20_120, 10_380, "167.1"), + ("joint", 29_040, 21_360, "238.316"), + ("separate", 13_780, 10_140, "238.316"), + ("single", 20_120, 10_380, "167.1"), ), ) -def test_wi_standard_deduction_phase_out_thresholds_round_to_ten_dollars( +def test_wi_standard_deduction_phase_out_thresholds_use_published_then_statutory_values( filing_status, published_2026, + statutory_base, + base_index, ): + # 2026 Form 1-ES instructions, p. 2, Standard Deduction Schedules. + # Future amounts: Wis. Stat. 71.05(22)(dp)-(dt), using prior-August + # CUUR0000SA0 and the statutory 1999 (single/HOH) or 2015 (joint/MFS) base. scale = getattr( SYSTEM.parameters.gov.states.wi.tax.income.deductions.standard.phase_out, filing_status, ) - uprating = SYSTEM.parameters.gov.irs.uprating - assert scale.brackets[1].threshold("2026-01-01") == published_2026 - # Later years project from the published 2026 start, rounded to the - # nearest $10. Expected values follow the loaded index. - factor = uprating("2027-01-01") / uprating("2026-01-01") - expected_2027 = round(published_2026 * factor / 10) * 10 + nsa = SYSTEM.parameters.gov.bls.cpi.cpi_u_nsa + assert nsa("2026-08-01") == 334.980 + base_year = 1999 if filing_status in ("single", "head_of_household") else 2015 + assert nsa(f"{base_year}-08-01") == float(base_index) + expected_2027 = _wi_independent_indexed_amount( + statutory_base, "334.980", base_index, published_2026 + ) assert scale.brackets[1].threshold("2027-01-01") == expected_2027 +def test_wi_standard_deduction_maxima_and_crossover_preserve_published_2026(): + # 2026 Form 1-ES instructions, p. 2, including the HOH switch to single. + standard = SYSTEM.parameters.gov.states.wi.tax.income.deductions.standard + maxima = standard.max("2026-01-01") + expected = { + "SINGLE": 13_960, + "HEAD_OF_HOUSEHOLD": 18_030, + "JOINT": 25_840, + "SURVIVING_SPOUSE": 25_840, + "SEPARATE": 12_280, + } + assert {status: maxima[status] for status in expected} == expected + assert ( + standard.phase_out.head_of_household.brackets[2].threshold("2026-01-01") + == 58_827 + ) + + @pytest.mark.parametrize( - ("filing_status", "published_2026", "projected_2027"), + ("filing_status", "published_2026", "statutory_2025"), ( - ("head_of_household", (15_110, 51_950, 332_720), (15_560, 53_500, 342_640)), - ("joint", (20_150, 69_260, 443_630), (20_750, 71_320, 456_850)), - ("separate", (10_080, 34_630, 221_820), (10_380, 35_660, 228_430)), - ("single", (15_110, 51_950, 332_720), (15_560, 53_500, 342_640)), + ("head_of_household", (15_110, 51_950, 332_720), (14_680, 50_480, 323_290)), + ("joint", (20_150, 69_260, 443_630), (19_580, 67_300, 431_060)), + ("separate", (10_080, 34_630, 221_820), (9_790, 33_650, 215_530)), + ("single", (15_110, 51_950, 332_720), (14_680, 50_480, 323_290)), ), ) def test_wi_income_tax_thresholds_use_published_then_rounded_values( filing_status, published_2026, - projected_2027, + statutory_2025, ): + # Published 2026: Form 1-ES instructions, p. 3. 2027: Wis. Stat. + # 71.06(1r), (2)(k)-(L), (2e)(bm) and (c), using Act 15's 2025 bases + # and actual prior-August CUUR0000SA0. Later August forecasts are proxies. scale = getattr( SYSTEM.parameters.gov.states.wi.tax.income.rates, filing_status, ) assert _thresholds(scale, "2026-01-01") == published_2026 - assert _thresholds(scale, "2027-01-01") == projected_2027 + nsa = SYSTEM.parameters.gov.bls.cpi.cpi_u_nsa + assert nsa("2024-08-01") == 314.796 + assert nsa("2026-08-01") == 334.980 + expected_2027 = tuple( + _wi_independent_indexed_amount(base, "334.980", "314.796", prior) + for base, prior in zip(statutory_2025, published_2026) + ) + assert _thresholds(scale, "2027-01-01") == expected_2027 + + +def test_state_indexes_do_not_follow_federal_chained_cpi(): + baseline = _raw_state_indexing_parameters("vt", "wi") + refreshed = _raw_state_indexing_parameters("vt", "wi") + refreshed.gov.bls.cpi.c_cpi_u.update(period="month:2026-08-01:1", value=9_999) + assert get_irs_cpi(refreshed, 2026) != get_irs_cpi(baseline, 2026) + + for parameters in (baseline, refreshed): + extend_vt_cpi_u_indexed_amounts(parameters, 2028) + extend_wi_cpi_u_indexed_amounts(parameters, 2028) + # 2026 and 2027 have NSA observations; Vermont's 2027 window still + # estimates the missing October 2025 value. 2028 uses the documented + # unchained state forecast proxies, which must also be independent. + assert _indexed_state_values(refreshed, (2026, 2027, 2028)) == ( + _indexed_state_values(baseline, (2026, 2027, 2028)) + ) + + +@pytest.mark.parametrize( + ("amount", "expected"), + ( + ("4.999", 0), + ("5", 10), + ("15", 20), + ("25", 30), + ("1004.999", 1_000), + ("1005", 1_010), + ), +) +def test_wi_half_ten_rounds_up(amount, expected): + assert round_wi_amount(Decimal(amount)) == expected + + +def test_wi_indexed_amounts_never_decrease(): + nsa = Parameter( + "cpi_u_nsa", + data={ + "1999-08-01": 167.1, + "2015-08-01": 238.316, + "2024-08-01": 314.796, + "2025-08-01": 323.976, + "2026-08-01": 300, + "2027-08-01": 290, + }, + ) + parameters = _raw_state_indexing_parameters( + "wi", cpi=SimpleNamespace(cpi_u_nsa=nsa) + ) + indexed = [ + parameter + for parameter in parameters.gov.states.wi.tax.income.get_descendants() + if isinstance(parameter, Parameter) + and "base" in parameter.metadata.get("wisconsin_indexing", {}) + ] + assert indexed + published = {parameter.name: parameter("2026-01-01") for parameter in indexed} + assert nsa("2027-08-01") < nsa("2026-08-01") < nsa("2025-08-01") + extend_wi_cpi_u_indexed_amounts(parameters, 2028) + + for parameter in indexed: + rule = parameter.metadata["wisconsin_indexing"] + base_index = nsa(f"{rule['base_year']}-08-01") + prior = published[parameter.name] + for year in (2027, 2028): + current_index = nsa(f"{year - 1}-08-01") + unrounded = ( + Decimal(str(rule["base"])) + * Decimal(str(current_index)) + / Decimal(str(base_index)) + ) + # Every statutory candidate falls below its published anchor, + # so equality proves that the no-decrease clause actually binds. + assert unrounded < prior, (parameter.name, year) + assert parameter(f"{year}-01-01") == prior, (parameter.name, year) def test_wa_working_families_tax_credit_amounts_round_to_five_dollars(): diff --git a/policyengine_us/tests/policy/baseline/contrib/states/ri/high_earner_tax/ri_high_earner_tax.yaml b/policyengine_us/tests/policy/baseline/contrib/states/ri/high_earner_tax/ri_high_earner_tax.yaml index a94fb67aa54..610af6034ba 100644 --- a/policyengine_us/tests/policy/baseline/contrib/states/ri/high_earner_tax/ri_high_earner_tax.yaml +++ b/policyengine_us/tests/policy/baseline/contrib/states/ri/high_earner_tax/ri_high_earner_tax.yaml @@ -1,22 +1,18 @@ # Test RI H7317 Additional Tax on High-Income Filers # For 2027+: 3% additional tax on income above $640,000 (inflation-adjusted). -# The $640,000 threshold has an explicit value only for 2026-01-01; #8905 -# unfroze its `uprating:` block (previously a silently-ignored sibling of -# `values:`), so 2027 is now gov.irs.uprating(2027)/gov.irs.uprating(2026) * -# 640,000, rounded down to the nearest 50 -- not yet an officially published -# 2027 figure (none exists for this proposed reform). -# -# The baseline tax below these tests also moved: gov/states/ri/tax/income/ -# rate.yaml's bracket thresholds ($79,900 @ bracket[1] / $181,650 @ bracket[2] -# in 2025) were frozen by the same #8905 bug and are now gov.irs.uprating -# projections ($84,450 / $192,000 for 2027) from RI's official 2026 -# thresholds -- this remains a projection pending RI's 2027 publication. +# Retain the original fixture's synthetic 2027 forecast assumptions: +# baseline bracket thresholds of $84,450 / $192,000 and a proposed surtax +# threshold of $659,050. These inputs isolate reform activation and tax +# stacking; they are not published Rhode Island tax-year amounts. - name: RI high earner tax - income below threshold (no surtax) period: 2027 reforms: policyengine_us.reforms.states.ri.high_earner_tax.ri_high_earner_tax_reform.ri_high_earner_tax input: gov.contrib.states.ri.high_earner_tax.in_effect: true + gov.contrib.states.ri.high_earner_tax.brackets[1].threshold: 659_050 + gov.states.ri.tax.income.rate[1].threshold: 84_450 + gov.states.ri.tax.income.rate[2].threshold: 192_000 people: person1: age: 45 @@ -30,7 +26,7 @@ members: [person1] state_code: RI output: - # Income below the 2027 threshold - only baseline tax applies, surtax = 0. + # Income below the synthetic threshold - only baseline tax applies, surtax = 0. # Baseline: .0375*84,450 + .0475*(192,000-84,450) + .0599*(500,000-192,000) = 26,724.70 ri_income_tax_before_non_refundable_credits: 26_724.70 @@ -39,6 +35,9 @@ reforms: policyengine_us.reforms.states.ri.high_earner_tax.ri_high_earner_tax_reform.ri_high_earner_tax input: gov.contrib.states.ri.high_earner_tax.in_effect: true + gov.contrib.states.ri.high_earner_tax.brackets[1].threshold: 659_050 + gov.states.ri.tax.income.rate[1].threshold: 84_450 + gov.states.ri.tax.income.rate[2].threshold: 192_000 people: person1: age: 45 @@ -52,8 +51,7 @@ members: [person1] state_code: RI output: - # Baseline tax (41,699.70) + 3% surtax on income above the 2027 threshold - # (gov.irs.uprating-projected from $640,000 @ 2026 to $659,050 @ 2027) + # Baseline tax (41,699.70) + 3% surtax above the synthetic $659,050 threshold. # Baseline: .0375*84,450 + .0475*(192,000-84,450) + .0599*(750,000-192,000) = 41,699.70 # Surtax: (750,000 - 659,050) * 0.03 = 90,950 * 0.03 = 2,728.5 # Total: 41,699.70 + 2,728.5 = 44,428.20 @@ -64,6 +62,9 @@ reforms: policyengine_us.reforms.states.ri.high_earner_tax.ri_high_earner_tax_reform.ri_high_earner_tax input: gov.contrib.states.ri.high_earner_tax.in_effect: true + gov.contrib.states.ri.high_earner_tax.brackets[1].threshold: 659_050 + gov.states.ri.tax.income.rate[1].threshold: 84_450 + gov.states.ri.tax.income.rate[2].threshold: 192_000 people: person1: age: 45 @@ -77,8 +78,7 @@ members: [person1] state_code: RI output: - # Baseline tax (56,674.70) + 3% surtax on income above the 2027 threshold - # (gov.irs.uprating-projected from $640,000 @ 2026 to $659,050 @ 2027) + # Baseline tax (56,674.70) + 3% surtax above the synthetic $659,050 threshold. # Baseline: .0375*84,450 + .0475*(192,000-84,450) + .0599*(1,000,000-192,000) = 56,674.70 # Surtax: (1,000,000 - 659,050) * 0.03 = 340,950 * 0.03 = 10,228.5 # Total: 56,674.70 + 10,228.5 = 66,903.20 @@ -89,6 +89,9 @@ reforms: policyengine_us.reforms.states.ri.high_earner_tax.ri_high_earner_tax_reform.ri_high_earner_tax input: gov.contrib.states.ri.high_earner_tax.in_effect: false + gov.contrib.states.ri.high_earner_tax.brackets[1].threshold: 659_050 + gov.states.ri.tax.income.rate[1].threshold: 84_450 + gov.states.ri.tax.income.rate[2].threshold: 192_000 people: person1: age: 45 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/deductions/standard/basic_standard_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/irs/deductions/standard/basic_standard_deduction.yaml index 483f073599a..29ad15f465b 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/deductions/standard/basic_standard_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/deductions/standard/basic_standard_deduction.yaml @@ -115,7 +115,8 @@ # C-CPI-U Sep 2015-Aug 2016 average 135.993 / CPI-U Sep 2015-Aug 2016 # average 238.649 = 90.886. # Increase = $250 x (182.424 / 90.886 - 1) = $251.80, rounded down to - # $250, so $500. Floor: CBO's $1,400. + # $250, so $500. Floor (63(c)(4)(B)(i), 1987 denominator 63.813): + # $500 x 182.424 / 63.813 = $1,429.36, rounded down to $1,400. # max($1,400, $500 + $3,000) = $3,500, below the $16,550 cap. period: 2027 input: @@ -136,14 +137,11 @@ - name: 2032 dependent filer with $3,000 of wages gets $550 plus earned income # Same 63(c)(4)(B)(ii) adjustment. The 12 months ending August 2031 have - # no observed month, so the window reads the c_cpi_u.yaml projection point - # at 2031-02-01: 202.7. That point is CBO's calendar-year 2031 average, not - # a September-August average (#9608). - # Increase = $250 x (202.7 / 90.886 - 1) = $307.57, rounded down to $300, - # so $550. CBO's tax-year index for 2032 (Feb 2026 Tax Parameters, row - # 153: 201.335) gives the same step: $250 x (201.335 / 90.886 - 1) = - # $303.81, rounded down to $300. Floor: CBO's $1,550. - # max($1,550, $550 + $3,000) = $3,550, below the $18,250 cap. + # no observed month, so the window reads CBO's projection of that average + # (tax_year_projection/c_cpi_u.yaml, 2032): 201.335. + # Increase = $250 x (201.335 / 90.886 - 1) = $303.81, rounded down to + # $300, so $550. Floor: $500 x 201.335 / 63.813 = $1,577.53, so $1,550. + # max($1,550, $550 + $3,000) = $3,550, below the $18,300 cap. period: 2032 input: people: @@ -165,11 +163,12 @@ # Past CBO's 2036 horizon, 63(c)(4)(B)(i) increases the 63(c)(5)(A) $500 # by the 1(f)(3) adjustment with calendar year 1987 as the base year. # C-CPI-U for the 12 months ending August 2041: uprating_extensions.py - # extends c_cpi_u.yaml past 2034 at its 2033-2034 growth rate, - # 214.9 x (214.9 / 210.8)^7 = 245.922. + # extends CBO's tax-year projection (tax_year_projection/c_cpi_u.yaml) + # past 2036 at its 2035-2036 growth rate, + # 217.68 x (217.68 / 213.471)^6 = 244.735. # 1(f)(3)(A)(ii) and (B): CPI-U Sep 1986-Aug 1987 average 111.983 x # 135.993 / 238.649 = 63.813. - # Increase = $500 x (245.922 / 63.813 - 1) = $1,426.89, rounded down to + # Increase = $500 x (244.735 / 63.813 - 1) = $1,417.59, rounded down to # $1,400, so $1,900. period: 2042 input: @@ -187,9 +186,32 @@ output: basic_standard_deduction: 1_900 +- name: 2040 dependent floor uses the tax-year chained CPI projection + # 26 U.S.C. 63(c)(4)(B)(i), 63(c)(5)(A), and 1(f)(7)(A): increase the + # $500 statutory base using the 1987 denominator 63.81317101684901 and + # round the increase down to $50. Extending CBO's tax-year index gives + # 217.68 x (217.68 / 213.471)^4 = 235.362411812; the unrounded total + # is $1,844.1523, so the floor is $1,800. The calendar-year projection + # instead gives $1,854.0658 and an incorrect $1,850 floor. + period: 2040 + input: + people: + head: + age: 20 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [head] + filing_status: SINGLE + households: + household: + members: [head] + output: + basic_standard_deduction: 1_800 + - name: 2042 dependent filer with $3,000 of wages gets $650 plus earned income - # Same 2041 C-CPI-U of 245.922 and 1997 denominator of 90.886. - # Increase = $250 x (245.922 / 90.886 - 1) = $426.46, rounded down to + # Same 2041 C-CPI-U of 244.735 and 1997 denominator of 90.886. + # Increase = $250 x (244.735 / 90.886 - 1) = $423.20, rounded down to # $400, so $650. max($1,900, $650 + $3,000) = $3,650. period: 2042 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_income_tax_before_credits.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_income_tax_before_credits.yaml index 56b2bf12ede..eff4c43df0a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_income_tax_before_credits.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_income_tax_before_credits.yaml @@ -21,3 +21,72 @@ output: # 82_046.3 + (12.30% of (1_000_000 - 850_503)) = 100_434.131 ca_income_tax_before_credits: 100_434.131 + +# Published 2026 amounts: FTB Tax News, October 2026, 2026 Indexing. +# https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 + +- name: California 2026 published single schedule at taxable income 25_000 + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: CA + filing_status: SINGLE + ca_taxable_income: 25_000 + output: + # 114.56 + .02 * (25_000 - 11_456) = 385.44 + ca_income_tax_before_credits: 385.44 + +- name: California 2026 published separate schedule at taxable income 25_000 + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: CA + filing_status: SEPARATE + ca_taxable_income: 25_000 + output: + # 114.56 + .02 * (25_000 - 11_456) = 385.44 + ca_income_tax_before_credits: 385.44 + +- name: California 2026 published joint schedule at taxable income 50_000 + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: CA + filing_status: JOINT + ca_taxable_income: 50_000 + output: + # 229.12 + .02 * (50_000 - 22_912) = 770.88 + ca_income_tax_before_credits: 770.88 + +- name: California 2026 published surviving spouse schedule at taxable income 50_000 + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: CA + filing_status: SURVIVING_SPOUSE + ca_taxable_income: 50_000 + output: + # 229.12 + .02 * (50_000 - 22_912) = 770.88 + ca_income_tax_before_credits: 770.88 + +- name: California 2026 published head of household schedule at taxable income 60_000 + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: CA + filing_status: HEAD_OF_HOUSEHOLD + ca_taxable_income: 60_000 + output: + # 857.05 + .04 * (60_000 - 54_316) = 1_084.41 + ca_income_tax_before_credits: 1_084.41 + +- name: California 2026 published single schedule at taxable income 1_000_000 + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: CA + filing_status: SINGLE + ca_taxable_income: 1_000_000 + output: + # 74_675.27 + .123 * (1_000_000 - 768_213) = 103_185.071 + ca_income_tax_before_credits: 103_185.07 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/renter/ca_renter_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/renter/ca_renter_credit.yaml index b0191cde7ff..db4824cf9f3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/renter/ca_renter_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/renter/ca_renter_credit.yaml @@ -47,3 +47,106 @@ rent: 0 output: ca_renter_credit: 0 + +# Published 2026 amounts: FTB Tax News, October 2026, 2026 Indexing. +# https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 + +- name: California 2026 renter credit at the published single ceiling + period: 2026 + input: + state_code: CA + filing_status: SINGLE + ca_agi: 55_830 + rent: 1 + output: + ca_renter_credit: 60 + +- name: California 2026 renter credit one dollar above the published single ceiling + period: 2026 + input: + state_code: CA + filing_status: SINGLE + ca_agi: 55_831 + rent: 1 + output: + ca_renter_credit: 0 + +- name: California 2026 renter credit at the published separate ceiling + period: 2026 + input: + state_code: CA + filing_status: SEPARATE + ca_agi: 55_830 + rent: 1 + output: + ca_renter_credit: 60 + +- name: California 2026 renter credit one dollar above the published separate ceiling + period: 2026 + input: + state_code: CA + filing_status: SEPARATE + ca_agi: 55_831 + rent: 1 + output: + ca_renter_credit: 0 + +- name: California 2026 renter credit at the published joint ceiling + period: 2026 + input: + state_code: CA + filing_status: JOINT + ca_agi: 111_660 + rent: 1 + output: + ca_renter_credit: 120 + +- name: California 2026 renter credit one dollar above the published joint ceiling + period: 2026 + input: + state_code: CA + filing_status: JOINT + ca_agi: 111_661 + rent: 1 + output: + ca_renter_credit: 0 + +- name: California 2026 renter credit at the published surviving spouse ceiling + period: 2026 + input: + state_code: CA + filing_status: SURVIVING_SPOUSE + ca_agi: 111_660 + rent: 1 + output: + ca_renter_credit: 120 + +- name: California 2026 renter credit one dollar above the published surviving spouse ceiling + period: 2026 + input: + state_code: CA + filing_status: SURVIVING_SPOUSE + ca_agi: 111_661 + rent: 1 + output: + ca_renter_credit: 0 + +- name: California 2026 renter credit at the published head of household ceiling + period: 2026 + input: + state_code: CA + filing_status: HEAD_OF_HOUSEHOLD + ca_agi: 111_660 + rent: 1 + output: + ca_renter_credit: 120 + +- name: California 2026 renter credit one dollar above the published head of household ceiling + period: 2026 + input: + state_code: CA + filing_status: HEAD_OF_HOUSEHOLD + ca_agi: 111_661 + rent: 1 + output: + ca_renter_credit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/standard/ca_standard_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/standard/ca_standard_deduction.yaml index 3ebfd55dca1..3beedc0cb64 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/standard/ca_standard_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/standard/ca_standard_deduction.yaml @@ -13,3 +13,46 @@ filing_status: JOINT output: ca_standard_deduction: 9_606 + +# Published 2026 amounts: FTB Tax News, October 2026, 2026 Indexing. +# https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 + +- name: California 2026 published standard deduction for single + period: 2026 + input: + state_code: CA + filing_status: SINGLE + output: + ca_standard_deduction: 5_900 + +- name: California 2026 published standard deduction for separate + period: 2026 + input: + state_code: CA + filing_status: SEPARATE + output: + ca_standard_deduction: 5_900 + +- name: California 2026 published standard deduction for joint + period: 2026 + input: + state_code: CA + filing_status: JOINT + output: + ca_standard_deduction: 11_800 + +- name: California 2026 published standard deduction for surviving spouse + period: 2026 + input: + state_code: CA + filing_status: SURVIVING_SPOUSE + output: + ca_standard_deduction: 11_800 + +- name: California 2026 published standard deduction for head of household + period: 2026 + input: + state_code: CA + filing_status: HEAD_OF_HOUSEHOLD + output: + ca_standard_deduction: 11_800 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/exemptions/ca_exemptions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/exemptions/ca_exemptions.yaml index 648ed555e86..5f32f55523f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/exemptions/ca_exemptions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/exemptions/ca_exemptions.yaml @@ -39,3 +39,39 @@ state_code: CA output: ca_exemptions: 658 + +# Published 2026 amounts: FTB Tax News, October 2026, 2026 Indexing. +# https://www.ftb.ca.gov/about-ftb/newsroom/tax-news/#article1 + +- name: California 2026 published single personal credit + period: 2026 + input: + state_code: CA + filing_status: SINGLE + aged_blind_count: 0 + adjusted_gross_income: 1 + tax_unit_dependents: 0 + output: + ca_exemptions: 158 + +- name: California 2026 published joint personal credit + period: 2026 + input: + state_code: CA + filing_status: JOINT + aged_blind_count: 0 + adjusted_gross_income: 1 + tax_unit_dependents: 0 + output: + ca_exemptions: 316 + +- name: California 2026 published joint personal and dependent credits + period: 2026 + input: + state_code: CA + filing_status: JOINT + aged_blind_count: 0 + adjusted_gross_income: 1 + tax_unit_dependents: 1 + output: + ca_exemptions: 807 diff --git a/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/test_or_ctc_sunset.py b/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/test_or_ctc_sunset.py index 0b9af4b1cf2..57a7f336b83 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/test_or_ctc_sunset.py +++ b/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/test_or_ctc_sunset.py @@ -125,9 +125,13 @@ def test_projections_compute_from_statutory_bases_not_chained(): def _cola_on_series(values, tax_year): """Run the COLA helper against a synthetic CPI-U series.""" - cpi_u = Parameter("cpi_u", data=dict(values)) - bls = SimpleNamespace(cpi=SimpleNamespace(cpi_u=cpi_u)) - parameters = SimpleNamespace(gov=SimpleNamespace(bls=bls)) + cpi = SimpleNamespace( + cpi_u=Parameter("cpi_u", data=dict(values)), + tax_year_projection=SimpleNamespace( + cpi_u=Parameter("cpi_u_projection", data=_tax_year_projection()) + ), + ) + parameters = SimpleNamespace(gov=SimpleNamespace(bls=SimpleNamespace(cpi=cpi))) return get_or_ctc_cola(parameters, tax_year) @@ -141,8 +145,8 @@ def _monthly(values, start_year, start_month, end_year, end_month, level): # A synthetic mirror of the live series shape: 2022 Q2 base months averaging -# 300, monthly observations through August 2025, then annual projection -# points at February instants. +# 300, monthly observations through August 2025, then calendar-year +# projection points at February instants. def _base_series(): values = {"2022-04-01": 297, "2022-05-01": 300, "2022-06-01": 303} _monthly(values, 2022, 7, 2025, 8, 331) @@ -151,16 +155,24 @@ def _base_series(): return values +# CBO's projections of the 12 months ending the August before each tax +# year. They differ from the calendar-year points above, so each assertion +# shows which series a window read. +def _tax_year_projection(): + return {"2027-01-01": 344, "2028-01-01": 358} + + def test_cola_fully_observed_window_averages_monthly_data(): # Tax year 2026 window (September 2024 - August 2025) is fully observed # at 331: COLA = 331 / 300 - 1. assert _cola_on_series(_base_series(), 2026) == pytest.approx(31 / 300) -def test_cola_unobserved_window_uses_annual_projection_point(): - # Tax year 2027 has no observed months, so the February 2026 annual - # projection point (347) applies: COLA = 347 / 300 - 1. - assert _cola_on_series(_base_series(), 2027) == pytest.approx(47 / 300) +def test_cola_unobserved_window_uses_tax_year_projection(): + # Tax year 2027 has no observed months, so CBO's projection of that + # window (344) applies, not the February 2026 calendar-year point (347): + # COLA = 344 / 300 - 1. + assert _cola_on_series(_base_series(), 2027) == pytest.approx(44 / 300) def test_cola_partial_window_ignores_overwritten_february_projection(): @@ -170,16 +182,16 @@ def test_cola_partial_window_ignores_overwritten_february_projection(): # disagrees: the tax year 2027 window averages the ten observed months # (five at 330, five at 342) with a flat two-month tail at the last # observation (342), giving (5 * 330 + 5 * 342 + 2 * 342) / 12 = 337 and - # COLA = 37 / 300. Reading the overwritten February instant as an - # annual projection would instead give 42 / 300 — so this assertion - # fails against the raw-February-read regression it guards against. + # COLA = 37 / 300. Reading the overwritten February instant as a + # projection would instead give 42 / 300 — so this assertion fails + # against the raw-February-read regression it guards against. values = _base_series() _monthly(values, 2025, 9, 2026, 1, 330) _monthly(values, 2026, 2, 2026, 6, 342) assert _cola_on_series(values, 2027) == pytest.approx(37 / 300) - # Later, fully unobserved windows still read their own projection - # points: tax year 2028 uses February 2027 (361). - assert _cola_on_series(values, 2028) == pytest.approx(61 / 300) + # Later, fully unobserved windows still read their own tax-year + # projection: tax year 2028 uses 358. + assert _cola_on_series(values, 2028) == pytest.approx(58 / 300) def test_cola_observations_ending_on_a_february_stay_conservative(): diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/agi/subtractions/social_security/ri_social_security_modification_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/agi/subtractions/social_security/ri_social_security_modification_eligible.yaml index 7f9b6848742..c12d59b5e29 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/agi/subtractions/social_security/ri_social_security_modification_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/agi/subtractions/social_security/ri_social_security_modification_eligible.yaml @@ -109,14 +109,13 @@ output: ri_social_security_modification_eligible: false -# The 2027 income limit is a gov.irs.uprating CPI projection from the 2025 -# explicit value (#8905 unfroze the sibling-of-values `uprating:` block that -# had been silently ignored, freezing 2026/2027 at the 2025 figure). RI has -# not yet published its own 2027 adjustment; the official figure supersedes -# this projection once released (see #8905). +# Retain the original fixture's synthetic 2027 income limits to isolate the +# strict eligibility boundary after removal of the age requirement. These +# assumptions are not published Rhode Island tax-year amounts. - name: 2027 - Single filer just below income limit is eligible period: 2027 input: + gov.states.ri.tax.income.agi.subtractions.social_security.limit.income.SINGLE: 112_650 adjusted_gross_income: 112_649 filing_status: SINGLE older_spouse_birth_year: 1990 @@ -127,6 +126,7 @@ - name: 2027 - Single filer at income limit is ineligible period: 2027 input: + gov.states.ri.tax.income.agi.subtractions.social_security.limit.income.SINGLE: 112_650 adjusted_gross_income: 112_650 filing_status: SINGLE older_spouse_birth_year: 1990 @@ -137,6 +137,7 @@ - name: 2027 - Joint filer just below income limit is eligible period: 2027 input: + gov.states.ri.tax.income.agi.subtractions.social_security.limit.income.JOINT: 140_850 adjusted_gross_income: 140_849 filing_status: JOINT older_spouse_birth_year: 1990 @@ -147,6 +148,7 @@ - name: 2027 - Joint filer at income limit is ineligible period: 2027 input: + gov.states.ri.tax.income.agi.subtractions.social_security.limit.income.JOINT: 140_850 adjusted_gross_income: 140_850 filing_status: JOINT older_spouse_birth_year: 1990 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/integration.yaml index c0c3dbbfce7..40c3d20a350 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/integration.yaml @@ -239,6 +239,10 @@ absolute_error_margin: 0.01 period: 2027 input: + # Synthetic forecast assumptions retained from the original fixture to + # isolate credit/surtax interaction; not published RI tax-year amounts. + gov.states.ri.tax.income.rate[1].threshold: 84_450 + gov.states.ri.tax.income.rate[2].threshold: 192_000 people: person1: age: 40 @@ -264,8 +268,7 @@ ri_ctc: 330 ri_high_earner_tax: 2_500 ri_social_security_modification: 10_000 - # Baseline tax uses gov/states/ri/tax/income/rate.yaml's bracket - # thresholds, gov.irs.uprating-projected for 2027 from the official 2026 - # thresholds (84,450 / 192,000): 71,649.70 before credits, + 2,500 surtax, + # Baseline tax uses the synthetic bracket thresholds supplied above + # (84,450 / 192,000): 71,649.70 before credits, + 2,500 surtax, # - 330 CTC = 73,819.70. ri_income_tax: 73_819.70 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/ri_high_earner_tax.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/ri_high_earner_tax.yaml index e7e572d10ac..bda137fea82 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/ri_high_earner_tax.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/ri_high_earner_tax.yaml @@ -20,6 +20,9 @@ period: 2028 absolute_error_margin: 0.01 input: + # Synthetic forecast assumption retained from the original fixture to + # isolate the surtax rate; not a published Rhode Island tax-year amount. + gov.states.ri.tax.income.high_earner_tax.threshold: 1_022_600 state_code: RI ri_taxable_income: 1_250_000 output: @@ -30,6 +33,9 @@ period: 2029 absolute_error_margin: 0.01 input: + # Synthetic forecast assumption retained from the original fixture to + # isolate the surtax rate; not a published Rhode Island tax-year amount. + gov.states.ri.tax.income.high_earner_tax.threshold: 1_039_400 state_code: RI ri_taxable_income: 1_250_000 output: @@ -40,12 +46,14 @@ period: 2027 absolute_error_margin: 0.01 input: + # Synthetic forecast assumptions retained from the original fixture to + # isolate tax stacking; not published Rhode Island tax-year amounts. + gov.states.ri.tax.income.rate[1].threshold: 84_450 + gov.states.ri.tax.income.rate[2].threshold: 192_000 state_code: RI ri_taxable_income: 1_250_000 output: - # Baseline tax uses gov/states/ri/tax/income/rate.yaml's bracket - # thresholds, gov.irs.uprating-projected for 2027 from the official 2026 - # thresholds: + # Baseline tax uses the synthetic bracket thresholds supplied above: # .0375*84,450 + .0475*(192,000-84,450) + .0599*(1,250,000-192,000) = 71,649.70 # + 1% high-earner surtax on income above the (explicit, unaffected) # $1,000,000 2027 threshold: (1,250,000 - 1,000,000) * 0.01 = 2,500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_income_tax_before_credits.yaml b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_income_tax_before_credits.yaml index d230d4d8cd9..7e84f4faa77 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_income_tax_before_credits.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_income_tax_before_credits.yaml @@ -28,6 +28,49 @@ output: wi_income_tax_before_credits: 22_232.83 # same as for SINGLE filing unit +# 2025 Act 15 bracket tops, corroborated by 2025 Form 1-ES, PDF page 4. +- name: WI 2025 single third bracket starts at the statutory amount + period: 2025 + absolute_error_margin: 0.01 + input: + state_code: WI + filing_status: SINGLE + wi_taxable_income: 51_000 + output: + # 2,089.00 + (51,000 - 50,480) * 5.3%. + wi_income_tax_before_credits: 2_116.56 + +- name: WI 2025 head of household shares the statutory single brackets + period: 2025 + absolute_error_margin: 0.01 + input: + state_code: WI + filing_status: HEAD_OF_HOUSEHOLD + wi_taxable_income: 51_000 + output: + wi_income_tax_before_credits: 2_116.56 + +- name: WI 2025 joint third bracket starts at the statutory amount + period: 2025 + absolute_error_margin: 0.01 + input: + state_code: WI + filing_status: JOINT + wi_taxable_income: 68_000 + output: + # 2,784.98 + (68,000 - 67,300) * 5.3%. + wi_income_tax_before_credits: 2_822.08 + +- name: WI 2025 separate third bracket starts at the statutory amount + period: 2025 + absolute_error_margin: 0.01 + input: + state_code: WI + filing_status: SEPARATE + wi_taxable_income: 34_000 + output: + # 1,392.49 + (34,000 - 33,650) * 5.3%. + wi_income_tax_before_credits: 1_411.04 - name: WI 2025 single tax matches the Tax Computation Worksheet absolute_error_margin: 0.01 period: 2025 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_standard_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_standard_deduction.yaml index 24ec29f0189..07c10d3b317 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_standard_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/wi_standard_deduction.yaml @@ -36,7 +36,9 @@ wi_agi: 49_705 + 10_000 state_code: WI output: - wi_standard_deduction: 7_864.22 - 0.12 * 10_000 + # Above the published HOH crossover, §71.05(22)(dp) uses the single + # formula, rather than continuing the rounded HOH amount at the switch. + wi_standard_deduction: 11_790 - (59_705 - 16_990) * 0.12 # 2026 Form 1-ES instructions, page 2, "2026 Standard Deduction" schedules. - name: WI 2026 single standard deduction below the phase-out @@ -93,7 +95,64 @@ state_code: WI output: # Head of household, over $58,827 but not over $136,453: - # 13,960 less 12% of the amount over $20,120. The model reaches the - # same amount through the 22.515% and 12% segments that meet at $58,827, - # within $0.05 of the schedule. + # 13,960 less 12% of the amount over $20,120 (the single schedule). wi_standard_deduction: 13_960 - 0.12 * (70_000 - 20_120) + +# Published schedules: 2026 Form 1-ES instructions, PDF page 2. +- name: WI 2026 published single deduction before phaseout + period: 2026 + input: + state_code: WI + filing_status: SINGLE + wi_agi: 20_000 + output: + wi_standard_deduction: 13_960 + +- name: WI 2026 published joint deduction after phaseout + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: WI + filing_status: JOINT + wi_agi: 30_000 + output: + # 25,840 - (30,000 - 29,040) * 19.778%. + wi_standard_deduction: 25_650.1312 + +- name: WI 2026 published head deduction after phaseout + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: WI + filing_status: HEAD_OF_HOUSEHOLD + wi_agi: 20_130 + output: + # 18,030 - (20,130 - 20,120) * 22.515%. + wi_standard_deduction: 18_027.7485 + +- name: WI 2026 published separate deduction after phaseout + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: WI + filing_status: SEPARATE + wi_agi: 14_000 + output: + # 12,280 - (14,000 - 13,780) * 19.778%. + wi_standard_deduction: 12_236.4884 + +- name: WI 2026 surviving spouse shares joint schedule + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: WI + filing_status: SURVIVING_SPOUSE + wi_agi: 30_000 + output: + wi_standard_deduction: 25_650.1312 + +- name: WI 2026 head uses the exact single formula above published crossover + period: 2026 + absolute_error_margin: 0.001 + input: {state_code: WI, filing_status: HEAD_OF_HOUSEHOLD, wi_agi: 60_000} + output: {wi_standard_deduction: 9_174.4} diff --git a/policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py b/policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py index 9049852d5a0..4afbc49f812 100644 --- a/policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py +++ b/policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py @@ -7,6 +7,10 @@ import yaml from policyengine_core.parameters import Parameter, ParameterNode +from policyengine_core.parameters.operations.propagate_parameter_metadata import ( + propagate_parameter_metadata, +) +from policyengine_core.parameters.operations.uprate_parameters import uprate_parameters from policyengine_us.system import system from policyengine_us.tools.per_capita_uprating import per_capita_path @@ -16,8 +20,10 @@ LONG_RUN_CBO_INCOME_BY_SOURCE_PARAMETERS, extend_dependent_standard_deduction_parameters, extend_educator_expense_cap, + get_average_for_12_months_ending_august, get_irs_cola, get_irs_cola_denominator, + get_irs_cpi, round_social_security_amount, round_social_security_payroll_cap, ) @@ -26,6 +32,16 @@ PARAMETERS = system.parameters +@pytest.mark.parametrize("name", ("cpi_u", "c_cpi_u")) +def test_last_published_calendar_cbo_forecast_survives_extension(name): + source = Path(__file__).parents[4] / "parameters/gov/bls/cpi" / f"{name}.yaml" + with source.open() as stream: + encoded = yaml.safe_load(stream)["values"] + date = "2035-02-01" + published = next(value for key, value in encoded.items() if str(key) == date) + assert getattr(PARAMETERS.gov.bls.cpi, name)(date) == published + + def test_all_uprating_factors_extend_to_2100(): """Test that all uprating factors extend through 2100 with consistent growth rates.""" parameters = PARAMETERS @@ -481,18 +497,158 @@ def months(start_year, start_month, end_year, end_month, level): c_cpi_u = { **months(2015, 9, 2016, 8, 150), **months(2019, 9, 2020, 8, 60), - # Monthly observations end in August 2030; later years hold annual - # projection points at February instants. + # Monthly observations end in August 2030; later years hold + # calendar-year projection points at February instants. **months(2029, 9, 2030, 8, 180), - "2032-02-01": 195, + "2032-02-01": 199, } cpi = SimpleNamespace( cpi_u=Parameter("cpi_u", data=cpi_u), c_cpi_u=Parameter("c_cpi_u", data=c_cpi_u), + # CBO's projections of the 12 months ending the August before each + # tax year. + tax_year_projection=SimpleNamespace( + cpi_u=Parameter("cpi_u_projection", data={"2033-01-01": 390}), + c_cpi_u=Parameter("c_cpi_u_projection", data={"2033-01-01": 195}), + ), ) return SimpleNamespace(gov=SimpleNamespace(bls=SimpleNamespace(cpi=cpi))) +def test_irs_window_includes_august_excludes_prior_august(): + """1(f)(6)(B) includes the ending August in the twelve-month average.""" + monthly = Parameter( + "c_cpi_u", + data={ + "2024-08-01": 1_000, + **{f"2024-{month:02d}-01": 100 for month in range(9, 13)}, + **{f"2025-{month:02d}-01": 100 for month in range(1, 8)}, + "2025-08-01": 220, + }, + ) + cpi = SimpleNamespace( + c_cpi_u=monthly, + tax_year_projection=SimpleNamespace( + c_cpi_u=Parameter("projection", data={"2026-01-01": 999}) + ), + ) + parameters = SimpleNamespace(gov=SimpleNamespace(bls=SimpleNamespace(cpi=cpi))) + + # September-July contribute 11 x 100, and the ending August 220: + # 1,320 / 12 = 110. Including the prior August instead gives 175. + assert get_irs_cpi(parameters, 2025) == 110 + + +def test_tax_year_projection_is_distinct_from_calendar_year_projection(): + """Forecast windows read the dedicated tax-year series, even after a refresh.""" + parameters = _synthetic_irs_parameters() + cpi = parameters.gov.bls.cpi + assert cpi.c_cpi_u("2032-02-01") == 199 + assert get_irs_cpi(parameters, 2032) == 195 + + # Refreshing a calendar-year forecast cannot change this tax window. + cpi.c_cpi_u = Parameter( + "c_cpi_u", + data={ + **{value.instant_str: value.value for value in cpi.c_cpi_u.values_list}, + "2032-02-01": 9_999, + }, + ) + assert get_irs_cpi(parameters, 2032) == 195 + # Refreshing the tax-year forecast changes the window itself. + cpi.tax_year_projection.c_cpi_u = Parameter( + "c_cpi_u_projection", data={"2033-01-01": 205} + ) + assert get_irs_cpi(parameters, 2032) == 205 + + +def test_missing_month_and_partial_window_completion_are_flat_estimates(): + """A missing interior month and an unobserved tail carry prior observations.""" + monthly = Parameter( + "c_cpi_u", + data={ + "2025-09-01": 100, + # October has no observation, as in the 2025 BLS series. + "2025-11-01": 120, + "2025-12-01": 130, + **{f"2026-{month:02d}-01": 130 + month * 10 for month in range(1, 7)}, + # Calendar-year forecasts must not fill July and August. + "2027-02-01": 999, + }, + ) + projection = Parameter("projection", data={"2027-01-01": 888}) + + # October carries September's 100; July and August carry June's 190. + assert get_average_for_12_months_ending_august( + monthly, 2026, projection + ) == pytest.approx(1_820 / 12) + + +def test_published_tax_parameters_survive_cpi_refresh(): + """Revised CPI cannot overwrite the IRS amounts encoded in the source YAML.""" + parameter_dir = Path(__file__).parents[4] / "parameters" + parameters = ParameterNode( + data={ + "gov": { + "irs": { + "uprating": {"values": {"2026-01-01": 1}}, + }, + } + } + ) + parameters.gov.add_child("bls", ParameterNode("gov.bls", data={})) + parameters.gov.bls.add_child("cpi", PARAMETERS.gov.bls.cpi.clone()) + irs = parameters.gov.irs + irs.add_child("deductions", ParameterNode("gov.irs.deductions", data={})) + irs.add_child("ald", ParameterNode("gov.irs.ald", data={})) + irs.deductions.add_child( + "standard", + ParameterNode( + "gov.irs.deductions.standard", + directory_path=str(parameter_dir / "gov/irs/deductions/standard"), + ), + ) + irs.ald.add_child( + "educator_expense", + ParameterNode( + "gov.irs.ald.educator_expense", + directory_path=str(parameter_dir / "gov/irs/ald/educator_expense"), + ), + ) + published = [ + (parameter, value.instant_str, value.value) + for subtree in (irs.deductions.standard, irs.ald.educator_expense) + for parameter in subtree.get_descendants() + if isinstance(parameter, Parameter) + for value in parameter.values_list + ] + + original_index = get_irs_cpi(parameters, 2025) + cpi = parameters.gov.bls.cpi.c_cpi_u + cpi.update(period="month:2025-08-01:1", value=2 * cpi("2025-08-01")) + assert get_irs_cpi(parameters, 2025) != original_index + for year in (2026, 2027): + irs.uprating.update( + period=f"year:{year}-01-01:1", value=get_irs_cpi(parameters, year - 1) + ) + + # Re-run the statutory extensions and ordinary metadata uprating from + # the source amounts, rather than a tree that already contains forecasts. + extend_dependent_standard_deduction_parameters(parameters, 2027) + extend_educator_expense_cap(parameters, 2027) + propagate_parameter_metadata(parameters) + uprate_parameters(parameters) + + for parameter, date, value in published: + assert parameter(date) == value, (parameter.name, date) + assert irs.deductions.standard.amount.SINGLE("2026-01-01") == 16_100 + assert irs.deductions.standard.dependent.amount("2026-01-01") == 1_350 + assert ( + irs.deductions.standard.dependent.additional_earned_income("2026-01-01") == 450 + ) + assert irs.ald.educator_expense.cap("2026-01-01") == 350 + + def test_irs_cola_follows_1f3_on_a_synthetic_index(): """COLA = C-CPI-U(prior year) / (CPI(base) x C-CPI-U(2016) / CPI(2016)) - 1.""" parameters = _synthetic_irs_parameters() @@ -501,7 +657,8 @@ def test_irs_cola_follows_1f3_on_a_synthetic_index(): assert get_irs_cola_denominator(parameters, 1997) == pytest.approx(75) # Tax year 2031 reads the fully observed Sep 2029-Aug 2030 window (180). assert get_irs_cola(parameters, 2031, 1997) == pytest.approx(180 / 75 - 1) - # Tax year 2033 has no observed month and reads the 2032 projection point. + # Tax year 2033 has no observed month, so it reads CBO's tax-year + # projection (195), not the 2032 calendar-year point (199). assert get_irs_cola(parameters, 2033, 1997) == pytest.approx(195 / 75 - 1) # "The percentage (if any)": the Sep 2019-Aug 2020 window (60) is below # the denominator, so the tax year 2021 COLA is zero, not negative. @@ -561,10 +718,14 @@ def encoded_dependent_standard_deduction_values(name): def test_dependent_standard_deduction_encoded_values_take_precedence(): - """IRS and CBO values in the YAML survive the statutory extension.""" + """IRS values in the YAML survive the statutory extension. + + Every encoded value is an IRS publication that the statute reproduces, + so precedence for a non-statutory value is checked on the synthetic tree + in the next test. + """ dependent = PARAMETERS.gov.irs.deductions.standard.dependent - statute_differs = [] - for name, base, base_year in DEPENDENT_STANDARD_DEDUCTION_STATUTORY_BASES: + for name, _, _ in DEPENDENT_STANDARD_DEDUCTION_STATUTORY_BASES: parameter = getattr(dependent, name) # The 0001 placeholder in additional_earned_income.yaml is not a year. encoded = { @@ -574,14 +735,6 @@ def test_dependent_standard_deduction_encoded_values_take_precedence(): } for year, value in encoded.items(): assert parameter(f"{year}-01-01") == value, (name, year) - if value != statutory_dependent_standard_deduction_amount( - base, base_year, year - ): - statute_differs.append((name, year)) - # The check only bites where an encoded value differs from the statutory - # computation on the model's index: CBO's floor does in 2031 and 2034 - # (#9608). - assert statute_differs def test_dependent_standard_deduction_extension_starts_after_last_encoded_year(): @@ -597,10 +750,19 @@ def months(start_year, level): cpi_u=Parameter( "cpi_u", data={**months(1986, 40), **months(1996, 100), **months(2015, 200)} ), - # Monthly observations end in August 2030; 2032 holds a projection. + # Monthly observations end in August 2030; 2032 holds a calendar-year + # point, which windows do not read. c_cpi_u=Parameter( "c_cpi_u", - data={**months(2015, 150), **months(2029, 190), "2032-02-01": 205}, + data={**months(2015, 150), **months(2029, 190), "2032-02-01": 211}, + ), + # CBO's projections of the 12 months ending the August before each + # tax year. + tax_year_projection=SimpleNamespace( + cpi_u=Parameter("cpi_u_projection", data={"2033-01-01": 410}), + c_cpi_u=Parameter( + "c_cpi_u_projection", data={"2032-01-01": 190, "2033-01-01": 205} + ), ), ) # A node, so Parameter.update can reach a parent. @@ -632,13 +794,13 @@ def months(start_year, level): assert dependent.additional_earned_income("2030-01-01") == 999 # Denominators: 1987 base 40 x 150 / 200 = 30; 1997 base 100 x 150 / 200 = 75. # 2031 reads the observed Sep 2029-Aug 2030 window (190); 2032 has no - # observed month and no projection point of its own, so it reads 190 too. + # observed month and reads its tax-year projection, also 190. # Floor: $500 x (190 / 30 - 1) = $2,666.67, rounded down to $2,650. # Addition: $250 x (190 / 75 - 1) = $383.33, rounded down to $350. for year in (2031, 2032): assert dependent.amount(f"{year}-01-01") == 3_150 assert dependent.additional_earned_income(f"{year}-01-01") == 600 - # 2033 reads the 2032 projection point (205). + # 2033 reads its tax-year projection (205), not the calendar-year point. # Floor: $500 x (205 / 30 - 1) = $2,916.67, rounded down to $2,900. # Addition: $250 x (205 / 75 - 1) = $433.33, rounded down to $400. assert dependent.amount("2033-01-01") == 3_400 @@ -674,6 +836,42 @@ def test_dependent_standard_deduction_projections_follow_statute(): assert dependent.amount("2042-01-01") == 1_900 +def test_statute_on_the_index_reproduces_cbo_dependent_floor_projections(): + """CBO's projected floor is 63(c)(4) applied to CBO's projected index. + + CBO Tax Parameters, February 2026, sheet 1: row 68 ("Dependent filers + (unearned)") by tax year. The model derives the floor from row 153, the + C-CPI-U over the 12 months ending the previous August, for 2028-2036, + and from BLS observations for 2027, so matching row 68 in every year + checks both the index and the statute encoding. + """ + cbo_floor = { + 2027: 1_400, + 2028: 1_450, + 2029: 1_450, + 2030: 1_500, + 2031: 1_500, + 2032: 1_550, + 2033: 1_600, + 2034: 1_600, + 2035: 1_650, + 2036: 1_700, + } + dependent = PARAMETERS.gov.irs.deductions.standard.dependent + for year, amount in cbo_floor.items(): + assert dependent.amount(f"{year}-01-01") == amount, year + + +def test_irs_uprating_is_the_c_cpi_u_for_12_months_ending_august(): + """1(f)(6)(B): the index for tax year T averages Sep T-2 through Aug T-1.""" + uprating = PARAMETERS.gov.irs.uprating + # CBO's actual tax year 2026 index (Tax Parameters row 153): 177.114. + assert uprating("2026-01-01") == pytest.approx(177.114, abs=5e-4) + # No BLS observation covers Sep 2026-Aug 2027: CBO's projection. + assert uprating("2028-01-01") == pytest.approx(185.881) + assert uprating("2036-01-01") == pytest.approx(217.68) + + def statutory_educator_expense_cap(year): """26 U.S.C. 62(d)(3): $250 plus its increase, to the nearest $50.""" base, base_year = EDUCATOR_EXPENSE_CAP_STATUTORY_BASE @@ -721,15 +919,16 @@ def test_educator_expense_cap_projections_follow_statute(): previous = value assert cap("2150-01-01") == cap("2100-01-01") - # Hand anchors. They rest on the model's CPI projection, so a CBO refresh - # can move them; 2031 and 2032 sit within $5 of the $125 step. The 2014 - # denominator is 134.30. The increase, $250 x the COLA, rounds to $100 - # while under $125: $89.57 in 2027, $112.80 in 2030 and $120.06 in 2031. - # It rounds to $150 from $127.32 in 2032 to $150.03 in 2035. Chaining - # from the rounded 2026 $350 reached $400 in 2030. - for year in range(2027, 2032): + # Hand anchors. They rest on the model's CPI projection (CBO's tax-year + # C-CPI-U from 2028), so a CBO refresh can move them; 2032 sits $0.23 + # below the $125 step. The 2014 denominator is 134.30. The increase, + # $250 x the COLA, rounds to $100 while under $125: $89.57 in 2027, + # $110.38 in 2030 and $124.77 in 2032 (index 201.335). It rounds to $150 + # from $132.16 in 2033 (index 205.302) to $171.34 in 2038. Chaining from + # the rounded 2026 $350 reached $400 in 2030. + for year in range(2027, 2033): assert cap(f"{year}-01-01") == 350, year - for year in range(2032, 2036): + for year in range(2033, 2039): assert cap(f"{year}-01-01") == 400, year @@ -744,10 +943,19 @@ def months(start_year, level): cpi = SimpleNamespace( cpi_u=Parameter("cpi_u", data={**months(2013, 100), **months(2015, 200)}), - # Monthly observations end in August 2030; 2032 holds a projection. + # Monthly observations end in August 2030; 2032 holds a calendar-year + # point, which windows do not read. c_cpi_u=Parameter( "c_cpi_u", - data={**months(2015, 150), **months(2029, 102), "2032-02-01": 126}, + data={**months(2015, 150), **months(2029, 102), "2032-02-01": 999}, + ), + # CBO's projections of the 12 months ending the August before each + # tax year. + tax_year_projection=SimpleNamespace( + cpi_u=Parameter("cpi_u_projection", data={"2033-01-01": 300}), + c_cpi_u=Parameter( + "c_cpi_u_projection", data={"2032-01-01": 110, "2033-01-01": 126} + ), ), ) # A node, so Parameter.update can reach a parent. @@ -768,12 +976,13 @@ def months(start_year, level): assert cap("2029-01-01") == 250 assert cap("2030-01-01") == 999 # Denominator: 2014 base 100 x 150 / 200 = 75. 2031 reads the observed - # Sep 2029-Aug 2030 window (102); 2032 has no observed month and no - # projection point of its own, so it reads 102 too. + # Sep 2029-Aug 2030 window (102). # $250 x (102 / 75 - 1) = $90, nearest to $100 (rounding down gives $50). - for year in (2031, 2032): - assert cap(f"{year}-01-01") == 350, year - # 2033 reads the 2032 projection point (126). + assert cap("2031-01-01") == 350 + # 2032 has no observed month and reads its tax-year projection (110). + # $250 x (110 / 75 - 1) = $116.67, nearest to $100. + assert cap("2032-01-01") == 350 + # 2033 reads its tax-year projection (126), not the calendar-year point. # $250 x (126 / 75 - 1) = $170, nearest to $150 (rounding up gives $200). assert cap("2033-01-01") == 400 assert cap("2040-01-01") == 400 diff --git a/policyengine_us/tests/policy/contrib/states/ca/ab2591/ca_ab2591.yaml b/policyengine_us/tests/policy/contrib/states/ca/ab2591/ca_ab2591.yaml index 760f94e4e75..2461bd119f8 100644 --- a/policyengine_us/tests/policy/contrib/states/ca/ab2591/ca_ab2591.yaml +++ b/policyengine_us/tests/policy/contrib/states/ca/ab2591/ca_ab2591.yaml @@ -2,7 +2,7 @@ # Allows taxpayers to elect a standard deduction equal to the federal # poverty line for their household size. # Effective for taxable years beginning on or after July 1, 2027. -# 2027 federal poverty guidelines (CONTIGUOUS_US): +# Existing 2027 federal poverty guideline projections (CONTIGUOUS_US): # first person = $16,334 # additional person = $5,813 # 1-person FPL = $16,334 @@ -168,6 +168,9 @@ absolute_error_margin: 1 reforms: policyengine_us.reforms.states.ca.ab2591.ab2591.ca_ab2591 input: + # Synthetic forecast assumption retained from the original fixture to + # isolate reform inactivity; not a published California tax-year amount. + gov.states.ca.tax.income.deductions.standard.amount.SINGLE: 6_009.22 gov.contrib.states.ca.ab2591.in_effect: false people: person1: @@ -182,9 +185,8 @@ members: [person1] state_code: CA output: - # 2025 indexed value ($5,706) uprated by CA CPI to 2027; the 2027 - # CA CPI point is an IRS-uprating projection, so it reflects the - # observed chained-CPI actuals through June 2026. + # The inactive reform leaves the synthetic baseline amount supplied + # above unchanged. ca_standard_deduction: 6_009.22 - name: Non-California filer unaffected by the reform. diff --git a/policyengine_us/tests/policy/contrib/states/ut/dependent_exemption/ut_dependent_exemption.yaml b/policyengine_us/tests/policy/contrib/states/ut/dependent_exemption/ut_dependent_exemption.yaml index 49278857c1e..ae021fe146e 100644 --- a/policyengine_us/tests/policy/contrib/states/ut/dependent_exemption/ut_dependent_exemption.yaml +++ b/policyengine_us/tests/policy/contrib/states/ut/dependent_exemption/ut_dependent_exemption.yaml @@ -1,8 +1,15 @@ +# The baseline exemption inputs below retain the original fixture's +# synthetic 2026 forecast assumption to isolate reform behavior. The $2,159 +# per-dependent amount is not asserted as a published Utah tax-year amount. - name: Under-18 repeal zeroes the young dependent, preserves the older one. period: 2026 absolute_error_margin: 1 reforms: policyengine_us.reforms.states.ut.dependent_exemption.ut_dependent_exemption_reform input: + gov.states.ut.tax.income.credits.taxpayer.personal_exemption: 2_159 + # Retain the original fixture's synthetic phase-out forecast as well; + # this is not asserted as a published Utah tax-year threshold. + gov.states.ut.tax.income.credits.taxpayer.phase_out.threshold.HEAD_OF_HOUSEHOLD: 27_939.15 gov.contrib.states.ut.dependent_exemption.in_effect: true gov.contrib.states.ut.dependent_exemption.amount: 0 gov.contrib.states.ut.dependent_exemption.age_limit.in_effect: true @@ -27,11 +34,11 @@ members: [person1, child1, person2] state_code: UT output: - # Only the 19-year-old keeps the uprated baseline per-dependent - # exemption (about $2,159 in 2026). + # Only the 19-year-old keeps the synthetic baseline per-dependent + # exemption supplied above. ut_personal_exemption: 2_159 # About $130 above the same household's baseline tax of $1,379: the - # taxpayer credit shrinks by 6% of the repealed ~$2,159 exemption. + # taxpayer credit shrinks by 6% of the repealed $2,159 exemption. # Asserts the exemption flows through to the bottom line. ut_income_tax: 1_508 @@ -40,6 +47,7 @@ absolute_error_margin: 1 reforms: policyengine_us.reforms.states.ut.dependent_exemption.ut_dependent_exemption_reform input: + gov.states.ut.tax.income.credits.taxpayer.personal_exemption: 2_159 gov.contrib.states.ut.dependent_exemption.in_effect: true people: person1: @@ -60,7 +68,7 @@ members: [person1, child1, person2] state_code: UT output: - # Two dependents at the uprated baseline amount. + # Two dependents at the synthetic baseline amount supplied above. ut_personal_exemption: 4_318 - name: A flat reform amount applies to every dependent when the age limit is off. @@ -125,6 +133,7 @@ absolute_error_margin: 1 reforms: policyengine_us.reforms.states.ut.dependent_exemption.ut_dependent_exemption_reform input: + gov.states.ut.tax.income.credits.taxpayer.personal_exemption: 2_159 gov.contrib.states.ut.dependent_exemption.amount: 0 people: person1: @@ -146,5 +155,5 @@ state_code: UT output: # in_effect is false, so the $0 amount does not apply: two dependents - # at the uprated baseline amount. + # at the synthetic baseline amount supplied above. ut_personal_exemption: 4_318 diff --git a/policyengine_us/variables/gov/states/wi/tax/income/wi_standard_deduction.py b/policyengine_us/variables/gov/states/wi/tax/income/wi_standard_deduction.py index 362bdf7f14b..ad2746b778c 100644 --- a/policyengine_us/variables/gov/states/wi/tax/income/wi_standard_deduction.py +++ b/policyengine_us/variables/gov/states/wi/tax/income/wi_standard_deduction.py @@ -26,7 +26,20 @@ def wi_standard_deduction_for_income(income, filing_status, parameters, period): deduction.standard.phase_out.head_of_household.calc(income), ], ) - return max_(0, max_amount - phase_out_amount) + amount = max_amount - phase_out_amount + # 71.05(22)(dp)1 and Form 1-ES use the single formula above the + # published HOH crossover. Continuing the HOH marginal scale after a + # rounded crossover retains a small rounding offset from that formula. + hoh_switch = deduction.standard.phase_out.head_of_household.thresholds[2] + single_amount = ( + deduction.standard.max.SINGLE - deduction.standard.phase_out.single.calc(income) + ) + amount = where( + (filing_status == statuses.HEAD_OF_HOUSEHOLD) & (income > hoh_switch), + single_amount, + amount, + ) + return max_(0, amount) class wi_standard_deduction(Variable): @@ -43,6 +56,7 @@ class wi_standard_deduction(Variable): "https://docs.legis.wisconsin.gov/misc/lfb/informational_papers/january_2023/0002_individual_income_tax_informational_paper_2.pdf", # Standard Deduction Table (keyed to WI income, line 7) and the statute, corroborating the phaseout: "https://www.revenue.wi.gov/TaxForms2025/2025-Form1-inst.pdf#page=35", + "https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=2", "https://docs.legis.wisconsin.gov/statutes/statutes/71/i/05/22", ) defined_for = StateCode.WI