Derive the 191->detail II and VA series, and give Step 3 an observed column control - #712
Merged
Conversation
…control
BEA publishes intermediate inputs (UII205-A) and value added (UVA205-A)
annually 1997-2024 on its 191-row "underlying" industry frame, in two
workbooks sitting beside the GrossOutput.xlsx this repo already reads.
Nothing read either one. This extracts both, allocates them to the 402
detail industries, and replaces Step 3's frozen-2017 VAPRO seed.
The 191->402 mapping is derived, not hand-written. UGO205-A and UGO305-A
order industries the same way, so the 138 leaves of the 205-A hierarchy
partition the 414 rows of 305-A into contiguous runs; the runs are closed
by matching gross output in all 28 years. All 138 leaves match, exactly
414 of 414 detail rows are consumed, and the 402 codes cover the model
schema once each. derive_underlying_line_mapping reproduces the
checked-in constant exactly, and --mapping on the new diagnostic is how
to re-check it when the BEA vintage moves.
Value added is allocated and intermediate inputs are taken as the
residual GO - VAPRO. That is what makes GO = T005 + VAPRO hold per
industry, which is the form T1 imposes; allocating both independently
broke it by up to $15.2B a cell at 2024. It costs nothing against BEA:
- VAPRO summed back to the 138 lines reproduces UVA205-A exactly
(0.0 on 3,864 cells); T005 reproduces UII205-A to $9M, which is
BEA's own GO=II+VA rounding.
- At 2017 the derived columns reproduce the published detail Use SUT
margins to $0.89M (VAPRO) and $1.48M (T005) per industry.
- Economy-wide VA matches published GDP to at most $9M on $29T in
every year 1997-2024.
- GO - T005 - VAPRO at detail is 2.9e-11.
It also removes the suppression problem. BEA suppresses intermediate
inputs in every year on lines 83 (Customs duties) and 176 (Private
households); both are single-industry lines whose published 2017 T005 is
zero, and the residual recovers that zero rather than needing a special
case.
Step 3's column control is now GO - VAPRO with both sides observed.
Aggregated to summary and scored against the published summary T005 it
is within 0.00007% economy-wide and 0.00023% weighted MAE by industry in
every year 2018-2024, worst summary industry 0.003%. The superseded
frozen-ratio seed scored 0.2-2.3% and 2.5-8.0%, with GSLG 18.3% low at
2022. That is a consistency check and not an independent validation --
UII205-A and the summary Use SUT's T005 are the same BEA estimate
published two ways -- so what it establishes is that the allocation adds
back correctly and the control now *is* BEA's T005. vapro_seed becomes
vapro; the now-dead _row helper and published_gross_output import go.
Signs are carried, not clipped. S00201 has a published 2017 VAPRO of
-$10,069M and stays negative in all 28 years. The residual T005 goes
negative in 11 cells, all in 5191A0 and all in 2002-2015, so the
2017-2024 nowcast span is clear; the other residual direction was worse
(13 spurious negatives across three industries, reaching -$13,117M).
This is not Step 2. VAPRO is the column total; Step 2 owes the split
across the five value-added rows, and T4/T6 are still soft placeholders.
What changes is that there is now a VA level for every year rather than
for 2017 alone, so the balance can run on 2024. It also arrives off the
P1-gated path -- a straight Excel read on the shape of the working
UGO305-A loader, so map_fbs_sectors_to_model_schema never enters it.
Repo-wide: black, ruff, mypy clean (bar the four known Windows-only
settings.py errors); 779 passed, 2 skipped, 1 xfailed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
allocate_underlying_to_detail is public and takes an arbitrary mapping. A code appearing under two lines would be indexed twice by .loc[children] and written twice into the output, so the group totals would silently stop adding up rather than raising. Same for a duplicated line in group_values, where .loc[line] returns a frame instead of a row. The checked-in mapping has neither -- 402 codes, all distinct -- so this guards the function, not the current data. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
WesIngwersen
force-pushed
the
step3_underlying_ii_va
branch
from
August 26, 2026 18:30
5a8bec4 to
4324cb0
Compare
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.
Stacked on #710 (
step3_core), which is green on all four checks.BEA publishes intermediate inputs (
UII205-A) and value added (UVA205-A) annually 1997-2024 on its 191-row "underlying" industry frame, in two workbooks sitting beside theGrossOutput.xlsxthis repo already reads. Nothing read either one. This extracts both, allocates them to the 402 detail industries, and replaces Step 3's frozen-2017VAPROseed.The 191→402 mapping is derived, not hand-written
UGO205-AandUGO305-Aorder industries the same way, so the 138 leaves of the 205-A hierarchy partition the 414 rows of 305-A into contiguous runs; the runs are closed by matching gross output in all 28 years. All 138 leaves match, exactly 414/414 detail rows are consumed, and the 402 codes cover the model schema once each.derive_underlying_line_mappingreproduces the checked-in constant exactly.--mappingon the new diagnostic is how to re-check it when the BEA vintage moves.VA is allocated; II is the residual
weight_c(t) = VAPRO_c(2017)/GO_c(2017) · GO_c(t), rescaled to the published line total; thenT005 = GO − VAPRO.Taking II as the residual is what makes
GO = T005 + VAPROhold per industry, which is the form T1 imposes — allocating both independently broke it by up to $15.2B a cell at 2024. It costs nothing against BEA:UVA205-AUII205-AGO=II+VArounding)GO − T005 − VAPROat detailIt also removes the suppression problem: BEA suppresses II in every year on lines 83 (Customs duties) and 176 (Private households), both single-industry lines whose published 2017
T005is zero, and the residual recovers that zero rather than needing a special case.Step 3's column control
Now
GO − VAPROwith both sides observed. Aggregated to summary and scored against the published summaryT005: within 0.00007% economy-wide and 0.00023% weighted MAE by industry in every year 2018-2024, worst summary industry 0.003%. The superseded frozen-ratio seed scored 0.2-2.3% and 2.5-8.0%, withGSLG18.3% low at 2022.UII205-Aand the summary Use SUT'sT005are the same BEA estimate published two ways. What it establishes is that the allocation adds back correctly, so the control is BEA'sT005rather than an approximation of it.vapro_seedbecomesvapro; the now-dead_rowhelper andpublished_gross_outputimport go.Signs are carried, not clipped
S00201has a published 2017VAPROof −$10,069M and stays negative in all 28 years. The residualT005goes negative in 11 cells, all in5191A0and all in 2002-2015, so the 2017-2024 nowcast span is clear. The other residual direction was worse: 13 spurious negatives across three industries, reaching −$13,117M.This is not Step 2
VAPROis the column total. Step 2 owes the split across the five value-added rows, and T4/T6 are still soft placeholders. What changes is that there is now a VA level for every year rather than for 2017 alone, so the balance can run on 2024.It also arrives off the P1-gated path — a straight Excel read on the shape of the working
UGO305-Aloader, somap_fbs_sectors_to_model_schemanever enters it.plan.md's gating table is updated accordingly.Checks
Repo-wide:
black,ruff,mypyclean (bar the four known Windows-onlysettings.pyerrors); 779 passed, 2 skipped, 1 xfailed.🤖 Generated with Claude Code