diff --git a/changelog.d/hb-pension-age-allowance-cohorts.fixed.md b/changelog.d/hb-pension-age-allowance-cohorts.fixed.md new file mode 100644 index 000000000..d74617015 --- /dev/null +++ b/changelog.d/hb-pension-age-allowance-cohorts.fixed.md @@ -0,0 +1 @@ +Give pension-age Housing Benefit claimants who attained State Pension age on or after 1 April 2021 (and couples who both did) the lower personal allowance in SI 2006/214 Sch 3 para 1(1)(c) and (2)(c), £238.00 and £363.25 a week in 2026-27, instead of the £256.00 and £383.35 kept by earlier cohorts. England's pensioner Council Tax Reduction applies the same split (SI 2012/2885 Sch 2 para 1); Scotland and Wales keep one rate. Adds `state_pension_age_date`, the day each person attains State Pension age. diff --git a/docs/book/programs/gov/dwp/housing-benefit.ipynb b/docs/book/programs/gov/dwp/housing-benefit.ipynb index 4f928b173..4c4606ea7 100644 --- a/docs/book/programs/gov/dwp/housing-benefit.ipynb +++ b/docs/book/programs/gov/dwp/housing-benefit.ipynb @@ -53,7 +53,11 @@ "source": [ "## Personal allowances\n", "\n", - "The applicable amount uses age- and household-composition bands. The chart below shows how the weekly allowances have evolved." + "The applicable amount uses age- and household-composition bands. The chart below shows how the weekly allowances have evolved.\n", + "\n", + "Since 1 April 2021 the pension-age allowances depend on when members of the benunit attained State Pension age ([SI 2006/214 Sch. 3 para. 1](https://www.legislation.gov.uk/uksi/2006/214/schedule/3), as amended by [SI 2021/188](https://www.legislation.gov.uk/uksi/2021/188/regulation/2/made); Northern Ireland: [SR 2006/406 Sch. 4 para. 1](https://www.legislation.gov.uk/nisr/2006/406/schedule/4)). A single claimant or lone parent who attained it before 1 April 2021, or a couple in which either member did, keeps the higher allowance (`aged`, £256.00 single and £383.35 couple a week in 2026-27). Where every member attained it on or after that date, the lower allowance applies (`aged_from_cutoff`, £238.00 and £363.25). `housing_benefit_attained_pension_age_before_cutoff` compares each member's `state_pension_age_date`, the day set by their date of birth under the Pensions Act 1995 timetable, with `pension_age_cutoff`. The regulations do not settle a couple in which one member has not yet reached State Pension age and the other reached it after the cutoff; PolicyEngine gives it the lower allowance, following the explanatory note to SI 2021/188.\n", + "\n", + "Council Tax Reduction reuses these allowances. England's pensioner scheme has the same split and amounts ([SI 2012/2885 Sch. 2 para. 1](https://www.legislation.gov.uk/uksi/2012/2885/schedule/2), as amended by [SI 2021/29](https://www.legislation.gov.uk/uksi/2021/29/contents/made)). The Scottish ([SSI 2012/319 Sch. 1 para. 2](https://www.legislation.gov.uk/ssi/2012/319/schedule/1)) and Welsh ([SI 2013/3029 Sch. 2 para. 1](https://www.legislation.gov.uk/wsi/2013/3029/schedule/2)) schemes keep one pension-age rate, the higher one." ] }, { @@ -81,16 +85,18 @@ "params = {\n", " \"Single (younger)\": allowances.single.younger,\n", " \"Single (older)\": allowances.single.older,\n", - " \"Single (aged)\": allowances.single.aged,\n", + " \"Single (pension age)\": allowances.single.aged,\n", + " \"Single (pension age, reached from April 2021)\": allowances.single.aged_from_cutoff,\n", " \"Lone parent (younger)\": allowances.lone_parent.younger,\n", " \"Lone parent (older)\": allowances.lone_parent.older,\n", - " \"Lone parent (aged)\": allowances.lone_parent.aged,\n", + " \"Lone parent (pension age)\": allowances.lone_parent.aged,\n", " \"Couple (younger)\": allowances.couple.younger,\n", " \"Couple (older)\": allowances.couple.older,\n", - " \"Couple (aged)\": allowances.couple.aged,\n", + " \"Couple (pension age)\": allowances.couple.aged,\n", + " \"Couple (pension age, both reached from April 2021)\": allowances.couple.aged_from_cutoff,\n", "}\n", "\n", - "dates = [f\"{y}-04-01\" for y in range(2016, 2026)]\n", + "dates = [f\"{y}-04-01\" for y in range(2016, 2027)]\n", "rows = [\n", " {\"date\": d, \"composition\": name, \"weekly allowance\": p(d)}\n", " for d in dates\n", diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/aged_from_cutoff.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/aged_from_cutoff.yaml new file mode 100644 index 000000000..9a36d00ec --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/aged_from_cutoff.yaml @@ -0,0 +1,30 @@ +description: Personal allowance for Housing Benefit for a couple where both members attained State Pension age on or after the pension-age cutoff (1 April 2021). +values: + 2021-04-01: 270.3 + 2022-04-01: 278.7 + 2023-04-01: 306.85 + 2024-04-01: 332.95 + 2025-04-01: 346.6 + 2026-04-01: 363.25 +metadata: + period: week + unit: currency-GBP + label: Housing Benefit couple personal allowance, State Pension age reached from April 2021 + uprating: gov.benefit_uprating_cpi + reference: + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) (Amendment) Regulations 2021 (SI 2021/188), regulation 2(3), inserting paragraph 1(2)(c) of Schedule 3 to SI 2006/214 from 1 April 2021 + href: https://www.legislation.gov.uk/uksi/2021/188/regulation/2/made + - title: SI 2006/214, Schedule 3, paragraph 1(2)(c), as in force on 2022-04-11 (set by the Social Security Benefits Up-rating Order 2022, SI 2022/292) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2022-04-11 + - title: SI 2006/214, Schedule 3, paragraph 1(2)(c), as in force on 2023-04-10 (set by the Social Security Benefits Up-rating Order 2023, SI 2023/316) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2023-04-10 + - title: SI 2006/214, Schedule 3, paragraph 1(2)(c), as in force on 2024-04-08 (set by the Social Security Benefits Up-rating Order 2024, SI 2024/242) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2024-04-08 + - title: SI 2006/214, Schedule 3, paragraph 1(2)(c), as in force on 2025-04-07 (set by the Social Security Benefits Up-rating Order 2025, SI 2025/295) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2025-04-07 + - title: SI 2006/214, Schedule 3, paragraph 1(2)(c), as substituted from April 2026 by the Social Security Benefits Up-rating Order 2026 (SI 2026/148), Schedule 6 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations (Northern Ireland) 2006 (SR 2006/406), Schedule 4, paragraph 1 (the same amounts) + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/4 + - title: Benefit and pension rates 2026 to 2027 (2025-26 and 2026-27 rates) + href: https://www.gov.uk/government/publications/benefit-and-pension-rates-2026-to-2027/proposed-benefit-and-pension-rates-2026-to-2027 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/aged_from_cutoff.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/aged_from_cutoff.yaml new file mode 100644 index 000000000..17e5e79a2 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/aged_from_cutoff.yaml @@ -0,0 +1,30 @@ +description: Personal allowance for Housing Benefit for a lone parent who attained State Pension age on or after the pension-age cutoff (1 April 2021). +values: + 2021-04-01: 177.1 + 2022-04-01: 182.6 + 2023-04-01: 201.05 + 2024-04-01: 218.15 + 2025-04-01: 227.1 + 2026-04-01: 238 +metadata: + period: week + unit: currency-GBP + label: Housing Benefit lone parent personal allowance, State Pension age reached from April 2021 + uprating: gov.benefit_uprating_cpi + reference: + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) (Amendment) Regulations 2021 (SI 2021/188), regulation 2(3), inserting paragraph 1(1)(c) of Schedule 3 to SI 2006/214 from 1 April 2021 + href: https://www.legislation.gov.uk/uksi/2021/188/regulation/2/made + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as in force on 2022-04-11 (set by the Social Security Benefits Up-rating Order 2022, SI 2022/292) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2022-04-11 + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as in force on 2023-04-10 (set by the Social Security Benefits Up-rating Order 2023, SI 2023/316) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2023-04-10 + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as in force on 2024-04-08 (set by the Social Security Benefits Up-rating Order 2024, SI 2024/242) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2024-04-08 + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as in force on 2025-04-07 (set by the Social Security Benefits Up-rating Order 2025, SI 2025/295) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2025-04-07 + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as substituted from April 2026 by the Social Security Benefits Up-rating Order 2026 (SI 2026/148), Schedule 6 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations (Northern Ireland) 2006 (SR 2006/406), Schedule 4, paragraph 1 (the same amounts) + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/4 + - title: Benefit and pension rates 2026 to 2027 (2025-26 and 2026-27 rates) + href: https://www.gov.uk/government/publications/benefit-and-pension-rates-2026-to-2027/proposed-benefit-and-pension-rates-2026-to-2027 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/pension_age_cutoff.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/pension_age_cutoff.yaml new file mode 100644 index 000000000..990ae7995 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/pension_age_cutoff.yaml @@ -0,0 +1,13 @@ +description: Since April 2021, pension-age Housing Benefit personal allowances depend on when members of the benefit unit attained State Pension age. The higher allowances apply if any member attained it before this date, written as a YYYYMMDD number; the lower allowances apply if every member attained it on or after this date. +values: + 2021-04-01: 20210401 +metadata: + unit: date + label: Housing Benefit pension-age personal allowance cutoff + reference: + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) (Amendment) Regulations 2021 (SI 2021/188), regulation 2 + href: https://www.legislation.gov.uk/uksi/2021/188/regulation/2/made + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 (SI 2006/214), Schedule 3, paragraph 1 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations (Northern Ireland) 2006 (SR 2006/406), Schedule 4, paragraph 1 + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/4 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/aged_from_cutoff.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/aged_from_cutoff.yaml new file mode 100644 index 000000000..5c446ef80 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/aged_from_cutoff.yaml @@ -0,0 +1,30 @@ +description: Personal allowance for Housing Benefit for a single claimant who attained State Pension age on or after the pension-age cutoff (1 April 2021). +values: + 2021-04-01: 177.1 + 2022-04-01: 182.6 + 2023-04-01: 201.05 + 2024-04-01: 218.15 + 2025-04-01: 227.1 + 2026-04-01: 238 +metadata: + period: week + unit: currency-GBP + label: Housing Benefit single personal allowance, State Pension age reached from April 2021 + uprating: gov.benefit_uprating_cpi + reference: + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) (Amendment) Regulations 2021 (SI 2021/188), regulation 2(3), inserting paragraph 1(1)(c) of Schedule 3 to SI 2006/214 from 1 April 2021 + href: https://www.legislation.gov.uk/uksi/2021/188/regulation/2/made + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as in force on 2022-04-11 (set by the Social Security Benefits Up-rating Order 2022, SI 2022/292) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2022-04-11 + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as in force on 2023-04-10 (set by the Social Security Benefits Up-rating Order 2023, SI 2023/316) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2023-04-10 + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as in force on 2024-04-08 (set by the Social Security Benefits Up-rating Order 2024, SI 2024/242) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2024-04-08 + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as in force on 2025-04-07 (set by the Social Security Benefits Up-rating Order 2025, SI 2025/295) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2025-04-07 + - title: SI 2006/214, Schedule 3, paragraph 1(1)(c), as substituted from April 2026 by the Social Security Benefits Up-rating Order 2026 (SI 2026/148), Schedule 6 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations (Northern Ireland) 2006 (SR 2006/406), Schedule 4, paragraph 1 (the same amounts) + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/4 + - title: Benefit and pension rates 2026 to 2027 (2025-26 and 2026-27 rates) + href: https://www.gov.uk/government/publications/benefit-and-pension-rates-2026-to-2027/proposed-benefit-and-pension-rates-2026-to-2027 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_pension_age_personal_allowance.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_pension_age_personal_allowance.yaml new file mode 100644 index 000000000..3a3cacfff --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_pension_age_personal_allowance.yaml @@ -0,0 +1,281 @@ +# Pension-age Housing Benefit personal allowances by when State Pension age was +# attained: SI 2006/214 Sch 3 para 1 (NI: SR 2006/406 Sch 4 para 1), as amended +# by SI 2021/188 from 1 April 2021. Higher rates (1)(b)/(2)(b) where a member +# attained pensionable age before 1 April 2021; lower rates (1)(c)/(2)(c) where +# every member attained it on or after. Amounts are the Up-rating Order rates. +# Each date of birth is placed by age and months_since_last_birthday, both +# measured at 6 October of the fiscal year. + +- name: Single woman who attained State Pension age on 31 March 2021 keeps the higher rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 71 + months_since_last_birthday: 6.19355 + is_male: false + benunits: + benunit: + members: [claimant] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: true + housing_benefit_applicable_amount: 256.00 * 52 # para 1(1)(b), claimant attained 31 March 2021 + +- name: Single man who attained State Pension age on 1 April 2021 gets the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 71 + months_since_last_birthday: 6.1613 + is_male: true + benunits: + benunit: + members: [claimant] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: false + housing_benefit_applicable_amount: 238.00 * 52 # para 1(1)(c), claimant attained 1 April 2021 + +- name: Single person aged 80 gets the higher rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 80 + months_since_last_birthday: 4.1613 + is_male: false + benunits: + benunit: + members: [claimant] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: true + housing_benefit_applicable_amount: 256.00 * 52 # para 1(1)(b), claimant attained 1 June 2006 + +- name: Single person aged 70 gets the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 70 + months_since_last_birthday: 6.0 + is_male: false + benunits: + benunit: + members: [claimant] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: false + housing_benefit_applicable_amount: 238.00 * 52 # para 1(1)(c), claimant attained 6 April 2022 + +- name: In 2021-22, a single person who attained State Pension age on 31 March 2021 gets the higher rate + period: 2021 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 66 + months_since_last_birthday: 6.19355 + is_male: false + benunits: + benunit: + members: [claimant] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: true + housing_benefit_applicable_amount: 191.15 * 52 # para 1(1)(b), claimant attained 31 March 2021 + +- name: In 2021-22, a single person who attained State Pension age on 1 April 2021 gets the lower rate + period: 2021 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 66 + months_since_last_birthday: 6.1613 + is_male: false + benunits: + benunit: + members: [claimant] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: false + housing_benefit_applicable_amount: 177.10 * 52 # para 1(1)(c), claimant attained 1 April 2021 + +- name: Couple where one member attained State Pension age before April 2021 gets the higher rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 80 + months_since_last_birthday: 4.1613 + is_male: true + younger: + age: 70 + months_since_last_birthday: 6.0 + is_male: false + benunits: + benunit: + members: [older, younger] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: true + housing_benefit_applicable_amount: 383.35 * 52 # para 1(2)(b), older attained 1 June 2011, younger attained 6 April 2022 + +- name: Couple where both attained State Pension age after April 2021 gets the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 70 + months_since_last_birthday: 6.0 + is_male: true + younger: + age: 68 + months_since_last_birthday: 9.1613 + is_male: false + benunits: + benunit: + members: [older, younger] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: false + housing_benefit_applicable_amount: 363.25 * 52 # para 1(2)(c), older attained 6 April 2022, younger attained 1 January 2024 + +- name: Couple on either side of the cutoff by one day gets the higher rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 71 + months_since_last_birthday: 6.19355 + is_male: true + younger: + age: 71 + months_since_last_birthday: 6.1613 + is_male: false + benunits: + benunit: + members: [older, younger] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: true + housing_benefit_applicable_amount: 383.35 * 52 # para 1(2)(b), older attained 31 March 2021, younger attained 1 April 2021 + +- name: Mixed-age couple whose older member attained State Pension age after April 2021 gets the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 70 + months_since_last_birthday: 6.0 + is_male: true + younger: + age: 60 + months_since_last_birthday: 9.1613 + is_male: false + benunits: + benunit: + members: [older, younger] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: false + housing_benefit_applicable_amount: 363.25 * 52 # para 1(2)(c), older attained 6 April 2022, younger attained 1 January 2033 + +- name: Mixed-age couple whose older member attained State Pension age before April 2021 gets the higher rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 80 + months_since_last_birthday: 4.1613 + is_male: true + younger: + age: 60 + months_since_last_birthday: 9.1613 + is_male: false + benunits: + benunit: + members: [older, younger] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + housing_benefit_attained_pension_age_before_cutoff: true + housing_benefit_applicable_amount: 383.35 * 52 # para 1(2)(b), older attained 1 June 2011, younger attained 1 January 2033 + +- name: Pension-age lone parent who attained State Pension age after April 2021 gets the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 70 + months_since_last_birthday: 6.0 + is_male: false + grandchild: + age: 12 + benunits: + benunit: + members: [claimant, grandchild] + housing_benefit_eligible: true + benefits_premiums: 0 + output: + is_lone_parent: true + housing_benefit_attained_pension_age_before_cutoff: false + housing_benefit_applicable_amount: 238.00 * 52 # para 1(1)(c) + +- name: Before April 2021 every pension-age unit counts as attaining State Pension age before the cutoff + period: 2020 + input: + people: + claimant: + age: 66 + months_since_last_birthday: 0.0 + is_male: false + benunits: + benunit: + members: [claimant] + output: + housing_benefit_attained_pension_age_before_cutoff: true + +- name: Private renter aged 70 with a £30,000 State Pension is assessed at the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 70 + state_pension_reported: 30_000 + benunits: + benunit: + members: [person] + households: + household: + members: [person] + rent: 9_000 + tenure_type: RENT_PRIVATELY + output: + housing_benefit_attained_pension_age_before_cutoff: false + housing_benefit_applicable_amount: 238 * 52 + housing_benefit: 47.68 # 656.08 at the higher rate: 0.65 x (256 - 238) x 52 = 608.40 more diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/state_pension_age_date.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/state_pension_age_date.yaml new file mode 100644 index 000000000..f9c1f230b --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/state_pension_age_date.yaml @@ -0,0 +1,104 @@ +# The day State Pension age is attained, written as a YYYYMMDD number, at +# boundaries of Pensions Act 1995 Schedule 4 paragraph 1. Age and +# months_since_last_birthday place the date of birth named in each test at +# 6 October of the fiscal year. Expected days come from a day-level reading +# of the statute. + +- name: Woman born 5 April 1950 attains State Pension age on her 60th birthday + period: 2015 + input: + age: 65 + months_since_last_birthday: 6.0323 + is_male: false + output: + state_pension_age_date: 20100405 + +- name: Woman born 6 April 1950 attains it on 6 May 2010 (table 1) + period: 2015 + input: + age: 65 + months_since_last_birthday: 6.0 + is_male: false + output: + state_pension_age_date: 20100506 + +- name: Man born 5 December 1953 attains it on his 65th birthday + period: 2018 + input: + age: 64 + months_since_last_birthday: 10.03333 + is_male: true + output: + state_pension_age_date: 20181205 + +- name: Man born 6 December 1953 attains it on 6 March 2019 (table 2) + period: 2018 + input: + age: 64 + months_since_last_birthday: 10.0 + is_male: true + output: + state_pension_age_date: 20190306 + +- name: Man born 5 October 1954 attains it on 6 September 2020 (table 2) + period: 2020 + input: + age: 66 + months_since_last_birthday: 0.03333 + is_male: true + output: + state_pension_age_date: 20200906 + +- name: Woman born 6 October 1954 attains it on her 66th birthday + period: 2020 + input: + age: 66 + months_since_last_birthday: 0.0 + is_male: false + output: + state_pension_age_date: 20201006 + +- name: Woman born 31 March 1955 attains it on 31 March 2021, before the Housing Benefit cutoff + period: 2026 + input: + age: 71 + months_since_last_birthday: 6.19355 + is_male: false + output: + state_pension_age_date: 20210331 + +- name: Man born 1 April 1955 attains it on 1 April 2021, the Housing Benefit cutoff + period: 2026 + input: + age: 71 + months_since_last_birthday: 6.1613 + is_male: true + output: + state_pension_age_date: 20210401 + +- name: Person born 31 July 1960 attains it on 30 November 2026 (rule 7A) + period: 2026 + input: + age: 66 + months_since_last_birthday: 2.19355 + is_male: false + output: + state_pension_age_date: 20261130 + +- name: Person born 6 March 1961 attains it on their 67th birthday + period: 2028 + input: + age: 67 + months_since_last_birthday: 7.0 + is_male: true + output: + state_pension_age_date: 20280306 + +- name: Person born 6 April 1978 attains it on their 68th birthday + period: 2046 + input: + age: 68 + months_since_last_birthday: 6.0 + is_male: false + output: + state_pension_age_date: 20460406 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_age_personal_allowance.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_age_personal_allowance.yaml new file mode 100644 index 000000000..ae2297838 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_age_personal_allowance.yaml @@ -0,0 +1,157 @@ +# Pension-age Council Tax Reduction personal allowances by country. England's +# prescribed requirements (SI 2012/2885 Sch 2 para 1, amended by SI 2021/29) give +# the lower rates where every member attained State Pension age on or after +# 1 April 2021; the Scottish (SSI 2012/319 Sch 1 para 2) and Welsh (SI 2013/3029 +# Sch 2 para 1) schemes have one pension-age rate. Amounts are for 2026-27. + +- name: In England, a single person who attained State Pension age on 31 March 2021 gets the higher rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 71 + months_since_last_birthday: 6.19355 + is_male: false + benunits: + benunit: + members: [claimant] + benefits_premiums: 0 + households: + household: + members: [claimant] + region: LONDON + output: + council_tax_reduction_applicable_amount: 256.00 * 52 + +- name: In England, a single person who attained State Pension age on 1 April 2021 gets the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 71 + months_since_last_birthday: 6.1613 + is_male: false + benunits: + benunit: + members: [claimant] + benefits_premiums: 0 + households: + household: + members: [claimant] + region: NORTH_EAST + output: + council_tax_reduction_applicable_amount: 238.00 * 52 + +- name: In England, a couple who both attained State Pension age after April 2021 get the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 70 + months_since_last_birthday: 6.0 + is_male: true + younger: + age: 68 + months_since_last_birthday: 9.1613 + is_male: false + benunits: + benunit: + members: [older, younger] + benefits_premiums: 0 + households: + household: + members: [older, younger] + region: SOUTH_WEST + output: + council_tax_reduction_applicable_amount: 363.25 * 52 + +- name: In Scotland, a single person who attained State Pension age on 1 April 2021 keeps the one pension-age rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 71 + months_since_last_birthday: 6.1613 + is_male: false + benunits: + benunit: + members: [claimant] + benefits_premiums: 0 + households: + household: + members: [claimant] + region: SCOTLAND + output: + council_tax_reduction_applicable_amount: 256.00 * 52 + +- name: In Scotland, a couple who both attained State Pension age after April 2021 keep the one pension-age rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 70 + months_since_last_birthday: 6.0 + is_male: true + younger: + age: 68 + months_since_last_birthday: 9.1613 + is_male: false + benunits: + benunit: + members: [older, younger] + benefits_premiums: 0 + households: + household: + members: [older, younger] + region: SCOTLAND + output: + council_tax_reduction_applicable_amount: 383.35 * 52 + +- name: In Wales, a single person who attained State Pension age on 1 April 2021 keeps the one pension-age rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 71 + months_since_last_birthday: 6.1613 + is_male: false + benunits: + benunit: + members: [claimant] + benefits_premiums: 0 + households: + household: + members: [claimant] + region: WALES + output: + council_tax_reduction_applicable_amount: 256.00 * 52 + +- name: In England, a mixed-age couple whose older member attained State Pension age after April 2021 gets the lower rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 70 + months_since_last_birthday: 6.0 + is_male: true + younger: + age: 60 + months_since_last_birthday: 9.1613 + is_male: false + benunits: + benunit: + members: [older, younger] + benefits_premiums: 0 + households: + household: + members: [older, younger] + region: EAST_MIDLANDS + output: + council_tax_reduction_applicable_amount: 363.25 * 52 diff --git a/policyengine_uk/tests/test_housing_benefit_pension_age_cohorts.py b/policyengine_uk/tests/test_housing_benefit_pension_age_cohorts.py new file mode 100644 index 000000000..93979e538 --- /dev/null +++ b/policyengine_uk/tests/test_housing_benefit_pension_age_cohorts.py @@ -0,0 +1,215 @@ +"""Pension-age Housing Benefit personal allowances by when State Pension age +was attained. + +The Housing Benefit (Persons who have attained the qualifying age for state +pension credit) Regulations 2006 (SI 2006/214) Sch 3 para 1, as amended by SI +2021/188 from 1 April 2021 (Northern Ireland: SR 2006/406 Sch 4 para 1): a +single claimant or lone parent who attained pensionable age before 1 April +2021 gets the higher allowance in (1)(b), one who attained it on or after gets +(1)(c); a couple gets (2)(b) where one or both members attained it before, and +(2)(c) where both attained it on or after. + +Invariants, for any pension-age single person or couple in any year: + +1. Differential: the pension-age personal allowance in + housing_benefit_applicable_amount is the higher rate exactly when a member's + attainment day, read from the statute day by day + (test_state_pension_age.reference_attainment_day), is before 1 April 2021, + and the lower rate otherwise. +2. Bounds: the lower rate is below the higher rate in every year, including + uprated years, and lone parents get the single rates. +3. Monotonicity: among pension-age single people of one sex in one year, an + earlier date of birth never gives a lower allowance. +4. Before April 2021 there was one pension-age rate, which every pension-age + unit gets. +5. The lower rates and the cutoff equal the statute's table for every year + 2021-22 to 2026-27 (hard-coded below from legislation.gov.uk). +6. Council Tax Reduction: England's pensioner scheme has the same split and + amounts (SI 2012/2885 Sch 2 para 1, amended by SI 2021/29), so its + allowance equals Housing Benefit's; the Scottish and Welsh schemes have + one pension-age rate, the higher one. +""" + +from datetime import date, timedelta + +import numpy as np +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation +from policyengine_uk.system import system +from test_state_pension_age import grid_months, reference_attainment_day + +CUTOFF = date(2021, 4, 1) +YEARS = list(range(2019, 2031)) +P = system.parameters.gov.dwp.housing_benefit.allowances + + +def rates(year: int, couple: bool) -> tuple: + """(higher, lower) weekly pension-age allowance; lower is None before the + cutoff took effect.""" + node = P.couple if couple else P.single + at = f"{year}-06-01" + return node.aged(at), node.aged_from_cutoff(at) + + +def build(units: list, year: int, region: str = "LONDON") -> Simulation: + """Each unit is a list of (birth, male). Units are eligible with no + premiums, so the applicable amount is 52 times the personal allowance.""" + people, benunits = {}, {} + mid_year = grid_months(date(year, 10, 6)) + for u, members in enumerate(units): + names = [] + for k, (birth, male) in enumerate(members): + age_in_months = mid_year - grid_months(birth) + age = int(age_in_months // 12) + name = f"u{u}p{k}" + people[name] = { + "age": {year: age}, + "months_since_last_birthday": {year: age_in_months - 12 * age}, + "is_male": {year: male}, + } + names.append(name) + benunits[f"u{u}"] = { + "members": names, + "housing_benefit_eligible": {year: True}, + "benefits_premiums": {year: 0}, + } + return Simulation( + situation={ + "people": people, + "benunits": benunits, + "households": {"h": {"members": list(people), "region": {year: region}}}, + } + ) + + +def at_pension_age(members: list, year: int) -> bool: + mid_year = date(year, 10, 6) + return any(reference_attainment_day(b, m) <= mid_year for b, m in members) + + +def expected_allowance(members: list, year: int) -> float: + higher, lower = rates(year, couple=len(members) == 2) + attained = [reference_attainment_day(b, m) for b, m in members] + if lower is None or any(day < CUTOFF for day in attained): + return higher + return lower + + +def check(units: list, year: int) -> np.ndarray: + """Invariant 1 for every unit with a member over State Pension age.""" + amount = build(units, year).calculate("housing_benefit_applicable_amount", year) + weekly = amount / 52 + wrong = [ + (members, weekly[i], expected_allowance(members, year)) + for i, members in enumerate(units) + if at_pension_age(members, year) + and abs(weekly[i] - expected_allowance(members, year)) > 0.005 + ] + assert not wrong, wrong[:10] + return weekly + + +BIRTHS = [date(1938, 1, 1) + timedelta(days=d) for d in range(0, 23 * 366, 5)] +EDGES = [date(1955, 4, 1) + timedelta(days=shift) for shift in range(-3, 4)] + + +@pytest.mark.parametrize("year", YEARS) +def test_single_allowance_matches_statute_for_every_birth_date(year): + """Invariants 1, 3 and 4 for single people born every fifth day from 1938 + and either side of 1 April 1955, the birthday that reaches 66 on the + cutoff.""" + births = sorted(set(BIRTHS) | set(EDGES)) + for male in (True, False): + units = [[(birth, male)] for birth in births] + weekly = check(units, year) + eligible = [weekly[i] for i, u in enumerate(units) if at_pension_age(u, year)] + assert all(a >= b - 1e-6 for a, b in zip(eligible, eligible[1:])) + if year < CUTOFF.year: + assert np.allclose(eligible, rates(year, couple=False)[0]) + + +@pytest.mark.parametrize("year", range(2021, 2041)) +def test_lower_rates_are_below_higher_rates(year): + """Invariant 2, including years uprated past the last published rate.""" + for couple in (False, True): + higher, lower = rates(year, couple) + assert lower < higher + at = f"{year}-06-01" + assert P.lone_parent.aged_from_cutoff(at) == P.single.aged_from_cutoff(at) + + +MEMBER = st.tuples( + st.dates(min_value=date(1930, 1, 1), max_value=date(1962, 12, 31)), + st.booleans(), +) + + +@settings( + max_examples=15, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +@given( + units=st.lists(st.lists(MEMBER, min_size=1, max_size=2), min_size=1, max_size=25), + year=st.sampled_from(YEARS), +) +def test_any_single_or_couple_follows_the_cohort_rule(units, year): + """Invariant 1 for random single people and couples, including couples + where only one member is over State Pension age.""" + check(units, year) + + +@settings( + max_examples=10, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +@given( + units=st.lists(st.lists(MEMBER, min_size=1, max_size=2), min_size=1, max_size=20), + year=st.sampled_from(YEARS), + region=st.sampled_from(["LONDON", "NORTH_WEST", "SCOTLAND", "WALES"]), +) +def test_council_tax_reduction_splits_only_in_england(units, year, region): + """Invariant 6 for random single people and couples.""" + sim = build(units, year, region) + hb = sim.calculate("housing_benefit_applicable_amount", year) / 52 + ctr = sim.calculate("council_tax_reduction_applicable_amount", year) / 52 + for i, members in enumerate(units): + if not at_pension_age(members, year): + continue + if region in ("SCOTLAND", "WALES"): + expected = rates(year, couple=len(members) == 2)[0] + else: + expected = hb[i] + assert abs(ctr[i] - expected) < 0.005, (members, region, ctr[i], expected) + + +# SI 2006/214 Sch 3 para 1(1)(c) and (2)(c), weekly: inserted by SI 2021/188 reg +# 2(3) from 1 April 2021, then set by the Up-rating Orders SI 2022/292, +# 2023/316, 2024/242, 2025/295 and 2026/148 (legislation.gov.uk point-in-time +# texts at 11 April 2022, 10 April 2023, 8 April 2024, 7 April 2025 and the +# current text). +STATUTE_LOWER_RATES = { + 2021: (177.10, 270.30), + 2022: (182.60, 278.70), + 2023: (201.05, 306.85), + 2024: (218.15, 332.95), + 2025: (227.10, 346.60), + 2026: (238.00, 363.25), +} + + +@pytest.mark.parametrize("year", sorted(STATUTE_LOWER_RATES)) +def test_lower_rates_and_cutoff_match_the_statute(year): + """Invariant 5.""" + single, couple = STATUTE_LOWER_RATES[year] + at = f"{year}-06-01" + assert P.single.aged_from_cutoff(at) == pytest.approx(single, abs=1e-6) + assert P.lone_parent.aged_from_cutoff(at) == pytest.approx(single, abs=1e-6) + assert P.couple.aged_from_cutoff(at) == pytest.approx(couple, abs=1e-6) + assert P.pension_age_cutoff(at) == 20210401 diff --git a/policyengine_uk/tests/test_state_pension_age.py b/policyengine_uk/tests/test_state_pension_age.py index 12e8eced7..aab0aaed4 100644 --- a/policyengine_uk/tests/test_state_pension_age.py +++ b/policyengine_uk/tests/test_state_pension_age.py @@ -263,6 +263,18 @@ def test_status_matches_statute_for_every_birth_date(year): assert not mismatches, mismatches[:10] +@pytest.mark.parametrize("year", YEARS) +def test_attainment_date_matches_statute_for_every_birth_date(year): + """state_pension_age_date is the day a day-level reading of the statute + gives, for every birth date in the differential set, and the same day + whichever year the person is placed from.""" + sim, keys = differential_simulation() + model = sim.calculate("state_pension_age_date", year) + expected = np.array([ymd(reference_attainment_day(b, m)) for b, m in keys]) + wrong = np.flatnonzero(model != expected) + assert not len(wrong), [(keys[i], model[i], expected[i]) for i in wrong[:10]] + + def mid_year_share(year: int, age: int, male: bool) -> float: """Share of people aged `age` on 6 October who have attained pensionable age by then, with birthdays spread evenly over the year.""" diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_applicable_amount.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_applicable_amount.py index 50c086675..af23be37f 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_applicable_amount.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_applicable_amount.py @@ -22,20 +22,39 @@ def formula(benunit, period, parameters): single = benunit("is_single_person", period) couple = benunit("is_couple", period) lone_parent = benunit("is_lone_parent", period) + # Pension-age allowances (SI 2006/214 Sch 3 para 1; NI: SR 2006/406 + # Sch 4 para 1). Since 1 April 2021 units whose members all attained + # State Pension age on or after the cutoff get the lower rates in + # sub-paragraphs (1)(c) and (2)(c); the rest keep the higher rates. + if p.pension_age_cutoff is None: + single_aged, couple_aged, lone_parent_aged = ( + p.single.aged, + p.couple.aged, + p.lone_parent.aged, + ) + else: + before_cutoff = benunit( + "housing_benefit_attained_pension_age_before_cutoff", period + ) + single_aged = where(before_cutoff, p.single.aged, p.single.aged_from_cutoff) + couple_aged = where(before_cutoff, p.couple.aged, p.couple.aged_from_cutoff) + lone_parent_aged = where( + before_cutoff, p.lone_parent.aged, p.lone_parent.aged_from_cutoff + ) single_personal_allowance = ( u_25 * p.single.younger + o_25 * p.single.older - + any_over_SP_age * p.single.aged + + any_over_SP_age * single_aged ) couple_personal_allowance = ( u_18 * p.couple.younger + o_18 * p.couple.older - + any_over_SP_age * p.couple.aged + + any_over_SP_age * couple_aged ) lone_parent_personal_allowance = ( u_18 * p.lone_parent.younger + o_18 * p.lone_parent.older - + any_over_SP_age * p.lone_parent.aged + + any_over_SP_age * lone_parent_aged ) personal_allowance = ( single * single_personal_allowance diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_attained_pension_age_before_cutoff.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_attained_pension_age_before_cutoff.py new file mode 100644 index 000000000..6869eac8b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_attained_pension_age_before_cutoff.py @@ -0,0 +1,49 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_attained_pension_age_before_cutoff(Variable): + value_type = bool + entity = BenUnit + label = "a member attained State Pension age before the Housing Benefit cutoff" + documentation = ( + "Whether any member of the benefit unit attained State Pension age " + "before the pension-age cutoff (1 April 2021). Such units keep the " + "higher pension-age personal allowance; units whose members all " + "attained it on or after the cutoff get the lower one. Before the " + "cutoff took effect there was a single pension-age allowance, the " + "higher one, so this is true for every unit then." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2021/188/regulation/2/made", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/4", + ) + + def formula(benunit, period, parameters): + cutoff = parameters( + period + ).gov.dwp.housing_benefit.allowances.pension_age_cutoff + if cutoff is None: + return np.ones(benunit.count, dtype=bool) + # "Pensionable age" is State Pension age under Pensions Act 1995 Sch 4 + # para 1 (SSCBA 1992 s.122(1), applied to these regulations by the + # Interpretation Act 1978 s.11), which state_pension_age_date follows. + # + # Para 1(2)(b) keeps the higher couple rate where "one member or both + # members" attained pensionable age before the cutoff, and (2)(c) gives + # the lower one where "both members" attained it on or after. Neither + # covers a couple where one member has not reached it and the other did + # so after the cutoff. In law that couple cannot be on pension-age + # Housing Benefit: mixed-age couples keep it only under the savings for + # awards from before 15 May 2019 (SI 2019/37 art 4), when the older + # member had already reached it. PolicyEngine can still give such a + # unit pension-age rates through a reported continuing award; it gets + # the lower rate, since the explanatory note to SI 2021/188 keeps the + # uplift only where "one or more members ... attained pensionable age + # before 1st April 2021". + # + # Dates are compared as YYYYMMDD integers, which are exact; as float32 + # they would not be (20210401 would round to 20210400). + attained = benunit.members("state_pension_age_date", period) + return benunit.any(attained < cutoff) diff --git a/policyengine_uk/variables/gov/dwp/state_pension_age.py b/policyengine_uk/variables/gov/dwp/state_pension_age.py index f93a15799..9296e4a9a 100644 --- a/policyengine_uk/variables/gov/dwp/state_pension_age.py +++ b/policyengine_uk/variables/gov/dwp/state_pension_age.py @@ -1,9 +1,7 @@ from policyengine_uk.model_api import * from policyengine_uk.utils.dates import ( - add_months_to_yyyymmdd, exact_age_in_months, grid_month, - grid_months_to_yyyymmdd, yyyymmdd_to_grid_months, ) @@ -26,35 +24,11 @@ class state_pension_age(Variable): ) def formula(person, period, parameters): - p = parameters(period).gov.dwp.state_pension.age # Dates are in months on a grid whose months start on the 6th, so the # middle of the fiscal year (6 October) is a whole month. - mid_year = grid_month(period.start.year, 10) age_in_months = exact_age_in_months( person("age", period), person("months_since_last_birthday", period) ) - birth = mid_year - age_in_months - # The day of birth: the one starting at or after that instant, so the - # person's legal age on 6 October is age. - birth_date = grid_months_to_yyyymmdd(birth) - - # Pensions Act 1995 Sch 4 para 1 rule (1): men born before 6 December - # 1953 attain pensionable age at 65. Everyone else follows the - # timetable in rules (2) to (10), which sets either an age or a day. - male_rule = person("is_male", period) & (birth_date < p.male.born_before) - age_rule = where(male_rule, p.male.age, p.age_by_birth_date.calc(birth_date)) - day_rule = where(male_rule, 0, p.day_by_birth_date.calc(birth_date)) - day_rule_month = where( - day_rule > 0, - yyyymmdd_to_grid_months(np.maximum(day_rule, 10101)), - -np.inf, - ) - # An age of N years and M months is attained at the commencement of - # the anniversary (Family Law Reform Act 1969 s.9(1)): the same day of - # the month, or the month's last day where that day does not exist, - # which also gives the three days in rule (7A). - anniversary = yyyymmdd_to_grid_months( - add_months_to_yyyymmdd(birth_date, age_rule) - ) - attained = np.maximum(anniversary, day_rule_month) + birth = grid_month(period.start.year, 10) - age_in_months + attained = yyyymmdd_to_grid_months(person("state_pension_age_date", period)) return (attained - birth) / 12 diff --git a/policyengine_uk/variables/gov/dwp/state_pension_age_date.py b/policyengine_uk/variables/gov/dwp/state_pension_age_date.py new file mode 100644 index 000000000..1fbe6532a --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/state_pension_age_date.py @@ -0,0 +1,51 @@ +from policyengine_uk.model_api import * +from policyengine_uk.utils.dates import ( + add_months_to_yyyymmdd, + exact_age_in_months, + grid_month, + grid_months_to_yyyymmdd, +) + + +class state_pension_age_date(Variable): + value_type = int + entity = Person + label = "date this person attains State Pension age" + documentation = ( + "The day on which this person attains State Pension age (pensionable " + "age), written as a YYYYMMDD number. It is set by their date of birth, " + "which comes from age and months_since_last_birthday." + ) + definition_period = YEAR + unit = "date" + reference = ( + "https://www.legislation.gov.uk/ukpga/1995/26/schedule/4", + "https://www.legislation.gov.uk/ukpga/2014/19/section/26", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.state_pension.age + # Dates are in months on a grid whose months start on the 6th, so the + # middle of the fiscal year (6 October) is a whole month. + age_in_months = exact_age_in_months( + person("age", period), person("months_since_last_birthday", period) + ) + # The day of birth: the one starting at or after that instant, so the + # person's legal age on 6 October is age. + birth_date = grid_months_to_yyyymmdd( + grid_month(period.start.year, 10) - age_in_months + ) + + # Pensions Act 1995 Sch 4 para 1 rule (1): men born before 6 December + # 1953 attain pensionable age at 65. Everyone else follows the + # timetable in rules (2) to (10), which sets either an age or a day. + male_rule = person("is_male", period) & (birth_date < p.male.born_before) + age_rule = where(male_rule, p.male.age, p.age_by_birth_date.calc(birth_date)) + day_rule = where(male_rule, 0, p.day_by_birth_date.calc(birth_date)) + # An age of N years and M months is attained at the commencement of + # the anniversary (Family Law Reform Act 1969 s.9(1)): the same day of + # the month, or the month's last day where that day does not exist, + # which also gives the three days in rule (7A). Where the statute sets + # a day instead, the day rule is later; otherwise it is zero. + anniversary = add_months_to_yyyymmdd(birth_date, age_rule) + return np.maximum(anniversary, day_rule) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_amount.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_amount.py index c09642958..cd4727688 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_amount.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_amount.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.variables.household.demographic.country import Country class council_tax_reduction_applicable_amount(Variable): @@ -21,20 +22,44 @@ def formula(benunit, period, parameters): single = benunit("is_single_person", period) couple = benunit("is_couple", period) lone_parent = benunit("is_lone_parent", period) + # Pension-age personal allowances. England's prescribed requirements + # (SI 2012/2885 Sch 2 para 1, amended by SI 2021/29 for schemes for + # financial years from 2021-22) split them by when State Pension age + # was attained, with the same cutoff and amounts as Housing Benefit. + # The Scottish (SSI 2012/319 Sch 1 para 2) and Welsh (SI 2013/3029 + # Sch 2 para 1) schemes keep one pension-age rate, the higher one. + # England's rows (2) and (5) do not cover a couple where one member has + # not reached State Pension age and the other did so after the cutoff; + # as for Housing Benefit, such a couple gets the lower rate. + single_aged, couple_aged, lone_parent_aged = ( + p.single.aged, + p.couple.aged, + p.lone_parent.aged, + ) + if p.pension_age_cutoff is not None: + in_england = benunit.household("country", period) == Country.ENGLAND + lower = in_england & ~benunit( + "housing_benefit_attained_pension_age_before_cutoff", period + ) + single_aged = where(lower, p.single.aged_from_cutoff, single_aged) + couple_aged = where(lower, p.couple.aged_from_cutoff, couple_aged) + lone_parent_aged = where( + lower, p.lone_parent.aged_from_cutoff, lone_parent_aged + ) single_personal_allowance = ( u_25 * p.single.younger + o_25 * p.single.older - + any_over_SP_age * p.single.aged + + any_over_SP_age * single_aged ) couple_personal_allowance = ( u_18 * p.couple.younger + o_18 * p.couple.older - + any_over_SP_age * p.couple.aged + + any_over_SP_age * couple_aged ) lone_parent_personal_allowance = ( u_18 * p.lone_parent.younger + o_18 * p.lone_parent.older - + any_over_SP_age * p.lone_parent.aged + + any_over_SP_age * lone_parent_aged ) personal_allowance = ( single * single_personal_allowance