Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/8529.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Include paid Medicare Part A premiums and Part D IRMAA in SPM medical out-of-pocket expenses.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
- name: Medicare Part A premium equals base premium when no MSP coverage.
period: 2026
input:
medicare_enrolled: true
base_part_a_premium: 6_780
msp_part_a_premium_coverage: 0
output:
medicare_part_a_premium: 6_780

- name: Medicare Part A premium is net of MSP coverage.
period: 2026
input:
medicare_enrolled: true
base_part_a_premium: 6_780
msp_part_a_premium_coverage: 6_780
output:
medicare_part_a_premium: 0

- name: Medicare Part A premium floors at zero after MSP coverage.
period: 2026
input:
medicare_enrolled: true
base_part_a_premium: 6_780
msp_part_a_premium_coverage: 7_000
output:
medicare_part_a_premium: 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
- name: MSP Part A coverage pays the Part A premium for QMB enrollees.
period: 2026
input:
medicare_enrolled: true
is_qmb_eligible: true
base_part_a_premium: 6_780
output:
msp_part_a_premium_coverage: 6_780

- name: MSP Part A coverage is zero for non-QMB enrollees.
period: 2026
input:
medicare_enrolled: true
is_qmb_eligible: false
base_part_a_premium: 6_780
output:
msp_part_a_premium_coverage: 0

- name: MSP Part A coverage is zero when not enrolled.
period: 2026
input:
medicare_enrolled: false
is_qmb_eligible: true
base_part_a_premium: 6_780
output:
msp_part_a_premium_coverage: 0
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,55 @@
output:
spm_unit_health_insurance_premiums: 5_528
spm_unit_medical_out_of_pocket_expenses: 5_528

- name: SPM unit MOOP includes paid Part A premium and Part D IRMAA.
period: 2026
input:
people:
retiree:
age: 70
medicare_enrolled: true
other_health_insurance_premiums: 500
base_part_a_premium: 6_780
msp_part_a_premium_coverage: 0
medicare_part_b_premium: 4_654.80
income_adjusted_part_d_premium_surcharge: 423.60
tax_units:
tax_unit:
members: [retiree]
spm_units:
spm_unit:
members: [retiree]
households:
household:
members: [retiree]
state_code: CA
output:
medicare_part_a_premium: 6_780
spm_unit_health_insurance_premiums: 12_358.40
spm_unit_medical_out_of_pocket_expenses: 12_358.40

- name: SPM unit MOOP excludes QMB-covered Part A premium.
period: 2026
input:
people:
retiree:
age: 70
medicare_enrolled: true
base_part_a_premium: 6_780
msp_part_a_premium_coverage: 6_780
medicare_part_b_premium: 2_434.80
tax_units:
tax_unit:
members: [retiree]
spm_units:
spm_unit:
members: [retiree]
households:
household:
members: [retiree]
state_code: CA
output:
medicare_part_a_premium: 0
spm_unit_health_insurance_premiums: 2_434.80
spm_unit_medical_out_of_pocket_expenses: 2_434.80
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from policyengine_us.model_api import *


class medicare_part_a_premium(Variable):
value_type = float
entity = Person
label = "Medicare Part A premium"
unit = USD
definition_period = YEAR
defined_for = "medicare_enrolled"
reference = "https://www.medicare.gov/basics/costs/medicare-costs"
documentation = (
"Annual Medicare Part A premium paid out of pocket by the enrollee, "
"net of Medicare Savings Program coverage."
)

def formula(person, period, parameters):
base_premium = person("base_part_a_premium", period)
msp_coverage = person("msp_part_a_premium_coverage", period)
return max_(base_premium - msp_coverage, 0)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from policyengine_us.model_api import *


class msp_part_a_premium_coverage(Variable):
value_type = float
entity = Person
unit = USD
label = "Medicare Part A premium amount covered by MSP"
definition_period = YEAR
reference = (
"https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
)
documentation = (
"Annual Part A premium amount paid on the enrollee's behalf through "
"Qualified Medicare Beneficiary coverage."
)

def formula(person, period, parameters):
enrolled = person("medicare_enrolled", period)
monthly_part_a_premium = person("base_part_a_premium", period) / MONTHS_IN_YEAR
monthly_coverage = 0
for month in period.get_subperiods(MONTH):
qmb_eligible = person("is_qmb_eligible", month)
monthly_coverage += where(
enrolled & qmb_eligible,
monthly_part_a_premium,
0,
)
return monthly_coverage
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ class spm_unit_health_insurance_premiums(Variable):
documentation = (
"Health insurance premium expenses for an SPM unit, combining a "
"data-imputed other premium component with modeled premium components "
"that can respond to policy reforms."
"that can respond to policy reforms, including Medicare premiums "
"paid out of pocket."
)

adds = [
"other_health_insurance_premiums",
"chip_premium",
"medicaid_premium",
"marketplace_net_premium",
"medicare_part_a_premium",
"medicare_part_b_premium",
"income_adjusted_part_d_premium_surcharge",
]
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ class spm_unit_medical_out_of_pocket_expenses(Variable):
"Total medical out-of-pocket expenses at the SPM unit level, "
"combining health insurance premiums with non-premium medical "
"expenses. Health insurance premiums include other health insurance "
"premiums plus modeled Marketplace, CHIP, Medicaid, and Medicare Part "
"B premiums net of Medicare Savings Program coverage. Non-premium "
"expenses include other medical expenses and over-the-counter health "
"expenses."
"premiums plus modeled Marketplace, CHIP, Medicaid, and Medicare "
"premiums net of Medicare Savings Program coverage where modeled. "
"Non-premium expenses include other medical expenses and "
"over-the-counter health expenses."
)

adds = [
Expand Down
Loading