From 80dc98895968b986ad1ce9d910c8e7c22d1da0a5 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Wed, 27 May 2026 11:32:29 +0200 Subject: [PATCH] Compare PolicyEngine UK pension treatment with STBM (#672) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #672 asks for a comparison of PolicyEngine UK's pension treatment with the Scottish Tax-Benefit Model's methodology described in the Virtual Worlds blog post. Persist the comparison in-repo as a docs page. The headline conclusion is the two models compute the same aggregate fiscal cost of pension tax relief for any given household; they differ only in presentation: - STBM splits relief-at-source (basic rate) and the higher-rate top-up (via SA basic-rate-band extension); - PolicyEngine UK combines them into a single pension_contributions_relief reduction in taxable income — matching the HMRC pension tax relief statistics methodology used as the calibration target. The page also enumerates: - shared mechanics (annual allowance taper, salary sacrifice, employer contribution exclusion from earnings), - shared gaps (annual-allowance carry-forward not modelled in either, decumulation taxation beyond basic private_pension_income), - divergences in State Pension structure (PolicyEngine UK uses the three-variable BSP / NSP / ASP split; STBM uses a single transfer per the linked blog), - post-2024 lifetime-allowance abolition: historical LTA params retained for back-cast, post-2024 lump-sum allowances not yet modelled. Cross-links to the pension-tax-relief and state-pension docs pages added under #704 and #1632 respectively, so the three pages function as a coherent pension-modelling reference. --- changelog.d/672.md | 1 + .../gov/hmrc/pensions-comparison-stbm.md | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 changelog.d/672.md create mode 100644 docs/book/programs/gov/hmrc/pensions-comparison-stbm.md diff --git a/changelog.d/672.md b/changelog.d/672.md new file mode 100644 index 000000000..25e9e2a2a --- /dev/null +++ b/changelog.d/672.md @@ -0,0 +1 @@ +- Add a documentation page at `docs/book/programs/gov/hmrc/pensions-comparison-stbm.md` comparing PolicyEngine UK's pension treatment with the Scottish Tax-Benefit Model methodology described in the Virtual Worlds blog — same aggregate fiscal cost, but presentational differences around relief-at-source vs higher-rate top-up, plus shared gaps (carry-forward, decumulation taxation). diff --git a/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md new file mode 100644 index 000000000..76fbddfb2 --- /dev/null +++ b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md @@ -0,0 +1,128 @@ +# Pension treatment compared with the Scottish Tax-Benefit Model + +This page documents how PolicyEngine UK's handling of personal pension +contributions compares with the [Scottish Tax-Benefit Model (STBM) +methodology][stbm-blog] described in the Virtual Worlds blog. It +addresses [#672](https://github.com/PolicyEngine/policyengine-uk/issues/672). + +Read alongside [pension-tax-relief.md](./pension-tax-relief.md), which +explains the PolicyEngine pension-relief mechanics in detail. + +## Summary + +Both models compute the **same total tax cost** of pension tax relief +at the aggregate level for a given household, but they differ in how +the relief is presented: + +| | PolicyEngine UK | Scottish Tax-Benefit Model | +|---------------------------------------|------------------------------------------------|--------------------------------------------------------| +| Treatment of within-allowance contribution | Reduce taxable income by gross contribution | Same | +| Relief mechanism in code | Single `pension_contributions_relief` variable | Split between relief-at-source and basic-rate-band extension | +| Excess-over-allowance treatment | Separate `personal_pension_contributions_tax` charge at marginal rate | Same | +| Salary sacrifice | `pension_contributions_via_salary_sacrifice` input; deducted from earnings before NI; affects employer NI cost | Same in principle | +| Employer contributions | `employer_pension_contributions` input; excluded from earnings for income tax and NI | Same | +| State Pension | Three composable variables (`basic_state_pension`, `new_state_pension`, `additional_state_pension`) with triple-lock uprating | Modelled as a single uprated transfer | + +## Where the two models could diverge + +### 1. Presentation of relief at source vs the higher-rate top-up + +STBM (as described in the Virtual Worlds blog) tends to keep the +**relief-at-source** portion (basic-rate, paid into the pension pot) +separate from the **higher-rate top-up** (paid back to the taxpayer via +Self Assessment). PolicyEngine UK combines both into a single +`pension_contributions_relief` reduction in taxable income. + +Why it doesn't change the answer: at the *household-level fiscal cost*, +both methods produce identical totals. HMRC's *pension tax relief +statistics* — which both models target for calibration — report the +combined relief. + +Where it would change the answer: a user who wants to break out the +"cash visible to the taxpayer" portion of their tax bill needs the +split version (because their own SA refund is only the higher-rate +top-up). PolicyEngine UK would need an output split into two new +variables (`pension_relief_at_source` and `pension_higher_rate_top_up`) +to surface this distinction — discussed in +[pension-tax-relief.md](./pension-tax-relief.md). + +### 2. Annual allowance taper + +For high earners (adjusted income > £260,000 since 2023-24), the +annual allowance is tapered. PolicyEngine UK encodes this through: + +- `gov/hmrc/income_tax/allowances/annual_allowance/taper.yaml` +- `gov/hmrc/income_tax/allowances/annual_allowance/reduction_rate.yaml` +- `gov/hmrc/income_tax/allowances/annual_allowance/minimum.yaml` + +STBM applies the same taper mechanically. The two diverge only if +STBM's modelling of the *adjusted-income* trigger differs from +PolicyEngine UK's `meets_marriage_allowance_income_conditions`-style +piecewise calculations. + +### 3. Carry-forward of unused allowance + +UK rules allow carrying forward unused annual allowance from the +previous three tax years. **Neither** PolicyEngine UK nor (as of the +linked blog) STBM models this — both treat the annual allowance as +strictly per-year. + +For most households this doesn't matter; the carry-forward is mainly +used by people with lumpy contributions (one-off bonus / sale events). +Either model would need an explicit `unused_annual_allowance_carryforward` +input to handle this correctly. + +### 4. Lifetime allowance (abolished from 6 April 2024) + +PolicyEngine UK historically tracked the lifetime allowance under +`gov/hmrc/pensions/`. From 6 April 2024 the lifetime allowance was +abolished and replaced by the **lump sum allowance** and **lump sum +and death benefit allowance**. PolicyEngine UK and STBM both need +parameters here; current PolicyEngine UK status: + +- the historical lifetime-allowance values remain in the parameter tree + for back-cast simulations, +- the post-2024 lump sum allowances are not yet modelled, as they + rarely affect ordinary income-tax-cost analysis (they only bite at + withdrawal). + +### 5. State Pension structure + +PolicyEngine UK uses the three-variable split documented in +[state-pension.md](../dwp/state-pension.md): +`basic_state_pension`, `new_state_pension`, `additional_state_pension` +(SERPS / S2P for BASIC; Protected Payment for NEW). STBM appears to +treat State Pension as a single transfer per the blog — which is +appropriate for headline distributional analysis but obscures the +Protected Payment structure that matters for reform analysis (e.g. +abolishing the triple lock on the new flat rate only). + +## Calibration + +Both models target HMRC pension tax relief statistics and DWP State +Pension outturn. PolicyEngine UK's residual State Pension undershoot is +documented under [state-pension.md](../dwp/state-pension.md) and +[#1632](https://github.com/PolicyEngine/policyengine-uk/issues/1632); +STBM's calibration variance is not publicly documented in detail. + +## What's not modelled in either + +- **Pension contribution behavioural response** to tax-rate changes + (people changing their contribution rate when the higher-rate band + changes). Both models hold contributions fixed. +- **Decumulation taxation** (income drawn from pensions in retirement) + beyond the basic `private_pension_income` input — neither model + walks through crystallisation, the 25% tax-free lump sum, or annuity + vs. drawdown decisions. + +## References + +- Virtual Worlds, [STBM blog: Pension contributions][stbm-blog] — the + reference methodology this page compares against. +- PolicyEngine UK: [pension-tax-relief.md](./pension-tax-relief.md), + [state-pension.md](../dwp/state-pension.md). +- Variables: [`pension_contributions_relief`](../../../policyengine_uk/variables/gov/hmrc/pensions/pension_contributions_relief.py), [`personal_pension_contributions_tax`](../../../policyengine_uk/variables/gov/hmrc/pensions/private_pension_contributions_tax.py). +- HMRC, [Pension tax relief statistics](https://www.gov.uk/government/collections/personal-pensions-statistics). +- Issue: [#672](https://github.com/PolicyEngine/policyengine-uk/issues/672). + +[stbm-blog]: https://stb-blog.virtual-worlds.scot/articles/2022/01/01/pension-contributions.html