diff --git a/changelog.d/added/8168.md b/changelog.d/added/8168.md new file mode 100644 index 00000000000..bbef50e71a4 --- /dev/null +++ b/changelog.d/added/8168.md @@ -0,0 +1 @@ +Marketplace take-up can now use reported Marketplace coverage while preserving a simulated take-up switch, with selected Marketplace plan benchmark ratios documented as explicit inputs. 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..d2463a2f650 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,31 @@ selected_marketplace_plan_premium_proxy: 8_000 used_aca_ptc: 0 marketplace_net_premium: 8_000 + +- name: Reported unsubsidized Marketplace buyer pays selected plan premium when simulated take-up is disabled. + absolute_error_margin: 0.01 + period: 2026 + input: + people: + person1: + age: 40 + has_marketplace_health_coverage_at_interview: true + is_medicaid_eligible: false + is_chip_eligible: false + is_basic_health_program_eligible: false + is_aca_eshi_eligible: false + is_medicare_eligible: false + tax_units: + tax_unit: + members: [person1] + aca_magi_fraction: 5 + slcsp: 10_000 + selected_marketplace_plan_benchmark_ratio: 0.8 + simulated_aca_take_up_if_eligible: false + output: + pays_aca_premium: [true] + takes_up_aca_if_eligible: true + is_aca_ptc_eligible: [false] + selected_marketplace_plan_premium_proxy: 8_000 + used_aca_ptc: 0 + marketplace_net_premium: 8_000 diff --git a/policyengine_us/tests/policy/baseline/gov/aca/takes_up_aca_if_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/aca/takes_up_aca_if_eligible.yaml new file mode 100644 index 00000000000..7db8da06413 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/aca/takes_up_aca_if_eligible.yaml @@ -0,0 +1,46 @@ +- name: Case 1, default simulated Marketplace take-up preserves existing ACA take-up behavior. + period: 2026 + output: + simulated_aca_take_up_if_eligible: true + takes_up_aca_if_eligible: true + +- name: Case 2, reported Marketplace coverage triggers take-up when simulated take-up is disabled. + period: 2026 + input: + people: + person1: + has_marketplace_health_coverage_at_interview: true + tax_units: + tax_unit: + members: [person1] + simulated_aca_take_up_if_eligible: false + output: + takes_up_aca_if_eligible: true + +- name: Case 3, no reported Marketplace coverage means no take-up when simulated take-up is disabled. + period: 2026 + input: + people: + person1: + has_marketplace_health_coverage_at_interview: false + tax_units: + tax_unit: + members: [person1] + simulated_aca_take_up_if_eligible: false + output: + takes_up_aca_if_eligible: false + +- name: Case 4, reported Marketplace coverage for one member triggers tax-unit take-up. + period: 2026 + input: + people: + person1: + has_marketplace_health_coverage_at_interview: false + person2: + has_marketplace_health_coverage_at_interview: true + tax_units: + tax_unit: + members: [person1, person2] + simulated_aca_take_up_if_eligible: false + output: + takes_up_aca_if_eligible: true diff --git a/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_benchmark_ratio.py b/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_benchmark_ratio.py index 94cd07a66fa..21f1eb7bdf7 100644 --- a/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_benchmark_ratio.py +++ b/policyengine_us/variables/gov/aca/ptc/selected_marketplace_plan_benchmark_ratio.py @@ -8,3 +8,9 @@ class selected_marketplace_plan_benchmark_ratio(Variable): unit = "/1" definition_period = YEAR default_value = 1.0 + documentation = ( + "Ratio of the selected Marketplace plan gross premium to the second " + "lowest cost silver plan benchmark premium. This is an explicit " + "user- or data-supplied input; when absent, the model assumes the " + "selected plan premium equals the benchmark premium." + ) diff --git a/policyengine_us/variables/gov/aca/simulated_aca_take_up_if_eligible.py b/policyengine_us/variables/gov/aca/simulated_aca_take_up_if_eligible.py new file mode 100644 index 00000000000..5e1cfb53b3d --- /dev/null +++ b/policyengine_us/variables/gov/aca/simulated_aca_take_up_if_eligible.py @@ -0,0 +1,14 @@ +from policyengine_us.model_api import * + + +class simulated_aca_take_up_if_eligible(Variable): + value_type = bool + entity = TaxUnit + label = "Whether a tax unit is simulated to take up ACA if eligible" + definition_period = YEAR + default_value = True + documentation = ( + "Reform-responsive Marketplace take-up switch for tax units without " + "reported Marketplace coverage at interview. Reported Marketplace " + "coverage is handled in takes_up_aca_if_eligible." + ) diff --git a/policyengine_us/variables/gov/aca/takes_up_aca_if_eligible.py b/policyengine_us/variables/gov/aca/takes_up_aca_if_eligible.py index 47ab37afd65..b50ab107944 100644 --- a/policyengine_us/variables/gov/aca/takes_up_aca_if_eligible.py +++ b/policyengine_us/variables/gov/aca/takes_up_aca_if_eligible.py @@ -7,3 +7,17 @@ class takes_up_aca_if_eligible(Variable): label = "Whether an eligible tax unit takes up ACA" definition_period = YEAR default_value = True + documentation = ( + "Whether the tax unit takes up Marketplace coverage when otherwise " + "eligible. Reported Marketplace coverage at interview is treated as " + "observed take-up; otherwise take-up follows the simulated take-up " + "switch." + ) + + def formula(tax_unit, period, parameters): + person = tax_unit.members + reported_marketplace_coverage = tax_unit.any( + person("has_marketplace_health_coverage_at_interview", period) + ) + simulated_take_up = tax_unit("simulated_aca_take_up_if_eligible", period) + return reported_marketplace_coverage | simulated_take_up