Repository navigation
Model the temporary 0% VAT on GB domestic electricity - #2189
vahid-ahmadi wants to merge 6 commits into
Conversation
Review of #2189 — Model the temporary 0% VAT on GB domestic electricityBase repository: PolicyEngine/policyengine-uk Source Documents
CriticalC1 — Keep the energy price VAT basis independent of gas-rate reforms (STILL OPEN)CRITICAL — confirmed formula defect. Location: policyengine_uk/variables/gov/hmrc/domestic_energy_vat.py:50 at the reviewed head; the helper divides both fixed energy inputs by this value at lines 21–22, and the baseline calculation repeats it at lines 73–75. A supported scalar This diff newly makes actual electricity/gas VAT depend on the mutable The underlying Scenario baseline-cloning issue is already tracked as #2188 and may provide the common repair. Its separate cancellation of Should AddressA1 — Retain VAT on energy components excluded from the new direct base (STILL OPEN)Severity: SHOULD ADDRESS (nonblocking coverage improvement). Captured location: policyengine_uk/variables/household/consumption/reduced_rate_vat_consumption.py:16 (also the new share parameter, lines 1 and 40–44). Trigger and observed behavior: With the PR's documented default dataset contract, Expected treatment: HMRC treats a supplier's standing charge as part of the electricity or gas supply; qualifying domestic fuel oil, kerosene, coal and other solid fuel also remain taxable at the reduced rate. Electricity's zero rate extends to the qualifying electricity supply, while gas and the other fuels keep their existing treatment. Removing double counting should retain a representation of components absent from the direct inputs. VAT Notice 701/19, sections 2.2, 6, 7 and 10.10, VATA Schedule 7A, Group 1, HMRC Brief 10/2026. Impact: For illustration, a continuously connected GB household at the documented Q2 2026 average electricity standing charge of 57.21p/day has £208.82 of gross standing charges over 365 days. At the fixed 5% input-price basis, those charges contain approximately £9.94 annual VAT. At that same price, the 182-day zero-rate portion of fiscal year 2026 removes approximately £4.96, which unit-only inputs omit. These are source-derived illustrations holding the Q2 price constant; they are not claims about the actual October tariff, the private dataset, or a population total. Ofgem Q2 2026 unit rates and standing charges, including 5% VAT. Why introduced by this diff: Energy-input coverage was already limited, but generic reduced-rate consumption previously represented domestic fuel and power as part of a broad spending share. This change removes the whole category without a corresponding full-bill/other-fuel replacement. The PR discloses the limitation; it remains a coverage improvement rather than evidence that its aggregate factor is wrong. Retain or add the omitted components, or make the default inputs complete bills, while ensuring the two VAT bases do not overlap. The OBR describes its 2.5% reduced-rate share as approximate and also includes children's car seats and other goods; it does not establish a zero non-energy residual. OBR VAT explanation. SuggestionsNone. Evidence Gaps
Notes
Validation SummaryReused exact-head validation (not rerun in this batch): tests: 60 passed, 1 warning in 24.39s; exit 0; exact snapshot import confirmed; test log: pr-2189-code-tests.log; diagnostics: ['pr-2189-code-diagnostic.py: exit 0, 15.57s; scalar/dated Scenario and Reform contrasts through VAT, household_tax, household_net_income', 'pr-2189-code-array-diagnostic.py: exit 0, 8.48s; nation vectors, 2025–2027 parity, both composition orders through final household_net_income', 'pr-2189-code-scalar-fresh.py: exit 0, 4.25s; isolated fresh process confirms fixed electricity VAT-base error']; diagnostic logs: ['pr-2189-code-diagnostic.log', 'pr-2189-code-array-diagnostic.log', 'pr-2189-code-scalar-fresh.log'] Reused exact-head validation (not rerun in this batch): Read SI 2026/987, HMRC Brief 10/2026, VAT Notice 701/19 and VATA Schedule 7A, Ofgem Q2 2026, ONS ADFX/ABQI/CDDL, official OBR proxy originals and 3 checksum-validated cached HMRC originals. Source validator exit 0: pr-2189-review-source-cache-check.json. Ratios: pr-2189-policy-share-comparison.json. Arithmetic: pr-2189-policy-arithmetic.json. Manifest: pr-2189-review-sources.json. Code reproduction delegated to uk_code and not duplicated. CI at 69957d0: No checks reported at capture. Detailed code, policy, source and reproduction artifacts were retained locally. Timingelapsed seconds: 1151.70s; setup seconds: 270.89s Review SeverityREQUEST_CHANGES. Open findings: 1 critical, 1 should address, 0 suggestions. |
Addresses juaristi22's review of #2189. C1: domestic_energy_vat divided the electricity and gas inputs by the baseline-tree reduced rate. Scenario(parameter_changes=...) clones that tree after applying the reform (#2188), so a 20% gas rate treated 5%-priced bills as if they included 20% (£218.75 instead of £250 on £1,050 + £1,050). The divisor is now a fixed price-basis parameter, gov.simulation.vat.energy_input_price_basis_rate = 0.05 (Ofgem Q2 2026 unit rates include 5% VAT), in both domestic_energy_vat and baseline_domestic_energy_vat. Scenario and Reform.from_dict now agree. Tests: her £250 case through both routes, a scalar zero gas rate leaving electricity VAT at £50, and the FY2026 GB window/NI/gas cases with gas. A1 (standing charges, other fuels) is not changed here: ONS electricity plus gas alone is 2.71% of spending in 2025 (2.74% in 2024), above the 2.5% reduced-rate share, so a narrower subtraction is a no-op; complete bills belong in the input data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, María. Both points are addressed in 6df47b1. C1: energy price basis (fixed)
A1: standing charges and other fuels (not changed here) The narrower fix would subtract only electricity and gas from the generic reduced-rate share, so oil and solid fuel stay in it. I checked this against ONS:
Electricity and gas alone are above the OBR's 2.5% reduced-rate share, so the generic base would still be zero and the change would do nothing in current model years. Standing charges can't go into the generic base either. Electricity standing charges must also be zero-rated during the window, and the generic base is taxed at the reduced rate and grossed up by coverage. The right home is the input data: complete-bill energy inputs, standing charges included, in policyengine-uk-data/Microcosm. Raising Tests
🤖 Generated with Claude Code |
eac21df to
691267f
Compare
8866719 to
43a7eec
Compare
Addresses juaristi22's review of #2189. C1: domestic_energy_vat divided the electricity and gas inputs by the baseline-tree reduced rate. Scenario(parameter_changes=...) clones that tree after applying the reform (#2188), so a 20% gas rate treated 5%-priced bills as if they included 20% (£218.75 instead of £250 on £1,050 + £1,050). The divisor is now a fixed price-basis parameter, gov.simulation.vat.energy_input_price_basis_rate = 0.05 (Ofgem Q2 2026 unit rates include 5% VAT), in both domestic_energy_vat and baseline_domestic_energy_vat. Scenario and Reform.from_dict now agree. Tests: her £250 case through both routes, a scalar zero gas rate leaving electricity VAT at £50, and the FY2026 GB window/NI/gas cases with gas. A1 (standing charges, other fuels) is not changed here: ONS electricity plus gas alone is 2.71% of spending in 2025 (2.74% in 2024), above the 2.5% reduced-rate share, so a narrower subtraction is a no-op; complete bills belong in the input data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Rebased onto the new #2187 head (
Tests: ruff clean; VAT pytest 30 passed; One thing for when this is retargeted to main: main's new Fix evidence check treats this as a fix PR ( 🤖 Generated with Claude Code |
SI 2026/987 zero-rates domestic electricity in England, Wales and Scotland from 1 October 2026 to 31 March 2027; Northern Ireland and gas stay at 5%. - Add domestic_energy_vat: VAT on the household's own electricity and gas bills, VAT-exclusive base = bill / 1.05, not grossed up by microdata_vat_coverage. Electricity uses the new nation-split gov.hmrc.vat.domestic_electricity_rate (fiscal_year_blend: FY 2026-27 has 183 days at 5% and 182 at 0%); gas uses the reduced rate. - Take the ONS COICOP 04.5 share of household spending (gov.hmrc.vat.domestic_fuel_and_power_share) out of the generic reduced-rate share, so energy is not counted twice. - baseline_domestic_energy_vat day-weights the dated baseline tree, so a simulation with no reform shows no vat_change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Energy-bill VAT sits outside both grossing factors from #2187, since the bills are calibrated to NEED and households bear that VAT in full. Re-derived the survey coverage against receipts net of energy VAT on the certified Microcosm UK 2024-25 release: 79.2 / (0.7 x (171.0 - 2.0)) = 0.670, which rounds to the existing 0.67. Records the derivation in the parameter and in docs/engineering/vat-coverage.md, and loosens a float32 difference check to 1p. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Addresses juaristi22's review of #2189. C1: domestic_energy_vat divided the electricity and gas inputs by the baseline-tree reduced rate. Scenario(parameter_changes=...) clones that tree after applying the reform (#2188), so a 20% gas rate treated 5%-priced bills as if they included 20% (£218.75 instead of £250 on £1,050 + £1,050). The divisor is now a fixed price-basis parameter, gov.simulation.vat.energy_input_price_basis_rate = 0.05 (Ofgem Q2 2026 unit rates include 5% VAT), in both domestic_energy_vat and baseline_domestic_energy_vat. Scenario and Reform.from_dict now agree. Tests: her £250 case through both routes, a scalar zero gas rate leaving electricity VAT at £50, and the FY2026 GB window/NI/gas cases with gas. A1 (standing charges, other fuels) is not changed here: ONS electricity plus gas alone is 2.71% of spending in 2025 (2.74% in 2024), above the 2.5% reduced-rate share, so a narrower subtraction is a no-op; complete bills belong in the input data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Microcosm prices electricity_consumption and gas_consumption at DESNZ QEP average domestic prices paid (tables 2.2.4 and 2.3.4, all payment methods, 2024-25, including VAT), not Ofgem cap unit rates. The 5% price-basis rate is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…weights reforms Main (3edfb4b, fixing #2167 and #2188) applies dated reforms on the statutory timeline. A calendar-2027 zero rate now leaves 1 January to 5 April 2028 at 5%, so the test dates the reform 6 April 2027 to 5 April 2028. The Scenario route also keeps the baseline tree now, so the price basis test asserts the £100 baseline on both routes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43a7eec to
ebddf75
Compare
The NEED energy rake bands households by income. The donor bands on LCFS gross income (p344p), NEED's concept, but the recipient read a household_gross_income column no spine stage writes and fell back to its HBAI net income, so recipients sat in too low a band and the rake gave richer households the lower bands' mean kWh. That skews electricity and gas by income, the distribution the GB domestic-electricity zero rate reads (PolicyEngine/policyengine-uk#2189). The stage now materializes the engine's household_gross_income with its four income predictors, for the band alone, as nts_bus_travel does; the fallback is gone. The end-to-end test reads the materialize step by kind, not by position. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The NEED energy rake bands households by income. The donor bands on LCFS gross income (p344p), NEED's concept, but the recipient read a household_gross_income column no spine stage writes and fell back to its HBAI net income, so recipients sat in too low a band and the rake gave richer households the lower bands' mean kWh. That skews electricity and gas by income, the distribution the GB domestic-electricity zero rate reads (PolicyEngine/policyengine-uk#2189). The stage now materializes the engine's household_gross_income with its four income predictors, for the band alone, as nts_bus_travel does; the fallback is gone. The end-to-end test reads the materialize step by kind, not by position. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #2166.
Stacked on #2187 (base branch
rederive-vat-coverage, which splits the VAT grossing factor for #1996). Review and merge #2187 first; GitHub will then retarget this PR tomain.What was wrong
From 1 October 2026 to 31 March 2027, domestic electricity in England, Wales and Scotland is zero-rated for VAT (SI 2026/987; HMRC Brief 10/2026). Northern Ireland and gas stay at 5%.
The model couldn't represent this. Domestic fuel and power sat only inside a flat 2.5% share of total consumption (
reduced_rate_share), taxed at one undated reduced rate and grossed up to receipts.electricity_consumptionhad no effect onvat, and there was no electricity-specific rate, nation split or date handling.Fix
domestic_energy_vat(household). It is VAT on the household's own electricity and gas bills:gov.hmrc.vat.domestic_electricity_rate.{great_britain, northern_ireland};gov.hmrc.vat.reduced_rate.vat= (full-rate VAT + VAT on the remaining reduced-rate base) / (survey coverage × household share of receipts) +domestic_energy_vat.baseline_vatdoes the same withbaseline_domestic_energy_vat. The two factors come from Split VAT grossing into household share and survey coverage #2187.fiscal_year_blend: true. Model year 2026 (6 April 2026 to 5 April 2027) has 183 days at 5% and 182 at 0%, so the GB rate for 2026 is 2.507%. Equal daily use is an assumption: HMRC bases liability on when electricity is consumed, and winter use is higher.electricity_consumptionandgas_consumptionare NEED kWh priced at DESNZ Quarterly Energy Prices average prices paid (2024-25, all payment methods), which include 5% VAT. The VAT-exclusive base is the bill / 1.05 (5/105 of the bill is VAT), and it is held fixed when the rate changes.reduced_rate_vat_consumption) is nowconsumption × max(reduced_rate_share − domestic_fuel_and_power_share, 0). The newgov.hmrc.vat.domestic_fuel_and_power_shareholds ONS COICOP 04.5 / household final consumption by year from 2000.reduced_rateno longer reaches electricity. Its description now says so. A reform to electricity VAT should changedomestic_electricity_rate.baseline_domestic_energy_vatday-weights the electricity rates itself (fiscal_year_average). The.baselineparameter tree keeps its dated values, so without this a simulation with no reform showed a nonzerovat_changein 2026 and 2027.Reconciliation numbers
How much of the 2.5% is domestic fuel and power: all of it, to within rounding.
Aggregate check against HMRC.
Coverage re-derived without energy VAT. With energy split out, coverage = pre-scaling non-energy VAT / (0.7 × (receipts − energy-bill VAT)). On the certified Microcosm UK 2024-25 release (
f9d1922c) for 2024-25: 79.2 / (0.7 × (171.0 − 2.0)) = 0.670. That rounds to the same 0.67 as #2187's derivation, so the value is unchanged; its derivation record anddocs/engineering/vat-coverage.mdnow describe the energy-excluded calculation.Total
vatagainst OBR receipts (same release):Tests
tests/test_domestic_electricity_vat.py(19 cases):vatresponding toelectricity_consumption;vat_changewithout a reform;vat_change−£50 on £1,050 of bills);reduced_ratereform reaching gas but not electricity.tests/policy/baseline/gov/hmrc/vat/domestic_energy_vat.yaml: five household cases covering GB, NI, gas, FY 2027-28 and the coverage treatment.tests/policyandtests/microsimulation: 3,233 passed, 8 skipped, 2 xfailed, 0 failed (one float32 tolerance fixed after the first run). The microsimulation tests were not run locally.reforms_config.yamlexpected values that include VAT may move with the baseline change.ruff formatandruff checkare clean, and the Towncrier draft renders under "Fixed".Coordination
microdata_vat_coverage: the value has been 0.383 since 2010 and overshoots OBR VAT receipts on current datasets #1996: this PR is stacked on Split VAT grossing into household share and survey coverage #2187. Energy-bill VAT is outside both grossing factors, and the coverage was re-derived against receipts net of energy VAT (unchanged at 0.67). The deprecatedmicrodata_vat_coverage, if reformed, replaces the two factors for non-energy VAT only.fiscal_year_blendparameters (fuel duty), so they score the wrong amount #2167 / Re-average fuel duty and other blended rates after mid-year reforms #2185 (mid-year reforms on blended parameters):domestic_electricity_rate, as with fuel duty. Re-average fuel duty and other blended rates after mid-year reforms #2185 fixes that for all blended parameters; once both land, a direct electricity test should be added there.uk-autumn-budget-dashboard-2026:vat − electricity × 5/105) must be removed when the dashboard moves to a policyengine-uk version with this change. Otherwise the relief applies twice.domestic_electricity_rate.great_britaindirectly.datasets/imputations/vat.py) readsreduced_rate_share. This PR leaves that parameter's values unchanged, so data builds are unaffected.Found while testing, not fixed here: with
Scenario(parameter_changes=...), the.baselineparameter tree is cloned after the reform is applied, sobaseline_vat(andbaseline_domestic_energy_vat) include the reform. Filed as #2188, since fixed onmainby #2305.Reproducer
test_vat_responds_to_electricityis the reproduction in #2166: onmain,vatdoes not respond toelectricity_consumption.Reproducer: policyengine_uk/tests/test_domestic_electricity_vat.py::test_vat_responds_to_electricity
🤖 Generated with Claude Code