Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/2154.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Correct the forecast basis for protected pension-age Housing Benefit personal allowances.
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
"""Project the protected pension-age Housing Benefit allowance.

The protected single and lone-parent allowance consists of the Pension Credit
standard minimum guarantee plus the retained Savings Credit uplift. The two
components use different annual review inputs, so neither CPI nor earnings
alone is a faithful forecast proxy.
"""

from policyengine_core.parameters import Parameter, ParameterNode


BASE_YEAR = 2026
GUARANTEE_COMPONENT = 238.0
SAVINGS_CREDIT_COMPONENT = 18.0
BASE_ALLOWANCE = GUARANTEE_COMPONENT + SAVINGS_CREDIT_COMPONENT


def project_components(
guarantee: float,
savings_credit_uplift: float,
earnings_growth: float,
cpi_growth: float,
) -> tuple[float, float]:
"""Project both components without reducing either cash amount."""
return (
guarantee * (1 + max(earnings_growth, 0)),
savings_credit_uplift * (1 + max(cpi_growth, 0)),
)


def add_protected_pension_age_uprating(
parameters: ParameterNode,
) -> ParameterNode:
"""Add the component-weighted forecast index used after April 2026."""
inputs = parameters.gov.economic_assumptions.statutory_uprating_inputs
allowances = parameters.gov.dwp.housing_benefit.allowances
last_input_year = min(
max(
int(value.instant_str[:4])
for value in input_parameter.values_list
if value.value is not None
)
for input_parameter in (
inputs.awe_total_pay_may_july,
inputs.cpi_september,
)
)

guarantee = GUARANTEE_COMPONENT
savings_credit_uplift = SAVINGS_CREDIT_COMPONENT
values = {f"{BASE_YEAR}-04-01": 1.0}
for year in range(BASE_YEAR + 1, last_input_year + 2):
observation_year = year - 1
guarantee, savings_credit_uplift = project_components(
guarantee,
savings_credit_uplift,
float(inputs.awe_total_pay_may_july(f"{observation_year}-07-01")),
float(inputs.cpi_september(f"{observation_year}-09-01")),
)
values[f"{year}-04-01"] = (guarantee + savings_credit_uplift) / BASE_ALLOWANCE

allowances.add_child(
"protected_pension_age_uprating",
Parameter(
"gov.dwp.housing_benefit.allowances.protected_pension_age_uprating",
data={
"description": (
"Forecast index for the protected pension-age Housing "
"Benefit allowance. The 2026-27 rounded base allocates "
"£238 to the Pension Credit guarantee and £18 to the "
"retained Savings Credit uplift. The components follow "
"non-negative May-to-July earnings and September CPI, "
"respectively. Projected values are not enacted rates."
),
"values": values,
"metadata": {
"unit": "/1",
"label": (
"Protected pension-age Housing Benefit allowance forecast index"
),
"reference": [
{
"title": (
"A14/2025 Housing Benefit uprating for the "
"financial year ending March 2027, paragraphs "
"5 and 20"
),
"href": (
"https://www.gov.uk/government/publications/"
"housing-benefit-adjudication-circulars-2025/"
"a142025-housing-benefit-uprating-for-the-"
"financial-year-ending-march-2027"
),
},
{
"title": (
"ONS KAC3 average weekly earnings, whole "
"economy, total pay"
),
"href": (
"https://www.ons.gov.uk/"
"employmentandlabourmarket/peopleinwork/"
"earningsandworkinghours/timeseries/kac3/lms"
),
},
{
"title": "ONS D7G7 Consumer Prices Index annual rate",
"href": (
"https://www.ons.gov.uk/economy/"
"inflationandpriceindices/timeseries/d7g7/mm23"
),
},
],
},
},
),
)
return parameters
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
description: Personal allowance for Housing Benefit for a lone parent over State Pension age.
description: >-
Personal allowance for Housing Benefit for a lone parent over State Pension
age. Amounts after the last enacted rate use a component-weighted forecast
and are not enacted future rates.

values:
2015-04-01: 181
Expand All @@ -13,9 +16,11 @@ metadata:
period: week
unit: currency-GBP
label: Housing benefit lone parent aged personal allowance
uprating: gov.benefit_uprating_cpi
uprating: gov.dwp.housing_benefit.allowances.protected_pension_age_uprating
reference:
- title: The Housing Benefit Regulations 2006 Schedule 3 sec. 1
href: https://www.legislation.gov.uk/uksi/2006/213/data.pdf#page=212
- title: Benefit and pension rates 2024 to 2025 - Policy paper
href: https://www.gov.uk/government/publications/benefit-and-pension-rates-2024-to-2025/benefit-and-pension-rates-2024-to-2025
- title: A14/2025 Housing Benefit uprating for the financial year ending March 2027, paragraphs 5 and 20
href: https://www.gov.uk/government/publications/housing-benefit-adjudication-circulars-2025/a142025-housing-benefit-uprating-for-the-financial-year-ending-march-2027
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
description: The following personal allowance amount is provided to single filers over the pension age under the Housing Benefit.
description: >-
The following personal allowance amount is provided to single filers over
the pension age under the Housing Benefit. Amounts after the last enacted
rate use a component-weighted forecast and are not enacted future rates.
values:
2015-04-01: 181
2021-04-01: 191.15
Expand All @@ -12,9 +15,11 @@ metadata:
period: week
unit: currency-GBP
label: Housing benefit single aged personal allowance
uprating: gov.benefit_uprating_cpi
uprating: gov.dwp.housing_benefit.allowances.protected_pension_age_uprating
reference:
- title: The Housing Benefit Regulations 2006 Schedule 3 sec. 1
href: https://www.legislation.gov.uk/uksi/2006/213/data.pdf#page=212
- title: Benefit and pension rates 2024 to 2025 - Policy paper
href: https://www.gov.uk/government/publications/benefit-and-pension-rates-2024-to-2025/benefit-and-pension-rates-2024-to-2025
- title: A14/2025 Housing Benefit uprating for the financial year ending March 2027, paragraphs 5 and 20
href: https://www.gov.uk/government/publications/housing-benefit-adjudication-circulars-2025/a142025-housing-benefit-uprating-for-the-financial-year-ending-march-2027
4 changes: 4 additions & 0 deletions policyengine_uk/tax_benefit_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
from policyengine_uk.parameters.gov.dwp.state_pension.triple_lock.create_triple_lock import (
add_triple_lock,
)
from policyengine_uk.parameters.gov.dwp.housing_benefit.allowances.create_protected_pension_age_uprating import (
add_protected_pension_age_uprating,
)
from policyengine_uk.parameters.gov.economic_assumptions.create_economic_assumption_indices import (
create_economic_assumption_indices,
)
Expand Down Expand Up @@ -101,6 +104,7 @@ def process_parameters(self) -> None:
self.parameters = add_lagged_earnings(self.parameters)
self.parameters = add_lagged_cpi(self.parameters)
self.parameters = add_statutory_uprating_inputs(self.parameters)
self.parameters = add_protected_pension_age_uprating(self.parameters)
self.parameters = add_triple_lock(self.parameters)
self.parameters = create_economic_assumption_indices(self.parameters)
self.parameters = add_lsr_deprecation_aliases(self.parameters)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import pytest

from policyengine_uk import system
from policyengine_uk.parameters.gov.dwp.housing_benefit.allowances.create_protected_pension_age_uprating import (
BASE_ALLOWANCE,
GUARANTEE_COMPONENT,
SAVINGS_CREDIT_COMPONENT,
project_components,
)


def _parameters():
return system.parameters


def test_protected_allowance_index_combines_the_two_statutory_inputs():
parameters = _parameters()
inputs = parameters.gov.economic_assumptions.statutory_uprating_inputs
index = parameters.gov.dwp.housing_benefit.allowances.protected_pension_age_uprating

guarantee, savings_credit_uplift = project_components(
GUARANTEE_COMPONENT,
SAVINGS_CREDIT_COMPONENT,
inputs.awe_total_pay_may_july("2026-07-01"),
inputs.cpi_september("2026-09-01"),
)

assert inputs.awe_total_pay_may_july("2026-07-01") == pytest.approx(0.039)
assert inputs.cpi_september("2026-09-01") == pytest.approx(0.02116)
assert index("2026-04-01") == 1
expected_index = (guarantee + savings_credit_uplift) / BASE_ALLOWANCE
assert expected_index == pytest.approx(1.037745625)
assert index("2027-04-01") == pytest.approx(expected_index)


def test_single_and_lone_parent_use_the_composite_projection():
allowances = _parameters().gov.dwp.housing_benefit.allowances
index = allowances.protected_pension_age_uprating
expected_2027 = 256 * index("2027-04-01") / index("2026-04-01")

assert allowances.single.aged("2026-04-01") == 256
assert allowances.lone_parent.aged("2026-04-01") == 256
assert expected_2027 == pytest.approx(265.66288)
assert allowances.single.aged("2027-04-01") == pytest.approx(expected_2027)
assert allowances.lone_parent.aged("2027-04-01") == pytest.approx(expected_2027)
assert allowances.single.aged("2027-04-01") != pytest.approx(
256
* _parameters().gov.benefit_uprating_cpi("2027-04-01")
/ _parameters().gov.benefit_uprating_cpi("2026-04-01")
)


def test_component_projection_does_not_reduce_cash_amounts():
assert project_components(238, 18, -0.01, -0.02) == (238, 18)
Loading