diff --git a/changelog.d/medicare-per-enrollee-cms.fixed.md b/changelog.d/medicare-per-enrollee-cms.fixed.md new file mode 100644 index 00000000000..04369fcfd3f --- /dev/null +++ b/changelog.d/medicare-per-enrollee-cms.fixed.md @@ -0,0 +1 @@ +Value Medicare enrollees at CMS's Medicare spending per enrollee (National Health Expenditure projections, 2013-2034, extended to 2100) instead of a $14,500 estimate held flat from 2025. diff --git a/policyengine_us/parameters/calibration/gov/hhs/medicare/per_capita_cost.yaml b/policyengine_us/parameters/calibration/gov/hhs/medicare/per_capita_cost.yaml index 3e92c3e491c..48ab04c9c07 100644 --- a/policyengine_us/parameters/calibration/gov/hhs/medicare/per_capita_cost.yaml +++ b/policyengine_us/parameters/calibration/gov/hhs/medicare/per_capita_cost.yaml @@ -1,12 +1,64 @@ -description: Average Medicare spending per enrolled beneficiary (national average). Represents the annual value of Medicare coverage including Part A and Part B. -values: - 2021-01-01: 11_080 # Traditional Medicare (Part A and/or Part B) per KFF - 2025-01-01: 14_500 # Estimated - update with official Centers for Medicare & Medicaid Services (CMS) data when available +description: The Centers for Medicare and Medicaid Services (CMS) reports and projects this Medicare spending per enrollee, which is all Medicare spending, including payments to Medicare Advantage plans, Part D and program administration, divided by average enrollment in Part A, Part B or both. metadata: - label: Medicare per capita cost unit: currency-USD period: year + label: CMS Medicare spending per enrollee reference: - - title: KFF Medicare Spending Per Beneficiary (2021) - href: https://www.kff.org/medicare/state-indicator/per-beneficiary/ - - title: Note - 2024 value is estimated and should be updated with official Centers for Medicare & Medicaid Services (CMS) data + # Table17 Health Insurance Enrollment and Enrollment Growth Rates, + # "Spending per Enrollee ($)", "Medicare" row: Medicare spending (the same + # row as Table03's Medicare source of funds) divided by Medicare + # enrollment. Historical for 2013-2024, projected for 2025-2034. ZIP + # Last-Modified 2026-09-03, sha256 + # 264f822618a5e1829138aea57cc6c8bf45bbaf072a72898fef5547f7ece6cd70, + # retrieved 2026-10-11 from + # https://www.cms.gov/data-research/statistics-trends-and-reports/national-health-expenditure-data/projected + - title: CMS National Health Expenditure Projections 2025-2034, Table 17 + href: https://www.cms.gov/files/zip/nhe-projections-tables.zip + # Medicare spending covers Parts A, B, C (Medicare Advantage) and D (file + # page 15) and, as program spending, federal administration and the + # non-medical expenditures of Part C and Part D private plans (file page + # 23). Premiums finance part of that spending rather than reduce it: the + # sponsor analysis counts SMI premiums as household spending on Medicare + # (file page 30). Medicare enrollment is Part A and/or B enrollment by "a + # person-year methodology, which sums the number of months each + # beneficiary is enrolled during the year and divides by 12", with U.S. + # territories removed (file page 34). sha256 + # 9c5755666847a78103016f04da937326744071a9a6736f4e77e91ce9e7af8629. + - title: "CMS National Health Expenditure Accounts: Methodology Paper, 2024 #page 15,23,30,34" + href: https://www.cms.gov/files/document/definitions-sources-methods.pdf#page=15 + # "Projections of Medicare spending and enrollment used in the NHE + # projections were generated for the most recent Trustees Report" (file + # page 7); file page 6 names the 2026 report for the economic assumptions. + # Last Updated June 24, 2026, sha256 + # ce62fe2c236cc96ce287027784b141584ddf39e62c5fd8ddc3e771a014944817. + - title: "Projections of National Health Expenditures and Enrollment: Methodology and Model Specification #page 6-7" + href: https://www.cms.gov/research-statistics-data-and-systems/statistics-trends-and-reports/nationalhealthexpenddata/downloads/projectionsmethodology.pdf#page=6 +values: + # Historical. + 2013-01-01: 11_483 + 2014-01-01: 11_683 + 2015-01-01: 11_929 + 2016-01-01: 12_119 + 2017-01-01: 12_319 + 2018-01-01: 12_795 + 2019-01-01: 13_366 + 2020-01-01: 13_547 + 2021-01-01: 14_293 + 2022-01-01: 14_921 + 2023-01-01: 15_915 + 2024-01-01: 16_779 + # Projections. + 2025-01-01: 17_751 + 2026-01-01: 18_983 + 2027-01-01: 20_096 + 2028-01-01: 21_310 + 2029-01-01: 22_543 + 2030-01-01: 23_789 + 2031-01-01: 25_185 + 2032-01-01: 26_552 + 2033-01-01: 28_277 + 2034-01-01: 30_129 + # 2035 to 2100 grow at the 2031-2032 rate (26_552 / 25_185, 5.4% a year), + # not the 2033-2034 rate, which carries the end of Medicare sequestration + # on August 31, 2033; later years hold the 2100 value. See + # set_all_uprating_parameters in uprating_extensions.py. diff --git a/policyengine_us/parameters/uprating_extensions.py b/policyengine_us/parameters/uprating_extensions.py index 23ec45e9904..4c18dec9df4 100644 --- a/policyengine_us/parameters/uprating_extensions.py +++ b/policyengine_us/parameters/uprating_extensions.py @@ -880,6 +880,23 @@ def set_all_uprating_parameters(parameters: ParameterNode) -> ParameterNode: period_day=1, ) + # CMS Medicare spending per enrollee (January values, last projection + # year 2034), which Medicare cost variables read directly. Sequestration + # cuts Medicare expenditures 2 percent through August 31, 2033 (2026 + # Medicare Trustees Report, file page 209); its end lifts 2033 and 2034 + # growth, and the Trustees' per-beneficiary growth falls from 6.6 + # percent in 2034 to 5.4 percent in 2035 (Table V.D1, file page 210). + # So each year from 2035 to 2100 grows at the 2031-2032 rate, and later + # years hold the 2100 value. + extend_parameter_values( + parameters.calibration.gov.hhs.medicare.per_capita_cost, + last_projected_year=2034, + end_year=END_YEAR, + period_month=1, + period_day=1, + growth_years=(2031, 2032), + ) + # CBO income-by-source aggregates are used directly and as anchors for # SOI-based income upraters. Extending them in the baseline path keeps # long-run nominal data aging independent of scenario-specific reforms. diff --git a/policyengine_us/tests/core/test_medicare_per_capita_cost.py b/policyengine_us/tests/core/test_medicare_per_capita_cost.py new file mode 100644 index 00000000000..d3d47ca3079 --- /dev/null +++ b/policyengine_us/tests/core/test_medicare_per_capita_cost.py @@ -0,0 +1,247 @@ +"""The CMS Medicare spending per enrollee series that values Medicare coverage. + +``calibration.gov.hhs.medicare.per_capita_cost`` holds the "Medicare" row of +"Spending per Enrollee ($)" in CMS's National Health Expenditure projections, +Table 17 (2025-2034 release): Medicare spending over Medicare enrollment. +Spending covers every Part, including payments to Medicare Advantage plans and +program administration; enrollment counts Part A and/or Part B enrollees in +person-years; both exclude the territories (NHEA methodology paper, file pages +15, 23 and 34). 2013-2024 are historical and 2025-2034 projected, from the +projections prepared for the 2026 Medicare Trustees Report. 2035 to 2100 grow +at the 2031-2032 rate, because the end of sequestration on August 31, 2033 +lifts 2033 and 2034 growth. + +``medicare_gross_cost`` returns the series for each enrolled person, +``medicare_cost`` subtracts the person's Part A and gross Part B premiums, and +``qmb_cost_sharing`` pays QMB enrollees a share of it each month. + +Invariants: + +1. Transcription: every value is Table 17's published dollar figure, and is + consistent with the same table's Medicare spending over Medicare enrollment + within rounding. +2. Cross-source level: the Trustees Report's per beneficiary cost (Table V.D1) + runs 5% to 8% above the series in every year from 2015 to 2034. V.D1 sums + per-Part averages (its footnote 2), while Table II.B1 counts 63.4 million + Part B and 56.8 million Part D enrollees among 69.3 million in 2025. +3. Bounds and order: the series is positive and strictly increasing from 2013 + to 2100, and holds the 2100 value afterwards. +4. Extension rule: each year from 2035 to 2100 equals the 2034 value times + (26,552 / 25,185) ** (year - 2034), the closed form of the iterative + extension; the 2035 value is within 0.1% of the 2034 value grown at the + Trustees' 2034-2035 per beneficiary growth. +5. Calendar years: every date within a year reads the January 1 value. +6. Consumers: for an enrolled person, ``medicare_gross_cost`` equals the + series; ``medicare_cost`` equals the series less the Part A premium and the + gross Part B premium, floored at zero, so never exceeds + ``medicare_gross_cost``; a QMB enrollee's monthly ``qmb_cost_sharing`` is + the series over 12 times the QMB rate. A person not enrolled gets zero. +""" + +import pytest +from hypothesis import given, settings +from hypothesis import strategies as st +from policyengine_core.parameters.operations.get_parameter import get_parameter + +from policyengine_us import Simulation +from policyengine_us.system import system + +SERIES = "calibration.gov.hhs.medicare.per_capita_cost" +FIRST_YEAR, LAST_PROJECTED_YEAR, END_YEAR = 2013, 2034, 2100 +YEARS = range(FIRST_YEAR, LAST_PROJECTED_YEAR + 1) +GROWTH_YEARS = (2031, 2032) + +# CMS NHE projections tables, Table 17, "Medicare" rows +# (https://www.cms.gov/files/zip/nhe-projections-tables.zip, Last-Modified +# 2026-09-03, sha256 264f8226...cd70). +MEDICARE_SPENDING_PER_ENROLLEE = dict( + zip( + YEARS, + ( + *(11_483, 11_683, 11_929, 12_119, 12_319, 12_795, 13_366, 13_547), + *(14_293, 14_921, 15_915, 16_779, 17_751, 18_983, 20_096, 21_310), + *(22_543, 23_789, 25_185, 26_552, 28_277, 30_129), + ), + ) +) +MEDICARE_SPENDING_BILLIONS = dict( + zip( + YEARS, + ( + *(588.9, 617.3, 647.7, 675.7, 704.9, 751.6, 805.2, 833.8, 894.6), + *(951.7, 1037.3, 1118.0, 1204.0, 1314.6, 1422.7, 1544.2, 1664.6), + *(1783.7, 1911.1, 2035.8, 2188.3, 2354.3), + ), + ) +) +MEDICARE_ENROLLMENT_MILLIONS = dict( + zip( + YEARS, + ( + *(51.3, 52.8, 54.3, 55.8, 57.2, 58.7, 60.2, 61.6, 62.6, 63.8), + *(65.2, 66.6, 67.8, 69.2, 70.8, 72.5, 73.8, 75.0, 75.9, 76.7), + *(77.4, 78.1), + ), + ) +) +# 2026 Medicare Trustees Report, Table V.D1 (file page 210), "Total" average +# per beneficiary cost: historical through 2025, intermediate estimates after. +TRUSTEES_PER_BENEFICIARY_COST = dict( + zip( + range(2015, 2036), + ( + *(12_734, 12_922, 13_127, 13_604, 14_224, 14_401, 15_170, 15_820), + *(16_809, 17_837, 18_894, 20_430, 21_497, 22_783, 24_076, 25_401), + *(26_826, 28_169, 29_989, 31_967, 33_687), + ), + ) +) + +years = st.integers(FIRST_YEAR, END_YEAR) + + +def _series(date): + return get_parameter(system.parameters, SERIES)(date) + + +def _value(year): + return _series(f"{year}-01-01") + + +@pytest.mark.parametrize("year", YEARS) +def test_series_is_table_17_medicare_spending_per_enrollee(year): + assert _value(year) == MEDICARE_SPENDING_PER_ENROLLEE[year] + + +@pytest.mark.parametrize("year", YEARS) +def test_published_values_match_spending_over_enrollment(year): + """Checks the transcribed rows against each other, so one mistyped + spending, enrollment or per-enrollee figure fails.""" + spending = MEDICARE_SPENDING_BILLIONS[year] + enrollment = MEDICARE_ENROLLMENT_MILLIONS[year] + # Both components are rounded to one decimal and the published value to + # the dollar. + low = 1_000 * (spending - 0.05) / (enrollment + 0.05) - 0.5 + high = 1_000 * (spending + 0.05) / (enrollment - 0.05) + 0.5 + assert low <= MEDICARE_SPENDING_PER_ENROLLEE[year] <= high + + +@pytest.mark.parametrize("year", range(2015, LAST_PROJECTED_YEAR + 1)) +def test_trustees_per_beneficiary_cost_runs_5_to_8_percent_above(year): + ratio = TRUSTEES_PER_BENEFICIARY_COST[year] / _value(year) + assert 1.05 <= ratio <= 1.08 + + +def test_2035_extension_follows_the_trustees_2035_growth(): + trustees_growth = ( + TRUSTEES_PER_BENEFICIARY_COST[2035] / TRUSTEES_PER_BENEFICIARY_COST[2034] + ) + assert _value(2035) == pytest.approx( + _value(LAST_PROJECTED_YEAR) * trustees_growth, rel=0.001 + ) + + +# The year domains below are finite and small, so they are checked +# exhaustively rather than sampled. +@pytest.mark.parametrize("year", range(FIRST_YEAR, END_YEAR)) +def test_series_is_positive_and_strictly_increasing(year): + """Adjacent years, so strict order holds for every pair of years.""" + assert 0 < _value(year) < _value(year + 1) + + +@pytest.mark.parametrize("year", range(LAST_PROJECTED_YEAR + 1, END_YEAR + 1)) +def test_extension_is_the_closed_form_of_the_2031_2032_growth(year): + earlier, later = GROWTH_YEARS + growth = ( + MEDICARE_SPENDING_PER_ENROLLEE[later] + / (MEDICARE_SPENDING_PER_ENROLLEE[earlier]) + ) + expected = MEDICARE_SPENDING_PER_ENROLLEE[LAST_PROJECTED_YEAR] * growth ** ( + year - LAST_PROJECTED_YEAR + ) + assert _value(year) == pytest.approx(expected, rel=1e-9) + assert _value(year) / _value(year - 1) == pytest.approx(growth, rel=1e-12) + + +@settings(deadline=None) +@given(st.integers(END_YEAR, END_YEAR + 1_000)) +def test_series_holds_the_2100_value_afterwards(year): + assert _value(year) == _value(END_YEAR) + + +@settings(deadline=None) +@given(years, st.integers(1, 12), st.integers(1, 28)) +def test_every_date_in_a_year_reads_the_january_value(year, month, day): + assert _series(f"{year}-{month:02d}-{day:02d}") == _value(year) + + +def _person_simulation(year, person): + members = ["person"] + return Simulation( + situation={ + "people": {"person": person}, + "tax_units": {"tax_unit": {"members": members}}, + "spm_units": {"spm_unit": {"members": members}}, + "families": {"family": {"members": members}}, + "marital_units": {"marital_unit": {"members": members}}, + "households": { + "household": {"members": members, "state_code": {year: "CA"}} + }, + } + ) + + +@settings(max_examples=20, deadline=None) +@given( + st.integers(2015, END_YEAR), + st.floats(0, 12_000, allow_nan=False), + st.floats(0, 40_000, allow_nan=False), +) +def test_medicare_cost_nets_premiums_from_the_series( + year, part_a_premium, part_b_premium +): + simulation = _person_simulation( + year, + { + "age": {year: 70}, + "is_medicare_eligible": {year: True}, + "medicare_enrolled": {year: True}, + "base_part_a_premium": {year: part_a_premium}, + "gross_medicare_part_b_premium": {year: part_b_premium}, + }, + ) + gross = simulation.calculate("medicare_gross_cost", year)[0] + net = simulation.calculate("medicare_cost", year)[0] + # Variables are float32, so compare to single precision. + assert gross == pytest.approx(_value(year), rel=1e-6) + expected = max(_value(year) - part_a_premium - part_b_premium, 0) + assert net == pytest.approx(expected, rel=1e-6, abs=0.01) + assert net <= gross + + +@settings(max_examples=10, deadline=None) +@given(st.integers(2015, END_YEAR)) +def test_person_not_enrolled_has_no_medicare_cost(year): + simulation = _person_simulation( + year, + { + "age": {year: 70}, + "is_medicare_eligible": {year: True}, + "medicare_enrolled": {year: False}, + }, + ) + assert simulation.calculate("medicare_gross_cost", year)[0] == 0 + assert simulation.calculate("medicare_cost", year)[0] == 0 + + +@settings(max_examples=10, deadline=None) +@given(st.integers(2015, END_YEAR), st.integers(1, 12)) +def test_qmb_cost_sharing_is_the_qmb_rate_of_monthly_spending(year, month): + period = f"{year}-{month:02d}" + rate = system.parameters( + period + ).gov.hhs.medicare.savings_programs.qmb.cost_sharing_rate + simulation = _person_simulation(year, {"msp_category": {period: "QMB"}}) + assert simulation.calculate("qmb_cost_sharing", period)[0] == pytest.approx( + _value(year) / 12 * rate, rel=1e-6 + ) diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/costs/medicare_cost.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/costs/medicare_cost.yaml index 5cb855c4319..b0fb091fce4 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/costs/medicare_cost.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/costs/medicare_cost.yaml @@ -9,7 +9,7 @@ tax_exempt_interest_income: 2023: 0 output: - medicare_cost: 12_280 # $14,500 spending - $2,220 Part B premium (2025) + medicare_cost: 15_531 # $17,751 spending - $2,220 Part B premium (2025) - name: unit test 2 - enrolled, pays full Part A premium period: 2025 @@ -22,7 +22,7 @@ tax_exempt_interest_income: 2023: 0 output: - medicare_cost: 6_064 # $14,500 - $6,216 Part A - $2,220 Part B (2025) + medicare_cost: 9_315 # $17,751 - $6,216 Part A - $2,220 Part B (2025) - name: unit test 3 - enrolled with IRMAA period: 2025 @@ -36,7 +36,7 @@ 2023: 0 filing_status: SINGLE output: - medicare_cost: 6_953.2 # $14,500 - $7,546.80 Part B with IRMAA (2025) + medicare_cost: 10_204.2 # $17,751 - $7,546.80 Part B with IRMAA (2025) - name: unit test 4 - eligible but not enrolled period: 2025 @@ -58,7 +58,7 @@ tax_exempt_interest_income: 2019: 0 output: - medicare_cost: 9_298 # $11,080 - $1,782 Part B (2021: $148.50*12) + medicare_cost: 12_511 # $14,293 - $1,782 Part B (2021: $148.50*12) - name: unit test 6 - direct Part B premium input period: 2025 @@ -68,4 +68,4 @@ medicare_quarters_of_coverage: 40 gross_medicare_part_b_premium: 3_000 output: - medicare_cost: 11_500 # $14,500 spending - $3,000 Part B premium + medicare_cost: 14_751 # $17,751 spending - $3,000 Part B premium diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/costs/medicare_gross_cost.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/costs/medicare_gross_cost.yaml index cba1201e13c..15eb8725e7d 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/costs/medicare_gross_cost.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/costs/medicare_gross_cost.yaml @@ -10,7 +10,8 @@ tax_exempt_interest_income: 2023: 0 output: - medicare_gross_cost: 14_500 + # CMS Medicare spending per enrollee, 2025. + medicare_gross_cost: 17_751 - name: unit test 2 - premiums do not reduce gross Medicare value period: 2025 @@ -25,4 +26,5 @@ 2023: 0 filing_status: SINGLE output: - medicare_gross_cost: 14_500 + # CMS Medicare spending per enrollee, 2025. + medicare_gross_cost: 17_751 diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_cost.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_cost.yaml index 1e9cdaec98a..55be058ba49 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_cost.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_cost.yaml @@ -11,8 +11,8 @@ base_part_b_premium: 2_434.8 output: # Part B premium: $202.90 * 12 = $2,434.80. - # QMB cost sharing: $14,500 * 20% = $2,900. - msp_cost: 5_334.8 + # QMB cost sharing: $18,983 * 20% = $3,796.60. + msp_cost: 6_231.4 - name: Case 2, SLMB MSP-only beneficiary receives Part B premium value. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_federal_and_state_cost.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_federal_and_state_cost.yaml index da73487521b..0c526fe9c29 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_federal_and_state_cost.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_federal_and_state_cost.yaml @@ -10,9 +10,9 @@ base_part_a_premium: 0 base_part_b_premium: 2_434.8 output: - # CA regular FMAP is 50%; total MSP cost is $5,334.80. - msp_federal_cost: 2_667.4 - msp_state_cost: 2_667.4 + # CA regular FMAP is 50%; total MSP cost is $6,231.40. + msp_federal_cost: 3_115.7 + msp_state_cost: 3_115.7 - name: Case 2, QI cost is federally financed within allocation. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/qmb_cost_sharing.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/qmb_cost_sharing.yaml index 4a812377fd3..1fa5134a84f 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/qmb_cost_sharing.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/qmb_cost_sharing.yaml @@ -4,8 +4,8 @@ input: msp_category: QMB output: - # $14,500 annual Medicare per-capita cost / 12 * 20%. - qmb_cost_sharing: 241.67 + # $18,983 annual Medicare spending per enrollee (2026) / 12 * 20%. + qmb_cost_sharing: 316.38 - name: Case 2, non-QMB MSP categories do not receive QMB cost sharing. period: 2026-01 diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/test_part_b_msp_offset.py b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/test_part_b_msp_offset.py index 611c0bf7592..29ecb083de7 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/test_part_b_msp_offset.py +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/test_part_b_msp_offset.py @@ -87,7 +87,8 @@ def test_medicare_cost_uses_gross_part_b_before_msp_offset(): ) assert sim.calculate("medicare_part_b_premium", PERIOD)[0] == pytest.approx(0) - assert sim.calculate("medicare_cost", PERIOD)[0] == pytest.approx(12_280) + # $17,751 CMS Medicare spending per enrollee (2025) - $2,220 gross Part B. + assert sim.calculate("medicare_cost", PERIOD)[0] == pytest.approx(15_531) def test_medicare_part_b_premium_is_zero_when_not_enrolled(): @@ -343,7 +344,8 @@ def test_gross_medicare_part_b_premium_if_enrolled_preserves_irmaa(): assert sim.calculate("gross_medicare_part_b_premium_if_enrolled", PERIOD)[ 0 ] == pytest.approx(4_440) - assert sim.calculate("medicare_cost", PERIOD)[0] == pytest.approx(10_060) + # $17,751 CMS Medicare spending per enrollee (2025) - $4,440 gross Part B. + assert sim.calculate("medicare_cost", PERIOD)[0] == pytest.approx(13_311) def test_medicare_irmaa_magi_two_years_prior_falls_back_to_lagged_income(): diff --git a/policyengine_us/tests/policy/baseline/household/income/household/cbo_household_income.yaml b/policyengine_us/tests/policy/baseline/household/income/household/cbo_household_income.yaml index 275f2797e57..07d9f4f1d8e 100644 --- a/policyengine_us/tests/policy/baseline/household/income/household/cbo_household_income.yaml +++ b/policyengine_us/tests/policy/baseline/household/income/household/cbo_household_income.yaml @@ -33,10 +33,12 @@ workers_compensation: 1_000 output: cbo_household_market_income: 49_102 - medicare_gross_cost: 14_500 - cbo_household_social_insurance_benefits: 29_500 - cbo_household_income_before_transfers_and_taxes: 78_602 - cbo_household_income: 78_602 + # CMS Medicare spending per enrollee, 2025. + medicare_gross_cost: 17_751 + # $12,000 + $17,751 + $2,000 + $1,000. + cbo_household_social_insurance_benefits: 32_751 + cbo_household_income_before_transfers_and_taxes: 81_853 + cbo_household_income: 81_853 - name: CBO means-tested transfers include only the listed programs period: 2026 diff --git a/policyengine_us/tests/policy/baseline/household/income/person/federal_and_state_benefit_cost.yaml b/policyengine_us/tests/policy/baseline/household/income/person/federal_and_state_benefit_cost.yaml index cdc30cc0523..11dedad24db 100644 --- a/policyengine_us/tests/policy/baseline/household/income/person/federal_and_state_benefit_cost.yaml +++ b/policyengine_us/tests/policy/baseline/household/income/person/federal_and_state_benefit_cost.yaml @@ -84,5 +84,7 @@ base_part_a_premium: 0 base_part_b_premium: 2_434.8 output: - federal_benefit_cost: 2_667.4 - state_benefit_cost: 2_667.4 + # MSP cost: $2,434.80 Part B premium + 20% of $18,983 CMS Medicare + # spending per enrollee (2026) = $6,231.40, split at CA's 50% FMAP. + federal_benefit_cost: 3_115.7 + state_benefit_cost: 3_115.7 diff --git a/policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py b/policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py index e50fffb6cf2..901e665cd28 100644 --- a/policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py +++ b/policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py @@ -39,6 +39,11 @@ def test_all_uprating_factors_extend_to_2100(): ("CPI-U", parameters.gov.bls.cpi.cpi_u, "-02-01"), ("Chained CPI-U", parameters.gov.bls.cpi.c_cpi_u, "-02-01"), ("CPI-W", parameters.gov.bls.cpi.cpi_w, "-02-01"), + ( + "CMS Medicare spending per enrollee", + parameters.calibration.gov.hhs.medicare.per_capita_cost, + "-01-01", + ), ] for name, param, date_suffix in uprating_params: