Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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