From 678b43483cfb148b2fe99c535f9dbb3be9e0ea9c Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Wed, 27 May 2026 11:32:29 +0200 Subject: [PATCH 1/6] 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 0000000000..25e9e2a2ac --- /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 0000000000..76fbddfb22 --- /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 From dbcf538549360fde1cfb19fae9dbaf813ad56905 Mon Sep 17 00:00:00 2001 From: vahid-ahmadi Date: Thu, 8 Oct 2026 15:54:30 +0100 Subject: [PATCH 2/6] Refresh the planning page against the current code and type its changelog fragment Checked every variable, parameter, path and link against main in October 2026, updated the data pipeline references to Microcosm UK, and renamed the changelog fragment to a Towncrier type. Co-Authored-By: Claude Opus 5.5 --- changelog.d/672.added.md | 1 + changelog.d/672.md | 1 - .../gov/hmrc/pensions-comparison-stbm.md | 202 ++++++++---------- 3 files changed, 86 insertions(+), 118 deletions(-) create mode 100644 changelog.d/672.added.md delete mode 100644 changelog.d/672.md diff --git a/changelog.d/672.added.md b/changelog.d/672.added.md new file mode 100644 index 0000000000..67dabe7559 --- /dev/null +++ b/changelog.d/672.added.md @@ -0,0 +1 @@ +- Add a documentation page (`docs/book/programs/gov/hmrc/pensions-comparison-stbm.md`) comparing PolicyEngine UK's treatment of pension contributions in income tax with the Scottish Tax-Benefit Model's source code, including a gap both share: contributions do not reduce adjusted net income for the personal allowance taper. diff --git a/changelog.d/672.md b/changelog.d/672.md deleted file mode 100644 index 25e9e2a2ac..0000000000 --- a/changelog.d/672.md +++ /dev/null @@ -1 +0,0 @@ -- 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 index 76fbddfb22..39f18ab016 100644 --- a/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md +++ b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md @@ -1,128 +1,96 @@ # 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. +This page compares how PolicyEngine UK and the +[Scottish Tax-Benefit Model (STBM)][stbm] treat personal pension +contributions in income tax, for +[#672](https://github.com/PolicyEngine/policyengine-uk/issues/672) (still open, +October 2026). + +The STBM column is taken from its source code at commit +[`f534ca1`][stbm-it] (`src/IncomeTaxCalculations.jl`, +`calculate_pension_taxation!`, and `src/Pensions.jl`). The +[STBM blog post on pension contributions][stbm-blog] that #672 links to is a +short note, and its author says they are unsure of it. It does not describe +the method, so this page does not rely on it. + +[How PolicyEngine UK models pension tax relief](./pension-tax-relief.md) has +more detail on the PolicyEngine side. ## 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. +| | PolicyEngine UK | STBM | +|---|---|---| +| How relief is given | Reduces taxable income by the contribution (`pension_contributions_relief`) | Treats contributions as paid net of basic rate: grosses them up by 1/(1 − basic rate) and widens every rate band above the starting band by the gross amount, as under relief at source | +| Contributions that get relief | The person's own contributions | Employee contributions, additional voluntary contributions **and employer contributions** | +| Basic-rate relief added to the pot | Not shown separately | Recorded separately (`pension_relief_at_source`) | +| Earnings limit | Relief capped at employment plus self-employment income | No earnings cap; £3,600 limit when total income is below it | +| Annual allowance | £60,000, tapered on adjusted net income above £260,000 (`pension_annual_allowance`) | Tapered on total income above a threshold-income parameter | +| Contributions above the allowance | Charged at the marginal rate (`personal_pension_contributions_tax`) | Relief stops at the allowance; no separate charge | +| Employer contributions in the data | Read from the data (`employer_pension_contributions`) | Imputed when missing from the FRS, using the ONS ASHE employer-contribution bands (`src/Pensions.jl`) | +| Carry-forward of unused allowance | Not modelled | Not modelled | + +## Where the two models differ + +### 1. Reducing taxable income versus widening the bands + +For an income-tax payer whose contribution stays inside one band, the two +methods give the same total relief. They can differ when the person pays +little or no income tax: STBM still records the basic-rate addition to the +pot, which PolicyEngine UK does not show. + +**Shared gap: the personal allowance taper.** In law, gross pension +contributions reduce adjusted net income +([Income Tax Act 2007 s. 58](https://www.legislation.gov.uk/ukpga/2007/3/section/58)), +so contributing can restore personal allowance lost above £100,000. +Neither model does this. In PolicyEngine UK, `adjusted_net_income` adds up +the taxable income components without deducting `pension_contributions_relief`: +an employee on £110,000 has adjusted net income of £110,000 and a personal +allowance of £7,570 in 2025-26 whether or not they contribute £10,000. +STBM widens the bands but leaves the taper income unchanged, and its code +flags this as unchecked. + +### 2. Employer contributions + +STBM counts employer contributions in the relief calculation. In UK law +employer contributions are not taxed as the employee's income, so they get +no personal relief. They are simply outside taxable pay, which is how +PolicyEngine UK treats them. Including them in STBM's relief widens the +employee's bands further than the law does. + +### 3. Annual allowance taper + +The legal taper uses "adjusted income", which adds employer contributions, +and applies only when "threshold income" is also above £200,000. + +- PolicyEngine UK tapers on adjusted net income, with no threshold-income + test. +- STBM tapers on total income above a threshold parameter. + +Neither follows the statute exactly. Both affect only very high earners. + +### 4. Lifetime and lump sum allowances + +The lifetime allowance was abolished from 6 April 2024 and replaced by the +lump sum allowance and the lump sum and death benefit allowance. +PolicyEngine UK has no parameters for any of these. They apply when pensions +are drawn, not to contributions. + +## What neither model does + +- Carry-forward of unused annual allowance from the previous three years. +- Behavioural responses: contributions are held fixed when tax rates change. +- Decumulation: crystallisation, the tax-free lump sum, and annuity versus + drawdown choices. ## 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). +- STBM source: [`IncomeTaxCalculations.jl`][stbm-it] and [`Pensions.jl`][stbm-pen] at `f534ca1`. +- [STBM blog: pension contributions][stbm-blog]. +- PolicyEngine UK: [pension tax relief](./pension-tax-relief.md); variables [`pension_contributions_relief`](https://github.com/PolicyEngine/policyengine-uk/blob/main/policyengine_uk/variables/gov/hmrc/pensions/pension_contributions_relief.py), [`pension_annual_allowance`](https://github.com/PolicyEngine/policyengine-uk/blob/main/policyengine_uk/variables/gov/hmrc/income_tax/allowances/pension_annual_allowance.py) and [`personal_pension_contributions_tax`](https://github.com/PolicyEngine/policyengine-uk/blob/main/policyengine_uk/variables/gov/hmrc/pensions/private_pension_contributions_tax.py). +- HMRC, [Pensions Tax Manual: annual allowance taper](https://www.gov.uk/hmrc-internal-manuals/pensions-tax-manual/ptm057100). - Issue: [#672](https://github.com/PolicyEngine/policyengine-uk/issues/672). +[stbm]: https://github.com/grahamstark/ScottishTaxBenefitModel.jl +[stbm-it]: https://github.com/grahamstark/ScottishTaxBenefitModel.jl/blob/f534ca1277260a6b4f24c9ab5ebfe9c015e1484d/src/IncomeTaxCalculations.jl +[stbm-pen]: https://github.com/grahamstark/ScottishTaxBenefitModel.jl/blob/f534ca1277260a6b4f24c9ab5ebfe9c015e1484d/src/Pensions.jl [stbm-blog]: https://stb-blog.virtual-worlds.scot/articles/2022/01/01/pension-contributions.html From b9d6e1000575baf6885ce8be439baf97bc780953 Mon Sep 17 00:00:00 2001 From: vahid-ahmadi Date: Mon, 12 Oct 2026 11:08:21 +0200 Subject: [PATCH 3/6] Drop the duplicate bullet from the changelog fragment Towncrier's default template adds its own bullet, so a fragment that starts with "- " renders as "- - " in CHANGELOG.md. The page itself was rechecked against main (pension_contributions_relief, pension_annual_allowance, personal_pension_contributions_tax, adjusted_net_income_components, annual allowance parameters) and needs no change. Co-Authored-By: Claude Opus 5.5 --- changelog.d/672.added.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/672.added.md b/changelog.d/672.added.md index 67dabe7559..2e0a22b781 100644 --- a/changelog.d/672.added.md +++ b/changelog.d/672.added.md @@ -1 +1 @@ -- Add a documentation page (`docs/book/programs/gov/hmrc/pensions-comparison-stbm.md`) comparing PolicyEngine UK's treatment of pension contributions in income tax with the Scottish Tax-Benefit Model's source code, including a gap both share: contributions do not reduce adjusted net income for the personal allowance taper. +Add a documentation page (`docs/book/programs/gov/hmrc/pensions-comparison-stbm.md`) comparing PolicyEngine UK's treatment of pension contributions in income tax with the Scottish Tax-Benefit Model's source code, including a gap both share: contributions do not reduce adjusted net income for the personal allowance taper. From c64cc6cd836b493f52010e12002ed0678ed66dab Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 02:21:45 -0400 Subject: [PATCH 4/6] Correct the STBM pension comparison against STBM's source and main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit STBM claims checked against ScottishTaxBenefitModel.jl at f534ca1: - calculate_pension_taxation! raises non_savings_thresholds from the basic rate onwards (IncomeTaxCalculations.jl:138), so it widens the basic band and moves the higher limits up, not "every band". - pension_contrib_basic_amount is £10,000 in the 2023-24 to 2026-27 rUK files, which the Scottish systems inherit; £3,600 before. - In its rUK systems from 2023-24, non_savings_basic_rate points at 40%. PolicyEngine UK claims checked against main a45baf5e4: - The relief cap rises to £3,600 for relief-at-source contributions (utils/pensions.py). - employer_pension_contributions is an input: Microcosm UK draws it from ONS ASHE Table P10 bands, the Enhanced FRS uses 3x employee contributions. - unused_pension_annual_allowance is estimated from 2020-21 (#2536). - Threshold income has been tested at £200,000 since 2020-21 (taper 240,000 - 40,000), and pre-2015 salary sacrifice is an input. - Clarified "default chargeable amount" and the Scottish starter-rate case. - Replaced the released .added fragment with a .changed fragment. Co-Authored-By: Claude Opus 5.5 --- ...-pension-comparison-corrections.changed.md | 1 + changelog.d/672.added.md | 1 - .../gov/hmrc/pensions-comparison-stbm.md | 34 ++++++++++++------- 3 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 changelog.d/672-stbm-pension-comparison-corrections.changed.md delete mode 100644 changelog.d/672.added.md diff --git a/changelog.d/672-stbm-pension-comparison-corrections.changed.md b/changelog.d/672-stbm-pension-comparison-corrections.changed.md new file mode 100644 index 0000000000..d9149e2528 --- /dev/null +++ b/changelog.d/672-stbm-pension-comparison-corrections.changed.md @@ -0,0 +1 @@ +Corrected the STBM pension comparison page (`docs/book/programs/gov/hmrc/pensions-comparison-stbm.md`): STBM raises the basic-rate limit and every higher limit rather than widening every band, its basic amount is £10,000 in its 2023-24 to 2026-27 systems, Microcosm UK imputes employer contributions from the same ONS ASHE bands as STBM, PolicyEngine UK now estimates carry-forward of unused annual allowance from 2020-21, the threshold income test has been £200,000 since 2020-21, and pre-July 2015 salary sacrifice can be supplied. diff --git a/changelog.d/672.added.md b/changelog.d/672.added.md deleted file mode 100644 index 2e0a22b781..0000000000 --- a/changelog.d/672.added.md +++ /dev/null @@ -1 +0,0 @@ -Add a documentation page (`docs/book/programs/gov/hmrc/pensions-comparison-stbm.md`) comparing PolicyEngine UK's treatment of pension contributions in income tax with the Scottish Tax-Benefit Model's source code, including a gap both share: contributions do not reduce adjusted net income for the personal allowance taper. diff --git a/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md index 67ce942385..c1a7059bcf 100644 --- a/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md +++ b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md @@ -20,21 +20,26 @@ more detail on the PolicyEngine side. | | PolicyEngine UK | STBM | |---|---|---| -| How relief is given | Reduces taxable income by the contribution (`pension_contributions_relief`) | Treats contributions as paid net of basic rate: grosses them up by 1/(1 − basic rate) and widens every rate band above the starting band by the gross amount, as under relief at source | +| How relief is given | Reduces taxable income by the contribution (`pension_contributions_relief`) | Treats contributions as paid net of basic rate: grosses them up by 1/(1 − basic rate) and raises the basic-rate limit and every higher rate limit by the gross amount, as under relief at source | | Contributions that get relief | The person's own contributions | Employee contributions, additional voluntary contributions **and employer contributions** | | Basic-rate relief added to the pot | Not shown separately | Recorded separately (`pension_relief_at_source`) | -| Earnings limit | Relief capped at relevant UK earnings: employment income, employer-paid Statutory Sick Pay and Statutory Maternity Pay, and self-employment profit | No earnings cap; £3,600 limit when total income is below it | +| Earnings limit | Relief capped at relevant UK earnings (employment income, employer-paid Statutory Sick Pay and Statutory Maternity Pay, and self-employment profit), or £3,600 for relief-at-source contributions if earnings are lower | No earnings cap; when total income is below a basic-amount parameter the limit is that amount (£10,000 in its 2023-24 to 2026-27 systems, £3,600 before) | | Annual allowance | £60,000 (`pension_annual_allowance`), tapered only when adjusted income is above £260,000 and threshold income is above £200,000, as in FA 2004 s. 228ZA | Tapered on total income above a threshold-income parameter | | Contributions above the allowance | Annual allowance charge on the excess, taxed as the top slice of income (`personal_pension_contributions_tax`) | Relief stops at the allowance; no separate charge | -| Employer contributions in the data | Read from the data (`employer_pension_contributions`) | Imputed when missing from the FRS, using the ONS ASHE employer-contribution bands (`src/Pensions.jl`) | -| Carry-forward of unused allowance | Input `unused_pension_annual_allowance` (FA 2004 s. 228A) adds to the allowance; defaults to nil, as the survey data has no past pension input amounts | Not modelled | +| Employer contributions in the data | An input (`employer_pension_contributions`). Microcosm UK draws it from the ONS ASHE employer-contribution bands (Table P10); the Enhanced FRS sets it to three times employee contributions | Imputed when missing from the FRS, using the ONS ASHE employer-contribution bands (`src/Pensions.jl`) | +| Carry-forward of unused allowance | `unused_pension_annual_allowance` (FA 2004 s. 228A) adds to the allowance. As the survey data has no past pension input amounts, from 2020-21 the default estimates it from an assumed five-year history (this year's input and taper incomes deflated by average earnings growth); before 2020-21 it is nil | Not modelled | + +The STBM column describes its Scottish systems, its default. In its +rest-of-UK systems from 2023-24, `non_savings_basic_rate` points at the 40% +rate (`params/sys_2023_24_ruk.jl` onwards, marked `FIXME`), so there the +gross-up uses 40% and only the additional-rate limit rises. ## Where the two models differ ### 1. Reducing taxable income versus widening the bands -For an income-tax payer whose contribution stays inside one band, the two -methods give the same total relief. They can differ when the person pays +For an income-tax payer whose contribution stays inside one band above the +Scottish starter rate, the two methods give the same total relief. They can differ when the person pays little or no income tax: STBM still records the basic-rate addition to the pot, which PolicyEngine UK does not show. @@ -61,7 +66,7 @@ employee's bands further than the law does. The legal taper ([FA 2004 s. 228ZA](https://www.legislation.gov.uk/ukpga/2004/12/section/228ZA)) uses "adjusted income", which adds employer contributions, and applies only -when "threshold income" is also above £200,000 (from 2023-24). +when "threshold income" is also above £200,000 (from 2020-21). - PolicyEngine UK applies both tests (`pension_annual_allowance_adjusted_income` and @@ -70,8 +75,9 @@ when "threshold income" is also above £200,000 (from 2023-24). income of £300,000 but threshold income of £200,000, so keeps the full £60,000 allowance. Its limits: by default the pension input amount is cash contributions, so defined-benefit accrual is counted only if supplied - as an input, and all salary sacrifice is treated as made on or after - 9 July 2015. + as an input, and salary sacrifice is treated as made on or after + 9 July 2015 unless `pension_contributions_via_salary_sacrifice_pre_2015` is + supplied. - STBM tapers on total income above a threshold parameter. Both affect only very high earners. @@ -80,7 +86,10 @@ PolicyEngine UK does not model the money purchase annual allowance, the £10,000 limit on money purchase savings after pensions are first flexibly accessed ([FA 2004 s. 227ZA](https://www.legislation.gov.uk/ukpga/2004/12/section/227ZA)). -It always uses the default chargeable amount. +Its annual allowance charge is always on the default chargeable amount, +the pension input amount above the annual allowance (s. 227ZA(3)), never the +alternative chargeable amount that applies once the money purchase annual +allowance is exceeded. ### 4. Lifetime and lump sum allowances @@ -92,8 +101,9 @@ are drawn, not to contributions. ## What neither model does - Working out carry-forward of unused annual allowance from the previous - three years. PolicyEngine UK accepts the result as an input but does not - derive it from past years. + three years' actual pension input. PolicyEngine UK accepts it as an input + and otherwise estimates it from an assumed history, not from recorded past + years. - Behavioural responses: contributions are held fixed when tax rates change. - Decumulation: crystallisation, the tax-free lump sum, and annuity versus drawdown choices. From e1c615bc1f417ffe43677daea3de681e43ada2d3 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 03:13:34 -0400 Subject: [PATCH 5/6] Cover STBM's savings and dividend limits and the Enhanced FRS SPI rows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the independent review of the corrections: - calculate_pension_taxation! also raises every savings and dividend threshold (IncomeTaxCalculations.jl:140-141), including the £5,000 savings starting-rate limit and the 0% dividend band, which s. 192(4) does not; so the two methods differ for dividend and starting-rate savings income even within one band. - In the rest-of-UK systems the 40% index means only the higher rate limit (£125,140) rises for non-savings income; the FIXME comment is on the Scottish lines too, so the page no longer cites it. - The Enhanced FRS imputes employer contributions with a QRF on its SPI-based high-income records (uk-data imputations/frs_only.py). - The alternative chargeable amount applies only when it is the larger (s. 227ZA(1)(c)); fragment wording fixed. Co-Authored-By: Claude Opus 5.5 --- ...-pension-comparison-corrections.changed.md | 2 +- .../gov/hmrc/pensions-comparison-stbm.md | 26 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/changelog.d/672-stbm-pension-comparison-corrections.changed.md b/changelog.d/672-stbm-pension-comparison-corrections.changed.md index d9149e2528..8e9f317d54 100644 --- a/changelog.d/672-stbm-pension-comparison-corrections.changed.md +++ b/changelog.d/672-stbm-pension-comparison-corrections.changed.md @@ -1 +1 @@ -Corrected the STBM pension comparison page (`docs/book/programs/gov/hmrc/pensions-comparison-stbm.md`): STBM raises the basic-rate limit and every higher limit rather than widening every band, its basic amount is £10,000 in its 2023-24 to 2026-27 systems, Microcosm UK imputes employer contributions from the same ONS ASHE bands as STBM, PolicyEngine UK now estimates carry-forward of unused annual allowance from 2020-21, the threshold income test has been £200,000 since 2020-21, and pre-July 2015 salary sacrifice can be supplied. +Corrected the STBM pension comparison page (`docs/book/programs/gov/hmrc/pensions-comparison-stbm.md`): STBM raises the basic-rate limit and every limit above it for non-savings income, and every savings and dividend limit, rather than widening every band, its basic amount is £10,000 in its 2023-24 to 2026-27 systems, Microcosm UK imputes employer contributions from the same ONS ASHE table (P10) as STBM, PolicyEngine UK now estimates carry-forward of unused annual allowance from 2020-21, the threshold income test has been £200,000 since 2020-21, and salary sacrifice under arrangements made before 9 July 2015 can be supplied. diff --git a/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md index c1a7059bcf..a0ba75b83a 100644 --- a/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md +++ b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md @@ -20,28 +20,33 @@ more detail on the PolicyEngine side. | | PolicyEngine UK | STBM | |---|---|---| -| How relief is given | Reduces taxable income by the contribution (`pension_contributions_relief`) | Treats contributions as paid net of basic rate: grosses them up by 1/(1 − basic rate) and raises the basic-rate limit and every higher rate limit by the gross amount, as under relief at source | +| How relief is given | Reduces taxable income by the contribution (`pension_contributions_relief`) | Treats contributions as paid net of basic rate: grosses them up by 1/(1 − basic rate) and raises the basic-rate limit and every rate limit above it by the gross amount, as under relief at source. For savings and dividend income it raises every limit, including the starting-rate limit for savings and its 0% dividend band (the dividend allowance), which relief at source does not | | Contributions that get relief | The person's own contributions | Employee contributions, additional voluntary contributions **and employer contributions** | | Basic-rate relief added to the pot | Not shown separately | Recorded separately (`pension_relief_at_source`) | | Earnings limit | Relief capped at relevant UK earnings (employment income, employer-paid Statutory Sick Pay and Statutory Maternity Pay, and self-employment profit), or £3,600 for relief-at-source contributions if earnings are lower | No earnings cap; when total income is below a basic-amount parameter the limit is that amount (£10,000 in its 2023-24 to 2026-27 systems, £3,600 before) | | Annual allowance | £60,000 (`pension_annual_allowance`), tapered only when adjusted income is above £260,000 and threshold income is above £200,000, as in FA 2004 s. 228ZA | Tapered on total income above a threshold-income parameter | | Contributions above the allowance | Annual allowance charge on the excess, taxed as the top slice of income (`personal_pension_contributions_tax`) | Relief stops at the allowance; no separate charge | -| Employer contributions in the data | An input (`employer_pension_contributions`). Microcosm UK draws it from the ONS ASHE employer-contribution bands (Table P10); the Enhanced FRS sets it to three times employee contributions | Imputed when missing from the FRS, using the ONS ASHE employer-contribution bands (`src/Pensions.jl`) | +| Employer contributions in the data | An input (`employer_pension_contributions`). Microcosm UK draws it from the ONS ASHE employer-contribution bands (Table P10); the Enhanced FRS sets it to three times employee contributions for survey respondents and imputes it with a quantile regression forest on the high-income records whose incomes it imputes from the SPI | Imputed when missing from the FRS, using the ONS ASHE employer-contribution bands (`src/Pensions.jl`) | | Carry-forward of unused allowance | `unused_pension_annual_allowance` (FA 2004 s. 228A) adds to the allowance. As the survey data has no past pension input amounts, from 2020-21 the default estimates it from an assumed five-year history (this year's input and taper incomes deflated by average earnings growth); before 2020-21 it is nil | Not modelled | The STBM column describes its Scottish systems, its default. In its rest-of-UK systems from 2023-24, `non_savings_basic_rate` points at the 40% -rate (`params/sys_2023_24_ruk.jl` onwards, marked `FIXME`), so there the -gross-up uses 40% and only the additional-rate limit rises. +rate (`params/sys_2023_24_ruk.jl` onwards), so there the gross-up uses 40% +and, for non-savings income, only the higher rate limit (£125,140, where the +additional rate starts) rises, not the basic-rate limit. In every system all +savings and dividend limits rise. ## Where the two models differ ### 1. Reducing taxable income versus widening the bands -For an income-tax payer whose contribution stays inside one band above the -Scottish starter rate, the two methods give the same total relief. They can differ when the person pays -little or no income tax: STBM still records the basic-rate addition to the -pot, which PolicyEngine UK does not show. +For an income-tax payer with only non-savings income whose contribution +stays inside one band above the Scottish starter rate, the two methods give +the same total relief. They can differ when the person pays little or no +income tax: STBM still records the basic-rate addition to the pot, which +PolicyEngine UK does not show. They also differ for dividend income, and for +savings income in the starting-rate band, because STBM raises those 0% band +limits too. **The personal allowance taper.** In law, gross pension contributions reduce adjusted net income @@ -88,8 +93,9 @@ accessed ([FA 2004 s. 227ZA](https://www.legislation.gov.uk/ukpga/2004/12/section/227ZA)). Its annual allowance charge is always on the default chargeable amount, the pension input amount above the annual allowance (s. 227ZA(3)), never the -alternative chargeable amount that applies once the money purchase annual -allowance is exceeded. +alternative chargeable amount (s. 227B), which replaces it when the money +purchase annual allowance is exceeded and the alternative amount is the +larger (s. 227ZA(1)). ### 4. Lifetime and lump sum allowances From ea8b31ceb32342f97f4dcef443a028c2eb5b76b2 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 03:49:48 -0400 Subject: [PATCH 6/6] Limit the STBM equality claim to Scottish systems and dividends above the allowance Second-round review (STBM run in Julia and PolicyEngine UK household runs): the savings starting-rate band shrinks with taxable non-savings income in both models, so STBM's raised starting-rate limit and PolicyEngine UK's deduction free the same amount; the models differ only for dividends above the allowance. The equality holds in STBM's Scottish systems, given its rest-of-UK 40% gross-up. Co-Authored-By: Claude Opus 5.5 --- .../gov/hmrc/pensions-comparison-stbm.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md index a0ba75b83a..3eddd435fa 100644 --- a/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md +++ b/docs/book/programs/gov/hmrc/pensions-comparison-stbm.md @@ -20,7 +20,7 @@ more detail on the PolicyEngine side. | | PolicyEngine UK | STBM | |---|---|---| -| How relief is given | Reduces taxable income by the contribution (`pension_contributions_relief`) | Treats contributions as paid net of basic rate: grosses them up by 1/(1 − basic rate) and raises the basic-rate limit and every rate limit above it by the gross amount, as under relief at source. For savings and dividend income it raises every limit, including the starting-rate limit for savings and its 0% dividend band (the dividend allowance), which relief at source does not | +| How relief is given | Reduces taxable income by the contribution (`pension_contributions_relief`) | Treats contributions as paid net of basic rate: grosses them up by 1/(1 − basic rate) and raises the basic-rate limit and every rate limit above it by the gross amount, as under relief at source. For savings and dividend income it raises every limit, including the starting-rate limit for savings and the top of the 0% dividend band (the dividend allowance), neither of which relief at source raises | | Contributions that get relief | The person's own contributions | Employee contributions, additional voluntary contributions **and employer contributions** | | Basic-rate relief added to the pot | Not shown separately | Recorded separately (`pension_relief_at_source`) | | Earnings limit | Relief capped at relevant UK earnings (employment income, employer-paid Statutory Sick Pay and Statutory Maternity Pay, and self-employment profit), or £3,600 for relief-at-source contributions if earnings are lower | No earnings cap; when total income is below a basic-amount parameter the limit is that amount (£10,000 in its 2023-24 to 2026-27 systems, £3,600 before) | @@ -40,13 +40,16 @@ savings and dividend limits rise. ### 1. Reducing taxable income versus widening the bands -For an income-tax payer with only non-savings income whose contribution -stays inside one band above the Scottish starter rate, the two methods give -the same total relief. They can differ when the person pays little or no -income tax: STBM still records the basic-rate addition to the pot, which -PolicyEngine UK does not show. They also differ for dividend income, and for -savings income in the starting-rate band, because STBM raises those 0% band -limits too. +In STBM's Scottish systems, for an income-tax payer with only non-savings +income whose contribution stays inside one band above the Scottish starter +rate, the two methods give the same total relief. They can differ when the +person pays little or no income tax: STBM still records the basic-rate +addition to the pot, which PolicyEngine UK does not show. They also differ +when dividends exceed the dividend allowance, because STBM widens the 0% +dividend band by the gross contribution and PolicyEngine UK does not. +Savings income in the starting-rate band does not make them differ: that +band shrinks as taxable non-savings income rises, so PolicyEngine UK's +deduction frees as much of it as STBM's higher starting-rate limit. **The personal allowance taper.** In law, gross pension contributions reduce adjusted net income