Skip to content

Commit a24b284

Browse files
authored
Merge pull request #214 from PolicyEngine/salary-sacrifice
Salary sacrifice pension variable
2 parents 21ecae6 + 1b0a4fd commit a24b284

5 files changed

Lines changed: 44 additions & 0 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: minor
2+
changes:
3+
added:
4+
- Add pension_contributions_via_salary_sacrifice variable from FRS SPNAMT field

policyengine_uk_data/datasets/frs.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,20 @@ def determine_education_level(fted_val, typeed2_val, age_val):
631631
pe_person["employer_pension_contributions"] = (
632632
pe_person["employee_pension_contributions"] * 3
633633
) # Rough estimate based on aggregates.
634+
# Salary sacrifice pension contributions from FRS Job table (SPNAMT field)
635+
# SPNAMT represents employer pension contributions made via salary sacrifice
636+
# arrangements where employees forego salary in exchange for increased pension
637+
# contributions. This is separate from regular employee pension contributions
638+
# (deduc1) and provides tax advantages for both employer and employee.
639+
# Uses same pattern as employee_pension_contributions (deduc1) without outlier
640+
# clipping, as job-level data is generally cleaner than pension provider data.
641+
# Source: https://datacatalogue.ukdataservice.ac.uk/datasets/dataset/630d4a8d-ba6a-82b3-f33d-c713c66efcb3
642+
# Note: Values are annualized from weekly amounts reported in the survey.
643+
pe_person["pension_contributions_via_salary_sacrifice"] = np.maximum(
644+
0,
645+
sum_to_entity(job.spnamt.fillna(0), job.person_id, person.person_id)
646+
* WEEKS_IN_YEAR,
647+
)
634648

635649
pe_household["housing_service_charges"] = (
636650
pd.DataFrame(

policyengine_uk_data/storage/uprating_factors.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ domestic_energy_consumption,1.0,1.04,1.144,1.209,1.237,1.277,1.301,1.327,1.353,1
2121
education_consumption,1.0,1.04,1.144,1.209,1.237,1.277,1.301,1.327,1.353,1.38,1.38,1.38,1.38,1.38,1.38
2222
employee_pension_contributions,1.0,1.059,1.127,1.205,1.261,1.308,1.337,1.365,1.396,1.431,1.431,1.431,1.431,1.431,1.431
2323
employer_pension_contributions,1.0,1.059,1.127,1.205,1.261,1.308,1.337,1.365,1.396,1.431,1.431,1.431,1.431,1.431,1.431
24+
pension_contributions_via_salary_sacrifice,1.0,1.059,1.127,1.205,1.261,1.308,1.337,1.365,1.396,1.431,1.431,1.431,1.431,1.431,1.431
2425
employment_income,1.0,1.059,1.127,1.205,1.261,1.308,1.337,1.365,1.396,1.431,1.431,1.431,1.431,1.431,1.431
2526
employment_income_before_lsr,1.0,1.059,1.127,1.205,1.261,1.308,1.337,1.365,1.396,1.431,1.431,1.431,1.431,1.431,1.431
2627
esa_contrib_reported,1.0,1.04,1.144,1.209,1.237,1.277,1.301,1.327,1.353,1.38,1.38,1.38,1.38,1.38,1.38

policyengine_uk_data/storage/uprating_growth_factors.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ domestic_energy_consumption,0,0.04,0.1,0.057,0.023,0.032,0.019,0.02,0.02,0.02,0.
2121
education_consumption,0,0.04,0.1,0.057,0.023,0.032,0.019,0.02,0.02,0.02,0.0,0.0,0.0,0.0,0.0
2222
employee_pension_contributions,0,0.059,0.064,0.069,0.046,0.037,0.022,0.021,0.023,0.025,0.0,0.0,0.0,0.0,0.0
2323
employer_pension_contributions,0,0.059,0.064,0.069,0.046,0.037,0.022,0.021,0.023,0.025,0.0,0.0,0.0,0.0,0.0
24+
pension_contributions_via_salary_sacrifice,0,0.059,0.064,0.069,0.046,0.037,0.022,0.021,0.023,0.025,0.0,0.0,0.0,0.0,0.0
2425
employment_income,0,0.059,0.064,0.069,0.046,0.037,0.022,0.021,0.023,0.025,0.0,0.0,0.0,0.0,0.0
2526
employment_income_before_lsr,0,0.059,0.064,0.069,0.046,0.037,0.022,0.021,0.023,0.025,0.0,0.0,0.0,0.0,0.0
2627
esa_contrib_reported,0,0.04,0.1,0.057,0.023,0.032,0.019,0.02,0.02,0.02,0.0,0.0,0.0,0.0,0.0
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
def test_pension_contributions_via_salary_sacrifice(baseline):
2+
"""Test that pension_contributions_via_salary_sacrifice loads and has reasonable values."""
3+
values = baseline.calculate(
4+
"pension_contributions_via_salary_sacrifice", period=2025
5+
)
6+
7+
# Basic validation: all values should be non-negative
8+
assert (
9+
values >= 0
10+
).all(), "Salary sacrifice pension contributions must be non-negative"
11+
12+
# Should have some non-zero values (not everyone uses salary sacrifice, but some do)
13+
total = values.sum()
14+
assert (
15+
total > 0
16+
), f"Expected some salary sacrifice contributions, got {total}"
17+
18+
# Reasonableness check: total should be less than total employment income
19+
# This is a very loose check just to catch major issues
20+
employment_income = baseline.calculate("employment_income", period=2025)
21+
total_employment = employment_income.sum()
22+
assert (
23+
total < total_employment
24+
), f"Salary sacrifice contributions ({total/1e9:.1f}B) cannot exceed total employment income ({total_employment/1e9:.1f}B)"

0 commit comments

Comments
 (0)