From 7a5076c4a13b6949a98177961c6c46702b262834 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 30 Sep 2026 17:28:09 -0400 Subject: [PATCH 1/6] Value means-tested capital less sale expenses and secured debt UC Regs 2013 reg. 49(1) and its legacy equivalents (HB Regs 2006 reg. 47, HB (SPC) Regs 2006 reg. 45, IS Regs 1987 reg. 49, JSA Regs 1996 reg. 111, ESA Regs 2008 reg. 113, SPC Regs 2002 reg. 19) calculate capital at market or surrender value less 10% where a sale would incur expenses and less any encumbrance secured on it. The model summed every capital source at full value. Each programme gets a capital.sale_expenses node (rate 0.1 and the sources whose sale incurs expenses: land, property and corporate_wealth, not cash savings). A shared helper applies the 10% before the encumbrance and never values an encumbered asset below nil. New household inputs carry debt secured on other residential property, non-residential property and land; the Enhanced FRS has none, so they default to zero. Co-Authored-By: Claude Opus 5.5 --- changelog.d/uc-capital-sale-expenses.fixed.md | 1 + policyengine_uk/data/uprating_indices.yaml | 3 + .../income/capital/sale_expenses/rate.yaml | 14 ++ .../income/capital/sale_expenses/sources.yaml | 22 ++ .../income/capital/sale_expenses/rate.yaml | 14 ++ .../income/capital/sale_expenses/sources.yaml | 26 +++ .../capital/sale_expenses/rate.yaml | 16 ++ .../capital/sale_expenses/sources.yaml | 28 +++ .../capital/sale_expenses/rate.yaml | 14 ++ .../capital/sale_expenses/sources.yaml | 26 +++ .../income/capital/sale_expenses/rate.yaml | 14 ++ .../income/capital/sale_expenses/sources.yaml | 26 +++ .../capital/sale_expenses/rate.yaml | 16 ++ .../capital/sale_expenses/sources.yaml | 31 +++ .../family/esa_income/esa_income_capital.yaml | 8 +- .../housing_benefit_capital.yaml | 35 ++- .../income_support_capital.yaml | 8 +- .../family/jsa_income/jsa_income_capital.yaml | 8 +- .../universal_credit/is_UC_eligible.yaml | 12 +- .../baseline/gov/dwp/capital_valuation.yaml | 218 ++++++++++++++++++ .../pension_credit_deemed_income.yaml | 6 +- .../pension_credit/pension_credit_income.yaml | 26 ++- .../test_capital_valuation_properties.py | 182 +++++++++++++++ .../tests/test_stock_capital_periods.py | 8 +- policyengine_uk/utils/capital_valuation.py | 40 ++++ .../gov/dwp/esa_income_assessable_capital.py | 10 +- .../housing_benefit_assessable_capital.py | 10 +- .../dwp/income_support_assessable_capital.py | 10 +- .../gov/dwp/jsa_income_assessable_capital.py | 10 +- .../pension_credit_assessable_capital.py | 8 +- .../universal_credit/uc_assessable_capital.py | 11 +- .../non_residential_property_secured_debt.py | 17 ++ ...other_residential_property_secured_debt.py | 17 ++ .../input/owned_land_secured_debt.py | 16 ++ 34 files changed, 869 insertions(+), 42 deletions(-) create mode 100644 changelog.d/uc-capital-sale-expenses.fixed.md create mode 100644 policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/rate.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/sources.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/rate.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/sources.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/rate.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/sources.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/rate.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/sources.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/rate.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml create mode 100644 policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml create mode 100644 policyengine_uk/tests/test_capital_valuation_properties.py create mode 100644 policyengine_uk/utils/capital_valuation.py create mode 100644 policyengine_uk/variables/input/non_residential_property_secured_debt.py create mode 100644 policyengine_uk/variables/input/other_residential_property_secured_debt.py create mode 100644 policyengine_uk/variables/input/owned_land_secured_debt.py diff --git a/changelog.d/uc-capital-sale-expenses.fixed.md b/changelog.d/uc-capital-sale-expenses.fixed.md new file mode 100644 index 0000000000..34790cb3d8 --- /dev/null +++ b/changelog.d/uc-capital-sale-expenses.fixed.md @@ -0,0 +1 @@ +Value Universal Credit, Housing Benefit, Income Support, income-based JSA, income-related ESA and Pension Credit capital at market value less 10% where a sale would incur expenses (land, property and shares; not cash savings) and less any debt secured on the asset, as UC Regs 2013 reg. 49(1) and its legacy equivalents require. Adds secured-debt inputs for other residential property, non-residential property and land. diff --git a/policyengine_uk/data/uprating_indices.yaml b/policyengine_uk/data/uprating_indices.yaml index 4fbc8bc819..4dad54bc83 100644 --- a/policyengine_uk/data/uprating_indices.yaml +++ b/policyengine_uk/data/uprating_indices.yaml @@ -92,10 +92,13 @@ gov.economic_assumptions.yoy_growth.obr.per_capita.gdp: - miscellaneous_income - mortgage_capital_repayment - net_financial_wealth +- non_residential_property_secured_debt - non_residential_property_value - other_investment_income +- other_residential_property_secured_debt - other_residential_property_value - owned_land +- owned_land_secured_debt - pension_income - private_pension_wealth - private_transfer_income diff --git a/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/rate.yaml new file mode 100644 index 0000000000..468d182cb9 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/rate.yaml @@ -0,0 +1,14 @@ +description: > + Share of the current market or surrender value deducted from income-related ESA + capital where there would be expenses attributable to sale. The deduction + is a flat 10% whatever the actual costs, taken before any incumbrance + secured on the asset. +values: + 2008-10-27: 0.1 +metadata: + label: Income-related ESA capital sale expense deduction + period: year + unit: /1 + reference: + - title: Employment and Support Allowance Regulations 2008 reg. 113(a) + href: https://www.legislation.gov.uk/uksi/2008/794/regulation/113 diff --git a/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/sources.yaml new file mode 100644 index 0000000000..b1946fe614 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/sources.yaml @@ -0,0 +1,22 @@ +description: > + Capital sources whose sale would incur expenses, so that income-related ESA + values them at 90% of market value. Land and property always have costs of + sale. Shares are sold through a broker, so `corporate_wealth` is listed; it + also holds unit trusts, which have no costs of sale, but the dataset does + not separate them. `savings` is not listed because a bank or building + society account is valued at its balance and withdrawing money is not a sale + (see the Universal Credit parameter of the same name for the guidance). + Sources not counted as income-related ESA capital are ignored. +metadata: + label: Income-related ESA capital sources with sale expenses + period: year + unit: list + reference: + - title: Employment and Support Allowance Regulations 2008 reg. 113(a) + href: https://www.legislation.gov.uk/uksi/2008/794/regulation/113 +values: + 2008-10-27: + - owned_land + - other_residential_property_value + - non_residential_property_value + - corporate_wealth diff --git a/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/rate.yaml new file mode 100644 index 0000000000..ff2e4d5759 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/rate.yaml @@ -0,0 +1,14 @@ +description: > + Share of the current market or surrender value deducted from income-based JSA + capital where there would be expenses attributable to sale. The deduction + is a flat 10% whatever the actual costs, taken before any incumbrance + secured on the asset. +values: + 1996-10-07: 0.1 +metadata: + label: Income-based JSA capital sale expense deduction + period: year + unit: /1 + reference: + - title: Jobseeker's Allowance Regulations 1996 reg. 111(a) + href: https://www.legislation.gov.uk/uksi/1996/207/regulation/111 diff --git a/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/sources.yaml new file mode 100644 index 0000000000..1a64a5ee2c --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/sources.yaml @@ -0,0 +1,26 @@ +description: > + Capital sources whose sale would incur expenses, so that income-based JSA + values them at 90% of market value. Land and property always have costs of + sale. Shares are sold through a broker, so `corporate_wealth` is listed; it + also holds unit trusts, which have no costs of sale, but the dataset does + not separate them. `savings` is not listed because a bank or building + society account is valued at its balance and withdrawing money is not a sale + (DMG 29620-29623, 29681 and 29685). Sources not counted as income-based JSA + capital are ignored. +metadata: + label: Income-based JSA capital sources with sale expenses + period: year + unit: list + reference: + - title: Jobseeker's Allowance Regulations 1996 reg. 111(a) + href: https://www.legislation.gov.uk/uksi/1996/207/regulation/111 + - title: Decision Makers' Guide chapter 29, paras. 29620-29623 + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=124 + - title: Decision Makers' Guide chapter 29, paras. 29681 and 29685 + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=139 +values: + 1996-10-07: + - owned_land + - other_residential_property_value + - non_residential_property_value + - corporate_wealth diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/rate.yaml new file mode 100644 index 0000000000..f496742f77 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/rate.yaml @@ -0,0 +1,16 @@ +description: > + Share of the current market or surrender value deducted from Housing Benefit + capital where there would be expenses attributable to sale. The deduction + is a flat 10% whatever the actual costs, taken before any encumbrance + secured on the asset. +values: + 2006-04-10: 0.1 +metadata: + label: Housing Benefit capital sale expense deduction + period: year + unit: /1 + reference: + - title: The Housing Benefit Regulations 2006 reg. 47(a) + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/47 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 reg. 45(a) + href: https://www.legislation.gov.uk/uksi/2006/214/regulation/45 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml new file mode 100644 index 0000000000..cb504ed3c4 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml @@ -0,0 +1,28 @@ +description: > + Capital sources whose sale would incur expenses, so that Housing Benefit + values them at 90% of market value. Land and property always have costs of + sale. Shares are sold through a broker, so `corporate_wealth` is listed; it + also holds unit trusts, which have no costs of sale, but the dataset does + not separate them. `savings` is not listed because a bank or building + society account is valued at its balance and withdrawing money is not a sale + (HBGM W1.430, W1.530-W1.531, P1.430 and P1.530-P1.531). Sources not counted + as Housing Benefit capital are ignored. +metadata: + label: Housing Benefit capital sources with sale expenses + period: year + unit: list + reference: + - title: The Housing Benefit Regulations 2006 reg. 47(a) + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/47 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 reg. 45(a) + href: https://www.legislation.gov.uk/uksi/2006/214/regulation/45 + - title: Housing Benefit Guidance Manual BW1, paras. W1.430 and W1.530-W1.531 + href: https://assets.publishing.service.gov.uk/media/5a749328ed915d0e8e3994c0/hbgm-bw1-assessment-of-capital.pdf#page=36 + - title: Housing Benefit Guidance Manual BP1, paras. P1.430 and P1.530-P1.531 + href: https://assets.publishing.service.gov.uk/media/5a7ec5d840f0b6230268b71f/hbgm-bp1-assessment-of-capital.pdf#page=31 +values: + 2006-04-10: + - owned_land + - other_residential_property_value + - non_residential_property_value + - corporate_wealth diff --git a/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml new file mode 100644 index 0000000000..7cb86fe853 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml @@ -0,0 +1,14 @@ +description: > + Share of the current market or surrender value deducted from Income Support + capital where there would be expenses attributable to sale. The deduction + is a flat 10% whatever the actual costs, taken before any incumbrance + secured on the asset. +values: + 2010-01-01: 0.1 +metadata: + label: Income Support capital sale expense deduction + period: year + unit: /1 + reference: + - title: Income Support (General) Regulations 1987 reg. 49(a) + href: https://www.legislation.gov.uk/uksi/1987/1967/regulation/49 diff --git a/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/sources.yaml new file mode 100644 index 0000000000..0af0f836b0 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/sources.yaml @@ -0,0 +1,26 @@ +description: > + Capital sources whose sale would incur expenses, so that Income Support + values them at 90% of market value. Land and property always have costs of + sale. Shares are sold through a broker, so `corporate_wealth` is listed; it + also holds unit trusts, which have no costs of sale, but the dataset does + not separate them. `savings` is not listed because a bank or building + society account is valued at its balance and withdrawing money is not a sale + (DMG 29620-29623, 29681 and 29685). Sources not counted as Income Support + capital are ignored. +metadata: + label: Income Support capital sources with sale expenses + period: year + unit: list + reference: + - title: Income Support (General) Regulations 1987 reg. 49(a) + href: https://www.legislation.gov.uk/uksi/1987/1967/regulation/49 + - title: Decision Makers' Guide chapter 29, paras. 29620-29623 + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=124 + - title: Decision Makers' Guide chapter 29, paras. 29681 and 29685 + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=139 +values: + 2010-01-01: + - owned_land + - other_residential_property_value + - non_residential_property_value + - corporate_wealth diff --git a/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/rate.yaml new file mode 100644 index 0000000000..b344e9dcf2 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/rate.yaml @@ -0,0 +1,14 @@ +description: > + Share of the current market or surrender value deducted from Pension Credit + capital where there would be expenses attributable to sale. The deduction + is a flat 10% whatever the actual costs, taken before any encumbrance + secured on the asset. +values: + 2003-10-06: 0.1 +metadata: + label: Pension Credit capital sale expense deduction + period: year + unit: /1 + reference: + - title: State Pension Credit Regulations 2002 reg. 19(a) + href: https://www.legislation.gov.uk/uksi/2002/1792/regulation/19 diff --git a/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/sources.yaml new file mode 100644 index 0000000000..da4dae9ae1 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/sources.yaml @@ -0,0 +1,26 @@ +description: > + Capital sources whose sale would incur expenses, so that Pension Credit + values them at 90% of market value. Land and property always have costs of + sale. Shares are sold through a broker, so `corporate_wealth` is listed; it + also holds unit trusts, which have no costs of sale, but the dataset does + not separate them. `savings` is not listed because a bank or building + society account is valued at its balance and withdrawing money is not a sale + (DMG 84712-84716, 84731 and 84772). Sources not counted as Pension Credit + capital are ignored. +metadata: + label: Pension Credit capital sources with sale expenses + period: year + unit: list + reference: + - title: State Pension Credit Regulations 2002 reg. 19(a) + href: https://www.legislation.gov.uk/uksi/2002/1792/regulation/19 + - title: Decision Makers' Guide chapter 84, paras. 84712-84716 + href: https://assets.publishing.service.gov.uk/media/6a5e38bb8b7e4fa537e693d5/dmg-ch84.pdf#page=99 + - title: Decision Makers' Guide chapter 84, paras. 84731 and 84772 + href: https://assets.publishing.service.gov.uk/media/6a5e38bb8b7e4fa537e693d5/dmg-ch84.pdf#page=102 +values: + 2003-10-06: + - owned_land + - other_residential_property_value + - non_residential_property_value + - corporate_wealth diff --git a/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/rate.yaml new file mode 100644 index 0000000000..150561614f --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/rate.yaml @@ -0,0 +1,16 @@ +description: > + Share of the current market or surrender value deducted from Universal + Credit capital where there would be expenses attributable to sale. The + deduction is a flat 10% whatever the actual costs, taken before any + encumbrance secured on the asset. +values: + 2013-04-29: 0.1 +metadata: + label: Universal Credit capital sale expense deduction + period: year + unit: /1 + reference: + - title: The Universal Credit Regulations 2013 reg. 49(1)(a) + href: https://www.legislation.gov.uk/uksi/2013/376/regulation/49 + - title: Advice for Decision Making chapter H1, paras. H1602-H1608 + href: https://assets.publishing.service.gov.uk/media/6a5e0ac7a2662d4563fe39e0/adm-ch-h1.pdf#page=44 diff --git a/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml new file mode 100644 index 0000000000..969e9ac619 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml @@ -0,0 +1,31 @@ +description: > + Capital sources whose sale would incur expenses, so that Universal Credit + values them at 90% of market value. Real property always has costs of sale + (ADM H1606, citing R(IS) 21/93), so `owned_land`, + `other_residential_property_value` and `non_residential_property_value` are + listed. `savings` is not listed: the 10% applies only where selling needs + an agent, broker, solicitor or accountant (ADM H1604-H1605), the costs of + withdrawing money from a building society are not costs of sale (H1607), + and an account is valued at its balance (H1675). `corporate_wealth` is + listed because quoted shares are valued less 10% for costs of sale (H1665). + It also holds unit trusts, which have no costs of sale (H1674), and stocks + and shares ISAs, which the guidance values at their withdrawal value + (H1656); the dataset does not separate these, so the deduction also + reaches them. Sources not counted as Universal Credit capital are ignored. +metadata: + label: Universal Credit capital sources with sale expenses + period: year + unit: list + reference: + - title: The Universal Credit Regulations 2013 reg. 49(1)(a) + href: https://www.legislation.gov.uk/uksi/2013/376/regulation/49 + - title: Advice for Decision Making chapter H1, paras. H1604-H1607 + href: https://assets.publishing.service.gov.uk/media/6a5e0ac7a2662d4563fe39e0/adm-ch-h1.pdf#page=44 + - title: Advice for Decision Making chapter H1, paras. H1665 and H1673-H1675 + href: https://assets.publishing.service.gov.uk/media/6a5e0ac7a2662d4563fe39e0/adm-ch-h1.pdf#page=57 +values: + 2013-04-29: + - owned_land + - other_residential_property_value + - non_residential_property_value + - corporate_wealth diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml index bdbbef68e0..abe48a7b5d 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml @@ -19,7 +19,9 @@ other_residential_property_value: 3_000 non_residential_property_value: 4_000 output: - esa_income_assessable_capital: 10_500 + # Savings at face value; land, shares and property less 10% for the + # expenses of sale (ESA Regs 2008 reg. 113(a)): 1,000 + 90% of 9,500. + esa_income_assessable_capital: 9_550 - name: Income-related ESA has no tariff income at the lower capital threshold period: 2026 @@ -210,4 +212,6 @@ corporate_wealth: 2_000 private_pension_wealth: 150_000 output: - esa_income_assessable_capital: 3_000 + # Savings at face value; land, shares and property less 10% for the + # expenses of sale (ESA Regs 2008 reg. 113(a)): 1,000 + 90% of 2,000. + esa_income_assessable_capital: 2_800 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml index e9a0cd47c3..c73e3b37f5 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml @@ -89,7 +89,7 @@ - name: Housing Benefit counts direct land holdings as capital period: 2025 - absolute_error_margin: 0 + absolute_error_margin: 0.01 input: people: person: @@ -103,11 +103,36 @@ households: household: members: person - owned_land: 16_001 + # 90% of 17,780 is 16,002, over the 16,000 limit after the 10% + # deduction for the expenses of sale (HB Regs 2006 reg. 47(a)). + owned_land: 17_780 output: - housing_benefit_assessable_capital: 16_001 + housing_benefit_assessable_capital: 16_002 housing_benefit_eligible: false +- name: Housing Benefit values land less 10% for the expenses of sale + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + in_social_housing: true + housing_benefit_reported: 1 + benunits: + benunit: + members: person + would_claim_uc: false + households: + household: + members: person + # Land worth 16,001 is valued at 14,400.90 (HB Regs 2006 reg. 47(a)), + # within the limit. + owned_land: 16_001 + output: + housing_benefit_assessable_capital: 14_400.9 + housing_benefit_eligible: true + - name: Housing Benefit counts corporate wealth as a broad financial-capital proxy period: 2025 absolute_error_margin: 0 @@ -126,7 +151,9 @@ members: person corporate_wealth: 50_000 output: - housing_benefit_assessable_capital: 50_000 + # Market value less 10% for the expenses of sale (HB Regs 2006 + # reg. 47(a)). + housing_benefit_assessable_capital: 45_000 housing_benefit_eligible: false - name: Mixed benunits split household Housing Benefit capital by adult share diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_capital.yaml index 585884ea9c..f90e5f1a9d 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_capital.yaml @@ -23,7 +23,9 @@ other_residential_property_value: 3000 non_residential_property_value: 4000 output: - income_support_assessable_capital: 10500 + # Savings at face value; land, shares and property less 10% for the + # expenses of sale (IS Regs 1987 reg. 49(a)): 1,000 + 90% of 9,500. + income_support_assessable_capital: 9550 - name: Income Support has no tariff income at the lower capital threshold period: 2021 @@ -233,4 +235,6 @@ corporate_wealth: 2000 private_pension_wealth: 150000 output: - income_support_assessable_capital: 3000 + # Savings at face value; land, shares and property less 10% for the + # expenses of sale (IS Regs 1987 reg. 49(a)): 1,000 + 90% of 2,000. + income_support_assessable_capital: 2800 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/jsa_income/jsa_income_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/jsa_income/jsa_income_capital.yaml index 13ecc3d659..bc50925503 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/jsa_income/jsa_income_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/jsa_income/jsa_income_capital.yaml @@ -19,7 +19,9 @@ other_residential_property_value: 3_000 non_residential_property_value: 4_000 output: - jsa_income_assessable_capital: 10_500 + # Savings at face value; land, shares and property less 10% for the + # expenses of sale (JSA Regs 1996 reg. 111(a)): 1,000 + 90% of 9,500. + jsa_income_assessable_capital: 9_550 - name: Income-based JSA has no tariff income at the lower capital threshold period: 2025 @@ -184,4 +186,6 @@ corporate_wealth: 2_000 private_pension_wealth: 150_000 output: - jsa_income_assessable_capital: 3_000 + # Savings at face value; land, shares and property less 10% for the + # expenses of sale (JSA Regs 1996 reg. 111(a)): 1,000 + 90% of 2,000. + jsa_income_assessable_capital: 2_800 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/is_UC_eligible.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/is_UC_eligible.yaml index fa145e20c1..fc466402eb 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/is_UC_eligible.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/is_UC_eligible.yaml @@ -259,7 +259,9 @@ members: person other_residential_property_value: 50_000 output: - uc_assessable_capital: 50_000 + # Market value less 10% for the expenses of sale (UC Regs 2013 + # reg. 49(1)(a)). + uc_assessable_capital: 45_000 is_uc_eligible: false - name: Countable non-residential property can push capital over the upper threshold @@ -277,7 +279,9 @@ members: person non_residential_property_value: 50_000 output: - uc_assessable_capital: 50_000 + # Market value less 10% for the expenses of sale (UC Regs 2013 + # reg. 49(1)(a)). + uc_assessable_capital: 45_000 is_uc_eligible: false - name: Countable corporate wealth can push capital over the upper threshold @@ -295,7 +299,9 @@ members: person corporate_wealth: 50_000 output: - uc_assessable_capital: 50_000 + # Market value less 10% for the expenses of sale (UC Regs 2013 + # reg. 49(1)(a)). + uc_assessable_capital: 45_000 is_uc_eligible: false - name: Main residence value is excluded from Universal Credit capital diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml new file mode 100644 index 0000000000..840b084ec1 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml @@ -0,0 +1,218 @@ +# Capital is valued at market value less 10% where a sale would incur +# expenses, and less any encumbrance secured on it: UC Regs 2013 reg. 49(1); +# HB Regs 2006 reg. 47; IS Regs 1987 reg. 49; JSA Regs 1996 reg. 111; ESA Regs +# 2008 reg. 113; SPC Regs 2002 reg. 19. Savings in a bank or building society +# have no sale expenses; land, property and shares do (ADM H1604-H1607). +# Expected values are worked by hand from those provisions. + +- name: UC values a mortgaged holiday home as in ADM H1602 + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + benunits: + benunit: + members: person + households: + household: + members: person + # 125,000 - 10% (12,500) - 100,500 mortgage = 12,000. + other_residential_property_value: 125_000 + other_residential_property_secured_debt: 100_500 + output: + uc_assessable_capital: 12_000 + is_uc_eligible: true + # 24 steps of 250 above 6,000 at 4.35 a month: 24 * 4.35 * 12. + uc_tariff_income: 1_252.8 + +- name: UC counts cash savings at face value + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + benunits: + benunit: + members: person + households: + household: + members: person + savings: 15_000 + output: + uc_assessable_capital: 15_000 + is_uc_eligible: true + +- name: UC shares valued less sale expenses bring capital within the limit + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + benunits: + benunit: + members: person + households: + household: + members: person + # 5,000 + 90% of 12,000 = 15,800, within the 16,000 limit; at full + # value the household would hold 17,000. + savings: 5_000 + corporate_wealth: 12_000 + output: + uc_assessable_capital: 15_800 + is_uc_eligible: true + # 9,800 above 6,000 is 40 steps of 250 (rounded up): 40 * 4.35 * 12. + uc_tariff_income: 2_088 + +- name: UC negative equity in a second home does not reduce savings + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + benunits: + benunit: + members: person + households: + household: + members: person + # The mortgage is deducted only from the property it is secured on + # (ADM H1615-H1616), so the property is valued at nil. + savings: 10_000 + other_residential_property_value: 100_000 + other_residential_property_secured_debt: 150_000 + output: + uc_assessable_capital: 10_000 + is_uc_eligible: true + +- name: UC deducts sale expenses before the encumbrance on business premises + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + benunits: + benunit: + members: person + households: + household: + members: person + # (90% of 40,000 - 20,000) + 90% of 5,000 = 16,000 + 4,500. + non_residential_property_value: 40_000 + non_residential_property_secured_debt: 20_000 + corporate_wealth: 5_000 + output: + uc_assessable_capital: 20_500 + is_uc_eligible: false + +- name: Housing Benefit values encumbered land less sale expenses + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + in_social_housing: true + housing_benefit_reported: 1 + benunits: + benunit: + members: person + would_claim_uc: false + households: + household: + members: person + # 1,000 + (90% of 20,000 - 5,000) = 14,000 (HB Regs 2006 reg. 47). + savings: 1_000 + owned_land: 20_000 + owned_land_secured_debt: 5_000 + output: + housing_benefit_assessable_capital: 14_000 + # 32 steps of 250 above 6,000 at 1 a week: 32 * 52. + housing_benefit_tariff_income: 1_664 + housing_benefit_eligible: true + +- name: Income Support values encumbered land less sale expenses + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + benunits: + benunit: + members: person + households: + household: + members: person + # 90% of 20,000 - 5,000 = 13,000 (IS Regs 1987 reg. 49). + owned_land: 20_000 + owned_land_secured_debt: 5_000 + output: + income_support_assessable_capital: 13_000 + +- name: Income-based JSA values a mortgaged second home less sale expenses + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + benunits: + benunit: + members: person + households: + household: + members: person + # 2,000 + (90% of 30,000 - 25,000) = 4,000 (JSA Regs 1996 reg. 111). + savings: 2_000 + other_residential_property_value: 30_000 + other_residential_property_secured_debt: 25_000 + output: + jsa_income_assessable_capital: 4_000 + +- name: Income-related ESA values shares less sale expenses + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: person + households: + household: + members: person + # 3,000 + 90% of 10,000 = 12,000 (ESA Regs 2008 reg. 113). + savings: 3_000 + corporate_wealth: 10_000 + output: + esa_income_assessable_capital: 12_000 + +- name: Pension Credit values mortgaged business premises less sale expenses + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 70 + benunits: + benunit: + members: person + households: + household: + members: person + # 2,000 + (90% of 30,000 - 10,000) = 19,000 (SPC Regs 2002 reg. 19). + savings: 2_000 + non_residential_property_value: 30_000 + non_residential_property_secured_debt: 10_000 + output: + pension_credit_assessable_capital: 19_000 + # 18 steps of 500 above 10,000 at 1 a week: 18 * 52. + pension_credit_deemed_income: 936 diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_deemed_income.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_deemed_income.yaml index cf16632edc..5e4f8db1ae 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_deemed_income.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_deemed_income.yaml @@ -78,9 +78,11 @@ households: household: members: person - owned_land: 10_001 + # 90% of 11,120 is 10,008 after the 10% deduction for the expenses + # of sale (SPC Regs 2002 reg. 19(a)): one 500 step above 10,000. + owned_land: 11_120 output: - pension_credit_assessable_capital: 10_001 + pension_credit_assessable_capital: 10_008 pension_credit_deemed_income: 52 - name: Pension Credit does not dilute pensioner capital across unrelated adult benunits. diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_income.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_income.yaml index b6cf5c9493..b578d941fe 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_income.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_income.yaml @@ -76,10 +76,16 @@ other_residential_property_value: 55_370 savings: 455 output: - pension_credit_assessable_capital: 55_825 - pension_credit_deemed_income: 4_784 - pension_credit_income: 15_260 - pension_credit: 0 + # 455 + 90% of 55,370 (SPC Regs 2002 reg. 19(a)). Deemed income is + # 81 steps of 500 above 10,000 at 1 a week: 81 * 52 = 4,212. + pension_credit_assessable_capital: 50_288 + pension_credit_deemed_income: 4_212 + pension_credit_income: 14_688 + # Income exceeds the 12,376 guarantee, so no guarantee credit. Savings + # credit: 60% of (12,376 - 208.07 * 52) = 933.82, less 40% of + # (14,688 - 12,376) = 924.80, leaves 9.02. + guarantee_credit: 0 + pension_credit: 9.016 - name: Case 5, 2026 Pension Credit uses tariff income with the published guarantee rate. period: 2026 @@ -99,12 +105,14 @@ savings: 87_285 corporate_wealth: 12_650 output: - pension_credit_assessable_capital: 99_935 - pension_credit_deemed_income: 9_360 - pension_credit_income: 9_360 + # 87,285 + 90% of 12,650 (SPC Regs 2002 reg. 19(a)). Deemed income is + # 178 steps of 500 above 10,000 at 1 a week: 178 * 52 = 9,256. + pension_credit_assessable_capital: 98_670 + pension_credit_deemed_income: 9_256 + pension_credit_income: 9_256 standard_minimum_guarantee: 12_376 - guarantee_credit: 3_016 - pension_credit: 3_016 + guarantee_credit: 3_120 + pension_credit: 3_120 - name: Pension Credit capital disregards private pension wealth period: 2026 diff --git a/policyengine_uk/tests/test_capital_valuation_properties.py b/policyengine_uk/tests/test_capital_valuation_properties.py new file mode 100644 index 0000000000..76a7aa5d1d --- /dev/null +++ b/policyengine_uk/tests/test_capital_valuation_properties.py @@ -0,0 +1,182 @@ +"""Property-based tests for how the means tests value capital. + +Universal Credit and each legacy means test calculate capital in the United +Kingdom at its current market or surrender value less 10% where there would +be expenses attributable to sale, and less any encumbrance secured on it (UC +Regs 2013 reg. 49(1); HB Regs 2006 reg. 47; HB (SPC) Regs 2006 reg. 45; IS +Regs 1987 reg. 49; JSA Regs 1996 reg. 111; ESA Regs 2008 reg. 113; SPC Regs +2002 reg. 19). Savings in a bank or building society incur no sale expenses; +land, property and shares do. + +Invariants, for any generated population of single-adult households: + +1. Non-increasing: every programme's assessable capital is at most the same + household's capital with the deduction switched off (rate 0, no debt). +2. Cash only: a household holding only savings has the same capital with the + deduction on or off. +3. Differential: capital equals a direct implementation of the regulation, + savings + sum over sources of max(0, 90% of value - secured debt). +4. Monotone: a higher sale-expense rate, or more secured debt, never raises + capital. +5. Isolation: debt secured on one asset never takes capital below the value + of the household's other assets, and capital is never negative. +""" + +from functools import reduce + +import numpy as np +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +YEAR = 2026 +PROPERTY_SETTINGS = settings( + max_examples=5, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +# Assessable capital variable -> parameter node holding its sources and +# sale-expense rule. Pension Credit counts only pension-age adults; the +# others are tested on working-age adults (pension-age Housing Benefit +# disregards all capital for Guarantee Credit recipients). +PROGRAMMES = { + "uc_assessable_capital": "gov.dwp.universal_credit.means_test.capital", + "housing_benefit_assessable_capital": "gov.dwp.housing_benefit.means_test.capital", + "income_support_assessable_capital": "gov.dwp.income_support.means_test.capital", + "jsa_income_assessable_capital": "gov.dwp.JSA.income.capital", + "esa_income_assessable_capital": "gov.dwp.ESA.income.capital", + "pension_credit_assessable_capital": "gov.dwp.pension_credit.income.capital", +} +PENSION_AGE_ONLY = {"pension_credit_assessable_capital"} +ASSETS = [ + "savings", + "owned_land", + "corporate_wealth", + "other_residential_property_value", + "non_residential_property_value", +] +DEBTS = { + "owned_land": "owned_land_secured_debt", + "other_residential_property_value": "other_residential_property_secured_debt", + "non_residential_property_value": "non_residential_property_secured_debt", +} +amount = st.one_of(st.just(0.0), st.floats(0, 400_000, allow_nan=False)) + + +@st.composite +def households(draw, cash_only=False): + assets = {asset: draw(amount) for asset in ASSETS} + debts = {debt: draw(amount) for debt in DEBTS.values()} + if cash_only: + assets = {asset: 0.0 for asset in ASSETS} | {"savings": assets["savings"]} + debts = {debt: 0.0 for debt in debts} + return dict(age=draw(st.sampled_from([30, 70])), assets=assets, debts=debts) + + +def situation(units, debt_scale=1.0): + people, benunits, homes = {}, {}, {} + for i, unit in enumerate(units): + people[f"p{i}"] = {"age": {YEAR: unit["age"]}} + benunits[f"b{i}"] = {"members": [f"p{i}"]} + homes[f"h{i}"] = { + "members": [f"p{i}"], + **{k: {YEAR: v} for k, v in unit["assets"].items()}, + **{k: {YEAR: v * debt_scale} for k, v in unit["debts"].items()}, + } + return {"people": people, "benunits": benunits, "households": homes} + + +def rate_reform(rate): + return { + f"{node}.sale_expenses.rate": {str(YEAR): rate} for node in PROGRAMMES.values() + } + + +def calculate(units, rate=None, debt_scale=1.0): + sim = Simulation( + situation=situation(units, debt_scale), + reform=None if rate is None else rate_reform(rate), + ) + return sim, {v: np.asarray(sim.calculate(v, YEAR), dtype=float) for v in PROGRAMMES} + + +def parameter_node(sim, path): + return reduce(getattr, path.split("."), sim.tax_benefit_system.parameters(YEAR)) + + +def applies(variable, unit): + return (unit["age"] >= 67) == (variable in PENSION_AGE_ONLY) + + +def expected_capital(unit, node): + """Reg. 49(1) applied source by source, independently of the model.""" + total = 0.0 + for source in node.sources: + value = unit["assets"][source] + if source in node.sale_expenses.sources: + value *= 1 - node.sale_expenses.rate + if source in DEBTS: + value = max(0.0, value - unit["debts"][DEBTS[source]]) + total += value + return total + + +def close(a, b): + return abs(a - b) <= 1 + 1e-6 * abs(b) + + +@PROPERTY_SETTINGS +@given(st.lists(households(), min_size=1, max_size=30)) +def test_valuation_matches_the_regulation_and_never_adds_capital(units): + sim, valued = calculate(units) + _, full = calculate(units, rate=0.0, debt_scale=0.0) + for variable, path in PROGRAMMES.items(): + node = parameter_node(sim, path) + assert node.sale_expenses.rate == 0.1 + assert "savings" in node.sources + assert "savings" not in node.sale_expenses.sources + for i, unit in enumerate(units): + assert valued[variable][i] >= 0, (variable, unit) + assert valued[variable][i] <= full[variable][i] + 0.01, (variable, unit) + if applies(variable, unit): + expected = expected_capital(unit, node) + assert close(valued[variable][i], expected), (variable, unit) + # Debt secured on property never reaches the other assets. + floor = sum( + unit["assets"][s] + * (1 - node.sale_expenses.rate * (s in node.sale_expenses.sources)) + for s in node.sources + if s not in DEBTS + ) + assert valued[variable][i] >= floor - 1, (variable, unit) + + +@PROPERTY_SETTINGS +@given(st.lists(households(cash_only=True), min_size=1, max_size=30)) +def test_cash_only_households_have_no_deduction(units): + _, valued = calculate(units) + _, full = calculate(units, rate=0.0) + for variable in PROGRAMMES: + assert np.allclose(valued[variable], full[variable]), variable + for i, unit in enumerate(units): + if applies(variable, unit): + assert close(valued[variable][i], unit["assets"]["savings"]), variable + + +@PROPERTY_SETTINGS +@given( + st.lists(households(), min_size=1, max_size=30), + st.floats(0, 0.5), + st.floats(0, 0.5), + st.floats(0, 2), +) +def test_capital_is_non_increasing_in_rate_and_secured_debt(units, r1, r2, scale): + low, high = sorted([r1, r2]) + _, at_low = calculate(units, rate=low) + _, at_high = calculate(units, rate=high) + _, more_debt = calculate(units, rate=low, debt_scale=1 + scale) + for variable in PROGRAMMES: + assert np.all(at_high[variable] <= at_low[variable] + 0.01), variable + assert np.all(more_debt[variable] <= at_low[variable] + 0.01), variable diff --git a/policyengine_uk/tests/test_stock_capital_periods.py b/policyengine_uk/tests/test_stock_capital_periods.py index d36c3068b2..e694045d13 100644 --- a/policyengine_uk/tests/test_stock_capital_periods.py +++ b/policyengine_uk/tests/test_stock_capital_periods.py @@ -23,7 +23,9 @@ def test_uc_capital_stocks_are_not_prorated_in_monthly_calculations(): assert simulation.calculate("savings", "2026-01")[0] == 12_000 assert simulation.calculate("corporate_wealth", "2026-01")[0] == 12_000 - assert simulation.calculate("uc_assessable_capital", "2026-01")[0] == 36_000 + # Savings at face value; property and shares less 10% for the expenses + # of sale (UC Regs 2013 reg. 49(1)(a)): 12,000 + 2 * 10,800. + assert simulation.calculate("uc_assessable_capital", "2026-01")[0] == 33_600 assert not simulation.calculate("is_uc_eligible", "2026-01")[0] @@ -43,7 +45,9 @@ def test_pension_credit_capital_stocks_are_not_prorated_monthly(): simulation = Simulation(situation=situation) assert simulation.calculate("savings", "2026-01")[0] == 12_000 + # Land and shares less 10% for the expenses of sale (SPC Regs 2002 + # reg. 19(a)): 12,000 + 2 * 10,800. assert ( simulation.calculate("pension_credit_assessable_capital", "2026-01")[0] - == 36_000 + == 33_600 ) diff --git a/policyengine_uk/utils/capital_valuation.py b/policyengine_uk/utils/capital_valuation.py new file mode 100644 index 0000000000..2e70896a1a --- /dev/null +++ b/policyengine_uk/utils/capital_valuation.py @@ -0,0 +1,40 @@ +"""Value means-tested capital as the capital-valuation regulations require. + +Universal Credit and each legacy means test value capital in the United +Kingdom "at its current market or surrender value less (a) where there would +be expenses attributable to sale, 10% [...]; and (b) the amount of any +encumbrances secured on it" (UC Regs 2013 reg. 49(1) and its legacy +equivalents). Each programme sets its own rate and the capital sources whose +sale would incur expenses in a ``capital.sale_expenses`` parameter node. +""" + +from policyengine_core.model_api import max_ + +# Household inputs holding the debts secured on each capital source, such as +# a mortgage on a second property. The encumbrance is deducted only from the +# asset it is secured on, so negative equity in one asset never reduces the +# value of another (ADM H1615-H1616). +SECURED_DEBT = { + "other_residential_property_value": "other_residential_property_secured_debt", + "non_residential_property_value": "non_residential_property_secured_debt", + "owned_land": "owned_land_secured_debt", +} + + +def valued_capital(value_of, sources, sale_expenses): + """Sum ``sources`` at market value less sale expenses and secured debt. + + ``value_of(variable)`` returns that household variable on the entity the + caller is working with. The sale-expense deduction comes first and the + encumbrance second (ADM H1608), and an encumbered asset is never valued + below nil. + """ + total = 0 + for source in sources: + value = value_of(source) + if source in sale_expenses.sources: + value = value * (1 - sale_expenses.rate) + if source in SECURED_DEBT: + value = max_(0, value - value_of(SECURED_DEBT[source])) + total = total + value + return total diff --git a/policyengine_uk/variables/gov/dwp/esa_income_assessable_capital.py b/policyengine_uk/variables/gov/dwp/esa_income_assessable_capital.py index 473bcdfebb..d9e00ba312 100644 --- a/policyengine_uk/variables/gov/dwp/esa_income_assessable_capital.py +++ b/policyengine_uk/variables/gov/dwp/esa_income_assessable_capital.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.capital_valuation import valued_capital class esa_income_assessable_capital(Variable): @@ -7,7 +8,8 @@ class esa_income_assessable_capital(Variable): label = "Assessable capital for income-related ESA" documentation = ( "Household capital apportioned to the benefit unit for the income-related " - "ESA capital test. Because the dataset only stores these stocks at " + "ESA capital test, valued at market value less 10% where a sale would " + "incur expenses and less any debt secured on it (reg. 113). Because the dataset only stores these stocks at " "household level, the model allocates full household capital to any " "benunit with a reported income-related ESA award and only falls back to " "an adult-share proxy when nobody in the household is on that reported " @@ -23,8 +25,10 @@ def formula(benunit, period, parameters): person = benunit.members claiming_esa_income = add(benunit, period, ["esa_income_reported"]) > 0 - household_capital = sum( - benunit.max(person.household(source, period)) for source in sources + household_capital = valued_capital( + lambda variable: benunit.max(person.household(variable, period)), + sources, + ESA.capital.sale_expenses, ) benunit_adults = add(benunit, period, ["is_adult"]) household_reporting_claimants = benunit.max( diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py index c978c5f699..cf1178e0a2 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.capital_valuation import valued_capital class housing_benefit_assessable_capital(Variable): @@ -7,7 +8,10 @@ class housing_benefit_assessable_capital(Variable): label = "Housing Benefit assessable capital" documentation = ( "Housing Benefit capital counted from the configured capital sources, " - "allocated across benunits using a household adult-share proxy." + "each valued at market value less 10% where a sale would incur " + "expenses and less any debt secured on it (reg. 47 of SI 2006/213, " + "reg. 45 of SI 2006/214), allocated across benunits using a household " + "adult-share proxy." ) definition_period = YEAR unit = GBP @@ -18,7 +22,9 @@ def formula(benunit, period, parameters): person = benunit.members any_over_SP_age = benunit.any(person("is_SP_age", period)) p = parameters(period).gov.dwp.housing_benefit.means_test.capital - household_capital = sum(household(source, period) for source in p.sources) + household_capital = valued_capital( + lambda variable: household(variable, period), p.sources, p.sale_expenses + ) benunit_adults = add(benunit, period, ["is_adult"]) household_adults = benunit.max( person.household.sum(person.household.members("is_adult", period)) diff --git a/policyengine_uk/variables/gov/dwp/income_support_assessable_capital.py b/policyengine_uk/variables/gov/dwp/income_support_assessable_capital.py index e497c670f8..2afff9bedf 100644 --- a/policyengine_uk/variables/gov/dwp/income_support_assessable_capital.py +++ b/policyengine_uk/variables/gov/dwp/income_support_assessable_capital.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.capital_valuation import valued_capital class income_support_assessable_capital(Variable): @@ -7,7 +8,8 @@ class income_support_assessable_capital(Variable): label = "Assessable capital for Income Support" documentation = ( "Household capital apportioned to the benefit unit for the Income Support " - "capital test. Because the dataset only stores these stocks at household " + "capital test, valued at market value less 10% where a sale would incur " + "expenses and less any debt secured on it (reg. 49). Because the dataset only stores these stocks at household " "level, the model allocates full household capital to any benunit on the " "IS claim path and only falls back to an adult-share proxy when nobody in " "the household is on that path." @@ -27,8 +29,10 @@ def formula(benunit, period, parameters): # any benunit on the IS claim path gets the full observed household total. # If nobody in the household is on that path, fall back to an all-adults # proxy so direct inspection still returns a usable value. - household_capital = sum( - benunit.max(person.household(source, period)) for source in sources + household_capital = valued_capital( + lambda variable: benunit.max(person.household(variable, period)), + sources, + IS.means_test.capital.sale_expenses, ) benunit_adults = add(benunit, period, ["is_adult"]) household_claiming_adults = benunit.max( diff --git a/policyengine_uk/variables/gov/dwp/jsa_income_assessable_capital.py b/policyengine_uk/variables/gov/dwp/jsa_income_assessable_capital.py index 2483cc9945..8fe20569d8 100644 --- a/policyengine_uk/variables/gov/dwp/jsa_income_assessable_capital.py +++ b/policyengine_uk/variables/gov/dwp/jsa_income_assessable_capital.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.capital_valuation import valued_capital class jsa_income_assessable_capital(Variable): @@ -7,7 +8,8 @@ class jsa_income_assessable_capital(Variable): label = "Assessable capital for income-based JSA" documentation = ( "Household capital apportioned to the benefit unit for the income-based " - "JSA capital test. Because the dataset only stores these stocks at " + "JSA capital test, valued at market value less 10% where a sale would " + "incur expenses and less any debt secured on it (reg. 111). Because the dataset only stores these stocks at " "household level, the model allocates full household capital to any " "benunit with a reported income-based JSA award and only falls back to " "an adult-share proxy when nobody in the household is on that reported " @@ -23,8 +25,10 @@ def formula(benunit, period, parameters): person = benunit.members claiming_jsa_income = add(benunit, period, ["jsa_income_reported"]) > 0 - household_capital = sum( - benunit.max(person.household(source, period)) for source in sources + household_capital = valued_capital( + lambda variable: benunit.max(person.household(variable, period)), + sources, + JSA.capital.sale_expenses, ) benunit_adults = add(benunit, period, ["is_adult"]) household_reporting_claimants = benunit.max( diff --git a/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_assessable_capital.py b/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_assessable_capital.py index 9f4c1fde97..068fbc1872 100644 --- a/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_assessable_capital.py +++ b/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_assessable_capital.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.capital_valuation import valued_capital class pension_credit_assessable_capital(Variable): @@ -7,7 +8,8 @@ class pension_credit_assessable_capital(Variable): label = "Pension Credit assessable capital" documentation = ( "Pension Credit capital counted from the configured capital sources, " - "split only across pension-age adults in the household so pensioner " + "each valued at market value less 10% where a sale would incur " + "expenses and less any debt secured on it (reg. 19), split only across pension-age adults in the household so pensioner " "couples pool capital together without dilution by unrelated working-" "age adults." ) @@ -19,7 +21,9 @@ def formula(benunit, period, parameters): household = benunit.household person = benunit.members p = parameters(period).gov.dwp.pension_credit.income.capital - household_capital = sum(household(source, period) for source in p.sources) + household_capital = valued_capital( + lambda variable: household(variable, period), p.sources, p.sale_expenses + ) any_pension_age = benunit.any(person("is_SP_age", period)) benunit_pension_age_adults = benunit.sum(person("is_SP_age", period)) household_pension_age_adults = benunit.max( diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/uc_assessable_capital.py b/policyengine_uk/variables/gov/dwp/universal_credit/uc_assessable_capital.py index eef9c8f729..d2f0125a76 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/uc_assessable_capital.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/uc_assessable_capital.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.capital_valuation import valued_capital class uc_assessable_capital(Variable): @@ -7,7 +8,9 @@ class uc_assessable_capital(Variable): label = "Universal Credit assessable capital" documentation = ( "Universal Credit capital counted from the configured capital sources, " - "with benunit-reported overrides when available." + "each valued at market value less 10% where a sale would incur " + "expenses and less any debt secured on it (reg. 49(1)), with " + "benunit-reported overrides when available." ) definition_period = YEAR unit = GBP @@ -16,8 +19,10 @@ class uc_assessable_capital(Variable): def formula(benunit, period, parameters): household = benunit.household p = parameters(period).gov.dwp.universal_credit.means_test - household_capital = sum( - household(source, period) for source in p.capital.sources + household_capital = valued_capital( + lambda variable: household(variable, period), + p.capital.sources, + p.capital.sale_expenses, ) benunit_adults = add(benunit, period, ["is_adult"]) household_reported_capital = household("household_uc_reported_capital", period) diff --git a/policyengine_uk/variables/input/non_residential_property_secured_debt.py b/policyengine_uk/variables/input/non_residential_property_secured_debt.py new file mode 100644 index 0000000000..3dc39a2996 --- /dev/null +++ b/policyengine_uk/variables/input/non_residential_property_secured_debt.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class non_residential_property_secured_debt(Variable): + label = "debt secured on non-residential property" + documentation = ( + "Amount owed on mortgages and other charges secured on non-residential " + "property the household owns. Means tests deduct it from that " + "property's value (UC Regs 2013 reg. 49(1)(b) and its legacy " + "equivalents)." + ) + entity = Household + definition_period = YEAR + value_type = float + unit = GBP + quantity_type = STOCK + uprating = "gov.economic_assumptions.indices.obr.per_capita.gdp" diff --git a/policyengine_uk/variables/input/other_residential_property_secured_debt.py b/policyengine_uk/variables/input/other_residential_property_secured_debt.py new file mode 100644 index 0000000000..50ec795c0d --- /dev/null +++ b/policyengine_uk/variables/input/other_residential_property_secured_debt.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class other_residential_property_secured_debt(Variable): + label = "debt secured on other residential property" + documentation = ( + "Amount owed on mortgages and other charges secured on residential " + "property the household owns other than the main residence, such as a " + "buy-to-let mortgage. Means tests deduct it from that property's value " + "(UC Regs 2013 reg. 49(1)(b) and its legacy equivalents)." + ) + entity = Household + definition_period = YEAR + value_type = float + unit = GBP + quantity_type = STOCK + uprating = "gov.economic_assumptions.indices.obr.per_capita.gdp" diff --git a/policyengine_uk/variables/input/owned_land_secured_debt.py b/policyengine_uk/variables/input/owned_land_secured_debt.py new file mode 100644 index 0000000000..b58b570051 --- /dev/null +++ b/policyengine_uk/variables/input/owned_land_secured_debt.py @@ -0,0 +1,16 @@ +from policyengine_uk.model_api import * + + +class owned_land_secured_debt(Variable): + label = "debt secured on owned land" + documentation = ( + "Amount owed on mortgages and other charges secured on land-only plots " + "the household owns. Means tests deduct it from that land's value (UC " + "Regs 2013 reg. 49(1)(b) and its legacy equivalents)." + ) + entity = Household + definition_period = YEAR + value_type = float + unit = GBP + quantity_type = STOCK + uprating = "gov.economic_assumptions.indices.obr.per_capita.gdp" From 0d315ed29e1e8365349fa3fa6d6b44d5adf97c1e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 30 Sep 2026 22:07:34 -0400 Subject: [PATCH 2/6] Tighten citations and tests from the adversarial review - Each programme's sale-expense parameters now cite its GB and NI regulations, the guidance paragraph that orders the 10% before the encumbrance, and per-asset guidance with exact PDF page anchors (DMG ch 52 for ESA, HBGM Annex F for HB savings, H1656/H1665/H1673-H1675 for UC). - The source-list descriptions and changelog say plainly that corporate_wealth also holds unit trusts, ISAs, employee share options and, in datasets built before the pension split, non-DB pension wealth. - The helper and secured-debt docs say debts net within a source category. - The property-test oracle fixes the sale-expense assets and the 10% itself instead of reading the parameters, checks pension-age HB, and runs on larger populations. New hand-computed cases cover HB second homes and premises, per-source flooring between two encumbered sources, pension-age HB, and a monthly secured debt. Co-Authored-By: Claude Opus 5.5 --- changelog.d/uc-capital-sale-expenses.fixed.md | 2 +- .../income/capital/sale_expenses/rate.yaml | 12 ++- .../income/capital/sale_expenses/sources.yaml | 29 +++++-- .../income/capital/sale_expenses/rate.yaml | 15 +++- .../income/capital/sale_expenses/sources.yaml | 25 ++++-- .../capital/sale_expenses/rate.yaml | 17 +++- .../capital/sale_expenses/sources.yaml | 39 ++++++--- .../capital/sale_expenses/rate.yaml | 12 ++- .../capital/sale_expenses/sources.yaml | 25 ++++-- .../income/capital/sale_expenses/rate.yaml | 12 ++- .../income/capital/sale_expenses/sources.yaml | 31 ++++--- .../capital/sale_expenses/rate.yaml | 8 +- .../capital/sale_expenses/sources.yaml | 32 +++++--- .../family/esa_income/esa_income_capital.yaml | 4 +- .../income_support_capital.yaml | 4 +- .../family/jsa_income/jsa_income_capital.yaml | 4 +- .../baseline/gov/dwp/capital_valuation.yaml | 81 ++++++++++++++++++- .../test_capital_valuation_properties.py | 68 +++++++++++----- .../tests/test_stock_capital_periods.py | 10 ++- policyengine_uk/utils/capital_valuation.py | 29 ++++--- .../non_residential_property_secured_debt.py | 6 +- ...other_residential_property_secured_debt.py | 5 +- .../input/owned_land_secured_debt.py | 7 +- 23 files changed, 357 insertions(+), 120 deletions(-) diff --git a/changelog.d/uc-capital-sale-expenses.fixed.md b/changelog.d/uc-capital-sale-expenses.fixed.md index 34790cb3d8..6b926ace41 100644 --- a/changelog.d/uc-capital-sale-expenses.fixed.md +++ b/changelog.d/uc-capital-sale-expenses.fixed.md @@ -1 +1 @@ -Value Universal Credit, Housing Benefit, Income Support, income-based JSA, income-related ESA and Pension Credit capital at market value less 10% where a sale would incur expenses (land, property and shares; not cash savings) and less any debt secured on the asset, as UC Regs 2013 reg. 49(1) and its legacy equivalents require. Adds secured-debt inputs for other residential property, non-residential property and land. +Value Universal Credit, Housing Benefit, Income Support, income-based JSA, income-related ESA and Pension Credit capital at market value less 10% where a sale would incur expenses and less any debt secured on the asset, as UC Regs 2013 reg. 49(1) and its legacy equivalents require. The 10% applies to land, property and corporate_wealth, not to cash savings; corporate_wealth also holds unit trusts, which have no costs of sale, and in datasets built before the private pension split it holds pension wealth, so the deduction reaches those too until the data separate them. Adds secured-debt inputs for other residential property, non-residential property and land. diff --git a/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/rate.yaml index 468d182cb9..e360c3ff9a 100644 --- a/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/rate.yaml +++ b/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/rate.yaml @@ -1,8 +1,8 @@ description: > - Share of the current market or surrender value deducted from income-related ESA - capital where there would be expenses attributable to sale. The deduction - is a flat 10% whatever the actual costs, taken before any incumbrance - secured on the asset. + Share of the current market or surrender value deducted from income-related + ESA capital where there would be expenses attributable to sale. It is a flat + 10% whatever the actual costs, taken from the gross value before any + encumbrance secured on the asset is deducted. values: 2008-10-27: 0.1 metadata: @@ -12,3 +12,7 @@ metadata: reference: - title: Employment and Support Allowance Regulations 2008 reg. 113(a) href: https://www.legislation.gov.uk/uksi/2008/794/regulation/113 + - title: Employment and Support Allowance Regulations (Northern Ireland) 2008 reg. 113(a) + href: https://www.legislation.gov.uk/nisr/2008/280/regulation/113 + - title: Decision Makers' Guide chapter 52, para. 52624 + href: https://assets.publishing.service.gov.uk/media/69d8f30ad3e08b8871b665ac/dmg-Ch-52.pdf#page=116 diff --git a/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/sources.yaml index b1946fe614..40f6f3fb9a 100644 --- a/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/sources.yaml +++ b/policyengine_uk/parameters/gov/dwp/ESA/income/capital/sale_expenses/sources.yaml @@ -1,11 +1,18 @@ description: > Capital sources whose sale would incur expenses, so that income-related ESA - values them at 90% of market value. Land and property always have costs of - sale. Shares are sold through a broker, so `corporate_wealth` is listed; it - also holds unit trusts, which have no costs of sale, but the dataset does - not separate them. `savings` is not listed because a bank or building - society account is valued at its balance and withdrawing money is not a sale - (see the Universal Credit parameter of the same name for the guidance). + values them at 90% of market value. Costs of sale normally arise where an + agent, broker, auctioneer, solicitor or accountant is needed, and real + property always has them (DMG 52622), so `owned_land`, + `other_residential_property_value` and `non_residential_property_value` are + listed. `savings` is not listed: a bank or building society account is + valued at its balance, and the costs of withdrawing money are not costs of + sale (DMG 52620-52623 and 52685). `corporate_wealth` is listed because + shares are valued less 10% for the costs of selling them (DMG 52671). + It is a mixed variable, though: it also holds unit trusts, which have no + costs of sale (DMG 52681), stocks and shares ISAs and employee share + options, and datasets built before private pension wealth was split out also + fold non-defined-benefit pension wealth into it, which is not capital at + all. The deduction reaches all of these until the data separate them. Sources not counted as income-related ESA capital are ignored. metadata: label: Income-related ESA capital sources with sale expenses @@ -14,6 +21,16 @@ metadata: reference: - title: Employment and Support Allowance Regulations 2008 reg. 113(a) href: https://www.legislation.gov.uk/uksi/2008/794/regulation/113 + - title: Employment and Support Allowance Regulations (Northern Ireland) 2008 reg. 113(a) + href: https://www.legislation.gov.uk/nisr/2008/280/regulation/113 + - title: Decision Makers' Guide chapter 52, paras. 52620-52622 + href: https://assets.publishing.service.gov.uk/media/69d8f30ad3e08b8871b665ac/dmg-Ch-52.pdf#page=115 + - title: Decision Makers' Guide chapter 52, para. 52623 + href: https://assets.publishing.service.gov.uk/media/69d8f30ad3e08b8871b665ac/dmg-Ch-52.pdf#page=116 + - title: Decision Makers' Guide chapter 52, para. 52671 + href: https://assets.publishing.service.gov.uk/media/69d8f30ad3e08b8871b665ac/dmg-Ch-52.pdf#page=126 + - title: Decision Makers' Guide chapter 52, paras. 52681 and 52685 + href: https://assets.publishing.service.gov.uk/media/69d8f30ad3e08b8871b665ac/dmg-Ch-52.pdf#page=128 values: 2008-10-27: - owned_land diff --git a/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/rate.yaml index ff2e4d5759..e67f83c653 100644 --- a/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/rate.yaml +++ b/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/rate.yaml @@ -1,8 +1,11 @@ description: > - Share of the current market or surrender value deducted from income-based JSA - capital where there would be expenses attributable to sale. The deduction - is a flat 10% whatever the actual costs, taken before any incumbrance - secured on the asset. + Share of the current market or surrender value deducted from income-based + JSA capital where there would be expenses attributable to sale. It is a flat + 10% whatever the actual costs, taken from the gross value before any + encumbrance secured on the asset is deducted. Before 1 October 2007 the same + deduction sat in reg. 111(a)(i) alongside a separate valuation for National + Savings Certificates; SI 2007/2618 substituted the regulation in its current + form. values: 1996-10-07: 0.1 metadata: @@ -12,3 +15,7 @@ metadata: reference: - title: Jobseeker's Allowance Regulations 1996 reg. 111(a) href: https://www.legislation.gov.uk/uksi/1996/207/regulation/111 + - title: Jobseeker's Allowance Regulations (Northern Ireland) 1996 reg. 111(a), as substituted by S.R. 2007/396 reg. 7(11) + href: https://www.legislation.gov.uk/nisr/2007/396/regulation/7 + - title: Decision Makers' Guide chapter 29, para. 29624 + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=125 diff --git a/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/sources.yaml index 1a64a5ee2c..538833841b 100644 --- a/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/sources.yaml +++ b/policyengine_uk/parameters/gov/dwp/JSA/income/capital/sale_expenses/sources.yaml @@ -1,12 +1,19 @@ description: > Capital sources whose sale would incur expenses, so that income-based JSA - values them at 90% of market value. Land and property always have costs of - sale. Shares are sold through a broker, so `corporate_wealth` is listed; it - also holds unit trusts, which have no costs of sale, but the dataset does - not separate them. `savings` is not listed because a bank or building - society account is valued at its balance and withdrawing money is not a sale - (DMG 29620-29623, 29681 and 29685). Sources not counted as income-based JSA - capital are ignored. + values them at 90% of market value. Costs of sale normally arise where an + agent, broker, auctioneer, solicitor or accountant is needed, and real + property always has them (DMG 29622), so `owned_land`, + `other_residential_property_value` and `non_residential_property_value` are + listed. `savings` is not listed: a bank or building society account is + valued at its balance, and the costs of withdrawing money are not costs of + sale (DMG 29620-29623 and 29685). `corporate_wealth` is listed because + shares are valued less 10% for the costs of selling them (DMG 29671). It is + a mixed variable, though: it also holds unit trusts, which have no costs of + sale (DMG 29681), stocks and shares ISAs and employee share options, and + datasets built before private pension wealth was split out also fold non- + defined-benefit pension wealth into it, which is not capital at all. The + deduction reaches all of these until the data separate them. Sources not + counted as income-based JSA capital are ignored. metadata: label: Income-based JSA capital sources with sale expenses period: year @@ -14,8 +21,12 @@ metadata: reference: - title: Jobseeker's Allowance Regulations 1996 reg. 111(a) href: https://www.legislation.gov.uk/uksi/1996/207/regulation/111 + - title: Jobseeker's Allowance Regulations (Northern Ireland) 1996 reg. 111(a), as substituted by S.R. 2007/396 reg. 7(11) + href: https://www.legislation.gov.uk/nisr/2007/396/regulation/7 - title: Decision Makers' Guide chapter 29, paras. 29620-29623 href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=124 + - title: Decision Makers' Guide chapter 29, para. 29671 + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=137 - title: Decision Makers' Guide chapter 29, paras. 29681 and 29685 href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=139 values: diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/rate.yaml index f496742f77..45b58092df 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/rate.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/rate.yaml @@ -1,8 +1,11 @@ description: > Share of the current market or surrender value deducted from Housing Benefit - capital where there would be expenses attributable to sale. The deduction - is a flat 10% whatever the actual costs, taken before any encumbrance - secured on the asset. + capital where there would be expenses attributable to sale. It is a flat 10% + whatever the actual costs, taken from the gross value before any encumbrance + secured on the asset is deducted. Before 1 October 2007 the same deduction + sat in reg. 47(a)(i) (reg. 45(a)(i) at pension age) alongside a separate + valuation for National Savings Certificates; SI 2007/2618 substituted the + regulation in its current form. values: 2006-04-10: 0.1 metadata: @@ -14,3 +17,11 @@ metadata: href: https://www.legislation.gov.uk/uksi/2006/213/regulation/47 - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 reg. 45(a) href: https://www.legislation.gov.uk/uksi/2006/214/regulation/45 + - title: The Housing Benefit Regulations (Northern Ireland) 2006 reg. 44(a) + href: https://www.legislation.gov.uk/nisr/2006/405/regulation/44 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations (Northern Ireland) 2006 reg. 43(a) + href: https://www.legislation.gov.uk/nisr/2006/406/regulation/43 + - title: Housing Benefit Guidance Manual BW1, para. W1.430 + href: https://assets.publishing.service.gov.uk/media/5a749328ed915d0e8e3994c0/hbgm-bw1-assessment-of-capital.pdf#page=36 + - title: MH v London Borough of Waltham Forest (HB) [2016] UKUT 161 (AAC), para. 43 + href: https://www.gov.uk/administrative-appeals-tribunal-decisions/mh-v-london-borough-of-waltham-forest-hb-2016-ukut-161-aac diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml index cb504ed3c4..ad9b7d587c 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml @@ -1,12 +1,19 @@ description: > Capital sources whose sale would incur expenses, so that Housing Benefit - values them at 90% of market value. Land and property always have costs of - sale. Shares are sold through a broker, so `corporate_wealth` is listed; it - also holds unit trusts, which have no costs of sale, but the dataset does - not separate them. `savings` is not listed because a bank or building - society account is valued at its balance and withdrawing money is not a sale - (HBGM W1.430, W1.530-W1.531, P1.430 and P1.530-P1.531). Sources not counted - as Housing Benefit capital are ignored. + values them at 90% of market value. Costs of sale normally arise where an + agent, broker, auctioneer, solicitor or accountant is needed, and real + property always has them (HBGM W1.430), so `owned_land`, + `other_residential_property_value` and `non_residential_property_value` are + listed. `savings` is not listed: a bank or building society account is + valued at its balance, and the costs of withdrawing money are not costs of + sale (HBGM BW1 Annex F and BP1 F2.03). `corporate_wealth` is listed because + shares are valued less 10% for the costs of selling them (HBGM W1.513). It + is a mixed variable, though: it also holds unit trusts, which have no costs + of sale (HBGM W1.530-W1.531), stocks and shares ISAs and employee share + options, and datasets built before private pension wealth was split out also + fold non-defined-benefit pension wealth into it, which is not capital at + all. The deduction reaches all of these until the data separate them. + Sources not counted as Housing Benefit capital are ignored. metadata: label: Housing Benefit capital sources with sale expenses period: year @@ -16,10 +23,24 @@ metadata: href: https://www.legislation.gov.uk/uksi/2006/213/regulation/47 - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 reg. 45(a) href: https://www.legislation.gov.uk/uksi/2006/214/regulation/45 - - title: Housing Benefit Guidance Manual BW1, paras. W1.430 and W1.530-W1.531 + - title: The Housing Benefit Regulations (Northern Ireland) 2006 reg. 44(a) + href: https://www.legislation.gov.uk/nisr/2006/405/regulation/44 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations (Northern Ireland) 2006 reg. 43(a) + href: https://www.legislation.gov.uk/nisr/2006/406/regulation/43 + - title: Housing Benefit Guidance Manual BW1, para. W1.430 href: https://assets.publishing.service.gov.uk/media/5a749328ed915d0e8e3994c0/hbgm-bw1-assessment-of-capital.pdf#page=36 - - title: Housing Benefit Guidance Manual BP1, paras. P1.430 and P1.530-P1.531 + - title: Housing Benefit Guidance Manual BP1, para. P1.430 href: https://assets.publishing.service.gov.uk/media/5a7ec5d840f0b6230268b71f/hbgm-bp1-assessment-of-capital.pdf#page=31 + - title: Housing Benefit Guidance Manual BW1, para. W1.513 + href: https://assets.publishing.service.gov.uk/media/5a749328ed915d0e8e3994c0/hbgm-bw1-assessment-of-capital.pdf#page=43 + - title: Housing Benefit Guidance Manual BW1, paras. W1.530-W1.531 + href: https://assets.publishing.service.gov.uk/media/5a749328ed915d0e8e3994c0/hbgm-bw1-assessment-of-capital.pdf#page=43 + - title: Housing Benefit Guidance Manual BP1, paras. P1.513 and P1.530-P1.531 + href: https://assets.publishing.service.gov.uk/media/5a7ec5d840f0b6230268b71f/hbgm-bp1-assessment-of-capital.pdf#page=38 + - title: Housing Benefit Guidance Manual BW1, Annex F + href: https://assets.publishing.service.gov.uk/media/5a749328ed915d0e8e3994c0/hbgm-bw1-assessment-of-capital.pdf#page=93 + - title: Housing Benefit Guidance Manual BP1, paras. F2.00-F2.03 + href: https://assets.publishing.service.gov.uk/media/5a7ec5d840f0b6230268b71f/hbgm-bp1-assessment-of-capital.pdf#page=83 values: 2006-04-10: - owned_land diff --git a/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml index 7cb86fe853..dd572337df 100644 --- a/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml +++ b/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml @@ -1,8 +1,10 @@ description: > Share of the current market or surrender value deducted from Income Support - capital where there would be expenses attributable to sale. The deduction - is a flat 10% whatever the actual costs, taken before any incumbrance - secured on the asset. + capital where there would be expenses attributable to sale. It is a flat 10% + whatever the actual costs, taken from the gross value before any encumbrance + secured on the asset is deducted. Before 1 October 2007 the same deduction + sat in reg. 49(a)(i) alongside a separate valuation for National Savings + Certificates; SI 2007/2618 substituted the regulation in its current form. values: 2010-01-01: 0.1 metadata: @@ -12,3 +14,7 @@ metadata: reference: - title: Income Support (General) Regulations 1987 reg. 49(a) href: https://www.legislation.gov.uk/uksi/1987/1967/regulation/49 + - title: Income Support (General) Regulations (Northern Ireland) 1987 reg. 49(a), as substituted by S.R. 2007/396 reg. 4(10) + href: https://www.legislation.gov.uk/nisr/2007/396/regulation/4 + - title: Decision Makers' Guide chapter 29, para. 29624 + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=125 diff --git a/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/sources.yaml index 0af0f836b0..baa3504bda 100644 --- a/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/sources.yaml +++ b/policyengine_uk/parameters/gov/dwp/income_support/means_test/capital/sale_expenses/sources.yaml @@ -1,12 +1,19 @@ description: > Capital sources whose sale would incur expenses, so that Income Support - values them at 90% of market value. Land and property always have costs of - sale. Shares are sold through a broker, so `corporate_wealth` is listed; it - also holds unit trusts, which have no costs of sale, but the dataset does - not separate them. `savings` is not listed because a bank or building - society account is valued at its balance and withdrawing money is not a sale - (DMG 29620-29623, 29681 and 29685). Sources not counted as Income Support - capital are ignored. + values them at 90% of market value. Costs of sale normally arise where an + agent, broker, auctioneer, solicitor or accountant is needed, and real + property always has them (DMG 29622), so `owned_land`, + `other_residential_property_value` and `non_residential_property_value` are + listed. `savings` is not listed: a bank or building society account is + valued at its balance, and the costs of withdrawing money are not costs of + sale (DMG 29620-29623 and 29685). `corporate_wealth` is listed because + shares are valued less 10% for the costs of selling them (DMG 29671). It is + a mixed variable, though: it also holds unit trusts, which have no costs of + sale (DMG 29681), stocks and shares ISAs and employee share options, and + datasets built before private pension wealth was split out also fold non- + defined-benefit pension wealth into it, which is not capital at all. The + deduction reaches all of these until the data separate them. Sources not + counted as Income Support capital are ignored. metadata: label: Income Support capital sources with sale expenses period: year @@ -14,8 +21,12 @@ metadata: reference: - title: Income Support (General) Regulations 1987 reg. 49(a) href: https://www.legislation.gov.uk/uksi/1987/1967/regulation/49 + - title: Income Support (General) Regulations (Northern Ireland) 1987 reg. 49(a), as substituted by S.R. 2007/396 reg. 4(10) + href: https://www.legislation.gov.uk/nisr/2007/396/regulation/4 - title: Decision Makers' Guide chapter 29, paras. 29620-29623 href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=124 + - title: Decision Makers' Guide chapter 29, para. 29671 + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=137 - title: Decision Makers' Guide chapter 29, paras. 29681 and 29685 href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=139 values: diff --git a/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/rate.yaml index b344e9dcf2..09c5550767 100644 --- a/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/rate.yaml +++ b/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/rate.yaml @@ -1,8 +1,10 @@ description: > Share of the current market or surrender value deducted from Pension Credit - capital where there would be expenses attributable to sale. The deduction - is a flat 10% whatever the actual costs, taken before any encumbrance - secured on the asset. + capital where there would be expenses attributable to sale. It is a flat 10% + whatever the actual costs, taken from the gross value before any encumbrance + secured on the asset is deducted. Before 1 October 2007 the same deduction + sat in reg. 19(a)(i) alongside a separate valuation for National Savings + Certificates; SI 2007/2618 substituted the regulation in its current form. values: 2003-10-06: 0.1 metadata: @@ -12,3 +14,7 @@ metadata: reference: - title: State Pension Credit Regulations 2002 reg. 19(a) href: https://www.legislation.gov.uk/uksi/2002/1792/regulation/19 + - title: State Pension Credit Regulations (Northern Ireland) 2003 reg. 19(a) + href: https://www.legislation.gov.uk/nisr/2003/28/regulation/19 + - title: Decision Makers' Guide chapter 84, paras. 84712-84716 + href: https://assets.publishing.service.gov.uk/media/6a5e38bb8b7e4fa537e693d5/dmg-ch84.pdf#page=99 diff --git a/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/sources.yaml index da4dae9ae1..1dbbd6816f 100644 --- a/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/sources.yaml +++ b/policyengine_uk/parameters/gov/dwp/pension_credit/income/capital/sale_expenses/sources.yaml @@ -1,12 +1,19 @@ description: > Capital sources whose sale would incur expenses, so that Pension Credit - values them at 90% of market value. Land and property always have costs of - sale. Shares are sold through a broker, so `corporate_wealth` is listed; it - also holds unit trusts, which have no costs of sale, but the dataset does - not separate them. `savings` is not listed because a bank or building - society account is valued at its balance and withdrawing money is not a sale - (DMG 84712-84716, 84731 and 84772). Sources not counted as Pension Credit - capital are ignored. + values them at 90% of market value. Costs of sale normally arise where an + agent, broker, auctioneer, solicitor or accountant is needed, and real + property always has them (DMG 84714), so `owned_land`, + `other_residential_property_value` and `non_residential_property_value` are + listed. `savings` is not listed: a bank or building society account is + valued at its balance, and the costs of withdrawing money are not costs of + sale (DMG 84712-84715 and 84731). `corporate_wealth` is listed because + shares are valued less 10% for the costs of selling them (DMG 84763). It is + a mixed variable, though: it also holds unit trusts, which have no costs of + sale (DMG 84772), stocks and shares ISAs and employee share options, and + datasets built before private pension wealth was split out also fold non- + defined-benefit pension wealth into it, which is not capital at all. The + deduction reaches all of these until the data separate them. Sources not + counted as Pension Credit capital are ignored. metadata: label: Pension Credit capital sources with sale expenses period: year @@ -14,10 +21,16 @@ metadata: reference: - title: State Pension Credit Regulations 2002 reg. 19(a) href: https://www.legislation.gov.uk/uksi/2002/1792/regulation/19 - - title: Decision Makers' Guide chapter 84, paras. 84712-84716 + - title: State Pension Credit Regulations (Northern Ireland) 2003 reg. 19(a) + href: https://www.legislation.gov.uk/nisr/2003/28/regulation/19 + - title: Decision Makers' Guide chapter 84, paras. 84712-84715 href: https://assets.publishing.service.gov.uk/media/6a5e38bb8b7e4fa537e693d5/dmg-ch84.pdf#page=99 - - title: Decision Makers' Guide chapter 84, paras. 84731 and 84772 + - title: Decision Makers' Guide chapter 84, para. 84731 href: https://assets.publishing.service.gov.uk/media/6a5e38bb8b7e4fa537e693d5/dmg-ch84.pdf#page=102 + - title: Decision Makers' Guide chapter 84, para. 84763 + href: https://assets.publishing.service.gov.uk/media/6a5e38bb8b7e4fa537e693d5/dmg-ch84.pdf#page=107 + - title: Decision Makers' Guide chapter 84, para. 84772 + href: https://assets.publishing.service.gov.uk/media/6a5e38bb8b7e4fa537e693d5/dmg-ch84.pdf#page=109 values: 2003-10-06: - owned_land diff --git a/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/rate.yaml index 150561614f..fe3a72ab6b 100644 --- a/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/rate.yaml +++ b/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/rate.yaml @@ -1,8 +1,8 @@ description: > Share of the current market or surrender value deducted from Universal - Credit capital where there would be expenses attributable to sale. The - deduction is a flat 10% whatever the actual costs, taken before any - encumbrance secured on the asset. + Credit capital where there would be expenses attributable to sale. It is a + flat 10% whatever the actual costs, taken from the gross value before any + encumbrance secured on the asset is deducted. values: 2013-04-29: 0.1 metadata: @@ -12,5 +12,7 @@ metadata: reference: - title: The Universal Credit Regulations 2013 reg. 49(1)(a) href: https://www.legislation.gov.uk/uksi/2013/376/regulation/49 + - title: The Universal Credit Regulations (Northern Ireland) 2016 reg. 49(1)(a) + href: https://www.legislation.gov.uk/nisr/2016/216/regulation/49 - title: Advice for Decision Making chapter H1, paras. H1602-H1608 href: https://assets.publishing.service.gov.uk/media/6a5e0ac7a2662d4563fe39e0/adm-ch-h1.pdf#page=44 diff --git a/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml index 969e9ac619..fe25cbe7d8 100644 --- a/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml +++ b/policyengine_uk/parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml @@ -1,17 +1,19 @@ description: > Capital sources whose sale would incur expenses, so that Universal Credit - values them at 90% of market value. Real property always has costs of sale - (ADM H1606, citing R(IS) 21/93), so `owned_land`, + values them at 90% of market value. Costs of sale normally arise where an + agent, broker, auctioneer, solicitor or accountant is needed, and real + property always has them (ADM H1606), so `owned_land`, `other_residential_property_value` and `non_residential_property_value` are - listed. `savings` is not listed: the 10% applies only where selling needs - an agent, broker, solicitor or accountant (ADM H1604-H1605), the costs of - withdrawing money from a building society are not costs of sale (H1607), - and an account is valued at its balance (H1675). `corporate_wealth` is - listed because quoted shares are valued less 10% for costs of sale (H1665). - It also holds unit trusts, which have no costs of sale (H1674), and stocks - and shares ISAs, which the guidance values at their withdrawal value - (H1656); the dataset does not separate these, so the deduction also - reaches them. Sources not counted as Universal Credit capital are ignored. + listed. `savings` is not listed: a bank or building society account is + valued at its balance, and the costs of withdrawing money are not costs of + sale (ADM H1604-H1607 and H1675). `corporate_wealth` is listed because + shares are valued less 10% for the costs of selling them (ADM H1665). It is + a mixed variable, though: it also holds unit trusts, which have no costs of + sale (ADM H1674), stocks and shares ISAs and employee share options, and + datasets built before private pension wealth was split out also fold non- + defined-benefit pension wealth into it, which is not capital at all. The + deduction reaches all of these until the data separate them. Sources not + counted as Universal Credit capital are ignored. metadata: label: Universal Credit capital sources with sale expenses period: year @@ -19,10 +21,16 @@ metadata: reference: - title: The Universal Credit Regulations 2013 reg. 49(1)(a) href: https://www.legislation.gov.uk/uksi/2013/376/regulation/49 + - title: The Universal Credit Regulations (Northern Ireland) 2016 reg. 49(1)(a) + href: https://www.legislation.gov.uk/nisr/2016/216/regulation/49 - title: Advice for Decision Making chapter H1, paras. H1604-H1607 href: https://assets.publishing.service.gov.uk/media/6a5e0ac7a2662d4563fe39e0/adm-ch-h1.pdf#page=44 - - title: Advice for Decision Making chapter H1, paras. H1665 and H1673-H1675 + - title: Advice for Decision Making chapter H1, para. H1656 + href: https://assets.publishing.service.gov.uk/media/6a5e0ac7a2662d4563fe39e0/adm-ch-h1.pdf#page=55 + - title: Advice for Decision Making chapter H1, para. H1665 href: https://assets.publishing.service.gov.uk/media/6a5e0ac7a2662d4563fe39e0/adm-ch-h1.pdf#page=57 + - title: Advice for Decision Making chapter H1, paras. H1673-H1675 + href: https://assets.publishing.service.gov.uk/media/6a5e0ac7a2662d4563fe39e0/adm-ch-h1.pdf#page=59 values: 2013-04-29: - owned_land diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml index abe48a7b5d..106352bad5 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml @@ -212,6 +212,6 @@ corporate_wealth: 2_000 private_pension_wealth: 150_000 output: - # Savings at face value; land, shares and property less 10% for the - # expenses of sale (ESA Regs 2008 reg. 113(a)): 1,000 + 90% of 2,000. + # Savings at face value; shares less 10% for the expenses of sale + # (ESA Regs 2008 reg. 113(a)): 1,000 + 90% of 2,000. esa_income_assessable_capital: 2_800 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_capital.yaml index f90e5f1a9d..85f0ecfb12 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_capital.yaml @@ -235,6 +235,6 @@ corporate_wealth: 2000 private_pension_wealth: 150000 output: - # Savings at face value; land, shares and property less 10% for the - # expenses of sale (IS Regs 1987 reg. 49(a)): 1,000 + 90% of 2,000. + # Savings at face value; shares less 10% for the expenses of sale + # (IS Regs 1987 reg. 49(a)): 1,000 + 90% of 2,000. income_support_assessable_capital: 2800 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/jsa_income/jsa_income_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/jsa_income/jsa_income_capital.yaml index bc50925503..ffea263934 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/jsa_income/jsa_income_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/jsa_income/jsa_income_capital.yaml @@ -186,6 +186,6 @@ corporate_wealth: 2_000 private_pension_wealth: 150_000 output: - # Savings at face value; land, shares and property less 10% for the - # expenses of sale (JSA Regs 1996 reg. 111(a)): 1,000 + 90% of 2,000. + # Savings at face value; shares less 10% for the expenses of sale + # (JSA Regs 1996 reg. 111(a)): 1,000 + 90% of 2,000. jsa_income_assessable_capital: 2_800 diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml index 840b084ec1..1b4870b502 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml @@ -1,8 +1,9 @@ # Capital is valued at market value less 10% where a sale would incur # expenses, and less any encumbrance secured on it: UC Regs 2013 reg. 49(1); # HB Regs 2006 reg. 47; IS Regs 1987 reg. 49; JSA Regs 1996 reg. 111; ESA Regs -# 2008 reg. 113; SPC Regs 2002 reg. 19. Savings in a bank or building society -# have no sale expenses; land, property and shares do (ADM H1604-H1607). +# 2008 reg. 113; SPC Regs 2002 reg. 19. A bank or building society account is +# valued at its balance (ADM H1604-H1607, H1675); land and property always have +# costs of sale (H1606) and shares are valued less 10% (H1665). # Expected values are worked by hand from those provisions. - name: UC values a mortgaged holiday home as in ADM H1602 @@ -216,3 +217,79 @@ pension_credit_assessable_capital: 19_000 # 18 steps of 500 above 10,000 at 1 a week: 18 * 52. pension_credit_deemed_income: 936 + +- name: UC floors each encumbered source at nil on its own + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + benunits: + benunit: + members: person + households: + household: + members: person + # The second home is in negative equity (90,000 - 150,000), so it is + # valued at nil; the business premises keep 90% of 10,000. Netting the + # debts across both would wrongly give nil. + other_residential_property_value: 100_000 + other_residential_property_secured_debt: 150_000 + non_residential_property_value: 10_000 + output: + uc_assessable_capital: 9_000 + +- name: Housing Benefit values mortgaged second homes and premises less sale expenses + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 30 + in_social_housing: true + housing_benefit_reported: 1 + benunits: + benunit: + members: person + would_claim_uc: false + households: + household: + members: person + # 1,000 + (90% of 50,000 - 30,000) + max(0, 90% of 20,000 - 25,000) + # = 1,000 + 15,000 + 0 = 16,000, at the limit (HB Regs 2006 reg. 47). + savings: 1_000 + other_residential_property_value: 50_000 + other_residential_property_secured_debt: 30_000 + non_residential_property_value: 20_000 + non_residential_property_secured_debt: 25_000 + output: + housing_benefit_assessable_capital: 16_000 + # 40 steps of 250 above 6,000 at 1 a week: 40 * 52. + housing_benefit_tariff_income: 2_080 + housing_benefit_eligible: true + +- name: Pension-age Housing Benefit values encumbered land less sale expenses + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 70 + benunits: + benunit: + members: person + households: + household: + members: person + # 90% of 200,000 - 50,000 = 130,000 (HB (SPC) Regs 2006 reg. 45). Its + # Pension Credit deemed income, 240 steps of 500 above 10,000 at 1 a + # week (12,480 a year), exceeds the 12,376 guarantee, so there is no + # guarantee credit to disregard the capital. + owned_land: 200_000 + owned_land_secured_debt: 50_000 + output: + pension_credit_assessable_capital: 130_000 + pension_credit_deemed_income: 12_480 + guarantee_credit: 0 + housing_benefit_assessable_capital: 130_000 diff --git a/policyengine_uk/tests/test_capital_valuation_properties.py b/policyengine_uk/tests/test_capital_valuation_properties.py index 76a7aa5d1d..3ccf6d7eb3 100644 --- a/policyengine_uk/tests/test_capital_valuation_properties.py +++ b/policyengine_uk/tests/test_capital_valuation_properties.py @@ -5,8 +5,9 @@ be expenses attributable to sale, and less any encumbrance secured on it (UC Regs 2013 reg. 49(1); HB Regs 2006 reg. 47; HB (SPC) Regs 2006 reg. 45; IS Regs 1987 reg. 49; JSA Regs 1996 reg. 111; ESA Regs 2008 reg. 113; SPC Regs -2002 reg. 19). Savings in a bank or building society incur no sale expenses; -land, property and shares do. +2002 reg. 19). A bank or building society account is valued at its balance +(ADM H1675); land and property always have costs of sale (H1606) and shares +are valued less 10% (H1665). Invariants, for any generated population of single-adult households: @@ -15,11 +16,15 @@ 2. Cash only: a household holding only savings has the same capital with the deduction on or off. 3. Differential: capital equals a direct implementation of the regulation, - savings + sum over sources of max(0, 90% of value - secured debt). + savings + sum over sources of max(0, 90% of value - secured debt), where + the test itself fixes which assets take the 10% (land, property and + shares, not cash), so a wrong parameter list fails it. 4. Monotone: a higher sale-expense rate, or more secured debt, never raises capital. -5. Isolation: debt secured on one asset never takes capital below the value - of the household's other assets, and capital is never negative. +5. Isolation: debt secured on one source never takes capital below the value + of the household's unencumbered sources, and capital is never negative. + (Isolation between two encumbered sources is pinned by the differential and + by a YAML case.) """ from functools import reduce @@ -38,9 +43,10 @@ suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], ) # Assessable capital variable -> parameter node holding its sources and -# sale-expense rule. Pension Credit counts only pension-age adults; the -# others are tested on working-age adults (pension-age Housing Benefit -# disregards all capital for Guarantee Credit recipients). +# sale-expense rule. Pension Credit counts only pension-age adults; Housing +# Benefit is checked at both ages, disregarding all capital for pension-age +# Guarantee Credit recipients (HB (SPC) Regs 2006 reg. 26); the others are +# checked on working-age adults. PROGRAMMES = { "uc_assessable_capital": "gov.dwp.universal_credit.means_test.capital", "housing_benefit_assessable_capital": "gov.dwp.housing_benefit.means_test.capital", @@ -50,6 +56,16 @@ "pension_credit_assessable_capital": "gov.dwp.pension_credit.income.capital", } PENSION_AGE_ONLY = {"pension_credit_assessable_capital"} +# The assets whose sale incurs expenses, fixed here from the law rather than +# read from the parameters: real property always (ADM H1606), shares (H1665); +# never a bank or building society balance (H1675). +SALE_EXPENSE_ASSETS = { + "owned_land", + "other_residential_property_value", + "non_residential_property_value", + "corporate_wealth", +} +LEGAL_RATE = 0.1 ASSETS = [ "savings", "owned_land", @@ -99,14 +115,18 @@ def calculate(units, rate=None, debt_scale=1.0): situation=situation(units, debt_scale), reform=None if rate is None else rate_reform(rate), ) - return sim, {v: np.asarray(sim.calculate(v, YEAR), dtype=float) for v in PROGRAMMES} + values = {v: np.asarray(sim.calculate(v, YEAR), dtype=float) for v in PROGRAMMES} + values["guarantee_credit"] = np.asarray(sim.calculate("guarantee_credit", YEAR)) + return sim, values def parameter_node(sim, path): return reduce(getattr, path.split("."), sim.tax_benefit_system.parameters(YEAR)) -def applies(variable, unit): +def applies(variable, unit, guarantee_credit=0.0): + if variable == "housing_benefit_assessable_capital": + return unit["age"] < 67 or guarantee_credit <= 0 return (unit["age"] >= 67) == (variable in PENSION_AGE_ONLY) @@ -115,8 +135,8 @@ def expected_capital(unit, node): total = 0.0 for source in node.sources: value = unit["assets"][source] - if source in node.sale_expenses.sources: - value *= 1 - node.sale_expenses.rate + if source in SALE_EXPENSE_ASSETS: + value *= 1 - LEGAL_RATE if source in DEBTS: value = max(0.0, value - unit["debts"][DEBTS[source]]) total += value @@ -128,25 +148,31 @@ def close(a, b): @PROPERTY_SETTINGS -@given(st.lists(households(), min_size=1, max_size=30)) +@given(st.lists(households(), min_size=20, max_size=200)) def test_valuation_matches_the_regulation_and_never_adds_capital(units): sim, valued = calculate(units) _, full = calculate(units, rate=0.0, debt_scale=0.0) for variable, path in PROGRAMMES.items(): node = parameter_node(sim, path) - assert node.sale_expenses.rate == 0.1 + assert node.sale_expenses.rate == LEGAL_RATE assert "savings" in node.sources - assert "savings" not in node.sale_expenses.sources + counted = set(node.sources) + assert set(node.sale_expenses.sources) & counted == ( + SALE_EXPENSE_ASSETS & counted + ), variable for i, unit in enumerate(units): + gc = valued["guarantee_credit"][i] assert valued[variable][i] >= 0, (variable, unit) assert valued[variable][i] <= full[variable][i] + 0.01, (variable, unit) - if applies(variable, unit): + if variable == "housing_benefit_assessable_capital" and unit["age"] >= 67: + if gc > 0: + assert valued[variable][i] == 0, unit + if applies(variable, unit, gc): expected = expected_capital(unit, node) assert close(valued[variable][i], expected), (variable, unit) # Debt secured on property never reaches the other assets. floor = sum( - unit["assets"][s] - * (1 - node.sale_expenses.rate * (s in node.sale_expenses.sources)) + unit["assets"][s] * (1 - LEGAL_RATE * (s in SALE_EXPENSE_ASSETS)) for s in node.sources if s not in DEBTS ) @@ -154,20 +180,20 @@ def test_valuation_matches_the_regulation_and_never_adds_capital(units): @PROPERTY_SETTINGS -@given(st.lists(households(cash_only=True), min_size=1, max_size=30)) +@given(st.lists(households(cash_only=True), min_size=20, max_size=200)) def test_cash_only_households_have_no_deduction(units): _, valued = calculate(units) _, full = calculate(units, rate=0.0) for variable in PROGRAMMES: assert np.allclose(valued[variable], full[variable]), variable for i, unit in enumerate(units): - if applies(variable, unit): + if applies(variable, unit, valued["guarantee_credit"][i]): assert close(valued[variable][i], unit["assets"]["savings"]), variable @PROPERTY_SETTINGS @given( - st.lists(households(), min_size=1, max_size=30), + st.lists(households(), min_size=20, max_size=200), st.floats(0, 0.5), st.floats(0, 0.5), st.floats(0, 2), diff --git a/policyengine_uk/tests/test_stock_capital_periods.py b/policyengine_uk/tests/test_stock_capital_periods.py index e694045d13..eead7689d9 100644 --- a/policyengine_uk/tests/test_stock_capital_periods.py +++ b/policyengine_uk/tests/test_stock_capital_periods.py @@ -15,6 +15,7 @@ def test_uc_capital_stocks_are_not_prorated_in_monthly_calculations(): "members": ["person"], "savings": {"2026": 12_000}, "other_residential_property_value": {"2026": 12_000}, + "other_residential_property_secured_debt": {"2026": 5_000}, "corporate_wealth": {"2026": 12_000}, } }, @@ -23,9 +24,14 @@ def test_uc_capital_stocks_are_not_prorated_in_monthly_calculations(): assert simulation.calculate("savings", "2026-01")[0] == 12_000 assert simulation.calculate("corporate_wealth", "2026-01")[0] == 12_000 + assert ( + simulation.calculate("other_residential_property_secured_debt", "2026-01")[0] + == 5_000 + ) # Savings at face value; property and shares less 10% for the expenses - # of sale (UC Regs 2013 reg. 49(1)(a)): 12,000 + 2 * 10,800. - assert simulation.calculate("uc_assessable_capital", "2026-01")[0] == 33_600 + # of sale, and the property less its mortgage (UC Regs 2013 reg. 49(1)): + # 12,000 + (10,800 - 5,000) + 10,800. + assert simulation.calculate("uc_assessable_capital", "2026-01")[0] == 28_600 assert not simulation.calculate("is_uc_eligible", "2026-01")[0] diff --git a/policyengine_uk/utils/capital_valuation.py b/policyengine_uk/utils/capital_valuation.py index 2e70896a1a..8c76af629d 100644 --- a/policyengine_uk/utils/capital_valuation.py +++ b/policyengine_uk/utils/capital_valuation.py @@ -1,19 +1,22 @@ """Value means-tested capital as the capital-valuation regulations require. -Universal Credit and each legacy means test value capital in the United -Kingdom "at its current market or surrender value less (a) where there would -be expenses attributable to sale, 10% [...]; and (b) the amount of any -encumbrances secured on it" (UC Regs 2013 reg. 49(1) and its legacy -equivalents). Each programme sets its own rate and the capital sources whose -sale would incur expenses in a ``capital.sale_expenses`` parameter node. +Universal Credit calculates capital "at its current market value or surrender +value less— (a) where there would be expenses attributable to sale, 10%; and +(b) the amount of any encumbrances secured on it" (UC Regs 2013 reg. 49(1)). +The legacy means tests have equivalent rules (HB Regs 2006 reg. 47, IS Regs +1987 reg. 49, JSA Regs 1996 reg. 111, ESA Regs 2008 reg. 113, SPC Regs 2002 +reg. 19). Each programme sets its own rate and the capital sources whose sale +would incur expenses in a ``capital.sale_expenses`` parameter node. """ from policyengine_core.model_api import max_ -# Household inputs holding the debts secured on each capital source, such as -# a mortgage on a second property. The encumbrance is deducted only from the -# asset it is secured on, so negative equity in one asset never reduces the -# value of another (ADM H1615-H1616). +# Household inputs holding the debt secured on each capital source, such as a +# mortgage on a second property. The debt is deducted from the source it is +# secured on and that source is floored at nil, so negative equity in one +# source never reduces another (ADM H1615-H1616). Each source is a category +# summed over the household's assets, so within a category the debts on one +# asset still offset equity in another. SECURED_DEBT = { "other_residential_property_value": "other_residential_property_secured_debt", "non_residential_property_value": "non_residential_property_secured_debt", @@ -25,9 +28,9 @@ def valued_capital(value_of, sources, sale_expenses): """Sum ``sources`` at market value less sale expenses and secured debt. ``value_of(variable)`` returns that household variable on the entity the - caller is working with. The sale-expense deduction comes first and the - encumbrance second (ADM H1608), and an encumbered asset is never valued - below nil. + caller is working with. The sale-expense deduction is taken from the gross + value before the encumbrance (ADM H1608), and a source carrying secured + debt is never valued below nil. """ total = 0 for source in sources: diff --git a/policyengine_uk/variables/input/non_residential_property_secured_debt.py b/policyengine_uk/variables/input/non_residential_property_secured_debt.py index 3dc39a2996..f5da202655 100644 --- a/policyengine_uk/variables/input/non_residential_property_secured_debt.py +++ b/policyengine_uk/variables/input/non_residential_property_secured_debt.py @@ -6,8 +6,10 @@ class non_residential_property_secured_debt(Variable): documentation = ( "Amount owed on mortgages and other charges secured on non-residential " "property the household owns. Means tests deduct it from that " - "property's value (UC Regs 2013 reg. 49(1)(b) and its legacy " - "equivalents)." + "property's value after the 10% for sale expenses, flooring the " + "property at nil (UC Regs 2013 reg. 49(1)(b) and its legacy " + "equivalents). The value and the debt are household totals across all " + "such properties, so debt on one property offsets equity in another." ) entity = Household definition_period = YEAR diff --git a/policyengine_uk/variables/input/other_residential_property_secured_debt.py b/policyengine_uk/variables/input/other_residential_property_secured_debt.py index 50ec795c0d..340e8842fd 100644 --- a/policyengine_uk/variables/input/other_residential_property_secured_debt.py +++ b/policyengine_uk/variables/input/other_residential_property_secured_debt.py @@ -7,7 +7,10 @@ class other_residential_property_secured_debt(Variable): "Amount owed on mortgages and other charges secured on residential " "property the household owns other than the main residence, such as a " "buy-to-let mortgage. Means tests deduct it from that property's value " - "(UC Regs 2013 reg. 49(1)(b) and its legacy equivalents)." + "after the 10% for sale expenses, flooring the property at nil (UC Regs " + "2013 reg. 49(1)(b) and its legacy equivalents). The value and the debt " + "are household totals across all such properties, so debt on one " + "property offsets equity in another." ) entity = Household definition_period = YEAR diff --git a/policyengine_uk/variables/input/owned_land_secured_debt.py b/policyengine_uk/variables/input/owned_land_secured_debt.py index b58b570051..5f8380682c 100644 --- a/policyengine_uk/variables/input/owned_land_secured_debt.py +++ b/policyengine_uk/variables/input/owned_land_secured_debt.py @@ -5,8 +5,11 @@ class owned_land_secured_debt(Variable): label = "debt secured on owned land" documentation = ( "Amount owed on mortgages and other charges secured on land-only plots " - "the household owns. Means tests deduct it from that land's value (UC " - "Regs 2013 reg. 49(1)(b) and its legacy equivalents)." + "the household owns. Means tests deduct it from that land's value after " + "the 10% for sale expenses, flooring the land at nil (UC Regs 2013 reg. " + "49(1)(b) and its legacy equivalents). The value and the debt are " + "household totals across all plots, so debt on one plot offsets equity " + "in another." ) entity = Household definition_period = YEAR From e51391f3c4e756a289f2a5e02b89fee57698c26c Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 30 Sep 2026 22:18:21 -0400 Subject: [PATCH 3/6] Cite R(IS) 21/93 for real property in the HB sale-expense sources HBGM W1.430 states only the general 10% rule; the rule that real property always has costs of sale comes from R(IS) 21/93, as DMG 29622 applies it. Co-Authored-By: Claude Opus 5.5 --- .../means_test/capital/sale_expenses/sources.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml index ad9b7d587c..f57c9f5bd7 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sale_expenses/sources.yaml @@ -2,7 +2,8 @@ description: > Capital sources whose sale would incur expenses, so that Housing Benefit values them at 90% of market value. Costs of sale normally arise where an agent, broker, auctioneer, solicitor or accountant is needed, and real - property always has them (HBGM W1.430), so `owned_land`, + property always has them (R(IS) 21/93, as DMG 29622 applies it; HBGM W1.430 + states the general 10% rule), so `owned_land`, `other_residential_property_value` and `non_residential_property_value` are listed. `savings` is not listed: a bank or building society account is valued at its balance, and the costs of withdrawing money are not costs of @@ -31,6 +32,8 @@ metadata: href: https://assets.publishing.service.gov.uk/media/5a749328ed915d0e8e3994c0/hbgm-bw1-assessment-of-capital.pdf#page=36 - title: Housing Benefit Guidance Manual BP1, para. P1.430 href: https://assets.publishing.service.gov.uk/media/5a7ec5d840f0b6230268b71f/hbgm-bp1-assessment-of-capital.pdf#page=31 + - title: Decision Makers' Guide chapter 29, para. 29622 (real property, R(IS) 21/93) + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=124 - title: Housing Benefit Guidance Manual BW1, para. W1.513 href: https://assets.publishing.service.gov.uk/media/5a749328ed915d0e8e3994c0/hbgm-bw1-assessment-of-capital.pdf#page=43 - title: Housing Benefit Guidance Manual BW1, paras. W1.530-W1.531 From 22274cad14581256419fc2c445cb5b6a6df6d5ba Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 3 Oct 2026 22:05:05 -0400 Subject: [PATCH 4/6] Value capital under reg 19 in two Pension Credit tests from main Two tests main added after this branch's earlier base assumed full-value capital: - The CTR savings-credit-only case holds savings 10,000 and a 7,000 second property: capital is 10,000 + 90% of 7,000 = 16,300 (SPC Regs 2002 reg. 19(a)), still over the 16,000 limit, so CTR stays nil. Deemed income is 13 steps x 52 = 676, Pension Credit income 13,314 + 676 = 13,990, and savings credit 60% of (12,376 - 208.07 x 52) less 40% of (13,990 - 12,376) = 288.22. - The reported-capital property test's proxy oracle now values land, property and shares at 90% and savings at face value. Co-Authored-By: Claude Opus 5.5 --- .../council_tax_reduction_pension_credit.yaml | 10 +++++++--- ...t_pension_credit_reported_capital_properties.py | 14 ++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml index 6e52f66d3d..146a5a399e 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml @@ -466,12 +466,16 @@ savings: 10_000 other_residential_property_value: 7_000 output: - savings_credit: 267.42 + # Capital 10,000 + 90% of 7,000 = 16,300 (SPC Regs 2002 reg. 19(a)), so + # deemed income is 13 steps x 52 = 676 and Pension Credit income is + # 13,314 + 676 = 13,990. Savings credit: 60% of (12,376 - 208.07 x 52) + # = 933.82, less 40% of (13,990 - 12,376) = 645.60, leaves 288.22. + savings_credit: 288.22 in_receipt_of_savings_credit_only: true # Pension Credit counts the second property as capital; household # savings alone (10,000) are under the limit. Before: CTR 1,999.60. - pension_credit_assessable_capital: 17_000 - council_tax_reduction_assessable_capital: 17_000 + pension_credit_assessable_capital: 16_300 + council_tax_reduction_assessable_capital: 16_300 council_tax_reduction: 0 - name: The same pensioner not claiming Pension Credit is tested on household savings only diff --git a/policyengine_uk/tests/test_pension_credit_reported_capital_properties.py b/policyengine_uk/tests/test_pension_credit_reported_capital_properties.py index cf5fef6f30..d3a1a9b2ca 100644 --- a/policyengine_uk/tests/test_pension_credit_reported_capital_properties.py +++ b/policyengine_uk/tests/test_pension_credit_reported_capital_properties.py @@ -11,9 +11,11 @@ 1. Override identity: a pension-age unit with reported capital R >= 0 has assessable capital R, whatever the household holds. 2. Default differential: with nothing reported, assessable capital equals the - household proxy recomputed here from the inputs (household sources times - the unit's share of the household's pension-age adults, plus person-level - sources of the claimant or partner), the formula before this change. + household proxy recomputed here from the inputs (household sources, valued + under SPC Regs 2002 reg. 19 with savings at face value and the others at + 90%, times the unit's share of the household's pension-age adults, plus + person-level sources of the claimant or partner), the formula before this + change. 3. Locality: reporting capital for one unit never changes another unit's assessable capital. 4. Bounds: assessable capital is never negative, and is 0 for a unit with no @@ -102,7 +104,11 @@ def proxy(people, units, household, index): "non_residential_property_value", "corporate_wealth", ] - household_capital = sum(household.get(s, 0) for s in sources) + # SPC Regs 2002 reg. 19(a): sources whose sale would incur expenses (land, + # property, shares) are valued at 90%; savings at face value. + household_capital = sum( + household.get(s, 0) * (1 if s == "savings" else 0.9) for s in sources + ) sp_age = {name: p["age"] >= 66 for name, p in people.items()} unit = units[index]["members"] unit_sp = sum(sp_age[n] for n in unit) From f3929c1918b4d75bd1e2d0306b6019f4ebaf3c59 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 11 Oct 2026 20:56:28 -0400 Subject: [PATCH 5/6] Value capital under reg 19 in the corporate_wealth CTR case from main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit £20,000 of shares is £18,000 of Pension Credit capital (SPC Regs 2002 reg. 19(a)), still over the CTR limit: deemed income 16 x 52 = 832, Pension Credit income 14,146, savings credit 933.816 - 0.4 x 1,770 = 225.82. Co-Authored-By: Claude Opus 5.5 --- .../council_tax_reduction_pension_credit.yaml | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml index e745af108f..5a29964d97 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml @@ -659,20 +659,21 @@ savings: 0 corporate_wealth: 20_000 output: - # (12,000 + 1,500 - 12,570) x 0.2 = 186. (20,000 - 10,000) / 500 = 20 - # steps of £1 a week; 20 x 52 = 1,040 of deemed income. - pension_credit_assessable_capital: 20_000 - pension_credit_deemed_income: 1_040 - # 13,500 - 186 + 1,040 = 14,354, above the minimum guarantee of 12,376. - pension_credit_income: 14_354 + # (12,000 + 1,500 - 12,570) x 0.2 = 186. Shares are valued at 90% for the + # expenses of sale (SPC Regs 2002 reg. 19(a)): 18,000. (18,000 - 10,000) / + # 500 = 16 steps of £1 a week; 16 x 52 = 832 of deemed income. + pension_credit_assessable_capital: 18_000 + pension_credit_deemed_income: 832 + # 13,500 - 186 + 832 = 14,146, above the minimum guarantee of 12,376. + pension_credit_income: 14_146 guarantee_credit: 0 - # 933.816 - 0.4 x (14,354 - 12,376) = 933.816 - 791.20 = 142.616. - savings_credit: 142.62 + # 933.816 - 0.4 x (14,146 - 12,376) = 933.816 - 708 = 225.816. + savings_credit: 225.82 in_receipt_of_savings_credit_only: true - # The Pension Credit capital is 20,000, over 16,000, with nil savings in + # The Pension Credit capital is 18,000, over 16,000, with nil savings in # the household. The same pensioner with 20,000 of private_pension_wealth # keeps CTR in the next case. - council_tax_reduction_assessable_capital: 20_000 + council_tax_reduction_assessable_capital: 18_000 council_tax_reduction: 0 - name: Savings credit only, private_pension_wealth is not Pension Credit capital, so it does not take the pensioner over the CTR capital limit From 54ed063b1bd93821dfb90373d12842c2918d1da9 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 10:48:18 -0400 Subject: [PATCH 6/6] Skip passported families in the HB valuation property Main's Housing Benefit passport (#1927 and the Universal Credit limb) gives a family on a passporting benefit nil HB capital, so the property's independent reg 47 valuation applies only to non-passported families. Co-Authored-By: Claude Opus 5.5 --- .../tests/test_capital_valuation_properties.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/policyengine_uk/tests/test_capital_valuation_properties.py b/policyengine_uk/tests/test_capital_valuation_properties.py index 3ccf6d7eb3..4bafb0c51d 100644 --- a/policyengine_uk/tests/test_capital_valuation_properties.py +++ b/policyengine_uk/tests/test_capital_valuation_properties.py @@ -117,6 +117,9 @@ def calculate(units, rate=None, debt_scale=1.0): ) values = {v: np.asarray(sim.calculate(v, YEAR), dtype=float) for v in PROGRAMMES} values["guarantee_credit"] = np.asarray(sim.calculate("guarantee_credit", YEAR)) + values["hb_passported"] = np.asarray( + sim.calculate("housing_benefit_on_passporting_benefit", YEAR) + ) return sim, values @@ -124,8 +127,12 @@ def parameter_node(sim, path): return reduce(getattr, path.split("."), sim.tax_benefit_system.parameters(YEAR)) -def applies(variable, unit, guarantee_credit=0.0): +def applies(variable, unit, guarantee_credit=0.0, hb_passported=False): if variable == "housing_benefit_assessable_capital": + # A family on a passporting benefit has nil HB capital + # (housing_benefit_on_passporting_benefit, on main since #1927). + if hb_passported: + return False return unit["age"] < 67 or guarantee_credit <= 0 return (unit["age"] >= 67) == (variable in PENSION_AGE_ONLY) @@ -167,7 +174,7 @@ def test_valuation_matches_the_regulation_and_never_adds_capital(units): if variable == "housing_benefit_assessable_capital" and unit["age"] >= 67: if gc > 0: assert valued[variable][i] == 0, unit - if applies(variable, unit, gc): + if applies(variable, unit, gc, valued["hb_passported"][i]): expected = expected_capital(unit, node) assert close(valued[variable][i], expected), (variable, unit) # Debt secured on property never reaches the other assets. @@ -187,7 +194,12 @@ def test_cash_only_households_have_no_deduction(units): for variable in PROGRAMMES: assert np.allclose(valued[variable], full[variable]), variable for i, unit in enumerate(units): - if applies(variable, unit, valued["guarantee_credit"][i]): + if applies( + variable, + unit, + valued["guarantee_credit"][i], + valued["hb_passported"][i], + ): assert close(valued[variable][i], unit["assets"]["savings"]), variable