Give the benchmark SUT panel an extractor, and fit theta on non-nested spans (#700, #699) - #713
Give the benchmark SUT panel an extractor, and fit theta on non-nested spans (#700, #699)#713WesIngwersen wants to merge 3 commits into
Conversation
f739ae9 to
497220c
Compare
BEA publishes 2007, 2012 and 2017 detail Supply and Use SUT as one zip of per-table workbooks with a sheet per year, all three already on the 2017 code basis in one frame. It was a local drop that only the Step 3 drift diagnostic read, through an ad-hoc zip reader. io_2017 now carries `_load_benchmark_detail_supply_use_usa(matrix, year)`, GCS-backed like every other table, with `load_benchmark_detail_U_intermediate_usa` and `load_benchmark_detail_supply_usa` as the typed 402 x 402 accessors. The panel is a second and third observation of every structural question in the build -- Step 3's input mix, Step 4a's commodity mix, the margin rates, the FD splits -- not just this one. The panel's 2017 sheets are the single-year workbooks cell for cell, on both matrices: 0 differing cells on 413 x 424 and 405 x 415. `assert_benchmark_panel_matches_2017()` is the check. The two loaders are kept separate anyway, because `_load_2017_detail_supply_use_usa` is what `bea_parse` emits as the BEA_Detail_Use_SUT / BEA_Detail_Supply FBAs and those stay pinned to their published workbook; the FBAs are not extended to 2007 and 2012 here. BEA's subsidy sign convention holds on all three years, so `_assert_bea_subsidy_signs` runs on every year the panel loader returns. `--holdout` reproduces unchanged, including the 2012->2017 best theta of 1.00. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…699) S2's experiment, and the answer is not the one the plan expected. Every theta on the plan's table starts at 2017, so elapsed years, cumulative inflation, price dispersion and structural drift all move with the calendar and none can be told from the others. The summary Use SUT publishes 1997-2024 and the price index reaches 2012, so 78 non-nested spans are free -- different bases, different lengths, different inflation. On those (`--regime`): crosses the 2021-22 surge R2 0.613 cumulative price level R2 0.525 elapsed years R2 0.142 relative-price dispersion R2 0.014 So the dispersion candidate the plan named is dead -- 1.4% of the variance, and the coefficient points the wrong way -- and so is elapsed time. Holding span length fixed, spans that cross the surge fit theta 0.0-0.5 and spans that do not fit 0.7-0.9, at every length from one to nine years. `default_theta` ships that: 0.75 off the surge, 0.0 across it (fitted 0.755 and 0.141). Rounding up to zero rather than to the target spans' own -0.25/-0.50 is deliberate -- a negative theta says nominal shares move against their own price, and it buys 0.6%. The median gain of the best theta over a frozen A is 5.44% of the score off the surge and 0.59% across it, so in the regime this build targets the carry is worth well under one percent however theta is set. What #497's theta = 1 cost was the 12.6% it gave away by pointing the wrong way. The margin-rate leg is built too, so the deflator is the purchaser one. The non-obvious part is reaching 402 rows annually: detail Supply is published only for benchmark years, so the rate's level is detail-observed at 2017 and only its movement is borrowed from the summary parent. S0a made that testable -- against the observed 2012 detail factor, weighted by 2017 intermediate dollars, the shipped rule is 0.756pp off, the parent's factor taken down unchanged is 1.010pp, and no factor at all is 1.818pp. A year with no published Supply table is refused rather than carried: MARGIN_YEARS (1997-2024, BEA's vintage) is a separate constraint from INTERMEDIATE_YEARS (gross output). They agree at 2024 today, so nothing is blocked; a 2025 build would reach a year with one and not the other, and a silent factor of 1.0 there would read as "margins did not move". The margin leg is inert in exactly the years the build targets -- at theta = 0 every factor is raised to the zero power. It moves 0.21% of the 2019 block and 0.54% of the 2021 block and 0.000% of the 2024 one. Kept because it is the correct deflator for a purchaser-valued cell, not because it changes the current answer. Also restates the plan's Step 3 sections that PR #712 left describing `vapro_seed`: the level table (the block total is theta-independent, so it is a check on the control), the column control table, and the GSLG/T31005 paragraphs. 2017 reproduction is unchanged -- $6.02M max absolute, 1.05% max relative, seven negatives, and the section still scores 100% on 44,281 cells. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`intermediate_estimation_plan.md` covers the theta findings but never states the mechanics, and the name invites reading it as a price ratio or a valuation bridge. It is neither: it is a scalar exponent, one per span, applied identically to all 402 commodity rows and all 402 industry columns. `About_the_price_carry.md` is the reference for that: the carry formula, the two legs of the commodity deflator and their sources, the BAS -> PRO -> PUR chain the margin leg sits in (and why its denominator is producer and not basic value), the theta = 1 - sigma CES reading, what is commodity-specific and what is not, the shipped values, and the approximations the carry rests on. Linked from the nowcasting README, from the plan's Inflation section where a reader first meets theta, and from the module docstring. The README's intermediate_structure_drift entry also gains the --regime flag added in 7761934. Every claim in it re-checked against the code: grid -1.0 to 1.5 in 0.25 steps, theta 0.75 for 2018-2021 and 0.0 for 2022-2024, MARGIN_YEARS 1997-2024 against INTERMEDIATE_YEARS 2017-2024, the four unpriced commodities, and mu of -0.944 for `42` and -0.989 for `486`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
497220c to
d245381
Compare
|
Consolidated into #742, which collapsed the #713 → #714 → #715 → #717 → #718 stack into one PR and merged into Verified superseded, not just replaced: every module this stack owns is byte-identical on Not re-targeting to #743 is the live Step 3 PR. Branch kept rather than deleted. |
Stacked on #712 (
step3_underlying_ii_va). Two items offintermediate_estimation_plan.md§What to build: S0a (#700) and S2 (#699).S0a — the benchmark detail SUT panel gets an extractor (#700)
BEA publishes 2007, 2012 and 2017 detail Supply and Use SUT as one zip of
per-table workbooks with a sheet per year, all three already on the 2017 code
basis in one frame. It was a local drop that only the Step 3 drift diagnostic
read, through an ad-hoc zip reader.
io_2017now carries_load_benchmark_detail_supply_use_usa(matrix, year),GCS-backed like every other table, with
load_benchmark_detail_U_intermediate_usaand
load_benchmark_detail_supply_usaas the typed 402 × 402 accessors.both matrices — 0 differing cells on 413 × 424 and 405 × 415.
assert_benchmark_panel_matches_2017()is the check._load_2017_detail_supply_use_usais what
bea_parseemits as theBEA_Detail_Use_SUT/BEA_Detail_SupplyFBAs, and those stay pinned to their published workbook. The FBAs are not
extended to 2007 and 2012 — the year is hardcoded on
bea_parse's detailbranches and the yaml declares
years: [2017]._assert_bea_subsidy_signsruns on every year the panel loader returns.SUPPLY-USE_2026-08-24.ziphas been uploaded toextract/input-data/USA_AllTablesSUP/and the download verifiedbyte-identical (sha256
ea81c120…).--holdoutreproduces unchanged, 2012→2017 best θ still 1.00.S2 — fit θ, add the margin-rate factor (#699)
The experiment the plan asked for, and the answer is not the one it expected.
Every θ on the plan's table starts at 2017, so elapsed years, cumulative
inflation, price dispersion and accumulated structural drift all move together
with the calendar and none can be told from the others. The summary Use SUT
publishes 1997-2024 and the price index reaches 2012, so 78 non-nested spans
are free — different bases, different lengths, different inflation. New
--regimeflag:variance, coefficient the wrong sign.
coefficient to 0.002 and its R² not at all.
the surge fit θ 0.0-0.5 and spans that do not fit 0.7-0.9, at every length
from one to nine years.
What ships (
default_theta): 0.75 off the surge, 0.0 across it — fitted0.755 and 0.141. Rounding up to zero rather than to the target spans' own
−0.25/−0.50 is deliberate: a negative θ says nominal shares move against their
own price, which is a curve-fit rather than a mechanism, and it buys 0.6%.
best θ over a frozen
Ais 5.44% of the score off the surge and 0.59%across it — and every year this build targets from 2022 on crosses it. What
#497's θ = 1 cost was not a missed 0.6%, it was the 12.6% it gave away by
pointing the wrong way.
DEFAULT_THETAis gone;THETA_497keeps the name forwhat #497 specified so the two stay scorable against each other.
The margin leg, built at detail
The deflator is now the purchaser one, price × margin rate. The non-obvious part
is reaching 402 rows annually: BEA publishes detail Supply only for benchmark
years, so the rate's level is detail-observed at 2017 and only its
movement is borrowed from the summary parent.
✅ S0a made that rule testable. Against the observed 2012 detail factor,
weighted by 2017 intermediate dollars:
MARGIN_YEARS(1997-2024, BEA's vintage) is a separate constraint fromINTERMEDIATE_YEARS(gross output). They agree at 2024, so nothing is blockedtoday; a 2025 build (#707) would reach a year with one and not the other, and a
silent factor of 1.0 would read as "margins did not move".
every factor is raised to the zero power. It moves 0.21% of the 2019 block,
0.54% of the 2021 block and 0.000% of the 2024 one. Kept because it is the
correct deflator for a purchaser-valued cell, not because it changes the current
answer.
_load_usa_summary_sutpicks theworkbook by year, which would take a ratio's numerator and denominator off
different vintages — a median 0.50pp on 2020's rates and 1.20pp on 2022's. They
agree exactly on 2017, so reading the current vintage throughout costs
nothing at the base and removes the seam at the target.
Also: plan-doc sections #712 left stale
PR #712 replaced
vapro_seedwith an observed control but did not restate thesections describing it. Fixed here, since they now contradict the code:
block total is θ-independent to 12 decimal places, because every column is
renormalised before the control is applied, so that table is a check on the
control and never evidence about the carry;
GSLG−18.3% were thesuperseded seed; it is now 0.00007% economy-wide;
GSLGandT31005paragraphs — the level problem is fixed, Step 3: can government spending by function explain the G* commodity mix? #578 (thecommodity mix) is untouched, and
T31005supplies only a column total, whichis now had for free.
Checks
black,ruff,mypyclean repo-wide (bar the 4 known Windows-onlysettings.pyresourceerrors CI does not see).pytest: 795 passed, 0failed. 2017 reproduction unchanged — $6.02M max absolute, 1.05% max relative,
seven negatives — and
use_intermediate_detail_sutstill scores 100% on 44,281populated cells.
Reproduce with
intermediate_structure_drift --regime --holdout --theta --seed --control.🤖 Generated with Claude Code