Skip to content

Fix and add retirement contribution calibration targets#554

Open
PavelMakarchuk wants to merge 4 commits intomainfrom
calibrate-retirement-contributions
Open

Fix and add retirement contribution calibration targets#554
PavelMakarchuk wants to merge 4 commits intomainfrom
calibrate-retirement-contributions

Conversation

@PavelMakarchuk
Copy link
Collaborator

Summary

  • Correct traditional_ira_contributions target from $25B to $13.2B — the prior value included non-deductible contributions, but since policyengine-us uses the raw value directly as the ALD (no deductibility logic), the target must match the actual deduction claimed on returns
  • Add traditional_401k_contributions target: $567.9B — employee elective deferrals from BEA/FRED National Income Accounts
  • Add self_employed_pension_contribution_ald target: $29.5B — Keogh plan deductions from SOI 1304
  • Remove roth_ira_contributions target ($39B) — structurally $0 due to CPS allocation bug where traditional IRA always exhausts the IRA limit first

Updates both loss.py (HARD_CODED_TOTALS) and etl_national_targets.py.

Benchmark Sources

Target Value Source
traditional_ira_contributions $13.2B IRS SOI 1304 Table 1.4 (TY 2022, "IRA payments", col 124)
traditional_401k_contributions $567.9B FRED Y351RC1A027NBEA ($815.4B total DC) minus FRED W351RC0A144NBEA ($247.5B employer-only)
self_employed_pension_contribution_ald $29.5B IRS SOI 1304 Table 1.4 (TY 2022, "Payments to a Keogh plan", col 116)

Model gap before this change

Variable Model (2026) Benchmark
traditional_ira_contributions $26.8B $13.2B (2x over — was calibrated to wrong target)
traditional_401k_contributions $245.4B $567.9B (-57% under — no target)
self_employed_pension_contribution_ald $5.9B $29.5B (-80% under — no target)
roth_ira_contributions $0.0B $39B target (structurally broken)

Test plan

  • CI passes (formatting, existing tests)
  • Re-run calibration and verify targets are closer to benchmarks
  • Verify no regression in other calibration targets

Closes #553

🤖 Generated with Claude Code

PavelMakarchuk and others added 2 commits February 25, 2026 17:11
- Correct traditional_ira_contributions: $25B → $13.2B (SOI 1304
  Table 1.4 actual deduction, not total contributions)
- Add traditional_401k_contributions: $567.9B (BEA/FRED employee
  DC contributions)
- Add self_employed_pension_contribution_ald: $29.5B (SOI 1304
  Table 1.4 Keogh plan deduction)
- Remove roth_ira_contributions: structurally $0 due to CPS
  allocation bug (#553)
- Update both loss.py and etl_national_targets.py

Closes #553

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace sequential waterfall with proportional allocation based on
administrative data. The old waterfall gave 401(k) first priority,
consuming all of RETCB_VAL and leaving IRA contributions at $0 for
every record. The Roth IRA allocation was also mathematically
guaranteed to produce $0.

The new approach splits RETCB_VAL proportionally:
- DC vs IRA: 90.8% / 9.2% (BEA/FRED vs IRS SOI)
- Within DC: 85% traditional / 15% Roth (Vanguard/PSCA)
- Within IRA: 39.2% traditional / 60.8% Roth (IRS SOI Tables 5 & 6)

All fractions are stored in imputation_parameters.yaml with sources.
Contribution limits are still enforced.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PavelMakarchuk and others added 2 commits February 25, 2026 18:25
- Split 401(k) target: $567.9B total employee DC deferrals (BEA/FRED)
  into traditional $482.7B (85%) and Roth $85.2B (15%) using Vanguard
  How America Saves 2024 dollar share estimate
- Add roth_ira_contributions target: $35.0B from IRS SOI Accumulation
  Tables 5 & 6 (TY 2022) — direct administrative source
- Update etl_national_targets.py in parallel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes CI failure caused by DE TANF deficit_rate parameter missing
history before 2024-10-01. The fix was merged in policyengine-us
PR #7170 but uv.lock was pinned at 1.570.7.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@PavelMakarchuk PavelMakarchuk marked this pull request as ready for review February 26, 2026 01:54
@PavelMakarchuk PavelMakarchuk requested review from MaxGhenis and baogorek and removed request for baogorek February 26, 2026 01:54
Copy link
Collaborator

@baogorek baogorek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just please update this one bullet point in the PR body (if this is indeed correct):

Says:

  • Remove roth_ira_contributions target ($39B) — structurally $0 due to CPS allocation bug where traditional IRA always exhausts the IRA limit first

But:
code actually keeps roth_ira_contributions and updates it from $39B to $35.0B in both loss.py and etl_national_targets.py (which it can do be

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.

Add calibration targets for retirement contributions

2 participants