Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/2321.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Round the High Income Child Benefit Charge as ITEPA 2003 s. 681C(3) requires: the percentage down to a whole number, and the Child Benefit and the charge down to whole pounds.
14 changes: 9 additions & 5 deletions policyengine_uk/parameters/gov/hmrc/child_benefit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ data in a release; updating model code alone does not repair existing data.

`gov.hmrc.child_benefit.opt_out_charge_share` is a behavioural assumption, not
a statutory eligibility rule. It defaults to one: a flagged family continues
to opt out only while the charge would recover the full benefit. The charge
share is calculated independently of payment and clipped to [0, 1]. A reform
that reduces the share below the threshold, removes the charge or neutralises
`CB_HITC` restores payment. A zero charge never sustains an opt-out, even if
the assumed threshold is zero. Genuine nonclaimants remain outside payment.
to opt out only while the continuous charge share is one, that is while the
higher adjusted net income in the family is at or above the end of the
phase-out band. The share is the unrounded fraction of the band crossed, calculated independently of
payment and clipped to [0, 1]. A reform that reduces the share below the
threshold, removes the charge or neutralises `CB_HITC` restores payment. A zero
continuous charge share never sustains an opt-out, even if the assumed
threshold is zero. The statutory charge (`CB_HITC`) is different: ITEPA 2003
s. 681C(3) rounds its percentage and amount down, so it can be nil while the
share is small but positive. Genuine nonclaimants remain outside payment.

Microcosm selects fully charged families first and can draw from partly charged
families if needed to meet its target. The model's default threshold is an
Expand Down
12 changes: 9 additions & 3 deletions policyengine_uk/reforms/conservatives/household_based_hitc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from policyengine_uk.model_api import *
from policyengine_uk.utils.child_benefit import (
child_benefit_charge_percentage,
round_down_to_pounds,
)


class CB_HITC(Variable):
Expand All @@ -15,10 +19,12 @@ def formula(person, period, parameters):
hitc = parameters(period).gov.hmrc.income_tax.charges.CB_HITC
personal_income = person("adjusted_net_income", period)
income = person.benunit.sum(personal_income)
percentage = max_(income - hitc.phase_out_start, 0) / (
hitc.phase_out_end - hitc.phase_out_start
# The same s. 681C(3) rounding as the baseline charge, on the
# household's combined income.
percentage = child_benefit_charge_percentage(
income, hitc.phase_out_start, hitc.phase_out_end
)
return min_(percentage, 1) * CB_received
return round_down_to_pounds(percentage * round_down_to_pounds(CB_received))


class make_cb_hitc_household_based(Variable):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,10 @@
household:
members: [parent, child]
output:
# Child Benefit 27.05 x 52 = 1,406.60; the charge takes
# (70,000 - 60,000) / 200 = 50% of it, 703.30.
CB_HITC: [703.30, 0]
income_tax: [16_135.30, 0]
# Child Benefit 27.05 x 52 = 1,406.60, rounded down to £1,406; the charge
# takes (70,000 - 60,000) / 200 = 50% of it, £703 (s. 681C(3)).
CB_HITC: [703, 0]
income_tax: [16_135, 0]
# 37,700 x 20% + (57,430 - 37,700) x 40%.
uc_income_tax_on_earnings: [15_432, 0]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
absolute_error_margin: 0.01
input:
people:
person1: {age: 40, adjusted_net_income: 100_000}
person1: {age: 40, adjusted_net_income: 200_000}
person2: {age: 8}
person3: {age: 5}
benunits:
Expand All @@ -98,8 +98,9 @@
output:
child_benefit_entitlement: 2_337.40
child_benefit: 2_337.40
# (100,000 - 60,000) / (10,000,000 - 60,000) * 2,337.40.
CB_HITC: [9.406036, 0, 0]
# (200,000 - 60,000) / (10,000,000 - 60,000) = 1.41%, rounded down to 1%
# (ITEPA 2003 s. 681C(3)); 1% of £2,337 is £23.37, rounded down to £23.
CB_HITC: [23, 0, 0]

- name: Case 9, the configurable opt-out threshold includes its exact boundary.
period: 2026
Expand All @@ -111,9 +112,10 @@
gov.hmrc.child_benefit.opt_out_charge_share: 0.5
output:
child_benefit: [1_000, 0, 0]
CB_HITC: [499.95, 0, 0]
# 49.995% is rounded down to 49% (s. 681C(3)): £490.
CB_HITC: [490, 0, 0]

- name: Case 10, a zero behavioural threshold still requires a positive charge.
- name: Case 10, a zero behavioural threshold still requires a positive continuous charge share.
period: 2026
input:
adjusted_net_income: [59_999, 60_000, 60_001]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,150 @@
members: [person1, person2, person3, person4]
output:
child_benefit: 2_337.40
CB_HITC: [2_337.40, 0, 0, 0]
# s. 681C(3): the Child Benefit total is rounded down to £2,337.
CB_HITC: [2_337, 0, 0, 0]
income_tax_pre_charges: [35_742, 4_486, 0, 0]
income_tax: [38_079.40, 4_486, 0, 0]
income_tax: [38_079, 4_486, 0, 0]

# ITEPA 2003 s. 681C(3): the Child Benefit total and the charge are rounded
# down to whole pounds, and the appropriate percentage ((ANI - £60,000) / £200
# from 2024-25) to a whole number.
- name: Case 6, the percentage, the Child Benefit and the charge are rounded down.
period: 2026
absolute_error_margin: 0
input:
people:
parent:
age: 40
employment_income: 71_336
child:
age: 5
benunit:
members: [parent, child]
output:
# (71,336 - 60,000) / 200 = 56.68, so 56%; £1,406.60 becomes £1,406;
# 56% of £1,406 is £787.36, so £787.
child_benefit: 1_406.60
CB_HITC: [787, 0]

- name: Case 7, a whole-number percentage is not rounded below itself.
period: 2026
absolute_error_margin: 0
input:
people:
parent:
age: 40
employment_income: 70_000
child:
age: 5
benunit:
members: [parent, child]
output:
# (70,000 - 60,000) / 200 = 50%; 50% of £1,406 is £703.
CB_HITC: [703, 0]

- name: Case 8, just under the next £200 step keeps the lower percentage.
period: 2026
absolute_error_margin: 0
input:
people:
parent:
age: 40
employment_income: 70_199
child:
age: 5
benunit:
members: [parent, child]
output:
# 50.995% rounds down to 50%: £703.
CB_HITC: [703, 0]

- name: Case 9, at or above £80,000 the whole Child Benefit, in whole pounds.
period: 2026
absolute_error_margin: 0
input:
people:
parent:
age: 40
employment_income: 90_000
child1:
age: 5
child2:
age: 3
benunit:
members: [parent, child1, child2]
output:
child_benefit: 2_337.40
CB_HITC: [2_337, 0, 0]

- name: Case 10, the 2023-24 rules, 1% per £100 above £50,000.
period: 2023
absolute_error_margin: 0
input:
people:
parent:
age: 40
employment_income: 55_550
child:
age: 5
benunit:
members: [parent, child]
child_benefit: 1_000
output:
# (55,550 - 50,000) / 100 = 55.5%, so 55%; 55% of £1,000 is £550.
CB_HITC: [550, 0]

- name: Case 11, the Child Benefit total is rounded down before the percentage applies.
period: 2026
absolute_error_margin: 0
input:
people:
parent:
age: 40
employment_income: 79_800
child:
age: 5
benunit:
members: [parent, child]
output:
# (79,800 - 60,000) / 200 = 99%; 99% of £1,406 is £1,391.94, so £1,391.
# Rounding only the charge (99% of £1,406.60 = £1,392.53) would give £1,392.
CB_HITC: [1_391, 0]

- name: Case 12, an income on an exact £200 step gets that many points.
period: 2026
absolute_error_margin: 0
input:
people:
parent:
age: 40
employment_income: 60_200
child:
age: 5
benunit:
members: [parent, child]
output:
# 1% of £1,406 is £14.06, so £14.
CB_HITC: [14, 0]

- name: Case 13, four children's £4,199 is not rounded down to £4,198.
period: 2026
absolute_error_margin: 0
input:
people:
parent:
age: 40
employment_income: 90_000
child1:
age: 2
child2:
age: 4
child3:
age: 6
child4:
age: 8
benunit:
members: [parent, child1, child2, child3, child4]
output:
# 52 x (27.05 + 3 x 17.90) = 4,199.
CB_HITC: [4_199, 0, 0, 0, 0]
Loading
Loading