policyengine-uk 2.41.3__py3-none-any.whl → 2.42.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ description: Age threshold below which single adults without children can only claim shared accommodation rates under LHA
2
+ values:
3
+ 2013-04-01: 35
4
+ metadata:
5
+ period: year
6
+ unit: year
7
+ label: LHA shared accommodation age threshold
8
+ reference:
9
+ - title: The Housing Benefit Regulations 2006 - Schedule 4 - Paragraph 28
10
+ href: https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/28
11
+ - title: LHA shared accommodation rate guidance
12
+ href: https://www.gov.uk/government/publications/local-housing-allowance-rates-applicable-from-april-2013
@@ -91,6 +91,30 @@ obr:
91
91
  - title: OBR EFO March 2025
92
92
  href: https://obr.uk/efo/economic-and-fiscal-outlook-march-2025/
93
93
 
94
+ consumer_price_index_ahc:
95
+ description: Consumer price index year-on-year growth, modified to remove housing costs.
96
+ values:
97
+ 2022-01-01: 0.107
98
+ 2023-01-01: 0.057
99
+ 2024-01-01: 0.018
100
+ 2025-01-01: 0.027
101
+ 2026-01-01: 0.017
102
+ 2027-01-01: 0.019
103
+ 2028-01-01: 0.019
104
+ 2029-01-01: 0.019
105
+ metadata:
106
+ unit: /1
107
+ label: after housing costs consumer price index growth
108
+ reference:
109
+ - title: OBR EFO March 2025
110
+ href: https://obr.uk/efo/economic-and-fiscal-outlook-march-2025/
111
+ reference:
112
+ - title: ONS CPI weights
113
+ href: https://www.ons.gov.uk/economy/inflationandpriceindices/datasets/consumerpriceinflationupdatingweightsannexatablesw1tow3
114
+ reference:
115
+ - title: ONS CPI series excluding housing costs
116
+ - href: https://www.ons.gov.uk/economy/inflationandpriceindices/adhocs/2863consumerpriceindicesseriesexcludingrentsmaintenancerepairsandwaterchargesfortheperiodjanuary1996toapril2025
117
+
94
118
  non_labour_income:
95
119
  description: Non-labour income year-on-year growth.
96
120
  values:
@@ -516,4 +540,4 @@ finance_ni:
516
540
  label: domestic rates growth
517
541
  reference:
518
542
  - title: Finance NI (based on outturn)
519
- href: https://www.finance-ni.gov.uk/
543
+ href: https://www.finance-ni.gov.uk/
@@ -0,0 +1,170 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+
4
+ from policyengine_uk.system import system
5
+
6
+ # Source: ONS series ref 2863
7
+ historical_modified_cpi = pd.DataFrame(
8
+ {
9
+ "period": ["2022-01-01", "2023-01-01", "2024-01-01"],
10
+ "modified_cpi_index": [126.05, 133.22, 135.68],
11
+ "modified_cpi_yoy": [0.107, 0.057, 0.018],
12
+ }
13
+ )
14
+
15
+ # Source: ONS Consumer price inflation, updating weights: Annex A, Tables W1 to W3
16
+ initial_weights = {
17
+ "w_water": 9.7399 / 1000,
18
+ "w_rent": 81.4551 / 1000,
19
+ "w_repair": 2.9902 / 1000,
20
+ }
21
+
22
+ cpi = (
23
+ system.parameters.gov.economic_assumptions.indices.obr.consumer_price_index
24
+ )
25
+ water_index = (
26
+ system.parameters.gov.economic_assumptions.indices.ofwat.water_bills
27
+ )
28
+ rent_index = system.parameters.gov.economic_assumptions.indices.obr.rent
29
+
30
+
31
+ def get_parameter_values(param, start_year, end_year):
32
+ values = {}
33
+ for year in range(start_year, end_year + 1):
34
+ instant = f"{year}-01-01"
35
+ value = param(instant)
36
+ if value is not None:
37
+ values[year] = value
38
+ return values
39
+
40
+
41
+ def create_modified_cpi_forecast(
42
+ cpi_parameter,
43
+ water_index_parameter,
44
+ rent_index_parameter,
45
+ historical_modified_cpi,
46
+ initial_weights,
47
+ forecast_start_year=2025,
48
+ forecast_end_year=2029,
49
+ ):
50
+
51
+ cpi_values = get_parameter_values(
52
+ cpi_parameter, forecast_start_year, forecast_end_year
53
+ )
54
+ water_values = get_parameter_values(
55
+ water_index_parameter, forecast_start_year, forecast_end_year
56
+ )
57
+ rent_values = get_parameter_values(
58
+ rent_index_parameter, forecast_start_year, forecast_end_year
59
+ )
60
+
61
+ last_historical_year = forecast_start_year - 1
62
+ last_cpi = cpi_parameter(f"{last_historical_year}-01-01")
63
+ last_water = water_index_parameter(f"{last_historical_year}-01-01")
64
+ last_rent = rent_index_parameter(f"{last_historical_year}-01-01")
65
+
66
+ results = []
67
+ for _, row in historical_modified_cpi.iterrows():
68
+ results.append(
69
+ {
70
+ "period": row["period"],
71
+ "modified_cpi_index": row["modified_cpi_index"],
72
+ "modified_cpi_yoy": row["modified_cpi_yoy"],
73
+ "data_type": "historical",
74
+ }
75
+ )
76
+
77
+ last_historical = historical_modified_cpi.iloc[-1]
78
+ last_modified_index = last_historical["modified_cpi_index"]
79
+
80
+ current_weights = initial_weights.copy()
81
+ current_weights["w_other"] = 1 - (
82
+ current_weights["w_water"]
83
+ + current_weights["w_repair"]
84
+ + current_weights["w_rent"]
85
+ )
86
+
87
+ forecast_years = sorted(cpi_values.keys())
88
+ prev_cpi = last_cpi
89
+ prev_water_index = last_water
90
+ prev_rent_index = last_rent
91
+
92
+ for year in forecast_years:
93
+ current_cpi = cpi_values[year]
94
+ current_water_index = water_values.get(year)
95
+ current_rent_index = rent_values.get(year)
96
+
97
+ pi_total = (current_cpi / prev_cpi) - 1
98
+ pi_repair = pi_total # Use CPI for maintenance and repair
99
+ pi_water = (current_water_index / prev_water_index) - 1
100
+ pi_rent = (current_rent_index / prev_rent_index) - 1
101
+
102
+ housing_contribution = (
103
+ current_weights["w_water"] * pi_water
104
+ + current_weights["w_repair"] * pi_repair
105
+ + current_weights["w_rent"] * pi_rent
106
+ )
107
+
108
+ pi_other = (pi_total - housing_contribution) / current_weights[
109
+ "w_other"
110
+ ]
111
+
112
+ new_modified_index = last_modified_index * (1 + pi_other)
113
+
114
+ if len(results) >= 1:
115
+ prev_year_value = results[-1]["modified_cpi_index"]
116
+ modified_cpi_yoy = (new_modified_index / prev_year_value) - 1
117
+ else:
118
+ modified_cpi_yoy = np.nan
119
+
120
+ results.append(
121
+ {
122
+ "period": f"{year}-01-01",
123
+ "year": int(year),
124
+ "modified_cpi_index": new_modified_index,
125
+ "modified_cpi_yoy": modified_cpi_yoy,
126
+ "original_cpi_yoy": pi_total,
127
+ "data_type": "forecast",
128
+ "pi_other": pi_other,
129
+ "pi_total": pi_total,
130
+ "pi_rent": pi_rent,
131
+ "pi_water": pi_water,
132
+ "pi_repair": pi_repair,
133
+ }
134
+ )
135
+
136
+ total_weighted_growth = (
137
+ current_weights["w_water"] * (1 + pi_water)
138
+ + current_weights["w_rent"] * (1 + pi_rent)
139
+ + current_weights["w_repair"] * (1 + pi_repair)
140
+ + current_weights["w_other"] * (1 + pi_other)
141
+ )
142
+
143
+ current_weights["w_water"] = (
144
+ current_weights["w_water"] * (1 + pi_water) / total_weighted_growth
145
+ )
146
+ current_weights["w_rent"] = (
147
+ current_weights["w_rent"] * (1 + pi_rent) / total_weighted_growth
148
+ )
149
+ current_weights["w_repair"] = (
150
+ current_weights["w_repair"]
151
+ * (1 + pi_repair)
152
+ / total_weighted_growth
153
+ )
154
+ current_weights["w_other"] = (
155
+ current_weights["w_other"] * (1 + pi_other) / total_weighted_growth
156
+ )
157
+
158
+ last_modified_index = new_modified_index
159
+ prev_cpi = current_cpi
160
+ prev_water_index = current_water_index
161
+ prev_rent_index = current_rent_index
162
+
163
+ return pd.DataFrame(results)
164
+
165
+
166
+ if __name__ == "__main__":
167
+ modified_cpi_forecast = create_modified_cpi_forecast(
168
+ cpi, water_index, rent_index, historical_modified_cpi, initial_weights
169
+ )
170
+ print(modified_cpi_forecast.to_markdown(index=False))
@@ -36,11 +36,13 @@ class LHA_category(Variable):
36
36
  household.max(person("age", period))
37
37
  )
38
38
  has_children = benunit.any(person("is_child", period))
39
- # Households with only one adult, if under 35, can only claim shared if without children:
39
+ # Households with only one adult, if under age threshold, can only
40
+ # claim shared if without children:
40
41
  # https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/28
42
+ p = parameters(period).gov.dwp.LHA
41
43
  can_only_claim_shared = (
42
44
  (num_adults_in_hh == 1)
43
- & (eldest_adult_age_in_hh < 35)
45
+ & (eldest_adult_age_in_hh < p.shared_accommodation_age_threshold)
44
46
  & ~has_children
45
47
  )
46
48
  return select(
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.42.0] - 2025-07-25 08:57:23
9
+
10
+ ### Changed
11
+
12
+ - Add after housing costs deflator
13
+
14
+ ## [2.41.4] - 2025-07-24 14:41:02
15
+
16
+ ### Fixed
17
+
18
+ - Parameterize age 35 threshold in LHA shared accommodation rules
19
+
8
20
  ## [2.41.3] - 2025-07-24 13:53:51
9
21
 
10
22
  ### Fixed
@@ -2010,6 +2022,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2010
2022
 
2011
2023
 
2012
2024
 
2025
+ [2.42.0]: https://github.com/PolicyEngine/openfisca-uk/compare/2.41.4...2.42.0
2026
+ [2.41.4]: https://github.com/PolicyEngine/openfisca-uk/compare/2.41.3...2.41.4
2013
2027
  [2.41.3]: https://github.com/PolicyEngine/openfisca-uk/compare/2.41.2...2.41.3
2014
2028
  [2.41.2]: https://github.com/PolicyEngine/openfisca-uk/compare/2.41.1...2.41.2
2015
2029
  [2.41.1]: https://github.com/PolicyEngine/openfisca-uk/compare/2.41.0...2.41.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: policyengine-uk
3
- Version: 2.41.3
3
+ Version: 2.42.0
4
4
  Summary: PolicyEngine tax and benefit system for the UK
5
5
  Project-URL: Homepage, https://github.com/PolicyEngine/policyengine-uk
6
6
  Project-URL: Repository, https://github.com/PolicyEngine/policyengine-uk
@@ -137,6 +137,7 @@ policyengine_uk/parameters/gov/dwp/LHA/__init__.py,sha256=YMNgG4e3yHHtoJ6hpx5Zuz
137
137
  policyengine_uk/parameters/gov/dwp/LHA/freeze.yaml,sha256=WtWomrgei1cmzRMX6PS71L_8GpXAF4wG5VNUmXV1agY,207
138
138
  policyengine_uk/parameters/gov/dwp/LHA/lha_list_of_rents.csv.gz,sha256=SVaiCl5aBL5aAKvWuEHSm5baJ8pTnlIt1XBTcDESCgI,853159
139
139
  policyengine_uk/parameters/gov/dwp/LHA/percentile.yaml,sha256=TtPLtgck3uJxlrk9PX2R9Ytk9lVkSU4GkCYEKCPE7Ds,247
140
+ policyengine_uk/parameters/gov/dwp/LHA/shared_accommodation_age_threshold.yaml,sha256=-j8Nz-vTFpTclX-l-oGGsAkad4cQmIvYqUFHbFLqDjw,568
140
141
  policyengine_uk/parameters/gov/dwp/LHA/means_test/earn_disregard.yaml,sha256=qOLXvpxZT0fvI1WV_NKinNJHqeGQ5tQ_Fa07v_ly-kA,319
141
142
  policyengine_uk/parameters/gov/dwp/LHA/means_test/income_disregard_couple.yaml,sha256=obyu1DC6rNUptV8jP-RFcQwYM87X88fwSM36X50YURU,350
142
143
  policyengine_uk/parameters/gov/dwp/LHA/means_test/income_disregard_lone.yaml,sha256=SLUyYWo5NNnJEbREMRJcGqE6WF9L1hkkrdtqLRcKRzw,360
@@ -313,7 +314,7 @@ policyengine_uk/parameters/gov/dwp/winter_fuel_payment/eligibility/taxable_incom
313
314
  policyengine_uk/parameters/gov/economic_assumptions/create_economic_assumption_indices.py,sha256=Z4dYghSit5gXo4V3wBpnLIc9zgTX4cfEyb_TUlJkTGY,1937
314
315
  policyengine_uk/parameters/gov/economic_assumptions/lag_average_earnings.py,sha256=ksHcyUQkLAJmKizCeSg8j0hzPc7ajgIvbExWLgCra4U,701
315
316
  policyengine_uk/parameters/gov/economic_assumptions/lag_cpi.py,sha256=IdtaMLN1_OSu-RFZsQV8vBlbOvXsPlnNlsOuinRHrxg,642
316
- policyengine_uk/parameters/gov/economic_assumptions/yoy_growth.yaml,sha256=DaWjPzfdO0r_oU1ilqbM6yy8VaBB-kWZ9sz41TZTcs8,16711
317
+ policyengine_uk/parameters/gov/economic_assumptions/yoy_growth.yaml,sha256=EpUOWaZWE18wJtDbutGPEy9YwoaRJsYO-fDpCydZ7eY,17708
317
318
  policyengine_uk/parameters/gov/hmrc/README.md,sha256=nkHVZl6lsjI93sR8uC7wAbul3_61wJrsP08iaW8f5lk,7
318
319
  policyengine_uk/parameters/gov/hmrc/minimum_wage.yaml,sha256=1oMbevU0ESHR51mcAG39POd1DA1FgPUep4hL6ojj-P4,2049
319
320
  policyengine_uk/parameters/gov/hmrc/business_rates/README.md,sha256=9ud50i_gMjGj6VymF-nzFDTzkFRMMJx6ybpLwbWzvpI,17
@@ -684,6 +685,7 @@ policyengine_uk/tests/policy/reforms/parametric/two_child_limit/age_exemption.ya
684
685
  policyengine_uk/tests/policy/reforms/parametric/two_child_limit/ctc_age_exemption.yaml,sha256=xOgctFi4eLVW7agHdRPUU9szoRzt4p0R9eiMvPqwv_s,3577
685
686
  policyengine_uk/tests/policy/reforms/parametric/winter_fuel_allowance/taxable_income_test.yaml,sha256=QY3LYJ92VzYH9mXU54XD_6PhefwHNK80kGYQ0R5I0SM,6289
686
687
  policyengine_uk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
688
+ policyengine_uk/utils/create_ahc_deflator.py,sha256=zCJ_R_hq8DUfuO7u3puhRl6gkC1hw2MX3TCusy-bICI,5464
687
689
  policyengine_uk/utils/create_triple_lock.py,sha256=E8qR51cq5jPL6EOXFoPi1qJhrcUBXg3dfWTvdqWN2Bo,948
688
690
  policyengine_uk/utils/dependencies.py,sha256=6mLDZr-lypI6RZMeb0rcWoJy5Ig7QT18kOuAMUgI7vg,8198
689
691
  policyengine_uk/utils/parameters.py,sha256=OQTzTkHMdwbphCo0mV7_n_FJT0rdwIKNFTsk_lsdETE,1301
@@ -769,7 +771,7 @@ policyengine_uk/variables/gov/dwp/CTC_maximum_rate.py,sha256=ocg678wah0U8MwhNLbc
769
771
  policyengine_uk/variables/gov/dwp/CTC_severely_disabled_child_element.py,sha256=nbqsoi7GJLH6lXT8iAEqp_Q9JxldefpyItmH-wgDdTc,958
770
772
  policyengine_uk/variables/gov/dwp/LHA_allowed_bedrooms.py,sha256=ZebexoeCZRCDHl7pRbcqojCUfszxYhWlkeA9zzVMS1s,2333
771
773
  policyengine_uk/variables/gov/dwp/LHA_cap.py,sha256=hDRReKCaRwiXwsjM7hvQsSqiO9qzNaENf3WQNPjcla8,548
772
- policyengine_uk/variables/gov/dwp/LHA_category.py,sha256=RQtKZapNcHmJgRMDZvUeN1WPO3qs9jFmpaNoA2t52Xs,3741
774
+ policyengine_uk/variables/gov/dwp/LHA_category.py,sha256=Wi8UPJkcfCIBNLFF1_B2PJwtUiNNwOLKkM4dsQSxJzg,3839
773
775
  policyengine_uk/variables/gov/dwp/LHA_eligible.py,sha256=bjBmNtzrCbf6RjbnkjM4ulpJ7wyw_gNSJ5yuV5-ZK5c,679
774
776
  policyengine_uk/variables/gov/dwp/WTC_basic_element.py,sha256=6NGKcTK8-t269DgDJ57U2xsmME_t-TAC9GkvJ1BOqSQ,450
775
777
  policyengine_uk/variables/gov/dwp/WTC_childcare_element.py,sha256=5pmPVtnrMgmJfSFA6XZoQgwalI4ZXna8ZHmqkJbSLys,883
@@ -1368,10 +1370,10 @@ policyengine_uk/variables/misc/spi_imputed.py,sha256=iPVlBF_TisM0rtKvO-3-PQ2UYCe
1368
1370
  policyengine_uk/variables/misc/uc_migrated.py,sha256=zFNcUJaO8gwmbL1iY9GKgUt3G6J9yrCraqBV_5dCvlM,306
1369
1371
  policyengine_uk/variables/misc/categories/lower_middle_or_higher.py,sha256=C54tHYz2DmOyvQYCC1bF8RJwRZinhAq_e3aYC-9F5fM,157
1370
1372
  policyengine_uk/variables/misc/categories/lower_or_higher.py,sha256=81NIbLLabRr9NwjpUZDuV8IV8_mqmp5NM-CZvt55TwE,129
1371
- policyengine_uk-2.41.3.data/data/share/openfisca/openfisca-country-template/CHANGELOG.md,sha256=WUPxoboZaT8uQ8KNRlu20cdu1sMPjxkZKiON2Ki0chs,58039
1372
- policyengine_uk-2.41.3.data/data/share/openfisca/openfisca-country-template/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
1373
- policyengine_uk-2.41.3.data/data/share/openfisca/openfisca-country-template/README.md,sha256=PCy7LRLdUDQS8U4PaeHeBVnyBZAqHv1dAVDDvEcom20,1976
1374
- policyengine_uk-2.41.3.dist-info/METADATA,sha256=1sHSTWMHikxKfzxzYenbsJe3HVxJv1qfZxd1ZmA4SBk,3502
1375
- policyengine_uk-2.41.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1376
- policyengine_uk-2.41.3.dist-info/licenses/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
1377
- policyengine_uk-2.41.3.dist-info/RECORD,,
1373
+ policyengine_uk-2.42.0.data/data/share/openfisca/openfisca-country-template/CHANGELOG.md,sha256=gvfrTmfJIgfSQPoJOQ5cgJM0ZcWfMOLCut8909_wiGs,58394
1374
+ policyengine_uk-2.42.0.data/data/share/openfisca/openfisca-country-template/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
1375
+ policyengine_uk-2.42.0.data/data/share/openfisca/openfisca-country-template/README.md,sha256=PCy7LRLdUDQS8U4PaeHeBVnyBZAqHv1dAVDDvEcom20,1976
1376
+ policyengine_uk-2.42.0.dist-info/METADATA,sha256=8v2z9cix1P4FfGKnDzHwgV_cbF4Xevt-q5kmKbetsiA,3502
1377
+ policyengine_uk-2.42.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1378
+ policyengine_uk-2.42.0.dist-info/licenses/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
1379
+ policyengine_uk-2.42.0.dist-info/RECORD,,