From 5f9fb760a158d1f1c5b7511978d6bf36f9e859ab Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Mon, 11 May 2026 13:18:49 -0400 Subject: [PATCH] Use bronze premiums for selected Marketplace plans --- changelog.d/changed/8211.md | 1 + .../gov/aca/ptc/marketplace_net_premium.yaml | 14 +++++++++++ ...lected_marketplace_plan_premium_proxy.yaml | 23 +++++++++++++++++++ .../baseline/gov/aca/ptc/used_aca_ptc.yaml | 20 +++++++++++++++- .../ptc/selected_marketplace_plan_category.py | 15 ++++++++++++ ...selected_marketplace_plan_premium_proxy.py | 12 ++++++++-- 6 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 changelog.d/changed/8211.md create mode 100644 policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_category.py diff --git a/changelog.d/changed/8211.md b/changelog.d/changed/8211.md new file mode 100644 index 00000000000..ed1c99d0cef --- /dev/null +++ b/changelog.d/changed/8211.md @@ -0,0 +1 @@ +Use actual lowest-cost bronze premiums when Bronze is the selected Marketplace plan category. diff --git a/policyengine_us/tests/policy/baseline/gov/aca/ptc/marketplace_net_premium.yaml b/policyengine_us/tests/policy/baseline/gov/aca/ptc/marketplace_net_premium.yaml index 21cdf7daa90..ddf141f5162 100644 --- a/policyengine_us/tests/policy/baseline/gov/aca/ptc/marketplace_net_premium.yaml +++ b/policyengine_us/tests/policy/baseline/gov/aca/ptc/marketplace_net_premium.yaml @@ -41,3 +41,17 @@ selected_marketplace_plan_premium_proxy: 8_000 used_aca_ptc: 0 marketplace_net_premium: 8_000 + +- name: Bronze selected plan net premium uses actual bronze premium. + absolute_error_margin: 0.01 + period: 2026 + input: + pays_aca_premium: true + selected_marketplace_plan_category: BRONZE + slcsp: 10_000 + lcbp: 5_000 + aca_ptc: 3_000 + output: + selected_marketplace_plan_premium_proxy: 5_000 + used_aca_ptc: 3_000 + marketplace_net_premium: 2_000 diff --git a/policyengine_us/tests/policy/baseline/gov/aca/ptc/selected_marketplace_plan_premium_proxy.yaml b/policyengine_us/tests/policy/baseline/gov/aca/ptc/selected_marketplace_plan_premium_proxy.yaml index 039ca1137b2..24ef11f2628 100644 --- a/policyengine_us/tests/policy/baseline/gov/aca/ptc/selected_marketplace_plan_premium_proxy.yaml +++ b/policyengine_us/tests/policy/baseline/gov/aca/ptc/selected_marketplace_plan_premium_proxy.yaml @@ -63,3 +63,26 @@ pays_aca_premium: true is_aca_ptc_eligible: false selected_marketplace_plan_premium_proxy: 8_000 + +- name: Case 6, bronze selected plan uses the lowest-cost bronze premium. + absolute_error_margin: 0.01 + period: 2026 + input: + pays_aca_premium: true + selected_marketplace_plan_category: BRONZE + slcsp: 10_000 + lcbp: 6_500 + output: + selected_marketplace_plan_premium_proxy: 6_500 + +- name: Case 7, silver selected plan keeps the benchmark-ratio proxy. + absolute_error_margin: 0.01 + period: 2026 + input: + pays_aca_premium: true + selected_marketplace_plan_category: SILVER + slcsp: 10_000 + lcbp: 6_500 + selected_marketplace_plan_benchmark_ratio: 0.9 + output: + selected_marketplace_plan_premium_proxy: 9_000 diff --git a/policyengine_us/tests/policy/baseline/gov/aca/ptc/used_aca_ptc.yaml b/policyengine_us/tests/policy/baseline/gov/aca/ptc/used_aca_ptc.yaml index 3c04f3d7eff..c1f36cf129c 100644 --- a/policyengine_us/tests/policy/baseline/gov/aca/ptc/used_aca_ptc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/aca/ptc/used_aca_ptc.yaml @@ -13,7 +13,7 @@ used_aca_ptc: 200 unused_aca_ptc: 0 -- name: Case 2, a bronze-like ratio leaves some ACA PTC unused. +- name: Case 2, a lower-than-benchmark selected-plan ratio leaves some ACA PTC unused. absolute_error_margin: 0.01 period: 2025 input: @@ -56,3 +56,21 @@ selected_marketplace_plan_premium_proxy: 0 used_aca_ptc: 0 unused_aca_ptc: 200 + +- name: Case 5, bronze selected plan uses actual bronze premium before applying PTC. + absolute_error_margin: 0.01 + period: 2026 + input: + is_aca_ptc_eligible: true + pays_aca_premium: true + selected_marketplace_plan_category: BRONZE + slcsp: 10_000 + lcbp: 7_000 + aca_magi: 20_000 + aca_required_contribution_percentage: 0.04 + tax_unit_is_filer: true + output: + aca_ptc: 9_200 + selected_marketplace_plan_premium_proxy: 7_000 + used_aca_ptc: 7_000 + unused_aca_ptc: 2_200 diff --git a/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_category.py b/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_category.py new file mode 100644 index 00000000000..a1d6ae04ed5 --- /dev/null +++ b/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_category.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class MarketplacePlanCategory(Enum): + BRONZE = "Bronze" + SILVER = "Silver" + + +class selected_marketplace_plan_category(Variable): + value_type = Enum + possible_values = MarketplacePlanCategory + default_value = MarketplacePlanCategory.SILVER + entity = TaxUnit + label = "Selected Marketplace plan category" + definition_period = YEAR diff --git a/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_premium_proxy.py b/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_premium_proxy.py index 604dc448498..d25f111c2a5 100644 --- a/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_premium_proxy.py +++ b/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_premium_proxy.py @@ -12,9 +12,17 @@ def formula(tax_unit, period, parameters): takes_up_aca_if_eligible = tax_unit("takes_up_aca_if_eligible", period) person = tax_unit.members pays_marketplace_premium = tax_unit.sum(person("pays_aca_premium", period)) > 0 + category = tax_unit("selected_marketplace_plan_category", period) + silver_premium = tax_unit("slcsp", period) * tax_unit( + "selected_marketplace_plan_benchmark_ratio", period + ) + selected_plan_premium = where( + category == category.possible_values.BRONZE, + tax_unit("lcbp", period), + silver_premium, + ) return where( takes_up_aca_if_eligible & pays_marketplace_premium, - tax_unit("slcsp", period) - * tax_unit("selected_marketplace_plan_benchmark_ratio", period), + selected_plan_premium, 0, )