Skip to content

Commit 1a1acf2

Browse files
Merge pull request #223 from PolicyEngine/calibration-fix-2
Calibration fix on SS target
2 parents 28b92d5 + dc4b9b0 commit 1a1acf2

2 files changed

Lines changed: 73 additions & 6 deletions

File tree

changelog_entry.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- bump: patch
2+
changes:
3+
added:
4+
- SS HMRC calibration targets.

policyengine_uk_data/utils/loss.py

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,11 @@ def pe_count(*variables):
257257

258258
df["ons/uk_population"] = household_from_person(age >= 0)
259259

260-
# Filter to columns that exist in statistics (other targets added via target_names/target_values)
261-
stats_for_period = statistics[
262-
statistics.time_period == int(time_period)
263-
].set_index("name")
264-
columns_in_stats = [c for c in df.columns if c in stats_for_period.index]
265-
targets = stats_for_period.loc[columns_in_stats]
260+
targets = (
261+
statistics[statistics.time_period == int(time_period)]
262+
.set_index("name")
263+
.loc[df.columns]
264+
)
266265

267266
targets.value = np.select(
268267
[
@@ -328,6 +327,66 @@ def pe_count(*variables):
328327
target_values.append(row[variable + "_count"])
329328
target_names.append(name_count)
330329

330+
# HMRC Table 6.2 - Salary sacrifice income tax relief by tax rate
331+
# This helps calibrate the distribution of SS users by income level
332+
# 2023-24 values (£m): Basic £1,600, Higher £4,400, Additional £1,200
333+
# Total IT relief from SS: £7,200m
334+
# Use true counterfactual: IT relief = counterfactual IT - baseline IT
335+
income_tax_baseline = sim.calculate("income_tax")
336+
income_tax_cf = counterfactual_sim.calculate("income_tax", time_period)
337+
it_relief = income_tax_cf - income_tax_baseline
338+
339+
# Get tax band from counterfactual adjusted net income (where SS is wages)
340+
adjusted_net_income_cf = counterfactual_sim.calculate(
341+
"adjusted_net_income", time_period
342+
)
343+
basic_rate_threshold = (
344+
sim.tax_benefit_system.parameters.gov.hmrc.income_tax.rates.uk[
345+
0
346+
].threshold(time_period)
347+
)
348+
higher_rate_threshold = (
349+
sim.tax_benefit_system.parameters.gov.hmrc.income_tax.rates.uk[
350+
1
351+
].threshold(time_period)
352+
)
353+
additional_rate_threshold = (
354+
sim.tax_benefit_system.parameters.gov.hmrc.income_tax.rates.uk[
355+
2
356+
].threshold(time_period)
357+
)
358+
359+
# Determine tax band for each person based on counterfactual income
360+
is_basic_rate = (adjusted_net_income_cf > basic_rate_threshold) & (
361+
adjusted_net_income_cf <= higher_rate_threshold
362+
)
363+
is_higher_rate = (adjusted_net_income_cf > higher_rate_threshold) & (
364+
adjusted_net_income_cf <= additional_rate_threshold
365+
)
366+
is_additional_rate = adjusted_net_income_cf > additional_rate_threshold
367+
368+
# Allocate the true IT relief to tax bands
369+
ss_it_relief_basic = it_relief * is_basic_rate
370+
ss_it_relief_higher = it_relief * is_higher_rate
371+
ss_it_relief_additional = it_relief * is_additional_rate
372+
373+
df["hmrc/salary_sacrifice_it_relief_basic"] = household_from_person(
374+
ss_it_relief_basic
375+
)
376+
df["hmrc/salary_sacrifice_it_relief_higher"] = household_from_person(
377+
ss_it_relief_higher
378+
)
379+
df["hmrc/salary_sacrifice_it_relief_additional"] = household_from_person(
380+
ss_it_relief_additional
381+
)
382+
383+
# Total gross salary sacrifice contributions
384+
# This is derived from the IT relief: £7.2bn IT relief at ~30% avg rate
385+
# implies ~£24bn gross contributions (but we target the relief directly)
386+
df["hmrc/salary_sacrifice_contributions"] = household_from_person(
387+
ss_contributions
388+
)
389+
331390
# HMRC Table 6.2 - Salary sacrifice income tax relief by tax rate (2023-24)
332391
# https://assets.publishing.service.gov.uk/media/687a294e312ee8a5f0806b6d/Tables_6_1_and_6_2.csv
333392
# Values in £bn
@@ -352,6 +411,8 @@ def pe_count(*variables):
352411
target_names.append("hmrc/salary_sacrifice_contributions")
353412
target_values.append(SS_CONTRIBUTIONS_2024 * uprating_factor)
354413

414+
print(target_names[-4:], target_values[-4:])
415+
355416
# Add two-child limit targets.
356417
child_is_affected = (
357418
sim.map_result(
@@ -476,6 +537,8 @@ def pe_count(*variables):
476537
]
477538
)
478539

540+
combined_targets.to_csv("test.csv")
541+
479542
return df, combined_targets.value
480543

481544

0 commit comments

Comments
 (0)