Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

UK model/data pipeline alignment plan

Architectural gaps vs US

1. _reported consulted at runtime in some would_claim_* formulas

US pattern: _reported columns are consulted once, in the data-build, to anchor stochastic take-up flags (reported recipient → takeup = True with certainty; rest filled probabilistically to a target rate). Runtime formulas only read the pre-computed takes_up_X_if_eligible flag, so reforms that change eligibility flow through cleanly to take-up.

UK pattern (partial): some UK would_claim_* variables already match: would_claim_uc and would_claim_pc are input-only with default_value = True, populated by the data build (now Microcosm UK’s frs_take_up stage). But several still derive from _reported at runtime:

In hand-entered situations each is claims_all_entitled_benefits | (foo_reported > 0) (for Income Support only the claimant’s or partner’s report counts), and claims_all_entitled_benefits is true for a benefit unit that reports under £1 across seven means-tested benefits. In data-built simulations claims_all_entitled_benefits is false for every benefit unit, and Housing Benefit and Council Tax Reduction ignore it, so a reform expanding eligibility only reaches existing _reported > 0 claimants. Setting claims_all_entitled_benefits to true on a data-built simulation does not change this: Housing Benefit and Council Tax Reduction ignore it there, and the eligibility tests for Child Tax Credit, Working Tax Credit, Income Support and working-age Housing Benefit (is_CTC_eligible, is_WTC_eligible, income_support_eligible, housing_benefit_eligible) also require a reported award. In years when tax credits are active it does turn on would_claim_CTC for families that report no Child Tax Credit. Unlike the family and disabled child elements, CTC_child_element does not check is_CTC_eligible, so a family with children that claims Child Tax Credit without being eligible has tax_credits (the child element, less the income taper) but no child_tax_credit. That amount enters its Housing Benefit and Council Tax Reduction means tests, and the tax credit award that the 2024 Winter Fuel Payment and Pension Age Winter Heating Payment tests read. This already happens on main in tax-credit years with nothing overridden. In hand-entered situations the flag is true for every family that reports none of the seven benefits, so each such family with children claims Child Tax Credit. In both kinds of simulation, a family that reports Child Tax Credit but claims Universal Credit still claims it although ineligible. So does a family whose legacy benefits have closed, but on main that happens only once tax credits are no longer active, so its tax_credits is zero unless a reform leaves tax credits active after a legacy benefit has closed. Otherwise, the same eligibility tests mean that a hand-entered family reporting none of the seven benefits can receive, of these five benefits, only Council Tax Reduction and pension-age Housing Benefit.

Fix: convert each to input-only default_value = True (matching would_claim_uc), and add each to Microcosm UK’s reported-anchored take-up stages. Because of those eligibility tests, the only new awards this gives families that report none of these benefits are Council Tax Reduction and pension-age Housing Benefit (the model’s pension-age route, which includes mixed-age couples that can still claim on it). For years when tax credits are active, CTC_child_element needs an is_CTC_eligible gate. The fix would spread the problem but does not create it: without the gate, a family with children drawn as a Child Tax Credit claimant without a report gets the child element, less the income taper, as tax_credits but no Child Tax Credit, and that amount counts as income in its Council Tax Reduction and any Housing Benefit means test. Tax credits stopped paying ongoing awards on 5 April 2025, and gov.dwp.tax_credits.active is false from 2025-04-06 (see tax-credits.md), so the WTC and CTC fix matters only for simulations of earlier years.

2. Take-up assignment ignores reported data

Done in Microcosm UK. Its frs_take_up, pension_credit_take_up and child_benefit_take_up stages keep every benefit unit that reports receipt as a claimant and draw the rest to the target rate (source_stages.json at 75167a6). The description below is the Enhanced FRS behaviour before policyengine-uk-data#359 (April 2026), which anchored would_claim_uc, would_claim_pc and would_claim_child_benefit on reported receipt, the same three flags Microcosm UK anchors.

Until then the Enhanced FRS take-up assignment was a pure random draw:

pe_benunit["would_claim_uc"] = generator.random(len(pe_benunit)) < universal_credit_rate

This discards information: respondents who reported receiving UC clearly took it up, and should have would_claim_uc = True with certainty.

Fix (done in policyengine-uk-data#359): port policyengine_us_data/utils/takeup.py::assign_takeup_with_reported_anchors into policyengine-uk-data and apply it to each take-up variable where a _reported column exists (would_claim_uc, would_claim_pc, would_claim_child_benefit). This tightens per-variable calibration without changing the target rates.

3. Second-stage imputation gap on SPI donors

Done in Microcosm UK. hmrc_spi_income_spine draws gift_aid and charitable_investment_gifts from the SPI jointly with the new incomes, and an FRS-only second stage, trained on the FRS rows, predicts pension contributions, tax-free savings income and the *_reported benefits for the SPI rows from those incomes. spi_housing_shell redraws tenure, dwelling and council tax band for the SPI households, and the wealth, spending and VAT stages now run after the SPI block, so they are drawn for the new incomes rather than inherited from the FRS parent. The description below is the Enhanced FRS behaviour before April 2026: policyengine-uk-data#347 then added gift_aid and charitable_investment_gifts to the SPI imputation, and #362 added a second-stage QRF (datasets/imputations/frs_only.py) for pension contributions, tax-free savings income and the *_reported benefits; rent and wealth on SPI rows still come from the FRS parent there.

policyengine_uk_data/datasets/imputations/income.py::impute_income trained a QRF that replaced only six income variables on SPI donor rows; everything else (rent, wealth, pension contributions, gift aid, benefits-reported flags) stayed as whatever middle-income FRS donor happened to be sampled. So a synthetic SPI donor ending up with £2M imputed self-employment income still carried an unchanged middle-FRS- donor’s savings balance and zero gift aid.

The US equivalent (policyengine-us-data#589) fixed this by adding a second-stage QRF: train on CPS with predictors = demographics + newly-imputed income vars, outputs = the ~60 CPS-only variables; for PUF-clone prediction, substitute imputed PUF incomes as predictors so CPS-only variables come out consistent with imputed income.

Fix: add the analogous second-stage QRF in policyengine_uk_data/datasets/imputations/, training on FRS with predictors = demographics + 6 income vars, outputs = a wide set of “FRS-only” consequential variables including rent, mortgage_interest_repayment, gift_aid, covenanted_payments, charitable_investment_gifts, other_deductions, employee_pension_contributions*, employer_pension_contributions, total wealth components, capital_allowances, deficiency_relief, and the full list of *_reported benefits. policyengine-uk-data#362 (April 2026) added this stage with a narrower output list: pension contributions, tax-free savings income and the *_reported benefits. Microcosm UK’s second stage had the same outputs at 75167a6, less the incapacity benefit and maternity allowance reports, which its base data lacks; it has since added trading losses, six owner-manager company variables and the War Widow’s Pension report (source_stages.json at 54b514f).

Specific aggregate residuals

After the formula-side fixes already merged (BASIC/NEW classification in PR #1618, new State Pension pro-rating + Protected Payment in PR #1634), the residual benefit-aggregate gaps against OBR on the Enhanced FRS (for the rows other than State Pension, the figures #1621 reported for 2025 on Enhanced FRS 1.50.3 in April 2026, which predates policyengine-uk-data#347, #359 and #362; the State Pension row is taken from the State Pension page; none re-measured on Microcosm UK) were:

VariableModelTargetGapLikely cause
income_support~£1.07 bn~£0.2 bn+£0.9 bnLegacy benefit near-fully migrated; same reported > 0 retention issue as the (pre-fix) tax credits.
esa_contrib~£5.56 bn~£2.5 bn+£3.1 bnLarge. Likely reported-based take-up plus no phase-out for migrated cases.
attendance_allowance~£8.76 bn~£7.0 bn+£1.8 bnCap-rate or take-up issue.
tax_free_childcare~£0.41 bn~£0.9 bn-£0.5 bnUnderstated by about half: under-imputed eligible families.
state_pension£119.0 bn£131.3 bn-£12.2 bn2024-25, against DWP’s Spring Forecast 2026 less payments abroad, on policyengine-uk-data-private 1.57.4, as documented in state-pension.md. Most of the shortfall arises in building the Enhanced FRS (policyengine-uk-data#493).

Each warrants a scoped PR pair (model + data) once the architectural fixes above land.

Small items from #1621

The issue body flagged three small items; two are resolved:

Separately, the state_pension_type BASIC/NEW classification was rewritten in PR #1618.

This page reflects the current gap rather than the issue body, so the next reviewer working through the queue doesn’t waste time on already-fixed items.

Candidate PR sequence

  1. Convert remaining would_claim_* formulas to input-only (model side) + reported-anchored assignment in Microcosm UK’s frs_take_up stage. Still open: the five formulas above read _reported at runtime on main.

  2. ~~Port assign_takeup_with_reported_anchors~~: done in policyengine-uk-data#359 and in Microcosm UK (gap 2).

  3. ~~Add second-stage QRF for FRS-only variables on SPI donors~~: done in policyengine-uk-data#362 and in Microcosm UK (gap 3), both with a narrower output list than proposed above; Microcosm UK also redraws housing and runs the wealth, spending and VAT stages after the SPI block.

  4. ~~Add gift_aid to IMPUTATIONS~~: done in policyengine-uk-data#347 and in Microcosm UK, where gift_aid is a stage-1 SPI output.

  5. Residual benefit-aggregate follow-ups: re-measure on the Microcosm release first, then separate small PRs for ESA contrib investigation, AA calibration, TFC under-imputation, the State Pension data-side fix (#1632, policyengine-uk-data#493). The IS phase-out landed in #1631 (gov.dwp.income_support.active is false from 2026-04-01).

References