policyengine-uk 2.45.4__py3-none-any.whl → 2.47.2__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.
Potentially problematic release.
This version of policyengine-uk might be problematic. Click here for more details.
- policyengine_uk/__init__.py +1 -0
- policyengine_uk/data/dataset_schema.py +6 -3
- policyengine_uk/data/economic_assumptions.py +1 -1
- policyengine_uk/dynamics/labour_supply.py +306 -0
- policyengine_uk/dynamics/participation.py +629 -0
- policyengine_uk/dynamics/progression.py +376 -0
- policyengine_uk/microsimulation.py +23 -1
- policyengine_uk/parameters/gov/dynamic/obr_labour_supply_assumptions.yaml +9 -0
- policyengine_uk/parameters/gov/economic_assumptions/yoy_growth.yaml +270 -32
- policyengine_uk/simulation.py +184 -9
- policyengine_uk/tax_benefit_system.py +4 -1
- policyengine_uk/tests/microsimulation/reforms_config.yaml +7 -7
- policyengine_uk/tests/microsimulation/test_validity.py +2 -3
- policyengine_uk/tests/microsimulation/update_reform_impacts.py +104 -40
- policyengine_uk/tests/policy/baseline/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.yaml +8 -8
- policyengine_uk/utils/__init__.py +1 -0
- policyengine_uk/utils/compare.py +28 -0
- policyengine_uk/utils/solve_private_school_attendance_factor.py +4 -6
- policyengine_uk/variables/gov/dwp/additional_state_pension.py +1 -1
- policyengine_uk/variables/gov/dwp/basic_state_pension.py +1 -1
- policyengine_uk/variables/household/demographic/benunit/benunit_count_adults.py +11 -0
- policyengine_uk/variables/input/consumption/property/council_tax.py +0 -35
- policyengine_uk/variables/input/rent.py +0 -40
- {policyengine_uk-2.45.4.dist-info → policyengine_uk-2.47.2.dist-info}/METADATA +5 -4
- {policyengine_uk-2.45.4.dist-info → policyengine_uk-2.47.2.dist-info}/RECORD +27 -21
- {policyengine_uk-2.45.4.dist-info → policyengine_uk-2.47.2.dist-info}/WHEEL +0 -0
- {policyengine_uk-2.45.4.dist-info → policyengine_uk-2.47.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -15,14 +15,58 @@ obr:
|
|
|
15
15
|
2019-01-01: 0.022
|
|
16
16
|
2020-01-01: 0.003
|
|
17
17
|
2021-01-01: 0.059
|
|
18
|
-
2022-01-01: 0.
|
|
19
|
-
2023-01-01: 0.
|
|
20
|
-
2024-01-01: 0.
|
|
21
|
-
2025-01-01: 0.
|
|
22
|
-
2026-01-01: 0.
|
|
23
|
-
2027-01-01: 0.
|
|
24
|
-
2028-01-01: 0.
|
|
25
|
-
2029-01-01: 0.
|
|
18
|
+
2022-01-01: 0.1287
|
|
19
|
+
2023-01-01: 0.0748
|
|
20
|
+
2024-01-01: 0.0331
|
|
21
|
+
2025-01-01: 0.0416
|
|
22
|
+
2026-01-01: 0.0308
|
|
23
|
+
2027-01-01: 0.0300
|
|
24
|
+
2028-01-01: 0.0283
|
|
25
|
+
2029-01-01: 0.0283
|
|
26
|
+
2030-01-01: 0.0238
|
|
27
|
+
2031-01-01: 0.0230
|
|
28
|
+
2032-01-01: 0.0237
|
|
29
|
+
2033-01-01: 0.0238
|
|
30
|
+
2034-01-01: 0.0238
|
|
31
|
+
2035-01-01: 0.0239
|
|
32
|
+
2036-01-01: 0.0239
|
|
33
|
+
2037-01-01: 0.0239
|
|
34
|
+
2038-01-01: 0.0239
|
|
35
|
+
2039-01-01: 0.0239
|
|
36
|
+
2040-01-01: 0.0239
|
|
37
|
+
2041-01-01: 0.0239
|
|
38
|
+
2042-01-01: 0.0239
|
|
39
|
+
2043-01-01: 0.0239
|
|
40
|
+
2044-01-01: 0.0239
|
|
41
|
+
2045-01-01: 0.0239
|
|
42
|
+
2046-01-01: 0.0239
|
|
43
|
+
2047-01-01: 0.0239
|
|
44
|
+
2048-01-01: 0.0239
|
|
45
|
+
2049-01-01: 0.0239
|
|
46
|
+
2050-01-01: 0.0239
|
|
47
|
+
2051-01-01: 0.0239
|
|
48
|
+
2052-01-01: 0.0239
|
|
49
|
+
2053-01-01: 0.0239
|
|
50
|
+
2054-01-01: 0.0239
|
|
51
|
+
2055-01-01: 0.0239
|
|
52
|
+
2056-01-01: 0.0239
|
|
53
|
+
2057-01-01: 0.0239
|
|
54
|
+
2058-01-01: 0.0239
|
|
55
|
+
2059-01-01: 0.0239
|
|
56
|
+
2060-01-01: 0.0239
|
|
57
|
+
2061-01-01: 0.0239
|
|
58
|
+
2062-01-01: 0.0239
|
|
59
|
+
2063-01-01: 0.0239
|
|
60
|
+
2064-01-01: 0.0239
|
|
61
|
+
2065-01-01: 0.0239
|
|
62
|
+
2066-01-01: 0.0239
|
|
63
|
+
2067-01-01: 0.0239
|
|
64
|
+
2068-01-01: 0.0239
|
|
65
|
+
2069-01-01: 0.0239
|
|
66
|
+
2070-01-01: 0.0239
|
|
67
|
+
2071-01-01: 0.0239
|
|
68
|
+
2072-01-01: 0.0239
|
|
69
|
+
2073-01-01: 0.0239
|
|
26
70
|
metadata:
|
|
27
71
|
unit: /1
|
|
28
72
|
label: retail price index growth
|
|
@@ -45,14 +89,58 @@ obr:
|
|
|
45
89
|
2019-01-01: 0.022
|
|
46
90
|
2020-01-01: 0.003
|
|
47
91
|
2021-01-01: 0.059
|
|
48
|
-
2022-01-01: 0.
|
|
49
|
-
2023-01-01: 0.
|
|
50
|
-
2024-01-01: 0.
|
|
51
|
-
2025-01-01: 0.
|
|
52
|
-
2026-01-01: 0.
|
|
53
|
-
2027-01-01: 0.
|
|
54
|
-
2028-01-01: 0.
|
|
55
|
-
2029-01-01: 0.
|
|
92
|
+
2022-01-01: 0.0644
|
|
93
|
+
2023-01-01: 0.0688
|
|
94
|
+
2024-01-01: 0.0467
|
|
95
|
+
2025-01-01: 0.0371
|
|
96
|
+
2026-01-01: 0.0216
|
|
97
|
+
2027-01-01: 0.0207
|
|
98
|
+
2028-01-01: 0.0225
|
|
99
|
+
2029-01-01: 0.0253
|
|
100
|
+
2030-01-01: 0.0292
|
|
101
|
+
2031-01-01: 0.0332
|
|
102
|
+
2032-01-01: 0.0371
|
|
103
|
+
2033-01-01: 0.0374
|
|
104
|
+
2034-01-01: 0.0377
|
|
105
|
+
2035-01-01: 0.0380
|
|
106
|
+
2036-01-01: 0.0383
|
|
107
|
+
2037-01-01: 0.0383
|
|
108
|
+
2038-01-01: 0.0383
|
|
109
|
+
2039-01-01: 0.0383
|
|
110
|
+
2040-01-01: 0.0383
|
|
111
|
+
2041-01-01: 0.0383
|
|
112
|
+
2042-01-01: 0.0383
|
|
113
|
+
2043-01-01: 0.0383
|
|
114
|
+
2044-01-01: 0.0383
|
|
115
|
+
2045-01-01: 0.0383
|
|
116
|
+
2046-01-01: 0.0383
|
|
117
|
+
2047-01-01: 0.0383
|
|
118
|
+
2048-01-01: 0.0383
|
|
119
|
+
2049-01-01: 0.0383
|
|
120
|
+
2050-01-01: 0.0383
|
|
121
|
+
2051-01-01: 0.0383
|
|
122
|
+
2052-01-01: 0.0383
|
|
123
|
+
2053-01-01: 0.0383
|
|
124
|
+
2054-01-01: 0.0383
|
|
125
|
+
2055-01-01: 0.0383
|
|
126
|
+
2056-01-01: 0.0383
|
|
127
|
+
2057-01-01: 0.0383
|
|
128
|
+
2058-01-01: 0.0383
|
|
129
|
+
2059-01-01: 0.0383
|
|
130
|
+
2060-01-01: 0.0383
|
|
131
|
+
2061-01-01: 0.0383
|
|
132
|
+
2062-01-01: 0.0383
|
|
133
|
+
2063-01-01: 0.0383
|
|
134
|
+
2064-01-01: 0.0383
|
|
135
|
+
2065-01-01: 0.0383
|
|
136
|
+
2066-01-01: 0.0383
|
|
137
|
+
2067-01-01: 0.0383
|
|
138
|
+
2068-01-01: 0.0383
|
|
139
|
+
2069-01-01: 0.0383
|
|
140
|
+
2070-01-01: 0.0383
|
|
141
|
+
2071-01-01: 0.0383
|
|
142
|
+
2072-01-01: 0.0383
|
|
143
|
+
2073-01-01: 0.0383
|
|
56
144
|
metadata:
|
|
57
145
|
unit: /1
|
|
58
146
|
label: average earnings growth
|
|
@@ -76,14 +164,58 @@ obr:
|
|
|
76
164
|
2019-01-01: 0.017
|
|
77
165
|
2020-01-01: 0.006
|
|
78
166
|
2021-01-01: 0.04
|
|
79
|
-
2022-01-01: 0.
|
|
80
|
-
2023-01-01: 0.
|
|
81
|
-
2024-01-01: 0.
|
|
82
|
-
2025-01-01: 0.
|
|
83
|
-
2026-01-01: 0.
|
|
84
|
-
2027-01-01: 0.
|
|
85
|
-
2028-01-01: 0.
|
|
86
|
-
2029-01-01: 0.
|
|
167
|
+
2022-01-01: 0.1004
|
|
168
|
+
2023-01-01: 0.0567
|
|
169
|
+
2024-01-01: 0.0233
|
|
170
|
+
2025-01-01: 0.0318
|
|
171
|
+
2026-01-01: 0.0193
|
|
172
|
+
2027-01-01: 0.0200
|
|
173
|
+
2028-01-01: 0.0200
|
|
174
|
+
2029-01-01: 0.0200
|
|
175
|
+
2030-01-01: 0.0200
|
|
176
|
+
2031-01-01: 0.0200
|
|
177
|
+
2032-01-01: 0.0200
|
|
178
|
+
2033-01-01: 0.0200
|
|
179
|
+
2034-01-01: 0.0200
|
|
180
|
+
2035-01-01: 0.0200
|
|
181
|
+
2036-01-01: 0.0200
|
|
182
|
+
2037-01-01: 0.0200
|
|
183
|
+
2038-01-01: 0.0200
|
|
184
|
+
2039-01-01: 0.0200
|
|
185
|
+
2040-01-01: 0.0200
|
|
186
|
+
2041-01-01: 0.0200
|
|
187
|
+
2042-01-01: 0.0200
|
|
188
|
+
2043-01-01: 0.0200
|
|
189
|
+
2044-01-01: 0.0200
|
|
190
|
+
2045-01-01: 0.0200
|
|
191
|
+
2046-01-01: 0.0200
|
|
192
|
+
2047-01-01: 0.0200
|
|
193
|
+
2048-01-01: 0.0200
|
|
194
|
+
2049-01-01: 0.0200
|
|
195
|
+
2050-01-01: 0.0200
|
|
196
|
+
2051-01-01: 0.0200
|
|
197
|
+
2052-01-01: 0.0200
|
|
198
|
+
2053-01-01: 0.0200
|
|
199
|
+
2054-01-01: 0.0200
|
|
200
|
+
2055-01-01: 0.0200
|
|
201
|
+
2056-01-01: 0.0200
|
|
202
|
+
2057-01-01: 0.0200
|
|
203
|
+
2058-01-01: 0.0200
|
|
204
|
+
2059-01-01: 0.0200
|
|
205
|
+
2060-01-01: 0.0200
|
|
206
|
+
2061-01-01: 0.0200
|
|
207
|
+
2062-01-01: 0.0200
|
|
208
|
+
2063-01-01: 0.0200
|
|
209
|
+
2064-01-01: 0.0200
|
|
210
|
+
2065-01-01: 0.0200
|
|
211
|
+
2066-01-01: 0.0200
|
|
212
|
+
2067-01-01: 0.0200
|
|
213
|
+
2068-01-01: 0.0200
|
|
214
|
+
2069-01-01: 0.0200
|
|
215
|
+
2070-01-01: 0.0200
|
|
216
|
+
2071-01-01: 0.0200
|
|
217
|
+
2072-01-01: 0.0200
|
|
218
|
+
2073-01-01: 0.0200
|
|
87
219
|
metadata:
|
|
88
220
|
unit: /1
|
|
89
221
|
label: consumer price index growth
|
|
@@ -113,6 +245,68 @@ obr:
|
|
|
113
245
|
- title: ONS CPI series excluding housing costs
|
|
114
246
|
href: https://www.ons.gov.uk/economy/inflationandpriceindices/adhocs/2863consumerpriceindicesseriesexcludingrentsmaintenancerepairsandwaterchargesfortheperiodjanuary1996toapril2025
|
|
115
247
|
|
|
248
|
+
cpih:
|
|
249
|
+
description: Consumer price index including owner occupiers' housing costs year-on-year growth.
|
|
250
|
+
values:
|
|
251
|
+
2022-01-01: 0.0877
|
|
252
|
+
2023-01-01: 0.0555
|
|
253
|
+
2024-01-01: 0.0320
|
|
254
|
+
2025-01-01: 0.0374
|
|
255
|
+
2026-01-01: 0.0227
|
|
256
|
+
2027-01-01: 0.0210
|
|
257
|
+
2028-01-01: 0.0205
|
|
258
|
+
2029-01-01: 0.0209
|
|
259
|
+
2030-01-01: 0.0224
|
|
260
|
+
2031-01-01: 0.0230
|
|
261
|
+
2032-01-01: 0.0237
|
|
262
|
+
2033-01-01: 0.0238
|
|
263
|
+
2034-01-01: 0.0238
|
|
264
|
+
2035-01-01: 0.0239
|
|
265
|
+
2036-01-01: 0.0239
|
|
266
|
+
2037-01-01: 0.0239
|
|
267
|
+
2038-01-01: 0.0239
|
|
268
|
+
2039-01-01: 0.0239
|
|
269
|
+
2040-01-01: 0.0239
|
|
270
|
+
2041-01-01: 0.0239
|
|
271
|
+
2042-01-01: 0.0239
|
|
272
|
+
2043-01-01: 0.0239
|
|
273
|
+
2044-01-01: 0.0239
|
|
274
|
+
2045-01-01: 0.0239
|
|
275
|
+
2046-01-01: 0.0239
|
|
276
|
+
2047-01-01: 0.0239
|
|
277
|
+
2048-01-01: 0.0239
|
|
278
|
+
2049-01-01: 0.0239
|
|
279
|
+
2050-01-01: 0.0239
|
|
280
|
+
2051-01-01: 0.0239
|
|
281
|
+
2052-01-01: 0.0239
|
|
282
|
+
2053-01-01: 0.0239
|
|
283
|
+
2054-01-01: 0.0239
|
|
284
|
+
2055-01-01: 0.0239
|
|
285
|
+
2056-01-01: 0.0239
|
|
286
|
+
2057-01-01: 0.0239
|
|
287
|
+
2058-01-01: 0.0239
|
|
288
|
+
2059-01-01: 0.0239
|
|
289
|
+
2060-01-01: 0.0239
|
|
290
|
+
2061-01-01: 0.0239
|
|
291
|
+
2062-01-01: 0.0239
|
|
292
|
+
2063-01-01: 0.0239
|
|
293
|
+
2064-01-01: 0.0239
|
|
294
|
+
2065-01-01: 0.0239
|
|
295
|
+
2066-01-01: 0.0239
|
|
296
|
+
2067-01-01: 0.0239
|
|
297
|
+
2068-01-01: 0.0239
|
|
298
|
+
2069-01-01: 0.0239
|
|
299
|
+
2070-01-01: 0.0239
|
|
300
|
+
2071-01-01: 0.0239
|
|
301
|
+
2072-01-01: 0.0239
|
|
302
|
+
2073-01-01: 0.0239
|
|
303
|
+
metadata:
|
|
304
|
+
unit: /1
|
|
305
|
+
label: CPIH growth
|
|
306
|
+
reference:
|
|
307
|
+
- title: OBR EFO March 2025
|
|
308
|
+
href: https://obr.uk/efo/economic-and-fiscal-outlook-march-2025/
|
|
309
|
+
|
|
116
310
|
non_labour_income:
|
|
117
311
|
description: Non-labour income year-on-year growth.
|
|
118
312
|
values:
|
|
@@ -317,14 +511,58 @@ ons:
|
|
|
317
511
|
description: Population year-on-year growth.
|
|
318
512
|
values:
|
|
319
513
|
2021-01-01: 0.004
|
|
320
|
-
2022-01-01: 0.
|
|
321
|
-
2023-01-01: 0.
|
|
322
|
-
2024-01-01: 0.
|
|
323
|
-
2025-01-01: 0.
|
|
324
|
-
2026-01-01: 0.
|
|
325
|
-
2027-01-01: 0.
|
|
326
|
-
2028-01-01: 0.
|
|
327
|
-
2029-01-01: 0.
|
|
514
|
+
2022-01-01: 0.0093
|
|
515
|
+
2023-01-01: 0.0131
|
|
516
|
+
2024-01-01: 0.0107
|
|
517
|
+
2025-01-01: 0.0072
|
|
518
|
+
2026-01-01: 0.0038
|
|
519
|
+
2027-01-01: 0.0037
|
|
520
|
+
2028-01-01: 0.0040
|
|
521
|
+
2029-01-01: 0.0044
|
|
522
|
+
2030-01-01: 0.0045
|
|
523
|
+
2031-01-01: 0.0043
|
|
524
|
+
2032-01-01: 0.0042
|
|
525
|
+
2033-01-01: 0.0041
|
|
526
|
+
2034-01-01: 0.0040
|
|
527
|
+
2035-01-01: 0.0039
|
|
528
|
+
2036-01-01: 0.0038
|
|
529
|
+
2037-01-01: 0.0037
|
|
530
|
+
2038-01-01: 0.0036
|
|
531
|
+
2039-01-01: 0.0035
|
|
532
|
+
2040-01-01: 0.0035
|
|
533
|
+
2041-01-01: 0.0034
|
|
534
|
+
2042-01-01: 0.0034
|
|
535
|
+
2043-01-01: 0.0033
|
|
536
|
+
2044-01-01: 0.0032
|
|
537
|
+
2045-01-01: 0.0032
|
|
538
|
+
2046-01-01: 0.0031
|
|
539
|
+
2047-01-01: 0.0030
|
|
540
|
+
2048-01-01: 0.0029
|
|
541
|
+
2049-01-01: 0.0028
|
|
542
|
+
2050-01-01: 0.0027
|
|
543
|
+
2051-01-01: 0.0025
|
|
544
|
+
2052-01-01: 0.0024
|
|
545
|
+
2053-01-01: 0.0022
|
|
546
|
+
2054-01-01: 0.0021
|
|
547
|
+
2055-01-01: 0.0020
|
|
548
|
+
2056-01-01: 0.0019
|
|
549
|
+
2057-01-01: 0.0018
|
|
550
|
+
2058-01-01: 0.0017
|
|
551
|
+
2059-01-01: 0.0016
|
|
552
|
+
2060-01-01: 0.0016
|
|
553
|
+
2061-01-01: 0.0016
|
|
554
|
+
2062-01-01: 0.0015
|
|
555
|
+
2063-01-01: 0.0015
|
|
556
|
+
2064-01-01: 0.0015
|
|
557
|
+
2065-01-01: 0.0015
|
|
558
|
+
2066-01-01: 0.0015
|
|
559
|
+
2067-01-01: 0.0015
|
|
560
|
+
2068-01-01: 0.0015
|
|
561
|
+
2069-01-01: 0.0015
|
|
562
|
+
2070-01-01: 0.0015
|
|
563
|
+
2071-01-01: 0.0015
|
|
564
|
+
2072-01-01: 0.0015
|
|
565
|
+
2073-01-01: 0.0014
|
|
328
566
|
metadata:
|
|
329
567
|
unit: /1
|
|
330
568
|
label: population growth
|
policyengine_uk/simulation.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Standard library imports
|
|
2
|
-
from typing import Dict, Optional, Union, Type
|
|
2
|
+
from typing import Dict, Optional, Union, Type, List
|
|
3
3
|
|
|
4
4
|
# Third-party imports
|
|
5
5
|
import numpy as np
|
|
@@ -23,9 +23,12 @@ from policyengine_uk.utils.scenario import Scenario
|
|
|
23
23
|
from policyengine_uk.data.economic_assumptions import (
|
|
24
24
|
extend_single_year_dataset,
|
|
25
25
|
)
|
|
26
|
+
from policyengine_uk.utils.dependencies import get_variable_dependencies
|
|
26
27
|
|
|
27
28
|
from .tax_benefit_system import CountryTaxBenefitSystem
|
|
28
29
|
|
|
30
|
+
from microdf import MicroDataFrame
|
|
31
|
+
|
|
29
32
|
|
|
30
33
|
class Simulation(CoreSimulation):
|
|
31
34
|
"""UK-specific simulation class for calculating tax and benefit outcomes.
|
|
@@ -36,6 +39,10 @@ class Simulation(CoreSimulation):
|
|
|
36
39
|
|
|
37
40
|
default_input_period: int = 2025
|
|
38
41
|
default_calculation_period: int = 2025
|
|
42
|
+
baseline: "Simulation"
|
|
43
|
+
|
|
44
|
+
calculated_periods: List[str] = []
|
|
45
|
+
_variable_dependencies: Dict[str, List[str]] = None
|
|
39
46
|
|
|
40
47
|
def __init__(
|
|
41
48
|
self,
|
|
@@ -103,10 +110,6 @@ class Simulation(CoreSimulation):
|
|
|
103
110
|
else:
|
|
104
111
|
raise ValueError(f"Unsupported dataset type: {dataset.__class__}")
|
|
105
112
|
|
|
106
|
-
# Handle behavioral responses for earnings and capital gains
|
|
107
|
-
self.move_values("employment_income", "employment_income_before_lsr")
|
|
108
|
-
self.move_values("capital_gains", "capital_gains_before_response")
|
|
109
|
-
|
|
110
113
|
self.input_variables = self.get_known_variables()
|
|
111
114
|
|
|
112
115
|
# Universal Credit reform (July 2025). Needs closer integration in the baseline,
|
|
@@ -123,6 +126,23 @@ class Simulation(CoreSimulation):
|
|
|
123
126
|
if scenario.simulation_modifier is not None:
|
|
124
127
|
scenario.simulation_modifier(self)
|
|
125
128
|
|
|
129
|
+
if scenario is not None:
|
|
130
|
+
self.baseline = Simulation(
|
|
131
|
+
scenario=None,
|
|
132
|
+
situation=situation,
|
|
133
|
+
dataset=dataset,
|
|
134
|
+
trace=trace,
|
|
135
|
+
)
|
|
136
|
+
else:
|
|
137
|
+
self.baseline = self.clone()
|
|
138
|
+
|
|
139
|
+
self.calculated_periods = []
|
|
140
|
+
|
|
141
|
+
def reset_calculations(self):
|
|
142
|
+
for variable in self.tax_benefit_system.variables:
|
|
143
|
+
if variable not in self.input_variables:
|
|
144
|
+
self.delete_arrays(variable)
|
|
145
|
+
|
|
126
146
|
def get_known_variables(self):
|
|
127
147
|
variables = []
|
|
128
148
|
for variable in self.tax_benefit_system.variables:
|
|
@@ -167,6 +187,10 @@ class Simulation(CoreSimulation):
|
|
|
167
187
|
builder.build_from_dict(self.tax_benefit_system, situation, self)
|
|
168
188
|
self.has_axes = builder.has_axes
|
|
169
189
|
|
|
190
|
+
self.dataset = UKSingleYearDataset.from_simulation(
|
|
191
|
+
self, fiscal_year=self.default_input_period
|
|
192
|
+
)
|
|
193
|
+
|
|
170
194
|
def build_from_url(self, url: str) -> None:
|
|
171
195
|
"""Build simulation from a HuggingFace dataset URL.
|
|
172
196
|
|
|
@@ -199,14 +223,11 @@ class Simulation(CoreSimulation):
|
|
|
199
223
|
# Determine dataset type and build accordingly
|
|
200
224
|
if UKMultiYearDataset.validate_file_path(dataset, False):
|
|
201
225
|
self.build_from_multi_year_dataset(UKMultiYearDataset(dataset))
|
|
202
|
-
self.dataset = dataset
|
|
203
226
|
elif UKSingleYearDataset.validate_file_path(dataset, False):
|
|
204
227
|
self.build_from_single_year_dataset(UKSingleYearDataset(dataset))
|
|
205
|
-
self.dataset = dataset
|
|
206
228
|
else:
|
|
207
229
|
dataset = Dataset.from_file(dataset, self.default_input_period)
|
|
208
230
|
self.build_from_dataset(dataset)
|
|
209
|
-
self.dataset = dataset
|
|
210
231
|
|
|
211
232
|
def build_from_dataframe(self, df: pd.DataFrame) -> None:
|
|
212
233
|
"""Build simulation from a pandas DataFrame.
|
|
@@ -407,13 +428,43 @@ class Simulation(CoreSimulation):
|
|
|
407
428
|
simulation.set_input(variable_target, known_period, array)
|
|
408
429
|
holder.delete_arrays(known_period)
|
|
409
430
|
|
|
431
|
+
def calculate_all(self, year: int) -> None:
|
|
432
|
+
person, benunit, household = (
|
|
433
|
+
pd.DataFrame(),
|
|
434
|
+
pd.DataFrame(),
|
|
435
|
+
pd.DataFrame(),
|
|
436
|
+
)
|
|
437
|
+
period = str(year)
|
|
438
|
+
for variable in self.tax_benefit_system.variables.values():
|
|
439
|
+
entity = variable.entity.key
|
|
440
|
+
result = self.calculate(variable.name, period).values
|
|
441
|
+
if entity == "person":
|
|
442
|
+
person[variable.name] = result
|
|
443
|
+
elif entity == "benunit":
|
|
444
|
+
benunit[variable.name] = result
|
|
445
|
+
elif entity == "household":
|
|
446
|
+
household[variable.name] = result
|
|
447
|
+
|
|
448
|
+
person = MicroDataFrame(person, weights="person_weight")
|
|
449
|
+
benunit = MicroDataFrame(benunit, weights="benunit_weight")
|
|
450
|
+
household = MicroDataFrame(household, weights="household_weight")
|
|
451
|
+
|
|
452
|
+
return UKSingleYearDataset(
|
|
453
|
+
person=person,
|
|
454
|
+
benunit=benunit,
|
|
455
|
+
household=household,
|
|
456
|
+
fiscal_year=year,
|
|
457
|
+
)
|
|
458
|
+
|
|
410
459
|
def calculate(
|
|
411
460
|
self,
|
|
412
|
-
variable_name: str,
|
|
461
|
+
variable_name: str = None,
|
|
413
462
|
period: str = None,
|
|
414
463
|
map_to: str = None,
|
|
415
464
|
decode_enums: bool = False,
|
|
416
465
|
):
|
|
466
|
+
if variable_name is None:
|
|
467
|
+
return self.calculate_all()
|
|
417
468
|
tracer: SimpleTracer = self.tracer
|
|
418
469
|
if len(tracer.stack) == 0:
|
|
419
470
|
# Only decode enums to string values when we're not within
|
|
@@ -428,3 +479,127 @@ class Simulation(CoreSimulation):
|
|
|
428
479
|
return super().calculate(
|
|
429
480
|
variable_name, period, map_to=map_to, decode_enums=decode_enums
|
|
430
481
|
)
|
|
482
|
+
|
|
483
|
+
def apply_dynamics(self, year: int):
|
|
484
|
+
"""Apply dynamics to the simulation for a specific year.
|
|
485
|
+
|
|
486
|
+
Args:
|
|
487
|
+
year: Year to apply dynamics for
|
|
488
|
+
"""
|
|
489
|
+
# Apply OBR labour supply dynamics if enabled
|
|
490
|
+
from policyengine_uk.dynamics.labour_supply import (
|
|
491
|
+
apply_labour_supply_responses,
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
return apply_labour_supply_responses(self, year=str(year))
|
|
495
|
+
|
|
496
|
+
def get_variable_dependencies(self, variable_name: str, depth: int = 1):
|
|
497
|
+
if self._variable_dependencies is None:
|
|
498
|
+
self._variable_dependencies = {}
|
|
499
|
+
self._example_simulation = Simulation(
|
|
500
|
+
situation={
|
|
501
|
+
"age": 30,
|
|
502
|
+
},
|
|
503
|
+
trace=True,
|
|
504
|
+
)
|
|
505
|
+
self._example_simulation.calculate("hbai_household_net_income")
|
|
506
|
+
for (
|
|
507
|
+
variable
|
|
508
|
+
) in self._example_simulation.tax_benefit_system.variables:
|
|
509
|
+
try:
|
|
510
|
+
dependencies = get_variable_dependencies(
|
|
511
|
+
variable, self._example_simulation
|
|
512
|
+
)
|
|
513
|
+
self._variable_dependencies[variable] = dependencies
|
|
514
|
+
except Exception as e:
|
|
515
|
+
self._variable_dependencies[variable] = []
|
|
516
|
+
|
|
517
|
+
if variable_name not in self._variable_dependencies:
|
|
518
|
+
raise ValueError(
|
|
519
|
+
f"Variable '{variable_name}' not found in simulation dependencies."
|
|
520
|
+
)
|
|
521
|
+
dependencies = self._variable_dependencies[variable_name]
|
|
522
|
+
|
|
523
|
+
if depth <= 1:
|
|
524
|
+
return dependencies
|
|
525
|
+
|
|
526
|
+
all_dependencies = set(dependencies)
|
|
527
|
+
for dep in dependencies:
|
|
528
|
+
try:
|
|
529
|
+
sub_dependencies = self.get_variable_dependencies(
|
|
530
|
+
dep, depth - 1
|
|
531
|
+
)
|
|
532
|
+
all_dependencies.update(sub_dependencies)
|
|
533
|
+
except ValueError:
|
|
534
|
+
continue
|
|
535
|
+
return list(all_dependencies)
|
|
536
|
+
|
|
537
|
+
def compare(
|
|
538
|
+
self,
|
|
539
|
+
other: "Simulation",
|
|
540
|
+
variables: list[str] = None,
|
|
541
|
+
period: str = None,
|
|
542
|
+
change_only: bool = False,
|
|
543
|
+
):
|
|
544
|
+
"""Compare two simulations for a specific variable list.
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
other: Another Simulation instance to compare against
|
|
548
|
+
variables: List of variable names to compare. If None, compares all variables.
|
|
549
|
+
|
|
550
|
+
Returns:
|
|
551
|
+
DataFrame with comparison results
|
|
552
|
+
"""
|
|
553
|
+
|
|
554
|
+
if variables is None:
|
|
555
|
+
variables = self.input_variables + [
|
|
556
|
+
"hbai_household_net_income",
|
|
557
|
+
]
|
|
558
|
+
|
|
559
|
+
df_self = self.calculate_dataframe(variables, period=period)
|
|
560
|
+
df_other = other.calculate_dataframe(variables, period=period)
|
|
561
|
+
|
|
562
|
+
df_combined = pd.concat(
|
|
563
|
+
[df_self, df_other], axis=1, keys=["self", "other"]
|
|
564
|
+
)
|
|
565
|
+
# Reset columns, then order by variable name first then self/other
|
|
566
|
+
df_combined.columns = [
|
|
567
|
+
f"{var}_{entity}" for entity, var in df_combined.columns
|
|
568
|
+
]
|
|
569
|
+
# Add change where applicable (numeric only)
|
|
570
|
+
for variable in variables:
|
|
571
|
+
self_col = f"{variable}_self"
|
|
572
|
+
other_col = f"{variable}_other"
|
|
573
|
+
try:
|
|
574
|
+
df_combined[f"{variable}_change"] = (
|
|
575
|
+
df_combined[other_col] - df_combined[self_col]
|
|
576
|
+
)
|
|
577
|
+
except:
|
|
578
|
+
# For other data types, use XOR
|
|
579
|
+
df_combined[f"{variable}_change"] = (
|
|
580
|
+
df_combined[other_col] != df_combined[self_col]
|
|
581
|
+
)
|
|
582
|
+
columns = []
|
|
583
|
+
|
|
584
|
+
for variable in variables:
|
|
585
|
+
columns.extend(
|
|
586
|
+
[
|
|
587
|
+
f"{variable}_self",
|
|
588
|
+
f"{variable}_other",
|
|
589
|
+
f"{variable}_change",
|
|
590
|
+
]
|
|
591
|
+
)
|
|
592
|
+
|
|
593
|
+
if change_only:
|
|
594
|
+
variables_to_include = []
|
|
595
|
+
for variable in variables:
|
|
596
|
+
if df_combined[f"{variable}_change"].mean() > 0:
|
|
597
|
+
variables_to_include.extend(
|
|
598
|
+
[
|
|
599
|
+
f"{variable}_self",
|
|
600
|
+
f"{variable}_other",
|
|
601
|
+
f"{variable}_change",
|
|
602
|
+
]
|
|
603
|
+
)
|
|
604
|
+
columns = variables_to_include
|
|
605
|
+
return df_combined[columns]
|
|
@@ -11,6 +11,7 @@ from policyengine_core.parameters.operations.uprate_parameters import (
|
|
|
11
11
|
uprate_parameters,
|
|
12
12
|
)
|
|
13
13
|
from policyengine_core.taxbenefitsystems import TaxBenefitSystem
|
|
14
|
+
from policyengine_core.variables import Variable
|
|
14
15
|
|
|
15
16
|
# PolicyEngine UK imports
|
|
16
17
|
from policyengine_uk.entities import BenUnit, Household, Person
|
|
@@ -56,6 +57,8 @@ class CountryTaxBenefitSystem(TaxBenefitSystem):
|
|
|
56
57
|
modelled_policies = COUNTRY_DIR / "modelled_policies.yaml"
|
|
57
58
|
auto_carry_over_input_variables: bool = True
|
|
58
59
|
|
|
60
|
+
variables: Dict[str, Variable]
|
|
61
|
+
|
|
59
62
|
def reset_parameter_caches(self):
|
|
60
63
|
"""Reset all caches in the tax-benefit system."""
|
|
61
64
|
self._parameters_at_instant_cache = {}
|
|
@@ -102,7 +105,7 @@ class CountryTaxBenefitSystem(TaxBenefitSystem):
|
|
|
102
105
|
def __init__(self):
|
|
103
106
|
"""Initialize the UK tax-benefit system with entities and parameters."""
|
|
104
107
|
self._parameters_at_instant_cache: Dict[str, Any] = {}
|
|
105
|
-
self.variables
|
|
108
|
+
self.variables = {}
|
|
106
109
|
|
|
107
110
|
# Create copies of entity classes to avoid modifying originals
|
|
108
111
|
person, benunit, household = (
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
reforms:
|
|
2
2
|
- name: Raise basic rate by 1pp
|
|
3
|
-
expected_impact:
|
|
3
|
+
expected_impact: 8.0
|
|
4
4
|
parameters:
|
|
5
5
|
gov.hmrc.income_tax.rates.uk[0].rate: 0.21
|
|
6
6
|
- name: Raise higher rate by 1pp
|
|
7
|
-
expected_impact: 4.
|
|
7
|
+
expected_impact: 4.8
|
|
8
8
|
parameters:
|
|
9
9
|
gov.hmrc.income_tax.rates.uk[1].rate: 0.42
|
|
10
10
|
- name: Raise personal allowance by ~800GBP/year
|
|
@@ -12,22 +12,22 @@ reforms:
|
|
|
12
12
|
parameters:
|
|
13
13
|
gov.hmrc.income_tax.allowances.personal_allowance.amount: 13000
|
|
14
14
|
- name: Raise child benefit by 25GBP/week per additional child
|
|
15
|
-
expected_impact: -1.
|
|
15
|
+
expected_impact: -1.3
|
|
16
16
|
parameters:
|
|
17
17
|
gov.hmrc.child_benefit.amount.additional: 25
|
|
18
18
|
- name: Reduce Universal Credit taper rate to 20%
|
|
19
|
-
expected_impact: -
|
|
19
|
+
expected_impact: -33.8
|
|
20
20
|
parameters:
|
|
21
21
|
gov.dwp.universal_credit.means_test.reduction_rate: 0.2
|
|
22
22
|
- name: Raise Class 1 main employee NICs rate to 10%
|
|
23
|
-
expected_impact: 12.
|
|
23
|
+
expected_impact: 12.7
|
|
24
24
|
parameters:
|
|
25
25
|
gov.hmrc.national_insurance.class_1.rates.employee.main: 0.1
|
|
26
26
|
- name: Raise VAT standard rate by 2pp
|
|
27
|
-
expected_impact:
|
|
27
|
+
expected_impact: 20.9
|
|
28
28
|
parameters:
|
|
29
29
|
gov.hmrc.vat.standard_rate: 0.22
|
|
30
30
|
- name: Raise additional rate by 3pp
|
|
31
|
-
expected_impact: 5.
|
|
31
|
+
expected_impact: 5.1
|
|
32
32
|
parameters:
|
|
33
33
|
gov.hmrc.income_tax.rates.uk[2].rate: 0.48
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from
|
|
1
|
+
from policyengine_uk import Microsimulation
|
|
2
2
|
import pytest
|
|
3
3
|
|
|
4
4
|
YEARS = range(2024, 2026)
|
|
@@ -6,8 +6,7 @@ YEARS = range(2024, 2026)
|
|
|
6
6
|
|
|
7
7
|
@pytest.mark.parametrize("year", YEARS)
|
|
8
8
|
def test_not_nan(year):
|
|
9
|
-
baseline =
|
|
10
|
-
baseline = baseline.baseline_simulation
|
|
9
|
+
baseline = Microsimulation()
|
|
11
10
|
for variable in baseline.tax_benefit_system.variables:
|
|
12
11
|
requires_computation_after = baseline.tax_benefit_system.variables[
|
|
13
12
|
variable
|