From 8db4ea9d7e91d7e7a511b83021d1294a9485bb11 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 09:57:48 +0000 Subject: [PATCH 1/4] Start cost-of-living payments in 2022 and pay each benefit unit and person MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Give the three cost-of-living amounts a zero before 2022, so backdating no longer pays them in 2015 to 2021 (#2847). Pay the means-tested amount to each benefit unit with a benefit listed in section 1(3) of the Social Security (Additional Payments) Acts 2022 and 2023, which leave out Housing Benefit, or with Child Tax Credit or Working Tax Credit and none of those benefits (section 1(2)), at least £26 of a credit for the year in 2022-23 (2022 Act section 2(2)). Pay the £150 disability amount to each person with a listed disability benefit (section 5). The household total adds both to the pensioner payment (#2848). Claude-Session: https://claude.ai/code/session_01WR8LHckHwu75WHHEdzLyNc Co-Authored-By: Claude Opus 5.5 --- changelog.d/2847.fixed.md | 1 + .../gov/treasury/cost-of-living-payments.md | 66 +++- .../disabled/amount.yaml | 7 +- .../disabled/qualifying_benefits.yaml | 7 +- .../means_tested_households/amount.yaml | 7 +- .../minimum_tax_credit_award.yaml | 13 + .../qualifying_benefits.yaml | 10 +- .../qualifying_tax_credits.yaml | 15 + .../pensioners/amount.yaml | 3 +- policyengine_uk/programs.yaml | 14 +- .../cost_of_living_support_payment.yaml | 349 +++++++++++++++++ .../test_cost_of_living_payment_properties.py | 354 ++++++++++++++++++ .../cost_of_living_disability_payment.py | 24 ++ .../cost_of_living_means_tested_payment.py | 41 ++ .../cost_of_living_support_payment.py | 44 ++- 15 files changed, 907 insertions(+), 48 deletions(-) create mode 100644 changelog.d/2847.fixed.md create mode 100644 policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/minimum_tax_credit_award.yaml create mode 100644 policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_tax_credits.yaml create mode 100644 policyengine_uk/tests/test_cost_of_living_payment_properties.py create mode 100644 policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_disability_payment.py create mode 100644 policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_means_tested_payment.py diff --git a/changelog.d/2847.fixed.md b/changelog.d/2847.fixed.md new file mode 100644 index 0000000000..9e2fbca812 --- /dev/null +++ b/changelog.d/2847.fixed.md @@ -0,0 +1 @@ +The Cost of Living Payments now read zero before 2022, so the model no longer pays them in 2015-16 to 2021-22. As under the Social Security (Additional Payments) Acts 2022 and 2023, the model pays the means-tested payment to each benefit unit on Universal Credit, Pension Credit, income-based JSA, income-related ESA or Income Support, or on tax credits alone (at least £26 a year in 2022-23), and not on Housing Benefit alone, and pays the £150 disability payment to each person on a qualifying disability benefit. diff --git a/docs/book/programs/gov/treasury/cost-of-living-payments.md b/docs/book/programs/gov/treasury/cost-of-living-payments.md index 6b20bafc34..a0b8b2c624 100644 --- a/docs/book/programs/gov/treasury/cost-of-living-payments.md +++ b/docs/book/programs/gov/treasury/cost-of-living-payments.md @@ -111,32 +111,60 @@ so a household whose survey record has no band qualifies. ## Cost-of-Living Payments (2022-23 and 2023-24) -Two successive packages, both modelled through the variable -`cost_of_living_support_payment` at `gov/treasury/cost_of_living_support/`. -The variable returns the **sum** of three independent strands depending -on which qualifying benefits the household receives: +The model pays two successive packages through the household variable +`cost_of_living_support_payment`, with parameters at +`gov/treasury/cost_of_living_support/`. The variable returns the **sum** of +three strands: the means-tested payment to each benefit unit, the disability +payment to each person and the pensioner payment to the household. | Strand | 2022-23 | 2023-24 | Qualifying benefits | |--------|---------|---------|---------------------| -| Means-tested CoL Payment | £650 (two instalments) | £900 (three instalments) | Universal Credit, Pension Credit, Housing Benefit, income-based JSA / ESA, Income Support | +| Means-tested CoL Payment | £650 (two instalments) | £900 (three instalments) | Universal Credit, Pension Credit, income-based JSA, income-related ESA or Income Support; or Child Tax Credit or Working Tax Credit and none of those (an award of at least £26 for the year in 2022-23) | | Pensioner CoL Payment | £300 | £300 | Winter Fuel Payment recipients | -| Disability CoL Payment | £150 | £150 | DLA, PIP, Attendance Allowance, AFCS, IIDB, SDA, child / war disability pension | +| Disability CoL Payment | £150 | £150 | DLA, PIP, Attendance Allowance or Armed Forces Independence Payment | -From 2024-01-01 the parameter values are explicitly reset to zero so the -one-off doesn't extrapolate forward. +From 2024-01-01 the amounts read zero, so the one-off payments don't +extrapolate forward. The amounts also read zero before 2022, so the model's +backdating of each parameter's earliest value to 2015 doesn't pay them in +2015-16 to 2021-22. ### How PolicyEngine computes the payment -For each strand `s ∈ {means_tested_households, pensioners, disabled}`: - -``` -on_s = (sum of household's reported amounts in s.qualifying_benefits) > 0 -strand_s = s.amount(period) * on_s -``` - -Total `cost_of_living_support_payment = means_test_bonus + pensioner_bonus + disabled_bonus`, -i.e. the strands stack — a pensioner on Pension Credit who also receives PIP -will collect all three payments. This matches the actual policy. +Under the Social Security (Additional Payments) Acts 2022 and 2023, the +Secretary of State and HMRC pay the means-tested payment to each "person", +meaning an individual or a couple (section 1(6) of the 2022 Act, section 1(9) +of the 2023 Act), and the Secretary of State pays the disability payment to +each individual (section 5(1)). Three variables follow them: + +- `cost_of_living_means_tested_payment` (benefit unit) pays + `means_tested_households.amount` to a benefit unit with any of + `means_tested_households.qualifying_benefits` (section 1(1) and (3)), or + with none of them and a yearly award of either credit in + `means_tested_households.qualifying_tax_credits` that reaches + `means_tested_households.minimum_tax_credit_award` (section 1(2)). + Parliament set that minimum at £26 for 2022-23 (section 2(2) of the 2022 + Act) and set none for 2023-24 (section 3(1) of the 2023 Act). A unit with + both a benefit and a tax credit gets one payment. +- `cost_of_living_disability_payment` (person) pays `disabled.amount` to a + person with any of `disabled.qualifying_benefits`. +- `cost_of_living_support_payment` (household) adds both over the + household's benefit units and members, and adds `pensioners.amount` once + if the household has any of `pensioners.qualifying_benefits` (the Winter + Fuel Payment). + +So a household with a pensioner couple on Pension Credit and an adult son on +Universal Credit gets two means-tested payments, and a couple both on PIP +gets two disability payments. The strands stack: a pensioner on Pension +Credit and Attendance Allowance with a Winter Fuel Payment collects all +three. + +The model holds yearly amounts, so it tests receipt of each benefit and tax +credit over the year rather than in the month ending with each qualifying +day, and compares each tax credit's yearly award with the £26 minimum. It +has no variables for the other disability benefits that section 5(2) lists +(constant attendance allowance, Adult Disability Payment, Child Disability +Payment and the war pension mobility supplement), so it pays no disability +payment to someone who gets only those. ## References @@ -145,3 +173,5 @@ will collect all three payments. This matches the actual policy. - HMT, [Energy Bills Support Scheme](https://www.gov.uk/government/publications/the-energy-bills-support-scheme-explainer) and [Council Tax Energy Rebate](https://www.gov.uk/government/publications/the-council-tax-rebate-2022-23-billing-authority-guidance). - DWP, [HBAI quality and methodology information report, FYE 2023](https://www.gov.uk/government/statistics/households-below-average-income-for-financial-years-ending-1995-to-2023/households-below-average-income-series-quality-and-methodology-information-report-fye-2023) (treatment of the cost-of-living support schemes in HBAI income). - House of Commons Library briefing [CBP-9501 — Cost of Living Payments and the energy crisis](https://commonslibrary.parliament.uk/research-briefings/cbp-9501/). +- [Social Security (Additional Payments) Act 2022](https://www.legislation.gov.uk/ukpga/2022/38), sections 1 to 5 (the 2022-23 means-tested and disability payments). +- [Social Security (Additional Payments) Act 2023](https://www.legislation.gov.uk/ukpga/2023/7), sections 1 to 5 (the 2023-24 means-tested and disability payments). diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/amount.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/amount.yaml index 5adb49963b..80ba1ee90a 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/amount.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/amount.yaml @@ -1,5 +1,6 @@ -description: One-off Disability Cost-of-Living Payment to households containing someone on a qualifying disability benefit. £150 in both 2022-23 and 2023-24, withdrawn from 2024-25. +description: Disability Cost of Living Payment to each person on a qualifying disability benefit. Parliament set £150 in section 5(1) of both the Social Security (Additional Payments) Act 2022 and the Social Security (Additional Payments) Act 2023. The model pays it in 2022-23 and 2023-24, and the amount reads zero before 2022 and from 2024. values: + 0001-01-01: 0 2022-01-01: 150 2023-01-01: 150 2024-01-01: 0 @@ -8,6 +9,10 @@ metadata: period: year label: Disability Cost-of-Living Payment reference: + - title: Social Security (Additional Payments) Act 2022, section 5(1) + href: https://www.legislation.gov.uk/ukpga/2022/38/section/5 + - title: Social Security (Additional Payments) Act 2023, section 5(1) + href: https://www.legislation.gov.uk/ukpga/2023/7/section/5 - title: 2022-23 Cost-of-Living Support package announcement (HMT/DWP, May 2022) href: https://www.gov.uk/government/news/millions-of-most-vulnerable-households-will-receive-1200-of-help-with-cost-of-living - title: Disability Cost-of-Living Payment 2023-24 (DWP guidance) diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml index 704193efd4..af8c629749 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml @@ -1,10 +1,13 @@ -description: Benefits which confer eligibility to the household payment to disability - benefits. +description: Disability benefits that qualify a person for the Disability Cost of Living Payment. The list follows section 5(2) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023. The model has no variables for the other benefits that section lists (constant attendance allowance, Adult Disability Payment, Child Disability Payment and the war pension mobility supplement), so it pays nobody who gets only those. metadata: economy: false label: Qualifying benefits for support for disabled households propagate_metadata_to_children: true reference: + - href: https://www.legislation.gov.uk/ukpga/2022/38/section/5 + title: Social Security (Additional Payments) Act 2022, section 5(2) + - href: https://www.legislation.gov.uk/ukpga/2023/7/section/5 + title: Social Security (Additional Payments) Act 2023, section 5(2) - href: https://www.gov.uk/government/news/millions-of-most-vulnerable-households-will-receive-1200-of-help-with-cost-of-living title: Cost-of-living support announcement | GOV.UK unit: variable diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/amount.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/amount.yaml index dc48eee302..9bb01b2a12 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/amount.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/amount.yaml @@ -1,5 +1,6 @@ -description: One-off Cost-of-Living Payment to households on qualifying means-tested benefits. £650 across 2022-23 (Spring £326 + Autumn £324) and £900 across 2023-24 (Spring £301 + Autumn £300 + Spring 2024 £299). +description: Yearly total of the means-tested Cost of Living Payments to each benefit unit on a qualifying benefit or tax credit. Parliament set £326 and £324 in the Social Security (Additional Payments) Act 2022, £650 in all, and £301, £300 and £299 in the Social Security (Additional Payments) Act 2023, £900 in all. The model pays the 2022 Act's amounts in 2022-23 and the 2023 Act's in 2023-24, and the amount reads zero before 2022 and from 2024. values: + 0001-01-01: 0 2022-01-01: 650 2023-01-01: 900 2024-01-01: 0 @@ -8,6 +9,10 @@ metadata: period: year label: Cost-of-Living Payment (means-tested) reference: + - title: Social Security (Additional Payments) Act 2022, section 1(1) and (2) + href: https://www.legislation.gov.uk/ukpga/2022/38/section/1 + - title: Social Security (Additional Payments) Act 2023, section 1(1) and (2) + href: https://www.legislation.gov.uk/ukpga/2023/7/section/1 - title: 2022-23 Cost-of-Living Support package announcement (HMT/DWP, May 2022) href: https://www.gov.uk/government/news/millions-of-most-vulnerable-households-will-receive-1200-of-help-with-cost-of-living - title: 2023-24 Cost-of-Living Payments (Autumn Statement 2022, DWP guidance) diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/minimum_tax_credit_award.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/minimum_tax_credit_award.yaml new file mode 100644 index 0000000000..1c8ae1b3e4 --- /dev/null +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/minimum_tax_credit_award.yaml @@ -0,0 +1,13 @@ +description: Smallest yearly award of a qualifying tax credit that qualifies a benefit unit for the means-tested Cost of Living Payment through the tax credit route. Under section 2(2) of the Social Security (Additional Payments) Act 2022, HMRC pays in 2022-23 only where the payment, award or expected award of the credit in question for the tax year comes to at least £26. Parliament set no such minimum in section 3(1) of the Social Security (Additional Payments) Act 2023. The model holds yearly amounts, so the formula compares each credit's yearly award with this amount. +values: + 2022-01-01: 26 + 2023-01-01: 0 +metadata: + unit: currency-GBP + period: year + label: Minimum tax credit award for the means-tested Cost-of-Living Payment + reference: + - title: Social Security (Additional Payments) Act 2022, section 2(2) + href: https://www.legislation.gov.uk/ukpga/2022/38/section/2 + - title: Social Security (Additional Payments) Act 2023, section 3(1) + href: https://www.legislation.gov.uk/ukpga/2023/7/section/3 diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_benefits.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_benefits.yaml index d2835a7723..d58558f229 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_benefits.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_benefits.yaml @@ -1,10 +1,13 @@ -description: Benefits which confer eligibility to the household payment to means-tested - benefits. +description: Means-tested benefits that qualify a benefit unit for the means-tested Cost of Living Payment. The list follows section 1(3) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023, which name Universal Credit, Pension Credit, income-based Jobseeker's Allowance, income-related Employment and Support Allowance and Income Support. Neither Act lists Housing Benefit. metadata: economy: false label: Qualifying benefits for support for means-tested households propagate_metadata_to_children: true reference: + - href: https://www.legislation.gov.uk/ukpga/2022/38/section/1 + title: Social Security (Additional Payments) Act 2022, section 1(3) + - href: https://www.legislation.gov.uk/ukpga/2023/7/section/1 + title: Social Security (Additional Payments) Act 2023, section 1(3) - href: https://www.gov.uk/government/news/millions-of-most-vulnerable-households-will-receive-1200-of-help-with-cost-of-living title: Cost-of-living support announcement | GOV.UK unit: variable @@ -12,7 +15,6 @@ values: 2022-01-01: - universal_credit - pension_credit - - housing_benefit - jsa_income - - income_support - esa_income + - income_support diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_tax_credits.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_tax_credits.yaml new file mode 100644 index 0000000000..1911f80829 --- /dev/null +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_tax_credits.yaml @@ -0,0 +1,15 @@ +description: Tax credits that qualify a benefit unit for the means-tested Cost of Living Payment when it gets none of the qualifying benefits. Under section 1(2) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023, HMRC pays a person with a qualifying entitlement to Child Tax Credit or Working Tax Credit but not to a qualifying benefit. +metadata: + economy: false + label: Qualifying tax credits for support for means-tested households + propagate_metadata_to_children: true + reference: + - href: https://www.legislation.gov.uk/ukpga/2022/38/section/1 + title: Social Security (Additional Payments) Act 2022, section 1(2) + - href: https://www.legislation.gov.uk/ukpga/2023/7/section/1 + title: Social Security (Additional Payments) Act 2023, section 1(2) + unit: variable +values: + 2022-01-01: + - child_tax_credit + - working_tax_credit diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml index 228e251b7e..90d80d18d9 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml @@ -1,5 +1,6 @@ -description: One-off Pensioner Cost-of-Living Payment paid as a top-up to the Winter Fuel Payment to households containing someone of State Pension age. £300 in both winter 2022-23 and winter 2023-24, withdrawn from winter 2024-25. +description: One-off Pensioner Cost-of-Living Payment, a £300 top-up to the Winter Fuel Payment for households with someone of State Pension age in winter 2022-23 and winter 2023-24. The amount reads zero before 2022 and from 2024. values: + 0001-01-01: 0 2022-01-01: 300 2023-01-01: 300 2024-01-01: 0 diff --git a/policyengine_uk/programs.yaml b/policyengine_uk/programs.yaml index ba571b4c2e..8d57e857f0 100644 --- a/policyengine_uk/programs.yaml +++ b/policyengine_uk/programs.yaml @@ -596,10 +596,22 @@ programs: agency: Treasury status: complete coverage: UK + variable: cost_of_living_support_payment parameter_prefix: gov.treasury.cost_of_living_support verified_start_year: 2022 verified_end_year: 2023 - notes: Temporary program, ended 2023 + notes: >- + Temporary program, ended 2023. The model pays the means-tested payment + to each benefit unit on Universal Credit, Pension Credit, income-based + JSA, income-related ESA or Income Support, or on Child Tax Credit or + Working Tax Credit and none of those (an award of at least £26 for the + year in 2022-23), the disability payment to each person on PIP, DLA, + Attendance Allowance or Armed Forces Independence Payment, and the + pensioner payment to each household with a Winter Fuel Payment. It + tests receipt over the year, not in the month ending with each + qualifying day, and has no variables for constant attendance allowance, + Adult Disability Payment, Child Disability Payment or the war pension + mobility supplement. - id: energy_bills_rebate name: Energy Bills Rebate diff --git a/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml b/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml index 1f5c46acef..8fa2f4a2d4 100644 --- a/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml @@ -61,3 +61,352 @@ members: [person] output: cost_of_living_support_payment: 0 + +# The cases below set every qualifying benefit and tax credit, and the Winter +# Fuel Payment, as inputs: with none set, the model computes Universal Credit +# for a working-age adult with no income and Pension Credit for a pensioner +# with none. Each expected value comes from the Social Security (Additional +# Payments) Acts 2022 and 2023. Under the 2022 Act the Secretary of State and +# HMRC pay £326 and £324 for qualifying days from 25 May 2022 to 31 October +# 2022 (section 1(1), (2) and (4)), £650 in all, which the model pays in model +# year 2022 (6 April 2022 to 5 April 2023). Under the 2023 Act they pay £301, +# £300 and £299 (section 1(1) and (2)), £900 in all, which the model pays in +# model year 2023. Under section 5(1) of each Act the Secretary of State pays +# £150 to each individual with a listed disability benefit. + +- name: 2021 pays no Cost of Living Payment in any strand + # Model year 2021 runs from 6 April 2021 to 5 April 2022, before the 2022 + # Act's first qualifying day (25 May 2022), and the pensioner amount starts + # in 2022. The pensioner, on Pension Credit and Attendance Allowance, the + # parent, on Child Tax Credit alone, and the household, with a Winter Fuel + # Payment, qualify in 2022 (next case) but get nothing in 2021. + period: 2021 + input: + people: + pensioner: + age: 70 + attendance_allowance: 3_000 + parent: + age: 35 + child: + age: 5 + benunits: + pensioner_unit: + members: [pensioner] + universal_credit: 0 + pension_credit: 1_000 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 0 + working_tax_credit: 0 + parent_unit: + members: [parent, child] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 2_000 + working_tax_credit: 0 + households: + household: + members: [pensioner, parent, child] + winter_fuel_allowance: 200 + output: + cost_of_living_means_tested_payment: [0, 0] + cost_of_living_disability_payment: [0, 0, 0] + cost_of_living_support_payment: 0 + +- name: 2022 pays every strand to the household that 2021 pays nothing + # The pensioner unit has Pension Credit, listed in section 1(3)(b), so the + # Secretary of State pays it £326 + £324 = £650 (section 1(1)). The parent + # unit has Child Tax Credit of £2,000, at least £26 (section 2(2)), and no + # listed benefit, so HMRC pays it £650 (section 1(2)). The pensioner has + # Attendance Allowance, listed in section 5(2)(c): £150. The pensioner + # amount adds £300. Total: £650 + £650 + £150 + £300 = £1,750. + period: 2022 + input: + people: + pensioner: + age: 70 + attendance_allowance: 3_000 + parent: + age: 35 + child: + age: 5 + benunits: + pensioner_unit: + members: [pensioner] + universal_credit: 0 + pension_credit: 1_000 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 0 + working_tax_credit: 0 + parent_unit: + members: [parent, child] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 2_000 + working_tax_credit: 0 + households: + household: + members: [pensioner, parent, child] + winter_fuel_allowance: 200 + output: + cost_of_living_means_tested_payment: [650, 650] + cost_of_living_disability_payment: [150, 0, 0] + cost_of_living_support_payment: 1_750 + +- name: 2022 Housing Benefit alone gets no means-tested payment + # Parliament left Housing Benefit out of the list in section 1(3) (Universal + # Credit, Pension Credit, income-based JSA, income-related ESA and Income + # Support), and the unit has no tax credit, so neither the Secretary of + # State (section 1(1)) nor HMRC (section 1(2)) pays it. + period: 2022 + input: + people: + tenant: + age: 40 + benunits: + tenant_unit: + members: [tenant] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + housing_benefit: 3_000 + child_tax_credit: 0 + working_tax_credit: 0 + households: + household: + members: [tenant] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 0 + cost_of_living_support_payment: 0 + +- name: 2022 Child Tax Credit alone at the £26 minimum gets the means-tested payment + # A yearly award of £26 meets section 2(2)'s "at least £26" for 2022-23, and + # the unit has no listed benefit, so HMRC pays £326 + £324 = £650 + # (section 1(2)). + period: 2022 + input: + people: + parent: + age: 30 + child: + age: 5 + benunits: + family: + members: [parent, child] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 26 + working_tax_credit: 0 + households: + household: + members: [parent, child] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 650 + cost_of_living_support_payment: 650 + +- name: 2022 Child Tax Credit alone just under the £26 minimum gets nothing + # A yearly award of £25.99 falls short of section 2(2)'s £26, so the unit + # has no qualifying entitlement and HMRC pays nothing. + period: 2022 + input: + people: + parent: + age: 30 + child: + age: 5 + benunits: + family: + members: [parent, child] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 25.99 + working_tax_credit: 0 + households: + household: + members: [parent, child] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 0 + cost_of_living_support_payment: 0 + +- name: 2022 Child Tax Credit and Working Tax Credit each under £26 get nothing + # Under section 2(2) the award of "the credit in question" must come to at + # least £26. Neither £20 award does, so the unit has a qualifying + # entitlement to neither credit, although the two together come to £40. + period: 2022 + input: + people: + parent: + age: 30 + child: + age: 5 + benunits: + family: + members: [parent, child] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 20 + working_tax_credit: 20 + households: + household: + members: [parent, child] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 0 + cost_of_living_support_payment: 0 + +- name: 2023 a small Child Tax Credit award alone gets the means-tested payment + # Parliament set no minimum award in section 3(1) of the 2023 Act: any + # payment of the credit counts. With no listed benefit, HMRC pays £301 + + # £300 + £299 = £900 (section 1(2)). + period: 2023 + input: + people: + parent: + age: 30 + child: + age: 5 + benunits: + family: + members: [parent, child] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 10 + working_tax_credit: 0 + households: + household: + members: [parent, child] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 900 + cost_of_living_support_payment: 900 + +- name: 2022 Universal Credit with tax credits gets one means-tested payment + # The unit has Universal Credit, so the Secretary of State pays it £650 + # under section 1(1). HMRC pays tax credit recipients under section 1(2) + # only where they have no listed benefit, so it adds nothing. + period: 2022 + input: + people: + parent: + age: 30 + child: + age: 5 + benunits: + family: + members: [parent, child] + universal_credit: 1_000 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 2_000 + working_tax_credit: 500 + households: + household: + members: [parent, child] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 650 + cost_of_living_support_payment: 650 + +- name: 2023 two qualifying benefit units in one household get two means-tested payments + # A person means an individual or a couple (section 1(9) of the 2023 Act). + # The adult son on Universal Credit and his parents on Pension Credit count + # as two persons, so the Secretary of State pays each £900 (section 1(1)). + # The pensioner amount adds £300: £900 + £900 + £300 = £2,100. + period: 2023 + input: + people: + son: + age: 30 + mother: + age: 70 + father: + age: 72 + benunits: + son_unit: + members: [son] + universal_credit: 1_000 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 0 + working_tax_credit: 0 + parents_unit: + members: [mother, father] + universal_credit: 0 + pension_credit: 2_000 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 0 + working_tax_credit: 0 + households: + household: + members: [son, mother, father] + winter_fuel_allowance: 300 + output: + cost_of_living_means_tested_payment: [900, 900] + cost_of_living_disability_payment: [0, 0, 0] + cost_of_living_support_payment: 2_100 + +- name: 2022 two people on PIP get two disability payments + # Under section 5(1) the Secretary of State pays £150 to each individual + # with a disability benefit on the list in section 5(2), which includes PIP + # (paragraph (b)). A couple both on PIP gets £150 + £150 = £300, although + # the couple counts as one person for the means-tested payment. + period: 2022 + input: + people: + first_partner: + age: 45 + pip: 4_000 + second_partner: + age: 47 + pip: 2_000 + benunits: + couple: + members: [first_partner, second_partner] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 0 + working_tax_credit: 0 + households: + household: + members: [first_partner, second_partner] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 0 + cost_of_living_disability_payment: [150, 150] + cost_of_living_support_payment: 300 diff --git a/policyengine_uk/tests/test_cost_of_living_payment_properties.py b/policyengine_uk/tests/test_cost_of_living_payment_properties.py new file mode 100644 index 0000000000..bb1d307707 --- /dev/null +++ b/policyengine_uk/tests/test_cost_of_living_payment_properties.py @@ -0,0 +1,354 @@ +"""Properties of the Cost of Living Payments. + +Under section 1 of the Social Security (Additional Payments) Acts 2022 and +2023, the Secretary of State pays the means-tested payment to each person, +meaning an individual or a couple, with Universal Credit, Pension Credit, +income-based JSA, income-related ESA or Income Support, and HMRC pays the same +amount to each person with Child Tax Credit or Working Tax Credit and none of +those benefits. In 2022-23 a tax credit counts only where its award comes to +at least £26 (2022 Act section 2(2)); Parliament set no minimum in the 2023 +Act (section 3(1)). Under section 5 of each Act the Secretary of State pays +£150 to each individual with a listed disability benefit. The model treats +each benefit unit as a person in the Acts' sense, and pays the pensioner +payment once to each household with a Winter Fuel Payment. + +The households here set every benefit the payments read as an input, so the +properties hold for any amounts of those benefits: + +1. Dates: in every model year from 2015 (the first the model computes) to + 2021, and from 2024 to 2040, every household's, benefit unit's and + person's payment is zero. +2. Decomposition: in 2022 and 2023, a household's payment equals the + means-tested amount (£326 + £324 in 2022, £301 + £300 + £299 in 2023) + times its qualifying benefit units, plus £150 times its qualifying people, + plus the pensioner amount if it has a Winter Fuel Payment. The test counts + qualifying units and people from the Acts' lists, not from the model's + parameters, and checks each benefit unit's and person's payment the same + way. +3. Monotonicity: in any year, adding a benefit unit to a household, or a + person to one of its benefit units, never lowers the household's payment. + +Each example builds one simulation of up to eight households. +""" + +import numpy as np +import pytest +from hypothesis import HealthCheck, example, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +# Section 1(3) of each Act: the social security benefits. +LISTED_BENEFITS = [ + "universal_credit", + "pension_credit", + "jsa_income", + "esa_income", + "income_support", +] +# Section 1(2) of each Act: the tax credits. +TAX_CREDITS = ["child_tax_credit", "working_tax_credit"] +# On neither list; the households vary in it all the same. +UNLISTED_BENEFITS = ["housing_benefit"] +BENEFIT_UNIT_INPUTS = LISTED_BENEFITS + TAX_CREDITS + UNLISTED_BENEFITS +# Section 5(2) of each Act: the disability benefits the model has variables +# for. +DISABILITY_BENEFITS = [ + "pip", + "dla", + "attendance_allowance", + "armed_forces_independence_payment", +] +# Section 1(1) and (2): £326 and £324 under the 2022 Act, and £301, £300 and +# £299 under the 2023 Act. +MEANS_TESTED_AMOUNT = {2022: 326 + 324, 2023: 301 + 300 + 299} +# 2022 Act section 2(2). The 2023 Act sets no minimum (section 3(1)). +MINIMUM_TAX_CREDIT_AWARD = {2022: 26, 2023: 0} +# Section 5(1) of each Act. +DISABILITY_AMOUNT = 150 +PAID_YEARS = [2022, 2023] +UNPAID_YEARS = [*range(2015, 2022), *range(2024, 2041)] +PAYMENTS = [ + "cost_of_living_support_payment", + "cost_of_living_means_tested_payment", + "cost_of_living_disability_payment", +] +# A penny: float32 holds a total of a few thousand pounds to within 0.001. +TOLERANCE = 1e-2 +SETTINGS = settings( + max_examples=40, + deadline=None, + derandomize=True, + database=None, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) + + +def float32(amount): + return float(np.float32(amount)) + + +# Awards either side of the £26 minimum and any other amount up to £20,000, +# each as float32 holds it, so the test compares the amounts the model reads. +AWARDS = st.one_of( + st.sampled_from([0.01, 25.99, 26.0, 26.01]), + st.floats(0.01, 20_000, allow_nan=False, allow_infinity=False), +).map(float32) + + +@st.composite +def people(draw): + """A person with up to two disability benefits, the rest zero.""" + paid = draw(st.sets(st.sampled_from(DISABILITY_BENEFITS), max_size=2)) + return {name: draw(AWARDS) if name in paid else 0.0 for name in DISABILITY_BENEFITS} + + +# The benefits a unit may have: none, Housing Benefit alone, tax credits +# alone, listed benefits alone, or any mix, so that each route to the +# means-tested payment, and Housing Benefit alone, occur often. +BENEFIT_POOLS = [ + [], + UNLISTED_BENEFITS, + TAX_CREDITS, + LISTED_BENEFITS, + BENEFIT_UNIT_INPUTS, +] + + +@st.composite +def benefit_units(draw): + """One to three people, and up to three non-zero benefits or tax credits + from one of BENEFIT_POOLS, the rest zero.""" + pool = draw(st.sampled_from(BENEFIT_POOLS)) + paid = ( + draw(st.sets(st.sampled_from(pool), min_size=1, max_size=min(3, len(pool)))) + if pool + else set() + ) + return { + "benefits": { + name: draw(AWARDS) if name in paid else 0.0 for name in BENEFIT_UNIT_INPUTS + }, + "people": draw(st.lists(people(), min_size=1, max_size=3)), + } + + +@st.composite +def households(draw): + return { + "winter_fuel_allowance": draw(st.one_of(st.just(0.0), AWARDS)), + "units": draw(st.lists(benefit_units(), min_size=1, max_size=3)), + } + + +def populations(years): + return st.fixed_dictionaries( + { + "year": st.sampled_from(years), + "households": st.lists(households(), min_size=1, max_size=8), + } + ) + + +def unit(*people, **benefits): + """A benefit unit with the given benefits, and people with the given + disability benefits (one person with none if no people are given).""" + return { + "benefits": { + name: float32(benefits.get(name, 0)) for name in BENEFIT_UNIT_INPUTS + }, + "people": [ + {name: float32(person.get(name, 0)) for name in DISABILITY_BENEFITS} + for person in (people or ({},)) + ], + } + + +# Households that exercise each rule, whatever Hypothesis draws: every strand +# in one household, Housing Benefit alone, Child Tax Credit at and just under +# £26, both credits at £20 each, Universal Credit with tax credits, and a +# couple both on PIP. +PINNED_HOUSEHOLDS = [ + { + "winter_fuel_allowance": 200.0, + "units": [ + unit({"attendance_allowance": 3_000}, pension_credit=1_000), + unit({}, {}, child_tax_credit=2_000), + ], + }, + {"winter_fuel_allowance": 0.0, "units": [unit(housing_benefit=3_000)]}, + { + "winter_fuel_allowance": 0.0, + "units": [unit(child_tax_credit=26), unit(child_tax_credit=25.99)], + }, + { + "winter_fuel_allowance": 0.0, + "units": [unit(child_tax_credit=20, working_tax_credit=20)], + }, + { + "winter_fuel_allowance": 0.0, + "units": [ + unit(universal_credit=1_000, child_tax_credit=2_000, working_tax_credit=500) + ], + }, + { + "winter_fuel_allowance": 0.0, + "units": [unit({"pip": 4_000}, {"pip": 2_000})], + }, +] + + +def pinned(year): + return {"year": year, "households": PINNED_HOUSEHOLDS} + + +def situation(population): + year = population["year"] + people_, benunits, households_ = {}, {}, {} + for h, household in enumerate(population["households"]): + members = [] + for u, benefit_unit in enumerate(household["units"]): + unit_members = [] + for p, person in enumerate(benefit_unit["people"]): + name = f"h{h}_u{u}_p{p}" + people_[name] = {key: {year: value} for key, value in person.items()} + unit_members.append(name) + benunits[f"h{h}_u{u}"] = { + "members": unit_members, + **{ + key: {year: value} + for key, value in benefit_unit["benefits"].items() + }, + } + members += unit_members + households_[f"h{h}"] = { + "members": members, + "winter_fuel_allowance": {year: household["winter_fuel_allowance"]}, + } + return {"people": people_, "benunits": benunits, "households": households_} + + +@pytest.fixture(scope="module") +def template(): + return Simulation(situation={"people": {"template": {}}}) + + +def simulate(template, population): + # These properties never reform parameters or variable definitions, so + # each example rebuilds its population on the template's system. + simulation = template.clone(clone_tax_benefit_system=False) + simulation.build_from_situation(situation(population)) + simulation.input_variables = simulation.get_known_variables() + simulation.calculated_periods = [] + return simulation + + +def calculate(simulation, population, variable): + return np.asarray(simulation.calculate(variable, population["year"]), dtype=float) + + +def unit_qualifies(benefit_unit, year): + """Section 1(1) and (3), or section 1(2) with the minimum award.""" + benefits = benefit_unit["benefits"] + if any(benefits[name] > 0 for name in LISTED_BENEFITS): + return True + minimum = MINIMUM_TAX_CREDIT_AWARD[year] + return any(benefits[name] > 0 and benefits[name] >= minimum for name in TAX_CREDITS) + + +def person_qualifies(person): + """Section 5(1) and (2).""" + return any(person[name] > 0 for name in DISABILITY_BENEFITS) + + +def pensioner_amount(template, year): + parameters = template.tax_benefit_system.parameters(f"{year}-01-01") + return parameters.gov.treasury.cost_of_living_support.pensioners.amount + + +@SETTINGS +@given(populations(UNPAID_YEARS)) +@example(pinned(2021)) +@example(pinned(2024)) +def test_no_household_payment_before_2022_or_from_2024(template, population): + simulation = simulate(template, population) + payment = calculate(simulation, population, "cost_of_living_support_payment") + assert np.all(payment == 0), payment + + +@SETTINGS +@given(populations(UNPAID_YEARS)) +@example(pinned(2021)) +def test_no_unit_or_person_payment_before_2022_or_from_2024(template, population): + simulation = simulate(template, population) + for variable in PAYMENTS[1:]: + payment = calculate(simulation, population, variable) + assert np.all(payment == 0), (variable, payment) + + +@SETTINGS +@given(populations(PAID_YEARS)) +@example(pinned(2022)) +@example(pinned(2023)) +def test_household_payment_counts_each_qualifying_unit_and_person(template, population): + year = population["year"] + expected = [ + MEANS_TESTED_AMOUNT[year] + * sum(unit_qualifies(u, year) for u in household["units"]) + + DISABILITY_AMOUNT + * sum(person_qualifies(p) for u in household["units"] for p in u["people"]) + + pensioner_amount(template, year) * (household["winter_fuel_allowance"] > 0) + for household in population["households"] + ] + simulation = simulate(template, population) + payment = calculate(simulation, population, "cost_of_living_support_payment") + np.testing.assert_allclose(payment, expected, rtol=0, atol=TOLERANCE) + + +@SETTINGS +@given(populations(PAID_YEARS)) +@example(pinned(2022)) +@example(pinned(2023)) +def test_each_unit_and_person_gets_its_own_payment(template, population): + year = population["year"] + units = [u for household in population["households"] for u in household["units"]] + simulation = simulate(template, population) + np.testing.assert_array_equal( + calculate(simulation, population, "cost_of_living_means_tested_payment"), + [MEANS_TESTED_AMOUNT[year] * unit_qualifies(u, year) for u in units], + ) + np.testing.assert_array_equal( + calculate(simulation, population, "cost_of_living_disability_payment"), + [DISABILITY_AMOUNT * person_qualifies(p) for u in units for p in u["people"]], + ) + + +@SETTINGS +@given( + population=populations(PAID_YEARS + UNPAID_YEARS), + additions=st.lists( + st.tuples(st.booleans(), benefit_units(), st.integers(0, 2)), + min_size=8, + max_size=8, + ), +) +def test_adding_a_unit_or_person_never_lowers_the_payment( + template, population, additions +): + """Each household gains a benefit unit, or one of its units gains a + person, drawn like any other.""" + grown = [] + for household, (add_unit, new_unit, index) in zip( + population["households"], additions + ): + units = [dict(u, people=list(u["people"])) for u in household["units"]] + if add_unit: + units.append(new_unit) + else: + units[index % len(units)]["people"].append(new_unit["people"][0]) + grown.append(dict(household, units=units)) + payment = "cost_of_living_support_payment" + before = calculate(simulate(template, population), population, payment) + grown_population = dict(population, households=grown) + after = calculate(simulate(template, grown_population), grown_population, payment) + assert np.all(after >= before - TOLERANCE), (before, after) diff --git a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_disability_payment.py b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_disability_payment.py new file mode 100644 index 0000000000..03c1384302 --- /dev/null +++ b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_disability_payment.py @@ -0,0 +1,24 @@ +from policyengine_uk.model_api import * + + +class cost_of_living_disability_payment(Variable): + label = "Disability cost-of-living payment" + documentation = ( + "The Disability Cost of Living Payment to the person in the year. The " + "Secretary of State pays it to each individual with a qualifying " + "disability benefit, so each person in a household who has one gets " + "it." + ) + entity = Person + definition_period = YEAR + value_type = float + unit = GBP + reference = [ + "https://www.legislation.gov.uk/ukpga/2022/38/section/5", + "https://www.legislation.gov.uk/ukpga/2023/7/section/5", + ] + + def formula(person, period, parameters): + p = parameters(period).gov.treasury.cost_of_living_support.disabled + on_benefit = add(person, period, p.qualifying_benefits) > 0 + return p.amount * on_benefit diff --git a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_means_tested_payment.py b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_means_tested_payment.py new file mode 100644 index 0000000000..153ca9cfbc --- /dev/null +++ b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_means_tested_payment.py @@ -0,0 +1,41 @@ +from policyengine_uk.model_api import * + + +class cost_of_living_means_tested_payment(Variable): + label = "Means-tested cost-of-living payment" + documentation = ( + "The means-tested Cost of Living Payments to the benefit unit in the " + "year. Under the Social Security (Additional Payments) Acts 2022 and " + "2023 a person means an individual or a couple, so each benefit unit " + "qualifies on its own. The Secretary of State pays a benefit unit " + "with a qualifying benefit, and HMRC pays one with a qualifying tax " + "credit and no qualifying benefit. In 2022-23 HMRC pays the tax " + "credit route only where the yearly award of either credit reaches " + "the minimum award." + ) + entity = BenUnit + definition_period = YEAR + value_type = float + unit = GBP + reference = [ + "https://www.legislation.gov.uk/ukpga/2022/38/section/1", + "https://www.legislation.gov.uk/ukpga/2022/38/section/2", + "https://www.legislation.gov.uk/ukpga/2023/7/section/1", + "https://www.legislation.gov.uk/ukpga/2023/7/section/3", + ] + + def formula(benunit, period, parameters): + p = parameters( + period + ).gov.treasury.cost_of_living_support.means_tested_households + on_benefit = add(benunit, period, p.qualifying_benefits) > 0 + # The formula tests each credit's own award against the minimum, + # following "the credit in question" in section 2(2) of the 2022 Act, + # not the credits' sum. + on_tax_credit = False + for credit in p.qualifying_tax_credits: + award = benunit(credit, period) + on_tax_credit = on_tax_credit | ( + (award > 0) & (award >= p.minimum_tax_credit_award) + ) + return p.amount * (on_benefit | on_tax_credit) diff --git a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py index 7a6d9bc084..a905411c24 100644 --- a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py +++ b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py @@ -3,31 +3,35 @@ class cost_of_living_support_payment(Variable): label = "Cost-of-living support payment" + documentation = ( + "The household's Cost of Living Payments in the year: the " + "means-tested payment to each of its benefit units, the disability " + "payment to each of its members and the pensioner payment, once per " + "household with a Winter Fuel Payment." + ) entity = Household definition_period = YEAR value_type = float unit = GBP + reference = [ + "https://www.legislation.gov.uk/ukpga/2022/38/section/1", + "https://www.legislation.gov.uk/ukpga/2022/38/section/5", + "https://www.legislation.gov.uk/ukpga/2023/7/section/1", + "https://www.legislation.gov.uk/ukpga/2023/7/section/5", + "https://www.gov.uk/guidance/cost-of-living-payment-pensioner", + ] def formula(household, period, parameters): - col = parameters(period).gov.treasury.cost_of_living_support - on_means_tested_benefits = ( - add( - household, - period, - col.means_tested_households.qualifying_benefits, - ) - > 0 + pensioners = parameters(period).gov.treasury.cost_of_living_support.pensioners + unit_and_person_payments = add( + household, + period, + [ + "cost_of_living_means_tested_payment", + "cost_of_living_disability_payment", + ], ) - means_test_bonus = col.means_tested_households.amount * on_means_tested_benefits - - on_pensioner_benefits = ( - add(household, period, col.pensioners.qualifying_benefits) > 0 - ) - pensioner_bonus = col.pensioners.amount * on_pensioner_benefits - - on_disability_benefits = ( - add(household, period, col.disabled.qualifying_benefits) > 0 + on_pensioner_benefit = ( + add(household, period, pensioners.qualifying_benefits) > 0 ) - disabled_bonus = col.disabled.amount * on_disability_benefits - - return means_test_bonus + pensioner_bonus + disabled_bonus + return unit_and_person_payments + pensioners.amount * on_pensioner_benefit From e4d61659269516ede0984b46644bd5595bdbb10a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 10:45:16 +0000 Subject: [PATCH 2/4] Tighten the cost-of-living properties and name the actors in their text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check every unpaid year in each dates example, both paid years in each decomposition example, and the exact rise when a qualifying benefit unit or person joins a household, all within one simulation per example. Take the £300 pensioner amount from the sources its parameter cites, not from the parameter. Add a 2023 Housing Benefit case. Cite section 4 of the 2022 Act beside section 2(2) for the £26 minimum, make Parliament, the Secretary of State or HMRC the actor in descriptions, test names and docs, move the model-baseline links to the 2022 amounts, and note the leading zero in the future-dating guide. Claude-Session: https://claude.ai/code/session_01WR8LHckHwu75WHHEdzLyNc Co-Authored-By: Claude Opus 5.5 --- changelog.d/2847.fixed.md | 2 +- docs/book/policy/future-date-announcements.md | 5 +- docs/book/policy/model-baseline.md | 2 +- .../gov/treasury/cost-of-living-payments.md | 12 +- .../disabled/qualifying_benefits.yaml | 2 +- .../minimum_tax_credit_award.yaml | 4 +- .../qualifying_benefits.yaml | 2 +- policyengine_uk/programs.yaml | 22 +- .../cost_of_living_support_payment.yaml | 77 +++-- .../test_cost_of_living_payment_properties.py | 297 +++++++++++------- .../cost_of_living_means_tested_payment.py | 7 +- .../cost_of_living_support_payment.py | 6 +- 12 files changed, 269 insertions(+), 169 deletions(-) diff --git a/changelog.d/2847.fixed.md b/changelog.d/2847.fixed.md index 9e2fbca812..6dbc8feb42 100644 --- a/changelog.d/2847.fixed.md +++ b/changelog.d/2847.fixed.md @@ -1 +1 @@ -The Cost of Living Payments now read zero before 2022, so the model no longer pays them in 2015-16 to 2021-22. As under the Social Security (Additional Payments) Acts 2022 and 2023, the model pays the means-tested payment to each benefit unit on Universal Credit, Pension Credit, income-based JSA, income-related ESA or Income Support, or on tax credits alone (at least £26 a year in 2022-23), and not on Housing Benefit alone, and pays the £150 disability payment to each person on a qualifying disability benefit. +The Cost of Living Payment amounts now read zero before 2022, so the model no longer pays them in 2015-16 to 2021-22. Following the Social Security (Additional Payments) Acts 2022 and 2023, the model now pays the means-tested payment to each benefit unit on Universal Credit, Pension Credit, income-based JSA, income-related ESA or Income Support, or on Child Tax Credit or Working Tax Credit alone (in 2022-23, with at least £26 of either credit), but not to one on Housing Benefit alone, and pays the £150 disability payment to each person on PIP, DLA, Attendance Allowance or Armed Forces Independence Payment. diff --git a/docs/book/policy/future-date-announcements.md b/docs/book/policy/future-date-announcements.md index e12b48e4d0..73f90114f3 100644 --- a/docs/book/policy/future-date-announcements.md +++ b/docs/book/policy/future-date-announcements.md @@ -121,7 +121,10 @@ The same pattern applies in reverse to one-off or time-limited payments. The means-tested Cost-of-Living Payment in [`gov/treasury/cost_of_living_support/means_tested_households/amount.yaml`](https://github.com/PolicyEngine/policyengine-uk/blob/main/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/amount.yaml) is £650 from 2022, £900 from 2023 and goes back to zero from -2024-01-01. +2024-01-01. It also reads zero before 2022, from a `0001-01-01: 0` row: the +model carries each parameter's earliest value back to 2015 +(`backdate_parameters` in `policyengine_uk/utils/parameters.py`), so without +that row it would pay the one-off amount in every year from 2015. ## Best practices diff --git a/docs/book/policy/model-baseline.md b/docs/book/policy/model-baseline.md index 216a78ee1c..b1d2e35b90 100644 --- a/docs/book/policy/model-baseline.md +++ b/docs/book/policy/model-baseline.md @@ -66,7 +66,7 @@ The government announced increases to [stamp duty nil rate thresholds](https://g ### Cost of living support -The government announced cost of living payments: [£650 for means-tested benefit recipients](https://github.com/PolicyEngine/policyengine-uk/blob/master/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/amount.yaml#L3), [£300 for pensioners](https://github.com/PolicyEngine/policyengine-uk/blob/master/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml#L3), and [£150 for disability benefit recipients](https://github.com/PolicyEngine/policyengine-uk/blob/master/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/amount.yaml#L3), implemented through dedicated [payment calculation variables](https://github.com/PolicyEngine/policyengine-uk/blob/master/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py). +The government announced cost of living payments: [£650 for means-tested benefit recipients](https://github.com/PolicyEngine/policyengine-uk/blob/master/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/amount.yaml#L4), [£300 for pensioners](https://github.com/PolicyEngine/policyengine-uk/blob/master/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml#L4), and [£150 for disability benefit recipients](https://github.com/PolicyEngine/policyengine-uk/blob/master/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/amount.yaml#L4), implemented through dedicated [payment calculation variables](https://github.com/PolicyEngine/policyengine-uk/blob/master/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py). ### Energy Price Guarantee diff --git a/docs/book/programs/gov/treasury/cost-of-living-payments.md b/docs/book/programs/gov/treasury/cost-of-living-payments.md index a0b8b2c624..2bac3b479f 100644 --- a/docs/book/programs/gov/treasury/cost-of-living-payments.md +++ b/docs/book/programs/gov/treasury/cost-of-living-payments.md @@ -124,9 +124,9 @@ payment to each person and the pensioner payment to the household. | Disability CoL Payment | £150 | £150 | DLA, PIP, Attendance Allowance or Armed Forces Independence Payment | From 2024-01-01 the amounts read zero, so the one-off payments don't -extrapolate forward. The amounts also read zero before 2022, so the model's -backdating of each parameter's earliest value to 2015 doesn't pay them in -2015-16 to 2021-22. +extrapolate forward. The amounts also read zero before 2022, so although the +model carries each parameter's earliest value back to 2015, it pays nothing +in 2015-16 to 2021-22. ### How PolicyEngine computes the payment @@ -134,7 +134,7 @@ Under the Social Security (Additional Payments) Acts 2022 and 2023, the Secretary of State and HMRC pay the means-tested payment to each "person", meaning an individual or a couple (section 1(6) of the 2022 Act, section 1(9) of the 2023 Act), and the Secretary of State pays the disability payment to -each individual (section 5(1)). Three variables follow them: +each individual (section 5(1)). Three variables model these payments: - `cost_of_living_means_tested_payment` (benefit unit) pays `means_tested_households.amount` to a benefit unit with any of @@ -161,8 +161,8 @@ three. The model holds yearly amounts, so it tests receipt of each benefit and tax credit over the year rather than in the month ending with each qualifying day, and compares each tax credit's yearly award with the £26 minimum. It -has no variables for the other disability benefits that section 5(2) lists -(constant attendance allowance, Adult Disability Payment, Child Disability +has no variables for the other disability benefits that Parliament listed +in section 5(2) (constant attendance allowance, Adult Disability Payment, Child Disability Payment and the war pension mobility supplement), so it pays no disability payment to someone who gets only those. diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml index af8c629749..addf7ef4a4 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml @@ -1,4 +1,4 @@ -description: Disability benefits that qualify a person for the Disability Cost of Living Payment. The list follows section 5(2) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023. The model has no variables for the other benefits that section lists (constant attendance allowance, Adult Disability Payment, Child Disability Payment and the war pension mobility supplement), so it pays nobody who gets only those. +description: Disability benefits that qualify a person for the Disability Cost of Living Payment. The list follows section 5(2) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023. The model has no variables for the other benefits Parliament listed there (constant attendance allowance, Adult Disability Payment, Child Disability Payment and the war pension mobility supplement), so it pays nobody who gets only those. metadata: economy: false label: Qualifying benefits for support for disabled households diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/minimum_tax_credit_award.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/minimum_tax_credit_award.yaml index 1c8ae1b3e4..c566da75ce 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/minimum_tax_credit_award.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/minimum_tax_credit_award.yaml @@ -1,4 +1,4 @@ -description: Smallest yearly award of a qualifying tax credit that qualifies a benefit unit for the means-tested Cost of Living Payment through the tax credit route. Under section 2(2) of the Social Security (Additional Payments) Act 2022, HMRC pays in 2022-23 only where the payment, award or expected award of the credit in question for the tax year comes to at least £26. Parliament set no such minimum in section 3(1) of the Social Security (Additional Payments) Act 2023. The model holds yearly amounts, so the formula compares each credit's yearly award with this amount. +description: Smallest yearly award of a qualifying tax credit that qualifies a benefit unit for the means-tested Cost of Living Payment through the tax credit route. Under section 2(2) of the Social Security (Additional Payments) Act 2022, a credit counts in 2022-23 only where the payment or award of that credit comes to at least £26, or HMRC expects at least £26 of it for the tax year 2022-23, and under section 4 HMRC makes final payments where the payments or award of a credit for 2022-23 come to at least £26. Parliament set no such minimum in section 3(1) of the Social Security (Additional Payments) Act 2023. The model holds yearly amounts, so the formula compares each credit's yearly award with this amount. values: 2022-01-01: 26 2023-01-01: 0 @@ -9,5 +9,7 @@ metadata: reference: - title: Social Security (Additional Payments) Act 2022, section 2(2) href: https://www.legislation.gov.uk/ukpga/2022/38/section/2 + - title: Social Security (Additional Payments) Act 2022, section 4 + href: https://www.legislation.gov.uk/ukpga/2022/38/section/4 - title: Social Security (Additional Payments) Act 2023, section 3(1) href: https://www.legislation.gov.uk/ukpga/2023/7/section/3 diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_benefits.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_benefits.yaml index d58558f229..ea98005829 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_benefits.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/means_tested_households/qualifying_benefits.yaml @@ -1,4 +1,4 @@ -description: Means-tested benefits that qualify a benefit unit for the means-tested Cost of Living Payment. The list follows section 1(3) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023, which name Universal Credit, Pension Credit, income-based Jobseeker's Allowance, income-related Employment and Support Allowance and Income Support. Neither Act lists Housing Benefit. +description: Means-tested benefits that qualify a benefit unit for the means-tested Cost of Living Payment. In section 1(3) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023, Parliament listed Universal Credit, Pension Credit, income-based Jobseeker's Allowance, income-related Employment and Support Allowance and Income Support, and left out Housing Benefit. metadata: economy: false label: Qualifying benefits for support for means-tested households diff --git a/policyengine_uk/programs.yaml b/policyengine_uk/programs.yaml index 8d57e857f0..66676544c6 100644 --- a/policyengine_uk/programs.yaml +++ b/policyengine_uk/programs.yaml @@ -601,17 +601,17 @@ programs: verified_start_year: 2022 verified_end_year: 2023 notes: >- - Temporary program, ended 2023. The model pays the means-tested payment - to each benefit unit on Universal Credit, Pension Credit, income-based - JSA, income-related ESA or Income Support, or on Child Tax Credit or - Working Tax Credit and none of those (an award of at least £26 for the - year in 2022-23), the disability payment to each person on PIP, DLA, - Attendance Allowance or Armed Forces Independence Payment, and the - pensioner payment to each household with a Winter Fuel Payment. It - tests receipt over the year, not in the month ending with each - qualifying day, and has no variables for constant attendance allowance, - Adult Disability Payment, Child Disability Payment or the war pension - mobility supplement. + Temporary programme, paid in 2022-23 and 2023-24. The model pays the + means-tested payment to each benefit unit on Universal Credit, Pension + Credit, income-based JSA, income-related ESA or Income Support, or on + Child Tax Credit or Working Tax Credit and none of those (in 2022-23, + at least £26 of either credit for the year), the disability payment to + each person on PIP, DLA, Attendance Allowance or Armed Forces + Independence Payment, and the pensioner payment to each household with + a Winter Fuel Payment. It tests receipt over the year, not in the month + ending with each qualifying day, and has no variables for constant + attendance allowance, Adult Disability Payment, Child Disability + Payment or the war pension mobility supplement. - id: energy_bills_rebate name: Energy Bills Rebate diff --git a/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml b/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml index 8fa2f4a2d4..2f616be305 100644 --- a/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml @@ -65,16 +65,18 @@ # The cases below set every qualifying benefit and tax credit, and the Winter # Fuel Payment, as inputs: with none set, the model computes Universal Credit # for a working-age adult with no income and Pension Credit for a pensioner -# with none. Each expected value comes from the Social Security (Additional -# Payments) Acts 2022 and 2023. Under the 2022 Act the Secretary of State and -# HMRC pay £326 and £324 for qualifying days from 25 May 2022 to 31 October -# 2022 (section 1(1), (2) and (4)), £650 in all, which the model pays in model -# year 2022 (6 April 2022 to 5 April 2023). Under the 2023 Act they pay £301, -# £300 and £299 (section 1(1) and (2)), £900 in all, which the model pays in -# model year 2023. Under section 5(1) of each Act the Secretary of State pays -# £150 to each individual with a listed disability benefit. +# with none. Each means-tested and disability amount comes from the Social +# Security (Additional Payments) Acts 2022 and 2023. Under the 2022 Act the +# Secretary of State and HMRC pay £326 and £324 for qualifying days from 25 +# May 2022 to 31 October 2022 (section 1(1), (2) and (4)), £650 in all, which +# the model pays in model year 2022 (6 April 2022 to 5 April 2023). Under the +# 2023 Act they pay £301, £300 and £299 (section 1(1) and (2)), £900 in all, +# which the model pays in model year 2023. Under section 5(1) of each Act the +# Secretary of State pays £150 to each individual with a listed disability +# benefit. Neither Act covers the £300 pensioner payment: pensioners/amount.yaml +# takes it from the May 2022 package announcement and DWP's 2023-24 guidance. -- name: 2021 pays no Cost of Living Payment in any strand +- name: 2021 a household qualifying for every strand gets no Cost of Living Payment # Model year 2021 runs from 6 April 2021 to 5 April 2022, before the 2022 # Act's first qualifying day (25 May 2022), and the pensioner amount starts # in 2022. The pensioner, on Pension Credit and Attendance Allowance, the @@ -118,13 +120,13 @@ cost_of_living_disability_payment: [0, 0, 0] cost_of_living_support_payment: 0 -- name: 2022 pays every strand to the household that 2021 pays nothing +- name: 2022 a household qualifying for every strand gets all three payments # The pensioner unit has Pension Credit, listed in section 1(3)(b), so the # Secretary of State pays it £326 + £324 = £650 (section 1(1)). The parent # unit has Child Tax Credit of £2,000, at least £26 (section 2(2)), and no # listed benefit, so HMRC pays it £650 (section 1(2)). The pensioner has - # Attendance Allowance, listed in section 5(2)(c): £150. The pensioner - # amount adds £300. Total: £650 + £650 + £150 + £300 = £1,750. + # Attendance Allowance, listed in section 5(2)(c): £150. The formula adds + # the £300 pensioner amount. Total: £650 + £650 + £150 + £300 = £1,750. period: 2022 input: people: @@ -163,7 +165,7 @@ cost_of_living_disability_payment: [150, 0, 0] cost_of_living_support_payment: 1_750 -- name: 2022 Housing Benefit alone gets no means-tested payment +- name: 2022 a benefit unit on Housing Benefit alone gets no means-tested payment # Parliament left Housing Benefit out of the list in section 1(3) (Universal # Credit, Pension Credit, income-based JSA, income-related ESA and Income # Support), and the unit has no tax credit, so neither the Secretary of @@ -192,7 +194,36 @@ cost_of_living_means_tested_payment: 0 cost_of_living_support_payment: 0 -- name: 2022 Child Tax Credit alone at the £26 minimum gets the means-tested payment +- name: 2023 a benefit unit on Housing Benefit alone gets no means-tested payment + # Parliament left Housing Benefit out of section 1(3) of the 2023 Act too. + # With no minimum award in 2023-24, any tax credit payment would qualify the + # unit (section 3(1)), but it has none, so neither the Secretary of State + # nor HMRC pays it. + period: 2023 + input: + people: + tenant: + age: 40 + benunits: + tenant_unit: + members: [tenant] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + housing_benefit: 3_000 + child_tax_credit: 0 + working_tax_credit: 0 + households: + household: + members: [tenant] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 0 + cost_of_living_support_payment: 0 + +- name: 2022 a benefit unit on £26 of Child Tax Credit alone gets the means-tested payment # A yearly award of £26 meets section 2(2)'s "at least £26" for 2022-23, and # the unit has no listed benefit, so HMRC pays £326 + £324 = £650 # (section 1(2)). @@ -221,7 +252,7 @@ cost_of_living_means_tested_payment: 650 cost_of_living_support_payment: 650 -- name: 2022 Child Tax Credit alone just under the £26 minimum gets nothing +- name: 2022 a benefit unit on £25.99 of Child Tax Credit alone gets nothing # A yearly award of £25.99 falls short of section 2(2)'s £26, so the unit # has no qualifying entitlement and HMRC pays nothing. period: 2022 @@ -249,7 +280,7 @@ cost_of_living_means_tested_payment: 0 cost_of_living_support_payment: 0 -- name: 2022 Child Tax Credit and Working Tax Credit each under £26 get nothing +- name: 2022 a benefit unit on £20 of each tax credit gets nothing # Under section 2(2) the award of "the credit in question" must come to at # least £26. Neither £20 award does, so the unit has a qualifying # entitlement to neither credit, although the two together come to £40. @@ -278,7 +309,7 @@ cost_of_living_means_tested_payment: 0 cost_of_living_support_payment: 0 -- name: 2023 a small Child Tax Credit award alone gets the means-tested payment +- name: 2023 a benefit unit on a small Child Tax Credit award alone gets the means-tested payment # Parliament set no minimum award in section 3(1) of the 2023 Act: any # payment of the credit counts. With no listed benefit, HMRC pays £301 + # £300 + £299 = £900 (section 1(2)). @@ -307,10 +338,10 @@ cost_of_living_means_tested_payment: 900 cost_of_living_support_payment: 900 -- name: 2022 Universal Credit with tax credits gets one means-tested payment +- name: 2022 a benefit unit on Universal Credit and tax credits gets one means-tested payment # The unit has Universal Credit, so the Secretary of State pays it £650 # under section 1(1). HMRC pays tax credit recipients under section 1(2) - # only where they have no listed benefit, so it adds nothing. + # only where they have no listed benefit, so HMRC pays this unit nothing. period: 2022 input: people: @@ -340,7 +371,7 @@ # A person means an individual or a couple (section 1(9) of the 2023 Act). # The adult son on Universal Credit and his parents on Pension Credit count # as two persons, so the Secretary of State pays each £900 (section 1(1)). - # The pensioner amount adds £300: £900 + £900 + £300 = £2,100. + # The formula adds the £300 pensioner amount: £900 + £900 + £300 = £2,100. period: 2023 input: people: @@ -380,9 +411,9 @@ - name: 2022 two people on PIP get two disability payments # Under section 5(1) the Secretary of State pays £150 to each individual - # with a disability benefit on the list in section 5(2), which includes PIP - # (paragraph (b)). A couple both on PIP gets £150 + £150 = £300, although - # the couple counts as one person for the means-tested payment. + # with a listed disability benefit, and Parliament listed PIP in section + # 5(2)(b). A couple both on PIP gets £150 + £150 = £300, although the couple + # counts as one person for the means-tested payment. period: 2022 input: people: diff --git a/policyengine_uk/tests/test_cost_of_living_payment_properties.py b/policyengine_uk/tests/test_cost_of_living_payment_properties.py index bb1d307707..1f910b34fc 100644 --- a/policyengine_uk/tests/test_cost_of_living_payment_properties.py +++ b/policyengine_uk/tests/test_cost_of_living_payment_properties.py @@ -6,29 +6,35 @@ income-based JSA, income-related ESA or Income Support, and HMRC pays the same amount to each person with Child Tax Credit or Working Tax Credit and none of those benefits. In 2022-23 a tax credit counts only where its award comes to -at least £26 (2022 Act section 2(2)); Parliament set no minimum in the 2023 -Act (section 3(1)). Under section 5 of each Act the Secretary of State pays -£150 to each individual with a listed disability benefit. The model treats -each benefit unit as a person in the Acts' sense, and pays the pensioner -payment once to each household with a Winter Fuel Payment. +at least £26 (2022 Act sections 2(2) and 4); Parliament set no minimum in the +2023 Act (section 3(1)). Under section 5 of each Act the Secretary of State +pays £150 to each individual with a listed disability benefit. The model +treats each benefit unit as a person in the Acts' sense, and pays the +pensioner payment once to each household with a Winter Fuel Payment. -The households here set every benefit the payments read as an input, so the -properties hold for any amounts of those benefits: +The tests set as inputs, in every year they check, every benefit the +payment formulas read, so the properties hold for any amounts of those +benefits: 1. Dates: in every model year from 2015 (the first the model computes) to 2021, and from 2024 to 2040, every household's, benefit unit's and - person's payment is zero. -2. Decomposition: in 2022 and 2023, a household's payment equals the + person's payment comes to zero. Each example checks all those years. +2. Decomposition: in 2022 and in 2023, a household's payment equals the means-tested amount (£326 + £324 in 2022, £301 + £300 + £299 in 2023) times its qualifying benefit units, plus £150 times its qualifying people, - plus the pensioner amount if it has a Winter Fuel Payment. The test counts - qualifying units and people from the Acts' lists, not from the model's - parameters, and checks each benefit unit's and person's payment the same + plus the £300 pensioner amount if it has a Winter Fuel Payment. The test + counts qualifying units and people from the Acts' lists and takes every + amount from the Acts or the sources below, never from the model's + parameters. It checks each benefit unit's and person's payment the same way. -3. Monotonicity: in any year, adding a benefit unit to a household, or a - person to one of its benefit units, never lowers the household's payment. - -Each example builds one simulation of up to eight households. +3. Monotonicity: in 2022 and in 2023, adding a qualifying benefit unit to a + household raises its payment by that unit's own payments, and adding a + person with a qualifying disability benefit to one of its units raises it + by £150, so neither ever lowers it. + +Each test builds one simulation per example: up to eight households, or up +to sixteen for the monotonicity test, which puts each household beside its +grown copy. """ import numpy as np @@ -48,7 +54,8 @@ ] # Section 1(2) of each Act: the tax credits. TAX_CREDITS = ["child_tax_credit", "working_tax_credit"] -# On neither list; the households vary in it all the same. +# On neither list; the strategies still draw it, so units on Housing Benefit +# alone occur. UNLISTED_BENEFITS = ["housing_benefit"] BENEFIT_UNIT_INPUTS = LISTED_BENEFITS + TAX_CREDITS + UNLISTED_BENEFITS # Section 5(2) of each Act: the disability benefits the model has variables @@ -62,10 +69,14 @@ # Section 1(1) and (2): £326 and £324 under the 2022 Act, and £301, £300 and # £299 under the 2023 Act. MEANS_TESTED_AMOUNT = {2022: 326 + 324, 2023: 301 + 300 + 299} -# 2022 Act section 2(2). The 2023 Act sets no minimum (section 3(1)). +# 2022 Act sections 2(2) and 4. Parliament set no minimum in the 2023 Act +# (section 3(1)). MINIMUM_TAX_CREDIT_AWARD = {2022: 26, 2023: 0} # Section 5(1) of each Act. DISABILITY_AMOUNT = 150 +# Neither Act sets the pensioner payment. pensioners/amount.yaml takes £300 a +# year from the May 2022 package announcement and DWP's 2023-24 guidance. +PENSIONER_AMOUNT = 300 PAID_YEARS = [2022, 2023] UNPAID_YEARS = [*range(2015, 2022), *range(2024, 2041)] PAYMENTS = [ @@ -141,26 +152,41 @@ def households(draw): } -def populations(years): - return st.fixed_dictionaries( - { - "year": st.sampled_from(years), - "households": st.lists(households(), min_size=1, max_size=8), - } +HOUSEHOLD_LISTS = st.lists(households(), min_size=1, max_size=8) + + +@st.composite +def qualifying_units(draw): + """A benefit unit with a listed benefit, or a tax credit of at least £26, + so that it qualifies in 2022 and in 2023 whatever else it has.""" + benefit_unit = draw(benefit_units()) + name = draw(st.sampled_from(LISTED_BENEFITS + TAX_CREDITS)) + benefit_unit["benefits"][name] = draw( + st.floats(26, 20_000, allow_nan=False, allow_infinity=False).map(float32) ) + return benefit_unit + + +@st.composite +def qualifying_people(draw): + """A person with at least one listed disability benefit.""" + new_person = draw(people()) + new_person[draw(st.sampled_from(DISABILITY_BENEFITS))] = draw(AWARDS) + return new_person + +def person(**benefits): + return {name: float32(benefits.get(name, 0)) for name in DISABILITY_BENEFITS} -def unit(*people, **benefits): - """A benefit unit with the given benefits, and people with the given - disability benefits (one person with none if no people are given).""" + +def unit(*members, **benefits): + """A benefit unit with these benefits and members: one member with no + disability benefit when the call names none.""" return { "benefits": { name: float32(benefits.get(name, 0)) for name in BENEFIT_UNIT_INPUTS }, - "people": [ - {name: float32(person.get(name, 0)) for name in DISABILITY_BENEFITS} - for person in (people or ({},)) - ], + "people": list(members) or [person()], } @@ -172,8 +198,8 @@ def unit(*people, **benefits): { "winter_fuel_allowance": 200.0, "units": [ - unit({"attendance_allowance": 3_000}, pension_credit=1_000), - unit({}, {}, child_tax_credit=2_000), + unit(person(attendance_allowance=3_000), pension_credit=1_000), + unit(person(), person(), child_tax_credit=2_000), ], }, {"winter_fuel_allowance": 0.0, "units": [unit(housing_benefit=3_000)]}, @@ -193,39 +219,52 @@ def unit(*people, **benefits): }, { "winter_fuel_allowance": 0.0, - "units": [unit({"pip": 4_000}, {"pip": 2_000})], + "units": [unit(person(pip=4_000), person(pip=2_000))], }, ] +# For each pinned household: whether it gains a unit, the unit, the person a +# unit gains otherwise, and which unit gains the person. The first household +# already has two qualifying units and gains a third. +PINNED_ADDITIONS = [ + (True, unit(universal_credit=1_000), person(pip=1_000), 0), + (False, unit(universal_credit=1_000), person(dla=500), 0), + (True, unit(working_tax_credit=26), person(pip=1_000), 0), + (True, unit(child_tax_credit=26), person(pip=1_000), 0), + (False, unit(universal_credit=1_000), person(attendance_allowance=3_000), 0), + (False, unit(universal_credit=1_000), person(pip=1_000), 0), + (True, unit(pension_credit=1_000), person(pip=1_000), 0), + (True, unit(pension_credit=1_000), person(pip=1_000), 0), +] -def pinned(year): - return {"year": year, "households": PINNED_HOUSEHOLDS} +def situation(households_, years): + """The households, with every input set to the same value in each year.""" + def each_year(value): + return {year: value for year in years} -def situation(population): - year = population["year"] - people_, benunits, households_ = {}, {}, {} - for h, household in enumerate(population["households"]): + people_, benunits, households_by_name = {}, {}, {} + for h, household in enumerate(households_): members = [] for u, benefit_unit in enumerate(household["units"]): unit_members = [] - for p, person in enumerate(benefit_unit["people"]): + for p, member in enumerate(benefit_unit["people"]): name = f"h{h}_u{u}_p{p}" - people_[name] = {key: {year: value} for key, value in person.items()} + people_[name] = {key: each_year(value) for key, value in member.items()} unit_members.append(name) benunits[f"h{h}_u{u}"] = { "members": unit_members, **{ - key: {year: value} + key: each_year(value) for key, value in benefit_unit["benefits"].items() }, } members += unit_members - households_[f"h{h}"] = { + households_by_name[f"h{h}"] = { "members": members, - "winter_fuel_allowance": {year: household["winter_fuel_allowance"]}, + "winter_fuel_allowance": each_year(household["winter_fuel_allowance"]), } - return {"people": people_, "benunits": benunits, "households": households_} + return {"people": people_, "benunits": benunits, "households": households_by_name} @pytest.fixture(scope="module") @@ -233,18 +272,18 @@ def template(): return Simulation(situation={"people": {"template": {}}}) -def simulate(template, population): - # These properties never reform parameters or variable definitions, so - # each example rebuilds its population on the template's system. +def simulate(template, households_, years): + # No test here reforms parameters or variable definitions, so simulate() + # builds each example's population on the template's tax-benefit system. simulation = template.clone(clone_tax_benefit_system=False) - simulation.build_from_situation(situation(population)) + simulation.build_from_situation(situation(households_, years)) simulation.input_variables = simulation.get_known_variables() simulation.calculated_periods = [] return simulation -def calculate(simulation, population, variable): - return np.asarray(simulation.calculate(variable, population["year"]), dtype=float) +def calculate(simulation, variable, year): + return np.asarray(simulation.calculate(variable, year), dtype=float) def unit_qualifies(benefit_unit, year): @@ -256,99 +295,123 @@ def unit_qualifies(benefit_unit, year): return any(benefits[name] > 0 and benefits[name] >= minimum for name in TAX_CREDITS) -def person_qualifies(person): +def person_qualifies(member): """Section 5(1) and (2).""" - return any(person[name] > 0 for name in DISABILITY_BENEFITS) + return any(member[name] > 0 for name in DISABILITY_BENEFITS) -def pensioner_amount(template, year): - parameters = template.tax_benefit_system.parameters(f"{year}-01-01") - return parameters.gov.treasury.cost_of_living_support.pensioners.amount +def unit_payments(benefit_unit, year): + """A unit's means-tested payment and its members' disability payments.""" + return MEANS_TESTED_AMOUNT[year] * unit_qualifies( + benefit_unit, year + ) + DISABILITY_AMOUNT * sum(person_qualifies(p) for p in benefit_unit["people"]) + + +def household_payment(household, year): + return sum(unit_payments(u, year) for u in household["units"]) + ( + PENSIONER_AMOUNT * (household["winter_fuel_allowance"] > 0) + ) @SETTINGS -@given(populations(UNPAID_YEARS)) -@example(pinned(2021)) -@example(pinned(2024)) -def test_no_household_payment_before_2022_or_from_2024(template, population): - simulation = simulate(template, population) - payment = calculate(simulation, population, "cost_of_living_support_payment") - assert np.all(payment == 0), payment +@given(HOUSEHOLD_LISTS) +@example(PINNED_HOUSEHOLDS) +def test_no_household_payment_before_2022_or_from_2024(template, households_): + simulation = simulate(template, households_, UNPAID_YEARS) + for year in UNPAID_YEARS: + payment = calculate(simulation, PAYMENTS[0], year) + assert np.all(payment == 0), (year, payment) @SETTINGS -@given(populations(UNPAID_YEARS)) -@example(pinned(2021)) -def test_no_unit_or_person_payment_before_2022_or_from_2024(template, population): - simulation = simulate(template, population) - for variable in PAYMENTS[1:]: - payment = calculate(simulation, population, variable) - assert np.all(payment == 0), (variable, payment) +@given(HOUSEHOLD_LISTS) +@example(PINNED_HOUSEHOLDS) +def test_no_unit_or_person_payment_before_2022_or_from_2024(template, households_): + simulation = simulate(template, households_, UNPAID_YEARS) + for year in UNPAID_YEARS: + for variable in PAYMENTS[1:]: + payment = calculate(simulation, variable, year) + assert np.all(payment == 0), (year, variable, payment) @SETTINGS -@given(populations(PAID_YEARS)) -@example(pinned(2022)) -@example(pinned(2023)) -def test_household_payment_counts_each_qualifying_unit_and_person(template, population): - year = population["year"] - expected = [ - MEANS_TESTED_AMOUNT[year] - * sum(unit_qualifies(u, year) for u in household["units"]) - + DISABILITY_AMOUNT - * sum(person_qualifies(p) for u in household["units"] for p in u["people"]) - + pensioner_amount(template, year) * (household["winter_fuel_allowance"] > 0) - for household in population["households"] - ] - simulation = simulate(template, population) - payment = calculate(simulation, population, "cost_of_living_support_payment") - np.testing.assert_allclose(payment, expected, rtol=0, atol=TOLERANCE) +@given(HOUSEHOLD_LISTS) +@example(PINNED_HOUSEHOLDS) +def test_household_payment_counts_each_qualifying_unit_and_person( + template, households_ +): + simulation = simulate(template, households_, PAID_YEARS) + for year in PAID_YEARS: + np.testing.assert_allclose( + calculate(simulation, PAYMENTS[0], year), + [household_payment(household, year) for household in households_], + rtol=0, + atol=TOLERANCE, + err_msg=str(year), + ) @SETTINGS -@given(populations(PAID_YEARS)) -@example(pinned(2022)) -@example(pinned(2023)) -def test_each_unit_and_person_gets_its_own_payment(template, population): - year = population["year"] - units = [u for household in population["households"] for u in household["units"]] - simulation = simulate(template, population) - np.testing.assert_array_equal( - calculate(simulation, population, "cost_of_living_means_tested_payment"), - [MEANS_TESTED_AMOUNT[year] * unit_qualifies(u, year) for u in units], - ) - np.testing.assert_array_equal( - calculate(simulation, population, "cost_of_living_disability_payment"), - [DISABILITY_AMOUNT * person_qualifies(p) for u in units for p in u["people"]], - ) +@given(HOUSEHOLD_LISTS) +@example(PINNED_HOUSEHOLDS) +def test_each_unit_and_person_gets_its_own_payment(template, households_): + simulation = simulate(template, households_, PAID_YEARS) + units = [u for household in households_ for u in household["units"]] + for year in PAID_YEARS: + np.testing.assert_array_equal( + calculate(simulation, PAYMENTS[1], year), + [MEANS_TESTED_AMOUNT[year] * unit_qualifies(u, year) for u in units], + err_msg=str(year), + ) + np.testing.assert_array_equal( + calculate(simulation, PAYMENTS[2], year), + [ + DISABILITY_AMOUNT * person_qualifies(p) + for u in units + for p in u["people"] + ], + err_msg=str(year), + ) @SETTINGS @given( - population=populations(PAID_YEARS + UNPAID_YEARS), + households_=HOUSEHOLD_LISTS, additions=st.lists( - st.tuples(st.booleans(), benefit_units(), st.integers(0, 2)), + st.tuples( + st.booleans(), qualifying_units(), qualifying_people(), st.integers(0, 2) + ), min_size=8, max_size=8, ), ) -def test_adding_a_unit_or_person_never_lowers_the_payment( - template, population, additions +@example(households_=PINNED_HOUSEHOLDS, additions=PINNED_ADDITIONS) +def test_adding_a_qualifying_unit_or_person_never_lowers_the_payment( + template, households_, additions ): - """Each household gains a benefit unit, or one of its units gains a - person, drawn like any other.""" - grown = [] - for household, (add_unit, new_unit, index) in zip( - population["households"], additions + """Each household gains a qualifying benefit unit, or one of its units + gains a person with a qualifying disability benefit.""" + grown, rises = [], {year: [] for year in PAID_YEARS} + for household, (add_unit, new_unit, new_person, index) in zip( + households_, additions ): units = [dict(u, people=list(u["people"])) for u in household["units"]] if add_unit: units.append(new_unit) else: - units[index % len(units)]["people"].append(new_unit["people"][0]) + units[index % len(units)]["people"].append(new_person) + for year in PAID_YEARS: + rises[year].append( + unit_payments(new_unit, year) if add_unit else DISABILITY_AMOUNT + ) grown.append(dict(household, units=units)) - payment = "cost_of_living_support_payment" - before = calculate(simulate(template, population), population, payment) - grown_population = dict(population, households=grown) - after = calculate(simulate(template, grown_population), grown_population, payment) - assert np.all(after >= before - TOLERANCE), (before, after) + # One simulation holds the households and, after them, their grown copies. + simulation = simulate(template, households_ + grown, PAID_YEARS) + count = len(households_) + for year in PAID_YEARS: + payment = calculate(simulation, PAYMENTS[0], year) + rise = payment[count:] - payment[:count] + assert np.all(rise >= -TOLERANCE), (year, rise) + np.testing.assert_allclose( + rise, rises[year], rtol=0, atol=TOLERANCE, err_msg=str(year) + ) diff --git a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_means_tested_payment.py b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_means_tested_payment.py index 153ca9cfbc..1c14b921dd 100644 --- a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_means_tested_payment.py +++ b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_means_tested_payment.py @@ -9,9 +9,9 @@ class cost_of_living_means_tested_payment(Variable): "2023 a person means an individual or a couple, so each benefit unit " "qualifies on its own. The Secretary of State pays a benefit unit " "with a qualifying benefit, and HMRC pays one with a qualifying tax " - "credit and no qualifying benefit. In 2022-23 HMRC pays the tax " - "credit route only where the yearly award of either credit reaches " - "the minimum award." + "credit and no qualifying benefit. In 2022-23 HMRC pays a benefit " + "unit on tax credits alone only where its yearly award of either " + "credit reaches minimum_tax_credit_award." ) entity = BenUnit definition_period = YEAR @@ -20,6 +20,7 @@ class cost_of_living_means_tested_payment(Variable): reference = [ "https://www.legislation.gov.uk/ukpga/2022/38/section/1", "https://www.legislation.gov.uk/ukpga/2022/38/section/2", + "https://www.legislation.gov.uk/ukpga/2022/38/section/4", "https://www.legislation.gov.uk/ukpga/2023/7/section/1", "https://www.legislation.gov.uk/ukpga/2023/7/section/3", ] diff --git a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py index a905411c24..ca03083e1a 100644 --- a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py +++ b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py @@ -5,9 +5,9 @@ class cost_of_living_support_payment(Variable): label = "Cost-of-living support payment" documentation = ( "The household's Cost of Living Payments in the year: the " - "means-tested payment to each of its benefit units, the disability " - "payment to each of its members and the pensioner payment, once per " - "household with a Winter Fuel Payment." + "means-tested payment to each of its qualifying benefit units, the " + "disability payment to each of its qualifying members, and the " + "pensioner payment once if the household has a Winter Fuel Payment." ) entity = Household definition_period = YEAR From 461b933ca2eb24fa69b4888b4e091d9f24efa02c Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 3 Nov 2026 09:04:51 -0500 Subject: [PATCH 3/4] Cover Working Tax Credit alone and correct four descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a YAML case for a benefit unit on £26 of Working Tax Credit alone, which gets the £650 means-tested payment under sections 1(2) and 2(2) of the 2022 Act. Name the mobility supplement as section 5(2)(i) of each Act lists it, say that the formula pays the pensioner top-up once to each household with a Winter Fuel Payment, and give the 2022 Act's second qualifying day as section 1(4) sets it. Co-Authored-By: Claude Opus 5.5 --- .../gov/treasury/cost-of-living-payments.md | 2 +- .../disabled/qualifying_benefits.yaml | 2 +- .../pensioners/amount.yaml | 2 +- policyengine_uk/programs.yaml | 2 +- .../cost_of_living_support_payment.yaml | 44 +++++++++++++++---- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/docs/book/programs/gov/treasury/cost-of-living-payments.md b/docs/book/programs/gov/treasury/cost-of-living-payments.md index 2bac3b479f..6985d54000 100644 --- a/docs/book/programs/gov/treasury/cost-of-living-payments.md +++ b/docs/book/programs/gov/treasury/cost-of-living-payments.md @@ -163,7 +163,7 @@ credit over the year rather than in the month ending with each qualifying day, and compares each tax credit's yearly award with the £26 minimum. It has no variables for the other disability benefits that Parliament listed in section 5(2) (constant attendance allowance, Adult Disability Payment, Child Disability -Payment and the war pension mobility supplement), so it pays no disability +Payment and the mobility supplement), so it pays no disability payment to someone who gets only those. ## References diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml index addf7ef4a4..c1324c31a8 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/disabled/qualifying_benefits.yaml @@ -1,4 +1,4 @@ -description: Disability benefits that qualify a person for the Disability Cost of Living Payment. The list follows section 5(2) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023. The model has no variables for the other benefits Parliament listed there (constant attendance allowance, Adult Disability Payment, Child Disability Payment and the war pension mobility supplement), so it pays nobody who gets only those. +description: Disability benefits that qualify a person for the Disability Cost of Living Payment. The list follows section 5(2) of the Social Security (Additional Payments) Act 2022 and of the Social Security (Additional Payments) Act 2023. The model has no variables for the other benefits Parliament listed there (constant attendance allowance, Adult Disability Payment, Child Disability Payment and the mobility supplement), so it pays nobody who gets only those. metadata: economy: false label: Qualifying benefits for support for disabled households diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml index 90d80d18d9..61f4ace446 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml @@ -1,4 +1,4 @@ -description: One-off Pensioner Cost-of-Living Payment, a £300 top-up to the Winter Fuel Payment for households with someone of State Pension age in winter 2022-23 and winter 2023-24. The amount reads zero before 2022 and from 2024. +description: One-off Pensioner Cost-of-Living Payment, a £300 top-up to the Winter Fuel Payment, which the formula pays once to each household with a Winter Fuel Payment in 2022-23 and 2023-24. The amount reads zero before 2022 and from 2024. values: 0001-01-01: 0 2022-01-01: 300 diff --git a/policyengine_uk/programs.yaml b/policyengine_uk/programs.yaml index 66676544c6..71da288265 100644 --- a/policyengine_uk/programs.yaml +++ b/policyengine_uk/programs.yaml @@ -611,7 +611,7 @@ programs: a Winter Fuel Payment. It tests receipt over the year, not in the month ending with each qualifying day, and has no variables for constant attendance allowance, Adult Disability Payment, Child Disability - Payment or the war pension mobility supplement. + Payment or the mobility supplement. - id: energy_bills_rebate name: Energy Bills Rebate diff --git a/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml b/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml index 2f616be305..575ca9a72a 100644 --- a/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/treasury/cost_of_living_support/cost_of_living_support_payment.yaml @@ -67,14 +67,15 @@ # for a working-age adult with no income and Pension Credit for a pensioner # with none. Each means-tested and disability amount comes from the Social # Security (Additional Payments) Acts 2022 and 2023. Under the 2022 Act the -# Secretary of State and HMRC pay £326 and £324 for qualifying days from 25 -# May 2022 to 31 October 2022 (section 1(1), (2) and (4)), £650 in all, which -# the model pays in model year 2022 (6 April 2022 to 5 April 2023). Under the -# 2023 Act they pay £301, £300 and £299 (section 1(1) and (2)), £900 in all, -# which the model pays in model year 2023. Under section 5(1) of each Act the -# Secretary of State pays £150 to each individual with a listed disability -# benefit. Neither Act covers the £300 pensioner payment: pensioners/amount.yaml -# takes it from the May 2022 package announcement and DWP's 2023-24 guidance. +# Secretary of State and HMRC pay £326 for 25 May 2022 and £324 for a second +# qualifying day no later than 31 October 2022 (section 1(1), (2) and (4)), +# £650 in all, which the model pays in model year 2022 (6 April 2022 to 5 April +# 2023). Under the 2023 Act they pay £301, £300 and £299 (section 1(1) and +# (2)), £900 in all, which the model pays in model year 2023. Under section +# 5(1) of each Act the Secretary of State pays £150 to each individual with a +# listed disability benefit. Neither Act covers the £300 pensioner payment: +# pensioners/amount.yaml takes it from the May 2022 package announcement and +# DWP's 2023-24 guidance. - name: 2021 a household qualifying for every strand gets no Cost of Living Payment # Model year 2021 runs from 6 April 2021 to 5 April 2022, before the 2022 @@ -309,6 +310,33 @@ cost_of_living_means_tested_payment: 0 cost_of_living_support_payment: 0 +- name: 2022 a benefit unit on £26 of Working Tax Credit alone gets the means-tested payment + # A yearly award of £26 meets section 2(2)'s "at least £26" for 2022-23, and + # the unit has no listed benefit, so HMRC pays £326 + £324 = £650 + # (section 1(2)). + period: 2022 + input: + people: + worker: + age: 30 + benunits: + worker_unit: + members: [worker] + universal_credit: 0 + pension_credit: 0 + jsa_income: 0 + esa_income: 0 + income_support: 0 + child_tax_credit: 0 + working_tax_credit: 26 + households: + household: + members: [worker] + winter_fuel_allowance: 0 + output: + cost_of_living_means_tested_payment: 650 + cost_of_living_support_payment: 650 + - name: 2023 a benefit unit on a small Child Tax Credit award alone gets the means-tested payment # Parliament set no minimum award in section 3(1) of the 2023 Act: any # payment of the credit counts. With no listed benefit, HMRC pays £301 + From 90e8418cb883db9a90527dc8e5f76183d31478eb Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 3 Nov 2026 13:07:13 -0500 Subject: [PATCH 4/4] Link the live pensioner Cost of Living Payment guidance GOV.UK returns 404 for the guidance page cost-of-living-payment-pensioner. The variable's reference and the pensioner amount parameter's reference now open the pensioner section of DWP's cost-of-living payment guidance. Co-Authored-By: Claude Opus 5.5 --- .../gov/treasury/cost_of_living_support/pensioners/amount.yaml | 2 +- .../cost_of_living_support/cost_of_living_support_payment.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml index 61f4ace446..a2af623fcb 100644 --- a/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml +++ b/policyengine_uk/parameters/gov/treasury/cost_of_living_support/pensioners/amount.yaml @@ -12,4 +12,4 @@ metadata: - title: 2022-23 Cost-of-Living Support package announcement (HMT/DWP, May 2022) href: https://www.gov.uk/government/news/millions-of-most-vulnerable-households-will-receive-1200-of-help-with-cost-of-living - title: Pensioner Cost-of-Living Payment 2023-24 (DWP guidance) - href: https://www.gov.uk/guidance/cost-of-living-payment-pensioner + href: https://www.gov.uk/guidance/cost-of-living-payment#pensioner-cost-of-living-payment diff --git a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py index ca03083e1a..5e32dfeb57 100644 --- a/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py +++ b/policyengine_uk/variables/gov/treasury/cost_of_living_support/cost_of_living_support_payment.py @@ -18,7 +18,7 @@ class cost_of_living_support_payment(Variable): "https://www.legislation.gov.uk/ukpga/2022/38/section/5", "https://www.legislation.gov.uk/ukpga/2023/7/section/1", "https://www.legislation.gov.uk/ukpga/2023/7/section/5", - "https://www.gov.uk/guidance/cost-of-living-payment-pensioner", + "https://www.gov.uk/guidance/cost-of-living-payment#pensioner-cost-of-living-payment", ] def formula(household, period, parameters):