Skip to content

Commit 5ccfb4b

Browse files
authored
Add Income Support capital rules (#1578)
* Add Income Support capital rules * Refine Income Support capital allocation proxy * Cover Income Support capital boundaries * Conservatively handle Income Support capital claims
1 parent 6b184c6 commit 5ccfb4b

10 files changed

Lines changed: 344 additions & 0 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
description: Lower capital threshold for Income Support tariff income.
2+
metadata:
3+
label: Income Support lower capital threshold
4+
period: year
5+
reference:
6+
- title: Income Support (General) Regulations 1987 reg. 53(1)
7+
href: https://www.legislation.gov.uk/uksi/1987/1967/data.pdf#page=76
8+
unit: GBP
9+
10+
values:
11+
2010-01-01: 6000
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
description: Capital sources included in the Income Support capital test.
2+
metadata:
3+
label: Income Support capital sources
4+
period: year
5+
propagate_metadata_to_children: true
6+
reference:
7+
- title: Income Support (General) Regulations 1987 reg. 46(1)-(2)
8+
href: https://www.legislation.gov.uk/uksi/1987/1967/data.pdf#page=70
9+
- title: Income Support (General) Regulations 1987 reg. 48(4)
10+
href: https://www.legislation.gov.uk/uksi/1987/1967/data.pdf#page=70
11+
- title: Income Support (General) Regulations 1987 Sch. 10
12+
href: https://www.legislation.gov.uk/uksi/1987/1967/data.pdf#page=188
13+
unit: list
14+
15+
values:
16+
2010-01-01:
17+
- savings
18+
- owned_land
19+
- corporate_wealth
20+
- other_residential_property_value
21+
- non_residential_property_value
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
description: Weekly amount of Income Support tariff income per capital step.
2+
metadata:
3+
label: Income Support tariff income amount
4+
period: year
5+
reference:
6+
- title: Income Support (General) Regulations 1987 reg. 53(1)
7+
href: https://www.legislation.gov.uk/uksi/1987/1967/data.pdf#page=76
8+
unit: GBP
9+
10+
values:
11+
2010-01-01: 1
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
description: Capital amount that generates one unit of Income Support tariff income.
2+
metadata:
3+
label: Income Support tariff income step
4+
period: year
5+
reference:
6+
- title: Income Support (General) Regulations 1987 reg. 53(1)
7+
href: https://www.legislation.gov.uk/uksi/1987/1967/data.pdf#page=76
8+
unit: GBP
9+
10+
values:
11+
2010-01-01: 250
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
description: Upper capital threshold for Income Support eligibility.
2+
metadata:
3+
label: Income Support upper capital threshold
4+
period: year
5+
reference:
6+
- title: Income Support (General) Regulations 1987 reg. 45
7+
href: https://www.legislation.gov.uk/uksi/1987/1967/data.pdf#page=70
8+
unit: GBP
9+
10+
values:
11+
2010-01-01: 16000
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
- name: Income Support capital test ignores the main residence
2+
period: 2021
3+
absolute_error_margin: 1
4+
input:
5+
people:
6+
p1:
7+
age: 26
8+
income_support_reported: true
9+
c1:
10+
age: 4
11+
is_child: true
12+
benunits:
13+
b1:
14+
members: [p1, c1]
15+
would_claim_IS: true
16+
households:
17+
household:
18+
members: [p1, c1]
19+
savings: 1000
20+
owned_land: 500
21+
corporate_wealth: 2000
22+
main_residence_value: 300000
23+
other_residential_property_value: 3000
24+
non_residential_property_value: 4000
25+
output:
26+
income_support_assessable_capital: 10500
27+
28+
- name: Income Support has no tariff income at the lower capital threshold
29+
period: 2021
30+
absolute_error_margin: 1
31+
input:
32+
people:
33+
p1:
34+
age: 26
35+
income_support_reported: true
36+
c1:
37+
age: 4
38+
is_child: true
39+
benunits:
40+
b1:
41+
members: [p1, c1]
42+
would_claim_IS: true
43+
households:
44+
household:
45+
members: [p1, c1]
46+
savings: 6000
47+
output:
48+
income_support_tariff_income: 0
49+
50+
- name: Income Support tariff income rounds up to the next 250 pounds
51+
period: 2021
52+
absolute_error_margin: 1
53+
input:
54+
people:
55+
p1:
56+
age: 26
57+
income_support_reported: true
58+
c1:
59+
age: 4
60+
is_child: true
61+
benunits:
62+
b1:
63+
members: [p1, c1]
64+
would_claim_IS: true
65+
households:
66+
household:
67+
members: [p1, c1]
68+
savings: 6251
69+
output:
70+
income_support_tariff_income: 104
71+
72+
- name: Income Support entitlement is reduced by tariff income above the lower threshold
73+
period: 2021
74+
absolute_error_margin: 1
75+
input:
76+
people:
77+
p1:
78+
age: 26
79+
income_support_reported: true
80+
c1:
81+
age: 4
82+
is_child: true
83+
benunits:
84+
b1:
85+
members: [p1, c1]
86+
would_claim_IS: true
87+
households:
88+
household:
89+
members: [p1, c1]
90+
savings: 6251
91+
output:
92+
income_support_eligible: true
93+
income_support_tariff_income: 104
94+
income_support: 4209.82
95+
96+
- name: Income Support remains eligible at the upper capital limit
97+
period: 2021
98+
absolute_error_margin: 1
99+
input:
100+
people:
101+
p1:
102+
age: 26
103+
income_support_reported: true
104+
c1:
105+
age: 4
106+
is_child: true
107+
benunits:
108+
b1:
109+
members: [p1, c1]
110+
would_claim_IS: true
111+
households:
112+
household:
113+
members: [p1, c1]
114+
savings: 16000
115+
output:
116+
income_support_eligible: true
117+
118+
- name: Income Support is not eligible above the capital limit
119+
period: 2021
120+
absolute_error_margin: 1
121+
input:
122+
people:
123+
p1:
124+
age: 26
125+
income_support_reported: true
126+
c1:
127+
age: 4
128+
is_child: true
129+
benunits:
130+
b1:
131+
members: [p1, c1]
132+
would_claim_IS: true
133+
households:
134+
household:
135+
members: [p1, c1]
136+
savings: 16001
137+
output:
138+
income_support_eligible: false
139+
income_support: 0
140+
141+
- name: Income Support allocates household capital by adult share across benunits
142+
period: 2021
143+
absolute_error_margin: 1
144+
input:
145+
people:
146+
p1:
147+
age: 26
148+
p2:
149+
age: 30
150+
p3:
151+
age: 32
152+
benunits:
153+
b1:
154+
members: [p1]
155+
would_claim_IS: false
156+
b2:
157+
members: [p2, p3]
158+
would_claim_IS: false
159+
households:
160+
household:
161+
members: [p1, p2, p3]
162+
savings: 18_000
163+
output:
164+
income_support_assessable_capital: [6_000, 12_000]
165+
166+
- name: Income Support does not dilute claimant capital across unrelated non-claiming adults
167+
period: 2021
168+
absolute_error_margin: 1
169+
input:
170+
people:
171+
claimant:
172+
age: 26
173+
unrelated_adult:
174+
age: 30
175+
benunits:
176+
claimant_benunit:
177+
members: [claimant]
178+
would_claim_IS: true
179+
unrelated_benunit:
180+
members: [unrelated_adult]
181+
would_claim_IS: false
182+
households:
183+
household:
184+
members: [claimant, unrelated_adult]
185+
savings: 18_000
186+
output:
187+
income_support_assessable_capital: [18_000, 0]
188+
189+
- name: Income Support does not dilute household capital across multiple claiming benunits
190+
period: 2021
191+
absolute_error_margin: 1
192+
input:
193+
people:
194+
claimant_1:
195+
age: 26
196+
income_support_reported: true
197+
claimant_2:
198+
age: 30
199+
income_support_reported: true
200+
benunits:
201+
benunit_1:
202+
members: [claimant_1]
203+
would_claim_IS: true
204+
benunit_2:
205+
members: [claimant_2]
206+
would_claim_IS: true
207+
households:
208+
household:
209+
members: [claimant_1, claimant_2]
210+
savings: 18_000
211+
output:
212+
income_support_assessable_capital: [18_000, 18_000]

policyengine_uk/variables/gov/dwp/income_support_applicable_income.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def formula(benunit, period, parameters):
2626
["income_tax", "national_insurance"],
2727
)
2828
income += add(benunit, period, ["social_security_income"])
29+
income += benunit("income_support_tariff_income", period)
2930
income -= tax
3031
income -= add(benunit, period, ["pension_contributions"]) * 0.5
3132
family_type = benunit("family_type", period)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from policyengine_uk.model_api import *
2+
3+
4+
class income_support_assessable_capital(Variable):
5+
value_type = float
6+
entity = BenUnit
7+
label = "Assessable capital for Income Support"
8+
documentation = (
9+
"Household capital apportioned to the benefit unit for the Income Support "
10+
"capital test. Because the dataset only stores these stocks at household "
11+
"level, the model allocates full household capital to any benunit on the "
12+
"IS claim path and only falls back to an adult-share proxy when nobody in "
13+
"the household is on that path."
14+
)
15+
definition_period = YEAR
16+
unit = GBP
17+
18+
def formula(benunit, period, parameters):
19+
IS = parameters(period).gov.dwp.income_support
20+
sources = IS.means_test.capital.sources
21+
person = benunit.members
22+
would_claim_is = benunit("would_claim_IS", period)
23+
24+
# The data model stores these capital stocks at household level. For the
25+
# live Income Support path, avoid diluting capital across separate claims:
26+
# any benunit on the IS claim path gets the full observed household total.
27+
# If nobody in the household is on that path, fall back to an all-adults
28+
# proxy so direct inspection still returns a usable value.
29+
household_capital = sum(
30+
benunit.max(person.household(source, period)) for source in sources
31+
)
32+
benunit_adults = add(benunit, period, ["is_adult"])
33+
household_claiming_adults = benunit.max(
34+
person.household.sum(
35+
person("is_adult", period) & person.benunit("would_claim_IS", period)
36+
)
37+
)
38+
household_adults = benunit.max(
39+
person.household.sum(person.household.members("is_adult", period))
40+
)
41+
fallback_divisor = max_(1, household_adults)
42+
claiming_proxy = where(would_claim_is, household_capital, 0)
43+
fallback_proxy = household_capital * benunit_adults / fallback_divisor
44+
return where(household_claiming_adults > 0, claiming_proxy, fallback_proxy)

policyengine_uk/variables/gov/dwp/income_support_eligible.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,20 @@ class income_support_eligible(Variable):
88
definition_period = YEAR
99

1010
def formula(benunit, period, parameters):
11+
IS = parameters(period).gov.dwp.income_support
1112
youngest_child_5_or_under = benunit("youngest_child_age", period) <= 5
1213
lone_parent = benunit("is_lone_parent", period)
1314
lone_parent_with_young_child = lone_parent & youngest_child_5_or_under
1415
has_carers = add(benunit, period, ["is_carer_for_benefits"]) > 0
1516
none_SP_age = ~benunit.any(benunit.members("is_SP_age", period))
1617
has_esa_income = benunit("esa_income", period) > 0
1718
already_claiming = add(benunit, period, ["income_support_reported"]) > 0
19+
capital = benunit("income_support_assessable_capital", period)
20+
capital_limit = IS.means_test.capital.upper_threshold
1821
return (
1922
(has_carers | lone_parent_with_young_child)
2023
& none_SP_age
2124
& ~has_esa_income
2225
& already_claiming
26+
& (capital <= capital_limit)
2327
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from policyengine_uk.model_api import *
2+
import numpy as np
3+
4+
5+
class income_support_tariff_income(Variable):
6+
value_type = float
7+
entity = BenUnit
8+
label = "Income Support tariff income from capital"
9+
definition_period = YEAR
10+
unit = GBP
11+
12+
def formula(benunit, period, parameters):
13+
IS = parameters(period).gov.dwp.income_support
14+
capital = benunit("income_support_assessable_capital", period)
15+
mt = IS.means_test.capital
16+
excess_capital = max_(0, capital - mt.lower_threshold)
17+
tariff_units = np.ceil(excess_capital / mt.tariff_income.step)
18+
return tariff_units * mt.tariff_income.amount * WEEKS_IN_YEAR

0 commit comments

Comments
 (0)