Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
17c7381
Set Income Tax reliefs and allowances against income in the way that …
MaxGhenis Nov 1, 2026
2f5b183
Follow net income in the allocation, test s. 25(3A) and update tests …
MaxGhenis Nov 1, 2026
998486f
Allow the allocation search's tie tolerance in the dense-grid propert…
MaxGhenis Nov 1, 2026
60de330
Skip the least-tax search for people who cannot gain from another share
MaxGhenis Nov 1, 2026
3ab4884
Read the fast path's rates as the slope of the tax schedule
MaxGhenis Nov 1, 2026
16766c1
Test pay that stops at the basic rate limit with nil-rate savings abo…
MaxGhenis Nov 1, 2026
e6ba856
Expect the least-tax share in the property income band base savings case
MaxGhenis Nov 1, 2026
4522b5d
Restate the property income band base properties for the least-tax share
MaxGhenis Nov 1, 2026
e500393
Name the model as the actor in the property income band base notes
MaxGhenis Nov 1, 2026
9d8d3e0
Leave the Marriage Allowance out of the least-tax search
MaxGhenis Nov 1, 2026
ea880ff
Name Parliament as the actor in the Marriage Allowance notes
MaxGhenis Nov 1, 2026
5d9ce13
Name who acts in the allowance-order comments
MaxGhenis Nov 2, 2026
74fdacf
Filter rate identities on the allowance order
MaxGhenis Nov 2, 2026
6429896
Hold pension relief on pay and keep the UC earnings slice in the old …
claude Nov 2, 2026
def18d3
Rename the property income band base test in the shard durations
claude Nov 2, 2026
70633f0
State the relief at source law and the search's limits as run
claude Nov 2, 2026
056a674
Let the trading loss and paternity pay tests follow the least-tax share
claude Nov 2, 2026
3b54d53
Rewrap the pension relief comment in the allowance search
MaxGhenis Nov 2, 2026
6602ccc
Narrow the s. 192(4A) citation in the allocation docstring
MaxGhenis Nov 2, 2026
57c1919
Merge main into the allowance order branch
MaxGhenis Nov 6, 2026
aed86e9
Update the child benefit charge case for the least-tax share
MaxGhenis Nov 6, 2026
321fb19
Merge main at 185ac40c8, with #2828's Step 6 Marriage Allowance, into…
MaxGhenis Nov 9, 2026
6c91a3c
Weigh the Marriage Allowance in the least-tax share
MaxGhenis Nov 9, 2026
9f33c78
Merge main into the allowance order branch
MaxGhenis Nov 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/2106.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The model now sets the Personal Allowance, other allowances and trade loss relief against non-savings, savings and dividend income in the way that gives the least tax (ITA 2007 s. 25(2)), and from 2027-28 against other income before property, savings and dividend income (s. 25(3A)), where it previously always took them from non-savings income first. When it compares ways, it counts the Marriage Allowance tax reduction that each wins or loses (s. 55B(2)). Pension relief stays on non-savings income, and the income tax that Universal Credit deducts from earnings still follows the order non-savings, savings, dividends.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
description: Income Tax deducts reliefs and allowances from income other than property, savings and dividend income before it deducts them from property, savings or dividend income, and then in the way that gives the least tax.
values:
# Before 2027-28, the taxpayer deducts them under s. 25(2) alone.
0000-01-01: false
2027-04-06: true
metadata:
unit: bool
period: year
label: Reliefs and allowances deducted from other income first
reference:
- title: Income Tax Act 2007 s. 25(2) and (3A)
href: https://www.legislation.gov.uk/ukpga/2007/3/section/25
- title: Finance Act 2026 s. 6(6) and (8) (s. 25(3A) has effect from 2027-28)
href: https://www.legislation.gov.uk/ukpga/2026/11/section/6/enacted
20 changes: 20 additions & 0 deletions policyengine_uk/reforms/cps/marriage_tax_reforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,31 @@ def formula(person, period, parameters):
takes_up = person("would_claim_marriage_allowance", period)
return eligible * amount_if_eligible * takes_up

class marriage_allowance_reduction_at_stake(Variable):
value_type = float
entity = Person
label = "Marriage Allowance tax reduction at stake in the share of deductions"
documentation = (
"Nil for a person who meets the reform's expansion conditions, "
"who receives the allowance at any share of reliefs and allowances."
)
definition_period = YEAR
unit = GBP

def formula(person, period, parameters):
return where(
person("meets_expanded_ma_conditions", period),
0,
person("marriage_allowance_appropriate_percentage", period)
* person("marriage_allowance_if_income_conditions_met", period),
)

class reform(Reform):
def apply(self):
self.add_variable(meets_expanded_ma_conditions)
self.update_variable(meets_marriage_allowance_income_conditions)
self.update_variable(marriage_allowance)
self.update_variable(marriage_allowance_reduction_at_stake)

return reform

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,17 @@
# A parent aged 35 with one child, pay 40,000 and interest 30,000. Child
# Benefit 27.05 x 52 = 1,406.60 (1,406 in whole pounds). Adjusted net income
# 70,000 is half-way through the 60,000 to 80,000 taper: charge 50% x 1,406
# = 703 (ITEPA 2003 s.681C). Pay: (40,000 - 12,570) x 20% = 5,486. Interest,
# higher-rate (savings allowance 500): 500 at nil, 37,700 - 27,430 - 500 =
# 9,770 at 20% = 1,954, 30,000 - 10,270 = 19,730 at 40% = 7,892; 9,846.
# Income tax before the winter fuel payment charge: 5,486 + 9,846 + 703 =
# 16,035. Without the pay: adjusted net income 30,000, no charge; interest
# 17,430 taxable, 5,000 at the starting rate and 1,000 savings allowance at
# nil, 11,430 at 20% = 2,286. Tax deducted: 16,035 - 2,286 = 13,749, which
# includes the whole 703 charge.
# = 703 (ITEPA 2003 s.681C). The least tax sets 2,300 of the personal
# allowance against the pay and 10,270 against the interest (ITA 2007
# s.25(2)). Pay: 37,700 at 20% = 7,540. Interest, higher-rate (savings
# allowance 500): 19,730 above the basic rate limit, 500 at nil and 19,230
# at 40% = 7,692. Income tax before the winter fuel payment charge: 7,540 +
# 7,692 + 703 = 15,935. Setting the whole allowance against the pay leaves
# the 500 at nil in the basic rate band and charges 100 more. Without the
# pay: adjusted net income 30,000, no charge; interest 17,430 taxable, 5,000
# at the starting rate and 1,000 savings allowance at nil, 11,430 at 20% =
# 2,286. Tax deducted: 15,935 - 2,286 = 13,649, which includes the whole 703
# charge.
period: 2026
absolute_error_margin: 0.01
input:
Expand All @@ -130,10 +133,10 @@
region: NORTH_EAST
output:
CB_HITC: [703, 0]
income_tax_before_winter_fuel_payment_charge: [16_035, 0]
legacy_means_test_income_tax: [5_486, 0]
income_tax_before_winter_fuel_payment_charge: [15_935, 0]
legacy_means_test_income_tax: [7_540, 0]
legacy_means_test_uncounted_income_tax_without_earnings: [2_286, 0]
legacy_means_test_deducted_income_tax: [13_749, 0]
legacy_means_test_deducted_income_tax: [13_649, 0]

- name: Only the part of the High Income Child Benefit Charge that the pay adds is deducted
# A parent aged 35 with one child, pay 10,000 and interest 65,000. With the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# The Marriage Allowance tax reduction the share of reliefs and allowances can
# win or lose (ITA 2007 ss. 25(2) and 55B). 2026-27: Personal Allowance £12,570,
# so the transfer reaches 10%, £1,257, rounded up to £1,260 (s. 55B(4) and (5)),
# and the reduction 20% of that, £252.

- name: A higher-rate earner has the reduction at stake, though the rate test fails
period: 2026
absolute_error_margin: 0.01
input:
people:
earner:
age: 40
employment_income: 60_000
partner:
age: 40
benunit:
members: [earner, partner]
is_married: true
output:
marriage_allowance_if_income_conditions_met: [1_260, 0]
marriage_allowance_reduction_at_stake: [252, 0]
marriage_allowance: [0, 0]

- name: The partner's unused allowance limits the amount at stake
period: 2026
absolute_error_margin: 0.01
input:
people:
earner:
age: 40
employment_income: 30_000
partner:
age: 40
employment_income: 12_000
benunit:
members: [earner, partner]
is_married: true
output:
# The partner leaves £570 unused: 20% of it is £114.
marriage_allowance_if_income_conditions_met: [570, 0]
marriage_allowance_reduction_at_stake: [114, 0]

- name: An unmarried couple has nothing at stake
period: 2026
absolute_error_margin: 0.01
input:
people:
earner:
age: 40
employment_income: 30_000
partner:
age: 40
benunit:
members: [earner, partner]
is_married: false
output:
marriage_allowance_if_income_conditions_met: [0, 0]
marriage_allowance_reduction_at_stake: [0, 0]

- name: A person who would not claim has nothing at stake
period: 2026
absolute_error_margin: 0.01
input:
people:
earner:
age: 40
employment_income: 30_000
would_claim_marriage_allowance: false
partner:
age: 40
benunit:
members: [earner, partner]
is_married: true
output:
marriage_allowance_if_income_conditions_met: [0, 0]
marriage_allowance_reduction_at_stake: [0, 0]
Loading
Loading