Skip to content

Index the income tax and NICs thresholds by September CPI after the 2030-31 freeze - #2180

Merged
MaxGhenis merged 4 commits into
mainfrom
tax-ni-thresholds-september-cpi
Oct 10, 2026
Merged

MaxGhenis merged 4 commits into
mainfrom
tax-ni-thresholds-september-cpi

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

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:

  • The personal allowance (PA) and basic rate limit (BRL) rise by the previous September's CPI under Income Tax Act 2007 s57(3) and s21(3), year by year from the previous year's rounded amount. The PA's increase is rounded up to a multiple of £10, and the BRL is rounded up to a multiple of £100. There is no change when September CPI did not rise (ss57(2), 21(1)).
  • The lower profits limit equals the PA. The upper profits limit equals the higher rate threshold (PA + BRL). The primary threshold and upper earnings limit equal those annual amounts over 52, to the penny, the convention already used for £241.73 and £966.73.
  • The secondary threshold rises by the same September CPI increase.

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

  • Income tax. ITA 2007 s57(2)-(3) and s21(1), (3). Finance Act 2021 s5, as amended by Finance Act 2023 s5 and Finance Act 2026 s10, fixes the BRL at £37,700 and the PA at £12,570 and disapplies ss21 and 57 for 2022-23 to 2030-31. The rule reproduces the last year it ran: the Income Tax (Indexation) Order 2021 (SI 2021/111) arts 2 and 3(a) took £12,500 and £37,500 to £12,570 and £37,700 on September 2020 CPI of 0.5%. A rise of £62.50 rounds up to £70, and £37,687.50 rounds up to £37,700.
  • NICs. No statute indexes the thresholds: SSCBA 1992 s5 needs Class 1 amounts specified each year, and s15(3)'s Class 4 figures change only by order after the SSAA 1992 s141 review. What is announced policy and what is a modelling assumption:
    • Announced. The Explanatory Memorandum to SI 2026/231 para 5.1 says the PA, HRT, UEL, UPL, PT and LPL will be "uprated by the September Consumer Prices Index (CPI)" after 2030-31.
    • Announced, for the frozen years. HMRC's Budget 2025 policy paper says the PT and LPL "will remain aligned with the Personal Allowance" and the UEL and UPL stay "aligned to the higher rate threshold" for those years. EM para 5.14 says the UEL has been aligned with the HRT since April 2009, and para 5.15 that for 2026-27 it "will remain at a level equivalent to the annual HRT".
    • Modelling assumption. The alignment continues after 2030-31 with the income tax round-ups included. That is consistent with the announced policy, but nothing says the NICs thresholds will take the round-ups.
    • Modelling assumption. For the ST, the Autumn Budget 2024 policy paper says only that after its freeze it "will be increased in line with Consumer Prices Index (CPI)". The September CPI basis, no rounding and no cut are assumptions. The YAML comments say so.

Change

  • parameters/gov/economic_assumptions/create_september_cpi_uprating.py builds yoy_growth.september_cpi_uprating, the April rise: September CPI of the previous year from statutory_uprating_inputs.cpi_september, to 0.1pp, floored at zero. create_economic_assumption_indices turns it into indices.september_cpi_uprating. The triple lock reads the same input. This is the series from branch benefit-uprating-september-cpi (no PR yet), copied verbatim except for the docstring and one error message, with the same move of round_to_published_precision into create_statutory_uprating_inputs.py. When that branch rebases, it should keep this module and drop its own PA and BRL uprating edits.
  • The new parameters/gov/hmrc/create_threshold_indexation.py runs in process_parameters after 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 of indices.september_cpi_uprating (2039), the horizon every other uprated parameter stops at. It uses exact decimal arithmetic.
    • Keys. Values are keyed to 1 January, as core uprating keys its values. So the unconverted parameters.baseline copy reads the same amount for a year as the fiscal-year-converted gov tree.
    • Reforms. A reform passed as a dict, the usual path, edits the processed tree, so changing one of these parameters does not move the others, as with core uprating.
    • Scenarios. A scenario's parameter_changes, or a modifier that resets and reprocesses (as no_economic_assumptions does), 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 use parameter_changes, and policyengine.py does not.
  • The seven parameter files lose their 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: 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) and parameters/gov/economic_assumptions/README.md.

Invariants

Tested in policyengine_uk/tests/test_threshold_indexation.py; property tests use Hypothesis.

  1. Statutory steps. For any previous amount and any September CPI increase g:
    • the PA rises by the smallest multiple of £10 at or above PA × g;
    • the BRL becomes the smallest multiple of £100 at or above BRL × (1 + g);
    • neither changes when g ≤ 0;
    • both never fall, and are non-decreasing in g and in the previous amount;
    • both agree with an independent exact-rational transcription of the statute (differential).
  2. Outturn. The steps reproduce the 2021-22 amounts in SI 2021/111 from the model's own September 2020 CPI.
  3. Freeze. PA £12,570 and BRL £37,700 in every year 2022-2030.
  4. Reference path. In 2031-2039, the model's PA and BRL equal the statute applied year by year, in exact rationals, to the model's September CPI input. 2040 holds 2039.
  5. Alignment, every year 2021-2040. UPL = PA + BRL, and 52 × UEL is within £0.26 (52 half-pennies) of the UPL. From 2023: LPL = PA, and 52 × PT is within £0.26 of the LPL. Intended exceptions, as the law stood:
  6. Secondary threshold. From 2031, ST(Y) = ST(Y-1) × (1 + g_Y).
  7. Function level, for any freeze end and CPI path (synthetic parameter tree, 60 Hypothesis examples):
    • stated values are unchanged;
    • after each NICs threshold's last stated year it equals its income tax equivalent;
    • the PA, BRL and ST never fall, and an aligned NICs threshold never falls after its first indexed year. That first year can fall by intent: a NICs amount stated above its income tax equivalent realigns. An explicit test covers it;
    • running the step twice changes nothing;
    • the nested parameters.baseline, read at 1 January, gives the same amounts as gov for 2030-2040.
  8. Scenarios.
    • With September 2030 CPI at 5%, the PA becomes £13,200 (£628.50 rounds up to £630), the BRL £39,600, the LPL £13,200 and the UPL £52,800.
    • With a fall in September CPI, nothing changes.
    • Under no_economic_assumptions, the thresholds stay frozen through 2040.
    • A scenario's parameter_changes override of the PA (£15,000) or BRL (£40,000) for 2031 keeps the NICs thresholds aligned with it in every year 2031-2040.
    • With September CPI at 14.2% a year for 2030-2038, the BRL passes the fixed £125,140 additional rate threshold by 2039 and still follows s21(3). Tests read the BRL from its bracket, because a scale read at an instant sorts its thresholds.
  9. No double indexing. None of the seven files carries uprating:.
  10. The September CPI series. Each April's rise is the previous September's CPI to 0.1 percentage points (halves up), and zero unless positive, for any input (Hypothesis). The model's series and index follow its input for 2011-2039.

Two old tests in test_ni_threshold_freeze.py asserted 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 Microsimulation runs, 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 of enhanced_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:

Year Personal allowance Basic rate limit Higher rate threshold = UPL 52 × UEL 52 × PT 52 × ST
2030-31 12,570.00 37,700.00 50,270.00 50,269.96 12,569.96 5,000.00
2031-32 12,821.41 → 12,830.00 38,454.01 → 38,500.00 51,275.42 → 51,330.00 51,275.39 → 51,330.24 12,821.37 → 12,829.96 5,100.00
2032-33 13,077.82 → 13,090.00 39,223.12 → 39,300.00 52,300.94 → 52,390.00 52,300.84 → 52,390.00 13,077.78 → 13,089.96 5,202.00
2033-34 13,339.38 → 13,360.00 40,007.53 → 40,100.00 53,346.91 → 53,460.00 53,346.86 → 53,460.16 13,339.34 → 13,359.84 5,306.04
2034-35 13,606.15 → 13,630.00 40,807.69 → 41,000.00 54,413.84 → 54,630.00 54,413.74 → 54,630.16 13,606.11 → 13,630.24 5,412.15 → 5,412.16
2035-36 13,878.28 → 13,910.00 41,623.80 → 41,900.00 55,502.08 → 55,810.00 55,502.05 → 55,810.04 13,878.24 → 13,910.00 5,520.40

Change in weighted totals, branch minus main, £bn:

Year Income tax Class 1 employee NI Class 1 employer NI Class 4 NI Universal Credit Pension Credit Housing Benefit Council Tax Reduction Household net income
2030-31 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000
2031-32 −0.173 +0.007 +0.000 −0.001 −0.003 −0.001 −0.000 −0.000 +0.162
2032-33 −0.286 +0.016 −0.000 −0.000 −0.005 −0.002 −0.000 −0.000 +0.264
2033-34 −0.412 +0.012 −0.000 −0.001 −0.008 −0.004 −0.001 −0.000 +0.390
2034-35 −0.674 +0.063 −0.000 −0.000 −0.010 −0.004 −0.000 −0.000 +0.597
2035-36 −0.961 +0.102 −0.000 +0.001 −0.013 −0.005 −0.001 −0.000 +0.842
  • Income tax falls because the PA and the higher rate threshold are higher. Employee NI rises slightly: the UEL rises with the higher rate threshold, so more earnings pay the 8% main rate rather than 2%, and that outweighs the small rise in the PT.
  • About 25 million households gain in each year, by £5 a year on average in 2031-32, rising to £26 in 2035-36. Every decile gains, and the top deciles gain most.
  • 0.64m–1.48m people pay more income tax plus NI, by £1–£6 a year on average and at most £16. In 2031-32 to 2033-34, 81%–91% of them are taxpayers outside Scotland whose NI earnings exceed the raised UEL but whose income tax is within the basic rate band. They gain only from the PA's rise (20% of it), which is less than the extra 6% main-rate NI on earnings up to the raised UEL. By 2034-35 about half are Scottish taxpayers, whose higher rate threshold this change does not move.
  • Poverty rates move by under 0.01 percentage points.

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.json and losers_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.py and test_ni_threshold_freeze.py at 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.py at eccbadd: 86 passed, 1 xfailed.
  • ruff format and ruff check on the changed Python files: clean.
  • Not run: make documentation. The book does not execute notebooks (execute_notebooks: off), and the stored outputs in programs/gov/hmrc/national-insurance.ipynb predate 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.

  • Law, code and docs. The reviewer read the statutes and the processing pipeline and checked the 2021 outturn and the multi-year path by execution.
  • Mutation, invariants and impact. 15 of 15 requested mutants killed. All 54 total cells, the 2030 control and the provenance re-verified from the saved run files.

Every finding is addressed in 25aa584:

  • the nested-baseline key (1 January);
  • policy versus assumption wording;
  • which scenarios rebuild the values;
  • the freeze-test docstring;
  • direct tests for the series' rounding and zero floor, which killed the two extra mutants that had survived;
  • the realignment example;
  • the BRL test accessor.

A delta review of 25aa584 confirmed those fixes and found:

  • Minor. Under a parameter_changes override of the PA or BRL, the unconverted parameters.baseline snapshot read at 1 January shows the April-dated override a year late, beside 1 January NICs values. gov stays aligned.
  • Nit. A citation needed naming.

Reply in eccbadd. The snapshot lags every April-dated stated value in the model:

  • PA 2021: £12,500 vs £12,570;
  • LEL 2026: £125 vs £129;
  • Child Benefit 2026: £26.05 vs £27.05.

So the override case is that general property, not something this PR introduced. No formula reads these seven from the snapshot. eccbadd:

  • adds regression tests that gov stays aligned under PA and BRL overrides;
  • documents the snapshot's lag;
  • fixes the citation.

A second delta review approved eccbadd with no findings. It:

  • reproduced the lag examples;
  • confirmed the new override tests fail under a mutant and pass when restored;
  • re-ran the 77 nested-baseline comparisons.

Merged locally with main at 9dd771a (which includes #2182), test_threshold_indexation.py, test_ni_threshold_freeze.py, test_ni_secondary_threshold.py and test_triple_lock_properties.py give 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

MaxGhenis and others added 2 commits October 7, 2026 12:18
…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>
MaxGhenis and others added 2 commits October 7, 2026 15:22
- 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>
@MaxGhenis

MaxGhenis commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator Author

Hand-off to the UK hub. Head eccbadd8935c62a50db088f8e9b6f73c9b4a2cc7.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

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). class_2/small_profits_threshold.yaml now has uprating: gov.economic_assumptions.indices.obr.consumer_price_index in the one-line form with no start_instant, and statutory values to 2026-04-06 (£7,105), so the follow-up only has to swap the index on that line. #2058 changed no other uprating: line; the Class 2 flat rate has none.

@MaxGhenis
MaxGhenis merged commit 4857dc7 into main Oct 10, 2026
7 checks passed
@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

UK hub: landed on Max's ruling (d1062, "merge as is", 2026-10-10) at head eccbadd8935c62a50db088f8e9b6f73c9b4a2cc7.

@MaxGhenis
MaxGhenis deleted the tax-ni-thresholds-september-cpi branch October 10, 2026 21:26
MaxGhenis added a commit that referenced this pull request Oct 11, 2026
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>
MaxGhenis added a commit that referenced this pull request Oct 11, 2026
…2259, #2262, #2285) into benefit-cap-75f-claimant-partner

The payee helper takes both main's can_claim (Pension Credit) and this
branch's couple (the benefit cap's couple).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Income tax and NICs thresholds use mismatched CPI series and no statutory rounding after the 2030-31 freeze

1 participant