PolicyEngine / PolicyEngine/microcosm

Subtract modeled Medicare Part A premium and Part D IRMAA in the other-premium residual

Open
#329 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
0
Forks
4
Avg merge
1d 3h
Merged PRs (30d)
94

Description

Type

Pure data / dataset contract.

Context

policyengine-us PR #8532 adds two modeled components to spm_unit_health_insurance_premiums (and therefore SPM MOOP):

  • medicare_part_a_premium (person-level; base Part A premium net of QMB Medicare Savings Program coverage), and
  • income_adjusted_part_d_premium_surcharge (person-level Part D IRMAA computed from prior-prior-year MAGI).

The MOOP decomposition contract (docs) expects data construction to subtract baseline modeled premiums from CPS-reported non-Medicare premiums when building other_health_insurance_premiums, so reforms move the modeled pieces without double counting. The legacy pipeline implements this in archived policyengine-us-data (derive_other_health_insurance_premiums in policyengine_us_data/datasets/cps/cps.py), subtracting baseline chip_premium, marketplace_net_premium, and medicaid_premium from health_insurance_premiums_without_medicare_part_b (PHIP_VAL, which includes Part A/D amounts).

Populace currently:

  • carries health_insurance_premiums_without_medicare_part_b raw from PHIP_VAL (cps_carried.py), and
  • does not construct other_health_insurance_premiums at all — it is an eCPS parity known gap pointing at #32.

What needs to happen

  1. When Populace ports the other-premium residual (the #32 MOOP family), the baseline subtraction list must include the two new Medicare components in addition to the legacy CHIP/Marketplace/Medicaid three. The Part D IRMAA subtraction is live immediately: the surcharge is computed from MAGI, so IRMAA-band enrollees whose PHIP_VAL includes Part D payments would otherwise double count.
  2. medicare_quarters_of_coverage is set nowhere in Populace; policyengine-us now defaults it to 40 (premium-free, matching 99% of beneficiaries), so modeled Part A is $0 in baseline microdata. Record this column as intentionally defaulted in the input-readiness contract (#98), and do not populate it before the Part A subtraction in (1) exists — populating quarters first would double count full Part A premiums ($6,780/yr per affected enrollee in 2026) against reported premiums.

Acceptance criteria

  • The other_health_insurance_premiums residual construction subtracts baseline chip_premium, marketplace_net_premium, medicaid_premium, medicare_part_a_premium, and income_adjusted_part_d_premium_surcharge, with a test.
  • medicare_quarters_of_coverage is recorded as observed, imputed, unavailable, or intentionally defaulted, and any future population of it is sequenced after the residual subtraction.

Related: #32 (MOOP input family umbrella), #98 (health input readiness, incl. lagged IRMAA MAGI), #204 (us-data replacement tracking), #169 (Part B premium payer-count diagnosis).

🤖 Generated with Claude Code

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the archived derive_other_health_insurance_premiums in policyengine_us_data/datasets/cps/cps.py and Populace's cps_carried.py, then read the MOOP decomposition documentation and related issues #32 and #98. Implement the residual contract with a test, and document medicare_quarters_of_coverage as intentionally defaulted with future population sequenced afterward.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data-engineering
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.