diff --git a/changelog.d/ab26-electricity-vat.changed.md b/changelog.d/ab26-electricity-vat.changed.md new file mode 100644 index 0000000000..cc02fa798b --- /dev/null +++ b/changelog.d/ab26-electricity-vat.changed.md @@ -0,0 +1 @@ +Extend the temporary zero rate of VAT on domestic electricity to 30 June 2027, and apply it in Northern Ireland from 1 April 2027, as announced at Budget 2026. diff --git a/policyengine_uk/parameters/gov/hmrc/vat/domestic_electricity_rate/great_britain.yaml b/policyengine_uk/parameters/gov/hmrc/vat/domestic_electricity_rate/great_britain.yaml index 3a066700c4..bb5da8d649 100644 --- a/policyengine_uk/parameters/gov/hmrc/vat/domestic_electricity_rate/great_britain.yaml +++ b/policyengine_uk/parameters/gov/hmrc/vat/domestic_electricity_rate/great_britain.yaml @@ -1,4 +1,4 @@ -description: VAT rate on supplies of domestic electricity in England, Wales and Scotland. It is the reduced rate except while the temporary zero rate applies. +description: VAT rate on supplies of domestic electricity in England, Wales and Scotland. It is the reduced rate except while the temporary zero rate applies, from 1 October 2026 to 30 June 2027. values: 1994-04-01: 0.08 1997-09-01: 0.05 @@ -10,7 +10,18 @@ values: href: https://www.legislation.gov.uk/uksi/2026/987/contents/made - title: HMRC Revenue and Customs Brief 10 (2026) href: https://www.gov.uk/government/publications/revenue-and-customs-brief-10-2026-temporary-zero-rate-of-vat-for-domestic-electricity-in-great-britain/temporary-zero-rate-of-vat-for-domestic-electricity-in-great-britain - 2027-04-01: 0.05 + # SI 2026/987 ends the zero rate on 31 March 2027. Budget 2026 extends it + # by three months, to 1 July 2027; that is policy, not yet law. + 2027-07-01: + value: 0.05 + metadata: + reference: + - title: Budget 2026, paragraph 6.210 (zero rate extended to 1 July 2027) + href: https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=138 + - title: Budget 2026 policy costings, page 12 (from 1 October 2026 until 1 July 2027) + href: https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=12 + - title: Budget 2026, Table 6.1, item 2 + href: https://assets.publishing.service.gov.uk/media/6ae187a2779378370fd80a9a/Table_6.1_and_6.2_Budget_2026_Policy_Decisions.xlsx metadata: unit: /1 period: year @@ -22,5 +33,6 @@ metadata: href: https://www.legislation.gov.uk/uksi/2026/987/contents/made # Liability follows the date the electricity is consumed (Revenue and # Customs Brief 10 (2026)). Day-weighting the fiscal year assumes equal - # daily use: FY 2026-27 has 183 days at 5% and 182 at 0%. + # daily use: FY 2026-27 has 178 days at 5% and 187 at 0%, and FY 2027-28 + # has 86 days at 0% and 280 at 5%. fiscal_year_blend: true diff --git a/policyengine_uk/parameters/gov/hmrc/vat/domestic_electricity_rate/northern_ireland.yaml b/policyengine_uk/parameters/gov/hmrc/vat/domestic_electricity_rate/northern_ireland.yaml index cbb38988ad..3c864f6a29 100644 --- a/policyengine_uk/parameters/gov/hmrc/vat/domestic_electricity_rate/northern_ireland.yaml +++ b/policyengine_uk/parameters/gov/hmrc/vat/domestic_electricity_rate/northern_ireland.yaml @@ -1,7 +1,23 @@ -description: VAT rate on supplies of domestic electricity in Northern Ireland. The temporary zero rate from 1 October 2026 does not apply there. +description: VAT rate on supplies of domestic electricity in Northern Ireland. The temporary zero rate from 1 October 2026 does not apply there; Budget 2026 expects the extended zero rate to apply from 1 April to 30 June 2027. values: 1994-04-01: 0.08 1997-09-01: 0.05 + # Budget 2026 expects the extended relief to apply UK-wide from April 2027. + # That is policy, not yet law, and the document says "expected". + 2027-04-01: + value: 0 + metadata: + reference: + - title: Budget 2026, paragraph 6.210 ("expected to apply UK-wide from April 2027") + href: https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=138 + - title: Budget 2026, section 4.3 ("Extended VAT relief is expected to apply in Northern Ireland from April 2027") + href: https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html + 2027-07-01: + value: 0.05 + metadata: + reference: + - title: Budget 2026 policy costings, page 12 (until 1 July 2027) + href: https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=12 metadata: unit: /1 period: year @@ -11,4 +27,6 @@ metadata: href: https://www.legislation.gov.uk/ukpga/1994/23/schedule/7A - title: HMRC Revenue and Customs Brief 10 (2026) href: https://www.gov.uk/government/publications/revenue-and-customs-brief-10-2026-temporary-zero-rate-of-vat-for-domestic-electricity-in-great-britain/temporary-zero-rate-of-vat-for-domestic-electricity-in-great-britain + # FY 2026-27 has 360 days at 5% and 5 at 0%; FY 2027-28 has 86 at 0% and + # 280 at 5%. fiscal_year_blend: true diff --git a/policyengine_uk/tests/policy/baseline/gov/hmrc/vat/domestic_energy_vat.yaml b/policyengine_uk/tests/policy/baseline/gov/hmrc/vat/domestic_energy_vat.yaml index ed9b9da39f..31fec255b9 100644 --- a/policyengine_uk/tests/policy/baseline/gov/hmrc/vat/domestic_energy_vat.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/hmrc/vat/domestic_energy_vat.yaml @@ -1,7 +1,11 @@ -# Temporary GB zero rate on domestic electricity, 1 October 2026 to -# 31 March 2027 (SI 2026/987). £1,050 of bills carries £50 of VAT at 5%. -# FY 2026-27 has 183 days at 5% and 182 at 0%: 50 * 183 / 365 = 25.07. -- name: GB electricity in FY 2026-27 is zero-rated for 182 of 365 days +# Temporary zero rate on domestic electricity: Great Britain from 1 October +# 2026 (SI 2026/987), extended by Budget 2026 to 1 July 2027 and expected to +# apply in Northern Ireland from 1 April 2027 (paragraph 6.210). £1,050 of +# bills carries £50 of VAT at 5%. +# FY 2026-27: GB 178 days at 5% and 187 at 0%: 50 * 178 / 365 = 24.38; +# NI 360 days at 5% and 5 at 0%: 50 * 360 / 365 = 49.32. +# FY 2027-28: every nation 86 days at 0% and 280 at 5%: 50 * 280 / 366 = 38.25. +- name: GB electricity in FY 2026-27 is zero-rated for 187 of 365 days period: 2026 absolute_error_margin: 0.01 input: @@ -9,9 +13,9 @@ electricity_consumption: 1_050 gas_consumption: 0 output: - domestic_energy_vat: 25.07 + domestic_energy_vat: 24.38 -- name: Northern Ireland electricity stays at 5% +- name: Northern Ireland electricity is zero-rated from 1 April 2027 period: 2026 absolute_error_margin: 0.01 input: @@ -19,7 +23,7 @@ electricity_consumption: 1_050 gas_consumption: 0 output: - domestic_energy_vat: 50 + domestic_energy_vat: 49.32 - name: Gas is not affected by the electricity zero rate period: 2026 @@ -31,9 +35,29 @@ output: domestic_energy_vat: 50 -- name: GB electricity is back at 5% in FY 2027-28 +- name: GB electricity in FY 2027-28 is zero-rated to 30 June 2027 + period: 2027 + absolute_error_margin: 0.01 + input: + region: LONDON + electricity_consumption: 1_050 + gas_consumption: 0 + output: + domestic_energy_vat: 38.25 + +- name: Northern Ireland electricity in FY 2027-28 is zero-rated to 30 June 2027 period: 2027 absolute_error_margin: 0.01 + input: + region: NORTHERN_IRELAND + electricity_consumption: 1_050 + gas_consumption: 0 + output: + domestic_energy_vat: 38.25 + +- name: Electricity is back at 5% in FY 2028-29 + period: 2028 + absolute_error_margin: 0.01 input: region: LONDON electricity_consumption: 1_050 diff --git a/policyengine_uk/tests/test_domestic_electricity_vat.py b/policyengine_uk/tests/test_domestic_electricity_vat.py index bc75f3f469..4177cae13b 100644 --- a/policyengine_uk/tests/test_domestic_electricity_vat.py +++ b/policyengine_uk/tests/test_domestic_electricity_vat.py @@ -2,10 +2,13 @@ Domestic electricity VAT: the temporary GB zero rate (SI 2026/987) and the explicit energy VAT base (#2166). -From 1 October 2026 to 31 March 2027 domestic electricity in England, Wales -and Scotland is zero-rated; Northern Ireland and gas stay at 5%. Model year -2026 runs 6 April 2026 to 5 April 2027, so with equal daily use it has 183 -days at 5% and 182 at 0%. +From 1 October 2026 domestic electricity in England, Wales and Scotland is +zero-rated. Budget 2026 extends the zero rate to 1 July 2027 and expects it to +apply in Northern Ireland from 1 April 2027 (paragraph 6.210). Gas stays at +5%. Model year 2026 runs 6 April 2026 to 5 April 2027, so with equal daily use +Great Britain has 178 days at 5% and 187 at 0%, and Northern Ireland 360 at 5% +and 5 at 0%. Model year 2027 (366 days) has 86 days at 0% and 280 at 5% in +every nation. """ from pathlib import Path @@ -19,7 +22,9 @@ from policyengine_uk.model_api import Scenario from policyengine_uk.system import system -FY2026_SHARE_AT_5_PERCENT = 183 / 365 +FY2026_SHARE_AT_5_PERCENT = 178 / 365 +NI_FY2026_SHARE_AT_5_PERCENT = 360 / 365 +FY2027_SHARE_AT_5_PERCENT = 280 / 366 GB_RATE = "gov.hmrc.vat.domestic_electricity_rate.great_britain" @@ -57,28 +62,39 @@ def calc(variable, year=2026, scenario=None, **kwargs): @pytest.mark.parametrize( - "date, rate", + "date, great_britain, northern_ireland", [ - ("2026-09-30", 0.05), - ("2026-10-01", 0.0), - ("2027-03-31", 0.0), - ("2027-04-01", 0.05), + ("2026-09-30", 0.05, 0.05), + ("2026-10-01", 0.0, 0.05), + ("2027-03-31", 0.0, 0.05), + ("2027-04-01", 0.0, 0.0), + ("2027-06-30", 0.0, 0.0), + ("2027-07-01", 0.05, 0.05), ], ) -def test_gb_rate_changes_on_both_statutory_dates(date, rate): +def test_rates_change_on_each_scheduled_date(date, great_britain, northern_ireland): rates = raw_parameters().gov.hmrc.vat.domestic_electricity_rate - assert rates.great_britain(date) == pytest.approx(rate) - assert rates.northern_ireland(date) == pytest.approx(0.05) + assert rates.great_britain(date) == pytest.approx(great_britain) + assert rates.northern_ireland(date) == pytest.approx(northern_ireland) -def test_fy2026_gb_rate_is_day_weighted(): +def test_model_year_rates_are_day_weighted(): rates = system.parameters.gov.hmrc.vat.domestic_electricity_rate - assert rates.great_britain("2025") == pytest.approx(0.05) + for year in ("2025", "2028"): + assert rates.great_britain(year) == pytest.approx(0.05) + assert rates.northern_ireland(year) == pytest.approx(0.05) assert rates.great_britain("2026") == pytest.approx( 0.05 * FY2026_SHARE_AT_5_PERCENT ) - assert rates.great_britain("2027") == pytest.approx(0.05) - assert rates.northern_ireland("2026") == pytest.approx(0.05) + assert rates.northern_ireland("2026") == pytest.approx( + 0.05 * NI_FY2026_SHARE_AT_5_PERCENT + ) + assert rates.great_britain("2027") == pytest.approx( + 0.05 * FY2027_SHARE_AT_5_PERCENT + ) + assert rates.northern_ireland("2027") == pytest.approx( + 0.05 * FY2027_SHARE_AT_5_PERCENT + ) @pytest.mark.parametrize("region", ["LONDON", "WALES", "SCOTLAND"]) @@ -89,15 +105,24 @@ def test_gb_electricity_vat_in_fy2026(region): ) -def test_northern_ireland_keeps_5_percent(): - assert calc("domestic_energy_vat", region="NORTHERN_IRELAND") == pytest.approx(50) +def test_northern_ireland_is_zero_rated_only_from_april_2027(): + assert calc("domestic_energy_vat", region="NORTHERN_IRELAND") == pytest.approx( + 50 * NI_FY2026_SHARE_AT_5_PERCENT + ) + + +@pytest.mark.parametrize("region", ["LONDON", "SCOTLAND", "NORTHERN_IRELAND"]) +def test_every_nation_is_zero_rated_to_1_july_2027(region): + assert calc("domestic_energy_vat", year=2027, region=region) == pytest.approx( + 50 * FY2027_SHARE_AT_5_PERCENT + ) def test_gas_is_unchanged(): assert calc("domestic_energy_vat", electricity=0, gas=1_050) == pytest.approx(50) -@pytest.mark.parametrize("year", [2025, 2027]) +@pytest.mark.parametrize("year", [2025, 2028]) def test_years_either_side_are_at_5_percent(year): assert calc("domestic_energy_vat", year=year) == pytest.approx(50) @@ -143,27 +168,35 @@ def test_extending_the_zero_rate_to_fy2027(): # Dated reforms are applied on the statutory timeline and day-weighted # into the model year (#2167), so the zero rate must cover all of model # year 2027: 6 April 2027 to 5 April 2028. A calendar-2027 window would - # leave 96 of 366 days at 5%. + # leave 96 of 366 days at 5%. The baseline already zero-rates the first + # 86 days, so the reform removes the other 280: 50 x 280 / 366 = £38.25. reform = Reform.from_dict( {GB_RATE: {"2027-04-06.2028-04-05": 0.0}}, country_id="uk" ) sim = Simulation(situation=household(year=2027), reform=reform) + baseline = 50 * FY2027_SHARE_AT_5_PERCENT assert sim.calculate("domestic_energy_vat", 2027)[0] == 0 - assert sim.calculate("baseline_domestic_energy_vat", 2027)[0] == pytest.approx(50) - assert sim.calculate("vat_change", 2027)[0] == pytest.approx(-50) + assert sim.calculate("baseline_domestic_energy_vat", 2027)[0] == pytest.approx( + baseline + ) + # vat_change is a difference of float32 totals, good to about 1p. + assert sim.calculate("vat_change", 2027)[0] == pytest.approx(-baseline, abs=0.01) def test_zero_rate_for_half_of_fy2027_is_day_weighted(): # A reform dated part-way through a model year (#2167, fixed by #2305) is # day-weighted on the blended electricity rate. Model year 2027 has 366 # days (6 April 2027 to 5 April 2028); a zero rate for the first 183 - # leaves half the year at 5%: 1,000 x 0.05 x 183 / 366 = £25. + # leaves half the year at 5%: 1,000 x 0.05 x 183 / 366 = £25. The + # baseline has 280 days at 5% (£38.25), so the change is £13.25. reform = Reform.from_dict( {GB_RATE: {"2027-04-06.2027-10-05": 0.0}}, country_id="uk" ) sim = Simulation(situation=household(year=2027), reform=reform) assert sim.calculate("domestic_energy_vat", 2027)[0] == pytest.approx(25) - assert sim.calculate("vat_change", 2027)[0] == pytest.approx(-25) + assert sim.calculate("vat_change", 2027)[0] == pytest.approx( + 25 - 50 * FY2027_SHARE_AT_5_PERCENT, abs=0.01 + ) def test_reduced_rate_reform_reaches_gas_not_electricity(): @@ -230,18 +263,19 @@ def test_scalar_zero_gas_rate_leaves_electricity_vat_alone(): @pytest.mark.parametrize( "region, electricity_rate", [ - # GB, model year 2026: 183 of 365 days at 5%, so 0.05 x 183 / 365. + # GB, model year 2026: 178 of 365 days at 5%, so 0.05 x 178 / 365. ("LONDON", 0.05 * FY2026_SHARE_AT_5_PERCENT), ("SCOTLAND", 0.05 * FY2026_SHARE_AT_5_PERCENT), - # Northern Ireland is outside the zero rate: 5% all year. - ("NORTHERN_IRELAND", 0.05), + # Northern Ireland joins the zero rate on 1 April 2027: 360 of 365 + # days at 5%. + ("NORTHERN_IRELAND", 0.05 * NI_FY2026_SHARE_AT_5_PERCENT), ], ) def test_baseline_fy2026_window_by_nation_with_gas(region, electricity_rate): # £1,050 of electricity and £2,100 of gas, each VAT-exclusive at / 1.05: - # electricity: 1,000 x rate (GB 25.07, NI 50) + # electricity: 1,000 x rate (GB 24.38, NI 49.32) # gas: 2,000 x 5% = £100 in every nation - # so GB = 125.07 and NI = 150. + # so GB = 124.38 and NI = 149.32. vat = calc("domestic_energy_vat", region=region, electricity=1_050, gas=2_100) assert vat == pytest.approx(1_000 * electricity_rate + 100, abs=0.01) gas_only = calc("domestic_energy_vat", region=region, electricity=0, gas=2_100) diff --git a/policyengine_uk/tests/test_private_school_vat_receipts.py b/policyengine_uk/tests/test_private_school_vat_receipts.py index c29f5b3d24..cf77d0e8b6 100644 --- a/policyengine_uk/tests/test_private_school_vat_receipts.py +++ b/policyengine_uk/tests/test_private_school_vat_receipts.py @@ -353,10 +353,14 @@ def test_vat_is_never_negative_and_receipts_are_counted_once(households, year, f def electricity_rate(region, year): # SI 2026/987 zero-rates domestic electricity in Great Britain from - # 1 October 2026 to 31 March 2027: 183 of model year 2026's 365 days are - # at 5%. Northern Ireland and every other year stay at 5%. - if region != "NORTHERN_IRELAND" and year == 2026: - return 0.05 * 183 / 365 + # 1 October 2026, and Budget 2026 extends that to 1 July 2027 and to + # Northern Ireland from 1 April 2027. Model year 2026 has 178 of 365 days + # at 5% in Great Britain and 360 in Northern Ireland; model year 2027 has + # 280 of 366 in both. Every other year stays at 5%. + if year == 2026: + return 0.05 * (360 if region == "NORTHERN_IRELAND" else 178) / 365 + if year == 2027: + return 0.05 * 280 / 366 return 0.05 diff --git a/policyengine_uk/variables/gov/hmrc/domestic_energy_vat.py b/policyengine_uk/variables/gov/hmrc/domestic_energy_vat.py index 8050829aba..9fd88bb3a1 100644 --- a/policyengine_uk/variables/gov/hmrc/domestic_energy_vat.py +++ b/policyengine_uk/variables/gov/hmrc/domestic_energy_vat.py @@ -31,7 +31,8 @@ class domestic_energy_vat(Variable): documentation = ( "VAT on the household's electricity and gas bills. Electricity is " "charged at its own rate, which is zero in Great Britain from 1 October " - "2026 to 31 March 2027; gas is charged at the reduced rate." + "2026 and in Northern Ireland from 1 April 2027, to 30 June 2027; gas " + "is charged at the reduced rate." ) entity = Household definition_period = YEAR