Skip to content

The High Income Child Benefit Charge ignores the rounding in ITEPA 2003 s. 681C(3) #2321

Closed

Description

@MaxGhenis

What the law says

ITEPA 2003 s. 681C sets the High Income Child Benefit Charge at the appropriate percentage of the Child Benefit concerned. The percentage is (ANI − £60,000) / £200, capped at 100% (s. 681C(2)). Subsection (3) then says:

(3) If— (a) the total of the amounts mentioned in paragraphs (a) and (b) of subsection (1), or the amount of the charge determined under that subsection, is not a whole number of pounds, or (b) the percentage determined under subsection (2)(b) is not a whole number, it is to be rounded down to the nearest whole number.

So the Child Benefit total, the percentage and the charge are each rounded down. For example, with adjusted net income of £71,336 and Child Benefit of £1,406.60:

  • the percentage is 56.68%, rounded down to 56%;
  • the Child Benefit is rounded down to £1,406;
  • 56% × £1,406 = £787.36, so the charge is £787.

What the model does

CB_HITC multiplies the received Child Benefit by child_benefit_charge_share, a continuous share (policyengine_uk/utils/child_benefit.py). Nothing is rounded, so the charge here is 56.68% × £1,406.60 = £797.26, which is £10.26 too much.

Minimal reproduction

policyengine-uk 2.126.7, and main at 6d89338:

from policyengine_uk import Simulation

situation = {
    "people": {
        "parent": {"age": {"2026": 40}, "employment_income": {"2026": 71_336}},
        "child": {"age": {"2026": 5}},
    },
    "benunits": {"b": {"members": ["parent", "child"]}},
    "households": {"h": {"members": ["parent", "child"], "country": {"2026": "ENGLAND"}}},
}
sim = Simulation(situation=situation)
sim.calculate("child_benefit", 2026), sim.calculate("CB_HITC", 2026)
# (array([1406.6]), array([797.26, 0.]))   the law gives 787

How it was found

The PolicyBench UK round 2 internal audit (October 2026). The two strongest models round the percentage down, and the engine does not. The affected audit cells will be added below once the audit has run.

A fix with tests follows in a PR.

Activity

  1. MaxGhenis commented on Oct 11, 2026

    @MaxGhenis
    CollaboratorAuthor

    Evidence from PolicyBench UK round 2, an internal audit of policyengine-uk 2.126.7 (references identical on 2.126.8). Six models answered the same 200 households. A reference adversary (a blind GPT-6.1 Sol judge, then reconciliation with the engine log) reviewed consensus disagreements and a sample of single-model misses, and each verdict was adjudicated against the engine code and the law.

    Audited cells that turn on this issue: 39. "With #2323" is the reference recomputed on that branch alone; "exact" counts the six models within £1 of the reference, before and after.

    Cell Reference Models (answer × count) With #2323 Exact before → after Other causes in the cell
    scenario_011/high_income_child_benefit_charge £797.26 £788 ×3 £787.00 0 → 3
    scenario_011/income_tax £16,607.81 £16,598 ×2 £16,597.55 1 → 2
    scenario_014/high_income_child_benefit_charge £1,199.83 £1,196 ×4 £1,195.00 0 → 4
    scenario_014/income_tax £21,646.12 £22,193 ×3 £21,641.29 0 → 0 #1799
    scenario_015/income_tax £43,701.80 £43,606 ×2 £43,701.20 0 → 0 #2347 (PR #2348)
    scenario_071/high_income_child_benefit_charge £2,334.36 £2,314 ×3 £2,313.00 0 → 0
    scenario_071/income_tax £17,329.95 £17,310 ×3 £17,308.59 0 → 0
    scenario_076/income_tax £31,318.88 £30,420 ×5 £31,318.48 0 → 0 #2309 (PR #2312)
    scenario_085/income_tax £45,911.63 £45,013 ×5 £45,911.03 0 → 0 #2309 (PR #2312), #2310
    scenario_095/high_income_child_benefit_charge £251.65 £65 ×2; £229 ×2 £228.00 0 → 2
    scenario_095/income_tax £16,454.65 £15,868 ×2; £16,432 ×2 £16,431.00 0 → 2
    scenario_098/high_income_child_benefit_charge £443.71 £436 ×4 £435.00 0 → 0
    scenario_098/income_tax £26,744.91 £26,737 ×4 £26,736.20 0 → 0
    scenario_111/income_tax £23,019.20 £23,055 ×5 £23,018.60 0 → 0 #1799
    scenario_116/high_income_child_benefit_charge £1,349.49 £1,336 ×4 £1,335.00 1 → 0
    scenario_116/income_tax £24,927.69 £24,914 ×4 £24,913.20 1 → 0
    scenario_120/high_income_child_benefit_charge £804.15 £802 ×3 £801.00 0 → 3
    scenario_120/income_tax £21,525.95 £21,524 ×3 £21,522.80 0 → 3
    scenario_122/high_income_child_benefit_charge £142.00 £140 ×4 £140.00 0 → 4
    scenario_123/high_income_child_benefit_charge £362.27 £352 ×3 £351.00 0 → 3
    scenario_123/income_tax £12,905.47 £12,895 ×3 £12,894.20 0 → 3
    scenario_125/high_income_child_benefit_charge £1,263.76 £1,252 ×4 £1,251.00 0 → 4
    scenario_125/income_tax £20,661.16 £20,649 ×4 £20,648.40 0 → 4
    scenario_127/high_income_child_benefit_charge £1,615.96 £1,613 ×4 £1,612.00 0 → 4
    scenario_127/income_tax £22,202.56 £22,199 ×4 £22,198.60 0 → 4
    scenario_128/high_income_child_benefit_charge £325.37 £304 ×4 £303.00 1 → 4
    scenario_128/income_tax £13,329.37 £13,308 ×4 £13,307.00 0 → 4
    scenario_129/high_income_child_benefit_charge £1,003.68 £982 ×4 £981.00 0 → 4
    scenario_129/income_tax £15,852.88 £15,831 ×4 £15,830.20 0 → 4
    scenario_133/high_income_child_benefit_charge £195.94 £183 ×4 £182.00 1 → 4
    scenario_133/income_tax £14,151.54 £14,138 ×4 £14,137.60 1 → 4
    scenario_134/high_income_child_benefit_charge £364.89 £360 ×3 £359.00 0 → 4
    scenario_134/income_tax £12,226.69 £12,221 ×4 £12,220.80 0 → 4
    scenario_139/income_tax £44,297.45 £43,979 ×3 £44,296.85 0 → 0 #2326 (PR #2327)
    scenario_142/high_income_child_benefit_charge £2,337.40 £2,213 ×1 £2,337.00 5 → 5
    scenario_144/high_income_child_benefit_charge £2,337.40 £2,213 ×1 £2,337.00 5 → 5
    scenario_161/high_income_child_benefit_charge £2,337.40 £2,213 ×1 £2,337.00 5 → 5
    scenario_163/high_income_child_benefit_charge £731.78 £0 ×4 £731.00 0 → 0 #2326 (PR #2327)
    scenario_163/income_tax £25,059.78 £0 ×3 £25,059.00 0 → 0 #2045 (PR #2240), #2326 (PR #2327)

    All cells, audited or not. Of the run's 2,800 references, #2323 moves 62 (43 of them audited). In those 62 cells, model answers matching the reference go from 104 to 177 of 372.

    Source: audit/adjudication.json and audit/attribution/attribution.json in the round 2 record.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions