Post-collapse calibration & target fixes (MP vs eCPS audit)
Follow-up to the collapse-scaffold RC (#193) + L0 wiring (#194) + export support gate (#195) + export population (#196). Those fixed the export side (every eCPS-supported export now populated + gated). This issue tracks the calibration-surface / target side — four distinct findings from an MP-vs-eCPS audit that scored both datasets against MP's 56 national targets via microdf weighted .sum(). Full evidence + per-target table in mp-ecps-tracking/audit/dashboard.html; detail in loop journal iters 74–78.
Overall: collapse build mean |loss| (capped 10) = 0.964 vs eCPS 1.106 (MP better aggregate), but eCPS wins the headline income lines because of the bugs below.
1. Income seam double-count (interest) — taxable_interest_income +377% vs target
- collapse $596B vs target $124B (+377%), vs eCPS $300B (+140%).
- Cause: interest lands from both CPS
INT_VAL (data_sources/cps.py) and PUF E00300 (data_sources/puf.py:75) on the collapsed scaffold row — they are summed rather than reconciled to one authoritative source. The collapse merge keeps shared CPS amount fields CPS-owned unless overridden; interest is double-sourced.
- Compounded by an aggressive PUF interest uprating factor
taxable_interest_income: 2.50 (data_sources/puf.py:153): PUF 2015 E00300 = $97.8B → ×2.50 = $245B, already ~2× the $124B target before the CPS contribution.
- Fix: reconcile CPS-total vs PUF-component for interest (pick one authoritative); revisit the 2.50× uprate.
2. Dividend qualified/non-qualified split inverted — qualified_dividend_income −65% vs target
- collapse qualified $102B (target $291B, −65%) / non-qualified $465B; eCPS qualified $352B / non-qualified $148B.
- Total dividend is ~right ($566B vs eCPS $499B); only the split is wrong. PUF source split is correct (E00650 qualified = 78% of E00600 ordinary). Downstream,
non_qualified = dividend_income(CPS total) − qualified(under-imputed) = $566.5B − $101.6B = $464.9B exactly, so non-qualified absorbs the CPS total and qualified is under-imputed.
- Fix: impute the qualified share of the total preserving the PUF ~78% split; don't derive non-qualified as a residual against the CPS total.
3. Wages uncalibrated — employment_income has no target in the build → AGI +18%
- employment_income: collapse $12,469B vs eCPS $10,357B, zero national target in the 158
policyengine_l0_package set (profile pe_native_broad). Drags adjusted_gross_income to +18% over its $14,425B target (the income components already sum past AGI; wages are the dominant excess).
- MP already HAS wage targets in Arch (
targets/arch.py): irs_soi.total_wages → wages_salaries_amount AND bea_nipa.wages_and_salaries → employment_income_before_lsr. They were just not in pe_native_broad.
- Note vs NIPA wages (~$11.5–12T) collapse is only ~+7% (eCPS −11%); the +20% was vs SOI/eCPS. Confirm the exact
bea_nipa.wages_and_salaries value from Arch.
- Fix: load a profile that includes the wage target (SOI and/or NIPA), so the largest aggregate is anchored.
4. Tax-expenditure targets scored as deduction amounts + missing SOI deduction-amount targets
salt_deduction target = $21.2B (JCT tax-expenditure, eCPS etl_national_targets.py reform_id=NEUTRALIZE_VARIABLE_REFORM_ID=1), but MP scores the model's deduction amount ($551B) against it → spurious +2496% (the "worst family"). MP's ledger entry has no reform_id, the build runs reform_id=0, and MP has no neutralization handling. Same for QBI (tax-exp $63B vs amount). These losses are not real miscalibration.
- The meaningful SALT signal is the SOI amount target
salt>0 = $250B, where MP is +254% (genuine over-imputation, same seam).
- MP's 158 is also missing the SOI deduction-amount targets for
medical_expense_deduction, charitable_deduction, mortgage/interest_deduction that eCPS loads via etl_irs_soi (all present in MP's Arch catalog, just not in pe_native_broad).
- Fix: either drop the reform-required tax-expenditure targets from the baseline solve or evaluate them with
reform_id=1 (MP has target_reform_id plumbing in registry/index_db/adapters); add the missing SOI deduction-amount targets.
Coverage note (answers "what targets is eCPS using that MP isn't")
eCPS has NO BEA/NIPA and NO direct wage target; its ~34 vars come from IRS SOI + CBO + Census + CMS/SSA/HHS + Treasury/JCT. MP's build shares that PE package (158 targets) and MP's Arch is a superset (164 concepts incl. NIPA + BEA-regional + fuller SOI). The only eCPS-only target found is the undocumented-population count (ssn_card_type=="NONE"); possible geographic gap to verify is congressional-district-level SOI (eCPS national+state+district; MP build national+state).
Post-collapse calibration & target fixes (MP vs eCPS audit)
Follow-up to the collapse-scaffold RC (#193) + L0 wiring (#194) + export support gate (#195) + export population (#196). Those fixed the export side (every eCPS-supported export now populated + gated). This issue tracks the calibration-surface / target side — four distinct findings from an MP-vs-eCPS audit that scored both datasets against MP's 56 national targets via microdf weighted
.sum(). Full evidence + per-target table inmp-ecps-tracking/audit/dashboard.html; detail in loop journal iters 74–78.Overall: collapse build mean |loss| (capped 10) = 0.964 vs eCPS 1.106 (MP better aggregate), but eCPS wins the headline income lines because of the bugs below.
1. Income seam double-count (interest) —
taxable_interest_income+377% vs targetINT_VAL(data_sources/cps.py) and PUFE00300(data_sources/puf.py:75) on the collapsed scaffold row — they are summed rather than reconciled to one authoritative source. The collapse merge keeps shared CPS amount fields CPS-owned unless overridden; interest is double-sourced.taxable_interest_income: 2.50(data_sources/puf.py:153): PUF 2015 E00300 = $97.8B → ×2.50 = $245B, already ~2× the $124B target before the CPS contribution.2. Dividend qualified/non-qualified split inverted —
qualified_dividend_income−65% vs targetnon_qualified = dividend_income(CPS total) − qualified(under-imputed)= $566.5B − $101.6B = $464.9B exactly, so non-qualified absorbs the CPS total and qualified is under-imputed.3. Wages uncalibrated —
employment_incomehas no target in the build → AGI +18%policyengine_l0_packageset (profilepe_native_broad). Dragsadjusted_gross_incometo +18% over its $14,425B target (the income components already sum past AGI; wages are the dominant excess).targets/arch.py):irs_soi.total_wages→wages_salaries_amountANDbea_nipa.wages_and_salaries→employment_income_before_lsr. They were just not inpe_native_broad.bea_nipa.wages_and_salariesvalue from Arch.4. Tax-expenditure targets scored as deduction amounts + missing SOI deduction-amount targets
salt_deductiontarget = $21.2B (JCT tax-expenditure, eCPSetl_national_targets.pyreform_id=NEUTRALIZE_VARIABLE_REFORM_ID=1), but MP scores the model's deduction amount ($551B) against it → spurious +2496% (the "worst family"). MP's ledger entry has noreform_id, the build runsreform_id=0, and MP has no neutralization handling. Same for QBI (tax-exp $63B vs amount). These losses are not real miscalibration.salt>0= $250B, where MP is +254% (genuine over-imputation, same seam).medical_expense_deduction,charitable_deduction, mortgage/interest_deductionthat eCPS loads viaetl_irs_soi(all present in MP's Arch catalog, just not inpe_native_broad).reform_id=1(MP hastarget_reform_idplumbing inregistry/index_db/adapters); add the missing SOI deduction-amount targets.Coverage note (answers "what targets is eCPS using that MP isn't")
eCPS has NO BEA/NIPA and NO direct wage target; its ~34 vars come from IRS SOI + CBO + Census + CMS/SSA/HHS + Treasury/JCT. MP's build shares that PE package (158 targets) and MP's Arch is a superset (164 concepts incl. NIPA + BEA-regional + fuller SOI). The only eCPS-only target found is the undocumented-population count (
ssn_card_type=="NONE"); possible geographic gap to verify is congressional-district-level SOI (eCPS national+state+district; MP build national+state).