Repository navigation
Conversation
DWP applies each review's percentage to the current full weekly rates of the basic and new State Pensions and rounds the results to the nearest 5p (HL10770; EMs to SI 2017/260-2020/234), and HM Treasury's forecast baseline projects them the same way (Budget 2026 policy costings, Annex A). The model instead multiplied the last published rate by the triple lock index's growth, unrounded, so the full new State Pension was £250.71 for 2027-28 against the £250.70 behind the Pension Tax Allowance explainer's £13,036.40. A generation step now fills each rate's projected years from the year before, rounded to gov.dwp.state_pension.weekly_rate_rounding (5p). The triple lock index is no longer rounded to five decimals, which put up to about 3e-6 of noise into its yearly growth. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Simulations hold float32, so 52 weeks at £250.70 comes back as £13,036.399. The tests now compare simulated incomes to half a penny, which still separates them from the unrounded rates' 57p to £1.86. The synthetic projection property builds its parameters under a node, as mark_as_modified needs a parent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Aggregate impact on certified data: passBase Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 0 (thresholds in Notes
Moves flagged for reviewNone. Receipts by tax head
Spending by benefit and service
Caseloads
Government balance, each component counted once
Model totals
Household income totals
Poverty rates
People in poverty
Inequality
Mean household net income in each side's own deciles
Standard reform costings (change in gov_balance)
Standard reforms: change in each reform's target
Household net income by decileEvery decile's mean change rounds to £0 in every year. No change in any year: population. Checks failing on both base and head (1)
Counted-once checkEach of 92 components was raised by £1 per unit in 2026-27, and every head of its totals was read household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A head that breaks a rule is measured again twice: with every other head held at its baseline value, and with every other head held at its value after the first £1 while the component rises again. It fails where either still shows the response. 0 failed; 0 were skipped.
Provenance
Dataset: Receipts by tax head: head levels
Spending by benefit and service: head levels
Caseloads: head levels
Government balance, each component counted once: head levels
Model totals: head levels
Household income totals: head levels
Population: head levels
Poverty rates: head levels
People in poverty: head levels
Inequality: head levels
Mean household net income in each side's own deciles: head levels
Standard reform costings (change in gov_balance): head levels
Standard reforms: change in each reform's target: head levels
|
A 3.9% triple lock for April 2028 takes the new State Pension to £273.675 exactly in April 2030. The model gives £273.70, and an index stored to five decimal places would give £273.65, so a new test covers both the halves-up convention and the index's precision. Another test checks that a rate a reform states for a year stays as stated. The earnings-path guarantee holds for the uprating percentages; the weekly rate then rounds to the nearest 5p, which s.150A(4) allows below the minimum (April 2019: £168.6231 became £168.60). Its test now checks the percentages and the cash chain exactly, not a 5-dp tolerance. The rounding parameter's documentation now names the reform routes that move it, and both it and the projection step say halves up is a convention: no published rate has landed on a half. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
£273.675 is 5,473.5 units of 5p, which both rules round up, so the tie test also checks £273.725 (5,474.5 units), which halves up takes to £273.75 and halves to even would take down. The rounding parameter's documentation now names only the reforms checked to move it: whole fiscal years set through a reform dictionary or parameter changes. General uprating on main sat within a third of a penny of the unrounded chain through 2039, not 0.1p. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main added add_energy_price_indices after create_economic_assumption_indices. Both steps now run, in main's order, with project_state_pension_rates after the energy price indices and before the Pension Credit projection. Neither step reads what the other generates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The full new State Pension for 2027-28 is now 250.70 a week, so the allowance's threshold is 13,036.40, HM Treasury's explainer figure. Jonathan and the Scottish taper case get 44, the taper ends at 13,318.40, and in 2028-29 the threshold is 13,478.40 (259.20 a week), so the full allowance is 182. The variable's documentation drops the unrounded 13,036.97. This applies the patch in #2719's comment 6503688653, with the documentation hunk's context moved to step_6_tax_reductions, as main now names it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Invariant 3 of test_dwp_published_rates expected the unrounded product of the 2026-27 rate and the triple lock index's growth, so it failed for both State Pension rates on this branch's CI. Those two rates now round to the nearest gov.dwp.state_pension.weekly_rate_rounding, as each Up-rating Order rounds them: 241.30 x 1.039 = 250.7107 gives 250.70, and 184.90 x 1.039 = 192.1111 gives 192.10. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With #2719 the Pension Tax Allowance applies from 2027-28, so the full new State Pension's 13,036.40 bears 93.28 of tax at Step 5 (20% x 466.40), the explainer's figure for Steph without the allowance, and the allowance then removes all of it: income_tax is 0. The test asserted 93.28 of income_tax. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With #2719 on main, the allowance's threshold is 52 weeks of the full new State Pension, so it moves to 13,036.40 in 2027-28, and the full allowance for 2028-29 falls from 183 to 182. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The uprating section said later years are uprated by the triple lock index. create_rate_projection now raises each April's rate from the year before by that index's growth and rounds it to the nearest 5p, as the Up-rating Orders round the full rates (Explanatory Memorandum to SI 2020/234, paragraph 7.17). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
The model now rounds projected State Pension weekly rates as DWP rounds them in each Up-rating Order. Each April, the model takes the previous year's full new and basic State Pension rates, raises them by that April's triple lock rate, and rounds each to the nearest 5p. Published rates (to April 2026) stay unchanged.
On the October 2026 forecast, the full new State Pension becomes £250.70, £259.20 and £265.70 a week for 2027-28 to 2029-30 (was £250.71, £259.24 and £265.72). The basic State Pension becomes £192.10, £198.65 and £203.60 (was £192.11, £198.64 and £203.61). 52 weeks at £250.70 give the £13,036.40 that HM Treasury's Pension Tax Allowance explainer uses. #2719's Pension Tax Allowance, now on main, takes its threshold from this rate, so the threshold moves to that figure.
Reproducer: policyengine_uk/tests/test_state_pension_rate_rounding.py::test_april_2027_is_the_pension_tax_allowance_explainer_figure
The rule and its sources
test_triple_lock_outturn.py). Always rounding up or always down to 5p, or rounding to the nearest 10p, each misses five or more of those years. Over 2003–2026 nearest 5p gets 44 of 45 published rates. The one miss, April 2003, followed a £100-a-year cash pledge.Each year starts from the previous year's rounded rate: £250.70 × 1.034 = £259.2238 gives £259.20 for April 2028, where rounding the unrounded path (£259.2357) would give £259.25.
How
create_rate_projection.project_state_pension_rates, runs after the economic assumption indices and main's household energy price indices, and before the Pension Credit projection. Neither it nor the energy price step reads what the other generates. For each rate it fills the years after the last stated value, through the last year of the rate's uprating index. The step multiplies the previous year's value by the index's growth over the year and rounds the product to the nearest multiple ofgov.dwp.state_pension.weekly_rate_rounding(0.05) inDecimal. No published rate has landed on a half, so the sources leave ties open; the model rounds halves up. The baseline copy, prior law's projected path for dated reforms and the fiscal-year annualisation all see the rounded rates. General uprating then has no year left to fill.upratingmetadata. So a reform to the triple lock rate, its inputs or the index moves the projection, and so does a reform to the rounding parameter, set for whole fiscal years (a single value, a year key or a date range covering 30 April) through a reform dict orScenario(parameter_changes=...). The step reads each April's rounding on 30 April. Setting the rounding to 0 gives the unrounded chain. A rate a reform states for a year stays as stated, and the years after follow prior law's rounded path, as dated reforms fill gaps.create_economic_assumption_indicesno longer rounds the triple lock index to 5 decimal places, and it already leaves the earnings uprating index unrounded. Rounding it added up to about 3e-6 to the index's yearly growth, enough to tip a rate to the other 5p.new_state_pensionandbasic_state_pensionpay a share of the full rate, so a partial award rises by the rounded full rate's percentage. The model's additional State Pension follows September CPI and does not change.Invariants (all tested)
For both rates:
project_weekly_rateon any synthetic path equals the chained rule;Existing tests in
test_process_time_reforms.pyandtest_triple_lock_statutory_inputs.pyused to accept the unrounded product (abs=0.006). They now check the nearest-5p chain exactly.test_dwp_published_rates.pychecks that each 2027-28 rate continues from the published 2026-27 rate. It expected the unrounded product for both State Pension rates and failed on c7b2972 (250.70 against 250.7107). It now rounds that product to the nearest 5p: 241.30 × 1.039 = 250.7107 gives £250.70, and 184.90 × 1.039 = 192.1111 gives £192.10.Impact
CI aggregate impact (certified Enhanced FRS 2024-25, main vs this branch)
At b5de2c7, against main at 2da212a (with #2719), the Aggregate impact check passed and flagged no move. On the certified Enhanced FRS 2024-25:
Before #2719 (c7b2972 against daec84d), income tax fell by £1.0m, £1.5m and £1.4m. The gap, £0.8m in 2028-29 and £0.2m in 2029-30, comes close to the fall in the Pension Tax Allowance's cost in the in-engine run below (£0.9m and £0.2m).
Pension Tax Allowance under #2719 (in-engine), certified Enhanced FRS 2024-25
This ran #2719's head (c086c49) against #2719 merged with this branch (local merge). Weighted figures, from
Microsimulationon the certified dataset (1.58.1, sha256 056e80fd…). #2719 took in more of main (#2545's Step 6 limit and #2723's savings income path among them) before it landed at head 60a92b4, so the figures at the merged state can differ from these.In this dataset every record on the full new State Pension also has some additional State Pension (most often £43 to £46 a year), so nobody sits exactly at the threshold, before or after. The change in 2028-29 comes from the full allowance: 20% × (£13,478.40 − £12,570) = £181.68 rounds up to £182, where the unrounded £182.05 rounded up to £183.
Pension Tax Allowance on the Budget dashboard's basis
This used the dashboard's microsimulation build (pe-uk 2.151.0 with this change overlaid, OBR October 2026 forecast) against the run behind the Neidle 53% note. The dashboard already set the threshold from the rate rounded to 5p, so only incomes move.
Before, people whose only income was the full new State Pension sat 57p, £1.86 and 90p above the threshold. In 2028-29 that left about 174,000 of them on the taper, paying about 67p each. Now they sit at the threshold: their allowance covers all their tax. The 2028-29 count of people on the taper still paying tax falls from 557,000 to 387,000, close to the 384,000 an earlier analysis got by setting that group aside.
Interaction with #2719
#2719 landed on main first, so this branch merges main (2da212a) and takes the patch from the comment on #2719. At £250.70 a week, 52 weeks give a 2027-28 threshold of £13,036.40, and the model rounds the full allowance, 20% × £466.40 = £93.28, up to £94. Five of the 15 cases in
tests/policy/reforms/oct_2026_budget/pension_tax_allowance.yamltake new expectations:The variable's documentation now gives the explainer's £13,036.40 for 2027-28, where it gave the unrounded £13,036.97. With the allowance in force from 2027-28,
test_state_pension_rate_rounding.pychecks the explainer's £93.28 as Steph's Step 5 tax and as her allowance, and her income tax at £0. It used to assert £93.28 of income tax.Tests
Each file ran on its own, without survey data, on the model and test code of b5de2c7: the commits after c69f9af change only the changelog fragment and the State Pension docs page.
test_state_pension_rate_rounding.py: 34 passed, in three partstest_triple_lock_outturn.py: 42 passedtests/policy/reforms/oct_2026_budget/pension_tax_allowance.yaml: 15 passedtest_income_tax_step_6_step_7_properties.py: 10 passedtest_dwp_published_rates.py: 1,297 passed, 60 skippedtest_carers_allowance_earnings_taper.py,test_council_tax_reduction_pension_credit_properties.py,test_pension_tax_allowance_properties.pyandtest_process_time_reforms.py) passed every test they reached before the 25-minute local limit.CI at b5de2c7 passes every check, among them the YAML suite, all six Python shards, the documentation build and Aggregate impact.
Axiom
axiom: n/a: a forecast convention for rates no Order has set yet. s.150A(4) leaves the rounding to the Secretary of State, and the queued s.150A issue, TheAxiomFoundation/rulespec-uk#366, excludes any rounding convention for that reason.
🤖 Generated with Claude Code