Skip to content

Fix Arizona property tax credit Schedule 2 thresholds - #9779

Open
MaxGhenis wants to merge 1 commit into
mainfrom
fix-az-ptc-schedule-2-thresholds
Open

MaxGhenis wants to merge 1 commit into
mainfrom
fix-az-ptc-schedule-2-thresholds

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

Summary

Arizona's property tax credit table for a claimant who lived with a spouse or other persons (ARS 43-1072(B)(2), Form 140PTC Schedule 2) had every band threshold one dollar low. cohabitating.yaml stored 2,500, 2,650, ..., 5,500 as the lower bounds of the second through last bands, but the statute and the 2021-2025 forms start those bands at 2,501, 2,651, ..., 5,501:

Household income Credit
$0-2,500 $502
2,501-2,650 479
2,651-2,800 457
... ...
5,351-5,500 56
5,501 and up 0

A household with income of exactly $2,500, $2,650, ..., $5,500 therefore got the next band's amount, $22-23 less, and one at $5,500 got nothing instead of $56. ARS 43-1072(A)(3)(b) limits the credit to combined income "less than five thousand five hundred one dollars", so $5,500 qualifies. Every threshold after zero is now one dollar higher, matching Schedule 1 (living_alone.yaml), which already used 1,751, 1,851, ..., 3,751.

Law

  • ARS 43-1072: (A)(3)(a) "less than three thousand seven hundred fifty-one dollars" (living alone); (A)(3)(b) "less than five thousand five hundred one dollars" (living with others); the (B)(1) and (B)(2) tables.
  • Form 140PTC, page 2, Schedules 1 and 2, for 2021, 2022, 2023, 2024 and 2025. I parsed both tables from the statute page and from page 2 of each year's form. All five years match the statute row for row on both schedules, including "3,751 and up" and "5,501 and up" at $0.
  • The 2025 Form 140PTC instructions (lines 11a and 11b, page 5) tell the filer to find the line 10 household income in the schedule.

Incomes with cents

SingleAmountTaxScale.calc uses numpy.digitize with right=False. A band therefore covers its lower bound up to, but not including, the next band's lower bound, and $2,500.50 gets the $0-2,500 amount ($502), as if the cents were dropped. The statute lists whole-dollar bands and leaves the gap between, say, $2,500 and $2,501 unassigned. It does state the income limit as "less than" $5,501 (or $3,751), one dollar above the last band's upper bound, so the last band covers every income below the limit. Reading every band the same way gives this result, and it needs no formula change.

The alternative is to round to the nearest dollar. Form 140PTC line 10 takes whole dollars, and the 2025 Form 140 instructions (page 4) say to round to the nearest whole dollar. The 140PTC instructions have no rounding rule. Rounding would move an income with 50 cents or more into the next band, for example $2,500.50 to $479 and $5,500.50 to $0, which contradicts (A)(3)(b) at the top edge. A comment in both parameter files records this choice, and the tests pin it.

Changes

  • cohabitating.yaml: thresholds after zero become 2_501, 2_651, ..., 5_501.
  • Both schedule files: a comment on band edges and cents, and direct links to each year's form PDF (page 2) in place of the fillable-form landing page. Schedule 1's 2022 reference linked to the 2021 form and now links to the 2022 one. The statute citation names (A)(3) as well as (B).
  • az_property_tax_credit.yaml: the existing "filer at 79 meets criteria" case had household income of $5,500 on Schedule 2 and expected $0. It now expects $56: taxes paid are 100 + 0.15 × 1,500 = 325, so the credit is the table amount.

Tests

  • az_property_tax_credit_schedules.yaml (new, 142 cases), generated from the statute table. For each schedule it covers:

    • $0;
    • both sides of every band edge;
    • $X.50 above each band's upper bound;
    • $0.99 below the (A)(3) limit, and the limit itself ($3,751 and $5,501);
    • 2021 repeats.

    It also has six household-path cases where income and schedule are computed rather than input: a married couple at $2,500 and $2,501, a single claimant living with an adult child at $5,500 and $5,501, and a single claimant living alone at $3,750 and $3,751.

  • test_az_property_tax_credit_schedules.py (new, 65 tests): a differential test against an independent transcription of the statute tables, for every whole-dollar income from $0 to $7,000 and cents around every edge, in each year from 2021 to 2026. It runs through the parameter scales and through az_property_tax_credit in one vectorised Simulation per schedule.

  • On main, 48 of the 153 YAML cases in the two credit test files fail: every Schedule 2 upper edge and the cents cases, the 2021 repeats, the household cases at $2,500 and $5,500, and the corrected $5,500 case. Every Schedule 1 case passes on main, as it should. 19 of the 65 Python tests fail on main, all of them Schedule 2.

  • On this branch, all 625 YAML tests under states/az pass, as do test_parameter_files.py, test_parameter_scale_thresholds.py and the code_health folder.

Invariants

These hold for every income, in every year from 2021 to 2026, on both schedules, and are tested:

  1. Matches the statute. The scale equals the statute table at every whole-dollar income, and at cents near every edge it equals the band that holds the income's whole dollars.
  2. Contiguous transcription. The transcribed bands are contiguous whole-dollar ranges starting at $0, and the last upper bound is one dollar below the (A)(3) limit.
  3. Never rises. The amount never rises as income rises (checked on a $0.25 grid from $0 to $7,000).
  4. Bounds. Below the limit the amount is between $56 and $502; at and above the limit it is $0.
  5. Cents. An income with cents gets the same amount as its whole dollars.

Microsimulation impact

I ran a real microsimulation on the default dataset (populace_us_2024.h5@populace-us-2024-spm-20260909) on policyengine-core 3.32.15. It compared main at 6b0e773 with this branch, one period per process, under the shared heavy-run lock with a 24 GB footprint watchdog. Peak footprints were 9.1-9.4 GB.

2025 2026
Tax units with a changed credit 0 of 79,729 0 of 79,729
az_property_tax_credit, weighted total (both sides) $40,666,618 $40,957,022
Eligible units / eligible on Schedule 2 141 / 92 141 / 92
Eligible Schedule 2 units with income below $5,501 6 6
Eligible Schedule 2 units with income in a moved window [T, T+1), T = 2,500, 2,650, ..., 5,500 0 0

The fix changes the credit only for Schedule 2 incomes in those $1 windows, and the dataset has none. No aggregate moves.

Interaction with #9762 and #9770

Neither PR touches either schedule file. Both edit az_property_tax_credit.yaml, appending cases at the end; this PR changes one case in the middle, and git merges both heads with this branch cleanly.

No test in either PR depends on the old one-dollar-low thresholds.

axiom: us-az:statutes/43-1072#shared_household_credit_band encoded-correct

rulespec-us us-az/statutes/43-1072.yaml (main at 9f38330fb) encodes the Schedule 2 bounds as lower 0, 2501, 2651, ..., 5351 and upper 2500, 2650, ..., 5500, and shared_household_income_limit as 5501. Its companion tests in us-az/statutes/43-1072.test.yaml cover:

  • household income 2,500: band 0, $502;
  • household income 5,500: band 20, $56;
  • household income 5,501: eligible_under_shared_household_income_path does not hold, credit $0.

Two related gaps, neither in this PR's scope:

🤖 Generated with Claude Code

ARS 43-1072(B)(2) and Form 140PTC Schedule 2 (2021-2025) give the bands
for a claimant living with others as $0-2,500 -> $502, 2,501-2,650 -> $479,
..., 5,351-5,500 -> $56, 5,501 and up -> $0. The single_amount scale stored
each band's lower bound one dollar low (2,500, 2,650, ..., 5,500), so incomes
of exactly 2,500, 2,650, ..., 5,500 got the next band's amount and 5,500 got
nothing. Each threshold after zero is now one dollar higher, as Schedule 1
already is.

Both schedule files document how cents between whole-dollar bands are
treated (the lower band, matching the (A)(3) "less than" limits), cite each
year's form PDF directly, and Schedule 1's 2022 reference no longer points
at the 2021 form.

Tests: YAML cases at every band edge of both schedules, the (A)(3) limits,
cents between bands and the household path; a differential test of every
whole-dollar income and of cents around every edge against a transcription
of the statute, 2021-2026, through the scales and a vectorised simulation;
monotonicity and bounds invariants. The existing case at $5,500 expected $0
and now expects $56.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant