Skip to content

Add federal vs. state budgetary impact to economic_impact_analysis #289

@MaxGhenis

Description

@MaxGhenis

Context

PolicyEngine/policyengine-us#8076 added Person-level variables federal_benefit_cost / state_benefit_cost that split benefit expenditures between levels of government (currently covers Medicaid FMAP and CHIP eFMAP; will extend to SNAP OBBBA FY2028 state match, etc.).

Today economic_impact_analysis() in src/policyengine/tax_benefit_models/us/analysis.py returns per-program stats and aggregate impacts, but doesn't partition benefit spending by federal vs. state. Every consumer — policyengine-api's compare.py::budgetary_impact (PolicyEngine/policyengine-api#3481), analysis notebooks (PolicyEngine/analysis-notebooks#131), ad-hoc scripts — needs the same arithmetic, so the logic belongs here, not duplicated in each caller.

Proposal

Extend PolicyReformAnalysis to expose:

  • federal_budgetary_impact: federal tax revenue change (income_tax + payroll_tax) minus federal benefit spending change (federal_benefit_cost)
  • state_budgetary_impact: state tax revenue change (state_income_tax) minus state benefit spending change (state_benefit_cost)
  • total_budgetary_impact: existing sum, unchanged

Implementation: add two ChangeAggregate(variable="federal_benefit_cost", type=ChangeAggregateType.SUM) / state_benefit_cost calls alongside the existing per-program aggregates, and expose the federal/state splits as top-level fields on the analysis object.

Also tag ProgramStatistics entries with a level_of_government field ("federal", "state", or "shared") so consumers can filter per-program rows. For shared programs like Medicaid/CHIP, also populate federal_change / state_change using the new variables.

Why here vs. API

  • Thin arithmetic on microsim sums — no Flask-specific state
  • Analysis notebooks and ad-hoc Python scripts (not just the app) need this split
  • policyengine-api#3481 becomes a pass-through wiring change once this lands

Example

from policyengine.tax_benefit_models.us import economic_impact_analysis

analysis = economic_impact_analysis(baseline_sim, reform_sim)
print(f"Federal cost: ${analysis.federal_budgetary_impact / 1e9:+.1f}B")
print(f"State cost:   ${analysis.state_budgetary_impact / 1e9:+.1f}B")
print(f"Total:        ${analysis.total_budgetary_impact / 1e9:+.1f}B")

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions