@@ -158,6 +158,102 @@ def pe_count(*variables):
158158 # Not strictly from the OBR but from the 2024 Independent Schools Council census. OBR will be using that.
159159 df ["obr/private_school_students" ] = pe ("attends_private_school" )
160160
161+ # Salary sacrifice NI relief - SPP estimates £4.1bn total (£1.2bn employee + £2.9bn employer)
162+ # Calculate relief via counterfactual: what additional NI would be paid if SS became income
163+ ss_contributions = sim .calculate (
164+ "pension_contributions_via_salary_sacrifice"
165+ )
166+ employment_income = sim .calculate ("employment_income" )
167+
168+ # Run counterfactual simulation with SS converted to employment income
169+ counterfactual_sim = Microsimulation (dataset = dataset , reform = reform )
170+ counterfactual_sim .set_input (
171+ "pension_contributions_via_salary_sacrifice" ,
172+ time_period ,
173+ np .zeros_like (ss_contributions ),
174+ )
175+ counterfactual_sim .set_input (
176+ "employment_income" ,
177+ time_period ,
178+ employment_income + ss_contributions ,
179+ )
180+
181+ # NI relief = counterfactual NI - baseline NI
182+ ni_employee_baseline = sim .calculate ("ni_employee" )
183+ ni_employer_baseline = sim .calculate ("ni_employer" )
184+ ni_employee_cf = counterfactual_sim .calculate ("ni_employee" , time_period )
185+ ni_employer_cf = counterfactual_sim .calculate ("ni_employer" , time_period )
186+
187+ employee_ni_relief = ni_employee_cf - ni_employee_baseline
188+ employer_ni_relief = ni_employer_cf - ni_employer_baseline
189+
190+ df ["obr/salary_sacrifice_employee_ni_relief" ] = household_from_person (
191+ employee_ni_relief
192+ )
193+ df ["obr/salary_sacrifice_employer_ni_relief" ] = household_from_person (
194+ employer_ni_relief
195+ )
196+
197+ # HMRC Table 6.2 - Salary sacrifice income tax relief by tax rate
198+ # This helps calibrate the distribution of SS users by income level
199+ # 2023-24 values (£m): Basic £1,600, Higher £4,400, Additional £1,200
200+ # Total IT relief from SS: £7,200m
201+ # Use true counterfactual: IT relief = counterfactual IT - baseline IT
202+ income_tax_baseline = sim .calculate ("income_tax" )
203+ income_tax_cf = counterfactual_sim .calculate ("income_tax" , time_period )
204+ it_relief = income_tax_cf - income_tax_baseline
205+
206+ # Get tax band from counterfactual adjusted net income (where SS is wages)
207+ adjusted_net_income_cf = counterfactual_sim .calculate (
208+ "adjusted_net_income" , time_period
209+ )
210+ basic_rate_threshold = (
211+ sim .tax_benefit_system .parameters .gov .hmrc .income_tax .rates .uk [
212+ 0
213+ ].threshold (time_period )
214+ )
215+ higher_rate_threshold = (
216+ sim .tax_benefit_system .parameters .gov .hmrc .income_tax .rates .uk [
217+ 1
218+ ].threshold (time_period )
219+ )
220+ additional_rate_threshold = (
221+ sim .tax_benefit_system .parameters .gov .hmrc .income_tax .rates .uk [
222+ 2
223+ ].threshold (time_period )
224+ )
225+
226+ # Determine tax band for each person based on counterfactual income
227+ is_basic_rate = (adjusted_net_income_cf > basic_rate_threshold ) & (
228+ adjusted_net_income_cf <= higher_rate_threshold
229+ )
230+ is_higher_rate = (adjusted_net_income_cf > higher_rate_threshold ) & (
231+ adjusted_net_income_cf <= additional_rate_threshold
232+ )
233+ is_additional_rate = adjusted_net_income_cf > additional_rate_threshold
234+
235+ # Allocate the true IT relief to tax bands
236+ ss_it_relief_basic = it_relief * is_basic_rate
237+ ss_it_relief_higher = it_relief * is_higher_rate
238+ ss_it_relief_additional = it_relief * is_additional_rate
239+
240+ df ["hmrc/salary_sacrifice_it_relief_basic" ] = household_from_person (
241+ ss_it_relief_basic
242+ )
243+ df ["hmrc/salary_sacrifice_it_relief_higher" ] = household_from_person (
244+ ss_it_relief_higher
245+ )
246+ df ["hmrc/salary_sacrifice_it_relief_additional" ] = household_from_person (
247+ ss_it_relief_additional
248+ )
249+
250+ # Total gross salary sacrifice contributions
251+ # This is derived from the IT relief: £7.2bn IT relief at ~30% avg rate
252+ # implies ~£24bn gross contributions (but we target the relief directly)
253+ df ["hmrc/salary_sacrifice_contributions" ] = household_from_person (
254+ ss_contributions
255+ )
256+
161257 # Population statistics from the ONS.
162258
163259 region = sim .calculate ("region" , map_to = "person" )
@@ -221,11 +317,12 @@ def pe_count(*variables):
221317
222318 df ["ons/uk_population" ] = household_from_person (age >= 0 )
223319
224- targets = (
225- statistics [statistics .time_period == int (time_period )]
226- .set_index ("name" )
227- .loc [df .columns ]
228- )
320+ # Filter to columns that exist in statistics (other targets added via target_names/target_values)
321+ stats_for_period = statistics [
322+ statistics .time_period == int (time_period )
323+ ].set_index ("name" )
324+ columns_in_stats = [c for c in df .columns if c in stats_for_period .index ]
325+ targets = stats_for_period .loc [columns_in_stats ]
229326
230327 targets .value = np .select (
231328 [
@@ -291,6 +388,30 @@ def pe_count(*variables):
291388 target_values .append (row [variable + "_count" ])
292389 target_names .append (name_count )
293390
391+ # HMRC Table 6.2 - Salary sacrifice income tax relief by tax rate (2023-24)
392+ # https://assets.publishing.service.gov.uk/media/687a294e312ee8a5f0806b6d/Tables_6_1_and_6_2.csv
393+ # Values in £bn
394+ SS_IT_RELIEF_BASIC_2024 = 1.6e9
395+ SS_IT_RELIEF_HIGHER_2024 = 4.4e9
396+ SS_IT_RELIEF_ADDITIONAL_2024 = 1.2e9
397+ SS_CONTRIBUTIONS_2024 = 24e9 # £7.2bn IT relief / 0.30 avg rate
398+
399+ # Uprate by ~3% per year for wage growth
400+ years_from_2024 = max (0 , int (time_period ) - 2024 )
401+ uprating_factor = 1.03 ** years_from_2024
402+
403+ target_names .append ("hmrc/salary_sacrifice_it_relief_basic" )
404+ target_values .append (SS_IT_RELIEF_BASIC_2024 * uprating_factor )
405+
406+ target_names .append ("hmrc/salary_sacrifice_it_relief_higher" )
407+ target_values .append (SS_IT_RELIEF_HIGHER_2024 * uprating_factor )
408+
409+ target_names .append ("hmrc/salary_sacrifice_it_relief_additional" )
410+ target_values .append (SS_IT_RELIEF_ADDITIONAL_2024 * uprating_factor )
411+
412+ target_names .append ("hmrc/salary_sacrifice_contributions" )
413+ target_values .append (SS_CONTRIBUTIONS_2024 * uprating_factor )
414+
294415 # Add two-child limit targets.
295416 child_is_affected = (
296417 sim .map_result (
0 commit comments