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
4 changes: 3 additions & 1 deletion docs/book/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ parts:
- caption: Validation
chapters:
- file: validation/hbai

- caption: Policy
chapters:
- file: policy/uc-rebalancing
2 changes: 1 addition & 1 deletion docs/book/index.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
" reformed.calculate(\"gov_balance\", 2025).sum()\n",
" - baseline.calc(\"gov_balance\", 2025).sum()\n",
")\n",
"f\"Revenue: £{round(revenue / 1e+9, 1)}bn\""
"f\"Revenue: £{round(revenue / 1e9, 1)}bn\""
]
}
],
Expand Down
95 changes: 95 additions & 0 deletions docs/book/policy/uc-rebalancing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Universal Credit rebalancing reforms

The Universal Credit rebalancing reforms represent changes to Universal Credit provisions introduced through the Universal Credit Bill. These reforms take effect from April 2026 and are designed to adjust benefit levels and eligibility criteria.

## Overview

The reforms consist of two main components:

1. **Health element changes for new claimants**: New Universal Credit claimants from April 2026 onwards receive a fixed health element amount, while existing claimants continue to receive inflation-linked increases.

2. **Standard allowance uplifts**: The standard allowance receives additional uplifts beyond the annual inflationary increase from 2026-2029.

## Health element changes

From April 2026, new Universal Credit claimants who qualify for the Limited Capacity for Work-Related Activity (LCWRA) element receive a fixed monthly amount of £217.26, rather than the inflation-adjusted amount that pre-2026 claimants continue to receive.

The implementation uses transition probabilities based on WPI Economics analysis for the Trussell Trust, derived from administrative Personal Independence Payment data. The probability of being a new claimant varies by year:

- 2026: 11%
- 2027: 13%
- 2028: 16%
- 2029: 22%

## Standard allowance uplifts

The standard allowance receives additional percentage uplifts beyond the normal inflationary increase:

- 2026: 2.3% additional uplift
- 2027: 3.1% additional uplift (cumulative)
- 2028: 4.0% additional uplift (cumulative)
- 2029: 4.8% additional uplift (cumulative)

These uplifts are applied to the previous year's standard allowance amount and compound over time.

## Implementation

The reforms are implemented through:

- **Parameters**: Three YAML files define the reform's activation status, health element amount for new claimants, and standard allowance uplift rates.
- **Scenario modifier**: The `add_universal_credit_reform` function applies the changes to Universal Credit calculations during microsimulation.
- **Scenario**: The `universal_credit_july_2025_reform` scenario enables the reforms in policy analysis.

## Examples

You can use these reforms in your own analysis by creating a `Simulation` with parametric changes to modify the reform parameters.

### Disabling the rebalancing reforms entirely

```python
from policyengine_uk import Simulation, Scenario

# Disable the reforms from 2026 onwards
scenario = Scenario(parameter_changes={
"gov.dwp.universal_credit.rebalancing.active": False,
})

sim = Simulation(scenario=scenario)
```

### Changing the standard allowance uplift parameters

```python
from policyengine_uk import Simulation, Scenario

# Set different uplift rates - e.g. 5% in 2026, 7% in 2027
scenario = Scenario(parameter_changes={
"gov.dwp.universal_credit.rebalancing.standard_allowance_uplift": {
"2026-01-01": 0.05,
"2027-01-01": 0.07,
"2028-01-01": 0.07,
"2029-01-01": 0.07
}
})

sim = Simulation(scenario=scenario)
```

### Changing the health element amount for new claimants

```python
from policyengine_uk import Simulation, Scenario

# Set the new claimant health element to £250 per month
scenario = Scenario(parameter_changes={
"gov.dwp.universal_credit.rebalancing.new_claimant_health_element": {
"2026-01-01": 250.00
}
})

sim = Simulation(scenario=scenario)
```

## Legislative reference

The reforms are based on provisions in the Universal Credit Bill, available at: https://bills.parliament.uk/publications/62123/documents/6889.
18 changes: 7 additions & 11 deletions docs/book/programs/gov/dcms/bbc/tv-licence.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,10 @@
"\n",
"df = pd.DataFrame()\n",
"df[\"Date\"] = [\n",
" parameter.instant_str\n",
" for parameter in dcms.bbc.tv_licence.colour.values_list\n",
" parameter.instant_str for parameter in dcms.bbc.tv_licence.colour.values_list\n",
"]\n",
"df[\"Full TV Licence Fee\"] = [\n",
" f\"£{parameter.value:.2f}\"\n",
" for parameter in dcms.bbc.tv_licence.colour.values_list\n",
" f\"£{parameter.value:.2f}\" for parameter in dcms.bbc.tv_licence.colour.values_list\n",
"]\n",
"df[\"Blind TV Licence Fee\"] = [\n",
" f\"£{0.5 * parameter.value:.2f}\"\n",
Expand Down Expand Up @@ -332,13 +330,11 @@
"for i in range(len(aged_discount[\"Reformed value\"])):\n",
" aged_discount[\"Current value\"] += [\"100%\"]\n",
" aged_discount[\"Change against current\"] += [\n",
" f\"{aged_discount['Reformed value'][i]-1:.0%}\"\n",
" f\"{aged_discount['Reformed value'][i] - 1:.0%}\"\n",
" ]\n",
" aged_discount[\"Reformed value\"][\n",
" i\n",
" ] = f\"{aged_discount['Reformed value'][i]:.0%}\"\n",
" aged_discount[\"Reformed value\"][i] = f\"{aged_discount['Reformed value'][i]:.0%}\"\n",
" aged_discount[\"Reference\"] += [\n",
" f\"<a href=\\\"{reference_list_ad[i]}\\\">Budgetary impact of changing aged discount to {aged_discount['Reformed value'][i]}</a>\"\n",
" f'<a href=\"{reference_list_ad[i]}\">Budgetary impact of changing aged discount to {aged_discount[\"Reformed value\"][i]}</a>'\n",
" ]\n",
"\n",
"df_aged_discount = pd.DataFrame(aged_discount)\n",
Expand Down Expand Up @@ -406,11 +402,11 @@
"for i in range(len(licence_fee[\"Reformed value\"])):\n",
" licence_fee[\"Current value\"] += [\"£159\"]\n",
" licence_fee[\"Change against current\"] += [\n",
" f\"£{licence_fee['Reformed value'][i]-159}\"\n",
" f\"£{licence_fee['Reformed value'][i] - 159}\"\n",
" ]\n",
" licence_fee[\"Reformed value\"][i] = f\"£{licence_fee['Reformed value'][i]}\"\n",
" licence_fee[\"Reference\"] += [\n",
" f\"<a href=\\\"{reference_list_fee[i]}\\\">Budgetary impact of changing licence fee to {licence_fee['Reformed value'][i]}</a>\"\n",
" f'<a href=\"{reference_list_fee[i]}\">Budgetary impact of changing licence fee to {licence_fee[\"Reformed value\"][i]}</a>'\n",
" ]\n",
"\n",
"df_licence_fee = pd.DataFrame(licence_fee)\n",
Expand Down
16 changes: 4 additions & 12 deletions docs/book/programs/gov/dwp/pension-credit.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,8 @@
"\n",
"parameters = system.parameters\n",
"\n",
"carer_addition = (\n",
" parameters.gov.dwp.pension_credit.guarantee_credit.carer.addition\n",
")\n",
"child_addition = (\n",
" parameters.gov.dwp.pension_credit.guarantee_credit.child.addition\n",
")\n",
"carer_addition = parameters.gov.dwp.pension_credit.guarantee_credit.carer.addition\n",
"child_addition = parameters.gov.dwp.pension_credit.guarantee_credit.child.addition\n",
"disabled_child = (\n",
" parameters.gov.dwp.pension_credit.guarantee_credit.child.disability.addition\n",
")\n",
Expand Down Expand Up @@ -1506,12 +1502,8 @@
"\n",
"parameters = system.parameters\n",
"\n",
"threshold_single = (\n",
" parameters.gov.dwp.pension_credit.savings_credit.threshold.SINGLE\n",
")\n",
"threshold_couple = (\n",
" parameters.gov.dwp.pension_credit.savings_credit.threshold.COUPLE\n",
")\n",
"threshold_single = parameters.gov.dwp.pension_credit.savings_credit.threshold.SINGLE\n",
"threshold_couple = parameters.gov.dwp.pension_credit.savings_credit.threshold.COUPLE\n",
"\n",
"elements = [threshold_single, threshold_couple] # [...]\n",
"\n",
Expand Down
4 changes: 1 addition & 3 deletions docs/book/programs/gov/dwp/universal-credit.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,7 @@
"disabled_child_amount = (\n",
" parameters.gov.dwp.universal_credit.elements.child.disabled.amount\n",
")\n",
"higher_amount = (\n",
" parameters.gov.dwp.universal_credit.elements.child.first.higher_amount\n",
")\n",
"higher_amount = parameters.gov.dwp.universal_credit.elements.child.first.higher_amount\n",
"\n",
"elements = [\n",
" carer_amount,\n",
Expand Down
20 changes: 8 additions & 12 deletions docs/book/programs/gov/hmrc/child-benefit.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -169,29 +169,27 @@
" data[\"Value\"] += [f\"£{parameter.value:.2f}\"]\n",
" try:\n",
" data[\"Reference\"] += [\n",
" f\"<a href=\\\"{parameter.metadata['reference'][0]['href']}\\\">{parameter.metadata['reference'][0]['title']}</a>\"\n",
" f'<a href=\"{parameter.metadata[\"reference\"][0][\"href\"]}\">{parameter.metadata[\"reference\"][0][\"title\"]}</a>'\n",
" ]\n",
" except:\n",
" data[\"Reference\"] += [\"\"]\n",
"\n",
"\n",
"for (\n",
" parameter\n",
") in parameters.gov.hmrc.child_benefit.amount.additional.values_list:\n",
"for parameter in parameters.gov.hmrc.child_benefit.amount.additional.values_list:\n",
" data[\"Date\"] += [parameter.instant_str]\n",
" data[\"Name\"] += [\"Additional\"]\n",
" data[\"Value\"] += [f\"£{parameter.value:.2f}\"]\n",
" try:\n",
" data[\"Reference\"] += [\n",
" f\"<a href=\\\"{parameter.metadata['reference'][0]['href']}\\\">{parameter.metadata['reference'][0]['title']}</a>\"\n",
" f'<a href=\"{parameter.metadata[\"reference\"][0][\"href\"]}\">{parameter.metadata[\"reference\"][0][\"title\"]}</a>'\n",
" ]\n",
" except:\n",
" data[\"Reference\"] += [\"\"]\n",
"\n",
"\n",
"pd.DataFrame(data).sort_values(\"Date\").set_index(\n",
" [\"Date\", \"Name\"]\n",
").style.format(lambda x: x)"
"pd.DataFrame(data).sort_values(\"Date\").set_index([\"Date\", \"Name\"]).style.format(\n",
" lambda x: x\n",
")"
]
},
{
Expand Down Expand Up @@ -296,15 +294,13 @@
" for i in range(n):\n",
" sim.add_person(age=10, name=str(i))\n",
" sim.add_benunit(members=[str(i) for i in range(n)])\n",
" return f'£{sim.calc(\"child_benefit\").sum():.2f}'\n",
" return f\"£{sim.calc('child_benefit').sum():.2f}\"\n",
"\n",
"\n",
"pd.DataFrame(\n",
" {\n",
" \"Number of children\": list(range(1, 7)),\n",
" \"Child Benefit (Annual)\": list(\n",
" map(get_cb_for_n_children, range(1, 7))\n",
" ),\n",
" \"Child Benefit (Annual)\": list(map(get_cb_for_n_children, range(1, 7))),\n",
" }\n",
").set_index(\"Number of children\")"
]
Expand Down
12 changes: 3 additions & 9 deletions docs/book/programs/gov/hmrc/fuel-duty.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,10 @@
"df = pd.DataFrame()\n",
"\n",
"df[\"Date of change\"] = [\n",
" parameter.instant_str\n",
" for parameter in hmrc.fuel_duty.petrol_and_diesel.values_list\n",
" parameter.instant_str for parameter in hmrc.fuel_duty.petrol_and_diesel.values_list\n",
"]\n",
"df[\"Fuel duty rate (£/litre)\"] = [\n",
" parameter.value\n",
" for parameter in hmrc.fuel_duty.petrol_and_diesel.values_list\n",
" parameter.value for parameter in hmrc.fuel_duty.petrol_and_diesel.values_list\n",
"]\n",
"df.sort_values(\"Date of change\", inplace=True)\n",
"df.set_index(\"Date of change\")"
Expand Down Expand Up @@ -1072,11 +1070,7 @@
" height=600,\n",
" width=800,\n",
" template=\"plotly_white\",\n",
").update_xaxes(\n",
" tickangle=45, tickfont={\"size\": 10}\n",
").update_traces(\n",
" line_shape=\"hv\"\n",
")"
").update_xaxes(tickangle=45, tickfont={\"size\": 10}).update_traces(line_shape=\"hv\")"
]
}
],
Expand Down
Loading
Loading