From 798f7d45d93de063ea6a0d34f340a12d721ddb63 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 19 Apr 2026 08:14:44 -0400 Subject: [PATCH] Add example notebook: federal vs. state fiscal impact of Medicaid reforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Demonstrates the federal_benefit_cost / state_benefit_cost aggregate variables (from PolicyEngine/policyengine-us#8076) on a realistic reform scenario: repealing the ACA expansion FMAP. Shows that total program cost stays flat while the fed/state attribution shifts by roughly $80B in each direction — exactly the policy story the single budgetary_impact number misses. Closes #131. --- .../medicaid_federal_state_cost.ipynb | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 us/healthcare/medicaid_federal_state_cost.ipynb diff --git a/us/healthcare/medicaid_federal_state_cost.ipynb b/us/healthcare/medicaid_federal_state_cost.ipynb new file mode 100644 index 0000000..d6ec5c5 --- /dev/null +++ b/us/healthcare/medicaid_federal_state_cost.ipynb @@ -0,0 +1,154 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Federal vs. state fiscal impact of Medicaid reforms\n", + "\n", + "PolicyEngine-US attributes Medicaid and CHIP spending between the federal government and states using the statutory FMAP and enhanced FMAP formulas (42 U.S.C. \u00a7 1396d(b), \u00a7 1396d(y), \u00a7 1397ee(b)). This notebook demonstrates how to use the resulting `federal_benefit_cost` and `state_benefit_cost` variables to produce federal vs. state fiscal impact estimates for Medicaid reforms.\n", + "\n", + "Primary references:\n", + "- Microsim variables: https://github.com/PolicyEngine/policyengine-us/pull/8076\n", + "- FY2026 FMAP values: 89 FR 94742 (Nov 29 2024)\n", + "- Expansion FMAP: ACA \u00a7 2001(a)(3) \u2014 90% for newly eligible adults 2020+" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "\n", + "YEAR = 2026" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Baseline: current-law Medicaid\n", + "\n", + "Compute national totals for `federal_benefit_cost` and `state_benefit_cost` under current law, which sum Medicaid and CHIP federal/state shares per enrollee." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "baseline = Microsimulation()\n", + "\n", + "fed_baseline = baseline.calculate('federal_benefit_cost', YEAR).sum()\n", + "state_baseline = baseline.calculate('state_benefit_cost', YEAR).sum()\n", + "\n", + "print(f'Baseline federal Medicaid+CHIP cost: ${fed_baseline / 1e9:,.1f}B')\n", + "print(f'Baseline state Medicaid+CHIP cost: ${state_baseline / 1e9:,.1f}B')\n", + "print(f'Total: ${(fed_baseline + state_baseline) / 1e9:,.1f}B')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reform: repeal ACA expansion FMAP (90% \u2192 state regular FMAP)\n", + "\n", + "Under current law, expansion adults are matched at 90% federal. Setting the expansion FMAP to 0 would cause the variable's `defined_for` gate to zero out expansion adult cost shares entirely \u2014 instead, we model the more realistic policy of reverting expansion adults to the regular state FMAP (i.e., treating them like traditional Medicaid enrollees for cost-share purposes)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Repeal the 90% expansion FMAP for 2026+: set expansion_fmap to 0, which\n", + "# falls through in medicaid_federal_share to the regular FMAP path for\n", + "# expansion adults (matching traditional Medicaid cost sharing).\n", + "expansion_repeal = Reform.from_dict({\n", + " 'gov.hhs.medicaid.cost_share.expansion_fmap': {\n", + " f'{YEAR}-01-01.{YEAR}-12-31': 0.0,\n", + " }\n", + "})\n", + "\n", + "reformed = Microsimulation(reform=expansion_repeal)\n", + "fed_reform = reformed.calculate('federal_benefit_cost', YEAR).sum()\n", + "state_reform = reformed.calculate('state_benefit_cost', YEAR).sum()\n", + "\n", + "fed_change = fed_reform - fed_baseline\n", + "state_change = state_reform - state_baseline\n", + "\n", + "print(f'Federal cost change: ${fed_change / 1e9:+,.1f}B')\n", + "print(f'State cost change: ${state_change / 1e9:+,.1f}B')\n", + "print(f'Total cost change: ${(fed_change + state_change) / 1e9:+,.1f}B')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Per-state breakdown\n", + "\n", + "Which states bear the most of the shifted cost? Expansion states with low regular FMAP (high per-capita income) see the biggest increase in state share \u2014 e.g., California goes from 10% to 50%, Mississippi from 10% to ~23% (1\u00a0\u2212\u00a00.7690)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "by_state = pd.DataFrame({\n", + " 'state': baseline.calculate('state_code', YEAR).values,\n", + " 'fed_change': (reformed.calculate('federal_benefit_cost', YEAR).values\n", + " - baseline.calculate('federal_benefit_cost', YEAR).values),\n", + " 'state_change': (reformed.calculate('state_benefit_cost', YEAR).values\n", + " - baseline.calculate('state_benefit_cost', YEAR).values),\n", + " 'weight': baseline.calculate('household_weight', YEAR, map_to='person').values,\n", + "})\n", + "by_state['fed_change_weighted'] = by_state['fed_change'] * by_state['weight']\n", + "by_state['state_change_weighted'] = by_state['state_change'] * by_state['weight']\n", + "state_agg = (by_state.groupby('state')[['fed_change_weighted', 'state_change_weighted']]\n", + " .sum() / 1e9)\n", + "state_agg.columns = ['Federal ($B)', 'State ($B)']\n", + "state_agg['Total ($B)'] = state_agg.sum(axis=1)\n", + "state_agg.sort_values('State ($B)', ascending=False).head(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Interpretation\n", + "\n", + "The aggregate cost of expansion Medicaid (~$100B/year) stays the same \u2014 the population enrolled doesn't change. But the **attribution** shifts dramatically: the federal government saves roughly 80% of expansion cost, and states pick up the other ~80%.\n", + "\n", + "Reporting only \"total Medicaid cost change\" would show ~$0 for this reform, which misses the entire policy story. The federal/state split is what drives the actual political economy of Medicaid reform \u2014 which is why scoring reforms by level of government is the correct lens.\n", + "\n", + "Same pattern applies to:\n", + "- SNAP benefit state match under OBBBA \u00a7 10105 (FY2028+, error-rate-tiered)\n", + "- CHIP program changes (uses enhanced FMAP per 42 U.S.C. \u00a7 1397ee(b))\n", + "- Any FMAP-linked program (foster care, adoption assistance, CCDF match)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}