Skip to content

Pooled prior-year ASEC wages are not aged to the target year #944

Description

@MaxGhenis

Observed while joining raw ASEC records to the certified national file (populace-us-2024-spm-20260915; see the wage-band target issue for context).

For every one of the 166,321 persons, the 2024-period payroll_tax_gross_wages equals the raw ASEC WSAL_VAL for that person's own income year (ratio 1.000 at the 10th, 50th and 90th percentiles). Records from income years 2022 (31% of weight) and 2023 (31%) therefore carry 2022 and 2023 nominal wages in the 2024 period. us_runtime/asec_pool.py scales each year's weights to a population share and does not adjust dollar amounts; I found no other stage that ages them for employment_income.

Consequences measured on FUTA: Microcosm's Σ min(wage, $43,000) is 8.5% below the raw ASEC 2025 file at Census weights ($31.78B vs $34.74B at 0.6%), while Σ min(wage, $7,000) matches within 1.2%. Total payroll-tax wages are $10.74T vs $12.07T. Calibration to SOI/BEA/CBO aggregates compensates in total but not by wage band.

Question for the build owners: is the no-aging behaviour intended (weights absorb the vintage difference) or should pooled prior-year dollar inputs be uprated to the target year before calibration? If intended, a wage-band target would be the guard; if not, this is a fix in the pooling or source stage.

Activity

  1. PavelMakarchuk commented on Oct 6, 2026

    @PavelMakarchuk
    Contributor

    Found by the policyengine-scorecard reform-validation diagnosis (batch 2), PolicyEngine/policyengine-scorecard#146. Memo: diagnosis/batch2/C.md, item C-1.
    Related: #944 (same no-aging behavior, measured on wages), #646 (child-vs-total SPM anomaly), #981 (per-record donor aging), #1044 (default pool moved to income years 2023-2025).

    Summary

    On the certified bundle us-6.2.1 (policyengine-us 2.2.1 + populace-us-2024-spm-20260915), records from ASEC income years 2022 and 2023 carry their own-year nominal dollars into the 2024 period, while the SPM calculator prices every unit at 2024 thresholds. The 2022-income records (34.1% of child weight) therefore meet a threshold about 13.7% above the one Census used for them; the 2023-income records meet one about 5.8% above.

    First-order estimate (taxes and benefits not recomputed): testing each record against its own source-year threshold lowers the national 2024 SPM child rate from 15.83% to 13.24% (-2.6 pp) and the total rate from 13.06% to 11.48% (-1.6 pp). This is one component of the child excess in #646. The batch-2 decomposition of the +2.43 pp national child gap vs Census P60-287 is: populace weighting +3.1 pp, this item +2.6 pp, the policyengine-us partnership-income omission (PolicyEngine/policyengine-us#9919) +1.3 pp, other resource differences -4.5 pp (all first order).

    What microcosm documents (@ 581b569)

    docs/us-asec-source-pins.md:216-220

    • Money. The pooled person tables carry nominal dollars of each income
      year, as they did for 2022-2024; no base-build stage restates them by source
      year. target_aging ages calibration targets, not survey records. The mean
      income year of the default pool is 2024, the target year; for the old pool
      it was 2023.

    docs/us-spm-role-stage.md:143-144
    ... each of the three Build P vintages (income years 2022-2024):

    What the engine does

    The SPM threshold year is the simulation period for every unit, whatever its source year:

    spm_calculator/policyengine_adapter.py:311-313 (spm-calculator 1.0.0, installed with policyengine-us 2.2.1)

        rows = [
            bound._amounts(
                int(period.start.year),

    Measurements on the certified H5

    Check income year 2022 2023 2024
    Share of child weight 34.1% 31.8% 34.1%
    Median of PE (market income + SS + SSI + UC) / Census SPM_TOTVAL, ASEC-channel units 1.0000 0.9999 0.9999
    Child-weighted median of PE threshold / Census SPM_POVTHRESHOLD 1.137 1.058 1.004
    Child-weighted median of PE geographic factor / Census SPM_GEOADJ 0.997 0.997 1.000
    PE child SPM rate 17.2% 14.6% 15.6%
    Census SPM_POOR on the same weighted records 15.4% 17.5% 16.6%
    • Wage inputs equal WSAL_VAL for 100% of ASEC-channel adults and 99.9% of PUF-clone adults.
    • The geographic factors match Census, so the threshold gap is the year, not the county adjustment.
    • Per state, the own-year-threshold effect is 0-5.5 pp (C.md, column vint).

    Why a pool centred on the target year still needs a fix

    #1044 makes the default pool income years 2023-2025, whose mean is the target year. Each record is still tested against a threshold from a different year than its dollars: 2023 records against a higher one, 2025 records against a lower one. Poverty is a threshold test, so the two errors cancel only if the income density near the threshold is the same in both vintages. (Reasoning, not measured.)

    Options

    1. Age pooled-year dollar inputs to the target year per record at build time, series by series (the per-record donor ager proposed in Age donor dollar values to the base year per record, not through weights (SCF, SIPP, PUF) #981, applied to the ASEC pool). This is also the fix Pooled prior-year ASEC wages are not aged to the target year #944 asks about.
    2. For the 3-year Census backtest rows (us/state_spm_poverty_levels.json), evaluate SPM status against each record's own source-year threshold. That matches how the Census flag on the H5 is built: SPM_POOR == (SPM_RESOURCES < SPM_POVTHRESHOLD) holds for 100% of units, with each source year's own thresholds.

    Acceptance test (external ground truth)

    The H5 carries Census SPM_POOR, SPM_RESOURCES, SPM_POVTHRESHOLD and source_year, and PE and Census SPM units align exactly (0 of 59,900 PE units span more than one Census SPM_ID). After the fix, the by-source-year gap between PE's SPM status and Census SPM_POOR on ASEC-channel records should no longer depend on the source year, within a stated tolerance.

    Limits

    First order: benefits and taxes are computed at 2024 law on nominal income and are not recomputed. Option 1 ages income with income-growth series, not SPM-threshold growth, so its effect will differ in size from the threshold counterfactual above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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