diff --git a/changelog.d/8527.fixed.md b/changelog.d/8527.fixed.md new file mode 100644 index 00000000000..9ed6d2783ea --- /dev/null +++ b/changelog.d/8527.fixed.md @@ -0,0 +1 @@ +Apply ACA premium tax credit formulas to years with historical SLCSP premiums. diff --git a/policyengine_us/parameters/gov/aca/required_contribution_percentage/final.yaml b/policyengine_us/parameters/gov/aca/required_contribution_percentage/final.yaml index 728696a4a2c..da40e2b5427 100644 --- a/policyengine_us/parameters/gov/aca/required_contribution_percentage/final.yaml +++ b/policyengine_us/parameters/gov/aca/required_contribution_percentage/final.yaml @@ -1,14 +1,21 @@ description: Final (ending) contribution percentage for each ACA bracket. metadata: unit: /1 + period: year label: ACA contribution percentage - final rate per bracket reference: - title: 26 U.S. Code § 36B(b)(3)(A) - Refundable credit for coverage under a qualified health plan href: https://www.law.cornell.edu/uscode/text/26/36B#b_3_A + - title: IRS Revenue Procedure 2017-36 - Applicable percentage table for 2018 + href: https://www.irs.gov/pub/irs-drop/rp-17-36.pdf#page=2 + - title: IRS Revenue Procedure 2018-34 - Applicable percentage table for 2019 + href: https://www.irs.gov/pub/irs-drop/rp-18-34.pdf#page=2 + - title: IRS Revenue Procedure 2019-29 - Applicable percentage table for 2020 + href: https://www.irs.gov/pub/irs-drop/rp-19-29.pdf#page=3 - title: IRS Revenue Procedure 2025-25 - Applicable percentage table for 2026 href: https://www.irs.gov/pub/irs-drop/rp-25-25.pdf values: - # Original ACA (2015-2020): 6 brackets + # Original ACA: 6 brackets 2015-01-01: - 0.02 # 0-133%: flat 2% - 0.04 # 133-150% @@ -16,6 +23,27 @@ values: - 0.0805 # 200-250% - 0.095 # 250-300% - 0.095 # 300-400%: flat 9.5% + 2018-01-01: + - 0.0201 + - 0.0403 + - 0.0634 + - 0.081 + - 0.0956 + - 0.0956 + 2019-01-01: + - 0.0208 + - 0.0415 + - 0.0654 + - 0.0836 + - 0.0986 + - 0.0986 + 2020-01-01: + - 0.0206 + - 0.0412 + - 0.0649 + - 0.0829 + - 0.0978 + - 0.0978 # ARPA/IRA (2021-2025): 5 brackets, no 133% threshold 2021-01-01: - 0 # 0-150%: flat 0% diff --git a/policyengine_us/parameters/gov/aca/required_contribution_percentage/initial.yaml b/policyengine_us/parameters/gov/aca/required_contribution_percentage/initial.yaml index c4fd4b29fe4..74805496be5 100644 --- a/policyengine_us/parameters/gov/aca/required_contribution_percentage/initial.yaml +++ b/policyengine_us/parameters/gov/aca/required_contribution_percentage/initial.yaml @@ -1,14 +1,21 @@ description: Initial (starting) contribution percentage for each ACA bracket. metadata: unit: /1 + period: year label: ACA contribution percentage - initial rate per bracket reference: - title: 26 U.S. Code § 36B(b)(3)(A) - Refundable credit for coverage under a qualified health plan href: https://www.law.cornell.edu/uscode/text/26/36B#b_3_A + - title: IRS Revenue Procedure 2017-36 - Applicable percentage table for 2018 + href: https://www.irs.gov/pub/irs-drop/rp-17-36.pdf#page=2 + - title: IRS Revenue Procedure 2018-34 - Applicable percentage table for 2019 + href: https://www.irs.gov/pub/irs-drop/rp-18-34.pdf#page=2 + - title: IRS Revenue Procedure 2019-29 - Applicable percentage table for 2020 + href: https://www.irs.gov/pub/irs-drop/rp-19-29.pdf#page=3 - title: IRS Revenue Procedure 2025-25 - Applicable percentage table for 2026 href: https://www.irs.gov/pub/irs-drop/rp-25-25.pdf values: - # Original ACA (2015-2020): 6 brackets + # Original ACA: 6 brackets 2015-01-01: - 0.02 # 0-133%: flat 2% - 0.03 # 133-150% @@ -16,6 +23,27 @@ values: - 0.063 # 200-250% - 0.0805 # 250-300% - 0.095 # 300-400%: flat 9.5% + 2018-01-01: + - 0.0201 + - 0.0302 + - 0.0403 + - 0.0634 + - 0.081 + - 0.0956 + 2019-01-01: + - 0.0208 + - 0.0311 + - 0.0415 + - 0.0654 + - 0.0836 + - 0.0986 + 2020-01-01: + - 0.0206 + - 0.0309 + - 0.0412 + - 0.0649 + - 0.0829 + - 0.0978 # ARPA/IRA (2021-2025): 5 brackets, no 133% threshold 2021-01-01: - 0 # 0-150%: flat 0% diff --git a/policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_ptc.yaml b/policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_ptc.yaml index 706f8915586..e958e68ded6 100644 --- a/policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_ptc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_ptc.yaml @@ -1,4 +1,4 @@ -- name: ACA PTC returns zero before 2024 +- name: ACA PTC calculated for 2023 using historical premiums absolute_error_margin: 0.01 period: 2023 input: @@ -6,6 +6,19 @@ slcsp: 1_200 aca_magi: 25_000 aca_required_contribution_percentage: 0.04 + tax_unit_is_filer: true + output: + aca_ptc: 200 # 1200 - 0.04 * 25000 = 200 + +- name: ACA PTC remains zero before available rating-area premium data + absolute_error_margin: 0.01 + period: 2017 + input: + is_aca_ptc_eligible: true + slcsp: 1_200 + aca_magi: 25_000 + aca_required_contribution_percentage: 0.04 + tax_unit_is_filer: true output: aca_ptc: 0 @@ -169,3 +182,51 @@ output: is_aca_ptc_eligible: [true] aca_ptc: 200 + +- name: ACA PTC remains zero in 2017 before available rating-area premium data + absolute_error_margin: 0.01 + period: 2017 + input: + is_aca_ptc_eligible: true + slcsp: 1_200 + aca_magi: 25_000 + aca_required_contribution_percentage: 0.04 + tax_unit_is_filer: true + output: + aca_ptc: 0 + +- name: ACA PTC applies to the same household in 2018 with rating-area premium data + absolute_error_margin: 0.01 + period: 2018 + input: + is_aca_ptc_eligible: true + slcsp: 1_200 + aca_magi: 25_000 + aca_required_contribution_percentage: 0.04 + tax_unit_is_filer: true + output: + aca_ptc: 200 + +- name: ACA PTC calculated for 2024 using historical premiums + absolute_error_margin: 0.01 + period: 2024 + input: + is_aca_ptc_eligible: true + slcsp: 1_200 + aca_magi: 25_000 + aca_required_contribution_percentage: 0.04 + tax_unit_is_filer: true + output: + aca_ptc: 200 + +- name: ACA PTC covers full SLCSP when ARPA contribution percentage is zero + absolute_error_margin: 0.01 + period: 2022 + input: + is_aca_ptc_eligible: true + slcsp: 1_200 + aca_magi: 25_000 + aca_required_contribution_percentage: 0 + tax_unit_is_filer: true + output: + aca_ptc: 1_200 diff --git a/policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_required_contribution_percentage.yaml b/policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_required_contribution_percentage.yaml index 7ddacf3e512..2bb9eedbbe6 100644 --- a/policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_required_contribution_percentage.yaml +++ b/policyengine_us/tests/policy/baseline/gov/aca/ptc/aca_required_contribution_percentage.yaml @@ -22,13 +22,13 @@ output: aca_required_contribution_percentage: 0.0314 -- name: Flat at 100% FPL in 2019 (pre-ARPA, should be 2%) +- name: Flat at 100% FPL in 2019 (pre-ARPA, should be 2.08%) period: 2019 absolute_error_margin: 0.0001 input: aca_magi_fraction: 1.0 output: - aca_required_contribution_percentage: 0.02 + aca_required_contribution_percentage: 0.0208 - name: aca_required_contribution_percentage unit test 1 period: 2022 @@ -101,3 +101,99 @@ aca_magi_fraction: 4.0 output: aca_required_contribution_percentage: 0.0996 + +- name: 2026 ACA contribution percentage is zero above 400 percent FPL. + period: 2026 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 4.01 + output: + aca_required_contribution_percentage: 0 + +- name: 2018 ACA contribution percentage at 100 percent FPL. + period: 2018 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 1.0 + output: + aca_required_contribution_percentage: 0.0201 + +- name: 2018 ACA contribution percentage at 350 percent FPL. + period: 2018 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 3.5 + output: + aca_required_contribution_percentage: 0.0956 + +- name: 2019 ACA contribution percentage at 350 percent FPL. + period: 2019 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 3.5 + output: + aca_required_contribution_percentage: 0.0986 + +- name: 2020 ACA contribution percentage at 100 percent FPL. + period: 2020 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 1.0 + output: + aca_required_contribution_percentage: 0.0206 + +- name: 2020 ACA contribution percentage at 350 percent FPL. + period: 2020 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 3.5 + output: + aca_required_contribution_percentage: 0.0978 + +- name: 2018 ACA contribution percentage at 400 percent FPL. + period: 2018 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 4.0 + output: + aca_required_contribution_percentage: 0.0956 + +- name: 2018 ACA contribution percentage is zero above 400 percent FPL. + period: 2018 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 4.01 + output: + aca_required_contribution_percentage: 0 + +- name: 2019 ACA contribution percentage at 400 percent FPL. + period: 2019 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 4.0 + output: + aca_required_contribution_percentage: 0.0986 + +- name: 2019 ACA contribution percentage is zero above 400 percent FPL. + period: 2019 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 4.01 + output: + aca_required_contribution_percentage: 0 + +- name: 2020 ACA contribution percentage at 400 percent FPL. + period: 2020 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 4.0 + output: + aca_required_contribution_percentage: 0.0978 + +- name: 2020 ACA contribution percentage is zero above 400 percent FPL. + period: 2020 + absolute_error_margin: 0.0001 + input: + aca_magi_fraction: 4.01 + output: + aca_required_contribution_percentage: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/aca/ptc/integration.yaml b/policyengine_us/tests/policy/baseline/gov/aca/ptc/integration.yaml index 617cf05cc72..4c91d75b84b 100644 --- a/policyengine_us/tests/policy/baseline/gov/aca/ptc/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/aca/ptc/integration.yaml @@ -92,3 +92,29 @@ selected_marketplace_plan_premium_proxy: 3_929.25 used_aca_ptc: 3_929.25 unused_aca_ptc: 394.31 + +- name: 2023 aca_ptc_los_angeles_single + absolute_error_margin: 0.01 + period: 2023 + input: + people: + person1: + age: 40 + employment_income: 30_000 + is_aca_eshi_eligible: false + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_fips: 6 # CA + county: LOS_ANGELES_COUNTY_CA + three_digit_zip_code: 902 + output: + is_medicaid_eligible: [false] + is_aca_ptc_eligible: [true] + slcsp: 4_250.01 + aca_magi_fraction: 2.20 + aca_required_contribution_percentage: 0.028 + aca_ptc: 3_410.01 diff --git a/policyengine_us/tests/policy/contrib/aca/ptc_700_fpl_cliff.yaml b/policyengine_us/tests/policy/contrib/aca/ptc_700_fpl_cliff.yaml index 569eb6d1cf7..1b3da2a3698 100644 --- a/policyengine_us/tests/policy/contrib/aca/ptc_700_fpl_cliff.yaml +++ b/policyengine_us/tests/policy/contrib/aca/ptc_700_fpl_cliff.yaml @@ -127,10 +127,10 @@ output: aca_required_contribution_percentage: 0.0996 -- name: Baseline comparison at 500% FPL - shows new eligibility +- name: Baseline comparison at 500% FPL - above post-ARPA cliff period: 2026 absolute_error_margin: 0.00001 input: aca_magi_fraction: 5.0 output: - aca_required_contribution_percentage: 0.0996 + aca_required_contribution_percentage: 0 diff --git a/policyengine_us/variables/gov/aca/ptc/aca_ptc.py b/policyengine_us/variables/gov/aca/ptc/aca_ptc.py index 8a5df33efcc..76c9fbe2464 100644 --- a/policyengine_us/variables/gov/aca/ptc/aca_ptc.py +++ b/policyengine_us/variables/gov/aca/ptc/aca_ptc.py @@ -8,12 +8,17 @@ class aca_ptc(Variable): unit = USD definition_period = YEAR reference = "https://www.law.cornell.edu/uscode/text/26/36B" + documentation = ( + "IRC section 36B applies before 2018, but PolicyEngine applies the " + "ACA PTC formula from 2018 onward because rating-area SLCSP premium " + "data currently begins in 2018." + ) defined_for = "is_aca_ptc_eligible" def formula(tax_unit, period, parameters): return 0 - def formula_2024(tax_unit, period, parameters): + def formula_2018(tax_unit, period, parameters): plan_cost = tax_unit("slcsp", period) income = tax_unit("aca_magi", period) applicable_figure = tax_unit("aca_required_contribution_percentage", period) diff --git a/policyengine_us/variables/gov/aca/ptc/aca_required_contribution_percentage.py b/policyengine_us/variables/gov/aca/ptc/aca_required_contribution_percentage.py index acbbce07d48..f0e3423ca1b 100644 --- a/policyengine_us/variables/gov/aca/ptc/aca_required_contribution_percentage.py +++ b/policyengine_us/variables/gov/aca/ptc/aca_required_contribution_percentage.py @@ -51,4 +51,11 @@ def formula(tax_unit, period, parameters): # Interpolate between initial and final rates initial = initial_rates[bracket_idx] final = final_rates[bracket_idx] - return initial + position * (final - initial) + applicable_figure = initial + position * (final - initial) + + income_eligible = parameters(period).gov.aca.ptc_income_eligibility.calc( + magi_frac + ) + above_fpl_limit = magi_frac > thresholds[-1] + capped_out = above_fpl_limit & ~income_eligible + return where(capped_out, 0, applicable_figure)