-
Notifications
You must be signed in to change notification settings - Fork 201
Add NY tax calculation for filters with AGI above $25 million #6914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
The supplemental tax calculation was using thresholds[-1] to detect high AGI cases, but since 2022 that threshold is infinity (due to NY moving to one less bracket). This meant the flat 10.9% rate was never triggered for AGI > $25M. Added explicit high_agi_threshold parameter ($25M) and updated the supplemental tax logic to use it instead of thresholds[-1]. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Issue Found and FixedAfter comparing our calculation with TaxAct/TaxSim results, we discovered our NY tax calculation was ~$150K too low for filers with AGI above $25 million. The ProblemFor NY AGI > $25M, Worksheet 11 in the IT-201 instructions requires:
The supplemental tax code was designed to detect this case using: agi_limit = single.thresholds[-1] # Last bracket threshold
# ...
return where(ny_agi > agi_limit, supplemental_tax_high_agi, ...)However, starting in 2022, NY moved to one less bracket and the parameter file was updated: - threshold:
2021-01-01: 25_000_000
2022-01-01: .inf # ← Last threshold is now infinity!Since The Fix
Results
Now matches TaxAct exactly (within rounding). |
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6914 +/- ##
===========================================
- Coverage 100.00% 95.55% -4.45%
===========================================
Files 11 1 -10
Lines 146 45 -101
Branches 0 2 +2
===========================================
- Hits 146 43 -103
- Misses 0 1 +1
- Partials 0 1 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@DTrim99 checks fail |
Use +100 instead of +1 when looking up marginal rates at the high AGI threshold to avoid float32 precision issues that caused incorrect comparisons at exactly $25,000,000. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
policyengine_us/variables/gov/states/ny/tax/income/ny_supplemental_tax.py
Show resolved
Hide resolved
policyengine_us/parameters/gov/states/ny/tax/income/supplemental/high_agi_threshold.yaml
Outdated
Show resolved
Hide resolved
| import numpy as np | ||
|
|
||
|
|
||
| def get_last_finite_threshold(scale): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a separate function for this? Can we not just do it in the formula? I assume we wont reuse this?
| ) | ||
| # Create array for marginal_rates lookup | ||
| # Use +100 for float32 precision at $25M threshold | ||
| high_agi_lookup = ny_agi * 0 + high_agi_threshold + 100 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not +1 to account for the threshold. Not sure why we need a $100 buffer
📋 PR Review - NY Supplemental Tax Fix for High AGI (>5M)✅ Summary: APPROVEThis PR correctly fixes a critical bug in the NY supplemental tax calculation for high-income filers (AGI > $25 million). 🔍 The IssueFor NY AGI > $25M, the tax should be calculated as:
The previous code used - threshold:
2021-01-01: 25_000_000
2022-01-01: .inf # ← Last threshold is now infinity!Since ✅ The FixAdded a helper function def get_last_finite_threshold(scale):
thresholds = scale.thresholds
if np.isinf(thresholds[-1]):
return thresholds[-2] # Returns $25M
return thresholds[-1]🟢 Validation Results
✅ Test Cases Added
🟡 Minor Suggestions (Optional)
🚀 Ready to MergeAll CI checks pass and the fix correctly restores the $25M threshold behavior for 2022+ tax years. 🤖 Automated review by Claude Code |
Fixes #6872