Skip to content

Apply ACA PTC formula to historical premiums#8531

Merged
hua7450 merged 6 commits into
PolicyEngine:mainfrom
daphnehanse11:codex/historical-aca-ptc
Jun 2, 2026
Merged

Apply ACA PTC formula to historical premiums#8531
hua7450 merged 6 commits into
PolicyEngine:mainfrom
daphnehanse11:codex/historical-aca-ptc

Conversation

@daphnehanse11
Copy link
Copy Markdown
Collaborator

Summary

  • apply the ACA PTC formula starting in 2018, the first year with rating-area SLCSP premium data
  • keep pre-2018 ACA PTC at zero until older rating-area premium data is added
  • add unit-style and integration regression coverage for 2023 ACA PTC calculations

Fixes #8527.

Tests

uv run python -m policyengine_core.scripts.policyengine_command test -c policyengine_us policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_ptc.yaml policyengine_us/tests/policy/baseline/gov/aca/ptc/integration.yaml

Also run in the original workspace:

uv run python -m policyengine_core.scripts.policyengine_command test -c policyengine_us policyengine_us/tests/policy/baseline/gov/aca

@codecov
Copy link
Copy Markdown

codecov Bot commented May 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (fa285ae) to head (6564ef9).
⚠️ Report is 32 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #8531   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            5         2    -3     
  Lines           62        46   -16     
=========================================
- Hits            62        46   -16     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@daphnehanse11 daphnehanse11 force-pushed the codex/historical-aca-ptc branch from 8f20740 to 1753cbb Compare May 29, 2026 18:52
@daphnehanse11 daphnehanse11 marked this pull request as ready for review June 1, 2026 16:28
Copy link
Copy Markdown
Collaborator

@PavelMakarchuk PavelMakarchuk left a comment

Choose a reason for hiding this comment

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

Program Review — PR #8531 (ACA PTC formula activation 2018+)

Source Documents

  • PDFs: IRS Rev. Proc. 2017-36 (2018), 2018-34 (2019), 2019-29 (2020) — listed in /tmp/review-program-pdf-manifest.md
  • Year: 2018+ activation (formula rename formula_2024formula_2018)
  • Scope: PR changes only (3 new parameter entries × 2 files, 1 variable formula rename, 3 test files updated)

🔴 Critical (Must Fix)

No critical issues found.

  • All 36 new parameter cells (2018/2019/2020 × initial+final × 6 brackets) match the cited IRS Revenue Procedures exactly.
  • The formula-rename mechanic is correct (formula_2018 with default formula → 0 for pre-2018 periods).
  • No hard-coded literals leaked into aca_ptc.py; downstream consumers (assigned_aca_ptc, premium_tax_credit, marketplace_net_premium, etc.) integrate cleanly.
  • CI failure (Contrib other-shard-1) is a GitHub Actions runner-shutdown timeout, not caused by this PR — same shard failing identically on unrelated branches (see /tmp/review-program-ci-failure.md).

🟡 Should Address

  1. SLCSP backward-uprating silent inconsistency (policyengine_us/variables/gov/aca/ptc/aca_ptc.py)
    benchmark_premium_uprating.yaml carries national-average SLCSP values for 2014–2017 ($273/$276/$299/$359). If slcsp uprates backward via this parameter, it would return positive SLCSP for 2014–2017 while aca_ptc returns 0 for those years — silent inconsistency. Either (a) document in aca_ptc.py docstring that the 2018 cutoff is gated on rating-area data availability (parameters/gov/aca/state_rating_area_cost.yaml starts 2018-01-01), not on statute (IRC §36B applies from 2014), or (b) extend formula_2018 to plain formula and let $0 SLCSP naturally yield $0 PTC.

  2. Missing period metadata in parameter YAMLs
    policyengine_us/parameters/gov/aca/required_contribution_percentage/initial.yaml and …/final.yaml lack the period: metadata field (REQUIRED per the parameter-patterns skill). Add period: year.

  3. Missing 2017↔2018 boundary test (same household) (policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_ptc.yaml)
    PR adds a 2017 zero test and a 2023 non-zero test, but no paired same-household test at the new activation boundary. Add a pair with identical inputs at period: 2017 (→ 0) and period: 2018 (→ non-zero) to lock in formula_2018 and prevent off-by-one regressions on the activation year.

  4. Missing 2024 regression test
    The previous activation year was 2024. Existing tests cover 2023 (integration) and 2025 (unit) but no explicit 2024 unit test survives. Add a period: 2024 case mirroring the 2025 unit test to prove the rename created no coverage hole at the old gate year.

  5. Missing 400% FPL cliff tests for 2018/2019/2020 (policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_required_contribution_percentage.yaml)
    Original-ACA brackets define rates only through 300–400% FPL. Add aca_required_contribution_percentage tests for each of 2018/2019/2020 at aca_magi_fraction: 4.0 (top of bracket → max rate) and 4.01 (above 400% FPL → 0, the original-ACA cliff). The existing fraction-4.40 test belongs to the ARPA schedule and does not exercise the cliff.

  6. Missing ARPA-era (2021–2022) aca_ptc.yaml unit test
    formula_2018 now drives all years 2018+. Add at least one period: 2021 or period: 2022 unit test asserting that a zero contribution percentage under ARPA yields the full SLCSP as PTC — protects against future refactors accidentally reintroducing an ARPA-specific branch.

  7. Changelog filename / PR number mismatch (changelog.d/8527.fixed.md)
    Branch is codex/historical-aca-ptc; PR is #8531. Filename references issue/PR 8527. Confirm 8527 is the intended issue reference, or rename per branch-name convention.

🟢 Suggestions

  • 2015/2016/2017 unindexed cosmetic — the 2015-01-01 entries use the raw IRC §36B(b)(3)(A)(i) baseline (2.0/3.0/4.0/6.3/8.05/9.5). IRS published indexed tables for 2015 (Rev. Proc. 2014-37), 2016 (Rev. Proc. 2014-62), and 2017 (Rev. Proc. 2016-24). Since aca_ptc returns 0 pre-2018, this has no output impact — but adding a code comment noting these are unindexed statutory baselines would prevent future confusion.
  • Parameter description template — descriptions ("Initial (starting) contribution percentage…") do not match the PolicyEngine "[entity] [verb] [category] to this share under the … program" template. Federal IRS parameters often deviate, so this is optional.
  • Pre-existing 2026 reference (rp-25-25.pdf) lacks a #page= anchor — inconsistent with the new entries but out of scope for this PR.
  • 2018 integration test — consider an end-to-end integration case at the new boundary year to complement the 2023 LA integration test.
  • Inlining is_filer — single-use intermediate in aca_ptc.py; the explanatory comment justifies keeping it. Optional.

PDF Audit Summary

Category Count
Confirmed correct 36/36 (all 2018-2020 cells × initial+final, verified independently by regulatory agent and reconciliation against IRS Rev. Proc. PDF text)
Mismatches (code-path confirmed + visually verified) 0
Mismatches rejected (PDF audit misread branch) 36 — investigated and cleared
Unmodeled items 0

Note on the 36 rejected mismatches: The PDF-audit subagent read YAMLs from the local checkout, which is on branch fix-nj-filing-threshold-phantom-taxnot PR #8531's codex/historical-aca-ptc branch. The on-disk files therefore did not contain the PR's 2018/2019/2020 entries, and the audit reported them as missing. The reconciliation verifier (/tmp/review-program-codepath-1.md) re-read the PR diff at /tmp/review-program-diff.txt, confirmed every new entry is present and well-formed, and independently matched all 36 cells to the IRS Rev. Procs. The regulatory-accuracy agent (/tmp/review-program-regulatory.md) independently corroborated the same 36 matches. The audit's 36-mismatch claim is a false positive driven by branch state, not a real issue.

Validation Summary

Check Result
Regulatory Accuracy 0 critical, 2 should-fix (SLCSP backward-uprating note, 2015–2017 unindexed cosmetic)
Reference Quality 0 critical, 1 pre-existing warning (2026 ref missing #page=) — all 3 new refs well-formed
Code Patterns 0 critical, 2 should-fix (period metadata missing, changelog filename/PR-number)
Test Coverage 4 gaps (2017↔2018 boundary, 2024 regression, 400% FPL cliff for 2018-2020, ARPA-era unit test)
PDF Value Audit 36 confirmed / 0 real mismatches (36 false-positive mismatches investigated and cleared)
CI Status 25/26 pass; 1 unrelated runner-shutdown timeout on Contrib other-shard-1 (zero assertion failures, infra issue)

Review Severity: APPROVE (with should-fix items)

@daphnehanse11 daphnehanse11 force-pushed the codex/historical-aca-ptc branch from 99f3eac to c2a96e9 Compare June 2, 2026 14:14
@daphnehanse11
Copy link
Copy Markdown
Collaborator Author

Fixed the review items from #8531 (review).

Changes made:

  • Documented why aca_ptc applies the formula starting in 2018: PolicyEngine's rating-area SLCSP data currently begins in 2018.
  • Added period: year metadata to the initial/final ACA required contribution percentage parameters.
  • Restored the original-ACA 400% FPL cliff in aca_required_contribution_percentage by using ptc_income_eligibility for years where above-400% households are not eligible, while preserving ARPA/IRA years.
  • Added requested regression tests for:
    • 2017/2018 same-household ACA PTC boundary.
    • 2024 ACA PTC.
    • 2022 full SLCSP PTC when contribution percentage is zero.
    • 2018/2019/2020 contribution percentage at 400% FPL and just above 400% FPL.

Verification:

  • uv run python -m policyengine_core.scripts.policyengine_command test policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_required_contribution_percentage.yaml policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_ptc.yaml -c policyengine_us - 39 passed.
  • uv run python -m policyengine_core.scripts.policyengine_command test policyengine_us/tests/policy/baseline/gov/aca/ptc/integration.yaml -c policyengine_us - 4 passed.
  • uv run ruff format --check . - passed.
  • uv run ruff check . - passed.

The only warnings were dependency/test-runner startup noise (uv skipping old Windows numpy artifacts, IPython dependency SyntaxWarning, and pytest anyio assert-rewrite warning), not warnings from the changed code.

@hua7450 hua7450 merged commit e1798e3 into PolicyEngine:main Jun 2, 2026
26 checks passed
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.

Apply ACA PTC formula before 2024 using existing historical SLCSP premiums

3 participants