Charge Class 4 NI on full trading profits, without deducting Class 1 - #1886
Merged
Merged
Conversation
SSCBA 1992 Sch 2 para 2 charges Class 4 on the full amount of trading profits; the para 3 reliefs do not include Class 1 contributions. The interaction with Class 1 is handled by the regulation 100 annual maximum. Fixes #1885 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ni_class_4 is total Class 4, not main-rate Class 4, so give it its own label and a section 15 reference. The docs do not execute notebooks, so regenerate the Class table output to match its source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1885
What was wrong
ni_class_4andni_class_4_maincomputed Class 4 profits asself_employment_income - ni_class_1_employee. Trading profits were reduced by the person's employee Class 1 NI before the Lower and Upper Profits Limits applied.The law has no such deduction. SSCBA 1992 Sch 2 para 2 charges Class 4 on "the full amount of all profits" chargeable under ITTOIA 2005 Part 2 Ch 2. The only reliefs are those in para 3: trade losses under ITA 2007 ss.64, 72, 83 and 89, and the interest and annual payments in para 3(5). Class 1 contributions are not among them. The Class 1 / Class 4 interaction is handled solely by the regulation 100 annual maximum. The model already implements that in
ni_class_4_maximum, and its Steps Six and Nine already used undeducted profits. The deduction arrived with a 2021 validation commit (66b6dce) with no comment or reference. The only Class-1-related exclusion in law is reg 94 of the 2001 Regulations (NIM24620). It removes earnings that bear Class 1 but are taxed as trading income, on application; it does not remove Class 1 contributions. It can't arise here, becauseemployment_incomeandself_employment_incomeare separate inputs.Example (2026-27): employment £30,000 and profits £20,000. The statute gives 6% × (20,000 − 12,570) = £445.80, and the annual maximum does not bind. The model returned about £362.
Changes
ni_class_4,ni_class_4_main: Class 4 profits areself_employment_income.ni_class_4_maximum: the Case 1 unused-band test (from Fix Class 4 NI dropping the additional-rate band at non-round thresholds #1884) uses the same profits.ni_class_4gets its own label ("NI Class 4 contributions", previously a copy ofni_class_4_main's) and a s.15 reference.Invariants
These hold for any 0 ≤ LPL < UPL, rates ≥ 0 and profits ≥ 0. Comparisons allow float32 storage: 1p + 4×10⁻⁷ × the largest amount involved.
ni_class_4 = main × clamp(p − LPL, 0, UPL − LPL) + additional × max(p − UPL, 0), withpthe full self-employment profit.ni_class_4equals an exact-rational implementation of s.15(3) capped by the literal reg 100 steps.0 ≤ ni_class_4 ≤the s.15(3) amount.ni_class_4is non-decreasing in profits wherever Class 2 does not change. Before April 2024, reg 100 subtracts Class 2, so crossing the small profits threshold can lower Class 4; Class 2 + Class 4 stays non-decreasing when main ≥ additional.Verification
Self-employment × employment grid: 1,732 profit levels (£0–£300k) × 152 employment incomes (£0–£150k), 263,264 cells per year. Base is #1884's merged code (2.102.1), head is this PR.
In every year, each cell where the maximum does not bind equals the closed-form statute on full profits. Cells where the maximum binds, which is most dual earners with profits well above the LPL, are unchanged. 2023 is larger because of that year's 9% main rate.
Aggregate revenue effect on the FRS-based microsimulation: not computed locally, since the dataset needs credentials. CI's microsimulation tests run on it.
Axiom parity
axiom: uk:statutes/ukpga/1992/4/15 encoded-correct (TheAxiomFoundation/rulespec-uk
uk/statutes/ukpga/1992/4/15.yamlchargesprofits_chargeable_to_class_4_contributionswith no Class 1 deduction; companion test15.test.yaml::class_4_main_and_additional_contributions_apply)The Axiom-vs-policyengine-uk NICs grid in TheAxiomFoundation/axiom-oracles#565 attributes 4 dual-earner rows to #1885.
Independent review
Claude Opus 5.5 via Subfleet (read-only) returned APPROVE with nothing blocking:
Its notes are addressed in this PR: the stale saved notebook output, the monotonicity caveat, the Axiom repo path, the reg 94 note and the duplicated
ni_class_4label.Commands run
ruff format .andruff check .pytest policyengine_uk/tests/test_ni_class_4_maximum.py policyengine_uk/tests/test_ni_class_4_properties.py policyengine_uk/tests/test_parameter_descriptions.py(16 passed)policyengine-core test policyengine_uk/tests/policy/baseline/gov/hmrc/national_insurance -c policyengine_uk(38 passed)🤖 Generated with Claude Code