Repository navigation
Uprate dollar inputs by national totals per capita - #9526
Merged
Merged
Conversation
Household weights grow with total population. Dollar inputs that follow a national total (IRS SOI series, CBO income projections) grew by the full total as well, so weighted totals counted population growth twice: 0.9 percent too high in 2025, 5.1 percent by 2035 on the default dataset. For each national total a variable uprates by, build a sibling parameter holding the total divided by population and point the variable at it. The dataset-extension path resolves its overrides the same way. CMS per-capita spending, CPI-U and the population series are unchanged. The Trustees 2025 long-run scenario extends the SOI totals by the average wage index; it now also carries population growth so each record's income still follows the average wage. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- HHS state median income was projected from 2027 by aggregate AGI while incomes now grow per capita, so the threshold outran incomes by population growth (2.8 percent by 2035) and shifted childcare and energy eligibility. Project it by AGI per capita; build that series before parameter uprating. - Refresh the derived series after every modify_parameters call. Core's Simulation applies the reform again after system init, and a reform applied only then left the series stale. - Dataset extension now raises when a national total has no per-capita sibling, and when a derived series no longer equals its total over population, instead of quietly double counting or ignoring a change. - Classify national totals by family (CBO, IRS SOI) and reject other calibration paths: state totals and head counts need other denominators. - Mark derived series with derived_from; refresh only those, and refuse to overwrite a hand-written series that shares the derived name. - Clear ancestor at-instant caches after adding a derived series. - Docs: default_uprating assigns the total; per_capita_uprating converts it. - Tests for each of the above, the post-2055 boundary, and mock fixtures that carry the sibling. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The Rest CI job already runs near its 60-minute limit; cache the Trustees build and share one fresh system across the post-init checks (five builds to three). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
uprating-per-capita
branch
from
September 18, 2026 15:26
6eab0e8 to
ab96702
Compare
The two one-dollar cases pin the 50 percent SMI floor for 2031. State median income is now projected per capita with AGI, so the floor is 69,317.41 instead of 70,405.39: the old value divided by population growth from 2027. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a double count of population growth in uprating. Stacked on #9525, which corrects the docs paragraph this PR then updates; merge that first and this diff shrinks to one commit.
The defect
Household weights grow with total population (
calibration.gov.census.populations.total). Dollar inputs that follow a national total, an IRS SOI series or a CBO income projection, grew by the full total as well. The weighted total of each such input therefore grew by the national total times population growth.Measured on the default dataset (
populace_us_2024.h5atpopulace-us-2024-spm-20260909), growth from 2024:employment_income_before_lsrsocial_security_retirementpre_subsidy_rentThe overshoot equalled weighted population growth in every case: 1.00928 in 2025, 1.03473 in 2030, 1.05056 in 2035. It applied to all 33 dataset columns on IRS SOI series and all 44 on the CBO total AGI default.
The fix
policyengine_us/tools/per_capita_uprating.pyruns at the end of system init. For each national total that a variable uprates by, it adds a sibling parameter holding the total divided by population (<path>_per_capita) and points the variable at it. A national total is any path undercalibration.govthat does not already sayper_capitaand is not the population series.Simulationuses policyengine-core's variable-level uprating, which readsvariable.uprating.Microsimulationextends the single-year dataset throughextend_single_year_dataset, which also has its own override table; those overrides now resolve to the per-capita sibling too.household_weightandfamily_weight.economy: falseandhousehold: false.Trustees 2025 long-run scenario
apply_trustees_2025_soi_income_projectionextends the SOI totals past 2036 by the average wage index so that each record's income follows wages. With per-capita uprating it now multiplies by population growth as well, so per-record growth still equals average-wage growth and the weights carry population. A new test asserts this for 2040 and 2050. The baseline extension past 2036 compounds the last CBO growth rate, which is aggregate growth, so it needs no change.Legacy data pipeline
policyengine_us_data/utils/uprating.pyalready divides national totals by population growth and skips any path containingper_capita. It will read the new paths as already per capita, which is correct. That repository is archived.Tests
tests/core/test_per_capita_uprating.py, 24 tests: path classification, no variable left on a national total, each per-capita series equals total over population, overrides resolve, weighted totals track national totals in an extended dataset for 2025, 2030 and 2035, the same throughSimulation, a population reform reaches the series, idempotence, and the Trustees scenario.tests/microsimulation/data,tests/policy/contrib/ssa,tests/policy/baseline/parameters/test_uprating_extensions.py,tests/test_system_import.py. The full suite is left to CI.Effect on results
Population results for the dataset year do not change. For later years, every input on a national total is lower than before by cumulative population growth: 0.9 percent in 2025, 5.1 percent in 2035. Household calculations that supply inputs for the year they calculate do not change. I have not measured the effect on budgetary or poverty estimates.
Review findings addressed (second commit)
An independent adversarial review confirmed the identity exactly (weighted-total growth equals national-total growth to ten decimal places at person, household and SPM-unit level, including the two negative totals) and requested changes on six points. All are in the second commit.
gov.hhs.smi.amountis projected from 2027 by aggregate AGI; with incomes now per capita, the threshold drifted above them by population growth, 2.8 percent by 2035, and moved childcare and energy eligibility in projection years. It now follows AGI per capita, and that series is built before parameter uprating runs. This is the only parameter outside the calibration tree that uprates by a national total.Simulationapplies a reform once more after the country system is built, and a non-idempotent reform to a total would then not reach uprating.modify_parametersnow refreshes the derived series after every call.calibration.gov.cbo.andcalibration.gov.irs.soi.. Any othercalibrationpath on a variable or override raises at init, since a state total or a head count needs a different denominator.derived_from; only those refresh, and a hand-written series that shares the derived name stops the build.parameters(instant)views resolve it.Also from the review: the unused import is gone, the docs paragraph now attributes the per-capita default correctly, and tests cover the boundary after the population series ends in 2055.
One test reprojected
tests/policy/baseline/gov/states/wa/dcyf/eceap/wa_eceap_income_eligible.yamlhas two 2031 cases one dollar either side of the 50 percent state-median-income floor. That floor is a projection, and with SMI now projected per capita the floor is 69,317.41 rather than 70,405.39, the old value divided by population growth from 2027. The cases now sit one dollar either side of the new floor. Every other projection-year test of an SMI-based program (11 files) passes unchanged.Not in this PR
calibration.gov.cbo.unemployment_compensationsits unused, and rent and child care expenses following total AGI.🤖 Generated with Claude Code