Skip to content

Reported Council Tax Reduction is never uprated, so it covers less of the bill each projected year #2674

Closed

Description

@juaristi22

What happens

council_tax_benefit_reported has no uprating, and the dataset projection in policyengine_uk/data/economic_assumptions.py does not grow it. A family whose Council Tax Reduction scheme the model does not simulate falls back to this reported amount (council_tax_benefit, council_tax_reduction_scheme_supported). These are mostly working-age claims in the English councils the model does not model.

Their reduction therefore stays at its data-year cash value, while uprate_council_tax grows their bill every year. The other benefits the model falls back to a reported amount for, such as housing_benefit_reported, pension_credit_reported and universal_credit_reported, all carry an uprating.

Size

Measured on Microcosm UK 2024-25 (staged build uk-frs-calibration-attempt-20261025T091414Z-a6299504) with policyengine-uk 2.151.0. All figures are for households whose reduction is reported only, not simulated: about 2,800 records, 1.62m households in 2024-25 and 1.70m in 2031-32.

2024-25 2031-32
Mean reported reduction (cash) £492.50 £492.07
Mean council tax bill (cash) £1,250 £1,804
Mean council tax net of the reduction (cash) £757 £1,312
Total reported reduction £0.80bn £0.84bn
Total if each reduction kept its 2024-25 share of the bill £0.80bn £1.21bn

By 2031-32 the reductions fall about £0.37bn a year short of their 2024-25 share of the bill (£0.15bn in 2027-28). The effect on the income distribution is small: about £9 a person (equivalised, 2027-28 prices) in the bottom BHC decile, 0.05% of its income.

The code is the same in 2.132.6 and 2.158.2: the variable has no uprating, and nothing outside the tests and the two CTR variables refers to it.

Suggested fix

Grow a reported reduction with its household's bill. In uprate_council_tax, multiply the person-level council_tax_benefit_reported by its household's factor, so the reduction keeps its share of the bill. Council Tax Reduction schemes work out the award from the council tax liability (a maximum share of the bill, then reduced for income), so an award moves with the bill. Uprating by CPI, as for other benefits, would still leave the reduction behind bills that the OBR forecasts to grow 5.5–6.2% a year in England.

A test could pin the share: a household whose reported reduction is half of its bill in the data year still has half in each projected year.

Reproduce

On any dataset with reported reductions:

from policyengine_uk import Microsimulation

sim = Microsimulation()
for year in (2024, 2027, 2031):
    rep = sim.calculate("council_tax_benefit_reported", year, map_to="household")
    bill = sim.calculate("council_tax", year)
    print(year, round(rep[rep > 0].mean()), round(bill[rep > 0].mean()))

The mean reduction stays at its data-year value while the mean bill grows.

Found while breaking down the bottom decile in the Living standards projections of PolicyEngine/uk-autumn-budget-dashboard-2026. Related: #1669 (closed), which added the simulated schemes this fallback sits beside.

Activity

  1. vahid-ahmadi commented on Oct 25, 2026

    @vahid-ahmadi
    Collaborator

    Checked at main 335bb01e32. The claim holds.

    • council_tax_benefit_reported is a person-level input with no uprating (variables/gov/dwp/council_tax_benefit_reported.py:4-10), and it is not in data/uprating_indices.yaml. So neither the YAML loop (economic_assumptions.py:342-360) nor _unmapped_uprating_indices (:142-153) grows it. It is not in DATASET_UPRATING_EXCLUSIONS, COUNTRY_UPRATED_INPUTS or YEAR_SPECIFIC_INPUTS (:94, :130, :139), so this is a gap, not a choice.
    • uprate_council_tax (economic_assumptions.py:523-560) only rewrites household["council_tax"], by the country's OBR receipts growth net of household weight growth.
    • The fallback is council_tax_benefit.py:80-87: a claimant whose scheme is not simulated (council_tax_reduction_scheme_supported) gets reported. It is capped at its share of the liability only next to a simulated claim in the same household.
    • housing_benefit_reported (uprating_indices.yaml:58), pension_credit_reported (:70) and universal_credit_reported (:81) are all uprated, as the issue says.

    Duplicates: none that I found. #1669 (closed) and PRs #1668 and #1831 touch the same variables but not projection. The CTR scheme issues (#1934, #1935, #1962, #2090) are about simulated schemes.

    Effect on published results: council_tax_benefit feeds household_benefits, household_net_income, hbai_household_net_income and gov_spending. So baseline net income, poverty and spending in projected years are slightly too low for these households, and the gap grows each year. Reform deltas move only where a reform changes the bill or CTR. I did not rerun your figures. They are internally consistent: £0.80bn × (£1,804 / £1,250) × (1.70m / 1.62m) ≈ £1.21bn in 2031-32, against £0.84bn modelled. One point supports your fix: the OBR series this code uses is receipts net of CTR (see tests/test_council_tax_uprating.py:44-63). Holding CTR's share of the bill fixed matches that basis. Growing the bill while CTR stays flat does not.

    Suggested fix, as you propose:

    1. In uprate_council_tax, map each person to their household's factors via person_household_id (as economic_assumptions.py:677-680 already does for region) and set person["council_tax_benefit_reported"] = previous_year.person["council_tax_benefit_reported"] * person_factor when the column is present.
    2. Add council_tax_benefit_reported next to council_tax in reset_growthfactor_uprating (economic_assumptions.py:827). Otherwise a reset will not restore its base value before re-uprating.
    3. Northern Ireland gets factor 1.0, so its reported reduction stays flat along with its (zero) council tax. If FRS reports anything for NI households here, it may be rate relief, which would belong with domestic_rates. Worth checking whether any NI records have a non-zero value before choosing.

    Test: in tests/test_council_tax_uprating.py, extend _uprated_council_tax with a person table (two people in one household, plus a second household in another country). Assert that council_tax_benefit_reported / council_tax stays the same after one and several projected years in England, Wales, Scotland and UNKNOWN, and that NI stays flat. Also assert that reset_growthfactor_uprating restores the base value. An end-to-end case with an unsupported English working-age claimant would show that council_tax_benefit keeps half of its bill.

    What I ran: code reading at main only. No tests and no population run.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions