Repository navigation
Isolate declared energy projections and validate index history - #2591
Conversation
Aggregate impact on certified data: passBase Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 0 (thresholds in Notes
Moves flagged for reviewNone. Spending by benefit and service
Caseloads
Household net income by decileNo household's net income changes in any year. No change in any year: receipts by tax head; government balance, each component counted once; model totals; household income totals; population; poverty rates; people in poverty; inequality; mean household net income in each side's own deciles; standard reform costings (change in gov_balance); standard reforms: change in each reform's target. Checks failing on both base and head (1)
Counted-once checkEach of 84 components was raised by £1 per unit in 2026-27, and every head of its totals was read household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A head that breaks a rule is measured again twice: with every other head held at its baseline value, and with every other head held at its value after the first £1 while the component rises again. It fails where either still shows the response. 0 failed; 0 were skipped. Provenance
Dataset: Receipts by tax head: head levels
Spending by benefit and service: head levels
Caseloads: head levels
Government balance, each component counted once: head levels
Model totals: head levels
Household income totals: head levels
Population: head levels
Poverty rates: head levels
People in poverty: head levels
Inequality: head levels
Mean household net income in each side's own deciles: head levels
Standard reform costings (change in gov_balance): head levels
Standard reforms: change in each reform's target: head levels
|
vahid-ahmadi
left a comment
There was a problem hiding this comment.
@juaristi22 thanks, this closes the two shoulds from my #2571 review cleanly. Review at head 673b67f3, round 1. No must or should findings, so I'm approving; three nits below.
Our #2571 review, status at this head
- should, index choice (headline CPI vs Ofgem cap, CY2024 vs FY2024-25): partly resolved, enough for this PR. You took option (b): the README (
economic_assumptions/README.md:117-137) anddataset-sources.md:84-101now call generic annual OBR CPI an interim proxy, say the shared start-year convention is an approximation, and point to #2526 for an energy-specific index. The numbers I asked for are not there; see nit 1. - should, the declared group sharing
DATASET_UPRATING_EXCLUSIONS: resolved.DECLARED_ENERGY_INPUTS(economic_assumptions.py:108-115) now drives bothuprate_energy(:390) and the reset group (:734,:742), withDATASET_UPRATING_EXCLUSIONSkept as a separate name. #2573 ended up putting liquid and solid fuel on the CPI mapping inuprating_indices.yamlrather than in the exclusions, andgit merge-treeof this head with #2573's head (112056f1) is clean, so the two can merge in either order. - nit, declared year before the index starts: resolved. With the real index a
fiscal_year 1990or2008declaration now raises ("first supports 2009-01-01"), where it used to give 1,000 to 1,610.6 in 2025;fiscal_year 2009still projects. - nit, base year never repriced: open. I couldn't find a line in
dataset-sources.mdsaying the declared year should match the data year, or that the base year keeps the declared prices. Still a nit. - nit, PR body and changelog: partly. The changelog now says what changed. The body still ends
axiom: needed.
What I checked
- The eight test files in your selection in a fresh env at the head: 141 passed.
- The 20 new cases against the base
economic_assumptions.pywith the head's tests: 10 failed, 10 passed, as the body says. The 10 failures are the widened-exclusions cases (projection and both reset variants), the four pre-support cases, the two unusable-history cases and the reformed-index case. - CI at the head is green, including Test / Result and Aggregate impact.
- Real index: CY2024 or FY2024-25 basis to 2026 gives a ratio of 1.0578, and to 2040 1.368.
- Index history against ONS MM23 (release 21 October 2026): the index rebuilds from
yoy_growth.obr.consumer_price_index, soI[Y+1]/I[Y]is calendar-year average CPI growth. For 2022 to 2025 the rates (9.07%, 7.3%, 2.5%, 3.4%) match ONS D7G7. These are the years any current declaration uses. See nit 2 for earlier years and 2026. - Public code search across PolicyEngine still finds no producer writing
energy_price_basis, so this stays inert for current datasets.
New findings
-
nit: say how big the approximation is.
dataset-sources.md:84-90andREADME.md:124-127say the shared start-year convention approximates calendar/fiscal alignment but give no size, and the sign depends on the index. On headline CPI the ONS D7BT average for FY2024-25 (134.78) is 0.7% above CY2024 (133.86), so mapping a FY2024-25 basis toI[2024]projects it about 0.7% too high. On the Ofgem cap it goes the other way: CY2024 is about 2.8% above FY2024-25 (my #2571 figures), so an energy index under the same convention would project a FY2024-25 basis about 2.8% too low. One sentence with these numbers would let a caller judge the proxy. The wording "January 1 index level" could also mislead, sinceI[Y]is the calendar-year average level dated 1 January rather than a January reading; "calendar-year average level" would be clearer. -
nit (not from this PR): the CPI history the new check accepts is not all calendar-year CPI.
yoy_growth.yaml:206-218says each value is growth over a calendar year, but 2010 to 2021 do not match ONS D7G7 calendar-year rates: for example 2014 1.1% (ONS 1.5%), 2016 1.1% (0.7%), 2021 4.0% (2.6%). They match ONS financial-year average growth instead (from D7BT monthly: 2014 1.05%, 2016 1.10%, 2021 3.97%), so 2010 to 2021 are FY rates and 2022 onward are CY rates. The cumulative effect from 2009 to 2024 is small (model 1.558, ONS 1.546, about 0.7%), and no plausible energy declaration starts that early. Separately, 2026 is the forecast 2.3%, while ONS January to September 2026 runs 3.0% above the same months of 2025, so a 2024 basis is projected to 2026 about 0.7pp low for now. Neither is for this PR; worth a line in the #2526 follow-up or a separate issue when the CPI series is next refreshed. -
nit:
axiom: needed. Same as last round; the body should give the axiom line a decision.
#2526
I'd keep #2526 open but narrow it. This PR and #2571 together deliver its consumer side: reading the declared price year, keeping unlabelled and legacy files flat, and the tests. What remains is the energy-specific index (Ofgem cap for outturn quarters, then a sourced assumption) and a Microcosm release that actually writes the declaration. I'd narrow #2526 to the index work once this merges, with the producer side linked from Microcosm. Refs #2526, not Fixes, is right.
🤖 Generated with Claude Code
|
Merged by the UK hub (Claude session 8e19f9d5) at head
|
Refs #2526
Keep explicit energy price declarations limited to domestic energy, electricity and gas when generic uprating exclusions change. Declared projections now reject basis or target dates before the selected index has usable history, including an index that starts partway through a year. Unlabelled spending retains its existing flat projection.
The documentation names generic annual OBR CPI as an interim proxy and explains the shared January 1 convention for calendar and fiscal price years. Energy-specific index work and producer/caller adoption remain open in #2526. This follows the review of #2571 and leaves the active fuel work in #2573 unchanged.
Reproducer: policyengine_uk/tests/test_energy_dataset_projection.py::test_declared_energy_projection_ignores_widened_generic_exclusions; policyengine_uk/tests/test_energy_dataset_projection.py::test_energy_projection_rejects_pre_support_basis_and_target
Validation: 141 tests passed across the eight affected energy, reset, metadata, disabled-assumption, dataset-routing and uprating test files; the strict outcome checker passed for that selection with required-data mode enabled. The new regression batch first produced 10 assertion failures and 10 passing controls against the original code; those 20 cases are included in the 141.
make formatpassed. Independent code and source reviews found no open findings.Test selection (the recorded run also enabled outcome and collection logging):
Full model CI and private-data runs were not executed locally; current-head Linux CI remains required. The documentation build was not run because these are guidance-only content changes. This does not retrofit metadata-free private releases or establish energy-specific forecasting, deployed adoption or encoded parity.
axiom: needed