Repository navigation
Index the income tax and NICs thresholds by September CPI after the 2030-31 freeze - #2180
Conversation
…reeze From 2031-32 the personal allowance and basic rate limit follow Income Tax Act 2007 s57(3) and s21(3) year by year: the September CPI increase, with the PA's increase rounded up to £10 and the BRL rounded up to £100. The PT, UEL, LPL and UPL stay aligned with the personal allowance and the higher rate threshold, as HMRC's Budget 2025 note and the Explanatory Memorandum to SI 2026/231 (paras 5.1, 5.15) say; the ST rises by September CPI. Before, the PA and the NICs thresholds followed calendar-year CPI and the BRL lagged calendar-year CPI, with no statutory rounding, so the higher rate threshold drifted from the UEL and UPL. Adds yoy_growth/indices.september_cpi_uprating (the same series as branch benefit-uprating-september-cpi) and create_threshold_indexation.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ds (#2179) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#2180 rewrites the Budget 2025 freeze paragraph and already drops the stale "52 x £96 = £4,992" sentence, so this branch no longer edits it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Key indexed values to 1 January, as core uprating does, so the unconverted parameters.baseline copy reads the same amount for a year as gov. Fiscal-year values are unchanged for every year 2015-2040. - Say which parts are announced policy (September CPI after 2030-31) and which are modelling assumptions (alignment with the round-ups; the ST's September CPI, unrounded, never cut), and which scenarios rebuild the values. - Test the September CPI series directly (published rounding, zero floor, index), read the BRL from its bracket, add a high-CPI case past the additional rate threshold, the realignment example, and the nested baseline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…il lag - Under a scenario's parameter_changes overriding the PA or BRL, the gov tree's NICs thresholds stay aligned with the override in every year 2031-2040 (new regression tests). - Document that stated values, overrides included, keep their dates, so the unconverted parameters.baseline copy read at 1 January lags them by a year, as it does for every April-dated parameter. - Name the Explanatory Memorandum before its paragraph numbers in the book. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Hand-off to the UK hub. Head
|
|
For the follow-up that moves the Class 2 small profits threshold onto this PR's September CPI index: #2058 merged on 2026-10-10 (cfee0e6). |
|
UK hub: landed on Max's ruling (d1062, "merge as is", 2026-10-10) at head
|
Brings in #2258 (120-minute Test job), #2180 (NICs thresholds indexed by September CPI after 2030-31), #2063 (salary sacrifice needs pay), #2038 (winter payments to the member a benefit is paid to), #2259, #2248, #2251, #2262, #2266, #2270, #2285, #2288, #2294 and #2021. Conflict: test_legacy_award_readers_properties.py imports. Kept both hypothesis.event (this branch's screened-out events) and hypothesis.example (#2294's found families). The rest of the file merged cleanly: #2294's without/silent/with-other comparison, the severe disability premium bound and the held benefit cap sit alongside this branch's work generators, screened reference and outside-member tests. Two comments now say the ESA and JSA readers also read the members' work. _legacy_award_payee.py merged cleanly: #2038's can_claim (Pension Credit) and this branch's own_report_is_paid are independent. The shared NI parameters already match main (#2058); #2180 changes only 2031-32 onward. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #2179
Summary
From 2031-32, when the Budget 2025 freeze ends, the model now indexes the income tax thresholds the way the law does, and keeps the NICs thresholds aligned with them as policy says:
Before this PR, the PA and the five NICs thresholds followed calendar-year CPI of the same year, and the BRL followed calendar-year CPI of the year before (
gov.benefit_uprating_cpi). None was rounded. The PA was indexed by the wrong CPI vintage, and the higher rate threshold and the UEL and UPL sat on different series, so they could drift apart. The freeze values through 2030-31 are unchanged.Law and policy
Change
parameters/gov/economic_assumptions/create_september_cpi_uprating.pybuildsyoy_growth.september_cpi_uprating, the April rise: September CPI of the previous year fromstatutory_uprating_inputs.cpi_september, to 0.1pp, floored at zero.create_economic_assumption_indicesturns it intoindices.september_cpi_uprating. The triple lock reads the same input. This is the series from branchbenefit-uprating-september-cpi(no PR yet), copied verbatim except for the docstring and one error message, with the same move ofround_to_published_precisionintocreate_statutory_uprating_inputs.py. When that branch rebases, it should keep this module and drop its own PA and BRLupratingedits.parameters/gov/hmrc/create_threshold_indexation.pyruns inprocess_parametersafter the indices and before the baseline clone. It writes a value for each tax year, from the year after each parameter's last stated value to the last year ofindices.september_cpi_uprating(2039), the horizon every other uprated parameter stops at. It uses exact decimal arithmetic.parameters.baselinecopy reads the same amount for a year as the fiscal-year-convertedgovtree.parameter_changes, or a modifier that resets and reprocesses (asno_economic_assumptionsdoes), rebuilds the values. So a changed CPI forecast moves all seven. Under that path, and only there, a raw edit to the PA or BRL after 2030-31 also moves the aligned NICs thresholds. In PE-UK only the benefit cap and two-child limit scenarios useparameter_changes, and policyengine.py does not.uprating:key, so core uprating cannot extend them a second time. They gain comments giving the post-freeze rule and its legal status, and references: the 2021-22 order, and the FA 2023 and FA 2026 amendments in place of the OBR EFO citation.docs/book/policy/model-baseline.md(this also corrects its stale "£4,992" secondary threshold sentence, fixed by Annualise the employer NI secondary threshold to the statutory £5,000 #2165) andparameters/gov/economic_assumptions/README.md.Invariants
Tested in
policyengine_uk/tests/test_threshold_indexation.py; property tests use Hypothesis.xfail(strict=False): the model's 2023-24 LPL is £11,908 (Class 4 lower profits limit is £11,908 in 2023-24; NICA 2022 s.2 sets £12,570 from 6 April 2023 #1968, fixed in open PR Fix Class 2 and Class 4 NICs against SSCBA 1992 for 2015-16 to 2026-27 #2058).parameters.baseline, read at 1 January, gives the same amounts asgovfor 2030-2040.no_economic_assumptions, the thresholds stay frozen through 2040.parameter_changesoverride of the PA (£15,000) or BRL (£40,000) for 2031 keeps the NICs thresholds aligned with it in every year 2031-2040.uprating:.Two old tests in
test_ni_threshold_freeze.pyasserted calendar-CPI uprating from 2031 (invariants 3 and 4). They are replaced by the tests above, and its docstring points there.Impact: Enhanced FRS, real runs
Two
Microsimulationruns, one per package state: main 6c5f01d and this branch at a29f821, both with clean tracked trees. The later commits change docs, tests, comments and the date the indexed values are keyed to. Every fiscal-year value of the seven thresholds (and the LEL) for 2015-2040 is identical before and after them; the per-year comparison is saved with the impact files. No formula reads the nested baseline for these parameters, so the run stands. The dataset is a private copy ofenhanced_frs_2024_25.h5(SHA-256 e433e532…), the file used for the other recent PE-UK impact runs. 2030-31 is the control: every total is unchanged.Thresholds (main → branch). Under the current OBR forecasts, September CPI and calendar CPI are both 2.0% a year from 2031. The threshold differences therefore come from the statutory round-ups, which compound year by year:
Change in weighted totals, branch minus main, £bn:
The impact scripts, raw outputs and the breakdown of who pays more are in the session's review folder:
dataset_impact.py,compare_impact.py,main.json,branch.jsonandlosers_breakdown.txt. Aggregates only; no record-level data.Tests run
policyengine-core test policyengine_uk/tests/policy -c policyengine_uk: 2,628 passed.pytest policyengine_uk/tests -n 8 -m "not microsimulation"at 91a0619: 3,203 passed, 4 skipped, 3 xfailed.test_threshold_indexation.pyandtest_ni_threshold_freeze.pyat 25aa584: 131 passed, 1 xfailed (Class 4 lower profits limit is £11,908 in 2023-24; NICA 2022 s.2 sets £12,570 from 6 April 2023 #1968).test_threshold_indexation.pyat eccbadd: 86 passed, 1 xfailed.ruff formatandruff checkon the changed Python files: clean.make documentation. The book does not execute notebooks (execute_notebooks: off), and the stored outputs inprograms/gov/hmrc/national-insurance.ipynbpredate many threshold changes (for example LEL £123 to 2033), so they are not regenerated here.Review
Two independent reviews (Subfleet, GPT-6.1 Sol) approved 91a0619 with minor findings only.
Every finding is addressed in 25aa584:
A delta review of 25aa584 confirmed those fixes and found:
parameter_changesoverride of the PA or BRL, the unconvertedparameters.baselinesnapshot read at 1 January shows the April-dated override a year late, beside 1 January NICs values.govstays aligned.Reply in eccbadd. The snapshot lags every April-dated stated value in the model:
So the override case is that general property, not something this PR introduced. No formula reads these seven from the snapshot. eccbadd:
govstays aligned under PA and BRL overrides;A second delta review approved eccbadd with no findings. It:
Merged locally with main at 9dd771a (which includes #2182),
test_threshold_indexation.py,test_ni_threshold_freeze.py,test_ni_secondary_threshold.pyandtest_triple_lock_properties.pygive 188 passed, 1 xfailed.Follow-ups (not in this PR)
axiom: uk:statutes/ukpga/2007/3/57 and /21 rulespec-uk#368 queued (corpus ingest pending: both citations 404 as of 2026-10-07); FA 2021 s5 freeze modules (2021/26/5, 2023/1/5, 2026/11/10) rulespec-uk#440 queued; NICs alignment after 2030-31 n/a: announced policy, not law (the SSCBA 1992 s15(3) standing figures stay correct)
🤖 Generated with Claude Code