You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
child_benefit_opts_out is never read: opted-out families still receive Child Benefit and pay the charge #2065
child_benefit_opts_out (policyengine_uk/variables/gov/hmrc/child_benefit_opts_out.py, on main and at 2.100.0) is an input variable ("whether this family would opt out of receiving Child Benefit payments; generated stochastically in the dataset") that no formula reads. A code search finds it only in its own definition and in tests/test_deterministic_variables.py.
Effect.child_benefit is defined_for = "would_claim_child_benefit" and adds child_benefit_entitlement; CB_HITC charges a percentage of the child_benefit received. A family flagged as opted out therefore still receives Child Benefit in the simulation and still pays the High Income Child Benefit Charge on it. In the real system an opted-out family receives no payment and owes no charge (it keeps the National Insurance credit only), which is exactly why families above the charge start opt out.
Scale. HMRC's Child Benefit statistics for August 2025 publish 684,635 families registered but opted out. The microcosm UK dataset now draws that share after the SPI chain (PolicyEngine/microcosm#1063, stage child_benefit_take_up in PR PolicyEngine/microcosm#1089: 9.0% of claiming families, all from families charged the whole benefit), so the dataset carries the flag at the published rate, and the engine discards it. On the 2026-09-30 microcosm build the earlier draw had the flag on 2.0m families; either way the engine's Child Benefit and charge totals are those of a world with no opt-outs.
Expected.child_benefit should be zero where child_benefit_opts_out is true (the entitlement can stay, for the NI credit and for reform analyses that remove the charge), and CB_HITC then follows from the benefit actually received. A unit test with a two-earner family above the charge start, opted out, should show zero Child Benefit and zero charge.
Confirmed on main. child_benefit_opts_out appears only in its own definition and in tests/test_deterministic_variables.py; no formula reads it. So child_benefit and CB_HITC are computed as if no family opts out.
The fix you describe looks right: zero child_benefit where child_benefit_opts_out is true, keep child_benefit_entitlement for the NI credit and for reforms that remove the charge, and let CB_HITC follow from the benefit received.
One thing to check when it lands: the opt-out decision is driven by the charge, so a reform that removes or raises the charge threshold should not leave the dataset's opt-out flags fixed. Otherwise a reform that abolishes the charge would still show 9% of claiming families forgoing the benefit. Either document that the flag is a baseline behaviour, or gate it on the family being charged under the simulated policy (for example, opts_out & (CB_HITC charge share > 0)), so reforms that remove the charge bring those families back.
Activity
vahid-ahmadi commentedon Oct 4, 2026
Confirmed on
main.child_benefit_opts_outappears only in its own definition and intests/test_deterministic_variables.py; no formula reads it. Sochild_benefitandCB_HITCare computed as if no family opts out.The fix you describe looks right: zero
child_benefitwherechild_benefit_opts_outis true, keepchild_benefit_entitlementfor the NI credit and for reforms that remove the charge, and letCB_HITCfollow from the benefit received.One thing to check when it lands: the opt-out decision is driven by the charge, so a reform that removes or raises the charge threshold should not leave the dataset's opt-out flags fixed. Otherwise a reform that abolishes the charge would still show 9% of claiming families forgoing the benefit. Either document that the flag is a baseline behaviour, or gate it on the family being charged under the simulated policy (for example,
opts_out & (CB_HITC charge share > 0)), so reforms that remove the charge bring those families back.