Evaluate claims_all_entitled_benefits per benefit unit - #1831
Draft
MaxGhenis wants to merge 2 commits into
Draft
Conversation
The formula summed its seven reported-benefit columns across the whole simulation (.sum() < 1), so in microdata the flag was False for every benefit unit whenever any benefit unit reported any of them, and would_claim_council_tax_reduction collapsed to FRS reporters only. Housing benefit, income support and the tax credits are unaffected: their own already-claiming eligibility gates carry the reporters-only behaviour independently of this flag. Refs PolicyEngine/policyengine-uk-data#448. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…path Review findings on the previous commit: the docstrings, test module docstring and changelog fragment said "reports any" where the formula tests the combined reported amount < £1, and the test named for single-benefit-unit semantics actually built two benefit units. Both now match the code: documentation states the threshold, and a genuine one-benefit-unit situation covers the calculator path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft — held for a decision on the interim Council Tax Reduction take-up assumption (see "Decision to make").
What was wrong
claims_all_entitled_benefitsended its formula withadd(benunit, period, [seven *_reported columns]).sum() < 1— a sum over the whole array, collapsing an entity-level boolean into one simulation-wide scalar. Onenhanced_frs_2024_25.h5v1.56.14 at 2025 the flag was False for all 61,223 benefit units although 51,855 report under £1 in total across the seven benefits, sowould_claim_council_tax_reduction(= flag OR reported CTR > 0) reduced to "reported CTR > 0" for every benefit unit, and simulated Council Tax Reduction reached FRS reporters only. Surfaced by the audit behind PolicyEngine/policyengine-uk-data#448.This PR evaluates the test per benefit unit: a family reporting under £1 in total across the seven means-tested benefits is assumed to claim what it is entitled to; a family reporting £1 or more is assumed to have reported completely. Single-benefit-unit situations — the calculator path — are unchanged, since the two forms coincide there.
Why per benefit unit is the intended reading
entity = BenUnit, "whether this family would claim any benefit they are entitled to"), and tests set it per family.tools/takeup.py(2022–2024, deleted in d380c0e8) derived take-up parameters from exactly that reporters-only baseline against aset_input(…, True)counterfactual.housing_benefit_eligible,income_support_eligible,is_WTC_eligibleandis_CTC_eligibleeach require the benefit's own reported amount to be positive (all four gates introduced in 13511284, 2022-03-23; those four benefits' random take-up branches were removed in 22bd7c8b, 2024-09-11). Measured on the licensed artefacts, the flag's value is immaterial to every one of those benefits' paid amounts (table below).would_claim_council_tax_reduction(#1769, June 2026) copied the housing benefit pattern, but the CTR chain has no reporter gate and CTR is open to new claims — so the collapsed flag silently restricted an active scheme to FRS reporters.Measured consequences
Three behaviours were measured on the licensed artefacts (aggregates only; incumbent calibrated weights unchanged): the old formula, the per-benefit-unit test (this PR — verified field-for-field identical to running the new formula directly), and all-True (the historical "maximum claimants" counterfactual, as an upper bound).
Unchanged to the measured precision (£0.1m; identical unweighted recipient counts) in every measured cell (2024–2026 on v1.56.14; 2025 on v1.56.16): housing benefit, income support, working tax credit, child tax credit, income-based JSA, income-related ESA, universal credit, pension credit and child benefit. Of these, only housing benefit, income support, WTC and CTC consume the flag, and each is additionally gated by its own reported amount; the other five never read it (income-based JSA and income-related ESA have their own reporter-gated formulas, and UC, pension credit and child benefit use dataset take-up inputs).
Council Tax Reduction is the only paid amount that moves (2025, v1.56.14 → per benefit unit):
The household-net-income change equals the CTR change to the stored precision in every v1.56.14 cell; on v1.56.16 at 2025 the two differ by one stored £0.1m unit (£1.6227bn vs £1.6228bn). v1.56.16 at 2025 is materially identical (UK CTR £2.29bn → £3.91bn). 2024: £2.21bn → £3.80bn; 2026: £2.33bn → £4.12bn.
Against official figures: Scotland's modelled CTR moves from £0.25bn (−36% against the ≈£0.389bn 2024-25 outturn, Scottish local government finance statistics 2024-25) to £0.70bn (+80%) — full take-up among entitled benefit units reporting none of the seven overshoots, as expected with no take-up rate applied. Wales moves from £0.01bn to £0.15bn against a 2024-25 scheme cost of £322.9m (Welsh CTR annual report); PolicyEngine/policyengine-uk-data#448 documents the imputed-savings gate and zero-liability records as the leading remaining Welsh gaps. No England or UK scheme-cost comparator was pinned.
Decision to make
The end state for CTR take-up is a dataset-provided
would_claim_council_tax_reductioncolumn anchored to official caseloads, the same way the data builds generatewould_claim_uc,would_claim_pcandwould_claim_child_benefit— policyengine-core prefers dataset inputs over formulas, so that follow-up needs no further model change. Until it exists, the interim choices are:Follow-ups (out of scope)
tax_creditsintermediate is gated only bywould_claim_WTC/would_claim_CTC, not by eligibility, so in 2024-and-earlier periods non-reporting families with children accrue a phantom intermediate (£0.53bn → £2.71bn at 2024) that dampens — never reverses — their new CTR awards through the means test. No paid tax-credit amount changes. From the labelled 2025 the scheme is inactive and the intermediate is zero.council_tax_less_benefit) moves from £47.60bn to £45.94bn at 2025 on incumbent weights; recalibration happens in the data pipeline, not here.Tests
policyengine_uk/tests/test_claims_all_entitled_benefits.py: on the old formula the per-benefit-unit cases fail (e.g.[False, False] == [False, True]); the single-benefit-unit semantics cases pass unchanged before and after. A microsimulation-marked case asserts the flag equals the per-benefit-unit test record-for-record and takes both values in microdata.References: PolicyEngine/policyengine-uk-data#448.
🤖 Generated with Claude Code