From fddad49666cd9ad4756697c8ac7f70626ab2ad89 Mon Sep 17 00:00:00 2001 From: Ziming Hua <113824411+hua7450@users.noreply.github.com> Date: Wed, 28 Oct 2026 10:40:46 -0400 Subject: [PATCH 01/24] Draft Autumn Budget 2026 savings/property and trading explainers --- analysis/uk-budget-2026-income-tax/README.md | 43 + .../generate_households.py | 373 +++ .../uk-budget-2026-income-tax/households.csv | 24 + .../uk-budget-2026-income-tax/households.json | 2015 +++++++++++++++++ .../uk-budget-2026-income-tax/provenance.json | 36 + .../requirements.txt | 3 + .../savings-interest-chart.json | 76 + .../savings-interest-curve.csv | 11 + .../trading-allowance-chart.json | 76 + .../trading-receipts-curve.csv | 11 + ...udget-2026-savings-property-income-tax.svg | 56 + ...k-autumn-budget-2026-trading-allowance.svg | 45 + ...budget-2026-savings-property-income-tax.md | 154 ++ ...uk-autumn-budget-2026-trading-allowance.md | 149 ++ app/src/data/posts/posts.json | 18 + 15 files changed, 3090 insertions(+) create mode 100644 analysis/uk-budget-2026-income-tax/README.md create mode 100644 analysis/uk-budget-2026-income-tax/generate_households.py create mode 100644 analysis/uk-budget-2026-income-tax/households.csv create mode 100644 analysis/uk-budget-2026-income-tax/households.json create mode 100644 analysis/uk-budget-2026-income-tax/provenance.json create mode 100644 analysis/uk-budget-2026-income-tax/requirements.txt create mode 100644 analysis/uk-budget-2026-income-tax/savings-interest-chart.json create mode 100644 analysis/uk-budget-2026-income-tax/savings-interest-curve.csv create mode 100644 analysis/uk-budget-2026-income-tax/trading-allowance-chart.json create mode 100644 analysis/uk-budget-2026-income-tax/trading-receipts-curve.csv create mode 100644 app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax.svg create mode 100644 app/public/assets/posts/uk-autumn-budget-2026-trading-allowance.svg create mode 100644 app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md create mode 100644 app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md new file mode 100644 index 000000000..b59c5b21d --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -0,0 +1,43 @@ +# Autumn Budget 2026 income tax explainers + +This directory supports two standalone posts: the combined savings/property rate increase and the trading allowance increase. The articles compare the newly announced measures with the already legislated 2027–28 baseline, one measure at a time. + +## Reproduce the household calculations + +From the repository root, using Python 3.13: + +```sh +uv venv --python 3.13 analysis/uk-budget-2026-income-tax/.venv +uv pip install --python analysis/uk-budget-2026-income-tax/.venv/bin/python -r analysis/uk-budget-2026-income-tax/requirements.txt +analysis/uk-budget-2026-income-tax/.venv/bin/python analysis/uk-budget-2026-income-tax/generate_households.py +``` + +The generator uses hypothetical adults, without population microdata. It records inputs and outputs and checks the results against independent arithmetic. The reform parameters match dashboard PR290 at the immutable commit recorded in `provenance.json`. Fixed nominal household incomes do not require population forecast uprating. + +The checked outputs include 23 household comparisons and 20 points across the two income curves. To also verify the original dashboard parameter builder, pass `--dashboard-checkout /path/to/checkout` with that checkout at the recorded commit. This check is optional and performs no download. + +The article chart blocks reproduce `savings-interest-chart.json` and `trading-allowance-chart.json`. Reinsert their contents when regenerating them. + +## Dataset decision + +Retain the dashboard's adopted `policyengine` 6.11.1 bundle, with UK 2.151.0, core 3.33.3 and national data cut `a6299504`. The certificate, full dataset ID and checksum are recorded in `provenance.json`. The newer candidate in policyengine.py PR725 is awaiting certification/adoption. A future update must change the package and dataset provenance together and regenerate the analysis. + +No population microdata were available for this draft. It contains no PolicyEngine national estimates, decile results or affected-person counts. Treasury forecasts are labelled separately and are not a substitute for those calculations. The publicly committed dashboard results checked on 28 October did not yet include these two Budget-day measures; older candidate savings/property charts must not be relabelled as the announced policy. + +When access and certified Budget-day outputs are available, use the national dataset above and the dashboard's October 2026 OBR forecast wrapper on both baseline and reform. Score each provision separately. Reconcile fiscal-year Treasury receipts with modelled tax-year liabilities, documenting behavioural and timing differences. Retain survey confidentiality; publish aggregates only. + +## Checks before publication + +- Add the outstanding national revenue, affected-person and decile results requested in the team brief, with provenance and model-coverage limits. +- Confirm the treatment of Scottish landlords' finance-cost relief against the final Budget implementation. The pinned model links that relief to the UK property basic rate even for Scotland. +- Check trading allowance coverage: gross receipts and actual expenses are needed to model the deduction choice; the pinned model does not apply the allowance to its separate miscellaneous-income input. +- Verify the final public dashboard link and add links to these explainers within the dashboard. The source checkout's README supplies the current Vercel dashboard URL. +- Have the policy interpretation and calculations reviewed before merging. This branch is a draft and is not publication approval. + +The two articles use the site's native chart blocks and cover assets. No runtime application or country-model code is changed. + +## Validation on 28 October 2026 + +`make format`, `make lint`, `make typecheck` and `make test` passed. The tests ran on Node 26.12.1: 6,042 app tests and 508 website tests passed, with 10 app tests skipped by the existing suite. After inserting the final chart data, the chart-parser and post-metadata checks passed again (18 tests). All 23 household comparisons and 20 curve points passed independent arithmetic checks. + +Browser access to the local preview was declined, so visual preview remains outstanding. The SVG cover XML and native chart specs were validated, but this does not confirm page layout at desktop or mobile widths. diff --git a/analysis/uk-budget-2026-income-tax/generate_households.py b/analysis/uk-budget-2026-income-tax/generate_households.py new file mode 100644 index 000000000..e3b752fcc --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/generate_households.py @@ -0,0 +1,373 @@ +"""Reproduce synthetic examples for the two Autumn Budget 2026 explainers. + +Run with this directory's pinned .venv/bin/python. No population data are used. +Tax liability changes isolate each announced measure against the 2027 baseline. +""" + +from __future__ import annotations + +import argparse +import ast +import csv +from datetime import datetime, timezone +import importlib.metadata as metadata +import json +import math +from pathlib import Path +import platform +import subprocess +import warnings + +import policyengine as pe + + +YEAR = 2027 +EXPECTED_VERSIONS = { + "policyengine": "6.11.1", + "policyengine-uk": "2.151.0", + "policyengine-core": "3.33.3", +} +SOURCE_COMMIT = "b50787aa75ef5aed36b822c973afa6b569464d55" +SOURCE_PR = "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/290" +RATE_ROOT = "gov.hmrc.income_tax.rates" +SAVINGS_PROPERTY = { + f"{RATE_ROOT}.{income}.{band}": rate + for income in ("savings", "property") + for band, rate in (("basic", 0.24), ("higher", 0.44), ("additional", 0.49)) +} +TRADING_PATH = "gov.hmrc.income_tax.allowances.trading_allowance" +TRADING = {TRADING_PATH: 3_000} +PERSON_OUTPUTS = [ + "income_tax", "savings_income_tax", "savings_allowance", + "savings_starter_rate_income", "basic_rate_savings_income", + "higher_rate_savings_income", "add_rate_savings_income", + "property_income_tax", "property_finance_cost_relief", + "taxable_property_income", "trading_allowance_deduction", + "taxable_self_employment_income", "national_insurance", "ni_class_4", +] + + +def close(actual: float, expected: float, label: str) -> None: + # Country-model monetary arrays are float32; two pence covers their + # representation error without concealing a material example discrepancy. + if not math.isclose(actual, expected, abs_tol=0.02, rel_tol=0): + raise AssertionError(f"{label}: engine {actual}, independent oracle {expected}") + + +def rounded(value): + if isinstance(value, list): + return [round(float(item), 2) for item in value] + return round(float(value), 2) + + +def calculate(person: dict, region: str, reform: dict, axes=None) -> dict: + result = pe.uk.calculate_household( + people=[{"age": 35, **person}], + household={"region": region}, + year=YEAR, + reform=reform, + axes=axes, + extra_variables=PERSON_OUTPUTS, + ) + output = {name: rounded(getattr(result.person[0], name)) for name in PERSON_OUTPUTS} + output["household_benefits"] = rounded(result.household.household_benefits) + return output + + +def verify_baseline_parameters() -> dict: + # Direct country access inspects parameters only. Tax calculations use pe.uk. + from policyengine_uk.system import system + + baseline = { + path: system.parameters.get_child(path)(f"{YEAR}-04-06") + for path in SAVINGS_PROPERTY + } + for path in SAVINGS_PROPERTY: + expected = {"basic": 0.22, "higher": 0.42, "additional": 0.47}[path.rsplit(".", 1)[1]] + close(baseline[path], expected, path) + baseline[TRADING_PATH] = system.parameters.get_child(TRADING_PATH)(f"{YEAR}-04-06") + close(baseline[TRADING_PATH], 1_000, TRADING_PATH) + return baseline + + +def source_comparison(checkout: Path | None) -> dict: + """Optionally execute the dashboard's relevant builder, not its pipeline.""" + record = { + "pull_request": SOURCE_PR, + "commit": SOURCE_COMMIT, + "source_file_url": f"https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/{SOURCE_COMMIT}/src/uk_budget_data/reforms.py", + "compared_file": "src/uk_budget_data/reforms.py", + "baseline_parameters": verify_baseline_parameters(), + "reform_parameters": {**SAVINGS_PROPERTY, **TRADING}, + "dashboard_builder_verified": checkout is not None, + } + if checkout is None: + return { + **record, + "comparison": "Independent reform dictionaries and baseline parameters verified. Optional dashboard-builder comparison not requested; immutable source reference recorded above.", + } + commit = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=checkout, text=True + ).strip() + if commit != SOURCE_COMMIT: + raise AssertionError(f"Dashboard checkout changed: {commit}") + source_file = checkout / "src/uk_budget_data/reforms.py" + tree = ast.parse(source_file.read_text()) + names = { + "INCOME_TAX_RATES", "UNEARNED_INCOME_RATE_PATHS", + "UNEARNED_INCOME_RATE_RISE", "UNEARNED_INCOME_RATES_FROM", + "TRADING_ALLOWANCE", "TRADING_ALLOWANCE_RAISED", "TRADING_ALLOWANCE_FROM", + } + selected = [ + node for node in tree.body + if ( + isinstance(node, ast.Assign) + and any(isinstance(target, ast.Name) and target.id in names for target in node.targets) + ) or (isinstance(node, ast.FunctionDef) and node.name == "unearned_income_rates_up") + ] + scope = { + "POLICY_YEARS": list(range(2026, 2032)), + # The real template validates then returns this same dictionary shape. + "rate_change": lambda path, years: {path: years}, + } + exec(compile(ast.Module(body=selected, type_ignores=[]), str(source_file), "exec"), scope) + dashboard = scope["unearned_income_rates_up"]() + flat = {path: values[str(YEAR)] for path, values in dashboard.items()} + assert flat == SAVINGS_PROPERTY, (flat, SAVINGS_PROPERTY) + assert scope["UNEARNED_INCOME_RATES_FROM"] == YEAR + assert scope["TRADING_ALLOWANCE_FROM"] == YEAR + assert {scope["TRADING_ALLOWANCE"]: scope["TRADING_ALLOWANCE_RAISED"]} == TRADING + return { + **record, + "comparison": "Relevant parameter declarations and savings/property builder match the independent flat reform dictionaries; no combined-package modifiers run.", + } + + +def cases() -> list[dict]: + rows = [] + + def add(case_id, policy, person, expected, region="LONDON", detail=None): + rows.append({ + "id": case_id, "policy": policy, "region": region, + "person": person, "independent_oracle": expected, + "detail": detail, + }) + + for case_id, salary, interest, allowance, before, after in [ + ("saver_below_allowance", 30_000, 500, 1_000, 0, 0), + ("saver_basic", 30_000, 2_000, 1_000, 220, 240), + ("saver_higher", 60_000, 2_000, 500, 630, 660), + ("saver_additional", 150_000, 2_000, 0, 940, 980), + ("saver_crosses_basic_higher", 49_270, 2_000, 500, 530, 560), + ("saver_starting_rate", 15_000, 4_000, 1_000, 94.60, 103.20), + ]: + add(case_id, "savings_property", { + "employment_income": salary, "savings_interest_income": interest, + }, { + "baseline": {"savings_allowance": allowance, "savings_income_tax": before}, + "reform": {"savings_allowance": allowance, "savings_income_tax": after}, + "change": {"income_tax": after - before}, + }) + add("saver_scotland_higher", "savings_property", { + "employment_income": 60_000, "savings_interest_income": 2_000, + }, {"baseline": {"savings_income_tax": 630}, "reform": {"savings_income_tax": 660}, + "change": {"income_tax": 30}}, region="SCOTLAND") + + for band, salary, before, after, total in [ + ("basic", 30_000, 2_200, 2_400, 4_806), + ("higher", 60_000, 4_200, 4_400, 14_752), + ("additional", 150_000, 4_700, 4_900, 57_523), + ("crosses_basic_higher", 45_000, 3_146, 3_346, 8_752), + ]: + add(f"landlord_{band}_mortgage", "savings_property", { + "employment_income": salary, "property_income": 10_000, + "property_finance_costs": 4_000, + }, { + "baseline": {"property_income_tax": before, "property_finance_cost_relief": 880, "income_tax": total}, + "reform": {"property_income_tax": after, "property_finance_cost_relief": 960, "income_tax": total + 120}, + "change": {"income_tax": 120}, + }, detail={"gross_rent": 12_000, "actual_non_finance_expenses": 2_000}) + for region in ("LONDON", "WALES", "NORTHERN_IRELAND"): + add(f"landlord_mortgage_free_{region.lower()}", "savings_property", { + "employment_income": 30_000, "property_income": 10_000, + }, {"baseline": {"property_income_tax": 2_200}, "reform": {"property_income_tax": 2_400}, + "change": {"income_tax": 200}}, region=region) + for finance, change in ((0, 0), (4_000, -80)): + add(f"landlord_scotland_finance_{finance}", "savings_property", { + "employment_income": 60_000, "property_income": 10_000, + "property_finance_costs": finance, + }, {"change": {"property_income_tax": 0, "property_finance_cost_relief": finance * 0.02, "income_tax": change}}, + region="SCOTLAND", detail="Scottish property rates do not change; the UK-wide finance-cost credit rate does.") + add("property_then_savings_order", "savings_property", { + "employment_income": 45_000, "property_income": 6_000, + "savings_interest_income": 2_000, + }, { + "baseline": {"property_income_tax": 1_466, "savings_income_tax": 630, "income_tax": 8_582}, + "reform": {"property_income_tax": 1_586, "savings_income_tax": 660, "income_tax": 8_732}, + "change": {"income_tax": 150}, + }) + + for salary, marginal in ((30_000, 0.2), (60_000, 0.4)): + wages_tax = 3_486 if salary == 30_000 else 11_432 + for expenses in (500, 2_500, 3_500): + receipts = 4_000 + before = max(0, receipts - max(expenses, 1_000)) + after = max(0, receipts - max(expenses, 3_000)) + add(f"trader_salary_{salary}_expenses_{expenses}", "trading", { + "employment_income": salary, + "self_employment_gross_receipts": receipts, + "self_employment_income": receipts - expenses, + }, { + "baseline": {"taxable_self_employment_income": before, "income_tax": wages_tax + before * marginal, "ni_class_4": 0}, + "reform": {"taxable_self_employment_income": after, "income_tax": wages_tax + after * marginal, "ni_class_4": 0}, + "change": {"income_tax": (after - before) * marginal, "national_insurance": 0}, + }, detail={"gross_receipts": receipts, "actual_expenses": expenses}) + return rows + + +def generate_cases() -> list[dict]: + output = [] + for case in cases(): + reform = SAVINGS_PROPERTY if case["policy"] == "savings_property" else TRADING + baseline = calculate(case["person"], case["region"], {}) + reformed = calculate(case["person"], case["region"], reform) + change = {name: round(reformed[name] - baseline[name], 2) for name in baseline} + result = {**case, "baseline": baseline, "reform": reformed, "change": change} + for scenario, expectations in case["independent_oracle"].items(): + for variable, expected in expectations.items(): + close(result[scenario][variable], expected, f"{case['id']} {scenario} {variable}") + close(baseline["household_benefits"], 0, f"{case['id']} baseline benefits") + close(reformed["household_benefits"], 0, f"{case['id']} reform benefits") + output.append(result) + return output + + +def generate_curves() -> tuple[list[dict], list[dict]]: + interest_rows = [{"interest": value} for value in range(500, 5_001, 500)] + for label, salary, allowance, old_rate in ( + ("basic", 30_000, 1_000, 0.22), ("higher", 60_000, 500, 0.42), + ): + axes = [[{"name": "savings_interest_income", "min": 500, "max": 5_000, "count": 10}]] + baseline = calculate({"employment_income": salary}, "LONDON", {}, axes) + reformed = calculate({"employment_income": salary}, "LONDON", SAVINGS_PROPERTY, axes) + for index, row in enumerate(interest_rows): + taxable = max(0, row["interest"] - allowance) + before, after = baseline["savings_income_tax"][index], reformed["savings_income_tax"][index] + close(before, taxable * old_rate, f"{label} savings curve baseline") + close(after, taxable * (old_rate + 0.02), f"{label} savings curve reform") + row[f"{label}_baseline_tax"] = before + row[f"{label}_reform_tax"] = after + row[f"{label}_tax_increase"] = round(after - before, 2) + + trading_rows = [{"receipts": value} for value in range(500, 5_001, 500)] + for label, expense_share in (("no_expenses", 0), ("expenses_75_percent", 0.75)): + profit_share = 1 - expense_share + axes = [[ + {"name": "self_employment_gross_receipts", "min": 500, "max": 5_000, "count": 10}, + {"name": "self_employment_income", "min": 500 * profit_share, "max": 5_000 * profit_share, "count": 10}, + ]] + baseline = calculate({"employment_income": 30_000}, "LONDON", {}, axes) + reformed = calculate({"employment_income": 30_000}, "LONDON", TRADING, axes) + for index, row in enumerate(trading_rows): + receipts = row["receipts"] + expenses = receipts * expense_share + old_taxable = max(0, receipts - max(expenses, 1_000)) + new_taxable = max(0, receipts - max(expenses, 3_000)) + close(baseline["taxable_self_employment_income"][index], old_taxable, f"{label} trading baseline") + close(reformed["taxable_self_employment_income"][index], new_taxable, f"{label} trading reform") + reduction = round(baseline["income_tax"][index] - reformed["income_tax"][index], 2) + close(reduction, (old_taxable - new_taxable) * 0.2, f"{label} trading tax reduction") + close(baseline["ni_class_4"][index], 0, f"{label} baseline Class 4") + close(reformed["ni_class_4"][index], 0, f"{label} reform Class 4") + row[f"{label}_actual_expenses"] = expenses + row[f"{label}_baseline_taxable_profit"] = old_taxable + row[f"{label}_reform_taxable_profit"] = new_taxable + row[f"{label}_tax_reduction"] = reduction + return interest_rows, trading_rows + + +def chart_specs(savings, trading) -> dict: + source = "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed." + return { + "savings-interest-chart.json": { + "type": "bar", "title": "Savings tax increases apply above the Personal Savings Allowance", + "subtitle": "Annual income tax increase; England, salaries £30,000 and £60,000, 2027–28", + "xKey": "interest", "yLabel": "Extra annual income tax (£)", + "format": {"prefix": "£", "decimals": 0}, "source": source, + "series": [ + {"key": "basic", "name": "£30,000 salary", "color": "negative"}, + {"key": "higher", "name": "£60,000 salary", "color": "secondary"}, + ], + "data": [{"interest": f"£{row['interest']:,}", "basic": row["basic_tax_increase"], "higher": row["higher_tax_increase"]} for row in savings], + }, + "trading-allowance-chart.json": { + "type": "bar", "title": "Trading allowance: the income tax reduction depends on expenses", + "subtitle": "Annual income tax reduction; England, £30,000 salary, 2027–28", + "xKey": "receipts", "yLabel": "Annual income tax reduction (£)", + "format": {"prefix": "£", "decimals": 0}, "source": source, + "series": [ + {"key": "noExpenses", "name": "No business expenses", "color": "primary"}, + {"key": "highExpenses", "name": "Expenses equal 75% of receipts", "color": "secondary"}, + ], + "data": [{"receipts": f"£{row['receipts']:,}", "noExpenses": row["no_expenses_tax_reduction"], "highExpenses": row["expenses_75_percent_tax_reduction"]} for row in trading], + }, + } + + +def write_csv(path: Path, rows: list[dict]) -> None: + with path.open("w", newline="") as handle: + writer = csv.DictWriter(handle, fieldnames=list(rows[0])) + writer.writeheader() + writer.writerows(rows) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--dashboard-checkout", type=Path, help="Optional checkout at the recorded PR290 commit for source-builder comparison; not needed for household calculations.") + parser.add_argument("--output-dir", type=Path, default=Path(__file__).resolve().parent) + args = parser.parse_args() + versions = {package: metadata.version(package) for package in EXPECTED_VERSIONS} + assert versions == EXPECTED_VERSIONS, (versions, EXPECTED_VERSIONS) + # Formula files are dynamically loaded, so their warning module names do + # not consistently match policyengine_uk. Filter these exact known messages. + warnings.filterwarnings("ignore", category=RuntimeWarning, message="(divide by zero|invalid value) encountered in (divide|multiply)") + warnings.filterwarnings("ignore", category=UserWarning, message="Accessing \\.values on a MicroSeries returns a plain numpy array without weights\\.") + comparison = source_comparison(args.dashboard_checkout) + households = generate_cases() + savings, trading = generate_curves() + payload = { + "metadata": { + "generated_at_utc": datetime.now(timezone.utc).isoformat(), + "tax_year": "2027–28", "model_year": YEAR, "versions": versions, + "python": platform.python_version(), "dashboard_comparison": comparison, + "scope": "Synthetic single adults age 35; no microdata, no behavioural responses or national estimates. Income and expenses held fixed; tax liabilities, not full household net-income changes.", + "assumptions": "No children, pensions, Gift Aid, student loans, capital gains, other tax reliefs, property losses or carried-forward finance costs. Savings are outside ISAs. Trading receipts and profit are both supplied; no connected-party receipts or partnership income. All example benefit totals are checked to be zero.", + "oracle_tolerance_gbp": 0.02, + "warning_filters": "Known household divide/invalid RuntimeWarnings and single-household model decile .values warnings only; no population weights are accessed by this generator.", + }, + "reforms": {"savings_property": SAVINGS_PROPERTY, "trading": TRADING}, + "households": households, + "savings_interest_curve": savings, "trading_receipts_curve": trading, + } + args.output_dir.mkdir(parents=True, exist_ok=True) + (args.output_dir / "households.json").write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n") + flat = [] + for row in households: + record = {"id": row["id"], "policy": row["policy"], "region": row["region"], "model_year": YEAR} + record.update({f"input_{name}": row["person"].get(name, 0) for name in ( + "employment_income", "savings_interest_income", "property_income", + "property_finance_costs", "self_employment_gross_receipts", "self_employment_income", + )}) + for scenario in ("baseline", "reform", "change"): + record.update({f"{scenario}_{name}": value for name, value in row[scenario].items()}) + flat.append(record) + write_csv(args.output_dir / "households.csv", flat) + write_csv(args.output_dir / "savings-interest-curve.csv", savings) + write_csv(args.output_dir / "trading-receipts-curve.csv", trading) + for filename, spec in chart_specs(savings, trading).items(): + (args.output_dir / filename).write_text(json.dumps(spec, indent=2, ensure_ascii=False) + "\n") + print(f"Verified {len(households)} household comparisons and {len(savings) + len(trading)} curve points; wrote {args.output_dir}") + + +if __name__ == "__main__": + main() diff --git a/analysis/uk-budget-2026-income-tax/households.csv b/analysis/uk-budget-2026-income-tax/households.csv new file mode 100644 index 000000000..86194df52 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/households.csv @@ -0,0 +1,24 @@ +id,policy,region,model_year,input_employment_income,input_savings_interest_income,input_property_income,input_property_finance_costs,input_self_employment_gross_receipts,input_self_employment_income,baseline_income_tax,baseline_savings_income_tax,baseline_savings_allowance,baseline_savings_starter_rate_income,baseline_basic_rate_savings_income,baseline_higher_rate_savings_income,baseline_add_rate_savings_income,baseline_property_income_tax,baseline_property_finance_cost_relief,baseline_taxable_property_income,baseline_trading_allowance_deduction,baseline_taxable_self_employment_income,baseline_national_insurance,baseline_ni_class_4,baseline_household_benefits,reform_income_tax,reform_savings_income_tax,reform_savings_allowance,reform_savings_starter_rate_income,reform_basic_rate_savings_income,reform_higher_rate_savings_income,reform_add_rate_savings_income,reform_property_income_tax,reform_property_finance_cost_relief,reform_taxable_property_income,reform_trading_allowance_deduction,reform_taxable_self_employment_income,reform_national_insurance,reform_ni_class_4,reform_household_benefits,change_income_tax,change_savings_income_tax,change_savings_allowance,change_savings_starter_rate_income,change_basic_rate_savings_income,change_higher_rate_savings_income,change_add_rate_savings_income,change_property_income_tax,change_property_finance_cost_relief,change_taxable_property_income,change_trading_allowance_deduction,change_taxable_self_employment_income,change_national_insurance,change_ni_class_4,change_household_benefits +saver_below_allowance,savings_property,LONDON,2027,30000,500,0,0,0,0,3486.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1394.4,0.0,0.0,3486.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1394.4,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +saver_basic,savings_property,LONDON,2027,30000,2000,0,0,0,0,3706.0,220.0,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1394.4,0.0,0.0,3726.0,240.0,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1394.4,0.0,0.0,20.0,20.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +saver_higher,savings_property,LONDON,2027,60000,2000,0,0,0,0,12062.0,630.0,500.0,0.0,0.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,3210.6,0.0,0.0,12092.0,660.0,500.0,0.0,0.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,3210.6,0.0,0.0,30.0,30.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +saver_additional,savings_property,LONDON,2027,150000,2000,0,0,0,0,54643.0,940.0,0.0,0.0,0.0,0.0,2000.0,0.0,0.0,0.0,0.0,0.0,5010.6,0.0,0.0,54683.0,980.0,0.0,0.0,0.0,0.0,2000.0,0.0,0.0,0.0,0.0,0.0,5010.6,0.0,0.0,40.0,40.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +saver_crosses_basic_higher,savings_property,LONDON,2027,49270,2000,0,0,0,0,7870.0,530.0,500.0,0.0,500.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,2936.0,0.0,0.0,7900.0,560.0,500.0,0.0,500.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,2936.0,0.0,0.0,30.0,30.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +saver_starting_rate,savings_property,LONDON,2027,15000,4000,0,0,0,0,580.6,94.6,1000.0,2570.0,430.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,194.4,0.0,0.0,589.2,103.2,1000.0,2570.0,430.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,194.4,0.0,0.0,8.6,8.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +saver_scotland_higher,savings_property,SCOTLAND,2027,60000,2000,0,0,0,0,13807.87,630.0,500.0,0.0,0.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,3210.6,0.0,0.0,13837.87,660.0,500.0,0.0,0.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,3210.6,0.0,0.0,30.0,30.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_basic_mortgage,savings_property,LONDON,2027,30000,0,10000,4000,0,0,4806.0,0.0,1000.0,0.0,0.0,0.0,0.0,2200.0,880.0,10000.0,0.0,0.0,1394.4,0.0,0.0,4926.0,0.0,1000.0,0.0,0.0,0.0,0.0,2400.0,960.0,10000.0,0.0,0.0,1394.4,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_higher_mortgage,savings_property,LONDON,2027,60000,0,10000,4000,0,0,14752.0,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,880.0,10000.0,0.0,0.0,3210.6,0.0,0.0,14872.0,0.0,500.0,0.0,0.0,0.0,0.0,4400.0,960.0,10000.0,0.0,0.0,3210.6,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_additional_mortgage,savings_property,LONDON,2027,150000,0,10000,4000,0,0,57523.0,0.0,0.0,0.0,0.0,0.0,0.0,4700.0,880.0,10000.0,0.0,0.0,5010.6,0.0,0.0,57643.0,0.0,0.0,0.0,0.0,0.0,0.0,4900.0,960.0,10000.0,0.0,0.0,5010.6,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_crosses_basic_higher_mortgage,savings_property,LONDON,2027,45000,0,10000,4000,0,0,8752.0,0.0,500.0,0.0,0.0,0.0,0.0,3146.0,880.0,10000.0,0.0,0.0,2594.4,0.0,0.0,8872.0,0.0,500.0,0.0,0.0,0.0,0.0,3346.0,960.0,10000.0,0.0,0.0,2594.4,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_mortgage_free_london,savings_property,LONDON,2027,30000,0,10000,0,0,0,5686.0,0.0,1000.0,0.0,0.0,0.0,0.0,2200.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,5886.0,0.0,1000.0,0.0,0.0,0.0,0.0,2400.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_mortgage_free_wales,savings_property,WALES,2027,30000,0,10000,0,0,0,5686.0,0.0,1000.0,0.0,0.0,0.0,0.0,2200.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,5886.0,0.0,1000.0,0.0,0.0,0.0,0.0,2400.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_mortgage_free_northern_ireland,savings_property,NORTHERN_IRELAND,2027,30000,0,10000,0,0,0,5686.0,0.0,1000.0,0.0,0.0,0.0,0.0,2200.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,5886.0,0.0,1000.0,0.0,0.0,0.0,0.0,2400.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_scotland_finance_0,savings_property,SCOTLAND,2027,60000,0,10000,0,0,0,17377.87,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,0.0,10000.0,0.0,0.0,3210.6,0.0,0.0,17377.87,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,0.0,10000.0,0.0,0.0,3210.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_scotland_finance_4000,savings_property,SCOTLAND,2027,60000,0,10000,4000,0,0,16497.87,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,880.0,10000.0,0.0,0.0,3210.6,0.0,0.0,16417.87,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,960.0,10000.0,0.0,0.0,3210.6,0.0,0.0,-80.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 +property_then_savings_order,savings_property,LONDON,2027,45000,2000,6000,0,0,0,8582.0,630.0,500.0,0.0,0.0,1500.0,0.0,1466.0,0.0,6000.0,0.0,0.0,2594.4,0.0,0.0,8732.0,660.0,500.0,0.0,0.0,1500.0,0.0,1586.0,0.0,6000.0,0.0,0.0,2594.4,0.0,0.0,150.0,30.0,0.0,0.0,0.0,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +trader_salary_30000_expenses_500,trading,LONDON,2027,30000,0,0,0,4000,3500,4086.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,3000.0,1394.4,0.0,0.0,3686.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2500.0,1000.0,1394.4,0.0,0.0,-400.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2000.0,-2000.0,0.0,0.0,0.0 +trader_salary_30000_expenses_2500,trading,LONDON,2027,30000,0,0,0,4000,1500,3786.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1500.0,1394.4,0.0,0.0,3686.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,1000.0,1394.4,0.0,0.0,-100.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,-500.0,0.0,0.0,0.0 +trader_salary_30000_expenses_3500,trading,LONDON,2027,30000,0,0,0,4000,500,3586.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,1394.4,0.0,0.0,3586.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,1394.4,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +trader_salary_60000_expenses_500,trading,LONDON,2027,60000,0,0,0,4000,3500,12632.0,0.0,500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,3000.0,3210.6,0.0,0.0,11832.0,0.0,500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2500.0,1000.0,3210.6,0.0,0.0,-800.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2000.0,-2000.0,0.0,0.0,0.0 +trader_salary_60000_expenses_2500,trading,LONDON,2027,60000,0,0,0,4000,1500,12032.0,0.0,500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1500.0,3210.6,0.0,0.0,11832.0,0.0,500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,1000.0,3210.6,0.0,0.0,-200.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,-500.0,0.0,0.0,0.0 +trader_salary_60000_expenses_3500,trading,LONDON,2027,60000,0,0,0,4000,500,11632.0,0.0,500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,3210.6,0.0,0.0,11632.0,0.0,500.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,3210.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 diff --git a/analysis/uk-budget-2026-income-tax/households.json b/analysis/uk-budget-2026-income-tax/households.json new file mode 100644 index 000000000..182007c95 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/households.json @@ -0,0 +1,2015 @@ +{ + "metadata": { + "generated_at_utc": "2026-10-28T14:37:16.549617+00:00", + "tax_year": "2027–28", + "model_year": 2027, + "versions": { + "policyengine": "6.11.1", + "policyengine-uk": "2.151.0", + "policyengine-core": "3.33.3" + }, + "python": "3.13.14", + "dashboard_comparison": { + "pull_request": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/290", + "commit": "b50787aa75ef5aed36b822c973afa6b569464d55", + "source_file_url": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/b50787aa75ef5aed36b822c973afa6b569464d55/src/uk_budget_data/reforms.py", + "compared_file": "src/uk_budget_data/reforms.py", + "baseline_parameters": { + "gov.hmrc.income_tax.rates.savings.basic": 0.22, + "gov.hmrc.income_tax.rates.savings.higher": 0.42, + "gov.hmrc.income_tax.rates.savings.additional": 0.47, + "gov.hmrc.income_tax.rates.property.basic": 0.22, + "gov.hmrc.income_tax.rates.property.higher": 0.42, + "gov.hmrc.income_tax.rates.property.additional": 0.47, + "gov.hmrc.income_tax.allowances.trading_allowance": 1000 + }, + "reform_parameters": { + "gov.hmrc.income_tax.rates.savings.basic": 0.24, + "gov.hmrc.income_tax.rates.savings.higher": 0.44, + "gov.hmrc.income_tax.rates.savings.additional": 0.49, + "gov.hmrc.income_tax.rates.property.basic": 0.24, + "gov.hmrc.income_tax.rates.property.higher": 0.44, + "gov.hmrc.income_tax.rates.property.additional": 0.49, + "gov.hmrc.income_tax.allowances.trading_allowance": 3000 + }, + "dashboard_builder_verified": true, + "comparison": "Relevant parameter declarations and savings/property builder match the independent flat reform dictionaries; no combined-package modifiers run." + }, + "scope": "Synthetic single adults age 35; no microdata, no behavioural responses or national estimates. Income and expenses held fixed; tax liabilities, not full household net-income changes.", + "assumptions": "No children, pensions, Gift Aid, student loans, capital gains, other tax reliefs, property losses or carried-forward finance costs. Savings are outside ISAs. Trading receipts and profit are both supplied; no connected-party receipts or partnership income. All example benefit totals are checked to be zero.", + "oracle_tolerance_gbp": 0.02, + "warning_filters": "Known household divide/invalid RuntimeWarnings and single-household model decile .values warnings only; no population weights are accessed by this generator." + }, + "reforms": { + "savings_property": { + "gov.hmrc.income_tax.rates.savings.basic": 0.24, + "gov.hmrc.income_tax.rates.savings.higher": 0.44, + "gov.hmrc.income_tax.rates.savings.additional": 0.49, + "gov.hmrc.income_tax.rates.property.basic": 0.24, + "gov.hmrc.income_tax.rates.property.higher": 0.44, + "gov.hmrc.income_tax.rates.property.additional": 0.49 + }, + "trading": { + "gov.hmrc.income_tax.allowances.trading_allowance": 3000 + } + }, + "households": [ + { + "id": "saver_below_allowance", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 30000, + "savings_interest_income": 500 + }, + "independent_oracle": { + "baseline": { + "savings_allowance": 1000, + "savings_income_tax": 0 + }, + "reform": { + "savings_allowance": 1000, + "savings_income_tax": 0 + }, + "change": { + "income_tax": 0 + } + }, + "detail": null, + "baseline": { + "income_tax": 3486.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 3486.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 0.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "saver_basic", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 30000, + "savings_interest_income": 2000 + }, + "independent_oracle": { + "baseline": { + "savings_allowance": 1000, + "savings_income_tax": 220 + }, + "reform": { + "savings_allowance": 1000, + "savings_income_tax": 240 + }, + "change": { + "income_tax": 20 + } + }, + "detail": null, + "baseline": { + "income_tax": 3706.0, + "savings_income_tax": 220.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 1000.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 3726.0, + "savings_income_tax": 240.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 1000.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 20.0, + "savings_income_tax": 20.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "saver_higher", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 60000, + "savings_interest_income": 2000 + }, + "independent_oracle": { + "baseline": { + "savings_allowance": 500, + "savings_income_tax": 630 + }, + "reform": { + "savings_allowance": 500, + "savings_income_tax": 660 + }, + "change": { + "income_tax": 30 + } + }, + "detail": null, + "baseline": { + "income_tax": 12062.0, + "savings_income_tax": 630.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 1500.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 12092.0, + "savings_income_tax": 660.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 1500.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 30.0, + "savings_income_tax": 30.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "saver_additional", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 150000, + "savings_interest_income": 2000 + }, + "independent_oracle": { + "baseline": { + "savings_allowance": 0, + "savings_income_tax": 940 + }, + "reform": { + "savings_allowance": 0, + "savings_income_tax": 980 + }, + "change": { + "income_tax": 40 + } + }, + "detail": null, + "baseline": { + "income_tax": 54643.0, + "savings_income_tax": 940.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 2000.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 5010.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 54683.0, + "savings_income_tax": 980.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 2000.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 5010.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 40.0, + "savings_income_tax": 40.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "saver_crosses_basic_higher", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 49270, + "savings_interest_income": 2000 + }, + "independent_oracle": { + "baseline": { + "savings_allowance": 500, + "savings_income_tax": 530 + }, + "reform": { + "savings_allowance": 500, + "savings_income_tax": 560 + }, + "change": { + "income_tax": 30 + } + }, + "detail": null, + "baseline": { + "income_tax": 7870.0, + "savings_income_tax": 530.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 500.0, + "higher_rate_savings_income": 1000.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 2936.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 7900.0, + "savings_income_tax": 560.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 500.0, + "higher_rate_savings_income": 1000.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 2936.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 30.0, + "savings_income_tax": 30.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "saver_starting_rate", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 15000, + "savings_interest_income": 4000 + }, + "independent_oracle": { + "baseline": { + "savings_allowance": 1000, + "savings_income_tax": 94.6 + }, + "reform": { + "savings_allowance": 1000, + "savings_income_tax": 103.2 + }, + "change": { + "income_tax": 8.600000000000009 + } + }, + "detail": null, + "baseline": { + "income_tax": 580.6, + "savings_income_tax": 94.6, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 2570.0, + "basic_rate_savings_income": 430.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 194.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 589.2, + "savings_income_tax": 103.2, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 2570.0, + "basic_rate_savings_income": 430.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 194.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 8.6, + "savings_income_tax": 8.6, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "saver_scotland_higher", + "policy": "savings_property", + "region": "SCOTLAND", + "person": { + "employment_income": 60000, + "savings_interest_income": 2000 + }, + "independent_oracle": { + "baseline": { + "savings_income_tax": 630 + }, + "reform": { + "savings_income_tax": 660 + }, + "change": { + "income_tax": 30 + } + }, + "detail": null, + "baseline": { + "income_tax": 13807.87, + "savings_income_tax": 630.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 1500.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 13837.87, + "savings_income_tax": 660.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 1500.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 30.0, + "savings_income_tax": 30.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_basic_mortgage", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 30000, + "property_income": 10000, + "property_finance_costs": 4000 + }, + "independent_oracle": { + "baseline": { + "property_income_tax": 2200, + "property_finance_cost_relief": 880, + "income_tax": 4806 + }, + "reform": { + "property_income_tax": 2400, + "property_finance_cost_relief": 960, + "income_tax": 4926 + }, + "change": { + "income_tax": 120 + } + }, + "detail": { + "gross_rent": 12000, + "actual_non_finance_expenses": 2000 + }, + "baseline": { + "income_tax": 4806.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 2200.0, + "property_finance_cost_relief": 880.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 4926.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 2400.0, + "property_finance_cost_relief": 960.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 120.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 200.0, + "property_finance_cost_relief": 80.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_higher_mortgage", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 60000, + "property_income": 10000, + "property_finance_costs": 4000 + }, + "independent_oracle": { + "baseline": { + "property_income_tax": 4200, + "property_finance_cost_relief": 880, + "income_tax": 14752 + }, + "reform": { + "property_income_tax": 4400, + "property_finance_cost_relief": 960, + "income_tax": 14872 + }, + "change": { + "income_tax": 120 + } + }, + "detail": { + "gross_rent": 12000, + "actual_non_finance_expenses": 2000 + }, + "baseline": { + "income_tax": 14752.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 4200.0, + "property_finance_cost_relief": 880.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 14872.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 4400.0, + "property_finance_cost_relief": 960.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 120.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 200.0, + "property_finance_cost_relief": 80.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_additional_mortgage", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 150000, + "property_income": 10000, + "property_finance_costs": 4000 + }, + "independent_oracle": { + "baseline": { + "property_income_tax": 4700, + "property_finance_cost_relief": 880, + "income_tax": 57523 + }, + "reform": { + "property_income_tax": 4900, + "property_finance_cost_relief": 960, + "income_tax": 57643 + }, + "change": { + "income_tax": 120 + } + }, + "detail": { + "gross_rent": 12000, + "actual_non_finance_expenses": 2000 + }, + "baseline": { + "income_tax": 57523.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 4700.0, + "property_finance_cost_relief": 880.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 5010.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 57643.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 4900.0, + "property_finance_cost_relief": 960.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 5010.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 120.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 200.0, + "property_finance_cost_relief": 80.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_crosses_basic_higher_mortgage", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 45000, + "property_income": 10000, + "property_finance_costs": 4000 + }, + "independent_oracle": { + "baseline": { + "property_income_tax": 3146, + "property_finance_cost_relief": 880, + "income_tax": 8752 + }, + "reform": { + "property_income_tax": 3346, + "property_finance_cost_relief": 960, + "income_tax": 8872 + }, + "change": { + "income_tax": 120 + } + }, + "detail": { + "gross_rent": 12000, + "actual_non_finance_expenses": 2000 + }, + "baseline": { + "income_tax": 8752.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 3146.0, + "property_finance_cost_relief": 880.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 2594.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 8872.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 3346.0, + "property_finance_cost_relief": 960.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 2594.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 120.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 200.0, + "property_finance_cost_relief": 80.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_mortgage_free_london", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 30000, + "property_income": 10000 + }, + "independent_oracle": { + "baseline": { + "property_income_tax": 2200 + }, + "reform": { + "property_income_tax": 2400 + }, + "change": { + "income_tax": 200 + } + }, + "detail": null, + "baseline": { + "income_tax": 5686.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 2200.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 5886.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 2400.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 200.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 200.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_mortgage_free_wales", + "policy": "savings_property", + "region": "WALES", + "person": { + "employment_income": 30000, + "property_income": 10000 + }, + "independent_oracle": { + "baseline": { + "property_income_tax": 2200 + }, + "reform": { + "property_income_tax": 2400 + }, + "change": { + "income_tax": 200 + } + }, + "detail": null, + "baseline": { + "income_tax": 5686.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 2200.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 5886.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 2400.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 200.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 200.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_mortgage_free_northern_ireland", + "policy": "savings_property", + "region": "NORTHERN_IRELAND", + "person": { + "employment_income": 30000, + "property_income": 10000 + }, + "independent_oracle": { + "baseline": { + "property_income_tax": 2200 + }, + "reform": { + "property_income_tax": 2400 + }, + "change": { + "income_tax": 200 + } + }, + "detail": null, + "baseline": { + "income_tax": 5686.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 2200.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 5886.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 2400.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 200.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 200.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_scotland_finance_0", + "policy": "savings_property", + "region": "SCOTLAND", + "person": { + "employment_income": 60000, + "property_income": 10000, + "property_finance_costs": 0 + }, + "independent_oracle": { + "change": { + "property_income_tax": 0, + "property_finance_cost_relief": 0.0, + "income_tax": 0 + } + }, + "detail": "Scottish property rates do not change; the UK-wide finance-cost credit rate does.", + "baseline": { + "income_tax": 17377.87, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 4200.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 17377.87, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 4200.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 0.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "landlord_scotland_finance_4000", + "policy": "savings_property", + "region": "SCOTLAND", + "person": { + "employment_income": 60000, + "property_income": 10000, + "property_finance_costs": 4000 + }, + "independent_oracle": { + "change": { + "property_income_tax": 0, + "property_finance_cost_relief": 80.0, + "income_tax": -80 + } + }, + "detail": "Scottish property rates do not change; the UK-wide finance-cost credit rate does.", + "baseline": { + "income_tax": 16497.87, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 4200.0, + "property_finance_cost_relief": 880.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 16417.87, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 4200.0, + "property_finance_cost_relief": 960.0, + "taxable_property_income": 10000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": -80.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 80.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "property_then_savings_order", + "policy": "savings_property", + "region": "LONDON", + "person": { + "employment_income": 45000, + "property_income": 6000, + "savings_interest_income": 2000 + }, + "independent_oracle": { + "baseline": { + "property_income_tax": 1466, + "savings_income_tax": 630, + "income_tax": 8582 + }, + "reform": { + "property_income_tax": 1586, + "savings_income_tax": 660, + "income_tax": 8732 + }, + "change": { + "income_tax": 150 + } + }, + "detail": null, + "baseline": { + "income_tax": 8582.0, + "savings_income_tax": 630.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 1500.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 1466.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 6000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 2594.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 8732.0, + "savings_income_tax": 660.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 1500.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 1586.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 6000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 2594.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 150.0, + "savings_income_tax": 30.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 120.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "trader_salary_30000_expenses_500", + "policy": "trading", + "region": "LONDON", + "person": { + "employment_income": 30000, + "self_employment_gross_receipts": 4000, + "self_employment_income": 3500 + }, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 3000, + "income_tax": 4086.0, + "ni_class_4": 0 + }, + "reform": { + "taxable_self_employment_income": 1000, + "income_tax": 3686.0, + "ni_class_4": 0 + }, + "change": { + "income_tax": -400.0, + "national_insurance": 0 + } + }, + "detail": { + "gross_receipts": 4000, + "actual_expenses": 500 + }, + "baseline": { + "income_tax": 4086.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 500.0, + "taxable_self_employment_income": 3000.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 3686.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 2500.0, + "taxable_self_employment_income": 1000.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": -400.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 2000.0, + "taxable_self_employment_income": -2000.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "trader_salary_30000_expenses_2500", + "policy": "trading", + "region": "LONDON", + "person": { + "employment_income": 30000, + "self_employment_gross_receipts": 4000, + "self_employment_income": 1500 + }, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 1500, + "income_tax": 3786.0, + "ni_class_4": 0 + }, + "reform": { + "taxable_self_employment_income": 1000, + "income_tax": 3686.0, + "ni_class_4": 0 + }, + "change": { + "income_tax": -100.0, + "national_insurance": 0 + } + }, + "detail": { + "gross_receipts": 4000, + "actual_expenses": 2500 + }, + "baseline": { + "income_tax": 3786.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 1500.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 3686.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 500.0, + "taxable_self_employment_income": 1000.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": -100.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 500.0, + "taxable_self_employment_income": -500.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "trader_salary_30000_expenses_3500", + "policy": "trading", + "region": "LONDON", + "person": { + "employment_income": 30000, + "self_employment_gross_receipts": 4000, + "self_employment_income": 500 + }, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 500, + "income_tax": 3586.0, + "ni_class_4": 0 + }, + "reform": { + "taxable_self_employment_income": 500, + "income_tax": 3586.0, + "ni_class_4": 0 + }, + "change": { + "income_tax": 0.0, + "national_insurance": 0 + } + }, + "detail": { + "gross_receipts": 4000, + "actual_expenses": 3500 + }, + "baseline": { + "income_tax": 3586.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 500.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 3586.0, + "savings_income_tax": 0.0, + "savings_allowance": 1000.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 500.0, + "national_insurance": 1394.4, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 0.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "trader_salary_60000_expenses_500", + "policy": "trading", + "region": "LONDON", + "person": { + "employment_income": 60000, + "self_employment_gross_receipts": 4000, + "self_employment_income": 3500 + }, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 3000, + "income_tax": 12632.0, + "ni_class_4": 0 + }, + "reform": { + "taxable_self_employment_income": 1000, + "income_tax": 11832.0, + "ni_class_4": 0 + }, + "change": { + "income_tax": -800.0, + "national_insurance": 0 + } + }, + "detail": { + "gross_receipts": 4000, + "actual_expenses": 500 + }, + "baseline": { + "income_tax": 12632.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 500.0, + "taxable_self_employment_income": 3000.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 11832.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 2500.0, + "taxable_self_employment_income": 1000.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": -800.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 2000.0, + "taxable_self_employment_income": -2000.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "trader_salary_60000_expenses_2500", + "policy": "trading", + "region": "LONDON", + "person": { + "employment_income": 60000, + "self_employment_gross_receipts": 4000, + "self_employment_income": 1500 + }, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 1500, + "income_tax": 12032.0, + "ni_class_4": 0 + }, + "reform": { + "taxable_self_employment_income": 1000, + "income_tax": 11832.0, + "ni_class_4": 0 + }, + "change": { + "income_tax": -200.0, + "national_insurance": 0 + } + }, + "detail": { + "gross_receipts": 4000, + "actual_expenses": 2500 + }, + "baseline": { + "income_tax": 12032.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 1500.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 11832.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 500.0, + "taxable_self_employment_income": 1000.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": -200.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 500.0, + "taxable_self_employment_income": -500.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + }, + { + "id": "trader_salary_60000_expenses_3500", + "policy": "trading", + "region": "LONDON", + "person": { + "employment_income": 60000, + "self_employment_gross_receipts": 4000, + "self_employment_income": 500 + }, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 500, + "income_tax": 11632.0, + "ni_class_4": 0 + }, + "reform": { + "taxable_self_employment_income": 500, + "income_tax": 11632.0, + "ni_class_4": 0 + }, + "change": { + "income_tax": 0.0, + "national_insurance": 0 + } + }, + "detail": { + "gross_receipts": 4000, + "actual_expenses": 3500 + }, + "baseline": { + "income_tax": 11632.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 500.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 11632.0, + "savings_income_tax": 0.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 500.0, + "national_insurance": 3210.6, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "change": { + "income_tax": 0.0, + "savings_income_tax": 0.0, + "savings_allowance": 0.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 0.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 0.0, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 0.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "household_benefits": 0.0 + } + } + ], + "savings_interest_curve": [ + { + "interest": 500, + "basic_baseline_tax": 0.0, + "basic_reform_tax": 0.0, + "basic_tax_increase": 0.0, + "higher_baseline_tax": 0.0, + "higher_reform_tax": 0.0, + "higher_tax_increase": 0.0 + }, + { + "interest": 1000, + "basic_baseline_tax": 0.0, + "basic_reform_tax": 0.0, + "basic_tax_increase": 0.0, + "higher_baseline_tax": 210.0, + "higher_reform_tax": 220.0, + "higher_tax_increase": 10.0 + }, + { + "interest": 1500, + "basic_baseline_tax": 110.0, + "basic_reform_tax": 120.0, + "basic_tax_increase": 10.0, + "higher_baseline_tax": 420.0, + "higher_reform_tax": 440.0, + "higher_tax_increase": 20.0 + }, + { + "interest": 2000, + "basic_baseline_tax": 220.0, + "basic_reform_tax": 240.0, + "basic_tax_increase": 20.0, + "higher_baseline_tax": 630.0, + "higher_reform_tax": 660.0, + "higher_tax_increase": 30.0 + }, + { + "interest": 2500, + "basic_baseline_tax": 330.0, + "basic_reform_tax": 360.0, + "basic_tax_increase": 30.0, + "higher_baseline_tax": 840.0, + "higher_reform_tax": 880.0, + "higher_tax_increase": 40.0 + }, + { + "interest": 3000, + "basic_baseline_tax": 440.0, + "basic_reform_tax": 480.0, + "basic_tax_increase": 40.0, + "higher_baseline_tax": 1050.0, + "higher_reform_tax": 1100.0, + "higher_tax_increase": 50.0 + }, + { + "interest": 3500, + "basic_baseline_tax": 550.0, + "basic_reform_tax": 600.0, + "basic_tax_increase": 50.0, + "higher_baseline_tax": 1260.0, + "higher_reform_tax": 1320.0, + "higher_tax_increase": 60.0 + }, + { + "interest": 4000, + "basic_baseline_tax": 660.0, + "basic_reform_tax": 720.0, + "basic_tax_increase": 60.0, + "higher_baseline_tax": 1470.0, + "higher_reform_tax": 1540.0, + "higher_tax_increase": 70.0 + }, + { + "interest": 4500, + "basic_baseline_tax": 770.0, + "basic_reform_tax": 840.0, + "basic_tax_increase": 70.0, + "higher_baseline_tax": 1680.0, + "higher_reform_tax": 1760.0, + "higher_tax_increase": 80.0 + }, + { + "interest": 5000, + "basic_baseline_tax": 880.0, + "basic_reform_tax": 960.0, + "basic_tax_increase": 80.0, + "higher_baseline_tax": 1890.0, + "higher_reform_tax": 1980.0, + "higher_tax_increase": 90.0 + } + ], + "trading_receipts_curve": [ + { + "receipts": 500, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 0, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 0.0, + "expenses_75_percent_actual_expenses": 375.0, + "expenses_75_percent_baseline_taxable_profit": 0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 1000, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 0, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 0.0, + "expenses_75_percent_actual_expenses": 750.0, + "expenses_75_percent_baseline_taxable_profit": 0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 1500, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 500, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 100.0, + "expenses_75_percent_actual_expenses": 1125.0, + "expenses_75_percent_baseline_taxable_profit": 375.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 75.0 + }, + { + "receipts": 2000, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1000, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 200.0, + "expenses_75_percent_actual_expenses": 1500.0, + "expenses_75_percent_baseline_taxable_profit": 500.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 100.0 + }, + { + "receipts": 2500, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1500, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 300.0, + "expenses_75_percent_actual_expenses": 1875.0, + "expenses_75_percent_baseline_taxable_profit": 625.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 125.0 + }, + { + "receipts": 3000, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2000, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2250.0, + "expenses_75_percent_baseline_taxable_profit": 750.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 150.0 + }, + { + "receipts": 3500, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2500, + "no_expenses_reform_taxable_profit": 500, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2625.0, + "expenses_75_percent_baseline_taxable_profit": 875.0, + "expenses_75_percent_reform_taxable_profit": 500, + "expenses_75_percent_tax_reduction": 75.0 + }, + { + "receipts": 4000, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3000, + "no_expenses_reform_taxable_profit": 1000, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3000.0, + "expenses_75_percent_baseline_taxable_profit": 1000.0, + "expenses_75_percent_reform_taxable_profit": 1000.0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 4500, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3500, + "no_expenses_reform_taxable_profit": 1500, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3375.0, + "expenses_75_percent_baseline_taxable_profit": 1125.0, + "expenses_75_percent_reform_taxable_profit": 1125.0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 5000, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 4000, + "no_expenses_reform_taxable_profit": 2000, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3750.0, + "expenses_75_percent_baseline_taxable_profit": 1250.0, + "expenses_75_percent_reform_taxable_profit": 1250.0, + "expenses_75_percent_tax_reduction": 0.0 + } + ] +} diff --git a/analysis/uk-budget-2026-income-tax/provenance.json b/analysis/uk-budget-2026-income-tax/provenance.json new file mode 100644 index 000000000..e4596e2d8 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/provenance.json @@ -0,0 +1,36 @@ +{ + "as_of": "2026-10-28", + "household_year": 2027, + "package_versions": { + "policyengine": "6.11.1", + "policyengine-uk": "2.151.0", + "policyengine-core": "3.33.3" + }, + "dashboard_reforms": { + "repository": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026", + "pull_request": 290, + "commit": "b50787aa75ef5aed36b822c973afa6b569464d55", + "path": "src/uk_budget_data/reforms.py", + "measures": ["unearned_income_rates_up", "trading_allowance_raise"] + }, + "population": { + "status": "pending_data_access_and_dashboard_budget_day_outputs", + "dataset": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "certificate": "https://github.com/PolicyEngine/policyengine.py/pull/720", + "dashboard_adoption": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/237", + "raw_microdata_used_for_households": false, + "national_results_generated": false, + "forecast": "October 2026 OBR inputs, applied to both baseline and reform when population scoring is run", + "replacement_policy": "Retain this adopted bundle until a later explicitly recorded update; do not silently use the candidate in policyengine.py PR725." + }, + "treasury_costings": { + "source": "https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html", + "table": "6.1", + "units": "GBP million; positive values below indicate revenue for savings/property and cost for trading", + "fiscal_years": ["2026-27", "2027-28", "2028-29", "2029-30", "2030-31", "2031-32"], + "property_row_61_revenue": [0, 35, 575, 435, 445, 455], + "savings_row_62_revenue": [15, 125, 555, 520, 555, 590], + "trading_row_15_cost": [0, 0, 225, 165, 175, 180] + } +} diff --git a/analysis/uk-budget-2026-income-tax/requirements.txt b/analysis/uk-budget-2026-income-tax/requirements.txt new file mode 100644 index 000000000..dcb085836 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/requirements.txt @@ -0,0 +1,3 @@ +policyengine[uk]==6.11.1 +policyengine-uk==2.151.0 +policyengine-core==3.33.3 diff --git a/analysis/uk-budget-2026-income-tax/savings-interest-chart.json b/analysis/uk-budget-2026-income-tax/savings-interest-chart.json new file mode 100644 index 000000000..516fc1488 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/savings-interest-chart.json @@ -0,0 +1,76 @@ +{ + "type": "bar", + "title": "Savings tax increases apply above the Personal Savings Allowance", + "subtitle": "Annual income tax increase; England, salaries £30,000 and £60,000, 2027–28", + "xKey": "interest", + "yLabel": "Extra annual income tax (£)", + "format": { + "prefix": "£", + "decimals": 0 + }, + "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", + "series": [ + { + "key": "basic", + "name": "£30,000 salary", + "color": "negative" + }, + { + "key": "higher", + "name": "£60,000 salary", + "color": "secondary" + } + ], + "data": [ + { + "interest": "£500", + "basic": 0.0, + "higher": 0.0 + }, + { + "interest": "£1,000", + "basic": 0.0, + "higher": 10.0 + }, + { + "interest": "£1,500", + "basic": 10.0, + "higher": 20.0 + }, + { + "interest": "£2,000", + "basic": 20.0, + "higher": 30.0 + }, + { + "interest": "£2,500", + "basic": 30.0, + "higher": 40.0 + }, + { + "interest": "£3,000", + "basic": 40.0, + "higher": 50.0 + }, + { + "interest": "£3,500", + "basic": 50.0, + "higher": 60.0 + }, + { + "interest": "£4,000", + "basic": 60.0, + "higher": 70.0 + }, + { + "interest": "£4,500", + "basic": 70.0, + "higher": 80.0 + }, + { + "interest": "£5,000", + "basic": 80.0, + "higher": 90.0 + } + ] +} diff --git a/analysis/uk-budget-2026-income-tax/savings-interest-curve.csv b/analysis/uk-budget-2026-income-tax/savings-interest-curve.csv new file mode 100644 index 000000000..beb9d0a60 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/savings-interest-curve.csv @@ -0,0 +1,11 @@ +interest,basic_baseline_tax,basic_reform_tax,basic_tax_increase,higher_baseline_tax,higher_reform_tax,higher_tax_increase +500,0.0,0.0,0.0,0.0,0.0,0.0 +1000,0.0,0.0,0.0,210.0,220.0,10.0 +1500,110.0,120.0,10.0,420.0,440.0,20.0 +2000,220.0,240.0,20.0,630.0,660.0,30.0 +2500,330.0,360.0,30.0,840.0,880.0,40.0 +3000,440.0,480.0,40.0,1050.0,1100.0,50.0 +3500,550.0,600.0,50.0,1260.0,1320.0,60.0 +4000,660.0,720.0,60.0,1470.0,1540.0,70.0 +4500,770.0,840.0,70.0,1680.0,1760.0,80.0 +5000,880.0,960.0,80.0,1890.0,1980.0,90.0 diff --git a/analysis/uk-budget-2026-income-tax/trading-allowance-chart.json b/analysis/uk-budget-2026-income-tax/trading-allowance-chart.json new file mode 100644 index 000000000..3e4ec0a6d --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/trading-allowance-chart.json @@ -0,0 +1,76 @@ +{ + "type": "bar", + "title": "Trading allowance: the income tax reduction depends on expenses", + "subtitle": "Annual income tax reduction; England, £30,000 salary, 2027–28", + "xKey": "receipts", + "yLabel": "Annual income tax reduction (£)", + "format": { + "prefix": "£", + "decimals": 0 + }, + "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", + "series": [ + { + "key": "noExpenses", + "name": "No business expenses", + "color": "primary" + }, + { + "key": "highExpenses", + "name": "Expenses equal 75% of receipts", + "color": "secondary" + } + ], + "data": [ + { + "receipts": "£500", + "noExpenses": 0.0, + "highExpenses": 0.0 + }, + { + "receipts": "£1,000", + "noExpenses": 0.0, + "highExpenses": 0.0 + }, + { + "receipts": "£1,500", + "noExpenses": 100.0, + "highExpenses": 75.0 + }, + { + "receipts": "£2,000", + "noExpenses": 200.0, + "highExpenses": 100.0 + }, + { + "receipts": "£2,500", + "noExpenses": 300.0, + "highExpenses": 125.0 + }, + { + "receipts": "£3,000", + "noExpenses": 400.0, + "highExpenses": 150.0 + }, + { + "receipts": "£3,500", + "noExpenses": 400.0, + "highExpenses": 75.0 + }, + { + "receipts": "£4,000", + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": "£4,500", + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": "£5,000", + "noExpenses": 400.0, + "highExpenses": 0.0 + } + ] +} diff --git a/analysis/uk-budget-2026-income-tax/trading-receipts-curve.csv b/analysis/uk-budget-2026-income-tax/trading-receipts-curve.csv new file mode 100644 index 000000000..32b0d7dee --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/trading-receipts-curve.csv @@ -0,0 +1,11 @@ +receipts,no_expenses_actual_expenses,no_expenses_baseline_taxable_profit,no_expenses_reform_taxable_profit,no_expenses_tax_reduction,expenses_75_percent_actual_expenses,expenses_75_percent_baseline_taxable_profit,expenses_75_percent_reform_taxable_profit,expenses_75_percent_tax_reduction +500,0,0,0,0.0,375.0,0,0,0.0 +1000,0,0,0,0.0,750.0,0,0,0.0 +1500,0,500,0,100.0,1125.0,375.0,0,75.0 +2000,0,1000,0,200.0,1500.0,500.0,0,100.0 +2500,0,1500,0,300.0,1875.0,625.0,0,125.0 +3000,0,2000,0,400.0,2250.0,750.0,0,150.0 +3500,0,2500,500,400.0,2625.0,875.0,500,75.0 +4000,0,3000,1000,400.0,3000.0,1000.0,1000.0,0.0 +4500,0,3500,1500,400.0,3375.0,1125.0,1125.0,0.0 +5000,0,4000,2000,400.0,3750.0,1250.0,1250.0,0.0 diff --git a/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax.svg b/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax.svg new file mode 100644 index 000000000..2fef7afc3 --- /dev/null +++ b/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax.svg @@ -0,0 +1,56 @@ + + Savings and property income tax + UK Autumn Budget 2026 raises the savings and property income tax rates scheduled for April 2027 from 22, 42 and 47 percent to 24, 44 and 49 percent. The property rates apply in England, Wales and Northern Ireland. + + + + + + + + + + + + + + + + + + + + + + + + + UK Autumn Budget 2026 + Savings and property + income tax + + Basic rate + 22% + + 24% + Before / after Budget 2026 + + Higher rate + 42% + + 44% + Before / after Budget 2026 + + Additional rate + 47% + + 49% + Before / after Budget 2026 + From 6 April 2027 · Savings: UK · Property: England, Wales and Northern Ireland + diff --git a/app/public/assets/posts/uk-autumn-budget-2026-trading-allowance.svg b/app/public/assets/posts/uk-autumn-budget-2026-trading-allowance.svg new file mode 100644 index 000000000..c1eea2abc --- /dev/null +++ b/app/public/assets/posts/uk-autumn-budget-2026-trading-allowance.svg @@ -0,0 +1,45 @@ + + The trading allowance rises to £3,000 + UK Autumn Budget 2026 raises the annual trading allowance from 1,000 pounds to 3,000 pounds from 6 April 2027. Eligible individuals choose the allowance or actual expenses. + + + + + + + + + + + + + + + + + + + + + + + + + UK Autumn Budget 2026 + The trading allowance + rises to £3,000 + + + Current annual allowance + £1,000 + + From 6 April 2027 + £3,000 + Eligible trading and miscellaneous income · Choose the allowance or actual expenses + diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md new file mode 100644 index 000000000..1e8e5d52f --- /dev/null +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md @@ -0,0 +1,154 @@ +The Autumn Budget 2026 increases the basic, higher and additional income tax rates on savings and property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%**. Savings rates apply across the UK. The property rates apply in England, Wales and Northern Ireland. Dividend rates remain unchanged. These are the changes announced in the [Budget 2026 document](https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html). + +In the examples below, a basic-rate saver with £2,000 of annual interest pays £20 more a year. A landlord with £10,000 of property profit and £4,000 of mortgage interest pays £120 more. + +This post examines this provision on its own. The [UK Autumn Budget 2026 dashboard](https://uk-autumn-budget-2026.vercel.app/uk/autumn-budget-2026) shows how it combines with the other announced measures. We cover the trading allowance increase in a [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance). + +## What changes in April 2027? + +Budget 2025 had already set savings and property rates at 22%, 42% and 47% from April 2027. The comparison here therefore measures the additional two-point increase announced in 2026, using the existing 2027 rules as the baseline. + +| Income tax band | Already scheduled for 2027–28 | Budget 2026 rate | Change | +| --- | ---: | ---: | ---: | +| Basic | 22% | 24% | +2 percentage points | +| Higher | 42% | 44% | +2 percentage points | +| Additional | 47% | 49% | +2 percentage points | + +The [Budget 2025 technical note](https://www.gov.uk/government/publications/changes-to-tax-rates-for-property-savings-and-dividend-income/change-to-tax-rates-for-property-savings-and-dividend-income-technical-note) sets the ordering from April 2027: employment, pension and trading income first; property next; savings after that; and dividends last. Allowances first reduce income other than property, savings or dividends. Taxable income then fills the bands in that order, so employment and rental income can push savings interest into a higher band. + +## Savers pay the higher rates on interest above their allowances + +The Personal Savings Allowance remains £1,000 for basic-rate taxpayers, £500 for higher-rate taxpayers and £0 for additional-rate taxpayers. People with low other income can also qualify for a starting rate of 0% on up to £5,000 of savings interest. These allowances depend on total income, as [HMRC's savings guidance](https://www.gov.uk/apply-tax-free-interest-on-savings/how-much-is-tax-free) explains. Interest earned inside an ISA remains exempt from income tax. + +These hypothetical adults live in England and receive only the wages and interest shown. Their wages use the Personal Allowance, and none qualifies for the starting rate for savings. The table isolates income tax on interest. + +| Annual employment income | Annual savings interest | Personal Savings Allowance | Interest taxed above 0% | Tax before the Budget change | Tax after | Extra annual tax | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| £30,000 | £500 | £1,000 | £0 | £0 | £0 | £0 | +| £30,000 | £2,000 | £1,000 | £1,000 | £220 | £240 | £20 | +| £60,000 | £2,000 | £500 | £1,500 | £630 | £660 | £30 | + +For the basic-rate example, £2,000 − £1,000 = £1,000 faces the savings basic rate: £1,000 × 22% = £220 before, against £1,000 × 24% = £240 after. The higher-rate example pays an extra £1,500 × 2% = £30. + + +The chart varies annual interest for the same two salaries. At these income levels, each additional £500 of interest above the allowance adds £10 to the tax increase. + +```chart +{ + "type": "bar", + "title": "Savings tax increases apply above the Personal Savings Allowance", + "subtitle": "Annual income tax increase; England, salaries £30,000 and £60,000, 2027–28", + "xKey": "interest", + "yLabel": "Extra annual income tax (£)", + "format": { + "prefix": "£", + "decimals": 0 + }, + "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", + "series": [ + { + "key": "basic", + "name": "£30,000 salary", + "color": "negative" + }, + { + "key": "higher", + "name": "£60,000 salary", + "color": "secondary" + } + ], + "data": [ + { + "interest": "£500", + "basic": 0.0, + "higher": 0.0 + }, + { + "interest": "£1,000", + "basic": 0.0, + "higher": 10.0 + }, + { + "interest": "£1,500", + "basic": 10.0, + "higher": 20.0 + }, + { + "interest": "£2,000", + "basic": 20.0, + "higher": 30.0 + }, + { + "interest": "£2,500", + "basic": 30.0, + "higher": 40.0 + }, + { + "interest": "£3,000", + "basic": 40.0, + "higher": 50.0 + }, + { + "interest": "£3,500", + "basic": 50.0, + "higher": 60.0 + }, + { + "interest": "£4,000", + "basic": 60.0, + "higher": 70.0 + }, + { + "interest": "£4,500", + "basic": 70.0, + "higher": 80.0 + }, + { + "interest": "£5,000", + "basic": 80.0, + "higher": 90.0 + } + ] +} +``` + +## Landlords' mortgage-interest relief rises too + +For individual residential landlords, mortgage interest normally produces a tax reduction rather than a deduction from rental profits. The reduction is limited by finance costs, property profits, adjusted total income and the tax liability. [HMRC's explanation of residential finance-cost relief](https://www.gov.uk/guidance/changes-to-tax-relief-for-residential-landlords-how-its-worked-out-including-case-studies) describes these limits. + +From April 2027 the relief follows the property basic rate. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. + +Consider two adults in England, each with £12,000 of rent, £2,000 of allowable non-finance expenses and £4,000 of qualifying mortgage interest. Deducting actual non-finance expenses leaves £10,000 of property profit. Both can use the full finance-cost reduction. + +| Calculation, 2027–28 | £30,000 salary: before | £30,000 salary: after | £60,000 salary: before | £60,000 salary: after | +| --- | ---: | ---: | ---: | ---: | +| Property profit | £10,000 | £10,000 | £10,000 | £10,000 | +| Rate on that profit | 22% | 24% | 42% | 44% | +| Tax before finance-cost relief | £2,200 | £2,400 | £4,200 | £4,400 | +| Finance-cost reduction | £880 | £960 | £880 | £960 | +| Tax attributable to property | £1,320 | £1,440 | £3,320 | £3,440 | +| Extra annual income tax | — | £120 | — | £120 | + +Both pay £200 more before relief, while their finance-cost reduction rises by £4,000 × 2% = £80. Their net increase is £200 − £80 = £120. A mortgage-free landlord with the same profit pays £200 more. Both tax bands rise by two points, explaining the identical increases despite different starting liabilities. + +The property **rate** increase excludes Scottish taxpayers, whose rental income follows Scottish rules. Finance-cost relief is a separate calculation. The [Finance Act 2026 amendment](https://www.legislation.gov.uk/ukpga/2026/11/schedule/1/paragraph/40/enacted) ties it to the UK property basic rate without a Scottish exception. Applying that rule, a Scottish landlord able to use the full reduction on £4,000 of eligible finance costs receives £80 more relief, reducing their income tax by £80 if nothing else changes. A mortgage-free Scottish landlord has no change from this measure. The savings increase still applies across the UK. + +## The Treasury forecasts revenue of £1.13 billion in 2028–29 + +The Treasury costs the savings and property changes separately. Their sum reaches £1,130 million in 2028–29 and £1,045 million in 2031–32. + +| Exchequer revenue, £ million | 2026–27 | 2027–28 | 2028–29 | 2029–30 | 2030–31 | 2031–32 | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| Property income rates | 0 | 35 | 575 | 435 | 445 | 455 | +| Savings income rates | 15 | 125 | 555 | 520 | 555 | 590 | +| Combined | 15 | 160 | 1,130 | 955 | 1,000 | 1,045 | + +These government receipts forecasts differ from annual household liabilities. The [Treasury policy costings, #page 74-75](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74) allow for some landlords incorporating and savers moving funds into tax-advantaged products such as ISAs. A static calculation holds those choices fixed. + +## Methodology + +The examples isolate the newly announced 2027–28 changes, including finance-cost relief, holding income and expenses constant. They include no pension contributions, Gift Aid, student loans or other reliefs. They show tax attributable to each income source, rather than household net income after benefits. + +The examples use `policyengine.py` 6.11.1 with PolicyEngine UK 2.151.0 and core 3.33.3, matching the pre-Budget policy baseline and parameter changes in the dashboard's [`unearned_income_rates_up` measure](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/b50787aa75ef5aed36b822c973afa6b569464d55/src/uk_budget_data/reforms.py). The calculations check tax changes against independent arithmetic. + +This draft reports hypothetical examples and Treasury forecasts. PolicyEngine national revenue, affected-person and decile estimates are pending the population run. That run is pinned to the dashboard's certified national dataset `a6299504`; population forecast inputs and model-coverage limits must accompany its results. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md b/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md new file mode 100644 index 000000000..d82f34cad --- /dev/null +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md @@ -0,0 +1,149 @@ +The [Autumn Budget 2026](https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html) announces an increase in the trading allowance from £1,000 to £3,000 from 6 April 2027. The allowance covers eligible trading and miscellaneous income. For an employee paying 20% income tax on their side income, the extra £2,000 deduction can reduce annual income tax by £400. The reduction depends on receipts, expenses and how much tax the individual would otherwise pay. + +This post examines that measure on its own. Our [Budget dashboard](https://uk-autumn-budget-2026.vercel.app/uk/autumn-budget-2026) places it alongside the other announced tax and benefit changes. We cover the savings and property income tax increases in a [separate explainer](/uk/research/uk-autumn-budget-2026-savings-property-income-tax). + +## How the allowance works + +The allowance is an alternative to deducting actual business expenses. Gross receipts are the money received before expenses; profit is what remains after those expenses. A person with £4,000 of receipts and £500 of allowable expenses has £3,500 of profit before considering the allowance. + +Under [HMRC's trading allowance guidance](https://www.gov.uk/guidance/tax-free-allowances-on-property-and-trading-income), an eligible person can choose the allowance or actual expenses. They cannot deduct both against the same receipts. If receipts are within the allowance, full relief can make the taxable amount zero. The allowance cannot create a tax loss. + +There is one allowance per individual across their eligible trades and miscellaneous income, rather than a separate allowance for each activity. The allocation between sources follows [section 783AK of the Income Tax (Trading and Other Income) Act 2005](https://www.legislation.gov.uk/ukpga/2005/5/section/783AK). The separate property income allowance does not increase under this measure. + +## Three people with the same receipts + +Consider three hypothetical single adults in England in 2027–28. Each earns £30,000 from employment and receives £4,000 from a side business. They have no other income, dependants, student loan repayments or benefit entitlements. Their trading profits remain in the 20% income tax band. Their costs differ. + +The table isolates income tax on the side business, holding receipts and expenses fixed. + +| Annual side-business receipts | Actual expenses | Taxable amount under current rules | Taxable amount under new rules | Income tax before | Income tax after | Annual tax reduction | +| --- | --- | --- | --- | --- | --- | --- | +| £4,000 | £500 | £3,000 | £1,000 | £600 | £200 | £400 | +| £4,000 | £2,500 | £1,500 | £1,000 | £300 | £200 | £100 | +| £4,000 | £3,500 | £500 | £500 | £100 | £100 | £0 | + +In the first case, the allowance exceeds expenses under both rules. Taxable income falls from £4,000 − £1,000 = £3,000 to £4,000 − £3,000 = £1,000. The tax reduction is £2,000 × 20% = £400. + +In the second case, actual expenses provide the larger deduction under current law. The £3,000 allowance then exceeds those £2,500 expenses by £500, reducing tax by £500 × 20% = £100. + +In the third case, actual expenses exceed both allowances. The individual continues to deduct £3,500, so taxable income and tax do not change. + +At a 40% marginal rate, the same calculations give reductions of £800, £200 and £0, assuming no tax-band changes or other interactions. + +## From £500 to £5,000 of side income + +The chart varies gross receipts for the same £30,000 employee. One series assumes no business expenses; the other assumes expenses equal 75% of receipts. Each calculation chooses the larger deduction in each scenario. + +```chart +{ + "type": "bar", + "title": "Trading allowance: the income tax reduction depends on expenses", + "subtitle": "Annual income tax reduction; England, £30,000 salary, 2027–28", + "xKey": "receipts", + "yLabel": "Annual income tax reduction (£)", + "format": { + "prefix": "£", + "decimals": 0 + }, + "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", + "series": [ + { + "key": "noExpenses", + "name": "No business expenses", + "color": "primary" + }, + { + "key": "highExpenses", + "name": "Expenses equal 75% of receipts", + "color": "secondary" + } + ], + "data": [ + { + "receipts": "£500", + "noExpenses": 0.0, + "highExpenses": 0.0 + }, + { + "receipts": "£1,000", + "noExpenses": 0.0, + "highExpenses": 0.0 + }, + { + "receipts": "£1,500", + "noExpenses": 100.0, + "highExpenses": 75.0 + }, + { + "receipts": "£2,000", + "noExpenses": 200.0, + "highExpenses": 100.0 + }, + { + "receipts": "£2,500", + "noExpenses": 300.0, + "highExpenses": 125.0 + }, + { + "receipts": "£3,000", + "noExpenses": 400.0, + "highExpenses": 150.0 + }, + { + "receipts": "£3,500", + "noExpenses": 400.0, + "highExpenses": 75.0 + }, + { + "receipts": "£4,000", + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": "£4,500", + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": "£5,000", + "noExpenses": 400.0, + "highExpenses": 0.0 + } + ] +} +``` + +With no expenses, the tax reduction rises between £1,000 and £3,000 of receipts, then stays at £400. With expenses equal to 75% of receipts, the reduction reaches £150 at £3,000 of receipts and falls to zero at £4,000: actual expenses then equal the new £3,000 allowance. + +## National Insurance and benefit interactions + +[HMRC's National Insurance guidance](https://www.gov.uk/hmrc-internal-manuals/business-income-manual/bim86052) confirms that the trading allowance also reduces the profits used to calculate Class 4 contributions. However, all the side-business examples above remain below the [£12,570 Class 4 lower profits limit](https://www.gov.uk/government/publications/rates-and-allowances-national-insurance-contributions/rates-and-allowances-national-insurance-contributions). They have no Class 4 reduction; employment National Insurance is unchanged. + +Universal Credit uses separate self-employment income rules. The allowance itself does not reduce income for Universal Credit purposes, as HMRC's allowance guidance explains. A full household calculation must also account for any change in tax paid and the benefit rules that apply to that household. + +The allowance is unavailable for partnership income and certain connected-party receipts, including income from an individual's employer or a company they control. [HMRC's exclusions](https://www.gov.uk/hmrc-internal-manuals/business-income-manual/bim86030) describe those restrictions. + +## Treasury costing + +Table 6.1, row 15, gives the following official forecast. These are reductions in Exchequer receipts, expressed below as positive costs; they are not PolicyEngine microsimulation estimates. + +| Fiscal year | Treasury cost (£ million) | +| --- | --- | +| 2026–27 | 0 | +| 2027–28 | 0 | +| 2028–29 | 225 | +| 2029–30 | 165 | +| 2030–31 | 175 | +| 2031–32 | 180 | + +The effective date remains 6 April 2027 even though the Treasury records no receipts effect in 2027–28. A household's tax-year liability and the government's forecast of receipts by fiscal year are different quantities. + +## Methodology and coverage + +The worked examples isolate the allowance increase and use hypothetical households. They hold earnings, receipts and expenses fixed, assume the individual selects the larger deduction, and exclude losses, behavioural responses and other tax or benefit interactions. + +The household calculations use `policyengine.py` 6.11.1 with PolicyEngine UK 2.151.0 and core 3.33.3, matching the dashboard's `trading_allowance_raise` measure. They supply both gross receipts and profit so the model can represent actual expenses, and check the resulting tax changes against independent arithmetic. + +In the population data, gross receipts are unavailable. The pinned model's [deduction calculation](https://github.com/PolicyEngine/policyengine-uk/blob/2.151.0/policyengine_uk/variables/gov/hmrc/income_tax/allowances/trading_allowance_deduction.py) uses an approximation that can overstate or understate the reform's effect for individual records. It also does not apply this allowance to its separate miscellaneous-income input, although eligible miscellaneous income is within the announced policy. These coverage limits matter when interpreting national results. + +This draft reports hypothetical examples and Treasury forecasts. PolicyEngine national cost, affected-person and decile estimates are pending the population run, pinned to the dashboard's certified national dataset `a6299504`. diff --git a/app/src/data/posts/posts.json b/app/src/data/posts/posts.json index adc5aa3ae..50f3c400b 100644 --- a/app/src/data/posts/posts.json +++ b/app/src/data/posts/posts.json @@ -1,4 +1,22 @@ [ + { + "title": "Autumn Budget 2026: higher tax on savings and property income", + "description": "Worked examples of the additional two percentage point increase from April 2027, including savings allowances and landlords' mortgage-interest relief.", + "date": "2026-10-28 14:00:00", + "tags": ["uk", "policy", "tax", "autumn-budget"], + "authors": ["ziming-hua"], + "filename": "uk-autumn-budget-2026-savings-property-income-tax.md", + "image": "uk-autumn-budget-2026-savings-property-income-tax.svg" + }, + { + "title": "Autumn Budget 2026: raising the trading allowance", + "description": "The trading allowance rises from £1,000 to £3,000. We show how receipts and actual expenses determine the income tax reduction.", + "date": "2026-10-28 14:00:00", + "tags": ["uk", "policy", "tax", "autumn-budget"], + "authors": ["ziming-hua"], + "filename": "uk-autumn-budget-2026-trading-allowance.md", + "image": "uk-autumn-budget-2026-trading-allowance.svg" + }, { "title": "High value council tax surcharge: revenue by constituency", "description": "We estimate the surcharge raises \u00a3410 million in 2028-29 from owner-occupied main residences in England before behavioural responses, 39% of it from 10 constituencies.", From 7f90092fa6e6f28f68b419c4edf1bef166d851b9 Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 10:54:17 -0400 Subject: [PATCH 02/24] Add provisional dashboard population results to draft explainers --- analysis/uk-budget-2026-income-tax/README.md | 18 +- .../population-preview/manifest.json | 198 +++ .../population-preview/summary.json | 1189 +++++++++++++++++ .../budgetary_impact.csv | 7 + .../distributional_impact.csv | 61 + .../trading_allowance_raise/metrics.csv | 7 + .../trading_allowance_raise/receipt.json | 453 +++++++ .../winners_losers.csv | 67 + .../budgetary_impact.csv | 7 + .../distributional_impact.csv | 61 + .../unearned_income_rates_up/metrics.csv | 7 + .../unearned_income_rates_up/receipt.json | 173 +++ .../winners_losers.csv | 67 + .../uk-budget-2026-income-tax/provenance.json | 76 +- .../verify_population_preview.py | 93 ++ ...budget-2026-savings-property-income-tax.md | 35 +- ...uk-autumn-budget-2026-trading-allowance.md | 50 +- 17 files changed, 2541 insertions(+), 28 deletions(-) create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/manifest.json create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/summary.json create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/budgetary_impact.csv create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/distributional_impact.csv create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/metrics.csv create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/receipt.json create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/winners_losers.csv create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/budgetary_impact.csv create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/distributional_impact.csv create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/metrics.csv create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/receipt.json create mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/winners_losers.csv create mode 100644 analysis/uk-budget-2026-income-tax/verify_population_preview.py diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index b59c5b21d..f063e833c 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -22,13 +22,23 @@ The article chart blocks reproduce `savings-interest-chart.json` and `trading-al Retain the dashboard's adopted `policyengine` 6.11.1 bundle, with UK 2.151.0, core 3.33.3 and national data cut `a6299504`. The certificate, full dataset ID and checksum are recorded in `provenance.json`. The newer candidate in policyengine.py PR725 is awaiting certification/adoption. A future update must change the package and dataset provenance together and regenerate the analysis. -No population microdata were available for this draft. It contains no PolicyEngine national estimates, decile results or affected-person counts. Treasury forecasts are labelled separately and are not a substitute for those calculations. The publicly committed dashboard results checked on 28 October did not yet include these two Budget-day measures; older candidate savings/property charts must not be relabelled as the announced policy. +No population microdata were downloaded locally. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. Vahid subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The drafts now reuse its digest-addressed public aggregate outputs, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. -When access and certified Budget-day outputs are available, use the national dataset above and the dashboard's October 2026 OBR forecast wrapper on both baseline and reform. Score each provision separately. Reconcile fiscal-year Treasury receipts with modelled tax-year liabilities, documenting behavioural and timing differences. Retain survey confidentiality; publish aggregates only. +The provisional national outputs use the exact dataset above with the dashboard's October 2026 OBR forecast wrapper on both baseline and reform. Each provision is scored separately. The source commit is `0d9dccb2`; its reform definitions and October forecast input file match household reference commit `b50787aa` byte for byte. Series not updated by the overlay retain the model's March forecast path; the underlying calibration remains pre-Budget. + +Verify the snapshot without downloading microdata or any other files: + +```sh +python3 analysis/uk-budget-2026-income-tax/verify_population_preview.py +``` + +The verifier checks the eight CSV hashes, certified execution identity, dataset checksum, provisional status, disclosure floor and complete decile grids. It writes `population-preview/summary.json`. Both measures are `provisional` and their reconciliation is `awaiting_source`; passing the disclosure floor does not mean final review approval. The snapshots are public aggregates only. + +Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipts with the model's annual government-balance effects, documenting behavioural, timing and coverage differences. Do not attribute a particular discrepancy to one of those factors before reconciliation. No separate winner/loser shares or absolute affected-person counts are exported. The field `people_affected` is a percentage, using an absolute household-income-change threshold of more than 0.01%, not millions of people or a taxpayer count. ## Checks before publication -- Add the outstanding national revenue, affected-person and decile results requested in the team brief, with provenance and model-coverage limits. +- Replace or confirm the provisional national revenue and decile results after final reconciliation. Add absolute affected-person counts and separate winner/loser shares when the producer exports those quantities; do not infer them from average changes or the affected percentage. - Confirm the treatment of Scottish landlords' finance-cost relief against the final Budget implementation. The pinned model links that relief to the UK property basic rate even for Scotland. - Check trading allowance coverage: gross receipts and actual expenses are needed to model the deduction choice; the pinned model does not apply the allowance to its separate miscellaneous-income input. - Verify the final public dashboard link and add links to these explainers within the dashboard. The source checkout's README supplies the current Vercel dashboard URL. @@ -40,4 +50,4 @@ The two articles use the site's native chart blocks and cover assets. No runtime `make format`, `make lint`, `make typecheck` and `make test` passed. The tests ran on Node 26.12.1: 6,042 app tests and 508 website tests passed, with 10 app tests skipped by the existing suite. After inserting the final chart data, the chart-parser and post-metadata checks passed again (18 tests). All 23 household comparisons and 20 curve points passed independent arithmetic checks. -Browser access to the local preview was declined, so visual preview remains outstanding. The SVG cover XML and native chart specs were validated, but this does not confirm page layout at desktop or mobile widths. +After adding the provisional national sections, snapshot verification and the article/chart checks passed again. Browser access to the local preview was declined, so visual preview remains outstanding. The SVG cover XML and native chart specs were validated, but this does not confirm page layout at desktop or mobile widths. diff --git a/analysis/uk-budget-2026-income-tax/population-preview/manifest.json b/analysis/uk-budget-2026-income-tax/population-preview/manifest.json new file mode 100644 index 000000000..85018bfdf --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/manifest.json @@ -0,0 +1,198 @@ +{ + "basis": { + "calibration": { + "source": "the certified dataset pinned by the installed policyengine bundle: Microcosm UK from policyengine 6.10.1, policyengine-uk-data before it", + "status": "pre_budget", + "vintage": "as pinned by the installed bundle" + }, + "forecast": { + "source": "OBR EFO October 2026", + "status": "updated", + "vintage": "OBR Economic and fiscal outlook, October 2026 (Annex A, Tables A.1 and A.3), applied over policyengine-uk's March 2026 growth rates by src/uk_budget_data/forecast/obr_october_2026.json" + }, + "notes": "The forecast is rebased on the Budget's OBR forecast: every simulation, baseline and reform alike, is built on the October 2026 growth rates in src/uk_budget_data/forecast/obr_october_2026.json (CPI, RPI, average earnings, house prices; the September 2027 CPI gap). Series that file does not list keep the March 2026 path the installed policyengine-uk ships; the receipt records the exact model version." + }, + "budget": { + "date": "2026-10-28", + "id": "uk-autumn-budget-2026" + }, + "combined": {}, + "execution": { + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "identity": { + "certificate": { + "bundle_version": "6.11.1", + "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", + "certified_by": "policyengine.py bundle certification", + "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "certified_for_core_version": "3.33.3", + "certified_for_model_version": "2.151.0", + "compatibility_basis": "built_with_model_package", + "country_id": "uk" + }, + "certification_status": "certified", + "core": { + "name": "policyengine-core", + "version": "3.33.3" + }, + "country_id": "uk", + "data": { + "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "build_model_version": "2.151.0", + "data_package": "microcosm-data", + "dataset": "microcosm_uk_2024_25", + "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_version": "0.1.0" + }, + "model": { + "name": "policyengine-uk", + "version": "2.151.0" + }, + "schema_version": 1, + "wrapper": { + "name": "policyengine", + "version": "6.11.1" + } + } + }, + "flat_aliases": {}, + "flat_files": {}, + "measures": { + "domestic_electricity_zero_vat": { + "artifact": "artifacts/domestic_electricity_zero_vat/4b0323419c2ff3c6", + "artifact_sha256": "4b0323419c2ff3c650e9b596492711d606e4c6b93cbb47b20f255706f451ee4a", + "data_limits": [], + "description": "VAT on domestic electricity is 0% instead of 5% from 1 October 2026 to 30 June 2027: in Great Britain to March 2027 and across the UK from April 2027. The model's baseline has no zero rate, so the measure covers the whole period, as the Treasury costs it. It applies to electricity spending only. 2026-27 carries the October to March share of a year's electricity use (about 57%), not a share of its days; 2027-28 its 91 days of 366.", + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "name": "Zero VAT on domestic electricity", + "outputs_sha256": "ccfdd7e4fd79735f382cfc95b6323a3331097e4180ec9b1148042d506699b94e", + "receipt_sha256": "f2535334472c0c38387923c0fe3cf72e928a90a107e32005b7098eb776cdf7f6", + "reconciliation": { + "responsiveness_status": "responsive", + "summary_status": "awaiting_source" + }, + "status": "provisional", + "unsupported_years": [], + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "fuel_duty_rise_deferral": { + "artifact": "artifacts/fuel_duty_rise_deferral/69cf8fc0ef40d810", + "artifact_sha256": "69cf8fc0ef40d810339521eec3efddf9e297da87ecadc22c0fb4b1aad1ce2378", + "data_limits": [], + "description": "The 5p cut in fuel duty is kept: the main rate stays at 52.95p a litre to 30 June 2027, so the rise due on 1 January 2027 and the March and April 2027 steps do not happen. From 1 July 2027 it returns to current law's 60.59p a litre, rising with RPI each April. Rates are day-weighted to fiscal years, and the VAT on the lower pump price is included.", + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "name": "Fuel duty cut extended", + "outputs_sha256": "f035235441044cfb56f3571aba6ec60b2526406338426da61f45e79e8ffa1fc1", + "receipt_sha256": "8f70fcd277ecbb80982e876b54aec7dcfb1fa765d515165def1ddfcfdd1ac194", + "reconciliation": { + "responsiveness_status": "responsive", + "summary_status": "awaiting_source" + }, + "status": "provisional", + "unsupported_years": [], + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "household_energy_payment_2026": { + "artifact": "artifacts/household_energy_payment_2026/ff7e323670ad8bba", + "artifact_sha256": "ff7e323670ad8bba5b5aed3ec5d3a7d6d68a13a1e28d9d1df068812857c6a496", + "attestation": { + "checker": "PREVIEW ONLY \u2014 not a signature (checker)", + "measure_id": "household_energy_payment_2026", + "reason": "PREVIEW ONLY \u2014 not a signature. Local preview placeholder; nobody has reviewed this receipt. Checked budget_measures.household_energy_payment_2026: in 2026-27 only it adds the payment to ebr_council_tax_rebate for households in England whose council tax band is A, B, C or D, leaving every other household and year at the native amount. The receipt's outputs were compared with the hand-computed households in tests/test_reforms.py.", + "receipt_sha256": "920cbb9051d16e1ca77c4d0c517fbbd93615b8cebef60a4772adf10e1c1fd44a", + "released_at": "2026-10-28T14:40:00+00:00", + "second": "PREVIEW ONLY \u2014 not a signature (second)" + }, + "data_limits": [], + "description": "A one-off \u00a3100 payment from January 2027 to each household in England in property valuation bands A to D (the lowest four of England's eight), up to 20 million households, paid into bank accounts and counted as household income in 2026-27. Scotland, Wales and Northern Ireland receive a share of the funding instead, which is not modelled.", + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "name": "Household Energy Payment", + "outputs_sha256": "07f3c82d557a12ed13094291e5b6c30666447fef161cace174a93cd98af11cca", + "receipt_sha256": "c1bbc5e6e34a2dc78fd922d73b0ed387eda37a8dce56b5ed5d291abaa7a2a63b", + "reconciliation": { + "responsiveness_status": "responsive", + "summary_status": "awaiting_source" + }, + "status": "provisional", + "unsupported_years": [], + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "trading_allowance_raise": { + "artifact": "artifacts/trading_allowance_raise/230c4665427e0bb1", + "artifact_sha256": "230c4665427e0bb1a8ab3c951753252190ff6f8fe86207e5d336b0616e465baf", + "data_limits": [], + "description": "From 6 April 2027 the trading allowance, which relieves trading receipts in place of actual expenses, rises from \u00a31,000 to \u00a33,000, for income tax and Class 4 National Insurance. Without gross receipts in the data, a profit within the allowance is treated as fully relieved, so the cost may be overstated.", + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "name": "Trading allowance raised to \u00a33,000", + "outputs_sha256": "c98e404df6c02459d8d1c10e8de5417ac538fd7876f2048f7bfcd0c48598d7bc", + "receipt_sha256": "12e5b9f9ecaa3c9f6e967ad30a71c26e0156a8468a8edde5377a1400393a0f3c", + "reconciliation": { + "responsiveness_status": "responsive", + "summary_status": "awaiting_source" + }, + "status": "provisional", + "unsupported_years": [], + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "unearned_income_rates_up": { + "artifact": "artifacts/unearned_income_rates_up/8bd7d211ae66c19d", + "artifact_sha256": "8bd7d211ae66c19d63f7f47dd1a32645834f41270588ec7a87bcfd700092d242", + "data_limits": [], + "description": "From 6 April 2027 the income tax rates on savings income rise to 24%, 44% and 49% at the basic, higher and additional rates across the UK, and those on property income to the same rates in England, Wales and Northern Ireland: 2 percentage points above current law, which already includes Budget 2025's rises. Finance cost relief for landlords follows the property basic rate, so rises to 24%. Dividend rates are unchanged. Incomes are held fixed, with no behavioural response.", + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "name": "Savings and property income tax rates up", + "outputs_sha256": "1315fa74166dfa15139fe4693bf7df5654244db1b39b8159a0a64e5c64bfe508", + "receipt_sha256": "4d8611bcb02d626dd6a9170d8564325ef8cc10266fb1b62485f604571a3413f4", + "reconciliation": { + "responsiveness_status": "responsive", + "summary_status": "awaiting_source" + }, + "status": "provisional", + "unsupported_years": [], + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + } + }, + "release": "uk-autumn-budget-2026", + "revision": 5, + "schema": "uk-budget-dashboard/publication-manifest/v1", + "superseded": [], + "updated_at": "2026-10-28T14:35:54.732859+00:00" +} diff --git a/analysis/uk-budget-2026-income-tax/population-preview/summary.json b/analysis/uk-budget-2026-income-tax/population-preview/summary.json new file mode 100644 index 000000000..b2ae1496c --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/summary.json @@ -0,0 +1,1189 @@ +{ + "status": "Provisional preview; reconciliation awaiting_source; not final approval", + "manifest_url": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/manifest.json", + "manifest_updated_at": "2026-10-28T14:35:54.732859+00:00", + "manifest_sha256": "93148ae1fc473dbb5301ca4ac283891ddf43e6ee377fdc2df0607f0a6b0b1b7a", + "units": { + "budget_change_gbp_bn": "Annual government balance change, GBP billion; positive revenue, negative cost", + "mean_household_change_gbp": "Weighted mean annual net income change, GBP per household; includes unaffected households", + "income_change_pct": "Decile total income change / decile total baseline income * 100", + "people_affected_pct": "Percentage of people in valid-decile households with abs(change / max(baseline income, GBP 1)) > 0.0001" + }, + "limitations": [ + "No affected headcounts, household shares, winner/loser shares or survey support counts exported", + "Static estimates; Treasury post-behavioural fiscal-year forecasts require separate reconciliation", + "Trading allowance lacks gross receipts and may overstate cost" + ], + "measures": { + "unearned_income_rates_up": { + "source_commit": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", + "generated_at": "2026-10-28T14:34:26.864876+00:00", + "description": "From 6 April 2027 the income tax rates on savings income rise to 24%, 44% and 49% at the basic, higher and additional rates across the UK, and those on property income to the same rates in England, Wales and Northern Ireland: 2 percentage points above current law, which already includes Budget 2025's rises. Finance cost relief for landlords follows the property basic rate, so rises to 24%. Dividend rates are unchanged. Incomes are held fixed, with no behavioural response.", + "execution": { + "baseline": { + "binding": "content", + "kind": "current_law", + "name": "unearned_income_rates_up baseline" + }, + "certificate": { + "bundle_version": "6.11.1", + "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", + "certificate_source": "packaged", + "certified_by": "policyengine.py bundle certification", + "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "certified_for_core_version": "3.33.3", + "certified_for_model_version": "2.151.0", + "compatibility_basis": "built_with_model_package", + "country_id": "uk", + "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" + }, + "certification_status": "certified", + "core": { + "name": "policyengine-core", + "version": "3.33.3" + }, + "country_id": "uk", + "data": { + "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "build_model_version": "2.151.0", + "data_package": "microcosm-data", + "dataset": "microcosm_uk_2024_25", + "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_version": "0.1.0" + }, + "fiscal_year": { + "convention": "uk_fiscal_year", + "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", + "period_start": "04-06", + "year_label": "start_year" + }, + "model": { + "name": "policyengine-uk", + "version": "2.151.0" + }, + "outputs_sha256": "1315fa74166dfa15139fe4693bf7df5654244db1b39b8159a0a64e5c64bfe508", + "receipt_type": "policyengine.execution_receipt", + "reform": { + "binding": "content", + "kind": "reform", + "name": "unearned_income_rates_up", + "reform_sha256": "e6238a8a012d3dba63b67c75f812ef5cf7931ee8ca17c35720a94ef520979638", + "representation": "policyengine-uk.scenario/v1" + }, + "runtime": { + "platform": "linux", + "python_version": "3.13.3" + }, + "schema_version": 1, + "supported_years": [ + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032 + ], + "wrapper": { + "name": "policyengine", + "version": "6.11.1" + }, + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "disclosure_floor": { + "checked": true, + "survey_households": 3, + "thin_cells": [], + "thin_cells_in_tables": false + }, + "sources": { + "budgetary_impact": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/budgetary_impact.csv", + "distributional_impact": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/distributional_impact.csv", + "winners_losers": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/winners_losers.csv", + "metrics": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/metrics.csv" + }, + "receipt_url": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/receipt.json", + "years": { + "2026": { + "budget_change_gbp_bn": 0.0, + "mean_household_change_gbp": 0.0, + "people_affected_pct": 0.0, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 2, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 3, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 4, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 5, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 6, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 7, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 8, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 9, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 10, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + } + ] + }, + "2027": { + "budget_change_gbp_bn": 0.6642382271213031, + "mean_household_change_gbp": -22.671638846816318, + "people_affected_pct": 10.673344206596365, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": -12.898118729678712, + "income_change_pct": -0.04985863048727435 + }, + { + "decile": 2, + "mean_household_change_gbp": -5.694578425096933, + "income_change_pct": -0.014274726231957425 + }, + { + "decile": 3, + "mean_household_change_gbp": -6.657553598437464, + "income_change_pct": -0.01493700611440189 + }, + { + "decile": 4, + "mean_household_change_gbp": -7.308607835285808, + "income_change_pct": -0.015130665063043254 + }, + { + "decile": 5, + "mean_household_change_gbp": -5.999313832829491, + "income_change_pct": -0.011040999093289379 + }, + { + "decile": 6, + "mean_household_change_gbp": -9.133481007058295, + "income_change_pct": -0.015457392166954702 + }, + { + "decile": 7, + "mean_household_change_gbp": -10.940919104608044, + "income_change_pct": -0.01679145061801241 + }, + { + "decile": 8, + "mean_household_change_gbp": -21.5078233997643, + "income_change_pct": -0.02924222878277037 + }, + { + "decile": 9, + "mean_household_change_gbp": -37.036157377175726, + "income_change_pct": -0.0424816465100822 + }, + { + "decile": 10, + "mean_household_change_gbp": -107.13162680777542, + "income_change_pct": -0.06764978971604362 + } + ] + }, + "2028": { + "budget_change_gbp_bn": 0.6957731772288318, + "mean_household_change_gbp": -23.653364852788222, + "people_affected_pct": 11.008162293996863, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": -13.41973138237426, + "income_change_pct": -0.051797994354371796 + }, + { + "decile": 2, + "mean_household_change_gbp": -6.338215310184361, + "income_change_pct": -0.01562814402382634 + }, + { + "decile": 3, + "mean_household_change_gbp": -6.89447245599531, + "income_change_pct": -0.01507923160657066 + }, + { + "decile": 4, + "mean_household_change_gbp": -7.530700661654769, + "income_change_pct": -0.015199990369575169 + }, + { + "decile": 5, + "mean_household_change_gbp": -6.8788149502975875, + "income_change_pct": -0.012557869706653325 + }, + { + "decile": 6, + "mean_household_change_gbp": -8.728224096645702, + "income_change_pct": -0.014460880161614037 + }, + { + "decile": 7, + "mean_household_change_gbp": -11.809515330751909, + "income_change_pct": -0.017821793400241998 + }, + { + "decile": 8, + "mean_household_change_gbp": -22.785654721608235, + "income_change_pct": -0.030450986910411898 + }, + { + "decile": 9, + "mean_household_change_gbp": -37.58069636855771, + "income_change_pct": -0.04241102691117292 + }, + { + "decile": 10, + "mean_household_change_gbp": -111.85151093127375, + "income_change_pct": -0.0691861186482591 + } + ] + }, + "2029": { + "budget_change_gbp_bn": 0.7276593169820835, + "mean_household_change_gbp": -24.629016272903616, + "people_affected_pct": 11.211334671637678, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": -13.976437998407777, + "income_change_pct": -0.05322985172426894 + }, + { + "decile": 2, + "mean_household_change_gbp": -6.498855289587565, + "income_change_pct": -0.015861030033688512 + }, + { + "decile": 3, + "mean_household_change_gbp": -7.341434113128795, + "income_change_pct": -0.015820633619852753 + }, + { + "decile": 4, + "mean_household_change_gbp": -8.370488863576746, + "income_change_pct": -0.016640010814691405 + }, + { + "decile": 5, + "mean_household_change_gbp": -6.616069295483351, + "income_change_pct": -0.01186750640488552 + }, + { + "decile": 6, + "mean_household_change_gbp": -9.026024721135434, + "income_change_pct": -0.014739892298832517 + }, + { + "decile": 7, + "mean_household_change_gbp": -12.984868754512368, + "income_change_pct": -0.019256034827620797 + }, + { + "decile": 8, + "mean_household_change_gbp": -23.63377334118966, + "income_change_pct": -0.031114843422502994 + }, + { + "decile": 9, + "mean_household_change_gbp": -38.78140865712871, + "income_change_pct": -0.04317103405831868 + }, + { + "decile": 10, + "mean_household_change_gbp": -116.09418043491492, + "income_change_pct": -0.07041327236762773 + } + ] + }, + "2030": { + "budget_change_gbp_bn": 0.7623675377687243, + "mean_household_change_gbp": -25.68817666790038, + "people_affected_pct": 11.515220448098733, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": -14.981320954576939, + "income_change_pct": -0.05610692023915448 + }, + { + "decile": 2, + "mean_household_change_gbp": -6.531174968146814, + "income_change_pct": -0.015838490300712545 + }, + { + "decile": 3, + "mean_household_change_gbp": -8.030036431729007, + "income_change_pct": -0.016970819222280532 + }, + { + "decile": 4, + "mean_household_change_gbp": -7.324763422872621, + "income_change_pct": -0.01437706071070637 + }, + { + "decile": 5, + "mean_household_change_gbp": -8.224558743431283, + "income_change_pct": -0.014513169605216732 + }, + { + "decile": 6, + "mean_household_change_gbp": -6.414100973437806, + "income_change_pct": -0.010245777552623752 + }, + { + "decile": 7, + "mean_household_change_gbp": -16.555145381069313, + "income_change_pct": -0.024164401723622005 + }, + { + "decile": 8, + "mean_household_change_gbp": -24.719282953845298, + "income_change_pct": -0.03191810416734249 + }, + { + "decile": 9, + "mean_household_change_gbp": -39.874223193190204, + "income_change_pct": -0.04373162273763173 + }, + { + "decile": 10, + "mean_household_change_gbp": -121.49216941209389, + "income_change_pct": -0.07181165560065904 + } + ] + }, + "2031": { + "budget_change_gbp_bn": 0.7933736065368444, + "mean_household_change_gbp": -26.618450973449693, + "people_affected_pct": 11.677047270799843, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": -15.740449373492428, + "income_change_pct": -0.05832341572449926 + }, + { + "decile": 2, + "mean_household_change_gbp": -6.122323367954729, + "income_change_pct": -0.014635606422439709 + }, + { + "decile": 3, + "mean_household_change_gbp": -8.55083626627086, + "income_change_pct": -0.017848939980989183 + }, + { + "decile": 4, + "mean_household_change_gbp": -7.717876836466778, + "income_change_pct": -0.014809745978892685 + }, + { + "decile": 5, + "mean_household_change_gbp": -8.480571400003587, + "income_change_pct": -0.014729454378751861 + }, + { + "decile": 6, + "mean_household_change_gbp": -6.449886317389771, + "income_change_pct": -0.010139823686994792 + }, + { + "decile": 7, + "mean_household_change_gbp": -18.032240662651855, + "income_change_pct": -0.025662723350375474 + }, + { + "decile": 8, + "mean_household_change_gbp": -25.156749151956337, + "income_change_pct": -0.03178995628746156 + }, + { + "decile": 9, + "mean_household_change_gbp": -41.97465710374913, + "income_change_pct": -0.04569066183442702 + }, + { + "decile": 10, + "mean_household_change_gbp": -124.94128651158324, + "income_change_pct": -0.07173645374140333 + } + ] + } + } + }, + "trading_allowance_raise": { + "source_commit": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", + "generated_at": "2026-10-28T14:34:31.676559+00:00", + "description": "From 6 April 2027 the trading allowance, which relieves trading receipts in place of actual expenses, rises from \u00a31,000 to \u00a33,000, for income tax and Class 4 National Insurance. Without gross receipts in the data, a profit within the allowance is treated as fully relieved, so the cost may be overstated.", + "execution": { + "baseline": { + "binding": "content", + "kind": "current_law", + "name": "trading_allowance_raise baseline" + }, + "certificate": { + "bundle_version": "6.11.1", + "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", + "certificate_source": "packaged", + "certified_by": "policyengine.py bundle certification", + "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "certified_for_core_version": "3.33.3", + "certified_for_model_version": "2.151.0", + "compatibility_basis": "built_with_model_package", + "country_id": "uk", + "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" + }, + "certification_status": "certified", + "core": { + "name": "policyengine-core", + "version": "3.33.3" + }, + "country_id": "uk", + "data": { + "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "build_model_version": "2.151.0", + "data_package": "microcosm-data", + "dataset": "microcosm_uk_2024_25", + "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_version": "0.1.0" + }, + "fiscal_year": { + "convention": "uk_fiscal_year", + "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", + "period_start": "04-06", + "year_label": "start_year" + }, + "model": { + "name": "policyengine-uk", + "version": "2.151.0" + }, + "outputs_sha256": "c98e404df6c02459d8d1c10e8de5417ac538fd7876f2048f7bfcd0c48598d7bc", + "receipt_type": "policyengine.execution_receipt", + "reform": { + "binding": "content", + "kind": "reform", + "name": "trading_allowance_raise", + "reform_sha256": "cdcc8b19d5234afe31ae857db16a8f2d6a18578a1d7da1c890b3c5f21832c268", + "representation": "policyengine-uk.scenario/v1" + }, + "runtime": { + "platform": "linux", + "python_version": "3.13.3" + }, + "schema_version": 1, + "supported_years": [ + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032 + ], + "wrapper": { + "name": "policyengine", + "version": "6.11.1" + }, + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "disclosure_floor": { + "checked": true, + "survey_households": 3, + "thin_cells": [ + { + "groups": [ + "0", + "1", + "10", + "11", + "14", + "15", + "16", + "17", + "19", + "20", + "21", + "22", + "23", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "45", + "48", + "5", + "50", + "53", + "55", + "59", + "61", + "62", + "65", + "7", + "70", + "71", + "72", + "76", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2027 + }, + { + "groups": [ + "0", + "1", + "10", + "11", + "14", + "15", + "16", + "17", + "19", + "20", + "21", + "22", + "23", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "45", + "48", + "5", + "50", + "53", + "55", + "59", + "61", + "62", + "65", + "7", + "70", + "71", + "72", + "76", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2028 + }, + { + "groups": [ + "0", + "1", + "10", + "11", + "15", + "16", + "17", + "18", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "48", + "49", + "5", + "52", + "53", + "54", + "55", + "59", + "61", + "62", + "64", + "65", + "7", + "70", + "71", + "72", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2029 + }, + { + "groups": [ + "0", + "1", + "10", + "11", + "15", + "16", + "17", + "18", + "21", + "22", + "24", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "48", + "49", + "5", + "52", + "53", + "55", + "59", + "62", + "64", + "65", + "7", + "70", + "71", + "72", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2030 + }, + { + "groups": [ + "0", + "1", + "10", + "11", + "15", + "16", + "17", + "18", + "21", + "22", + "24", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "48", + "49", + "5", + "52", + "53", + "55", + "59", + "62", + "65", + "7", + "70", + "71", + "72", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2031 + } + ], + "thin_cells_in_tables": false + }, + "sources": { + "budgetary_impact": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/budgetary_impact.csv", + "distributional_impact": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/distributional_impact.csv", + "winners_losers": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/winners_losers.csv", + "metrics": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/metrics.csv" + }, + "receipt_url": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/receipt.json", + "years": { + "2026": { + "budget_change_gbp_bn": 0.0, + "mean_household_change_gbp": 0.0, + "people_affected_pct": 0.0, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 2, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 3, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 4, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 5, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 6, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 7, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 8, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 9, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + }, + { + "decile": 10, + "mean_household_change_gbp": 0.0, + "income_change_pct": 0.0 + } + ] + }, + "2027": { + "budget_change_gbp_bn": -0.11211049920380475, + "mean_household_change_gbp": 3.8265768397370326, + "people_affected_pct": 0.927300325538701, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": 0.8282869579049835, + "income_change_pct": 0.003201804405520605 + }, + { + "decile": 2, + "mean_household_change_gbp": 3.3868711859576655, + "income_change_pct": 0.00848994523446706 + }, + { + "decile": 3, + "mean_household_change_gbp": 1.0358538798379522, + "income_change_pct": 0.002324060258470595 + }, + { + "decile": 4, + "mean_household_change_gbp": 0.4511768558204679, + "income_change_pct": 0.0009340501013965675 + }, + { + "decile": 5, + "mean_household_change_gbp": 2.110421363657789, + "income_change_pct": 0.0038839709026547995 + }, + { + "decile": 6, + "mean_household_change_gbp": 3.4306001100428425, + "income_change_pct": 0.005805905900275085 + }, + { + "decile": 7, + "mean_household_change_gbp": 5.727796398009129, + "income_change_pct": 0.00879067009340119 + }, + { + "decile": 8, + "mean_household_change_gbp": 8.569167211108919, + "income_change_pct": 0.011650716272284782 + }, + { + "decile": 9, + "mean_household_change_gbp": 6.179334830941979, + "income_change_pct": 0.007087892928041495 + }, + { + "decile": 10, + "mean_household_change_gbp": 7.026181987372866, + "income_change_pct": 0.004436782564734936 + } + ] + }, + "2028": { + "budget_change_gbp_bn": -0.11978275834096004, + "mean_household_change_gbp": 4.072934905418043, + "people_affected_pct": 0.9286182837759142, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": 0.872907442741444, + "income_change_pct": 0.0033692816571870075 + }, + { + "decile": 2, + "mean_household_change_gbp": 3.6466648968587405, + "income_change_pct": 0.008991585395208439 + }, + { + "decile": 3, + "mean_household_change_gbp": 1.050515189648108, + "income_change_pct": 0.0022976321904294946 + }, + { + "decile": 4, + "mean_household_change_gbp": 0.40590253193385906, + "income_change_pct": 0.0008192749723536514 + }, + { + "decile": 5, + "mean_household_change_gbp": 2.1686078274995624, + "income_change_pct": 0.00395898054233744 + }, + { + "decile": 6, + "mean_household_change_gbp": 3.4802353211278247, + "income_change_pct": 0.0057660373239485025 + }, + { + "decile": 7, + "mean_household_change_gbp": 6.274458616898333, + "income_change_pct": 0.009468814090748174 + }, + { + "decile": 8, + "mean_household_change_gbp": 9.526185755176916, + "income_change_pct": 0.01273089412093796 + }, + { + "decile": 9, + "mean_household_change_gbp": 4.193623637417247, + "income_change_pct": 0.004732639416725624 + }, + { + "decile": 10, + "mean_household_change_gbp": 9.397571571174439, + "income_change_pct": 0.005812898693235177 + } + ] + }, + "2029": { + "budget_change_gbp_bn": -0.11258787723929066, + "mean_household_change_gbp": 3.811119143153684, + "people_affected_pct": 0.8154265353796385, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": 0.5034638546034419, + "income_change_pct": 0.0019174632572421628 + }, + { + "decile": 2, + "mean_household_change_gbp": 2.691709987994653, + "income_change_pct": 0.006569355841784248 + }, + { + "decile": 3, + "mean_household_change_gbp": 1.1172971606173472, + "income_change_pct": 0.002407751503349727 + }, + { + "decile": 4, + "mean_household_change_gbp": 0.42974337440005095, + "income_change_pct": 0.000854303077646435 + }, + { + "decile": 5, + "mean_household_change_gbp": 1.422505664856513, + "income_change_pct": 0.0025516049386295437 + }, + { + "decile": 6, + "mean_household_change_gbp": 3.10132878485467, + "income_change_pct": 0.005064605259166233 + }, + { + "decile": 7, + "mean_household_change_gbp": 5.432430546650813, + "income_change_pct": 0.008056074634453826 + }, + { + "decile": 8, + "mean_household_change_gbp": 10.003191487338368, + "income_change_pct": 0.01316961673282176 + }, + { + "decile": 9, + "mean_household_change_gbp": 4.052024387895121, + "income_change_pct": 0.00451066861447806 + }, + { + "decile": 10, + "mean_household_change_gbp": 9.649605980998823, + "income_change_pct": 0.005852664893579923 + } + ] + }, + "2030": { + "budget_change_gbp_bn": -0.12346843268843957, + "mean_household_change_gbp": 4.160227660123491, + "people_affected_pct": 0.8380164892515954, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": 0.5767920953669808, + "income_change_pct": 0.0021601585192287773 + }, + { + "decile": 2, + "mean_household_change_gbp": 2.775295760757472, + "income_change_pct": 0.0067302583689375995 + }, + { + "decile": 3, + "mean_household_change_gbp": 1.1945629291412128, + "income_change_pct": 0.002524610154941521 + }, + { + "decile": 4, + "mean_household_change_gbp": 0.4557512078379667, + "income_change_pct": 0.0008945494080537144 + }, + { + "decile": 5, + "mean_household_change_gbp": 1.4676819568528197, + "income_change_pct": 0.0025898917900408487 + }, + { + "decile": 6, + "mean_household_change_gbp": 3.776272166780537, + "income_change_pct": 0.006032153961907541 + }, + { + "decile": 7, + "mean_household_change_gbp": 5.069190471410754, + "income_change_pct": 0.007399147041305793 + }, + { + "decile": 8, + "mean_household_change_gbp": 11.055837353722, + "income_change_pct": 0.01427555034554112 + }, + { + "decile": 9, + "mean_household_change_gbp": 5.443441193244057, + "income_change_pct": 0.005970035215584783 + }, + { + "decile": 10, + "mean_household_change_gbp": 10.152307691098917, + "income_change_pct": 0.0060008313868543375 + } + ] + }, + "2031": { + "budget_change_gbp_bn": -0.1310177297120496, + "mean_household_change_gbp": 4.395753554915857, + "people_affected_pct": 0.812193590620492, + "deciles": [ + { + "decile": 1, + "mean_household_change_gbp": 0.5941561456709603, + "income_change_pct": 0.0022015391725468156 + }, + { + "decile": 2, + "mean_household_change_gbp": 2.9888686555262742, + "income_change_pct": 0.007144984454694446 + }, + { + "decile": 3, + "mean_household_change_gbp": 1.6211406745780168, + "income_change_pct": 0.003383954703403833 + }, + { + "decile": 4, + "mean_household_change_gbp": 0.4760062856654819, + "income_change_pct": 0.000913403041332967 + }, + { + "decile": 5, + "mean_household_change_gbp": 1.547667019974265, + "income_change_pct": 0.0026880607082914415 + }, + { + "decile": 6, + "mean_household_change_gbp": 3.862405668151834, + "income_change_pct": 0.006072062445056921 + }, + { + "decile": 7, + "mean_household_change_gbp": 5.309079871383469, + "income_change_pct": 0.007555658253083922 + }, + { + "decile": 8, + "mean_household_change_gbp": 12.260235155552552, + "income_change_pct": 0.015492953295148063 + }, + { + "decile": 9, + "mean_household_change_gbp": 6.069320375527061, + "income_change_pct": 0.006606635622003341 + }, + { + "decile": 10, + "mean_household_change_gbp": 9.690703552604862, + "income_change_pct": 0.005564027124521743 + } + ] + } + } + } + } +} diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/budgetary_impact.csv b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/budgetary_impact.csv new file mode 100644 index 000000000..843856403 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/budgetary_impact.csv @@ -0,0 +1,7 @@ +reform_id,reform_name,year,value +trading_allowance_raise,"Trading allowance raised to £3,000",2026,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,-0.11211049920380475 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,-0.11978275834096004 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,-0.11258787723929066 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,-0.12346843268843957 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,-0.1310177297120496 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/distributional_impact.csv b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/distributional_impact.csv new file mode 100644 index 000000000..0511c06ff --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/distributional_impact.csv @@ -0,0 +1,61 @@ +reform_id,reform_name,year,decile,value +trading_allowance_raise,"Trading allowance raised to £3,000",2026,10th,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,1st,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,2nd,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,3rd,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,4th,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,5th,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,6th,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,7th,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,8th,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,9th,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,10th,0.004436782564734936 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,1st,0.003201804405520605 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,2nd,0.00848994523446706 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,3rd,0.002324060258470595 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,4th,0.0009340501013965675 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,5th,0.0038839709026547995 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,6th,0.005805905900275085 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,7th,0.00879067009340119 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,8th,0.011650716272284782 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,9th,0.007087892928041495 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,10th,0.005812898693235177 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,1st,0.0033692816571870075 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,2nd,0.008991585395208439 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,3rd,0.0022976321904294946 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,4th,0.0008192749723536514 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,5th,0.00395898054233744 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,6th,0.0057660373239485025 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,7th,0.009468814090748174 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,8th,0.01273089412093796 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,9th,0.004732639416725624 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,10th,0.005852664893579923 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,1st,0.0019174632572421628 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,2nd,0.006569355841784248 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,3rd,0.002407751503349727 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,4th,0.000854303077646435 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,5th,0.0025516049386295437 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,6th,0.005064605259166233 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,7th,0.008056074634453826 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,8th,0.01316961673282176 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,9th,0.00451066861447806 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,10th,0.0060008313868543375 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,1st,0.0021601585192287773 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,2nd,0.0067302583689375995 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,3rd,0.002524610154941521 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,4th,0.0008945494080537144 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,5th,0.0025898917900408487 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,6th,0.006032153961907541 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,7th,0.007399147041305793 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,8th,0.01427555034554112 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,9th,0.005970035215584783 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,10th,0.005564027124521743 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,1st,0.0022015391725468156 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,2nd,0.007144984454694446 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,3rd,0.003383954703403833 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,4th,0.000913403041332967 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,5th,0.0026880607082914415 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,6th,0.006072062445056921 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,7th,0.007555658253083922 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,8th,0.015492953295148063 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,9th,0.006606635622003341 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/metrics.csv b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/metrics.csv new file mode 100644 index 000000000..11310714a --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/metrics.csv @@ -0,0 +1,7 @@ +reform_id,reform_name,year,people_affected,gini_change,poverty_change_pp,poverty_change_pct +trading_allowance_raise,"Trading allowance raised to £3,000",2026,0.0,0.0,0.0,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,0.927300325538701,-8.349973017775194e-07,0.0,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,0.9286182837759142,-3.244415933840377e-07,0.0,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,0.8154265353796385,9.16297028044841e-06,0.0,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,0.8380164892515954,9.96113804150047e-06,0.0,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,0.812193590620492,5.42499477041384e-06,0.0,0.0 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/receipt.json b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/receipt.json new file mode 100644 index 000000000..90dd8831f --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/receipt.json @@ -0,0 +1,453 @@ +{ + "dashboard": { + "basis": { + "calibration": { + "source": "the certified dataset pinned by the installed policyengine bundle: Microcosm UK from policyengine 6.10.1, policyengine-uk-data before it", + "status": "pre_budget", + "vintage": "as pinned by the installed bundle" + }, + "forecast": { + "source": "OBR EFO October 2026", + "status": "updated", + "vintage": "OBR Economic and fiscal outlook, October 2026 (Annex A, Tables A.1 and A.3), applied over policyengine-uk's March 2026 growth rates by src/uk_budget_data/forecast/obr_october_2026.json" + }, + "notes": "The forecast is rebased on the Budget's OBR forecast: every simulation, baseline and reform alike, is built on the October 2026 growth rates in src/uk_budget_data/forecast/obr_october_2026.json (CPI, RPI, average earnings, house prices; the September 2027 CPI gap). Series that file does not list keep the March 2026 path the installed policyengine-uk ships; the receipt records the exact model version." + }, + "composition": null, + "config_baseline": { + "binding": "content", + "kind": "current_law", + "name": "configured baseline", + "reform_sha256": null, + "representation": null + }, + "data_limits": [], + "data_limits_registry_sha256": "c48a8fe082168969b5c3e6d6689a630c9f47ac64fa9de7efd11a055d2cab1a4b", + "dataset_years": [ + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032 + ], + "description": "From 6 April 2027 the trading allowance, which relieves trading receipts in place of actual expenses, rises from \u00a31,000 to \u00a33,000, for income tax and Class 4 National Insurance. Without gross receipts in the data, a profit within the allowance is treated as fully relieved, so the cost may be overstated.", + "digests": { + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "outputs_sha256": "c98e404df6c02459d8d1c10e8de5417ac538fd7876f2048f7bfcd0c48598d7bc", + "receipt_sha256": "12e5b9f9ecaa3c9f6e967ad30a71c26e0156a8468a8edde5377a1400393a0f3c" + }, + "disclosure_floor": { + "checked": true, + "survey_households": 3, + "thin_cells": [ + { + "groups": [ + "0", + "1", + "10", + "11", + "14", + "15", + "16", + "17", + "19", + "20", + "21", + "22", + "23", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "45", + "48", + "5", + "50", + "53", + "55", + "59", + "61", + "62", + "65", + "7", + "70", + "71", + "72", + "76", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2027 + }, + { + "groups": [ + "0", + "1", + "10", + "11", + "14", + "15", + "16", + "17", + "19", + "20", + "21", + "22", + "23", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "45", + "48", + "5", + "50", + "53", + "55", + "59", + "61", + "62", + "65", + "7", + "70", + "71", + "72", + "76", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2028 + }, + { + "groups": [ + "0", + "1", + "10", + "11", + "15", + "16", + "17", + "18", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "48", + "49", + "5", + "52", + "53", + "54", + "55", + "59", + "61", + "62", + "64", + "65", + "7", + "70", + "71", + "72", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2029 + }, + { + "groups": [ + "0", + "1", + "10", + "11", + "15", + "16", + "17", + "18", + "21", + "22", + "24", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "48", + "49", + "5", + "52", + "53", + "55", + "59", + "62", + "64", + "65", + "7", + "70", + "71", + "72", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2030 + }, + { + "groups": [ + "0", + "1", + "10", + "11", + "15", + "16", + "17", + "18", + "21", + "22", + "24", + "25", + "26", + "27", + "29", + "30", + "31", + "32", + "34", + "35", + "36", + "38", + "40", + "41", + "44", + "48", + "49", + "5", + "52", + "53", + "55", + "59", + "62", + "65", + "7", + "70", + "71", + "72", + "78", + "79", + "8", + "80", + "82", + "86", + "87", + "88", + "89" + ], + "table": "age_impact", + "year": 2031 + } + ], + "thin_cells_in_tables": false + }, + "files": { + "age_impact.csv": "fba108ffa8b12d2e543a743a4646cb894be14f568377fd46734cd60cd0333af2", + "budgetary_impact.csv": "ed71cf21bfd60b0044cc27868d24b08ab26e415241e1b3eff34b130051c0581b", + "distributional_impact.csv": "18670f3ed2936a5b4e5a94c1c5c6f961b9ad6c47c37a4245cb7789afc09a8a01", + "household_scatter_binned.csv": "d622c921d9da66b23c55910ca01559dfce1d241e95c890c2a3ff4d4f08471fe3", + "income_curve.csv": "447037ac0bdf9f0bde2083a9a0c56764aa0d9dc2e76010c841a70edf3b8ce192", + "metrics.csv": "e6d47c154d8a4b696e2ee7cab5d96d95ce30721945a4b29ec26279a498175627", + "poverty_inequality.csv": "c0a5c9a2b989cb2ce417faf6bd6f03f6fc0c48ad88f1ce5f4229bde2c25956d8", + "winners_losers.csv": "8652a18c4dc237cfb7815000cc40d752176631c3fbd132bd3795f847dced9894" + }, + "generated_at": "2026-10-28T14:34:31.676559+00:00", + "generator_argv": [ + "/private/tmp/claude-501/-Users-vahid/59114aef-a9b7-4663-a8bc-32b2c6146551/scratchpad/run7/src/uk_budget_data/cli.py", + "generate", + "--artifacts", + "--backend", + "modal", + "--reforms", + "trading_allowance_raise" + ], + "git_sha": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", + "key": "trading_allowance_raise", + "measure_ids": [ + "trading_allowance_raise" + ], + "member_outputs_sha256": null, + "members": null, + "model_limits": [], + "model_limits_registry_sha256": "9d3479f1f5ac859ab6bd2644aaff443a29c0dad3f2944b1ef98866028f9d4b89", + "modifier_templates": { + "baseline": [], + "reform": [] + }, + "name": "Trading allowance raised to \u00a33,000", + "publishable": true, + "reasons": [], + "receipt_source": "policyengine==6.11.1", + "tree_clean": true, + "unsupported_years": [] + }, + "execution_receipt": { + "baseline": { + "binding": "content", + "kind": "current_law", + "name": "trading_allowance_raise baseline" + }, + "certificate": { + "bundle_version": "6.11.1", + "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", + "certificate_source": "packaged", + "certified_by": "policyengine.py bundle certification", + "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "certified_for_core_version": "3.33.3", + "certified_for_model_version": "2.151.0", + "compatibility_basis": "built_with_model_package", + "country_id": "uk", + "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" + }, + "certification_status": "certified", + "core": { + "name": "policyengine-core", + "version": "3.33.3" + }, + "country_id": "uk", + "data": { + "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "build_model_version": "2.151.0", + "data_package": "microcosm-data", + "dataset": "microcosm_uk_2024_25", + "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_version": "0.1.0" + }, + "fiscal_year": { + "convention": "uk_fiscal_year", + "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", + "period_start": "04-06", + "year_label": "start_year" + }, + "model": { + "name": "policyengine-uk", + "version": "2.151.0" + }, + "outputs_sha256": "c98e404df6c02459d8d1c10e8de5417ac538fd7876f2048f7bfcd0c48598d7bc", + "receipt_type": "policyengine.execution_receipt", + "reform": { + "binding": "content", + "kind": "reform", + "name": "trading_allowance_raise", + "reform_sha256": "cdcc8b19d5234afe31ae857db16a8f2d6a18578a1d7da1c890b3c5f21832c268", + "representation": "policyengine-uk.scenario/v1" + }, + "runtime": { + "platform": "linux", + "python_version": "3.13.3" + }, + "schema_version": 1, + "supported_years": [ + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032 + ], + "wrapper": { + "name": "policyengine", + "version": "6.11.1" + }, + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "schema": "uk-budget-dashboard/artifact-receipt/v1" +} diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/winners_losers.csv b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/winners_losers.csv new file mode 100644 index 000000000..aa99d9ba8 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/winners_losers.csv @@ -0,0 +1,67 @@ +reform_id,reform_name,year,decile,avg_change +trading_allowance_raise,"Trading allowance raised to £3,000",2026,1,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,10,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,2,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,3,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,4,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,5,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,6,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,7,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,8,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,9,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2026,all,0.0 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,1,0.8282869579049835 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,10,7.026181987372866 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,2,3.3868711859576655 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,3,1.0358538798379522 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,4,0.4511768558204679 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,5,2.110421363657789 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,6,3.4306001100428425 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,7,5.727796398009129 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,8,8.569167211108919 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,9,6.179334830941979 +trading_allowance_raise,"Trading allowance raised to £3,000",2027,all,3.8265768397370326 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,1,0.872907442741444 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,10,9.397571571174439 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,2,3.6466648968587405 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,3,1.050515189648108 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,4,0.40590253193385906 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,5,2.1686078274995624 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,6,3.4802353211278247 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,7,6.274458616898333 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,8,9.526185755176916 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,9,4.193623637417247 +trading_allowance_raise,"Trading allowance raised to £3,000",2028,all,4.072934905418043 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,1,0.5034638546034419 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,10,9.649605980998823 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,2,2.691709987994653 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,3,1.1172971606173472 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,4,0.42974337440005095 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,5,1.422505664856513 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,6,3.10132878485467 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,7,5.432430546650813 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,8,10.003191487338368 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,9,4.052024387895121 +trading_allowance_raise,"Trading allowance raised to £3,000",2029,all,3.811119143153684 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,1,0.5767920953669808 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,10,10.152307691098917 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,2,2.775295760757472 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,3,1.1945629291412128 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,4,0.4557512078379667 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,5,1.4676819568528197 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,6,3.776272166780537 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,7,5.069190471410754 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,8,11.055837353722 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,9,5.443441193244057 +trading_allowance_raise,"Trading allowance raised to £3,000",2030,all,4.160227660123491 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,1,0.5941561456709603 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,10,9.690703552604862 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,2,2.9888686555262742 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,3,1.6211406745780168 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,4,0.4760062856654819 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,5,1.547667019974265 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,6,3.862405668151834 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,7,5.309079871383469 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,8,12.260235155552552 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,9,6.069320375527061 +trading_allowance_raise,"Trading allowance raised to £3,000",2031,all,4.395753554915857 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/budgetary_impact.csv b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/budgetary_impact.csv new file mode 100644 index 000000000..da37a0595 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/budgetary_impact.csv @@ -0,0 +1,7 @@ +reform_id,reform_name,year,value +unearned_income_rates_up,Savings and property income tax rates up,2026,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2027,0.6642382271213031 +unearned_income_rates_up,Savings and property income tax rates up,2028,0.6957731772288318 +unearned_income_rates_up,Savings and property income tax rates up,2029,0.7276593169820835 +unearned_income_rates_up,Savings and property income tax rates up,2030,0.7623675377687243 +unearned_income_rates_up,Savings and property income tax rates up,2031,0.7933736065368444 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/distributional_impact.csv b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/distributional_impact.csv new file mode 100644 index 000000000..2d308558a --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/distributional_impact.csv @@ -0,0 +1,61 @@ +reform_id,reform_name,year,decile,value +unearned_income_rates_up,Savings and property income tax rates up,2026,10th,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,1st,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,2nd,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,3rd,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,4th,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,5th,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,6th,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,7th,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,8th,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,9th,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2027,10th,-0.06764978971604362 +unearned_income_rates_up,Savings and property income tax rates up,2027,1st,-0.04985863048727435 +unearned_income_rates_up,Savings and property income tax rates up,2027,2nd,-0.014274726231957425 +unearned_income_rates_up,Savings and property income tax rates up,2027,3rd,-0.01493700611440189 +unearned_income_rates_up,Savings and property income tax rates up,2027,4th,-0.015130665063043254 +unearned_income_rates_up,Savings and property income tax rates up,2027,5th,-0.011040999093289379 +unearned_income_rates_up,Savings and property income tax rates up,2027,6th,-0.015457392166954702 +unearned_income_rates_up,Savings and property income tax rates up,2027,7th,-0.01679145061801241 +unearned_income_rates_up,Savings and property income tax rates up,2027,8th,-0.02924222878277037 +unearned_income_rates_up,Savings and property income tax rates up,2027,9th,-0.0424816465100822 +unearned_income_rates_up,Savings and property income tax rates up,2028,10th,-0.0691861186482591 +unearned_income_rates_up,Savings and property income tax rates up,2028,1st,-0.051797994354371796 +unearned_income_rates_up,Savings and property income tax rates up,2028,2nd,-0.01562814402382634 +unearned_income_rates_up,Savings and property income tax rates up,2028,3rd,-0.01507923160657066 +unearned_income_rates_up,Savings and property income tax rates up,2028,4th,-0.015199990369575169 +unearned_income_rates_up,Savings and property income tax rates up,2028,5th,-0.012557869706653325 +unearned_income_rates_up,Savings and property income tax rates up,2028,6th,-0.014460880161614037 +unearned_income_rates_up,Savings and property income tax rates up,2028,7th,-0.017821793400241998 +unearned_income_rates_up,Savings and property income tax rates up,2028,8th,-0.030450986910411898 +unearned_income_rates_up,Savings and property income tax rates up,2028,9th,-0.04241102691117292 +unearned_income_rates_up,Savings and property income tax rates up,2029,10th,-0.07041327236762773 +unearned_income_rates_up,Savings and property income tax rates up,2029,1st,-0.05322985172426894 +unearned_income_rates_up,Savings and property income tax rates up,2029,2nd,-0.015861030033688512 +unearned_income_rates_up,Savings and property income tax rates up,2029,3rd,-0.015820633619852753 +unearned_income_rates_up,Savings and property income tax rates up,2029,4th,-0.016640010814691405 +unearned_income_rates_up,Savings and property income tax rates up,2029,5th,-0.01186750640488552 +unearned_income_rates_up,Savings and property income tax rates up,2029,6th,-0.014739892298832517 +unearned_income_rates_up,Savings and property income tax rates up,2029,7th,-0.019256034827620797 +unearned_income_rates_up,Savings and property income tax rates up,2029,8th,-0.031114843422502994 +unearned_income_rates_up,Savings and property income tax rates up,2029,9th,-0.04317103405831868 +unearned_income_rates_up,Savings and property income tax rates up,2030,10th,-0.07181165560065904 +unearned_income_rates_up,Savings and property income tax rates up,2030,1st,-0.05610692023915448 +unearned_income_rates_up,Savings and property income tax rates up,2030,2nd,-0.015838490300712545 +unearned_income_rates_up,Savings and property income tax rates up,2030,3rd,-0.016970819222280532 +unearned_income_rates_up,Savings and property income tax rates up,2030,4th,-0.01437706071070637 +unearned_income_rates_up,Savings and property income tax rates up,2030,5th,-0.014513169605216732 +unearned_income_rates_up,Savings and property income tax rates up,2030,6th,-0.010245777552623752 +unearned_income_rates_up,Savings and property income tax rates up,2030,7th,-0.024164401723622005 +unearned_income_rates_up,Savings and property income tax rates up,2030,8th,-0.03191810416734249 +unearned_income_rates_up,Savings and property income tax rates up,2030,9th,-0.04373162273763173 +unearned_income_rates_up,Savings and property income tax rates up,2031,10th,-0.07173645374140333 +unearned_income_rates_up,Savings and property income tax rates up,2031,1st,-0.05832341572449926 +unearned_income_rates_up,Savings and property income tax rates up,2031,2nd,-0.014635606422439709 +unearned_income_rates_up,Savings and property income tax rates up,2031,3rd,-0.017848939980989183 +unearned_income_rates_up,Savings and property income tax rates up,2031,4th,-0.014809745978892685 +unearned_income_rates_up,Savings and property income tax rates up,2031,5th,-0.014729454378751861 +unearned_income_rates_up,Savings and property income tax rates up,2031,6th,-0.010139823686994792 +unearned_income_rates_up,Savings and property income tax rates up,2031,7th,-0.025662723350375474 +unearned_income_rates_up,Savings and property income tax rates up,2031,8th,-0.03178995628746156 +unearned_income_rates_up,Savings and property income tax rates up,2031,9th,-0.04569066183442702 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/metrics.csv b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/metrics.csv new file mode 100644 index 000000000..dfb46f33e --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/metrics.csv @@ -0,0 +1,7 @@ +reform_id,reform_name,year,people_affected,gini_change,poverty_change_pp,poverty_change_pct +unearned_income_rates_up,Savings and property income tax rates up,2026,0.0,0.0,0.0,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2027,10.673344206596365,-0.00028251218573879843,0.00028419495,0.002069667 +unearned_income_rates_up,Savings and property income tax rates up,2028,11.008162293996863,-0.00028521977216218057,0.0026416779,0.019280192 +unearned_income_rates_up,Savings and property income tax rates up,2029,11.211334671637678,-0.0002876005452886594,0.0005235672,0.0038050439 +unearned_income_rates_up,Savings and property income tax rates up,2030,11.515220448098733,-0.0002894803540428024,0.0011587143,0.008401513 +unearned_income_rates_up,Savings and property income tax rates up,2031,11.677047270799843,-0.0002925173508581513,0.0025806427,0.018773075 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/receipt.json b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/receipt.json new file mode 100644 index 000000000..886a56441 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/receipt.json @@ -0,0 +1,173 @@ +{ + "dashboard": { + "basis": { + "calibration": { + "source": "the certified dataset pinned by the installed policyengine bundle: Microcosm UK from policyengine 6.10.1, policyengine-uk-data before it", + "status": "pre_budget", + "vintage": "as pinned by the installed bundle" + }, + "forecast": { + "source": "OBR EFO October 2026", + "status": "updated", + "vintage": "OBR Economic and fiscal outlook, October 2026 (Annex A, Tables A.1 and A.3), applied over policyengine-uk's March 2026 growth rates by src/uk_budget_data/forecast/obr_october_2026.json" + }, + "notes": "The forecast is rebased on the Budget's OBR forecast: every simulation, baseline and reform alike, is built on the October 2026 growth rates in src/uk_budget_data/forecast/obr_october_2026.json (CPI, RPI, average earnings, house prices; the September 2027 CPI gap). Series that file does not list keep the March 2026 path the installed policyengine-uk ships; the receipt records the exact model version." + }, + "composition": null, + "config_baseline": { + "binding": "content", + "kind": "current_law", + "name": "configured baseline", + "reform_sha256": null, + "representation": null + }, + "data_limits": [], + "data_limits_registry_sha256": "c48a8fe082168969b5c3e6d6689a630c9f47ac64fa9de7efd11a055d2cab1a4b", + "dataset_years": [ + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032 + ], + "description": "From 6 April 2027 the income tax rates on savings income rise to 24%, 44% and 49% at the basic, higher and additional rates across the UK, and those on property income to the same rates in England, Wales and Northern Ireland: 2 percentage points above current law, which already includes Budget 2025's rises. Finance cost relief for landlords follows the property basic rate, so rises to 24%. Dividend rates are unchanged. Incomes are held fixed, with no behavioural response.", + "digests": { + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "outputs_sha256": "1315fa74166dfa15139fe4693bf7df5654244db1b39b8159a0a64e5c64bfe508", + "receipt_sha256": "4d8611bcb02d626dd6a9170d8564325ef8cc10266fb1b62485f604571a3413f4" + }, + "disclosure_floor": { + "checked": true, + "survey_households": 3, + "thin_cells": [], + "thin_cells_in_tables": false + }, + "files": { + "age_impact.csv": "2c5ead6535d59e4ca507059d280ee8543d5ff39d6759ec3b86ebbbb35f54b2c5", + "budgetary_impact.csv": "76a9bcf35b7427af58098ef063a873afdff4b3eccc84b55782b5e7bfc9595bc0", + "distributional_impact.csv": "0d7fc5da79518ad6e255acfd7fb5469eb483117849afea8a2db57c70e936ba48", + "household_scatter_binned.csv": "1930be90eda9c3459a493fc3b2b51626fac93653fd5b22214746e04bcb31d7b3", + "income_curve.csv": "1b470f7215bf16eed979f987e0f87575bb78cfe8a077c9ecbf47e3fbe175dde4", + "metrics.csv": "abf2e4f4fdc4276588ac2d89fdec83df246aa517fda8590fd20d3ccd368aa15c", + "poverty_inequality.csv": "e0ae3a92c9f2341fdd61f51cefd752f307b78e8fd1f9badf9abb153c4a7d76f3", + "winners_losers.csv": "651d1c59976cdb1faab8d5f87ef9099aa67eb37d6c24f85707088e09f27aa8f0" + }, + "generated_at": "2026-10-28T14:34:26.864876+00:00", + "generator_argv": [ + "/private/tmp/claude-501/-Users-vahid/59114aef-a9b7-4663-a8bc-32b2c6146551/scratchpad/run7/src/uk_budget_data/cli.py", + "generate", + "--artifacts", + "--backend", + "modal", + "--reforms", + "unearned_income_rates_up" + ], + "git_sha": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", + "key": "unearned_income_rates_up", + "measure_ids": [ + "unearned_income_rates_up" + ], + "member_outputs_sha256": null, + "members": null, + "model_limits": [], + "model_limits_registry_sha256": "9d3479f1f5ac859ab6bd2644aaff443a29c0dad3f2944b1ef98866028f9d4b89", + "modifier_templates": { + "baseline": [], + "reform": [] + }, + "name": "Savings and property income tax rates up", + "publishable": true, + "reasons": [], + "receipt_source": "policyengine==6.11.1", + "tree_clean": true, + "unsupported_years": [] + }, + "execution_receipt": { + "baseline": { + "binding": "content", + "kind": "current_law", + "name": "unearned_income_rates_up baseline" + }, + "certificate": { + "bundle_version": "6.11.1", + "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", + "certificate_source": "packaged", + "certified_by": "policyengine.py bundle certification", + "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "certified_for_core_version": "3.33.3", + "certified_for_model_version": "2.151.0", + "compatibility_basis": "built_with_model_package", + "country_id": "uk", + "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" + }, + "certification_status": "certified", + "core": { + "name": "policyengine-core", + "version": "3.33.3" + }, + "country_id": "uk", + "data": { + "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "build_model_version": "2.151.0", + "data_package": "microcosm-data", + "dataset": "microcosm_uk_2024_25", + "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_version": "0.1.0" + }, + "fiscal_year": { + "convention": "uk_fiscal_year", + "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", + "period_start": "04-06", + "year_label": "start_year" + }, + "model": { + "name": "policyengine-uk", + "version": "2.151.0" + }, + "outputs_sha256": "1315fa74166dfa15139fe4693bf7df5654244db1b39b8159a0a64e5c64bfe508", + "receipt_type": "policyengine.execution_receipt", + "reform": { + "binding": "content", + "kind": "reform", + "name": "unearned_income_rates_up", + "reform_sha256": "e6238a8a012d3dba63b67c75f812ef5cf7931ee8ca17c35720a94ef520979638", + "representation": "policyengine-uk.scenario/v1" + }, + "runtime": { + "platform": "linux", + "python_version": "3.13.3" + }, + "schema_version": 1, + "supported_years": [ + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032 + ], + "wrapper": { + "name": "policyengine", + "version": "6.11.1" + }, + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "schema": "uk-budget-dashboard/artifact-receipt/v1" +} diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/winners_losers.csv b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/winners_losers.csv new file mode 100644 index 000000000..630647b07 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/winners_losers.csv @@ -0,0 +1,67 @@ +reform_id,reform_name,year,decile,avg_change +unearned_income_rates_up,Savings and property income tax rates up,2026,1,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,10,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,2,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,3,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,4,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,5,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,6,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,7,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,8,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,9,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2026,all,0.0 +unearned_income_rates_up,Savings and property income tax rates up,2027,1,-12.898118729678712 +unearned_income_rates_up,Savings and property income tax rates up,2027,10,-107.13162680777542 +unearned_income_rates_up,Savings and property income tax rates up,2027,2,-5.694578425096933 +unearned_income_rates_up,Savings and property income tax rates up,2027,3,-6.657553598437464 +unearned_income_rates_up,Savings and property income tax rates up,2027,4,-7.308607835285808 +unearned_income_rates_up,Savings and property income tax rates up,2027,5,-5.999313832829491 +unearned_income_rates_up,Savings and property income tax rates up,2027,6,-9.133481007058295 +unearned_income_rates_up,Savings and property income tax rates up,2027,7,-10.940919104608044 +unearned_income_rates_up,Savings and property income tax rates up,2027,8,-21.5078233997643 +unearned_income_rates_up,Savings and property income tax rates up,2027,9,-37.036157377175726 +unearned_income_rates_up,Savings and property income tax rates up,2027,all,-22.671638846816318 +unearned_income_rates_up,Savings and property income tax rates up,2028,1,-13.41973138237426 +unearned_income_rates_up,Savings and property income tax rates up,2028,10,-111.85151093127375 +unearned_income_rates_up,Savings and property income tax rates up,2028,2,-6.338215310184361 +unearned_income_rates_up,Savings and property income tax rates up,2028,3,-6.89447245599531 +unearned_income_rates_up,Savings and property income tax rates up,2028,4,-7.530700661654769 +unearned_income_rates_up,Savings and property income tax rates up,2028,5,-6.8788149502975875 +unearned_income_rates_up,Savings and property income tax rates up,2028,6,-8.728224096645702 +unearned_income_rates_up,Savings and property income tax rates up,2028,7,-11.809515330751909 +unearned_income_rates_up,Savings and property income tax rates up,2028,8,-22.785654721608235 +unearned_income_rates_up,Savings and property income tax rates up,2028,9,-37.58069636855771 +unearned_income_rates_up,Savings and property income tax rates up,2028,all,-23.653364852788222 +unearned_income_rates_up,Savings and property income tax rates up,2029,1,-13.976437998407777 +unearned_income_rates_up,Savings and property income tax rates up,2029,10,-116.09418043491492 +unearned_income_rates_up,Savings and property income tax rates up,2029,2,-6.498855289587565 +unearned_income_rates_up,Savings and property income tax rates up,2029,3,-7.341434113128795 +unearned_income_rates_up,Savings and property income tax rates up,2029,4,-8.370488863576746 +unearned_income_rates_up,Savings and property income tax rates up,2029,5,-6.616069295483351 +unearned_income_rates_up,Savings and property income tax rates up,2029,6,-9.026024721135434 +unearned_income_rates_up,Savings and property income tax rates up,2029,7,-12.984868754512368 +unearned_income_rates_up,Savings and property income tax rates up,2029,8,-23.63377334118966 +unearned_income_rates_up,Savings and property income tax rates up,2029,9,-38.78140865712871 +unearned_income_rates_up,Savings and property income tax rates up,2029,all,-24.629016272903616 +unearned_income_rates_up,Savings and property income tax rates up,2030,1,-14.981320954576939 +unearned_income_rates_up,Savings and property income tax rates up,2030,10,-121.49216941209389 +unearned_income_rates_up,Savings and property income tax rates up,2030,2,-6.531174968146814 +unearned_income_rates_up,Savings and property income tax rates up,2030,3,-8.030036431729007 +unearned_income_rates_up,Savings and property income tax rates up,2030,4,-7.324763422872621 +unearned_income_rates_up,Savings and property income tax rates up,2030,5,-8.224558743431283 +unearned_income_rates_up,Savings and property income tax rates up,2030,6,-6.414100973437806 +unearned_income_rates_up,Savings and property income tax rates up,2030,7,-16.555145381069313 +unearned_income_rates_up,Savings and property income tax rates up,2030,8,-24.719282953845298 +unearned_income_rates_up,Savings and property income tax rates up,2030,9,-39.874223193190204 +unearned_income_rates_up,Savings and property income tax rates up,2030,all,-25.68817666790038 +unearned_income_rates_up,Savings and property income tax rates up,2031,1,-15.740449373492428 +unearned_income_rates_up,Savings and property income tax rates up,2031,10,-124.94128651158324 +unearned_income_rates_up,Savings and property income tax rates up,2031,2,-6.122323367954729 +unearned_income_rates_up,Savings and property income tax rates up,2031,3,-8.55083626627086 +unearned_income_rates_up,Savings and property income tax rates up,2031,4,-7.717876836466778 +unearned_income_rates_up,Savings and property income tax rates up,2031,5,-8.480571400003587 +unearned_income_rates_up,Savings and property income tax rates up,2031,6,-6.449886317389771 +unearned_income_rates_up,Savings and property income tax rates up,2031,7,-18.032240662651855 +unearned_income_rates_up,Savings and property income tax rates up,2031,8,-25.156749151956337 +unearned_income_rates_up,Savings and property income tax rates up,2031,9,-41.97465710374913 +unearned_income_rates_up,Savings and property income tax rates up,2031,all,-26.618450973449693 diff --git a/analysis/uk-budget-2026-income-tax/provenance.json b/analysis/uk-budget-2026-income-tax/provenance.json index e4596e2d8..143214131 100644 --- a/analysis/uk-budget-2026-income-tax/provenance.json +++ b/analysis/uk-budget-2026-income-tax/provenance.json @@ -11,26 +11,86 @@ "pull_request": 290, "commit": "b50787aa75ef5aed36b822c973afa6b569464d55", "path": "src/uk_budget_data/reforms.py", - "measures": ["unearned_income_rates_up", "trading_allowance_raise"] + "measures": [ + "unearned_income_rates_up", + "trading_allowance_raise" + ] }, "population": { - "status": "pending_data_access_and_dashboard_budget_day_outputs", + "status": "provisional_dashboard_aggregate_outputs_available_awaiting_reconciliation", "dataset": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", "sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", "certificate": "https://github.com/PolicyEngine/policyengine.py/pull/720", "dashboard_adoption": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/237", "raw_microdata_used_for_households": false, - "national_results_generated": false, "forecast": "October 2026 OBR inputs, applied to both baseline and reform when population scoring is run", - "replacement_policy": "Retain this adopted bundle until a later explicitly recorded update; do not silently use the candidate in policyengine.py PR725." + "replacement_policy": "Retain this adopted bundle until a later explicitly recorded update; do not silently use the candidate in policyengine.py PR725.", + "national_results_generated_locally": false, + "national_results_reused_from_dashboard": true, + "dashboard_snapshot": { + "manifest_revision": 5, + "manifest_updated_at": "2026-10-28T14:35:54.732859Z", + "fetched_at": "2026-10-28T14:46:46Z", + "base_url": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/", + "source_commit": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", + "reform_and_forecast_files_match_household_reference": true, + "measures": { + "unearned_income_rates_up": { + "artifact": "artifacts/unearned_income_rates_up/8bd7d211ae66c19d", + "generated_at": "2026-10-28T14:34:26.864876Z" + }, + "trading_allowance_raise": { + "artifact": "artifacts/trading_allowance_raise/230c4665427e0bb1", + "generated_at": "2026-10-28T14:34:31.676559Z" + } + }, + "manifest_status": "provisional", + "reconciliation_status": "awaiting_source", + "combined_artifact_available": false, + "disclosure_floor_survey_households": 3, + "thin_decile_cells_recorded": false, + "limitations": [ + "No absolute affected-person counts or separate winner/loser shares are exported.", + "people_affected is a percentage of people in households whose absolute net-income percentage change exceeds 0.01%; it is not a headcount.", + "Trading gross receipts are missing; the receipt warns this may overstate cost." + ] + } }, "treasury_costings": { "source": "https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html", "table": "6.1", "units": "GBP million; positive values below indicate revenue for savings/property and cost for trading", - "fiscal_years": ["2026-27", "2027-28", "2028-29", "2029-30", "2030-31", "2031-32"], - "property_row_61_revenue": [0, 35, 575, 435, 445, 455], - "savings_row_62_revenue": [15, 125, 555, 520, 555, 590], - "trading_row_15_cost": [0, 0, 225, 165, 175, 180] + "fiscal_years": [ + "2026-27", + "2027-28", + "2028-29", + "2029-30", + "2030-31", + "2031-32" + ], + "property_row_61_revenue": [ + 0, + 35, + 575, + 435, + 445, + 455 + ], + "savings_row_62_revenue": [ + 15, + 125, + 555, + 520, + 555, + 590 + ], + "trading_row_15_cost": [ + 0, + 0, + 225, + 165, + 175, + 180 + ] } } diff --git a/analysis/uk-budget-2026-income-tax/verify_population_preview.py b/analysis/uk-budget-2026-income-tax/verify_population_preview.py new file mode 100644 index 000000000..b494b2ebc --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/verify_population_preview.py @@ -0,0 +1,93 @@ +"""Verify the saved public preview aggregates offline and rebuild their summary.""" + +import csv +import hashlib +import json +from pathlib import Path + +BASE = Path(__file__).resolve().parent +SNAPSHOT = BASE / "population-preview" +SOURCE = "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/" +MEASURES = ("unearned_income_rates_up", "trading_allowance_raise") +TABLES = ("budgetary_impact", "distributional_impact", "winners_losers", "metrics") + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def read_json(path): + return json.loads(path.read_text()) + + +def main(): + provenance = read_json(BASE / "provenance.json") + manifest = read_json(SNAPSHOT / "manifest.json") + summary = { + "status": "Provisional preview; reconciliation awaiting_source; not final approval", + "manifest_url": SOURCE + "manifest.json", + "manifest_updated_at": manifest["updated_at"], + "manifest_sha256": hashlib.sha256((SNAPSHOT / "manifest.json").read_bytes()).hexdigest(), + "units": { + "budget_change_gbp_bn": "Annual government balance change, GBP billion; positive revenue, negative cost", + "mean_household_change_gbp": "Weighted mean annual net income change, GBP per household; includes unaffected households", + "income_change_pct": "Decile total income change / decile total baseline income * 100", + "people_affected_pct": "Percentage of people in valid-decile households with abs(change / max(baseline income, GBP 1)) > 0.0001", + }, + "limitations": [ + "No affected headcounts, household shares, winner/loser shares or survey support counts exported", + "Static estimates; Treasury post-behavioural fiscal-year forecasts require separate reconciliation", + "Trading allowance lacks gross receipts and may overstate cost", + ], + "measures": {}, + } + for mid in MEASURES: + entry = manifest["measures"][mid] + receipt = read_json(SNAPSHOT / mid / "receipt.json") + dashboard, execution = receipt["dashboard"], receipt["execution_receipt"] + require(entry["status"] == "provisional", f"{mid}: unexpected publication status") + require(entry["reconciliation"]["summary_status"] == "awaiting_source", f"{mid}: unexpected reconciliation") + require(dashboard["publishable"] and execution["certification_status"] == "certified", f"{mid}: not publishable/certified") + for package, key in (("policyengine", "wrapper"), ("policyengine-uk", "model"), ("policyengine-core", "core")): + expected = provenance["package_versions"][package] + require(execution[key]["version"] == expected == manifest["execution"]["identity"][key]["version"], f"{mid}: {package} mismatch") + require(execution["data"]["dataset_sha256"] == provenance["population"]["sha256"], f"{mid}: dataset hash mismatch") + require(manifest["execution"]["identity"]["data"]["dataset_sha256"] == execution["data"]["dataset_sha256"], f"{mid}: manifest dataset mismatch") + require(execution["data"]["build_id"] == provenance["population"]["dataset"], f"{mid}: dataset build mismatch") + require(execution["certificate"]["certified_dataset_sha256"] == execution["data"]["dataset_sha256"], f"{mid}: certificate mismatch") + require(dashboard["digests"]["receipt_sha256"] == entry["receipt_sha256"], f"{mid}: receipt identity mismatch") + floor = dashboard["disclosure_floor"] + require(floor["checked"] and floor["survey_households"] == 3 and not floor["thin_cells_in_tables"], f"{mid}: disclosure floor failed") + require(not any(cell["table"] in TABLES for cell in floor["thin_cells"]), f"{mid}: thin decile cells") + tables = {} + for name in TABLES: + path = SNAPSHOT / mid / f"{name}.csv" + require(hashlib.sha256(path.read_bytes()).hexdigest() == dashboard["files"][path.name], f"{mid}: {path.name} hash mismatch") + tables[name] = list(csv.DictReader(path.open())) + years = {} + for year in entry["years"]: + rows = {name: [row for row in data if int(row["year"]) == year] for name, data in tables.items()} + cash = {row["decile"]: float(row["avg_change"]) for row in rows["winners_losers"]} + percent = {int("".join(filter(str.isdigit, row["decile"]))): float(row["value"]) for row in rows["distributional_impact"]} + require(set(cash) == {str(i) for i in range(1, 11)} | {"all"} and set(percent) == set(range(1, 11)), f"{mid}/{year}: incomplete deciles") + require(len(rows["budgetary_impact"]) == len(rows["metrics"]) == 1, f"{mid}/{year}: incomplete headline") + years[str(year)] = { + "budget_change_gbp_bn": float(rows["budgetary_impact"][0]["value"]), + "mean_household_change_gbp": cash["all"], + "people_affected_pct": float(rows["metrics"][0]["people_affected"]), + "deciles": [{"decile": i, "mean_household_change_gbp": cash[str(i)], "income_change_pct": percent[i]} for i in range(1, 11)], + } + summary["measures"][mid] = { + "source_commit": dashboard["git_sha"], "generated_at": dashboard["generated_at"], + "description": dashboard["description"], "execution": execution, + "disclosure_floor": floor, + "sources": {name: SOURCE + entry["artifact"] + f"/{name}.csv" for name in TABLES}, + "receipt_url": SOURCE + entry["artifact"] + "/receipt.json", "years": years, + } + (SNAPSHOT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n") + print("Verified 8 aggregate CSV hashes, certified provenance and provisional disclosure gates; rebuilt population-preview/summary.json") + + +if __name__ == "__main__": + main() diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md index 1e8e5d52f..3f168b689 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md @@ -2,7 +2,7 @@ The Autumn Budget 2026 increases the basic, higher and additional income tax rat In the examples below, a basic-rate saver with £2,000 of annual interest pays £20 more a year. A landlord with £10,000 of property profit and £4,000 of mortgage interest pays £120 more. -This post examines this provision on its own. The [UK Autumn Budget 2026 dashboard](https://uk-autumn-budget-2026.vercel.app/uk/autumn-budget-2026) shows how it combines with the other announced measures. We cover the trading allowance increase in a [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance). +This post examines this provision on its own. The [UK Autumn Budget 2026 dashboard preview](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026) places it alongside the other announced measures. We cover the trading allowance increase in a [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance). ## What changes in April 2027? @@ -133,6 +133,28 @@ Both pay £200 more before relief, while their finance-cost reduction rises by The property **rate** increase excludes Scottish taxpayers, whose rental income follows Scottish rules. Finance-cost relief is a separate calculation. The [Finance Act 2026 amendment](https://www.legislation.gov.uk/ukpga/2026/11/schedule/1/paragraph/40/enacted) ties it to the UK property basic rate without a Scottish exception. Applying that rule, a Scottish landlord able to use the full reduction on £4,000 of eligible finance costs receives £80 more relief, reducing their income tax by £80 if nothing else changes. A mortgage-free Scottish landlord has no change from this measure. The savings increase still applies across the UK. +## Preliminary national estimates + +The dashboard's [provisional revenue output](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/budgetary_impact.csv), generated on 28 October at 14:34 UTC, estimates that the measure raises **£664 million in 2027–28**, increasing to **£793 million in 2031–32**. These are static annual government-balance effects: savings, rental income and other household circumstances are held fixed. The results are awaiting reconciliation with Treasury costings. + +The [average cash changes](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/winners_losers.csv) show an annual household income reduction of **£22.67 across all households** in 2027–28, including unaffected households. The largest average cash loss is in the highest income decile, at £107.13. Deciles are ranked by baseline equivalised household net income, which accounts for household size. + +| Income decile | Average annual household income change | +| --- | ---: | +| 1 (lowest income) | −£12.90 | +| 2 | −£5.69 | +| 3 | −£6.66 | +| 4 | −£7.31 | +| 5 | −£6.00 | +| 6 | −£9.13 | +| 7 | −£10.94 | +| 8 | −£21.51 | +| 9 | −£37.04 | +| 10 (highest income) | −£107.13 | +| All households | −£22.67 | + +The dashboard's [affected-population metric](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/metrics.csv) is **10.67% of people living in households whose net income changes by more than 0.01%** in 2027–28. It is not a taxpayer count or a headcount. The current exports do not provide separate shares gaining and losing, so an average loss within a decile should not be read as a loss for every household in it. + ## The Treasury forecasts revenue of £1.13 billion in 2028–29 The Treasury costs the savings and property changes separately. Their sum reaches £1,130 million in 2028–29 and £1,045 million in 2031–32. @@ -141,9 +163,10 @@ The Treasury costs the savings and property changes separately. Their sum reache | --- | ---: | ---: | ---: | ---: | ---: | ---: | | Property income rates | 0 | 35 | 575 | 435 | 445 | 455 | | Savings income rates | 15 | 125 | 555 | 520 | 555 | 590 | -| Combined | 15 | 160 | 1,130 | 955 | 1,000 | 1,045 | +| Treasury combined | 15 | 160 | 1,130 | 955 | 1,000 | 1,045 | +| PolicyEngine, provisional static | 0 | 664 | 696 | 728 | 762 | 793 | -These government receipts forecasts differ from annual household liabilities. The [Treasury policy costings, #page 74-75](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74) allow for some landlords incorporating and savers moving funds into tax-advantaged products such as ISAs. A static calculation holds those choices fixed. +These government receipts forecasts differ from annual household liabilities. The [Treasury policy costings, #page 74-75](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74) allow for some landlords incorporating and savers moving funds into tax-advantaged products such as ISAs. The PolicyEngine run holds those choices fixed. Tax-year liabilities and fiscal-year receipts forecasts also differ in timing. Reconciliation has not yet established how much of the gap between these estimates comes from behaviour, collection timing or model coverage. ## Methodology @@ -151,4 +174,8 @@ The examples isolate the newly announced 2027–28 changes, including finance-co The examples use `policyengine.py` 6.11.1 with PolicyEngine UK 2.151.0 and core 3.33.3, matching the pre-Budget policy baseline and parameter changes in the dashboard's [`unearned_income_rates_up` measure](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/b50787aa75ef5aed36b822c973afa6b569464d55/src/uk_budget_data/reforms.py). The calculations check tax changes against independent arithmetic. -This draft reports hypothetical examples and Treasury forecasts. PolicyEngine national revenue, affected-person and decile estimates are pending the population run. That run is pinned to the dashboard's certified national dataset `a6299504`; population forecast inputs and model-coverage limits must accompany its results. +The national figures reuse the dashboard's [recorded execution receipt](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/receipt.json), generated at source commit `0d9dccb2`. They use certified national dataset `microcosm-uk-2024-25-national-20261025T091414Z-a6299504` and the October 2026 OBR forecast overlay on both baseline and reform. Growth series not updated by the overlay retain the model's March forecast path; the dataset retains its pre-Budget calibration. Household examples use fixed nominal incomes. + +The receipt records a passed disclosure floor of at least three survey households per published cell; no thin decile cells are recorded. The affected-population calculation uses the absolute percentage income change, floors baseline household income at £1, and includes only households with a valid decile. Its percentage does not establish how many people gain or lose. + +**Draft status:** the population results are provisional and marked `awaiting_source` for reconciliation in the preview manifest. Final reconciliation, absolute affected-person counts and separate winner/loser shares remain outstanding. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md b/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md index d82f34cad..71b9cdae7 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md @@ -1,6 +1,6 @@ The [Autumn Budget 2026](https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html) announces an increase in the trading allowance from £1,000 to £3,000 from 6 April 2027. The allowance covers eligible trading and miscellaneous income. For an employee paying 20% income tax on their side income, the extra £2,000 deduction can reduce annual income tax by £400. The reduction depends on receipts, expenses and how much tax the individual would otherwise pay. -This post examines that measure on its own. Our [Budget dashboard](https://uk-autumn-budget-2026.vercel.app/uk/autumn-budget-2026) places it alongside the other announced tax and benefit changes. We cover the savings and property income tax increases in a [separate explainer](/uk/research/uk-autumn-budget-2026-savings-property-income-tax). +This post examines that measure on its own. Our [Budget dashboard](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026) places it alongside the other announced tax and benefit changes. We cover the savings and property income tax increases in a [separate explainer](/uk/research/uk-autumn-budget-2026-savings-property-income-tax). ## How the allowance works @@ -123,20 +123,42 @@ Universal Credit uses separate self-employment income rules. The allowance itsel The allowance is unavailable for partnership income and certain connected-party receipts, including income from an individual's employer or a company they control. [HMRC's exclusions](https://www.gov.uk/hmrc-internal-manuals/business-income-manual/bim86030) describe those restrictions. +## Preliminary national estimates + +The dashboard's [provisional cost output](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/budgetary_impact.csv), generated on 28 October at 14:34 UTC, estimates a **£112 million cost in 2027–28** and **£131 million in 2031–32**. These are static annual government-balance effects. The receipt warns that missing gross receipts in the population data can overstate the cost, and the results are awaiting reconciliation with Treasury costings. + +The [average cash changes](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/winners_losers.csv) show a **£3.83 annual household income gain across all households** in 2027–28, including unaffected households. The highest average gain is in decile 8, at £8.57. These population averages include people with no eligible trading income; the worked examples above describe particular eligible individuals. Deciles are ranked by baseline equivalised household net income, which accounts for household size. + +| Income decile | Average annual household income change | +| --- | ---: | +| 1 (lowest income) | +£0.83 | +| 2 | +£3.39 | +| 3 | +£1.04 | +| 4 | +£0.45 | +| 5 | +£2.11 | +| 6 | +£3.43 | +| 7 | +£5.73 | +| 8 | +£8.57 | +| 9 | +£6.18 | +| 10 (highest income) | +£7.03 | +| All households | +£3.83 | + +The dashboard's [affected-population metric](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/metrics.csv) is **0.93% of people living in households whose net income changes by more than 0.01%** in 2027–28. It is not a count of eligible traders. The current exports do not provide separate shares gaining and losing or an absolute affected-person count. + ## Treasury costing -Table 6.1, row 15, gives the following official forecast. These are reductions in Exchequer receipts, expressed below as positive costs; they are not PolicyEngine microsimulation estimates. +The Treasury column reproduces Table 6.1, row 15. The PolicyEngine column reports the provisional static estimates. Both columns express costs to the Exchequer as positive values. -| Fiscal year | Treasury cost (£ million) | -| --- | --- | -| 2026–27 | 0 | -| 2027–28 | 0 | -| 2028–29 | 225 | -| 2029–30 | 165 | -| 2030–31 | 175 | -| 2031–32 | 180 | +| Year | Treasury cost (£ million) | PolicyEngine provisional static cost (£ million) | +| --- | ---: | ---: | +| 2026–27 | 0 | 0 | +| 2027–28 | 0 | 112 | +| 2028–29 | 225 | 120 | +| 2029–30 | 165 | 113 | +| 2030–31 | 175 | 123 | +| 2031–32 | 180 | 131 | -The effective date remains 6 April 2027 even though the Treasury records no receipts effect in 2027–28. A household's tax-year liability and the government's forecast of receipts by fiscal year are different quantities. +The effective date remains 6 April 2027 even though the Treasury records no receipts effect in 2027–28. Tax-year liabilities and the government's fiscal-year receipts forecasts are different quantities. The comparison also needs to allow for model coverage, including missing gross receipts. Reconciliation has not yet attributed the gap between the estimates. ## Methodology and coverage @@ -146,4 +168,8 @@ The household calculations use `policyengine.py` 6.11.1 with PolicyEngine UK 2.1 In the population data, gross receipts are unavailable. The pinned model's [deduction calculation](https://github.com/PolicyEngine/policyengine-uk/blob/2.151.0/policyengine_uk/variables/gov/hmrc/income_tax/allowances/trading_allowance_deduction.py) uses an approximation that can overstate or understate the reform's effect for individual records. It also does not apply this allowance to its separate miscellaneous-income input, although eligible miscellaneous income is within the announced policy. These coverage limits matter when interpreting national results. -This draft reports hypothetical examples and Treasury forecasts. PolicyEngine national cost, affected-person and decile estimates are pending the population run, pinned to the dashboard's certified national dataset `a6299504`. +The national figures reuse the dashboard's [recorded execution receipt](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/receipt.json), generated at source commit `0d9dccb2`. They use certified national dataset `microcosm-uk-2024-25-national-20261025T091414Z-a6299504` and the October 2026 OBR forecast overlay on both baseline and reform. Growth series not updated by the overlay retain the model's March forecast path; the dataset retains its pre-Budget calibration. Household examples use fixed nominal incomes. + +The receipt records a passed disclosure floor of at least three survey households per published cell; no thin decile cells are recorded. The affected-population calculation uses the absolute percentage income change, floors baseline household income at £1, and includes only households with a valid decile. Its percentage does not establish how many people gain or lose. + +**Draft status:** the population results are provisional and marked `awaiting_source` for reconciliation in the preview manifest. Final reconciliation, absolute affected-person counts and separate winner/loser shares remain outstanding. From f581840f590e3a9466a2a03e39a769a0db99f880 Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 11:07:52 -0400 Subject: [PATCH 03/24] Clarify income bands and prepare draft review handoff --- analysis/uk-budget-2026-income-tax/README.md | 2 ++ .../uk-budget-2026-income-tax/REVIEW_NOTES.md | 34 +++++++++++++++++++ ...budget-2026-savings-property-income-tax.md | 18 +++++++++- ...uk-autumn-budget-2026-trading-allowance.md | 4 +-- 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index f063e833c..9af0d0e23 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -46,6 +46,8 @@ Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipt The two articles use the site's native chart blocks and cover assets. No runtime application or country-model code is changed. +See `REVIEW_NOTES.md` for the independent draft-readiness check, the comparison with Pavel's posts and the remaining publication work. + ## Validation on 28 October 2026 `make format`, `make lint`, `make typecheck` and `make test` passed. The tests ran on Node 26.12.1: 6,042 app tests and 508 website tests passed, with 10 app tests skipped by the existing suite. After inserting the final chart data, the chart-parser and post-metadata checks passed again (18 tests). All 23 household comparisons and 20 curve points passed independent arithmetic checks. diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md new file mode 100644 index 000000000..2f21d9c60 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md @@ -0,0 +1,34 @@ +# Draft review handoff + +Both standalone posts are ready for agent review in draft PR #1460. Publication remains a separate decision. + +## Internal readiness check + +An independent policy/source reviewer and code/reproducibility reviewer examined commit `7f90092fa6e6f28f68b419c4edf1bef166d851b9` on 28 October 2026. The review was complete for draft readiness, with no confirmed critical or should-address findings and one optional clarity suggestion. + +- The policy reviewer checked the official Budget, legislation and HMRC guidance, and visually inspected physical pages 23, 74 and 75 of the Treasury costings. The rates, start dates, allowance rules, Scottish finance-cost relief interpretation and Treasury series were corroborated. +- The code reviewer independently reproduced all 23 hypothetical household comparisons and 20 curve points on the pinned bundle. Numeric outputs, CSVs and chart specifications matched the saved results. +- All eight public aggregate CSV hashes matched their receipts. National fiscal signs, decile averages and affected-population percentage units matched the articles. The saved summary reproduced exactly. +- The 18 chart-parser and post-metadata tests passed on the frozen snapshot using Node 26.12.1. The earlier full suite passed 6,550 tests, with 10 existing skips. CI was not monitored. + +The optional suggestion was to name the Treasury's trading-allowance expense-switching response. The follow-up adds that explanation with its physical-page-23 citation. It also adds an explicit savings/property band calculation using the already reproduced `property_then_savings_order` case (£8,582 to £8,732 income tax) and uses the canonical dashboard address shared in the team channel. These are prose and citation changes; model calculations are unchanged. The band table is checked against the saved component and total taxes. + +## What to review + +- Savings/property: income ordering, the transition between basic and higher bands, and the conditional £80 finance-relief gain for Scottish landlords with £4,000 of fully usable finance costs. +- Trading: the receipts-versus-expenses choice, the separate miscellaneous-income coverage limitation and the population approximation when gross receipts are missing. +- Population: the static-model/Treasury comparison and the interpretation of average changes. The producer's `people_affected` field is a percentage of people in households with an absolute income change above 0.01%; it is not a headcount or a separate winner/loser share. + +The source preview remains revision 5, with both entries `provisional` and reconciliation `awaiting_source`. The articles retain those labels. Max's later instruction to call approved outputs “first estimates” is conditional on the checks passing; it is not an approval of this cached snapshot. + +## Before publication + +- Complete reconciliation and confirm or replace the provisional population snapshot. +- Obtain absolute affected-person counts and separate winner/loser shares when available; preserve disclosure controls. +- Resolve or retain explicit limits for missing trading receipts/expenses and miscellaneous income. +- Complete desktop/mobile visual preview and final editorial review. Browser preview was not verified during this work. +- Link the standalone articles from the dashboard. + +## Related team work + +Pavel's [Pension Tax Allowance draft, #1457](https://github.com/PolicyEngine/policyengine-app-v2/pull/1457), and [fuel-duty draft, #1459](https://github.com/PolicyEngine/policyengine-app-v2/pull/1459), informed the calculation-first presentation, explicit assumptions and separation of Treasury costings from model results. They were read as comparative examples, not formally approved by this review. Their shared line-chart work is not required by these posts' existing native bar charts. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md index 3f168b689..a126b8a96 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md @@ -2,7 +2,7 @@ The Autumn Budget 2026 increases the basic, higher and additional income tax rat In the examples below, a basic-rate saver with £2,000 of annual interest pays £20 more a year. A landlord with £10,000 of property profit and £4,000 of mortgage interest pays £120 more. -This post examines this provision on its own. The [UK Autumn Budget 2026 dashboard preview](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026) places it alongside the other announced measures. We cover the trading allowance increase in a [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance). +This post examines this provision on its own. The [UK Autumn Budget 2026 dashboard](https://policyengine.org/uk/budgets/autumn-2026) places it alongside the other announced measures. We cover the trading allowance increase in a [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance). ## What changes in April 2027? @@ -133,6 +133,22 @@ Both pay £200 more before relief, while their finance-cost reduction rises by The property **rate** increase excludes Scottish taxpayers, whose rental income follows Scottish rules. Finance-cost relief is a separate calculation. The [Finance Act 2026 amendment](https://www.legislation.gov.uk/ukpga/2026/11/schedule/1/paragraph/40/enacted) ties it to the UK property basic rate without a Scottish exception. Applying that rule, a Scottish landlord able to use the full reduction on £4,000 of eligible finance costs receives £80 more relief, reducing their income tax by £80 if nothing else changes. A mortgage-free Scottish landlord has no change from this measure. The savings increase still applies across the UK. +## When property income pushes savings into a higher band + +Consider an adult in England with £45,000 of salary, £6,000 of property profit after allowable expenses, £2,000 of interest and no mortgage interest. The £12,570 Personal Allowance leaves £32,430 of taxable salary. That uses £32,430 of the £37,700 basic-rate band, leaving £5,270. + +Property income fills that remaining £5,270, with £730 entering the higher band. The individual qualifies for a £500 Personal Savings Allowance; the remaining £1,500 of interest falls in the higher savings band. + +| Income tax component, 2027–28 | Before | After | +| --- | ---: | ---: | +| Salary: £32,430 at 20% | £6,486.00 | £6,486.00 | +| Property: £5,270 at 22% / 24% | £1,159.40 | £1,264.80 | +| Property: £730 at 42% / 44% | £306.60 | £321.20 | +| Savings: £1,500 at 42% / 44% | £630.00 | £660.00 | +| Total income tax | £8,582.00 | £8,732.00 | + +The extra tax is £120 on property plus £30 on savings, or **£150 a year**. The calculation shows why the order of income sources matters even when each rate rises by the same two percentage points. + ## Preliminary national estimates The dashboard's [provisional revenue output](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/budgetary_impact.csv), generated on 28 October at 14:34 UTC, estimates that the measure raises **£664 million in 2027–28**, increasing to **£793 million in 2031–32**. These are static annual government-balance effects: savings, rental income and other household circumstances are held fixed. The results are awaiting reconciliation with Treasury costings. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md b/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md index 71b9cdae7..d96ab10b1 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md @@ -1,6 +1,6 @@ The [Autumn Budget 2026](https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html) announces an increase in the trading allowance from £1,000 to £3,000 from 6 April 2027. The allowance covers eligible trading and miscellaneous income. For an employee paying 20% income tax on their side income, the extra £2,000 deduction can reduce annual income tax by £400. The reduction depends on receipts, expenses and how much tax the individual would otherwise pay. -This post examines that measure on its own. Our [Budget dashboard](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026) places it alongside the other announced tax and benefit changes. We cover the savings and property income tax increases in a [separate explainer](/uk/research/uk-autumn-budget-2026-savings-property-income-tax). +This post examines that measure on its own. Our [Budget dashboard](https://policyengine.org/uk/budgets/autumn-2026) places it alongside the other announced tax and benefit changes. We cover the savings and property income tax increases in a [separate explainer](/uk/research/uk-autumn-budget-2026-savings-property-income-tax). ## How the allowance works @@ -158,7 +158,7 @@ The Treasury column reproduces Table 6.1, row 15. The PolicyEngine column report | 2030–31 | 175 | 123 | | 2031–32 | 180 | 131 | -The effective date remains 6 April 2027 even though the Treasury records no receipts effect in 2027–28. Tax-year liabilities and the government's fiscal-year receipts forecasts are different quantities. The comparison also needs to allow for model coverage, including missing gross receipts. Reconciliation has not yet attributed the gap between the estimates. +The effective date remains 6 April 2027 even though the Treasury records no receipts effect in 2027–28. Tax-year liabilities and the government's fiscal-year receipts forecasts are different quantities. The [Treasury policy costing](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=23) also allows for taxpayers switching from actual expenses to the larger allowance, a behavioural response. The static model holds circumstances fixed and also faces the gross-receipts coverage limit. Reconciliation has not yet attributed the gap between the estimates. ## Methodology and coverage From cdeb356c2c567fdea1bf73974480c9fba5ee5ba3 Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Wed, 28 Oct 2026 11:39:46 -0400 Subject: [PATCH 04/24] Add a line chart type for blog posts, and valueLabels for bar charts BlogLineChart.tsx draws series against a numeric x axis, with step series, markers labelled in a strip above the plot, an x axis format, a y axis fitted to the data on request, and a y axis width that follows the tick labels. blogChartUtils gains a thousands separator, a niceTicks option that leaves zero out, and validFormat. Bar charts take "valueLabels": false when several series make the labels overlap. chart-standards.md documents both. Used by the Budget 2026 posts (#1457, #1459). Co-Authored-By: Claude Opus 5.5 --- docs/engineering/skills/chart-standards.md | 14 +- .../__tests__/components/blog-chart.test.tsx | 22 ++ .../components/blog-line-chart.test.tsx | 140 +++++++++ website/src/components/blog/BlogChart.tsx | 28 +- website/src/components/blog/BlogLineChart.tsx | 289 ++++++++++++++++++ website/src/components/blog/blogChartUtils.ts | 39 ++- 6 files changed, 514 insertions(+), 18 deletions(-) create mode 100644 website/src/__tests__/components/blog-line-chart.test.tsx create mode 100644 website/src/components/blog/BlogLineChart.tsx diff --git a/docs/engineering/skills/chart-standards.md b/docs/engineering/skills/chart-standards.md index 3e65f9ef2..e4dcc100e 100644 --- a/docs/engineering/skills/chart-standards.md +++ b/docs/engineering/skills/chart-standards.md @@ -242,9 +242,9 @@ import { Posts draw charts as ` ```chart ` fenced blocks holding a JSON spec. `website/src/components/blog/BlogChart.tsx` parses each block and wraps it in a figure with -title, subtitle, watermark and source line. `bar` (in `BlogChart.tsx`) and `waterfall` -(`BlogWaterfallChart.tsx`) draw with Recharts, Inter, the `--chart-*` tokens and ui-kit's -shared axis, grid, tooltip and legend styles. `stateMap` (`BlogStateMap.tsx`) draws an 11 by +title, subtitle, watermark and source line. `bar` (in `BlogChart.tsx`), `line` +(`BlogLineChart.tsx`) and `waterfall` (`BlogWaterfallChart.tsx`) draw with Recharts, Inter, +the `--chart-*` tokens and ui-kit's shared axis, grid, tooltip and legend styles. `stateMap` (`BlogStateMap.tsx`) draws an 11 by 8 tile grid shaded from `--background` to `--primary`. Each file's header comment documents its spec. @@ -254,6 +254,14 @@ its spec. - Do not add matplotlib PNGs or Plotly JSON to new posts. When a post needs a chart type the website lacks (a line or scatter chart, say), add the type to `website/src/components/blog/` with tests before the post uses it. +- `line` draws series against a numeric x axis, such as a tax or benefit schedule by income. + Give it the exact breakpoints plus regular points (every £100, say) so the tooltip has detail + without drawing anything inexact. `"step": true` holds a series' value to the next point, for + marginal rates; `markers` label named x values in a strip above the plot; `xFormat` formats + the x axis; `"yIncludesZero": false` fits the y axis to levels far from zero. +- `format` and `xFormat` take `"separator": true` to group thousands (£13,036). +- A `bar` chart with several series can set `"valueLabels": false` when the labels above the + bars would overlap; the tooltip still gives each value. - `website/src/__tests__/components/blog-chart-posts.test.ts` fails CI when a post's chart block does not parse. Keep the chart's numbers identical to the tables and text beside it. - The website builds Tailwind with the `tw:` prefix, so ui-kit components that rely on diff --git a/website/src/__tests__/components/blog-chart.test.tsx b/website/src/__tests__/components/blog-chart.test.tsx index dee6f2a17..4ae96881d 100644 --- a/website/src/__tests__/components/blog-chart.test.tsx +++ b/website/src/__tests__/components/blog-chart.test.tsx @@ -184,6 +184,28 @@ describe("BlogChart", () => { expect(legend).toEqual(["Census", "PolicyEngine prediction"]); }); + test("valueLabels false draws the bars without value labels", () => { + const { container } = render( + , + ); + const texts = [...container.querySelectorAll("svg text")].map( + (el) => el.textContent, + ); + for (const t of ["+0.07", "+0.22", "−0.06", "+0.86"]) { + expect(texts).not.toContain(t); + } + expect(texts).toContain("+1.00 pp"); + expect(container.querySelectorAll(".recharts-bar-rectangle")).toHaveLength( + 4, + ); + }); + + test("rejects a non-boolean valueLabels", () => { + expect( + parseBlogChartSpec(JSON.stringify({ ...SPEC, valueLabels: "no" })), + ).toBeNull(); + }); + test("names the figure by its title", () => { render(); expect( diff --git a/website/src/__tests__/components/blog-line-chart.test.tsx b/website/src/__tests__/components/blog-line-chart.test.tsx new file mode 100644 index 000000000..8cd33eef5 --- /dev/null +++ b/website/src/__tests__/components/blog-line-chart.test.tsx @@ -0,0 +1,140 @@ +import { cloneElement, type ReactElement } from "react"; +import { render, screen } from "@testing-library/react"; +import { describe, expect, test, vi } from "vitest"; + +import { + BlogChart, + formatChartValue, + niceTicks, + parseBlogChartSpec, +} from "@/components/blog/BlogChart"; + +// jsdom has no layout, so give the responsive container a fixed size. +vi.mock("recharts", async (importOriginal) => { + const mod = await importOriginal(); + return { + ...mod, + ResponsiveContainer: ({ + children, + height, + }: { + children: ReactElement<{ width?: number; height?: number }>; + height?: number | string; + }) => + cloneElement(children, { + width: 600, + height: typeof height === "number" ? height : 240, + }), + }; +}); + +const SPEC = { + type: "line", + title: "Income tax for a single pensioner, 2027-28", + xKey: "income", + xLabel: "Total income", + series: [ + { key: "baseline", name: "Without the allowance", color: "quinary" }, + { key: "reform", name: "With the allowance", color: "primary" }, + ], + data: [ + { income: 12000, baseline: 0, reform: 0 }, + { income: 12570, baseline: 0, reform: 0 }, + { income: 13036.4, baseline: 93.28, reform: 0 }, + { income: 13800, baseline: 246, reform: 246 }, + ], + markers: [{ x: 12570, label: "Personal Allowance" }], + format: { prefix: "£", decimals: 0, separator: true }, + xFormat: { prefix: "£", decimals: 0, separator: true }, + source: "PolicyEngine UK", +}; + +const parse = (spec: unknown) => parseBlogChartSpec(JSON.stringify(spec)); + +describe("line chart spec", () => { + test("a valid spec parses as a line chart", () => { + expect(parse(SPEC)?.type).toBe("line"); + }); + + test("yIncludesZero false parses", () => { + expect(parse({ ...SPEC, yIncludesZero: false })?.type).toBe("line"); + }); + + test("a step series parses", () => { + const spec = { + ...SPEC, + series: [{ key: "reform", name: "Rate", step: true }], + }; + expect(parse(spec)?.type).toBe("line"); + }); + + test.each([ + ["x values out of order", { data: [...SPEC.data].reverse() }], + [ + "a row missing a series value", + { data: [...SPEC.data.slice(0, 3), { income: 13800, baseline: 246 }] }, + ], + [ + "a string x value", + { data: [{ ...SPEC.data[0], income: "low" }, SPEC.data[1]] }, + ], + ["one data row", { data: [SPEC.data[0]] }], + ["a marker without a label", { markers: [{ x: 12570 }] }], + [ + "a non-boolean step", + { series: [{ key: "reform", name: "R", step: "yes" }] }, + ], + ["a bad x format", { xFormat: { separator: "yes" } }], + ["a bad x label", { xLabel: 3 }], + ["a non-boolean yIncludesZero", { yIncludesZero: "no" }], + ])("rejects %s", (_, override) => { + expect(parse({ ...SPEC, ...override })).toBeNull(); + }); +}); + +describe("line chart rendering", () => { + test("renders the title, series names, marker label and source", () => { + render(); + expect( + screen.getByText("Income tax for a single pensioner, 2027-28"), + ).toBeInTheDocument(); + expect(screen.getByText("Without the allowance")).toBeInTheDocument(); + expect(screen.getByText("With the allowance")).toBeInTheDocument(); + expect(screen.getByText("Personal Allowance")).toBeInTheDocument(); + expect(screen.getByText("PolicyEngine UK")).toBeInTheDocument(); + }); + + test("an invalid spec renders nothing", () => { + const { container } = render( + , + ); + expect(container).toBeEmptyDOMElement(); + }); +}); + +describe("chart helpers", () => { + test("the separator groups thousands", () => { + expect( + formatChartValue(13036.4, { prefix: "£", decimals: 2, separator: true }), + ).toBe("£13,036.40"); + expect(formatChartValue(-1234567, { decimals: 0, separator: true })).toBe( + "−1,234,567", + ); + expect(formatChartValue(999, { decimals: 0, separator: true })).toBe("999"); + }); + + test("without the separator, values stay ungrouped", () => { + expect(formatChartValue(13036, { decimals: 0 })).toBe("13036"); + }); + + test("niceTicks can leave zero out of the range", () => { + const axis = niceTicks([12000, 13800], 6, false); + expect(axis.domain[0]).toBeGreaterThan(0); + expect(axis.ticks[0]).toBeLessThanOrEqual(12000); + expect(axis.ticks.at(-1)).toBeGreaterThanOrEqual(13800); + }); + + test("niceTicks includes zero by default", () => { + expect(niceTicks([12000, 13800]).domain[0]).toBe(0); + }); +}); diff --git a/website/src/components/blog/BlogChart.tsx b/website/src/components/blog/BlogChart.tsx index d2bd74c1e..272bea86a 100644 --- a/website/src/components/blog/BlogChart.tsx +++ b/website/src/components/blog/BlogChart.tsx @@ -9,8 +9,8 @@ * Posts carry data, not styling. Styles are inline token variables because * the website's Tailwind build uses a prefix that ui-kit's utility classes lack. * - * Types: "bar" (below), "waterfall" (BlogWaterfallChart.tsx) and "stateMap" - * (BlogStateMap.tsx). Every type takes an optional "title", "subtitle" and + * Types: "bar" (below), "line" (BlogLineChart.tsx), "waterfall" + * (BlogWaterfallChart.tsx) and "stateMap" (BlogStateMap.tsx). Every type takes an optional "title", "subtitle" and * "source"; an invalid spec renders nothing. * * Spec (type "bar"): @@ -22,8 +22,13 @@ * "data": [{ "group": "All people", "census": 0.07 }, ...], * "yLabel": "...", * "format": { "decimals": 2, "suffix": " pp", "signed": true }, + * "valueLabels": false, * "source": "..." * } + * + * "valueLabels" (default true) prints each bar's value above it. Set it to + * false when several series make the labels overlap; the tooltip still + * gives each value. */ import { type ReactNode, useId } from "react"; @@ -58,6 +63,7 @@ import { niceTicks, validSharedFields, } from "./blogChartUtils"; +import { type BlogLineSpec, LineBody, parseLineSpec } from "./BlogLineChart"; import { type BlogStateMapSpec, StateMapBody, @@ -87,17 +93,22 @@ export interface BlogBarChartSpec { data: BlogChartRow[]; yLabel?: string; format?: BlogChartFormat; + valueLabels?: boolean; source?: string; height?: number; } export type BlogChartSpec = | BlogBarChartSpec + | BlogLineSpec | BlogWaterfallSpec | BlogStateMapSpec; function parseBarSpec(s: Record): BlogBarChartSpec | null { if (s.type !== "bar" || typeof s.xKey !== "string") return null; + if (s.valueLabels !== undefined && typeof s.valueLabels !== "boolean") { + return null; + } if (!Array.isArray(s.series) || s.series.length === 0) return null; if (!Array.isArray(s.data) || s.data.length === 0) return null; if ( @@ -134,6 +145,8 @@ export function parseBlogChartSpec(raw: string): BlogChartSpec | null { switch (spec.type) { case "bar": return parseBarSpec(spec); + case "line": + return parseLineSpec(spec); case "waterfall": return parseWaterfallSpec(spec); case "stateMap": @@ -240,10 +253,12 @@ function BarBody({ spec }: { spec: BlogBarChartSpec }) { radius={[2, 2, 0, 0]} isAnimationActive={false} > - } - /> + {spec.valueLabels !== false && ( + } + /> + )} ))} @@ -325,6 +340,7 @@ export function BlogChart({ data }: { data: string | string[] }) { return ( {spec.type === "bar" && } + {spec.type === "line" && } {spec.type === "waterfall" && } {spec.type === "stateMap" && } diff --git a/website/src/components/blog/BlogLineChart.tsx b/website/src/components/blog/BlogLineChart.tsx new file mode 100644 index 000000000..94e6ed510 --- /dev/null +++ b/website/src/components/blog/BlogLineChart.tsx @@ -0,0 +1,289 @@ +"use client"; + +/** + * Line body for ```chart blocks of type "line". + * + * Draws one or more series against a numeric x axis, such as a tax schedule + * by income. Both axes round out to nice ticks; the y axis includes zero + * unless "yIncludesZero" is false, and the x axis spans the data only. A series with "step": true holds each value + * until the next point, for rates that jump at thresholds. Optional markers + * draw dashed vertical lines at named x values, labelled horizontally in a + * strip above the plot, one row per marker, so labels cross neither the + * data nor each other. + * + * Spec: + * { + * "type": "line", + * "title": "...", "subtitle": "...", + * "xKey": "income", + * "xLabel": "Total income", + * "series": [ + * { "key": "baseline", "name": "Without the reform", "color": "quinary" }, + * { "key": "reform", "name": "With the reform", "color": "primary", "step": false } + * ], + * "data": [{ "income": 12000, "baseline": 0, "reform": 0 }, ...], + * "markers": [{ "x": 12570, "label": "Personal Allowance" }], + * "yLabel": "...", + * "format": { "prefix": "£", "decimals": 0, "separator": true }, + * "xFormat": { "prefix": "£", "decimals": 0, "separator": true }, + * "source": "..." + * } + * + * Data rows must be sorted by x, and every row needs a number for every + * series, or the spec is rejected. + */ + +import { + AXIS_STYLE, + GRID_STYLE, + LEGEND_STYLE, + TOOLTIP_STYLE, +} from "@policyengine/ui-kit/charts"; +import { + CartesianGrid, + Legend, + Line, + LineChart, + ReferenceLine, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from "recharts"; + +import { + type BlogChartFormat, + type BlogChartRow, + type ChartColorName, + chartColor, + formatChartValue, + isFiniteNumber, + isRecord, + niceTicks, + validFormat, +} from "./blogChartUtils"; + +export interface BlogLineSeries { + key: string; + name: string; + color?: ChartColorName; + step?: boolean; +} + +export interface BlogLineMarker { + x: number; + label: string; +} + +export interface BlogLineSpec { + type: "line"; + title?: string; + subtitle?: string; + xKey: string; + xLabel?: string; + series: BlogLineSeries[]; + data: BlogChartRow[]; + markers?: BlogLineMarker[]; + yLabel?: string; + /** False fits the y axis to the data, for levels far from zero. */ + yIncludesZero?: boolean; + format?: BlogChartFormat; + xFormat?: BlogChartFormat; + source?: string; + height?: number; +} + +export function parseLineSpec(s: Record): BlogLineSpec | null { + if (s.type !== "line" || typeof s.xKey !== "string") return null; + if (s.xLabel !== undefined && typeof s.xLabel !== "string") return null; + if (!validFormat(s.xFormat)) return null; + if (s.yIncludesZero !== undefined && typeof s.yIncludesZero !== "boolean") { + return null; + } + if (!Array.isArray(s.series) || s.series.length === 0) return null; + if ( + !s.series.every( + (x) => + isRecord(x) && + typeof x.key === "string" && + typeof x.name === "string" && + (x.step === undefined || typeof x.step === "boolean"), + ) + ) { + return null; + } + if (!Array.isArray(s.data) || s.data.length < 2) return null; + const keys = (s.series as BlogLineSeries[]).map((x) => x.key); + const xKey = s.xKey; + let previous = -Infinity; + for (const row of s.data) { + if (!isRecord(row) || !isFiniteNumber(row[xKey])) return null; + if (row[xKey] < previous) return null; + previous = row[xKey]; + if (!keys.every((k) => isFiniteNumber(row[k]))) return null; + } + if ( + s.markers !== undefined && + !( + Array.isArray(s.markers) && + s.markers.every( + (m) => + isRecord(m) && isFiniteNumber(m.x) && typeof m.label === "string", + ) + ) + ) { + return null; + } + return s as unknown as BlogLineSpec; +} + +const MARKER_ROW_HEIGHT = 16; + +interface MarkerLabelProps { + viewBox?: { x?: number; y?: number }; + value: string; + row: number; + rows: number; + anchor: "start" | "end"; +} + +/** A marker's label in the strip above the plot, in its own row, beside its + * line: right of it in the left half of the plot, left of it in the right + * half. */ +function MarkerLabel({ viewBox, value, row, rows, anchor }: MarkerLabelProps) { + const x = Number(viewBox?.x); + const y = Number(viewBox?.y); + if (!Number.isFinite(x) || !Number.isFinite(y)) return null; + return ( + + {value} + + ); +} + +export function LineBody({ spec }: { spec: BlogLineSpec }) { + const format = spec.format ?? {}; + const xFormat = spec.xFormat ?? {}; + const xs = spec.data.map((row) => row[spec.xKey] as number); + const values = spec.data.flatMap((row) => + spec.series.map((s) => row[s.key] as number), + ); + const yAxis = niceTicks(values, 4, spec.yIncludesZero ?? true); + const xAxis = niceTicks(xs, 6, false); + const xMin = Math.min(...xs); + const xMax = Math.max(...xs); + const xTicks = xAxis.ticks.filter((t) => t >= xMin && t <= xMax); + const markerRows = spec.markers?.length ?? 0; + const yTick = (v: number) => + formatChartValue(v, { ...format, decimals: yAxis.decimals }); + // Room for the longest tick label, plus the rotated axis title. + const yAxisWidth = + Math.max(...yAxis.ticks.map((t) => yTick(t).length)) * 7 + + (spec.yLabel ? 28 : 12); + const xTick = (v: number) => + formatChartValue(v, { ...xFormat, decimals: xAxis.decimals }); + + return ( + + + + + + {(spec.markers ?? []).map((m, i) => ( + ( + + )} + /> + ))} + formatChartValue(Number(x), xFormat)} + formatter={(value, name) => [ + formatChartValue(Number(value), format), + String(name), + ]} + /> + + {spec.series.map((s, i) => ( + + ))} + + + ); +} diff --git a/website/src/components/blog/blogChartUtils.ts b/website/src/components/blog/blogChartUtils.ts index 643b3c0bf..aed48956f 100644 --- a/website/src/components/blog/blogChartUtils.ts +++ b/website/src/components/blog/blogChartUtils.ts @@ -11,6 +11,8 @@ export interface BlogChartFormat { prefix?: string; suffix?: string; signed?: boolean; + /** Group thousands with commas, as in £13,036. */ + separator?: boolean; } export type BlogChartRow = Record; @@ -30,24 +32,36 @@ export function formatChartValue( value: number, format: BlogChartFormat = {}, ): string { - const { decimals = 1, prefix = "", suffix = "", signed = false } = format; + const { + decimals = 1, + prefix = "", + suffix = "", + signed = false, + separator = false, + } = format; const digits = Math.min(MAX_DECIMALS, Math.max(0, Math.round(decimals))); - const magnitude = Math.abs(value).toFixed(digits); - const isZero = Number(magnitude) === 0; + const fixed = Math.abs(value).toFixed(digits); + const magnitude = separator + ? fixed.replace(/^\d+/, (whole) => whole.replace(/\B(?=(\d{3})+$)/g, ",")) + : fixed; + const isZero = Number(fixed) === 0; const sign = value < 0 && !isZero ? "−" : signed && !isZero ? "+" : ""; return `${sign}${prefix}${magnitude}${suffix}`; } /** * Round the value range out to a step of 1, 2, 2.5 or 5 times a power of ten, - * including zero, so tick labels land on round numbers. + * including zero unless `includeZero` is false, so tick labels land on round + * numbers. */ export function niceTicks( values: number[], target = 4, + includeZero = true, ): { domain: [number, number]; ticks: number[]; decimals: number } { - const lo = values.reduce((a, b) => Math.min(a, b), 0); - const hi = values.reduce((a, b) => Math.max(a, b), 0); + const seed = includeZero || values.length === 0 ? 0 : values[0]; + const lo = values.reduce((a, b) => Math.min(a, b), seed); + const hi = values.reduce((a, b) => Math.max(a, b), seed); // A span under 1e-9 gets a unit axis: a smaller step underflows, or needs // more decimals than toFixed allows. const span = hi - lo >= 1e-9 ? hi - lo : 1; @@ -90,10 +104,16 @@ export function validSharedFields(s: Record): boolean { if (s.height !== undefined && !(isFiniteNumber(s.height) && s.height > 0)) { return false; } - const { format } = s; + return validFormat(s.format); +} + +/** An optional BlogChartFormat with every field of the right type. */ +export function validFormat(format: unknown): boolean { + const optionalString = (v: unknown) => + v === undefined || typeof v === "string"; if (format === undefined) return true; if (!isRecord(format)) return false; - const { decimals, prefix, suffix, signed } = format; + const { decimals, prefix, suffix, signed, separator } = format; return ( (decimals === undefined || (Number.isInteger(decimals) && @@ -101,7 +121,8 @@ export function validSharedFields(s: Record): boolean { (decimals as number) <= MAX_DECIMALS)) && optionalString(prefix) && optionalString(suffix) && - (signed === undefined || typeof signed === "boolean") + (signed === undefined || typeof signed === "boolean") && + (separator === undefined || typeof separator === "boolean") ); } From 5a70185ae5ea8e947b155ebcd048e0e2e1cf7148 Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 11:41:49 -0400 Subject: [PATCH 05/24] Keep savings/property post and shared analysis in base draft --- analysis/uk-budget-2026-income-tax/README.md | 9 + .../uk-budget-2026-income-tax/REVIEW_NOTES.md | 26 + .../dashboard_salary_comparison.json | 54 + .../generate_trading_extensions.py | 225 ++++ .../uk-budget-2026-income-tax/provenance.json | 9 + .../trading_extensions.json | 966 ++++++++++++++++++ ...k-autumn-budget-2026-trading-allowance.svg | 45 - ...budget-2026-savings-property-income-tax.md | 60 +- ...uk-autumn-budget-2026-trading-allowance.md | 175 ---- app/src/data/posts/posts.json | 9 - 10 files changed, 1321 insertions(+), 257 deletions(-) create mode 100644 analysis/uk-budget-2026-income-tax/dashboard_salary_comparison.json create mode 100644 analysis/uk-budget-2026-income-tax/generate_trading_extensions.py create mode 100644 analysis/uk-budget-2026-income-tax/trading_extensions.json delete mode 100644 app/public/assets/posts/uk-autumn-budget-2026-trading-allowance.svg delete mode 100644 app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index 9af0d0e23..e5a2edd2b 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -53,3 +53,12 @@ See `REVIEW_NOTES.md` for the independent draft-readiness check, the comparison `make format`, `make lint`, `make typecheck` and `make test` passed. The tests ran on Node 26.12.1: 6,042 app tests and 508 website tests passed, with 10 app tests skipped by the existing suite. After inserting the final chart data, the chart-parser and post-metadata checks passed again (18 tests). All 23 household comparisons and 20 curve points passed independent arithmetic checks. After adding the provisional national sections, snapshot verification and the article/chart checks passed again. Browser access to the local preview was declined, so visual preview remains outstanding. The SVG cover XML and native chart specs were validated, but this does not confirm page layout at desktop or mobile widths. + + +## Additional trading and calculator examples + +```sh +analysis/uk-budget-2026-income-tax/.venv/bin/python analysis/uk-budget-2026-income-tax/generate_trading_extensions.py +``` + +This checks five additional synthetic pairs requested in Max's review, including UC, Class4 and missing-receipts fallbacks. `trading_extensions.json` records complete inputs, raw outputs and arithmetic checks. `dashboard_salary_comparison.json` records the calculator's March-index salary comparison. Household examples use no population data. Shared analysis is kept in the savings/property base PR so the trading article can be reviewed in a separate stacked PR. diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md index 2f21d9c60..458323ea2 100644 --- a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md +++ b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md @@ -32,3 +32,29 @@ The source preview remains revision 5, with both entries `provisional` and recon ## Related team work Pavel's [Pension Tax Allowance draft, #1457](https://github.com/PolicyEngine/policyengine-app-v2/pull/1457), and [fuel-duty draft, #1459](https://github.com/PolicyEngine/policyengine-app-v2/pull/1459), informed the calculation-first presentation, explicit assumptions and separation of Treasury costings from model results. They were read as comparative examples, not formally approved by this review. Their shared line-chart work is not required by these posts' existing native bar charts. + + +## Follow-up to Max's reviews + +Max's trading review is [comment6472758764](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472758764); savings/property is [comment6472939282](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472939282), with calculator alignment in [comment6473177137](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6473177137). + +Addressed in the next draft revision: + +- Whole-pound prose/summary tables; pence retained in worked calculations and exact source records. +- National headlines; England explicitly named for the mortgaged landlord; government reach figures explained with their different denominators. +- Clearer source citations and reader-facing methods; build-status fields, identifiers and review history retained here and in provenance rather than the article text. +- The UC parent and full-time sole trader are reproduced by `generate_trading_extensions.py`: five pairs passed. The £4,000-receipts parent gains £180 after £220 of UC withdrawal; the sole trader gains £520 including £120 Class4. +- For the specified £18,000-wage parent at £1,500 receipts, the gain is £45 (tax−£100, UC−£55). Max's £79 case needs exact inputs to resolve; it was not copied into the article. +- Missing-receipts examples demonstrate £300 instead of £100 of tax relief for the small trader, and £0 instead of £520 of tax/NI savings for the sole trader. +- The calculator salary comparison is recorded in `dashboard_salary_comparison.json`: the pinned March earnings index grows a £45,000 2026 salary to about £46,080 in2027; taxes round to£9,014/£9,164, change£150. The article's fixed2027salary remains£45,000, taxes£8,582/£8,732. No finance-cost calculator input exists. +- Companion household-preset work is dashboard [PR292](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/292). At checked head65ea750a, the £45k/£6k/£2k recommendation had not yet replaced its older preset. No unsupported preset deep link is used. + +Still needed before publication: + +- Final population regeneration, with a component CSV/receipt binding the exact dataset bytes and updated forecast. Max's earlier ad32af7f run reproduces the saved first estimates but does not supply those component artifacts. His later correction on dashboard#290 calls for detailed October forecast tables and council tax in the final regeneration. The dataset pin has not changed automatically. +- Weighted tax/benefit totals and household counts by decile. Person-weighted deciles with household-weighted cash means do not justify dividing one mean by the sum of means to claim a48% revenue share. +- A bottom-decile income-source breakdown explaining its higher average loss; no cause has been inferred. +- Max's internal260,000-person income-tax count and£71m miscellaneous-income sensitivity need scripts/aggregate receipts, output definitions and unique source-household support. The latter also needs a single shared trading/miscellaneous allowance and explicit eligibility/expense assumptions; it is not treated as a proven upper bound. These numbers are not added as reproduced results. +- Replace preview artifact links when verified public artifacts exist; complete visual preview and editorial review. + +The articles remain drafts. Publication approval is separate from readiness for agent review. The trading article will have its own stacked PR, reusing this shared analysis foundation. diff --git a/analysis/uk-budget-2026-income-tax/dashboard_salary_comparison.json b/analysis/uk-budget-2026-income-tax/dashboard_salary_comparison.json new file mode 100644 index 000000000..3c65d13a8 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/dashboard_salary_comparison.json @@ -0,0 +1,54 @@ +{ + "scope": "Synthetic salary-uprating comparison; no population data", + "versions": { + "policyengine": "6.11.1", + "policyengine-uk": "2.151.0", + "policyengine-core": "3.33.3" + }, + "year": 2027, + "salary_input_year": 2026, + "salary_growth_basis": "Pinned UK March OBR average earnings index, Jan1 to Jan1, matching calculator earnings_growth", + "growth_factor": 1.0240009985556604, + "inputs": { + "age": 35, + "employment_income": 46080.04493500472, + "property_income": 6000, + "savings_interest_income": 2000 + }, + "baseline": { + "income_tax": 9014.02, + "savings_income_tax": 630.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 1500.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 1682.01, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 6000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 2680.81, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "reform": { + "income_tax": 9164.02, + "savings_income_tax": 660.0, + "savings_allowance": 500.0, + "savings_starter_rate_income": 0.0, + "basic_rate_savings_income": 0.0, + "higher_rate_savings_income": 1500.0, + "add_rate_savings_income": 0.0, + "property_income_tax": 1802.01, + "property_finance_cost_relief": 0.0, + "taxable_property_income": 6000.0, + "trading_allowance_deduction": 0.0, + "taxable_self_employment_income": 0.0, + "national_insurance": 2680.81, + "ni_class_4": 0.0, + "household_benefits": 0.0 + }, + "income_tax_change": 150.0, + "reference": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/292#issuecomment-6473170340" +} diff --git a/analysis/uk-budget-2026-income-tax/generate_trading_extensions.py b/analysis/uk-budget-2026-income-tax/generate_trading_extensions.py new file mode 100644 index 000000000..75ab4a13c --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/generate_trading_extensions.py @@ -0,0 +1,225 @@ +"""Reproduce synthetic trading-allowance examples requested in Max's review. + +Run: .venv/bin/python generate_trading_extensions.py +Only trading_extensions.json is written; no population data are used. +""" + +from __future__ import annotations + +import argparse +from datetime import datetime, timezone +import importlib.metadata as metadata +import json +import math +from pathlib import Path +import platform +import warnings + +import policyengine as pe + + +YEAR = 2027 +ALLOWANCE_PATH = "gov.hmrc.income_tax.allowances.trading_allowance" +REFORM = {ALLOWANCE_PATH: 3_000} +VERSIONS = {"policyengine": "6.11.1", "policyengine-uk": "2.151.0", "policyengine-core": "3.33.3"} +REVIEW_URL = "https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472758764" +PERSON_OUTPUTS = [ + "employment_income", "self_employment_income", "self_employment_gross_receipts", + "income_tax", "national_insurance", "ni_class_4", "taxable_self_employment_income", + "trading_allowance_deduction", "uc_income_tax_on_earnings", "uc_income_tax_on_trade", + "uc_national_insurance_on_earnings", "uc_national_insurance_on_trade", + "uc_individual_earned_income_before_mif", "uc_individual_earned_income", + "uc_is_in_gainful_self_employment", "uc_mif_applies", +] +BENUNIT_OUTPUTS = [ + "universal_credit", "universal_credit_pre_benefit_cap", "claims_universal_credit", + "uc_maximum_amount", "uc_standard_allowance", "uc_child_element", + "uc_housing_costs_element", "uc_work_allowance", "uc_earned_income_before_work_allowance", + "uc_earned_income", "uc_income_reduction", "uc_benefit_cap_reduction", "child_benefit", +] +HOUSEHOLD_OUTPUTS = [ + "household_net_income", "hbai_household_net_income", "household_benefits", + "household_tax", "household_market_income", "household_gross_income", "rent", "council_tax", +] + + +def close(actual: float, expected: float, label: str) -> None: + if not math.isclose(actual, expected, abs_tol=0.02, rel_tol=0): + raise AssertionError(f"{label}: actual {actual}, independent expectation {expected}") + + +def parameters() -> dict: + # Parameter inspection only; all tax/benefit computation uses pe.uk below. + from policyengine_uk.system import system + + nodes = { + "trading_allowance": ALLOWANCE_PATH, + "uc_taper": "gov.dwp.universal_credit.means_test.reduction_rate", + "uc_work_allowance_monthly_with_housing": "gov.dwp.universal_credit.means_test.work_allowance.with_housing", + "uc_work_allowance_monthly_without_housing": "gov.dwp.universal_credit.means_test.work_allowance.without_housing", + } + values = {name: float(system.parameters.get_child(path)(f"{YEAR}-04-06")) for name, path in nodes.items()} + close(values["trading_allowance"], 1_000, "baseline trading allowance") + close(values["uc_taper"], 0.55, "UC taper") + return values + + +def lone_parent(receipts: int, supply_receipts: bool = True) -> dict: + adult = { + "age": 35, "employment_status": "PT_EMPLOYED", "hours_worked": 20 * 52, + "employment_income": 18_000, "self_employment_income": receipts, + # Employment is the main job. This is the statutory gainful-employment + # determination, not an override of an income floor or UC award. + "uc_is_in_gainful_self_employment": False, + } + if supply_receipts: + adult["self_employment_gross_receipts"] = receipts + return { + "people": [adult, {"age": 4, "employment_status": "CHILD"}], + "benunit": {"would_claim_uc": True, "would_claim_child_benefit": True}, + "household": { + "region": "LONDON", "brma": "CENTRAL_LONDON", + "tenure_type": "RENT_PRIVATELY", "rent": 12_000, "council_tax": 0, + }, + } + + +def sole_trader(supply_receipts: bool = True) -> dict: + adult = { + "age": 35, "employment_status": "FT_SELF_EMPLOYED", "hours_worked": 35 * 52, + "employment_income": 0, "self_employment_income": 19_500, + "uc_is_in_gainful_self_employment": True, + } + if supply_receipts: + adult["self_employment_gross_receipts"] = 20_000 + return { + "people": [adult], "benunit": {"would_claim_uc": False, "would_claim_child_benefit": False}, + "household": {"region": "LONDON", "brma": "CENTRAL_LONDON", "tenure_type": "OWNED_OUTRIGHT", "rent": 0, "council_tax": 0}, + } + + +def calculate(inputs: dict, reform: dict) -> dict: + result = pe.uk.calculate_household( + **inputs, year=YEAR, reform=reform, + extra_variables=PERSON_OUTPUTS + BENUNIT_OUTPUTS + HOUSEHOLD_OUTPUTS, + ) + # Preserve wrapper-provided floating-point values, including float32 + # representation differences, rather than rounding the recorded raw output. + return { + "person": [{name: float(getattr(person, name)) for name in PERSON_OUTPUTS} for person in result.person], + "benunit": {name: float(getattr(result.benunit, name)) for name in BENUNIT_OUTPUTS}, + "household": {name: float(getattr(result.household, name)) for name in HOUSEHOLD_OUTPUTS}, + } + + +def run_case(case: dict, law: dict) -> dict: + baseline = calculate(case["inputs"], {}) + reformed = calculate(case["inputs"], REFORM) + delta = { + "income_tax": sum(person["income_tax"] for person in reformed["person"]) - sum(person["income_tax"] for person in baseline["person"]), + "national_insurance": sum(person["national_insurance"] for person in reformed["person"]) - sum(person["national_insurance"] for person in baseline["person"]), + "ni_class_4": sum(person["ni_class_4"] for person in reformed["person"]) - sum(person["ni_class_4"] for person in baseline["person"]), + "universal_credit": reformed["benunit"]["universal_credit"] - baseline["benunit"]["universal_credit"], + "household_benefits": reformed["household"]["household_benefits"] - baseline["household"]["household_benefits"], + "household_net_income": reformed["household"]["household_net_income"] - baseline["household"]["household_net_income"], + "hbai_household_net_income": reformed["household"]["hbai_household_net_income"] - baseline["household"]["hbai_household_net_income"], + } + for scenario, expected in case["independent_oracle"].items(): + for name, amount in expected.items(): + actual = delta[name] if scenario == "change" else baseline["person"][0][name] if scenario == "baseline" else reformed["person"][0][name] + close(actual, amount, f"{case['id']} {scenario} {name}") + close(delta["household_benefits"], delta["universal_credit"], f"{case['id']} other benefits unchanged") + close(delta["household_net_income"], -delta["income_tax"] - delta["national_insurance"] + delta["universal_credit"], f"{case['id']} net-income identity") + trace = None + if case["type"] == "lone_parent": + old_uc, new_uc = baseline["benunit"], reformed["benunit"] + for result in (baseline, reformed): + assert result["benunit"]["universal_credit"] > 0 + close(result["person"][0]["uc_mif_applies"], 0, f"{case['id']} MIF") + assert result["benunit"]["uc_earned_income_before_work_allowance"] > result["benunit"]["uc_work_allowance"] + close(new_uc["uc_work_allowance"], old_uc["uc_work_allowance"], f"{case['id']} work allowance unchanged") + earnings_change = new_uc["uc_earned_income_before_work_allowance"] - old_uc["uc_earned_income_before_work_allowance"] + close(earnings_change, -delta["income_tax"] - delta["national_insurance"], f"{case['id']} UC net-earnings increase") + close(delta["universal_credit"], -law["uc_taper"] * earnings_change, f"{case['id']} UC taper arithmetic") + trace = { + "baseline_annual_uc_earnings_before_work_allowance": old_uc["uc_earned_income_before_work_allowance"], + "reform_annual_uc_earnings_before_work_allowance": new_uc["uc_earned_income_before_work_allowance"], + "annual_work_allowance": old_uc["uc_work_allowance"], + "baseline_earnings_above_work_allowance": old_uc["uc_earned_income"], + "reform_earnings_above_work_allowance": new_uc["uc_earned_income"], + "explanation": "Employment earnings already exceed the work allowance. The entire increase in UC net earnings is tapered at 55%; no work-allowance boundary is crossed.", + } + comparison = None + if "review_claim" in case: + comparison = { + "claim": case["review_claim"], + "matches": all(math.isclose(delta[name], amount, abs_tol=0.02, rel_tol=0) for name, amount in case["review_claim"].items()), + } + return {**case, "baseline": baseline, "reform": reformed, "change": delta, "uc_trace": trace, "review_comparison": comparison} + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--output", type=Path, default=Path(__file__).with_name("trading_extensions.json")) + args = parser.parse_args() + versions = {name: metadata.version(name) for name in VERSIONS} + assert versions == VERSIONS, (versions, VERSIONS) + warnings.filterwarnings("ignore", category=RuntimeWarning, message="(divide by zero|invalid value) encountered in (divide|multiply)") + warnings.filterwarnings("ignore", category=UserWarning, message="Accessing \\.values on a MicroSeries returns a plain numpy array without weights\\.") + law = parameters() + cases = [ + { + "id": "lone_parent_4000_receipts", "type": "lone_parent", "inputs": lone_parent(4_000), + "gross_receipts_supplied": True, "actual_expenses": 0, + "independent_oracle": {"baseline": {"taxable_self_employment_income": 3_000, "income_tax": 1_686}, "reform": {"taxable_self_employment_income": 1_000, "income_tax": 1_286}, "change": {"income_tax": -400, "national_insurance": 0, "universal_credit": -220, "household_net_income": 180}}, + "review_claim": {"income_tax": -400, "universal_credit": -220, "household_net_income": 180}, + }, + { + "id": "lone_parent_1500_receipts", "type": "lone_parent", "inputs": lone_parent(1_500), + "gross_receipts_supplied": True, "actual_expenses": 0, + "independent_oracle": {"baseline": {"taxable_self_employment_income": 500, "income_tax": 1_186}, "reform": {"taxable_self_employment_income": 0, "income_tax": 1_086}, "change": {"income_tax": -100, "national_insurance": 0, "universal_credit": -55, "household_net_income": 45}}, + "review_claim": {"income_tax": -100, "universal_credit": -21, "household_net_income": 79}, + }, + { + "id": "lone_parent_1500_profit_receipts_omitted", "type": "lone_parent", "inputs": lone_parent(1_500, False), + "gross_receipts_supplied": False, "actual_expenses": 0, + "independent_oracle": {"baseline": {"taxable_self_employment_income": 1_500, "income_tax": 1_386}, "reform": {"taxable_self_employment_income": 0, "income_tax": 1_086}, "change": {"income_tax": -300, "national_insurance": 0, "universal_credit": -165, "household_net_income": 135}}, + "limitation": "Omitting receipts activates the pinned model's fallback. This £300 tax reduction exceeds the legally calculated £100 with receipts supplied; the resulting net gain is £135 instead of £45.", + }, + { + "id": "sole_trader_20000_receipts_500_expenses", "type": "sole_trader", "inputs": sole_trader(), + "gross_receipts_supplied": True, "actual_expenses": 500, + "independent_oracle": {"baseline": {"taxable_self_employment_income": 19_000, "income_tax": 1_286, "ni_class_4": 385.8}, "reform": {"taxable_self_employment_income": 17_000, "income_tax": 886, "ni_class_4": 265.8}, "change": {"income_tax": -400, "national_insurance": -120, "universal_credit": 0, "household_net_income": 520}}, + "review_claim": {"income_tax": -400, "ni_class_4": -120, "household_net_income": 520}, + }, + { + "id": "sole_trader_19500_profit_receipts_omitted", "type": "sole_trader", "inputs": sole_trader(False), + "gross_receipts_supplied": False, "actual_expenses": 500, + "independent_oracle": {"baseline": {"taxable_self_employment_income": 19_500, "income_tax": 1_386, "ni_class_4": 415.8}, "reform": {"taxable_self_employment_income": 19_500, "income_tax": 1_386, "ni_class_4": 415.8}, "change": {"income_tax": 0, "national_insurance": 0, "universal_credit": 0, "household_net_income": 0}}, + "limitation": "With receipts omitted, profit exceeds both allowance amounts, so the pinned fallback applies no relief on either side. It misses the £520 gain calculated when £20,000 receipts and £500 expenses are represented.", + }, + ] + outputs = [] + for case in cases: + output = run_case(case, law) + outputs.append(output) + print(f"{case['id']}: " + json.dumps({name: round(value, 2) for name, value in output["change"].items()}), flush=True) + payload = { + "metadata": { + "generated_at_utc": datetime.now(timezone.utc).isoformat(), "model_year": YEAR, + "tax_year": "2027–28", "versions": versions, "python": platform.python_version(), + "review_url": REVIEW_URL, "review_comment_timestamp_utc": "2026-10-28T15:11:33Z", + "baseline_parameters": law, "reform": REFORM, + "scope": "Five synthetic case pairs; no population data, behavioural responses or national estimates. Annual model calculations; actual UC assessment periods and timing of tax payments can differ.", + "assumptions": "Lone parent age35 with child age4, employment as main job, £18,000 annual wages, side business with zero expenses, London/Central London private rent £12,000/year, UC and Child Benefit take-up true. Sole trader age35, full-time35hours/week, £20,000 receipts and £500 costs, no other income, owns home outright, no UC claim. Both: council tax input zero; no childcare costs, capital, disability, pensions, losses or other income. Omitted inputs otherwise retain pinned model defaults. No UC award, floor amount, work allowance, or earnings intermediate is forced.", + "oracle_tolerance_gbp": 0.02, + "independent_arithmetic": "Basic-rate income tax20% above Personal Allowance£12,570; known-receipt taxable profit=max(0,receipts-max(expenses,allowance)); Class4 NI6% above£12,570; active UC award falls55% of extra UC net earnings above its unchanged work allowance. Missing-receipt outputs separately test the pinned fallback, not the legal receipt-based calculation.", + }, + "cases": outputs, + } + args.output.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n") + print(f"Verified {len(outputs)} case pairs; wrote {args.output}", flush=True) + + +if __name__ == "__main__": + main() diff --git a/analysis/uk-budget-2026-income-tax/provenance.json b/analysis/uk-budget-2026-income-tax/provenance.json index 143214131..07f8bdc76 100644 --- a/analysis/uk-budget-2026-income-tax/provenance.json +++ b/analysis/uk-budget-2026-income-tax/provenance.json @@ -92,5 +92,14 @@ 175, 180 ] + }, + "review_follow_up": { + "trading_comment": "https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472758764", + "savings_property_comment": "https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472939282", + "dashboard_households_pr": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/292", + "additional_household_pairs": 5, + "raw_population_accessed": false, + "additional_internal_population_numbers_adopted": false, + "final_regeneration_note": "Detailed October forecast tables and council tax are expected; retain the recorded first-estimate snapshot until replacement outputs bind the exact dataset and forecast." } } diff --git a/analysis/uk-budget-2026-income-tax/trading_extensions.json b/analysis/uk-budget-2026-income-tax/trading_extensions.json new file mode 100644 index 000000000..7a8ae6f2f --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/trading_extensions.json @@ -0,0 +1,966 @@ +{ + "metadata": { + "generated_at_utc": "2026-10-28T15:19:07.459647+00:00", + "model_year": 2027, + "tax_year": "2027–28", + "versions": { + "policyengine": "6.11.1", + "policyengine-uk": "2.151.0", + "policyengine-core": "3.33.3" + }, + "python": "3.13.14", + "review_url": "https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472758764", + "review_comment_timestamp_utc": "2026-10-28T15:11:33Z", + "baseline_parameters": { + "trading_allowance": 1000.0, + "uc_taper": 0.55, + "uc_work_allowance_monthly_with_housing": 441.94429445251563, + "uc_work_allowance_monthly_without_housing": 734.8488268414194 + }, + "reform": { + "gov.hmrc.income_tax.allowances.trading_allowance": 3000 + }, + "scope": "Five synthetic case pairs; no population data, behavioural responses or national estimates. Annual model calculations; actual UC assessment periods and timing of tax payments can differ.", + "assumptions": "Lone parent age35 with child age4, employment as main job, £18,000 annual wages, side business with zero expenses, London/Central London private rent £12,000/year, UC and Child Benefit take-up true. Sole trader age35, full-time35hours/week, £20,000 receipts and £500 costs, no other income, owns home outright, no UC claim. Both: council tax input zero; no childcare costs, capital, disability, pensions, losses or other income. Omitted inputs otherwise retain pinned model defaults. No UC award, floor amount, work allowance, or earnings intermediate is forced.", + "oracle_tolerance_gbp": 0.02, + "independent_arithmetic": "Basic-rate income tax20% above Personal Allowance£12,570; known-receipt taxable profit=max(0,receipts-max(expenses,allowance)); Class4 NI6% above£12,570; active UC award falls55% of extra UC net earnings above its unchanged work allowance. Missing-receipt outputs separately test the pinned fallback, not the legal receipt-based calculation." + }, + "cases": [ + { + "id": "lone_parent_4000_receipts", + "type": "lone_parent", + "inputs": { + "people": [ + { + "age": 35, + "employment_status": "PT_EMPLOYED", + "hours_worked": 1040, + "employment_income": 18000, + "self_employment_income": 4000, + "uc_is_in_gainful_self_employment": false, + "self_employment_gross_receipts": 4000 + }, + { + "age": 4, + "employment_status": "CHILD" + } + ], + "benunit": { + "would_claim_uc": true, + "would_claim_child_benefit": true + }, + "household": { + "region": "LONDON", + "brma": "CENTRAL_LONDON", + "tenure_type": "RENT_PRIVATELY", + "rent": 12000, + "council_tax": 0 + } + }, + "gross_receipts_supplied": true, + "actual_expenses": 0, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 3000, + "income_tax": 1686 + }, + "reform": { + "taxable_self_employment_income": 1000, + "income_tax": 1286 + }, + "change": { + "income_tax": -400, + "national_insurance": 0, + "universal_credit": -220, + "household_net_income": 180 + } + }, + "review_claim": { + "income_tax": -400, + "universal_credit": -220, + "household_net_income": 180 + }, + "baseline": { + "person": [ + { + "employment_income": 18000.0, + "self_employment_income": 4000.0, + "self_employment_gross_receipts": 4000.0, + "income_tax": 1686.0, + "national_insurance": 434.4031066894531, + "ni_class_4": 0.0, + "taxable_self_employment_income": 3000.0, + "trading_allowance_deduction": 1000.0, + "uc_income_tax_on_earnings": 1686.0, + "uc_income_tax_on_trade": 600.0, + "uc_national_insurance_on_earnings": 434.4031066894531, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 19879.59765625, + "uc_individual_earned_income": 19879.59765625, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + }, + { + "employment_income": 0.0, + "self_employment_income": 0.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "taxable_self_employment_income": 0.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 0.0, + "uc_income_tax_on_trade": 0.0, + "uc_national_insurance_on_earnings": 0.0, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 0.0, + "uc_individual_earned_income": 0.0, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + } + ], + "benunit": { + "universal_credit": 13076.5009765625, + "universal_credit_pre_benefit_cap": 13076.5009765625, + "claims_universal_credit": 1.0, + "uc_maximum_amount": 21093.447265625, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 3774.9287109375, + "uc_housing_costs_element": 12000.0, + "uc_work_allowance": 5303.33154296875, + "uc_earned_income_before_work_allowance": 19879.59765625, + "uc_earned_income": 14576.265625, + "uc_income_reduction": 8016.9462890625, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 1455.8287353515625 + }, + "household": { + "household_net_income": 36801.48828125, + "hbai_household_net_income": 34411.92578125, + "household_benefits": 17101.892578125, + "household_tax": 2300.403076171875, + "household_market_income": 22000.0, + "household_gross_income": 39101.890625, + "rent": 12000.0, + "council_tax": 0.0 + } + }, + "reform": { + "person": [ + { + "employment_income": 18000.0, + "self_employment_income": 4000.0, + "self_employment_gross_receipts": 4000.0, + "income_tax": 1286.0, + "national_insurance": 434.4031066894531, + "ni_class_4": 0.0, + "taxable_self_employment_income": 1000.0, + "trading_allowance_deduction": 3000.0, + "uc_income_tax_on_earnings": 1286.0, + "uc_income_tax_on_trade": 200.0, + "uc_national_insurance_on_earnings": 434.4031066894531, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 20279.59765625, + "uc_individual_earned_income": 20279.59765625, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + }, + { + "employment_income": 0.0, + "self_employment_income": 0.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "taxable_self_employment_income": 0.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 0.0, + "uc_income_tax_on_trade": 0.0, + "uc_national_insurance_on_earnings": 0.0, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 0.0, + "uc_individual_earned_income": 0.0, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + } + ], + "benunit": { + "universal_credit": 12856.5009765625, + "universal_credit_pre_benefit_cap": 12856.5009765625, + "claims_universal_credit": 1.0, + "uc_maximum_amount": 21093.447265625, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 3774.9287109375, + "uc_housing_costs_element": 12000.0, + "uc_work_allowance": 5303.33154296875, + "uc_earned_income_before_work_allowance": 20279.59765625, + "uc_earned_income": 14976.265625, + "uc_income_reduction": 8236.9462890625, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 1455.8287353515625 + }, + "household": { + "household_net_income": 36981.48828125, + "hbai_household_net_income": 34591.92578125, + "household_benefits": 16881.892578125, + "household_tax": 1900.403076171875, + "household_market_income": 22000.0, + "household_gross_income": 38881.890625, + "rent": 12000.0, + "council_tax": 0.0 + } + }, + "change": { + "income_tax": -400.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "universal_credit": -220.0, + "household_benefits": -220.0, + "household_net_income": 180.0, + "hbai_household_net_income": 180.0 + }, + "uc_trace": { + "baseline_annual_uc_earnings_before_work_allowance": 19879.59765625, + "reform_annual_uc_earnings_before_work_allowance": 20279.59765625, + "annual_work_allowance": 5303.33154296875, + "baseline_earnings_above_work_allowance": 14576.265625, + "reform_earnings_above_work_allowance": 14976.265625, + "explanation": "Employment earnings already exceed the work allowance. The entire increase in UC net earnings is tapered at 55%; no work-allowance boundary is crossed." + }, + "review_comparison": { + "claim": { + "income_tax": -400, + "universal_credit": -220, + "household_net_income": 180 + }, + "matches": true + } + }, + { + "id": "lone_parent_1500_receipts", + "type": "lone_parent", + "inputs": { + "people": [ + { + "age": 35, + "employment_status": "PT_EMPLOYED", + "hours_worked": 1040, + "employment_income": 18000, + "self_employment_income": 1500, + "uc_is_in_gainful_self_employment": false, + "self_employment_gross_receipts": 1500 + }, + { + "age": 4, + "employment_status": "CHILD" + } + ], + "benunit": { + "would_claim_uc": true, + "would_claim_child_benefit": true + }, + "household": { + "region": "LONDON", + "brma": "CENTRAL_LONDON", + "tenure_type": "RENT_PRIVATELY", + "rent": 12000, + "council_tax": 0 + } + }, + "gross_receipts_supplied": true, + "actual_expenses": 0, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 500, + "income_tax": 1186 + }, + "reform": { + "taxable_self_employment_income": 0, + "income_tax": 1086 + }, + "change": { + "income_tax": -100, + "national_insurance": 0, + "universal_credit": -55, + "household_net_income": 45 + } + }, + "review_claim": { + "income_tax": -100, + "universal_credit": -21, + "household_net_income": 79 + }, + "baseline": { + "person": [ + { + "employment_income": 18000.0, + "self_employment_income": 1500.0, + "self_employment_gross_receipts": 1500.0, + "income_tax": 1186.0, + "national_insurance": 434.4031066894531, + "ni_class_4": 0.0, + "taxable_self_employment_income": 500.0, + "trading_allowance_deduction": 1000.0, + "uc_income_tax_on_earnings": 1186.0, + "uc_income_tax_on_trade": 100.0, + "uc_national_insurance_on_earnings": 434.4031066894531, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 17879.59765625, + "uc_individual_earned_income": 17879.59765625, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + }, + { + "employment_income": 0.0, + "self_employment_income": 0.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "taxable_self_employment_income": 0.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 0.0, + "uc_income_tax_on_trade": 0.0, + "uc_national_insurance_on_earnings": 0.0, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 0.0, + "uc_individual_earned_income": 0.0, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + } + ], + "benunit": { + "universal_credit": 14176.5009765625, + "universal_credit_pre_benefit_cap": 14176.5009765625, + "claims_universal_credit": 1.0, + "uc_maximum_amount": 21093.447265625, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 3774.9287109375, + "uc_housing_costs_element": 12000.0, + "uc_work_allowance": 5303.33154296875, + "uc_earned_income_before_work_allowance": 17879.59765625, + "uc_earned_income": 12576.265625, + "uc_income_reduction": 6916.9462890625, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 1455.8287353515625 + }, + "household": { + "household_net_income": 35901.48828125, + "hbai_household_net_income": 33511.92578125, + "household_benefits": 18201.892578125, + "household_tax": 1800.403076171875, + "household_market_income": 19500.0, + "household_gross_income": 37701.890625, + "rent": 12000.0, + "council_tax": 0.0 + } + }, + "reform": { + "person": [ + { + "employment_income": 18000.0, + "self_employment_income": 1500.0, + "self_employment_gross_receipts": 1500.0, + "income_tax": 1086.0, + "national_insurance": 434.4031066894531, + "ni_class_4": 0.0, + "taxable_self_employment_income": 0.0, + "trading_allowance_deduction": 1500.0, + "uc_income_tax_on_earnings": 1086.0, + "uc_income_tax_on_trade": 0.0, + "uc_national_insurance_on_earnings": 434.4031066894531, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 17979.59765625, + "uc_individual_earned_income": 17979.59765625, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + }, + { + "employment_income": 0.0, + "self_employment_income": 0.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "taxable_self_employment_income": 0.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 0.0, + "uc_income_tax_on_trade": 0.0, + "uc_national_insurance_on_earnings": 0.0, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 0.0, + "uc_individual_earned_income": 0.0, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + } + ], + "benunit": { + "universal_credit": 14121.5009765625, + "universal_credit_pre_benefit_cap": 14121.5009765625, + "claims_universal_credit": 1.0, + "uc_maximum_amount": 21093.447265625, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 3774.9287109375, + "uc_housing_costs_element": 12000.0, + "uc_work_allowance": 5303.33154296875, + "uc_earned_income_before_work_allowance": 17979.59765625, + "uc_earned_income": 12676.265625, + "uc_income_reduction": 6971.9462890625, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 1455.8287353515625 + }, + "household": { + "household_net_income": 35946.48828125, + "hbai_household_net_income": 33556.92578125, + "household_benefits": 18146.892578125, + "household_tax": 1700.403076171875, + "household_market_income": 19500.0, + "household_gross_income": 37646.890625, + "rent": 12000.0, + "council_tax": 0.0 + } + }, + "change": { + "income_tax": -100.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "universal_credit": -55.0, + "household_benefits": -55.0, + "household_net_income": 45.0, + "hbai_household_net_income": 45.0 + }, + "uc_trace": { + "baseline_annual_uc_earnings_before_work_allowance": 17879.59765625, + "reform_annual_uc_earnings_before_work_allowance": 17979.59765625, + "annual_work_allowance": 5303.33154296875, + "baseline_earnings_above_work_allowance": 12576.265625, + "reform_earnings_above_work_allowance": 12676.265625, + "explanation": "Employment earnings already exceed the work allowance. The entire increase in UC net earnings is tapered at 55%; no work-allowance boundary is crossed." + }, + "review_comparison": { + "claim": { + "income_tax": -100, + "universal_credit": -21, + "household_net_income": 79 + }, + "matches": false + } + }, + { + "id": "lone_parent_1500_profit_receipts_omitted", + "type": "lone_parent", + "inputs": { + "people": [ + { + "age": 35, + "employment_status": "PT_EMPLOYED", + "hours_worked": 1040, + "employment_income": 18000, + "self_employment_income": 1500, + "uc_is_in_gainful_self_employment": false + }, + { + "age": 4, + "employment_status": "CHILD" + } + ], + "benunit": { + "would_claim_uc": true, + "would_claim_child_benefit": true + }, + "household": { + "region": "LONDON", + "brma": "CENTRAL_LONDON", + "tenure_type": "RENT_PRIVATELY", + "rent": 12000, + "council_tax": 0 + } + }, + "gross_receipts_supplied": false, + "actual_expenses": 0, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 1500, + "income_tax": 1386 + }, + "reform": { + "taxable_self_employment_income": 0, + "income_tax": 1086 + }, + "change": { + "income_tax": -300, + "national_insurance": 0, + "universal_credit": -165, + "household_net_income": 135 + } + }, + "limitation": "Omitting receipts activates the pinned model's fallback. This £300 tax reduction exceeds the legally calculated £100 with receipts supplied; the resulting net gain is £135 instead of £45.", + "baseline": { + "person": [ + { + "employment_income": 18000.0, + "self_employment_income": 1500.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 1386.0, + "national_insurance": 434.4031066894531, + "ni_class_4": 0.0, + "taxable_self_employment_income": 1500.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 1386.0, + "uc_income_tax_on_trade": 300.0, + "uc_national_insurance_on_earnings": 434.4031066894531, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 17679.59765625, + "uc_individual_earned_income": 17679.59765625, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + }, + { + "employment_income": 0.0, + "self_employment_income": 0.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "taxable_self_employment_income": 0.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 0.0, + "uc_income_tax_on_trade": 0.0, + "uc_national_insurance_on_earnings": 0.0, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 0.0, + "uc_individual_earned_income": 0.0, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + } + ], + "benunit": { + "universal_credit": 14286.5009765625, + "universal_credit_pre_benefit_cap": 14286.5009765625, + "claims_universal_credit": 1.0, + "uc_maximum_amount": 21093.447265625, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 3774.9287109375, + "uc_housing_costs_element": 12000.0, + "uc_work_allowance": 5303.33154296875, + "uc_earned_income_before_work_allowance": 17679.59765625, + "uc_earned_income": 12376.265625, + "uc_income_reduction": 6806.9462890625, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 1455.8287353515625 + }, + "household": { + "household_net_income": 35811.48828125, + "hbai_household_net_income": 33421.92578125, + "household_benefits": 18311.892578125, + "household_tax": 2000.403076171875, + "household_market_income": 19500.0, + "household_gross_income": 37811.890625, + "rent": 12000.0, + "council_tax": 0.0 + } + }, + "reform": { + "person": [ + { + "employment_income": 18000.0, + "self_employment_income": 1500.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 1086.0, + "national_insurance": 434.4031066894531, + "ni_class_4": 0.0, + "taxable_self_employment_income": 0.0, + "trading_allowance_deduction": 1500.0, + "uc_income_tax_on_earnings": 1086.0, + "uc_income_tax_on_trade": 0.0, + "uc_national_insurance_on_earnings": 434.4031066894531, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 17979.59765625, + "uc_individual_earned_income": 17979.59765625, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + }, + { + "employment_income": 0.0, + "self_employment_income": 0.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "taxable_self_employment_income": 0.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 0.0, + "uc_income_tax_on_trade": 0.0, + "uc_national_insurance_on_earnings": 0.0, + "uc_national_insurance_on_trade": 0.0, + "uc_individual_earned_income_before_mif": 0.0, + "uc_individual_earned_income": 0.0, + "uc_is_in_gainful_self_employment": 0.0, + "uc_mif_applies": 0.0 + } + ], + "benunit": { + "universal_credit": 14121.5009765625, + "universal_credit_pre_benefit_cap": 14121.5009765625, + "claims_universal_credit": 1.0, + "uc_maximum_amount": 21093.447265625, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 3774.9287109375, + "uc_housing_costs_element": 12000.0, + "uc_work_allowance": 5303.33154296875, + "uc_earned_income_before_work_allowance": 17979.59765625, + "uc_earned_income": 12676.265625, + "uc_income_reduction": 6971.9462890625, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 1455.8287353515625 + }, + "household": { + "household_net_income": 35946.48828125, + "hbai_household_net_income": 33556.92578125, + "household_benefits": 18146.892578125, + "household_tax": 1700.403076171875, + "household_market_income": 19500.0, + "household_gross_income": 37646.890625, + "rent": 12000.0, + "council_tax": 0.0 + } + }, + "change": { + "income_tax": -300.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "universal_credit": -165.0, + "household_benefits": -165.0, + "household_net_income": 135.0, + "hbai_household_net_income": 135.0 + }, + "uc_trace": { + "baseline_annual_uc_earnings_before_work_allowance": 17679.59765625, + "reform_annual_uc_earnings_before_work_allowance": 17979.59765625, + "annual_work_allowance": 5303.33154296875, + "baseline_earnings_above_work_allowance": 12376.265625, + "reform_earnings_above_work_allowance": 12676.265625, + "explanation": "Employment earnings already exceed the work allowance. The entire increase in UC net earnings is tapered at 55%; no work-allowance boundary is crossed." + }, + "review_comparison": null + }, + { + "id": "sole_trader_20000_receipts_500_expenses", + "type": "sole_trader", + "inputs": { + "people": [ + { + "age": 35, + "employment_status": "FT_SELF_EMPLOYED", + "hours_worked": 1820, + "employment_income": 0, + "self_employment_income": 19500, + "uc_is_in_gainful_self_employment": true, + "self_employment_gross_receipts": 20000 + } + ], + "benunit": { + "would_claim_uc": false, + "would_claim_child_benefit": false + }, + "household": { + "region": "LONDON", + "brma": "CENTRAL_LONDON", + "tenure_type": "OWNED_OUTRIGHT", + "rent": 0, + "council_tax": 0 + } + }, + "gross_receipts_supplied": true, + "actual_expenses": 500, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 19000, + "income_tax": 1286, + "ni_class_4": 385.8 + }, + "reform": { + "taxable_self_employment_income": 17000, + "income_tax": 886, + "ni_class_4": 265.8 + }, + "change": { + "income_tax": -400, + "national_insurance": -120, + "universal_credit": 0, + "household_net_income": 520 + } + }, + "review_claim": { + "income_tax": -400, + "ni_class_4": -120, + "household_net_income": 520 + }, + "baseline": { + "person": [ + { + "employment_income": 0.0, + "self_employment_income": 19500.0, + "self_employment_gross_receipts": 20000.0, + "income_tax": 1286.0, + "national_insurance": 385.79998779296875, + "ni_class_4": 385.79998779296875, + "taxable_self_employment_income": 19000.0, + "trading_allowance_deduction": 500.0, + "uc_income_tax_on_earnings": 1286.0, + "uc_income_tax_on_trade": 1286.0, + "uc_national_insurance_on_earnings": 385.79998779296875, + "uc_national_insurance_on_trade": 385.79998779296875, + "uc_individual_earned_income_before_mif": 17828.19921875, + "uc_individual_earned_income": 20386.02734375, + "uc_is_in_gainful_self_employment": 1.0, + "uc_mif_applies": 1.0 + } + ], + "benunit": { + "universal_credit": 0.0, + "universal_credit_pre_benefit_cap": 0.0, + "claims_universal_credit": 0.0, + "uc_maximum_amount": 5318.5185546875, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 0.0, + "uc_housing_costs_element": 0.0, + "uc_work_allowance": 0.0, + "uc_earned_income_before_work_allowance": 20386.02734375, + "uc_earned_income": 20386.02734375, + "uc_income_reduction": 5318.5185546875, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 0.0 + }, + "household": { + "household_net_income": 17648.19921875, + "hbai_household_net_income": 17828.19921875, + "household_benefits": 0.0, + "household_tax": 1851.800048828125, + "household_market_income": 19500.0, + "household_gross_income": 19500.0, + "rent": 0.0, + "council_tax": 0.0 + } + }, + "reform": { + "person": [ + { + "employment_income": 0.0, + "self_employment_income": 19500.0, + "self_employment_gross_receipts": 20000.0, + "income_tax": 886.0, + "national_insurance": 265.79998779296875, + "ni_class_4": 265.79998779296875, + "taxable_self_employment_income": 17000.0, + "trading_allowance_deduction": 2500.0, + "uc_income_tax_on_earnings": 886.0, + "uc_income_tax_on_trade": 886.0, + "uc_national_insurance_on_earnings": 265.79998779296875, + "uc_national_insurance_on_trade": 265.79998779296875, + "uc_individual_earned_income_before_mif": 18348.19921875, + "uc_individual_earned_income": 20386.02734375, + "uc_is_in_gainful_self_employment": 1.0, + "uc_mif_applies": 1.0 + } + ], + "benunit": { + "universal_credit": 0.0, + "universal_credit_pre_benefit_cap": 0.0, + "claims_universal_credit": 0.0, + "uc_maximum_amount": 5318.5185546875, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 0.0, + "uc_housing_costs_element": 0.0, + "uc_work_allowance": 0.0, + "uc_earned_income_before_work_allowance": 20386.02734375, + "uc_earned_income": 20386.02734375, + "uc_income_reduction": 5318.5185546875, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 0.0 + }, + "household": { + "household_net_income": 18168.19921875, + "hbai_household_net_income": 18348.19921875, + "household_benefits": 0.0, + "household_tax": 1331.800048828125, + "household_market_income": 19500.0, + "household_gross_income": 19500.0, + "rent": 0.0, + "council_tax": 0.0 + } + }, + "change": { + "income_tax": -400.0, + "national_insurance": -120.0, + "ni_class_4": -120.0, + "universal_credit": 0.0, + "household_benefits": 0.0, + "household_net_income": 520.0, + "hbai_household_net_income": 520.0 + }, + "uc_trace": null, + "review_comparison": { + "claim": { + "income_tax": -400, + "ni_class_4": -120, + "household_net_income": 520 + }, + "matches": true + } + }, + { + "id": "sole_trader_19500_profit_receipts_omitted", + "type": "sole_trader", + "inputs": { + "people": [ + { + "age": 35, + "employment_status": "FT_SELF_EMPLOYED", + "hours_worked": 1820, + "employment_income": 0, + "self_employment_income": 19500, + "uc_is_in_gainful_self_employment": true + } + ], + "benunit": { + "would_claim_uc": false, + "would_claim_child_benefit": false + }, + "household": { + "region": "LONDON", + "brma": "CENTRAL_LONDON", + "tenure_type": "OWNED_OUTRIGHT", + "rent": 0, + "council_tax": 0 + } + }, + "gross_receipts_supplied": false, + "actual_expenses": 500, + "independent_oracle": { + "baseline": { + "taxable_self_employment_income": 19500, + "income_tax": 1386, + "ni_class_4": 415.8 + }, + "reform": { + "taxable_self_employment_income": 19500, + "income_tax": 1386, + "ni_class_4": 415.8 + }, + "change": { + "income_tax": 0, + "national_insurance": 0, + "universal_credit": 0, + "household_net_income": 0 + } + }, + "limitation": "With receipts omitted, profit exceeds both allowance amounts, so the pinned fallback applies no relief on either side. It misses the £520 gain calculated when £20,000 receipts and £500 expenses are represented.", + "baseline": { + "person": [ + { + "employment_income": 0.0, + "self_employment_income": 19500.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 1386.0, + "national_insurance": 415.79998779296875, + "ni_class_4": 415.79998779296875, + "taxable_self_employment_income": 19500.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 1386.0, + "uc_income_tax_on_trade": 1386.0, + "uc_national_insurance_on_earnings": 415.79998779296875, + "uc_national_insurance_on_trade": 415.79998779296875, + "uc_individual_earned_income_before_mif": 17698.19921875, + "uc_individual_earned_income": 20386.02734375, + "uc_is_in_gainful_self_employment": 1.0, + "uc_mif_applies": 1.0 + } + ], + "benunit": { + "universal_credit": 0.0, + "universal_credit_pre_benefit_cap": 0.0, + "claims_universal_credit": 0.0, + "uc_maximum_amount": 5318.5185546875, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 0.0, + "uc_housing_costs_element": 0.0, + "uc_work_allowance": 0.0, + "uc_earned_income_before_work_allowance": 20386.02734375, + "uc_earned_income": 20386.02734375, + "uc_income_reduction": 5318.5185546875, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 0.0 + }, + "household": { + "household_net_income": 17518.19921875, + "hbai_household_net_income": 17698.19921875, + "household_benefits": 0.0, + "household_tax": 1981.800048828125, + "household_market_income": 19500.0, + "household_gross_income": 19500.0, + "rent": 0.0, + "council_tax": 0.0 + } + }, + "reform": { + "person": [ + { + "employment_income": 0.0, + "self_employment_income": 19500.0, + "self_employment_gross_receipts": 0.0, + "income_tax": 1386.0, + "national_insurance": 415.79998779296875, + "ni_class_4": 415.79998779296875, + "taxable_self_employment_income": 19500.0, + "trading_allowance_deduction": 0.0, + "uc_income_tax_on_earnings": 1386.0, + "uc_income_tax_on_trade": 1386.0, + "uc_national_insurance_on_earnings": 415.79998779296875, + "uc_national_insurance_on_trade": 415.79998779296875, + "uc_individual_earned_income_before_mif": 17698.19921875, + "uc_individual_earned_income": 20386.02734375, + "uc_is_in_gainful_self_employment": 1.0, + "uc_mif_applies": 1.0 + } + ], + "benunit": { + "universal_credit": 0.0, + "universal_credit_pre_benefit_cap": 0.0, + "claims_universal_credit": 0.0, + "uc_maximum_amount": 5318.5185546875, + "uc_standard_allowance": 5318.5185546875, + "uc_child_element": 0.0, + "uc_housing_costs_element": 0.0, + "uc_work_allowance": 0.0, + "uc_earned_income_before_work_allowance": 20386.02734375, + "uc_earned_income": 20386.02734375, + "uc_income_reduction": 5318.5185546875, + "uc_benefit_cap_reduction": 0.0, + "child_benefit": 0.0 + }, + "household": { + "household_net_income": 17518.19921875, + "hbai_household_net_income": 17698.19921875, + "household_benefits": 0.0, + "household_tax": 1981.800048828125, + "household_market_income": 19500.0, + "household_gross_income": 19500.0, + "rent": 0.0, + "council_tax": 0.0 + } + }, + "change": { + "income_tax": 0.0, + "national_insurance": 0.0, + "ni_class_4": 0.0, + "universal_credit": 0.0, + "household_benefits": 0.0, + "household_net_income": 0.0, + "hbai_household_net_income": 0.0 + }, + "uc_trace": null, + "review_comparison": null + } + ] +} diff --git a/app/public/assets/posts/uk-autumn-budget-2026-trading-allowance.svg b/app/public/assets/posts/uk-autumn-budget-2026-trading-allowance.svg deleted file mode 100644 index c1eea2abc..000000000 --- a/app/public/assets/posts/uk-autumn-budget-2026-trading-allowance.svg +++ /dev/null @@ -1,45 +0,0 @@ - - The trading allowance rises to £3,000 - UK Autumn Budget 2026 raises the annual trading allowance from 1,000 pounds to 3,000 pounds from 6 April 2027. Eligible individuals choose the allowance or actual expenses. - - - - - - - - - - - - - - - - - - - - - - - - - UK Autumn Budget 2026 - The trading allowance - rises to £3,000 - - - Current annual allowance - £1,000 - - From 6 April 2027 - £3,000 - Eligible trading and miscellaneous income · Choose the allowance or actual expenses - diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md index a126b8a96..18f1e9fe0 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md @@ -1,12 +1,14 @@ The Autumn Budget 2026 increases the basic, higher and additional income tax rates on savings and property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%**. Savings rates apply across the UK. The property rates apply in England, Wales and Northern Ireland. Dividend rates remain unchanged. These are the changes announced in the [Budget 2026 document](https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html). -In the examples below, a basic-rate saver with £2,000 of annual interest pays £20 more a year. A landlord with £10,000 of property profit and £4,000 of mortgage interest pays £120 more. +PolicyEngine estimates that the measure raises **£664 million in 2027–28**, compared with the Treasury's **£160 million** for that year. These are preliminary static estimates; the Treasury costing includes behavioural responses. -This post examines this provision on its own. The [UK Autumn Budget 2026 dashboard](https://policyengine.org/uk/budgets/autumn-2026) places it alongside the other announced measures. We cover the trading allowance increase in a [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance). +A basic-rate saver with £2,000 of annual interest pays £20 more a year. A landlord in England with £10,000 of property profit and £4,000 of mortgage interest pays £120 more; a Scottish landlord with the same fully usable finance costs pays £80 less. + +A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. ## What changes in April 2027? -Budget 2025 had already set savings and property rates at 22%, 42% and 47% from April 2027. The comparison here therefore measures the additional two-point increase announced in 2026, using the existing 2027 rules as the baseline. +The [Budget 2025 technical note](https://www.gov.uk/government/publications/changes-to-tax-rates-for-property-savings-and-dividend-income/change-to-tax-rates-for-property-savings-and-dividend-income-technical-note) had already set savings and property rates at 22%, 42% and 47% from April 2027. The additional two-point increase is measured against those existing 2027 rules. | Income tax band | Already scheduled for 2027–28 | Budget 2026 rate | Change | | --- | ---: | ---: | ---: | @@ -14,7 +16,7 @@ Budget 2025 had already set savings and property rates at 22%, 42% and 47% from | Higher | 42% | 44% | +2 percentage points | | Additional | 47% | 49% | +2 percentage points | -The [Budget 2025 technical note](https://www.gov.uk/government/publications/changes-to-tax-rates-for-property-savings-and-dividend-income/change-to-tax-rates-for-property-savings-and-dividend-income-technical-note) sets the ordering from April 2027: employment, pension and trading income first; property next; savings after that; and dividends last. Allowances first reduce income other than property, savings or dividends. Taxable income then fills the bands in that order, so employment and rental income can push savings interest into a higher band. +The same note sets the ordering from April 2027: employment, pension and trading income first; property next; savings after that; and dividends last. Allowances first reduce income other than property, savings or dividends. Taxable income then fills the bands in that order, so employment and rental income can push savings interest into a higher band. ## Savers pay the higher rates on interest above their allowances @@ -116,7 +118,7 @@ The chart varies annual interest for the same two salaries. At these income leve For individual residential landlords, mortgage interest normally produces a tax reduction rather than a deduction from rental profits. The reduction is limited by finance costs, property profits, adjusted total income and the tax liability. [HMRC's explanation of residential finance-cost relief](https://www.gov.uk/guidance/changes-to-tax-relief-for-residential-landlords-how-its-worked-out-including-case-studies) describes these limits. -From April 2027 the relief follows the property basic rate. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. +From April 2027 the relief follows the property basic rate, as the [Treasury policy costings, pages 74 and 75](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74 "Treasury policy costings #page 74-75") confirm. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. The dashboard calculator has no finance-cost input, so the mortgage examples below illustrate an effect its preset cannot show. Consider two adults in England, each with £12,000 of rent, £2,000 of allowable non-finance expenses and £4,000 of qualifying mortgage interest. Deducting actual non-finance expenses leaves £10,000 of property profit. Both can use the full finance-cost reduction. @@ -149,49 +151,51 @@ Property income fills that remaining £5,270, with £730 entering the higher ban The extra tax is £120 on property plus £30 on savings, or **£150 a year**. The calculation shows why the order of income sources matters even when each rate rises by the same two percentage points. +[Try the Budget dashboard's calculator](https://policyengine.org/uk/budgets/autumn-2026). Its salary input is for 2026–27 and is grown into the target year, while this table fixes salary at £45,000 in 2027–28. On its current earnings path, a £45,000 salary input becomes about £46,080, giving total tax of £9,014 before and £9,164 after. The additional tax remains £150. These values can be entered manually; the existing preset may use different incomes. + ## Preliminary national estimates -The dashboard's [provisional revenue output](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/budgetary_impact.csv), generated on 28 October at 14:34 UTC, estimates that the measure raises **£664 million in 2027–28**, increasing to **£793 million in 2031–32**. These are static annual government-balance effects: savings, rental income and other household circumstances are held fixed. The results are awaiting reconciliation with Treasury costings. +The dashboard's [revenue estimate](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/budgetary_impact.csv) estimates that the measure raises **£664 million in 2027–28**, increasing to **£793 million in 2031–32**. These are static annual government-balance effects: savings, rental income and other household circumstances are held fixed. The estimates remain preliminary while the Treasury comparison is reconciled. -The [average cash changes](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/winners_losers.csv) show an annual household income reduction of **£22.67 across all households** in 2027–28, including unaffected households. The largest average cash loss is in the highest income decile, at £107.13. Deciles are ranked by baseline equivalised household net income, which accounts for household size. +The [average cash changes](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/winners_losers.csv) show an annual household income reduction of **£23 across all households** in 2027–28, including unaffected households. Households in the top decile lose £107 on average. Each decile contains roughly equal numbers of people, ranked by household income adjusted for household size. The cash figures are household-weighted averages within those groups. | Income decile | Average annual household income change | | --- | ---: | -| 1 (lowest income) | −£12.90 | -| 2 | −£5.69 | -| 3 | −£6.66 | -| 4 | −£7.31 | -| 5 | −£6.00 | -| 6 | −£9.13 | -| 7 | −£10.94 | -| 8 | −£21.51 | -| 9 | −£37.04 | -| 10 (highest income) | −£107.13 | -| All households | −£22.67 | +| 1 (lowest income) | −£13 | +| 2 | −£6 | +| 3 | −£7 | +| 4 | −£7 | +| 5 | −£6 | +| 6 | −£9 | +| 7 | −£11 | +| 8 | −£22 | +| 9 | −£37 | +| 10 (highest income) | −£107 | +| All households | −£23 | -The dashboard's [affected-population metric](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/metrics.csv) is **10.67% of people living in households whose net income changes by more than 0.01%** in 2027–28. It is not a taxpayer count or a headcount. The current exports do not provide separate shares gaining and losing, so an average loss within a decile should not be read as a loss for every household in it. +The model's [population results](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/metrics.csv) indicate that **10.67% of people live in households whose net income changes by more than 0.01%** in 2027–28. An average loss within a decile does not mean every household in it loses. The lowest decile's £13 average loss also exceeds the £6 to £11 averages in deciles 2 to 7; an income-source breakdown is needed to establish what drives that pattern. -## The Treasury forecasts revenue of £1.13 billion in 2028–29 +The government estimates that **84% of income tax payers are unaffected** in 2027–28 and that around half the revenue comes from the top 10% of households. Budget footnote 74 bases these estimates on projected HMRC Survey of Personal Incomes data and Treasury household mapping. The model's affected-person share uses a different population and threshold from the taxpayer estimate, so the two reach figures are not directly comparable. The decile means also do not establish a share of government revenue: that comparison requires weighted tax totals by decile. -The Treasury costs the savings and property changes separately. Their sum reaches £1,130 million in 2028–29 and £1,045 million in 2031–32. +## The Treasury's costing: £160 million in 2027–28 + +The Treasury costs savings and property separately. Their combined forecast is £160 million in 2027–28 and £1,045 million in 2031–32. | Exchequer revenue, £ million | 2026–27 | 2027–28 | 2028–29 | 2029–30 | 2030–31 | 2031–32 | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | Property income rates | 0 | 35 | 575 | 435 | 445 | 455 | | Savings income rates | 15 | 125 | 555 | 520 | 555 | 590 | | Treasury combined | 15 | 160 | 1,130 | 955 | 1,000 | 1,045 | -| PolicyEngine, provisional static | 0 | 664 | 696 | 728 | 762 | 793 | +| PolicyEngine, preliminary static | 0 | 664 | 696 | 728 | 762 | 793 | -These government receipts forecasts differ from annual household liabilities. The [Treasury policy costings, #page 74-75](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74) allow for some landlords incorporating and savers moving funds into tax-advantaged products such as ISAs. The PolicyEngine run holds those choices fixed. Tax-year liabilities and fiscal-year receipts forecasts also differ in timing. Reconciliation has not yet established how much of the gap between these estimates comes from behaviour, collection timing or model coverage. +The Treasury costings allow for some landlords incorporating and savers moving funds into tax-advantaged products such as ISAs. The static model holds those choices fixed. The published costing notes do not explain the annual profile, including the £15 million savings figure in 2026–27 before the rates take effect. No particular collection-timing explanation is assumed here. A component comparison is needed to distinguish the property and savings contributions to the difference. ## Methodology The examples isolate the newly announced 2027–28 changes, including finance-cost relief, holding income and expenses constant. They include no pension contributions, Gift Aid, student loans or other reliefs. They show tax attributable to each income source, rather than household net income after benefits. -The examples use `policyengine.py` 6.11.1 with PolicyEngine UK 2.151.0 and core 3.33.3, matching the pre-Budget policy baseline and parameter changes in the dashboard's [`unearned_income_rates_up` measure](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/b50787aa75ef5aed36b822c973afa6b569464d55/src/uk_budget_data/reforms.py). The calculations check tax changes against independent arithmetic. - -The national figures reuse the dashboard's [recorded execution receipt](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/receipt.json), generated at source commit `0d9dccb2`. They use certified national dataset `microcosm-uk-2024-25-national-20261025T091414Z-a6299504` and the October 2026 OBR forecast overlay on both baseline and reform. Growth series not updated by the overlay retain the model's March forecast path; the dataset retains its pre-Budget calibration. Household examples use fixed nominal incomes. +The examples use `policyengine.py` 6.11.1 with PolicyEngine UK 2.151.0 and core 3.33.3. Income is fixed at the stated 2027–28 amounts, and tax changes are checked against independent arithmetic. -The receipt records a passed disclosure floor of at least three survey households per published cell; no thin decile cells are recorded. The affected-population calculation uses the absolute percentage income change, floors baseline household income at £1, and includes only households with a valid decile. Its percentage does not establish how many people gain or lose. +The national estimates use the certified Microcosm UK 2024–25 national data and the initial October 2026 OBR forecast overlay on both baseline and reform. Growth series not updated by that overlay retain the model's March forecast path; the dataset retains its pre-Budget calibration. The [analysis files](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460/files) record exact dataset identifiers, checksums, parameter changes and calculation records. -**Draft status:** the population results are provisional and marked `awaiting_source` for reconciliation in the preview manifest. Final reconciliation, absolute affected-person counts and separate winner/loser shares remain outstanding. +Published decile cells meet a disclosure floor of at least three survey households. The affected-person calculation uses the absolute percentage income change, floors baseline household income at £1 and includes households with a valid decile. It does not supply separate shares gaining and losing or absolute affected-person counts. The income-source explanation for the lowest-decile result and the component reconciliation remain outstanding. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md b/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md deleted file mode 100644 index d96ab10b1..000000000 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-trading-allowance.md +++ /dev/null @@ -1,175 +0,0 @@ -The [Autumn Budget 2026](https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html) announces an increase in the trading allowance from £1,000 to £3,000 from 6 April 2027. The allowance covers eligible trading and miscellaneous income. For an employee paying 20% income tax on their side income, the extra £2,000 deduction can reduce annual income tax by £400. The reduction depends on receipts, expenses and how much tax the individual would otherwise pay. - -This post examines that measure on its own. Our [Budget dashboard](https://policyengine.org/uk/budgets/autumn-2026) places it alongside the other announced tax and benefit changes. We cover the savings and property income tax increases in a [separate explainer](/uk/research/uk-autumn-budget-2026-savings-property-income-tax). - -## How the allowance works - -The allowance is an alternative to deducting actual business expenses. Gross receipts are the money received before expenses; profit is what remains after those expenses. A person with £4,000 of receipts and £500 of allowable expenses has £3,500 of profit before considering the allowance. - -Under [HMRC's trading allowance guidance](https://www.gov.uk/guidance/tax-free-allowances-on-property-and-trading-income), an eligible person can choose the allowance or actual expenses. They cannot deduct both against the same receipts. If receipts are within the allowance, full relief can make the taxable amount zero. The allowance cannot create a tax loss. - -There is one allowance per individual across their eligible trades and miscellaneous income, rather than a separate allowance for each activity. The allocation between sources follows [section 783AK of the Income Tax (Trading and Other Income) Act 2005](https://www.legislation.gov.uk/ukpga/2005/5/section/783AK). The separate property income allowance does not increase under this measure. - -## Three people with the same receipts - -Consider three hypothetical single adults in England in 2027–28. Each earns £30,000 from employment and receives £4,000 from a side business. They have no other income, dependants, student loan repayments or benefit entitlements. Their trading profits remain in the 20% income tax band. Their costs differ. - -The table isolates income tax on the side business, holding receipts and expenses fixed. - -| Annual side-business receipts | Actual expenses | Taxable amount under current rules | Taxable amount under new rules | Income tax before | Income tax after | Annual tax reduction | -| --- | --- | --- | --- | --- | --- | --- | -| £4,000 | £500 | £3,000 | £1,000 | £600 | £200 | £400 | -| £4,000 | £2,500 | £1,500 | £1,000 | £300 | £200 | £100 | -| £4,000 | £3,500 | £500 | £500 | £100 | £100 | £0 | - -In the first case, the allowance exceeds expenses under both rules. Taxable income falls from £4,000 − £1,000 = £3,000 to £4,000 − £3,000 = £1,000. The tax reduction is £2,000 × 20% = £400. - -In the second case, actual expenses provide the larger deduction under current law. The £3,000 allowance then exceeds those £2,500 expenses by £500, reducing tax by £500 × 20% = £100. - -In the third case, actual expenses exceed both allowances. The individual continues to deduct £3,500, so taxable income and tax do not change. - -At a 40% marginal rate, the same calculations give reductions of £800, £200 and £0, assuming no tax-band changes or other interactions. - -## From £500 to £5,000 of side income - -The chart varies gross receipts for the same £30,000 employee. One series assumes no business expenses; the other assumes expenses equal 75% of receipts. Each calculation chooses the larger deduction in each scenario. - -```chart -{ - "type": "bar", - "title": "Trading allowance: the income tax reduction depends on expenses", - "subtitle": "Annual income tax reduction; England, £30,000 salary, 2027–28", - "xKey": "receipts", - "yLabel": "Annual income tax reduction (£)", - "format": { - "prefix": "£", - "decimals": 0 - }, - "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", - "series": [ - { - "key": "noExpenses", - "name": "No business expenses", - "color": "primary" - }, - { - "key": "highExpenses", - "name": "Expenses equal 75% of receipts", - "color": "secondary" - } - ], - "data": [ - { - "receipts": "£500", - "noExpenses": 0.0, - "highExpenses": 0.0 - }, - { - "receipts": "£1,000", - "noExpenses": 0.0, - "highExpenses": 0.0 - }, - { - "receipts": "£1,500", - "noExpenses": 100.0, - "highExpenses": 75.0 - }, - { - "receipts": "£2,000", - "noExpenses": 200.0, - "highExpenses": 100.0 - }, - { - "receipts": "£2,500", - "noExpenses": 300.0, - "highExpenses": 125.0 - }, - { - "receipts": "£3,000", - "noExpenses": 400.0, - "highExpenses": 150.0 - }, - { - "receipts": "£3,500", - "noExpenses": 400.0, - "highExpenses": 75.0 - }, - { - "receipts": "£4,000", - "noExpenses": 400.0, - "highExpenses": 0.0 - }, - { - "receipts": "£4,500", - "noExpenses": 400.0, - "highExpenses": 0.0 - }, - { - "receipts": "£5,000", - "noExpenses": 400.0, - "highExpenses": 0.0 - } - ] -} -``` - -With no expenses, the tax reduction rises between £1,000 and £3,000 of receipts, then stays at £400. With expenses equal to 75% of receipts, the reduction reaches £150 at £3,000 of receipts and falls to zero at £4,000: actual expenses then equal the new £3,000 allowance. - -## National Insurance and benefit interactions - -[HMRC's National Insurance guidance](https://www.gov.uk/hmrc-internal-manuals/business-income-manual/bim86052) confirms that the trading allowance also reduces the profits used to calculate Class 4 contributions. However, all the side-business examples above remain below the [£12,570 Class 4 lower profits limit](https://www.gov.uk/government/publications/rates-and-allowances-national-insurance-contributions/rates-and-allowances-national-insurance-contributions). They have no Class 4 reduction; employment National Insurance is unchanged. - -Universal Credit uses separate self-employment income rules. The allowance itself does not reduce income for Universal Credit purposes, as HMRC's allowance guidance explains. A full household calculation must also account for any change in tax paid and the benefit rules that apply to that household. - -The allowance is unavailable for partnership income and certain connected-party receipts, including income from an individual's employer or a company they control. [HMRC's exclusions](https://www.gov.uk/hmrc-internal-manuals/business-income-manual/bim86030) describe those restrictions. - -## Preliminary national estimates - -The dashboard's [provisional cost output](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/budgetary_impact.csv), generated on 28 October at 14:34 UTC, estimates a **£112 million cost in 2027–28** and **£131 million in 2031–32**. These are static annual government-balance effects. The receipt warns that missing gross receipts in the population data can overstate the cost, and the results are awaiting reconciliation with Treasury costings. - -The [average cash changes](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/winners_losers.csv) show a **£3.83 annual household income gain across all households** in 2027–28, including unaffected households. The highest average gain is in decile 8, at £8.57. These population averages include people with no eligible trading income; the worked examples above describe particular eligible individuals. Deciles are ranked by baseline equivalised household net income, which accounts for household size. - -| Income decile | Average annual household income change | -| --- | ---: | -| 1 (lowest income) | +£0.83 | -| 2 | +£3.39 | -| 3 | +£1.04 | -| 4 | +£0.45 | -| 5 | +£2.11 | -| 6 | +£3.43 | -| 7 | +£5.73 | -| 8 | +£8.57 | -| 9 | +£6.18 | -| 10 (highest income) | +£7.03 | -| All households | +£3.83 | - -The dashboard's [affected-population metric](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/metrics.csv) is **0.93% of people living in households whose net income changes by more than 0.01%** in 2027–28. It is not a count of eligible traders. The current exports do not provide separate shares gaining and losing or an absolute affected-person count. - -## Treasury costing - -The Treasury column reproduces Table 6.1, row 15. The PolicyEngine column reports the provisional static estimates. Both columns express costs to the Exchequer as positive values. - -| Year | Treasury cost (£ million) | PolicyEngine provisional static cost (£ million) | -| --- | ---: | ---: | -| 2026–27 | 0 | 0 | -| 2027–28 | 0 | 112 | -| 2028–29 | 225 | 120 | -| 2029–30 | 165 | 113 | -| 2030–31 | 175 | 123 | -| 2031–32 | 180 | 131 | - -The effective date remains 6 April 2027 even though the Treasury records no receipts effect in 2027–28. Tax-year liabilities and the government's fiscal-year receipts forecasts are different quantities. The [Treasury policy costing](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=23) also allows for taxpayers switching from actual expenses to the larger allowance, a behavioural response. The static model holds circumstances fixed and also faces the gross-receipts coverage limit. Reconciliation has not yet attributed the gap between the estimates. - -## Methodology and coverage - -The worked examples isolate the allowance increase and use hypothetical households. They hold earnings, receipts and expenses fixed, assume the individual selects the larger deduction, and exclude losses, behavioural responses and other tax or benefit interactions. - -The household calculations use `policyengine.py` 6.11.1 with PolicyEngine UK 2.151.0 and core 3.33.3, matching the dashboard's `trading_allowance_raise` measure. They supply both gross receipts and profit so the model can represent actual expenses, and check the resulting tax changes against independent arithmetic. - -In the population data, gross receipts are unavailable. The pinned model's [deduction calculation](https://github.com/PolicyEngine/policyengine-uk/blob/2.151.0/policyengine_uk/variables/gov/hmrc/income_tax/allowances/trading_allowance_deduction.py) uses an approximation that can overstate or understate the reform's effect for individual records. It also does not apply this allowance to its separate miscellaneous-income input, although eligible miscellaneous income is within the announced policy. These coverage limits matter when interpreting national results. - -The national figures reuse the dashboard's [recorded execution receipt](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/receipt.json), generated at source commit `0d9dccb2`. They use certified national dataset `microcosm-uk-2024-25-national-20261025T091414Z-a6299504` and the October 2026 OBR forecast overlay on both baseline and reform. Growth series not updated by the overlay retain the model's March forecast path; the dataset retains its pre-Budget calibration. Household examples use fixed nominal incomes. - -The receipt records a passed disclosure floor of at least three survey households per published cell; no thin decile cells are recorded. The affected-population calculation uses the absolute percentage income change, floors baseline household income at £1, and includes only households with a valid decile. Its percentage does not establish how many people gain or lose. - -**Draft status:** the population results are provisional and marked `awaiting_source` for reconciliation in the preview manifest. Final reconciliation, absolute affected-person counts and separate winner/loser shares remain outstanding. diff --git a/app/src/data/posts/posts.json b/app/src/data/posts/posts.json index 50f3c400b..47200893e 100644 --- a/app/src/data/posts/posts.json +++ b/app/src/data/posts/posts.json @@ -8,15 +8,6 @@ "filename": "uk-autumn-budget-2026-savings-property-income-tax.md", "image": "uk-autumn-budget-2026-savings-property-income-tax.svg" }, - { - "title": "Autumn Budget 2026: raising the trading allowance", - "description": "The trading allowance rises from £1,000 to £3,000. We show how receipts and actual expenses determine the income tax reduction.", - "date": "2026-10-28 14:00:00", - "tags": ["uk", "policy", "tax", "autumn-budget"], - "authors": ["ziming-hua"], - "filename": "uk-autumn-budget-2026-trading-allowance.md", - "image": "uk-autumn-budget-2026-trading-allowance.svg" - }, { "title": "High value council tax surcharge: revenue by constituency", "description": "We estimate the surcharge raises \u00a3410 million in 2028-29 from owner-occupied main residences in England before behavioural responses, 39% of it from 10 constituencies.", From 932ae46f726eb840f3e559b525e33ca5492c19eb Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Wed, 28 Oct 2026 11:43:31 -0400 Subject: [PATCH 06/24] Keep line chart axis labels, axis title and legend apart The first x tick label no longer touches the lowest y tick label at the plot's corner, and the legend sits clear of the x axis title. Checked on every chart in the PTA post at 1280 and 375 pixels wide. Co-Authored-By: Claude Opus 5.5 --- website/src/components/blog/BlogLineChart.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/website/src/components/blog/BlogLineChart.tsx b/website/src/components/blog/BlogLineChart.tsx index 94e6ed510..181038184 100644 --- a/website/src/components/blog/BlogLineChart.tsx +++ b/website/src/components/blog/BlogLineChart.tsx @@ -214,13 +214,16 @@ export function LineBody({ spec }: { spec: BlogLineSpec }) { tick={AXIS_STYLE} axisLine={false} tickLine={false} + // Drop the x tick labels below the lowest y tick label, which + // sits on the axis line at the plot's corner. + tickMargin={10} tickFormatter={xTick} label={ spec.xLabel ? { value: spec.xLabel, position: "insideBottom", - offset: -4, + offset: -14, style: AXIS_STYLE, } : undefined @@ -270,7 +273,15 @@ export function LineBody({ spec }: { spec: BlogLineSpec }) { String(name), ]} /> - + {spec.series.map((s, i) => ( Date: Wed, 28 Oct 2026 11:47:38 -0400 Subject: [PATCH 07/24] Pin Budget paragraph citations and record latest review decisions --- analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md | 11 +++++++++++ ...-autumn-budget-2026-savings-property-income-tax.md | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md index 458323ea2..86a2eba41 100644 --- a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md +++ b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md @@ -58,3 +58,14 @@ Still needed before publication: - Replace preview artifact links when verified public artifacts exist; complete visual preview and editorial review. The articles remain drafts. Publication approval is separate from readiness for agent review. The trading article will have its own stacked PR, reusing this shared analysis foundation. + + +## Latest review follow-ups and PR split + +- Savings/property remains draft PR1460. Trading is separate draft PR1463, stacked on1460 for shared analysis. Both link to dashboard292, and the dashboard cross-reference links both articles. +- Max confirmed the savings/property revision at5a70185a in comment6473557134 and withdrew the48% inference. The two remaining requests were precise paragraph citations and final component exports. +- Official Budget PDF physical page142 was checked for paragraphs6.246/6.247 and6.254; physical45 contains paragraph2.50. These are now the rule citations. +- Max's newer trading comment on1463,6473574155, agrees to omit the unsupported260,000 count and£71m sensitivity; the latter ignores the shared allowance. Those figures remain excluded. +- Per that follow-up, only the mutually reproduced£180 UC example is retained in the article. The£1,500 diagnostic pair remains in the raw analysis record, with both input sets distinguished, rather than presented as an explained cross-run comparison. +- The trading lead example is named Alex and remains first: age35, salary30k, receipts4k, costs500, tax reduction400. UC and full-time self-employment are additional examples. +- A fresh complete pass covered all five Max conversation comments on1460 and the follow-up on1463, including edits through15:45:19UTC. Both PRs had no inline review threads or submitted reviews in that pass. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md index 18f1e9fe0..3a1fe68b0 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md @@ -1,4 +1,4 @@ -The Autumn Budget 2026 increases the basic, higher and additional income tax rates on savings and property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%**. Savings rates apply across the UK. The property rates apply in England, Wales and Northern Ireland. Dividend rates remain unchanged. These are the changes announced in the [Budget 2026 document](https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html). +The Autumn Budget 2026 increases the basic, higher and additional income tax rates on savings and property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%**. Savings rates apply across the UK. The property rates apply in England, Wales and Northern Ireland. Dividend rates remain unchanged. These are the changes announced in the [Budget 2026, paragraphs 6.246 and 6.247](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142 "Budget 2026 #page 142,45"). PolicyEngine estimates that the measure raises **£664 million in 2027–28**, compared with the Treasury's **£160 million** for that year. These are preliminary static estimates; the Treasury costing includes behavioural responses. @@ -175,7 +175,7 @@ The [average cash changes](https://ab2026-local-preview.vercel.app/uk/autumn-bud The model's [population results](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/metrics.csv) indicate that **10.67% of people live in households whose net income changes by more than 0.01%** in 2027–28. An average loss within a decile does not mean every household in it loses. The lowest decile's £13 average loss also exceeds the £6 to £11 averages in deciles 2 to 7; an income-source breakdown is needed to establish what drives that pattern. -The government estimates that **84% of income tax payers are unaffected** in 2027–28 and that around half the revenue comes from the top 10% of households. Budget footnote 74 bases these estimates on projected HMRC Survey of Personal Incomes data and Treasury household mapping. The model's affected-person share uses a different population and threshold from the taxpayer estimate, so the two reach figures are not directly comparable. The decile means also do not establish a share of government revenue: that comparison requires weighted tax totals by decile. +The government estimates that **84% of income tax payers are unaffected** in 2027–28 and that around half the revenue comes from the top 10% of households. Budget paragraph 2.50 and footnote 74 base these estimates on projected HMRC Survey of Personal Incomes data and Treasury household mapping. The model's affected-person share uses a different population and threshold from the taxpayer estimate, so the two reach figures are not directly comparable. The decile means also do not establish a share of government revenue: that comparison requires weighted tax totals by decile. ## The Treasury's costing: £160 million in 2027–28 From 6d3b480aac7f9f8a448b7add2ed078c82436d91c Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 12:04:11 -0400 Subject: [PATCH 08/24] Round savings/property worked table to whole pounds --- analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md | 7 +++++++ ...k-autumn-budget-2026-savings-property-income-tax.md | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md index 86a2eba41..ddde6df8a 100644 --- a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md +++ b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md @@ -69,3 +69,10 @@ The articles remain drafts. Publication approval is separate from readiness for - Per that follow-up, only the mutually reproduced£180 UC example is retained in the article. The£1,500 diagnostic pair remains in the raw analysis record, with both input sets distinguished, rather than presented as an explained cross-run comparison. - The trading lead example is named Alex and remains first: age35, salary30k, receipts4k, costs500, tax reduction400. UC and full-time self-employment are additional examples. - A fresh complete pass covered all five Max conversation comments on1460 and the follow-up on1463, including edits through15:45:19UTC. Both PRs had no inline review threads or submitted reviews in that pass. + + +## Rounding correction at 16:01 UTC + +Max's latest comments on PR1460 (6473972686) and PR1463 (6473966614) supersede the earlier permission to retain pence in worked tables. Reader-facing tables now use whole pounds throughout; pence are permitted only in prose spelling out a formula. Exact model outputs and hashed source files retain their original precision. The rounded band-crossing components still sum to£8,582/£8,732, and the rounded sole-trader totals remain£1,672/£1,152, a£520 change. + +The dashboard now defines property and savings as separate measures. The article can continue to analyse them together, but a new measure definition is not a substitute for published execution-bound component outputs. The old first-estimate snapshot remains identified by its original measure IDs until replacement data are verified. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md index 3a1fe68b0..0f24502f1 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md @@ -143,11 +143,11 @@ Property income fills that remaining £5,270, with £730 entering the higher ban | Income tax component, 2027–28 | Before | After | | --- | ---: | ---: | -| Salary: £32,430 at 20% | £6,486.00 | £6,486.00 | -| Property: £5,270 at 22% / 24% | £1,159.40 | £1,264.80 | -| Property: £730 at 42% / 44% | £306.60 | £321.20 | -| Savings: £1,500 at 42% / 44% | £630.00 | £660.00 | -| Total income tax | £8,582.00 | £8,732.00 | +| Salary: £32,430 at 20% | £6,486 | £6,486 | +| Property: £5,270 at 22% / 24% | £1,159 | £1,265 | +| Property: £730 at 42% / 44% | £307 | £321 | +| Savings: £1,500 at 42% / 44% | £630 | £660 | +| Total income tax | £8,582 | £8,732 | The extra tax is £120 on property plus £30 on savings, or **£150 a year**. The calculation shows why the order of income sources matters even when each rate rises by the same two percentage points. From 9d88f9490aeb21ea84293d403eca38c6ec8a47ec Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 12:05:59 -0400 Subject: [PATCH 09/24] Flag pending replacement of regenerated national results --- analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md | 7 +++++++ analysis/uk-budget-2026-income-tax/provenance.json | 13 +++++++++++++ ...utumn-budget-2026-savings-property-income-tax.md | 2 ++ 3 files changed, 22 insertions(+) diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md index ddde6df8a..9e576c402 100644 --- a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md +++ b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md @@ -76,3 +76,10 @@ The articles remain drafts. Publication approval is separate from readiness for Max's latest comments on PR1460 (6473972686) and PR1463 (6473966614) supersede the earlier permission to retain pence in worked tables. Reader-facing tables now use whole pounds throughout; pence are permitted only in prose spelling out a formula. Exact model outputs and hashed source files retain their original precision. The rounded band-crossing components still sum to£8,582/£8,732, and the rounded sole-trader totals remain£1,672/£1,152, a£520 change. The dashboard now defines property and savings as separate measures. The article can continue to analyse them together, but a new measure definition is not a substitute for published execution-bound component outputs. The old first-estimate snapshot remains identified by its original measure IDs until replacement data are verified. + + +## Live-source check at16:04UTC + +Preview manifest revision15 (updated16:01:00Z) has no property_income_rates_up or savings_income_rates_up artifacts yet. The old combined result is withdrawn because the measure was split; its archived snapshot remains in the analysis records. A newer trading artifact71f8a26e4f547021 is provisional and failed reconciliation. It uses the same certifieda6299504 dataset and detailed October forecasts, but its source still excludes the council-tax update. Neither it nor Max's rounded internal component figures has replaced the saved first-estimate data. + +The drafts now explicitly flag the older national snapshot as awaiting replacement. These national sections must not be treated as current approved dashboard outputs or published until replacement execution-bound results are reconciled. Household calculations and their input/output records are unchanged. diff --git a/analysis/uk-budget-2026-income-tax/provenance.json b/analysis/uk-budget-2026-income-tax/provenance.json index 07f8bdc76..a447c6a34 100644 --- a/analysis/uk-budget-2026-income-tax/provenance.json +++ b/analysis/uk-budget-2026-income-tax/provenance.json @@ -54,6 +54,19 @@ "people_affected is a percentage of people in households whose absolute net-income percentage change exceeds 0.01%; it is not a headcount.", "Trading gross receipts are missing; the receipt warns this may overstate cost." ] + }, + "live_source_check": { + "checked_at_utc": "2026-10-28T16:04:05Z", + "manifest_revision": 15, + "manifest_updated_at": "2026-10-28T16:01:00.454209Z", + "property_income_rates_up": "not_yet_published", + "savings_income_rates_up": "not_yet_published", + "unearned_income_rates_up": "withdrawn_due_to_measure_split", + "new_trading_artifact": "71f8a26e4f547021", + "new_trading_status": "provisional_reconciliation_failed", + "new_trading_dataset_matches_pin": true, + "replacement_adopted": false, + "forecast_note": "New trading batch has October detailed forecasts but still March council tax; it is not the final forecast batch." } }, "treasury_costings": { diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md index 0f24502f1..b13af94b7 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md @@ -1,3 +1,5 @@ +> Draft review note: the national figures below use the earlier recorded forecast snapshot and await replacement by the regenerated savings and property results. The household calculations remain as stated. + The Autumn Budget 2026 increases the basic, higher and additional income tax rates on savings and property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%**. Savings rates apply across the UK. The property rates apply in England, Wales and Northern Ireland. Dividend rates remain unchanged. These are the changes announced in the [Budget 2026, paragraphs 6.246 and 6.247](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142 "Budget 2026 #page 142,45"). PolicyEngine estimates that the measure raises **£664 million in 2027–28**, compared with the Treasury's **£160 million** for that year. These are preliminary static estimates; the Treasury costing includes behavioural responses. From 4e6f0b10a4f8e54d51c6747ae98149a710d6b33d Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 12:20:16 -0400 Subject: [PATCH 10/24] Align budget explainers with PTA forecast and chart methodology --- analysis/uk-budget-2026-income-tax/README.md | 20 +- .../uk-budget-2026-income-tax/REVIEW_NOTES.md | 23 +- .../curve-validation.json | 30 + .../uk-budget-2026-income-tax/forecast.py | 58 ++ .../generate_households.py | 104 ++- .../generate_trading_extensions.py | 5 +- .../uk-budget-2026-income-tax/households.csv | 6 +- .../uk-budget-2026-income-tax/households.json | 791 +++++++++++++++++- .../obr_october_2026.json | 89 ++ .../uk-budget-2026-income-tax/provenance.json | 66 +- .../savings-interest-chart.json | 223 ++++- .../savings-interest-curve.csv | 36 + .../trading-allowance-chart.json | 232 ++++- .../trading-receipts-curve.csv | 37 + .../trading_extensions.json | 48 +- ...budget-2026-savings-property-income-tax.md | 272 +++++- 16 files changed, 1920 insertions(+), 120 deletions(-) create mode 100644 analysis/uk-budget-2026-income-tax/curve-validation.json create mode 100644 analysis/uk-budget-2026-income-tax/forecast.py create mode 100644 analysis/uk-budget-2026-income-tax/obr_october_2026.json diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index e5a2edd2b..6c9177d64 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -12,9 +12,9 @@ uv pip install --python analysis/uk-budget-2026-income-tax/.venv/bin/python -r a analysis/uk-budget-2026-income-tax/.venv/bin/python analysis/uk-budget-2026-income-tax/generate_households.py ``` -The generator uses hypothetical adults, without population microdata. It records inputs and outputs and checks the results against independent arithmetic. The reform parameters match dashboard PR290 at the immutable commit recorded in `provenance.json`. Fixed nominal household incomes do not require population forecast uprating. +The generator uses hypothetical adults, without population microdata. It records inputs and outputs and checks the results against independent arithmetic. The reform parameters match dashboard PR290 at the immutable commit recorded in `provenance.json`. Both the baseline and reform now also use the same October 2026 forecast as Pavel’s PTA post (dashboard commit `640426575270224db9b04d6c94d30e264a347be2`). Supplied income amounts remain fixed in 2027–28; the forecast updates statutory and other model parameters. Fixed nominal incomes do not remove the need to use the agreed forecast. -The checked outputs include 23 household comparisons and 20 points across the two income curves. To also verify the original dashboard parameter builder, pass `--dashboard-checkout /path/to/checkout` with that checkout at the recorded commit. This check is optional and performs no download. +The checked outputs include 23 household comparisons and 93 displayed points across the two income curves. The displayed lines use £100 intervals and the exact policy breakpoints. All four series are independently checked against the model at every £2 from £500 to £5,000, including a comparison of the plotted interpolation with the engine results; `curve-validation.json` records counts and maximum errors. The non-integer £1,333⅓ expense-choice breakpoint is also calculated with the model. To also verify the original dashboard parameter builder, pass `--dashboard-checkout /path/to/checkout` with that checkout at the recorded commit. This check is optional and performs no download. The article chart blocks reproduce `savings-interest-chart.json` and `trading-allowance-chart.json`. Reinsert their contents when regenerating them. @@ -22,7 +22,7 @@ The article chart blocks reproduce `savings-interest-chart.json` and `trading-al Retain the dashboard's adopted `policyengine` 6.11.1 bundle, with UK 2.151.0, core 3.33.3 and national data cut `a6299504`. The certificate, full dataset ID and checksum are recorded in `provenance.json`. The newer candidate in policyengine.py PR725 is awaiting certification/adoption. A future update must change the package and dataset provenance together and regenerate the analysis. -No population microdata were downloaded locally. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. Vahid subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The drafts now reuse its digest-addressed public aggregate outputs, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. +No population microdata were downloaded locally. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. Vahid subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The drafts retain its digest-addressed public aggregate outputs as an earlier review snapshot, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. The provisional national outputs use the exact dataset above with the dashboard's October 2026 OBR forecast wrapper on both baseline and reform. Each provision is scored separately. The source commit is `0d9dccb2`; its reform definitions and October forecast input file match household reference commit `b50787aa` byte for byte. Series not updated by the overlay retain the model's March forecast path; the underlying calibration remains pre-Budget. @@ -44,7 +44,7 @@ Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipt - Verify the final public dashboard link and add links to these explainers within the dashboard. The source checkout's README supplies the current Vercel dashboard URL. - Have the policy interpretation and calculations reviewed before merging. This branch is a draft and is not publication approval. -The two articles use the site's native chart blocks and cover assets. No runtime application or country-model code is changed. +The two articles use the site's native chart blocks and cover assets. Household curves use Pavel's shared numeric line renderer from PR1462; no duplicate chart implementation or country-model code is added. See `REVIEW_NOTES.md` for the independent draft-readiness check, the comparison with Pavel's posts and the remaining publication work. @@ -61,4 +61,14 @@ After adding the provisional national sections, snapshot verification and the ar analysis/uk-budget-2026-income-tax/.venv/bin/python analysis/uk-budget-2026-income-tax/generate_trading_extensions.py ``` -This checks five additional synthetic pairs requested in Max's review, including UC, Class4 and missing-receipts fallbacks. `trading_extensions.json` records complete inputs, raw outputs and arithmetic checks. `dashboard_salary_comparison.json` records the calculator's March-index salary comparison. Household examples use no population data. Shared analysis is kept in the savings/property base PR so the trading article can be reviewed in a separate stacked PR. +This checks five additional synthetic pairs requested in Max's review, including UC, Class4 and missing-receipts fallbacks, on the same pinned October forecast as the main generator. `trading_extensions.json` records complete inputs, raw outputs and arithmetic checks. `dashboard_salary_comparison.json` records the calculator's March-index salary comparison. Household examples use no population data. Shared analysis is kept in the savings/property base PR so the trading article can be reviewed in a separate stacked PR. + +## Alignment with Pavel’s PTA post + +The exact forecast input is retained as `obr_october_2026.json`; `forecast.py` verifies its Git blob before use and reconstructs the source’s rounded fuel-duty path. Its complete eight-path parameter mapping was checked for exact equality with the immutable dashboard source’s `with_forecast(None).parameter_changes`. `pe.uk.calculate_household` accepts parameter mappings, so both synthetic generators pass that mapping together with only the measure being analysed. There is no population data load to precede, and no other Budget measure is activated. + +Pavel’s comparison uses £100 chart sampling plus the true breakpoints and verifies the results on a denser model grid. These drafts now follow that method: numeric income axes, explicit £ formats, named threshold markers and independent validation at every £2. Reader-facing tables continue to use whole pounds per Max’s latest correction; raw analysis retains precision. + +The household forecast pin and the archived national forecast are recorded separately. Applying the new household overlay does not regenerate or validate the historical national snapshot. That snapshot still awaits reconciled replacement outputs with execution-bound component results. + +The October-forecast rerun passed all23 household comparisons and all5 trading extension pairs. All policy deltas remain unchanged. Some absolute levels change: the three Scottish cases’ income-tax levels fall by £2.93 on both sides, and the parent’s total benefits/net income rise by about £20.10 on both sides. These do not change the article’s reported tax or household gains. The new93 displayed chart points passed18,008 model-liability comparisons and9,004 interpolation comparisons over2,251 income points per series. The largest interpolation difference is£0.0033, below the£0.01 tolerance. diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md index 9e576c402..0e6dde8a3 100644 --- a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md +++ b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md @@ -31,7 +31,7 @@ The source preview remains revision 5, with both entries `provisional` and recon ## Related team work -Pavel's [Pension Tax Allowance draft, #1457](https://github.com/PolicyEngine/policyengine-app-v2/pull/1457), and [fuel-duty draft, #1459](https://github.com/PolicyEngine/policyengine-app-v2/pull/1459), informed the calculation-first presentation, explicit assumptions and separation of Treasury costings from model results. They were read as comparative examples, not formally approved by this review. Their shared line-chart work is not required by these posts' existing native bar charts. +Pavel's [Pension Tax Allowance draft, #1457](https://github.com/PolicyEngine/policyengine-app-v2/pull/1457), and [fuel-duty draft, #1459](https://github.com/PolicyEngine/policyengine-app-v2/pull/1459), informed the calculation-first presentation, explicit assumptions and separation of Treasury costings from model results. They were read as comparative examples, not formally approved by this review. The earlier drafts used native bar charts. The current alignment reuses their shared numeric line renderer from PR1462 for the household curves. ## Follow-up to Max's reviews @@ -83,3 +83,24 @@ The dashboard now defines property and savings as separate measures. The article Preview manifest revision15 (updated16:01:00Z) has no property_income_rates_up or savings_income_rates_up artifacts yet. The old combined result is withdrawn because the measure was split; its archived snapshot remains in the analysis records. A newer trading artifact71f8a26e4f547021 is provisional and failed reconciliation. It uses the same certifieda6299504 dataset and detailed October forecasts, but its source still excludes the council-tax update. Neither it nor Max's rounded internal component figures has replaced the saved first-estimate data. The drafts now explicitly flag the older national snapshot as awaiting replacement. These national sections must not be treated as current approved dashboard outputs or published until replacement execution-bound results are reconciled. Household calculations and their input/output records are unchanged. + +## Alignment with Pavel’s current PTA draft + +The user requested the same methodology and styling as Pavel’s PTA PR1457. The reference was read at head `d282ef870176c81feb87175d02584121bdc50197`, whose chart dependency is PR1462. The main article structure follows rules, household examples and curves, population impacts, assumptions and limitations, then methodology. The shared numeric line renderer is reused rather than copied. + +Both synthetic generators now apply the exact October forecast used by that PTA revision (dashboard commit `640426575270224db9b04d6c94d30e264a347be2`) to the baseline and the isolated reform. Previously the synthetic examples held incomes fixed but retained the model’s March parameter forecast. These are distinct choices: the inputs still stay fixed, while projected model parameters now use the common October overlay. The forecast’s original JSON is saved and hash-checked, and the complete eight-path parameter mapping was compared with the original source’s `with_forecast(None)` for exact equality. The archived national results are not regenerated or relabelled by this household change. + +Charts now show numeric axes, £ formatting and named allowance thresholds using Pavel’s PR1462 renderer. Display points include every £100 plus exact breakpoints, including the 75%-expense choice at £1,333⅓ of trading receipts. Both tax scenarios are independently checked against arithmetic at every £2, and linear interpolation of the displayed data is compared with the model changes to a one-penny tolerance. Counts and measured maximum errors are saved in `curve-validation.json`. Max’s latest instruction to use whole pounds in all reader-facing tables remains in force. + +Manifest revision17, updated16:09:01.451619UTC, publishes separate property (`3537bd303ac226cf`) and savings (`af6aaaee33f616ee`) artifacts, but both are provisional and fail reconciliation, as does the newer trading artifact. No replacement is adopted. Max’s16:10 webinar guidance is to use available dashboard figures and say other figures are “still being checked”; the saved older estimates are not cleared for spoken or published headline results by that message. + +The rerun completed at16:18:33UTC with all23 main household comparisons and all5 trading extension pairs passing. Every policy delta is unchanged. The Scottish income-tax levels change by−£2.93 in baseline and reform, while the UC parent’s total benefits and net income change by about+£20.10 in both; these level changes are retained in raw outputs. UC levels and the£180 and£520 article examples are unchanged. The generated curves contain46 savings points and47 trading points. At2,251 income points per series,18,008 liability comparisons and9,004 chart-interpolation comparisons pass; the maximum interpolation error is£0.0033, below the one-penny tolerance. Both generated line specs are ready to insert into the separate articles. Python compilation and diff-whitespace checks also passed. No population outputs or source artifacts were changed. + + +### PTA presentation alignment validation + +Both posts now use the shared line-chart renderer from app-v2 PR1462, the same dependency as Pavel's PTA PR1457. The savings/property PR is stacked on `pavel/blog-line-chart`; the trading PR remains stacked on the savings/property branch. The posts share rules, household impacts, population impacts, assumptions and limitations, and methodology sections. All reader tables use whole pounds. + +The line renderer, bar renderer, article-chart parser and post metadata checks passed (51 tests); website ESLint and TypeScript checks passed. No CI monitoring was performed. The 23 household cases, five extension pairs and dense curve checks passed on the pinned October forecast. Browser approval declined the public dashboard preview origin, so its rendered policy tab and the final visual layout were not verified in this pass. No alternative access to that blocked origin was attempted. + +Max's 16:18:54 UTC webinar update asks authors to introduce each measure for 30–60 seconds: say what it does and who it reaches, leaving costings to the dashboard. Q&A should use displayed dashboard figures and describe missing figures as still being checked. The archived national figures in these draft articles are not webinar-approved estimates. diff --git a/analysis/uk-budget-2026-income-tax/curve-validation.json b/analysis/uk-budget-2026-income-tax/curve-validation.json new file mode 100644 index 000000000..76f6785dc --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/curve-validation.json @@ -0,0 +1,30 @@ +{ + "range_gbp": [ + 500, + 5000 + ], + "validation_interval_gbp": 2, + "points_per_series": 2251, + "series": 4, + "liability_checks": 18008, + "interpolation_checks": 9004, + "chart_interval_gbp": 100, + "savings_breakpoints_gbp": [ + 500, + 1000 + ], + "trading_breakpoints_gbp": [ + 1000, + 1333.3333333333333, + 3000, + 4000 + ], + "chart_rows": { + "savings": 46, + "trading": 47 + }, + "maximum_model_error_gbp": 2.2737367544323206e-13, + "maximum_chart_interpolation_error_gbp": 0.0033000000000242835, + "tolerance_gbp": 0.01, + "method": "All four series checked against pe.uk at every £2; both scenarios compared with independent tax arithmetic; plotted linear interpolation compared with the engine tax changes. The non-integer expense-choice breakpoint is additionally calculated with pe.uk." +} diff --git a/analysis/uk-budget-2026-income-tax/forecast.py b/analysis/uk-budget-2026-income-tax/forecast.py new file mode 100644 index 000000000..80be8c660 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/forecast.py @@ -0,0 +1,58 @@ +"""The exact October forecast used by Pavel's PTA comparison. + +The stored JSON is unchanged from dashboard commit 640426575270224db9b04d6c94d30e264a347be2. +The fuel-duty path follows that commit's forecast_parameter_changes, including +its ROUND_HALF_UP rule. Synthetic households load no population data, so passing +these changes to pe.uk before calculation is equivalent to with_forecast. +""" + +from decimal import ROUND_HALF_UP, Decimal +from functools import lru_cache +import hashlib +import json +from pathlib import Path + + +COMMIT = "640426575270224db9b04d6c94d30e264a347be2" +FORECAST_PATH = Path(__file__).with_name("obr_october_2026.json") +EXPECTED_BLOB = "b504a48fffb93714ff358d869cad712b6daea20e" + + +@lru_cache(maxsize=None) +def parameter_changes() -> dict: + raw = FORECAST_PATH.read_bytes() + blob = hashlib.sha1(b"blob " + str(len(raw)).encode() + b"\0" + raw).hexdigest() + assert blob == EXPECTED_BLOB, (blob, EXPECTED_BLOB) + record = json.loads(raw) + changes = { + path: dict(entry["values"]) + for path, entry in record["parameter_changes"].items() + } + rate = Decimal("0.6059") + steps = [("2027-04-01", float(rate))] + for year in range(2028, 2033): + growth = Decimal(str(changes["gov.economic_assumptions.yoy_growth.obr.rpi"][f"{year - 1}-01-01.{year - 1}-12-31"])) + rate = (rate * (1 + growth)).quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP) + steps.append((f"{year}-04-01", float(rate))) + changes["gov.hmrc.fuel_duty.petrol_and_diesel"] = { + f"{day}.{int(day[:4]) + 1}-03-31": rate for day, rate in steps + } + return changes + + +def with_forecast(reform: dict) -> dict: + """Apply the common forecast, with the isolated measure taking precedence.""" + return {**parameter_changes(), **reform} + + +def provenance() -> dict: + return { + "dashboard_commit": COMMIT, + "source": f"https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/{COMMIT}/src/uk_budget_data/forecast/obr_october_2026.json", + "forecast_file_git_blob": EXPECTED_BLOB, + "forecast_module_git_blob": "b2ca186b6fd514f334ced11934d38b256e6d2127", + "forecast_file_sha256": hashlib.sha256(FORECAST_PATH.read_bytes()).hexdigest(), + "baseline_and_reform": True, + "nominal_household_inputs": "Held fixed in 2027; the forecast updates model parameters, not the supplied income amounts.", + "remaining_series": "March paths remain for cpih, non-labour income, private rent, mortgage interest, per-capita series, council tax and fuel volumes/prices, as recorded by this forecast vintage.", + } diff --git a/analysis/uk-budget-2026-income-tax/generate_households.py b/analysis/uk-budget-2026-income-tax/generate_households.py index e3b752fcc..e66fa1605 100644 --- a/analysis/uk-budget-2026-income-tax/generate_households.py +++ b/analysis/uk-budget-2026-income-tax/generate_households.py @@ -19,6 +19,9 @@ import warnings import policyengine as pe +import numpy as np + +from forecast import provenance as forecast_provenance, with_forecast YEAR = 2027 @@ -65,7 +68,7 @@ def calculate(person: dict, region: str, reform: dict, axes=None) -> dict: people=[{"age": 35, **person}], household={"region": region}, year=YEAR, - reform=reform, + reform=with_forecast(reform), axes=axes, extra_variables=PERSON_OUTPUTS, ) @@ -242,34 +245,48 @@ def generate_cases() -> list[dict]: return output -def generate_curves() -> tuple[list[dict], list[dict]]: - interest_rows = [{"interest": value} for value in range(500, 5_001, 500)] +def generate_curves() -> tuple[list[dict], list[dict], dict]: + # Model checks use every £2. Displayed curves include all £100 points and + # the exact deduction-choice breakpoints, matching the PTA chart method. + grid = list(range(500, 5_001, 2)) + interest_rows = [{"interest": value} for value in range(500, 5_001, 100)] + model_errors = [] + interpolation_errors = [] for label, salary, allowance, old_rate in ( ("basic", 30_000, 1_000, 0.22), ("higher", 60_000, 500, 0.42), ): - axes = [[{"name": "savings_interest_income", "min": 500, "max": 5_000, "count": 10}]] + axes = [[{"name": "savings_interest_income", "min": 500, "max": 5_000, "count": len(grid)}]] baseline = calculate({"employment_income": salary}, "LONDON", {}, axes) reformed = calculate({"employment_income": salary}, "LONDON", SAVINGS_PROPERTY, axes) - for index, row in enumerate(interest_rows): - taxable = max(0, row["interest"] - allowance) + changes = [] + for index, interest in enumerate(grid): + taxable = max(0, interest - allowance) before, after = baseline["savings_income_tax"][index], reformed["savings_income_tax"][index] close(before, taxable * old_rate, f"{label} savings curve baseline") close(after, taxable * (old_rate + 0.02), f"{label} savings curve reform") + model_errors.extend((abs(before - taxable * old_rate), abs(after - taxable * (old_rate + 0.02)))) + changes.append(round(after - before, 2)) + for row in interest_rows: + index = grid.index(row["interest"]) + before, after = baseline["savings_income_tax"][index], reformed["savings_income_tax"][index] row[f"{label}_baseline_tax"] = before row[f"{label}_reform_tax"] = after row[f"{label}_tax_increase"] = round(after - before, 2) + interpolated = np.interp(grid, [row["interest"] for row in interest_rows], [row[f"{label}_tax_increase"] for row in interest_rows]) + interpolation_errors.extend(abs(float(plotted) - actual) for plotted, actual in zip(interpolated, changes)) - trading_rows = [{"receipts": value} for value in range(500, 5_001, 500)] + trading_breakpoints = (1_000, 4_000 / 3, 3_000, 4_000) + trading_rows = [{"receipts": value} for value in sorted(set(range(500, 5_001, 100)) | set(trading_breakpoints))] for label, expense_share in (("no_expenses", 0), ("expenses_75_percent", 0.75)): profit_share = 1 - expense_share axes = [[ - {"name": "self_employment_gross_receipts", "min": 500, "max": 5_000, "count": 10}, - {"name": "self_employment_income", "min": 500 * profit_share, "max": 5_000 * profit_share, "count": 10}, + {"name": "self_employment_gross_receipts", "min": 500, "max": 5_000, "count": len(grid)}, + {"name": "self_employment_income", "min": 500 * profit_share, "max": 5_000 * profit_share, "count": len(grid)}, ]] baseline = calculate({"employment_income": 30_000}, "LONDON", {}, axes) reformed = calculate({"employment_income": 30_000}, "LONDON", TRADING, axes) - for index, row in enumerate(trading_rows): - receipts = row["receipts"] + changes = [] + for index, receipts in enumerate(grid): expenses = receipts * expense_share old_taxable = max(0, receipts - max(expenses, 1_000)) new_taxable = max(0, receipts - max(expenses, 3_000)) @@ -279,37 +296,77 @@ def generate_curves() -> tuple[list[dict], list[dict]]: close(reduction, (old_taxable - new_taxable) * 0.2, f"{label} trading tax reduction") close(baseline["ni_class_4"][index], 0, f"{label} baseline Class 4") close(reformed["ni_class_4"][index], 0, f"{label} reform Class 4") + model_errors.extend((abs(baseline["income_tax"][index] - (3_486 + old_taxable * 0.2)), abs(reformed["income_tax"][index] - (3_486 + new_taxable * 0.2)))) + changes.append(reduction) + # This non-integer breakpoint cannot be represented by a regular axis. + special_inputs = {"employment_income": 30_000, "self_employment_gross_receipts": 4_000 / 3, "self_employment_income": (4_000 / 3) * profit_share} + special_before = calculate(special_inputs, "LONDON", {}) + special_after = calculate(special_inputs, "LONDON", TRADING) + for row in trading_rows: + receipts = row["receipts"] + expenses = receipts * expense_share + old_taxable = max(0, receipts - max(expenses, 1_000)) + new_taxable = max(0, receipts - max(expenses, 3_000)) + if receipts in grid: + index = grid.index(receipts) + reduction = changes[index] + else: + reduction = round(special_before["income_tax"] - special_after["income_tax"], 2) + close(reduction, (old_taxable - new_taxable) * 0.2, f"{label} plotted trading reduction") row[f"{label}_actual_expenses"] = expenses row[f"{label}_baseline_taxable_profit"] = old_taxable row[f"{label}_reform_taxable_profit"] = new_taxable row[f"{label}_tax_reduction"] = reduction - return interest_rows, trading_rows + interpolated = np.interp(grid, [row["receipts"] for row in trading_rows], [row[f"{label}_tax_reduction"] for row in trading_rows]) + interpolation_errors.extend(abs(float(plotted) - actual) for plotted, actual in zip(interpolated, changes)) + maximum_model_error = max(model_errors) + maximum_interpolation_error = max(interpolation_errors) + assert maximum_model_error <= 0.01, maximum_model_error + assert maximum_interpolation_error <= 0.01, maximum_interpolation_error + validation = { + "range_gbp": [500, 5_000], "validation_interval_gbp": 2, + "points_per_series": len(grid), "series": 4, + "liability_checks": len(model_errors), "interpolation_checks": len(interpolation_errors), + "chart_interval_gbp": 100, + "savings_breakpoints_gbp": [500, 1_000], + "trading_breakpoints_gbp": list(trading_breakpoints), + "chart_rows": {"savings": len(interest_rows), "trading": len(trading_rows)}, + "maximum_model_error_gbp": maximum_model_error, + "maximum_chart_interpolation_error_gbp": maximum_interpolation_error, + "tolerance_gbp": 0.01, + "method": "All four series checked against pe.uk at every £2; both scenarios compared with independent tax arithmetic; plotted linear interpolation compared with the engine tax changes. The non-integer expense-choice breakpoint is additionally calculated with pe.uk.", + } + return interest_rows, trading_rows, validation def chart_specs(savings, trading) -> dict: source = "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed." return { "savings-interest-chart.json": { - "type": "bar", "title": "Savings tax increases apply above the Personal Savings Allowance", + "type": "line", "title": "Savings tax increases apply above the Personal Savings Allowance", "subtitle": "Annual income tax increase; England, salaries £30,000 and £60,000, 2027–28", - "xKey": "interest", "yLabel": "Extra annual income tax (£)", - "format": {"prefix": "£", "decimals": 0}, "source": source, + "xKey": "interest", "xLabel": "Annual savings interest", "yLabel": "Extra annual income tax", + "format": {"prefix": "£", "decimals": 0, "separator": True}, + "xFormat": {"prefix": "£", "decimals": 0, "separator": True}, "source": source, "series": [ {"key": "basic", "name": "£30,000 salary", "color": "negative"}, {"key": "higher", "name": "£60,000 salary", "color": "secondary"}, ], - "data": [{"interest": f"£{row['interest']:,}", "basic": row["basic_tax_increase"], "higher": row["higher_tax_increase"]} for row in savings], + "markers": [{"x": 500, "label": "£60,000 salary: savings allowance"}, {"x": 1_000, "label": "£30,000 salary: savings allowance"}], + "data": [{"interest": row["interest"], "basic": row["basic_tax_increase"], "higher": row["higher_tax_increase"]} for row in savings], }, "trading-allowance-chart.json": { - "type": "bar", "title": "Trading allowance: the income tax reduction depends on expenses", + "type": "line", "title": "Trading allowance: the income tax reduction depends on expenses", "subtitle": "Annual income tax reduction; England, £30,000 salary, 2027–28", - "xKey": "receipts", "yLabel": "Annual income tax reduction (£)", - "format": {"prefix": "£", "decimals": 0}, "source": source, + "xKey": "receipts", "xLabel": "Annual side-business receipts", "yLabel": "Annual income tax reduction", + "format": {"prefix": "£", "decimals": 0, "separator": True}, + "xFormat": {"prefix": "£", "decimals": 0, "separator": True}, "source": source, "series": [ {"key": "noExpenses", "name": "No business expenses", "color": "primary"}, {"key": "highExpenses", "name": "Expenses equal 75% of receipts", "color": "secondary"}, ], - "data": [{"receipts": f"£{row['receipts']:,}", "noExpenses": row["no_expenses_tax_reduction"], "highExpenses": row["expenses_75_percent_tax_reduction"]} for row in trading], + "markers": [{"x": 1_000, "label": "Current allowance"}, {"x": 3_000, "label": "New allowance"}, {"x": 4_000, "label": "75% expenses equal £3,000"}], + "data": [{"receipts": row["receipts"], "noExpenses": row["no_expenses_tax_reduction"], "highExpenses": row["expenses_75_percent_tax_reduction"]} for row in trading], }, } @@ -334,7 +391,7 @@ def main() -> None: warnings.filterwarnings("ignore", category=UserWarning, message="Accessing \\.values on a MicroSeries returns a plain numpy array without weights\\.") comparison = source_comparison(args.dashboard_checkout) households = generate_cases() - savings, trading = generate_curves() + savings, trading, curve_validation = generate_curves() payload = { "metadata": { "generated_at_utc": datetime.now(timezone.utc).isoformat(), @@ -343,11 +400,13 @@ def main() -> None: "scope": "Synthetic single adults age 35; no microdata, no behavioural responses or national estimates. Income and expenses held fixed; tax liabilities, not full household net-income changes.", "assumptions": "No children, pensions, Gift Aid, student loans, capital gains, other tax reliefs, property losses or carried-forward finance costs. Savings are outside ISAs. Trading receipts and profit are both supplied; no connected-party receipts or partnership income. All example benefit totals are checked to be zero.", "oracle_tolerance_gbp": 0.02, + "forecast": forecast_provenance(), "warning_filters": "Known household divide/invalid RuntimeWarnings and single-household model decile .values warnings only; no population weights are accessed by this generator.", }, "reforms": {"savings_property": SAVINGS_PROPERTY, "trading": TRADING}, "households": households, "savings_interest_curve": savings, "trading_receipts_curve": trading, + "curve_validation": curve_validation, } args.output_dir.mkdir(parents=True, exist_ok=True) (args.output_dir / "households.json").write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n") @@ -366,7 +425,8 @@ def main() -> None: write_csv(args.output_dir / "trading-receipts-curve.csv", trading) for filename, spec in chart_specs(savings, trading).items(): (args.output_dir / filename).write_text(json.dumps(spec, indent=2, ensure_ascii=False) + "\n") - print(f"Verified {len(households)} household comparisons and {len(savings) + len(trading)} curve points; wrote {args.output_dir}") + (args.output_dir / "curve-validation.json").write_text(json.dumps(curve_validation, indent=2, ensure_ascii=False) + "\n") + print(f"Verified {len(households)} household comparisons, {len(savings) + len(trading)} plotted curve points and {curve_validation['interpolation_checks']} dense chart checks; wrote {args.output_dir}") if __name__ == "__main__": diff --git a/analysis/uk-budget-2026-income-tax/generate_trading_extensions.py b/analysis/uk-budget-2026-income-tax/generate_trading_extensions.py index 75ab4a13c..5792ebf2d 100644 --- a/analysis/uk-budget-2026-income-tax/generate_trading_extensions.py +++ b/analysis/uk-budget-2026-income-tax/generate_trading_extensions.py @@ -17,6 +17,8 @@ import policyengine as pe +from forecast import provenance as forecast_provenance, with_forecast + YEAR = 2027 ALLOWANCE_PATH = "gov.hmrc.income_tax.allowances.trading_allowance" @@ -100,7 +102,7 @@ def sole_trader(supply_receipts: bool = True) -> dict: def calculate(inputs: dict, reform: dict) -> dict: result = pe.uk.calculate_household( - **inputs, year=YEAR, reform=reform, + **inputs, year=YEAR, reform=with_forecast(reform), extra_variables=PERSON_OUTPUTS + BENUNIT_OUTPUTS + HOUSEHOLD_OUTPUTS, ) # Preserve wrapper-provided floating-point values, including float32 @@ -213,6 +215,7 @@ def main() -> None: "scope": "Five synthetic case pairs; no population data, behavioural responses or national estimates. Annual model calculations; actual UC assessment periods and timing of tax payments can differ.", "assumptions": "Lone parent age35 with child age4, employment as main job, £18,000 annual wages, side business with zero expenses, London/Central London private rent £12,000/year, UC and Child Benefit take-up true. Sole trader age35, full-time35hours/week, £20,000 receipts and £500 costs, no other income, owns home outright, no UC claim. Both: council tax input zero; no childcare costs, capital, disability, pensions, losses or other income. Omitted inputs otherwise retain pinned model defaults. No UC award, floor amount, work allowance, or earnings intermediate is forced.", "oracle_tolerance_gbp": 0.02, + "forecast": forecast_provenance(), "independent_arithmetic": "Basic-rate income tax20% above Personal Allowance£12,570; known-receipt taxable profit=max(0,receipts-max(expenses,allowance)); Class4 NI6% above£12,570; active UC award falls55% of extra UC net earnings above its unchanged work allowance. Missing-receipt outputs separately test the pinned fallback, not the legal receipt-based calculation.", }, "cases": outputs, diff --git a/analysis/uk-budget-2026-income-tax/households.csv b/analysis/uk-budget-2026-income-tax/households.csv index 86194df52..1ce14b9b1 100644 --- a/analysis/uk-budget-2026-income-tax/households.csv +++ b/analysis/uk-budget-2026-income-tax/households.csv @@ -5,7 +5,7 @@ saver_higher,savings_property,LONDON,2027,60000,2000,0,0,0,0,12062.0,630.0,500.0 saver_additional,savings_property,LONDON,2027,150000,2000,0,0,0,0,54643.0,940.0,0.0,0.0,0.0,0.0,2000.0,0.0,0.0,0.0,0.0,0.0,5010.6,0.0,0.0,54683.0,980.0,0.0,0.0,0.0,0.0,2000.0,0.0,0.0,0.0,0.0,0.0,5010.6,0.0,0.0,40.0,40.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 saver_crosses_basic_higher,savings_property,LONDON,2027,49270,2000,0,0,0,0,7870.0,530.0,500.0,0.0,500.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,2936.0,0.0,0.0,7900.0,560.0,500.0,0.0,500.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,2936.0,0.0,0.0,30.0,30.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 saver_starting_rate,savings_property,LONDON,2027,15000,4000,0,0,0,0,580.6,94.6,1000.0,2570.0,430.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,194.4,0.0,0.0,589.2,103.2,1000.0,2570.0,430.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,194.4,0.0,0.0,8.6,8.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -saver_scotland_higher,savings_property,SCOTLAND,2027,60000,2000,0,0,0,0,13807.87,630.0,500.0,0.0,0.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,3210.6,0.0,0.0,13837.87,660.0,500.0,0.0,0.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,3210.6,0.0,0.0,30.0,30.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +saver_scotland_higher,savings_property,SCOTLAND,2027,60000,2000,0,0,0,0,13804.94,630.0,500.0,0.0,0.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,3210.6,0.0,0.0,13834.94,660.0,500.0,0.0,0.0,1500.0,0.0,0.0,0.0,0.0,0.0,0.0,3210.6,0.0,0.0,30.0,30.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 landlord_basic_mortgage,savings_property,LONDON,2027,30000,0,10000,4000,0,0,4806.0,0.0,1000.0,0.0,0.0,0.0,0.0,2200.0,880.0,10000.0,0.0,0.0,1394.4,0.0,0.0,4926.0,0.0,1000.0,0.0,0.0,0.0,0.0,2400.0,960.0,10000.0,0.0,0.0,1394.4,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 landlord_higher_mortgage,savings_property,LONDON,2027,60000,0,10000,4000,0,0,14752.0,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,880.0,10000.0,0.0,0.0,3210.6,0.0,0.0,14872.0,0.0,500.0,0.0,0.0,0.0,0.0,4400.0,960.0,10000.0,0.0,0.0,3210.6,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 landlord_additional_mortgage,savings_property,LONDON,2027,150000,0,10000,4000,0,0,57523.0,0.0,0.0,0.0,0.0,0.0,0.0,4700.0,880.0,10000.0,0.0,0.0,5010.6,0.0,0.0,57643.0,0.0,0.0,0.0,0.0,0.0,0.0,4900.0,960.0,10000.0,0.0,0.0,5010.6,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 @@ -13,8 +13,8 @@ landlord_crosses_basic_higher_mortgage,savings_property,LONDON,2027,45000,0,1000 landlord_mortgage_free_london,savings_property,LONDON,2027,30000,0,10000,0,0,0,5686.0,0.0,1000.0,0.0,0.0,0.0,0.0,2200.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,5886.0,0.0,1000.0,0.0,0.0,0.0,0.0,2400.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 landlord_mortgage_free_wales,savings_property,WALES,2027,30000,0,10000,0,0,0,5686.0,0.0,1000.0,0.0,0.0,0.0,0.0,2200.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,5886.0,0.0,1000.0,0.0,0.0,0.0,0.0,2400.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 landlord_mortgage_free_northern_ireland,savings_property,NORTHERN_IRELAND,2027,30000,0,10000,0,0,0,5686.0,0.0,1000.0,0.0,0.0,0.0,0.0,2200.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,5886.0,0.0,1000.0,0.0,0.0,0.0,0.0,2400.0,0.0,10000.0,0.0,0.0,1394.4,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,200.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -landlord_scotland_finance_0,savings_property,SCOTLAND,2027,60000,0,10000,0,0,0,17377.87,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,0.0,10000.0,0.0,0.0,3210.6,0.0,0.0,17377.87,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,0.0,10000.0,0.0,0.0,3210.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -landlord_scotland_finance_4000,savings_property,SCOTLAND,2027,60000,0,10000,4000,0,0,16497.87,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,880.0,10000.0,0.0,0.0,3210.6,0.0,0.0,16417.87,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,960.0,10000.0,0.0,0.0,3210.6,0.0,0.0,-80.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_scotland_finance_0,savings_property,SCOTLAND,2027,60000,0,10000,0,0,0,17374.94,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,0.0,10000.0,0.0,0.0,3210.6,0.0,0.0,17374.94,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,0.0,10000.0,0.0,0.0,3210.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +landlord_scotland_finance_4000,savings_property,SCOTLAND,2027,60000,0,10000,4000,0,0,16494.94,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,880.0,10000.0,0.0,0.0,3210.6,0.0,0.0,16414.94,0.0,500.0,0.0,0.0,0.0,0.0,4200.0,960.0,10000.0,0.0,0.0,3210.6,0.0,0.0,-80.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,80.0,0.0,0.0,0.0,0.0,0.0,0.0 property_then_savings_order,savings_property,LONDON,2027,45000,2000,6000,0,0,0,8582.0,630.0,500.0,0.0,0.0,1500.0,0.0,1466.0,0.0,6000.0,0.0,0.0,2594.4,0.0,0.0,8732.0,660.0,500.0,0.0,0.0,1500.0,0.0,1586.0,0.0,6000.0,0.0,0.0,2594.4,0.0,0.0,150.0,30.0,0.0,0.0,0.0,0.0,0.0,120.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 trader_salary_30000_expenses_500,trading,LONDON,2027,30000,0,0,0,4000,3500,4086.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,3000.0,1394.4,0.0,0.0,3686.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2500.0,1000.0,1394.4,0.0,0.0,-400.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2000.0,-2000.0,0.0,0.0,0.0 trader_salary_30000_expenses_2500,trading,LONDON,2027,30000,0,0,0,4000,1500,3786.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1500.0,1394.4,0.0,0.0,3686.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,1000.0,1394.4,0.0,0.0,-100.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,500.0,-500.0,0.0,0.0,0.0 diff --git a/analysis/uk-budget-2026-income-tax/households.json b/analysis/uk-budget-2026-income-tax/households.json index 182007c95..c40b4fca3 100644 --- a/analysis/uk-budget-2026-income-tax/households.json +++ b/analysis/uk-budget-2026-income-tax/households.json @@ -1,6 +1,6 @@ { "metadata": { - "generated_at_utc": "2026-10-28T14:37:16.549617+00:00", + "generated_at_utc": "2026-10-28T16:18:33.153156+00:00", "tax_year": "2027–28", "model_year": 2027, "versions": { @@ -32,12 +32,22 @@ "gov.hmrc.income_tax.rates.property.additional": 0.49, "gov.hmrc.income_tax.allowances.trading_allowance": 3000 }, - "dashboard_builder_verified": true, - "comparison": "Relevant parameter declarations and savings/property builder match the independent flat reform dictionaries; no combined-package modifiers run." + "dashboard_builder_verified": false, + "comparison": "Independent reform dictionaries and baseline parameters verified. Optional dashboard-builder comparison not requested; immutable source reference recorded above." }, "scope": "Synthetic single adults age 35; no microdata, no behavioural responses or national estimates. Income and expenses held fixed; tax liabilities, not full household net-income changes.", "assumptions": "No children, pensions, Gift Aid, student loans, capital gains, other tax reliefs, property losses or carried-forward finance costs. Savings are outside ISAs. Trading receipts and profit are both supplied; no connected-party receipts or partnership income. All example benefit totals are checked to be zero.", "oracle_tolerance_gbp": 0.02, + "forecast": { + "dashboard_commit": "640426575270224db9b04d6c94d30e264a347be2", + "source": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/640426575270224db9b04d6c94d30e264a347be2/src/uk_budget_data/forecast/obr_october_2026.json", + "forecast_file_git_blob": "b504a48fffb93714ff358d869cad712b6daea20e", + "forecast_module_git_blob": "b2ca186b6fd514f334ced11934d38b256e6d2127", + "forecast_file_sha256": "dc039d30660d17f30a45e49538dbd22953e02bd4f6b63eda2eaebcf8252baf54", + "baseline_and_reform": true, + "nominal_household_inputs": "Held fixed in 2027; the forecast updates model parameters, not the supplied income amounts.", + "remaining_series": "March paths remain for cpih, non-labour income, private rent, mortgage interest, per-capita series, council tax and fuel volumes/prices, as recorded by this forecast vintage." + }, "warning_filters": "Known household divide/invalid RuntimeWarnings and single-household model decile .values warnings only; no population weights are accessed by this generator." }, "reforms": { @@ -519,7 +529,7 @@ }, "detail": null, "baseline": { - "income_tax": 13807.87, + "income_tax": 13804.94, "savings_income_tax": 630.0, "savings_allowance": 500.0, "savings_starter_rate_income": 0.0, @@ -536,7 +546,7 @@ "household_benefits": 0.0 }, "reform": { - "income_tax": 13837.87, + "income_tax": 13834.94, "savings_income_tax": 660.0, "savings_allowance": 500.0, "savings_starter_rate_income": 0.0, @@ -1124,7 +1134,7 @@ }, "detail": "Scottish property rates do not change; the UK-wide finance-cost credit rate does.", "baseline": { - "income_tax": 17377.87, + "income_tax": 17374.94, "savings_income_tax": 0.0, "savings_allowance": 500.0, "savings_starter_rate_income": 0.0, @@ -1141,7 +1151,7 @@ "household_benefits": 0.0 }, "reform": { - "income_tax": 17377.87, + "income_tax": 17374.94, "savings_income_tax": 0.0, "savings_allowance": 500.0, "savings_starter_rate_income": 0.0, @@ -1193,7 +1203,7 @@ }, "detail": "Scottish property rates do not change; the UK-wide finance-cost credit rate does.", "baseline": { - "income_tax": 16497.87, + "income_tax": 16494.94, "savings_income_tax": 0.0, "savings_allowance": 500.0, "savings_starter_rate_income": 0.0, @@ -1210,7 +1220,7 @@ "household_benefits": 0.0 }, "reform": { - "income_tax": 16417.87, + "income_tax": 16414.94, "savings_income_tax": 0.0, "savings_allowance": 500.0, "savings_starter_rate_income": 0.0, @@ -1818,6 +1828,42 @@ "higher_reform_tax": 0.0, "higher_tax_increase": 0.0 }, + { + "interest": 600, + "basic_baseline_tax": 0.0, + "basic_reform_tax": 0.0, + "basic_tax_increase": 0.0, + "higher_baseline_tax": 42.0, + "higher_reform_tax": 44.0, + "higher_tax_increase": 2.0 + }, + { + "interest": 700, + "basic_baseline_tax": 0.0, + "basic_reform_tax": 0.0, + "basic_tax_increase": 0.0, + "higher_baseline_tax": 84.0, + "higher_reform_tax": 88.0, + "higher_tax_increase": 4.0 + }, + { + "interest": 800, + "basic_baseline_tax": 0.0, + "basic_reform_tax": 0.0, + "basic_tax_increase": 0.0, + "higher_baseline_tax": 126.0, + "higher_reform_tax": 132.0, + "higher_tax_increase": 6.0 + }, + { + "interest": 900, + "basic_baseline_tax": 0.0, + "basic_reform_tax": 0.0, + "basic_tax_increase": 0.0, + "higher_baseline_tax": 168.0, + "higher_reform_tax": 176.0, + "higher_tax_increase": 8.0 + }, { "interest": 1000, "basic_baseline_tax": 0.0, @@ -1827,6 +1873,42 @@ "higher_reform_tax": 220.0, "higher_tax_increase": 10.0 }, + { + "interest": 1100, + "basic_baseline_tax": 22.0, + "basic_reform_tax": 24.0, + "basic_tax_increase": 2.0, + "higher_baseline_tax": 252.0, + "higher_reform_tax": 264.0, + "higher_tax_increase": 12.0 + }, + { + "interest": 1200, + "basic_baseline_tax": 44.0, + "basic_reform_tax": 48.0, + "basic_tax_increase": 4.0, + "higher_baseline_tax": 294.0, + "higher_reform_tax": 308.0, + "higher_tax_increase": 14.0 + }, + { + "interest": 1300, + "basic_baseline_tax": 66.0, + "basic_reform_tax": 72.0, + "basic_tax_increase": 6.0, + "higher_baseline_tax": 336.0, + "higher_reform_tax": 352.0, + "higher_tax_increase": 16.0 + }, + { + "interest": 1400, + "basic_baseline_tax": 88.0, + "basic_reform_tax": 96.0, + "basic_tax_increase": 8.0, + "higher_baseline_tax": 378.0, + "higher_reform_tax": 396.0, + "higher_tax_increase": 18.0 + }, { "interest": 1500, "basic_baseline_tax": 110.0, @@ -1836,6 +1918,42 @@ "higher_reform_tax": 440.0, "higher_tax_increase": 20.0 }, + { + "interest": 1600, + "basic_baseline_tax": 132.0, + "basic_reform_tax": 144.0, + "basic_tax_increase": 12.0, + "higher_baseline_tax": 462.0, + "higher_reform_tax": 484.0, + "higher_tax_increase": 22.0 + }, + { + "interest": 1700, + "basic_baseline_tax": 154.0, + "basic_reform_tax": 168.0, + "basic_tax_increase": 14.0, + "higher_baseline_tax": 504.0, + "higher_reform_tax": 528.0, + "higher_tax_increase": 24.0 + }, + { + "interest": 1800, + "basic_baseline_tax": 176.0, + "basic_reform_tax": 192.0, + "basic_tax_increase": 16.0, + "higher_baseline_tax": 546.0, + "higher_reform_tax": 572.0, + "higher_tax_increase": 26.0 + }, + { + "interest": 1900, + "basic_baseline_tax": 198.0, + "basic_reform_tax": 216.0, + "basic_tax_increase": 18.0, + "higher_baseline_tax": 588.0, + "higher_reform_tax": 616.0, + "higher_tax_increase": 28.0 + }, { "interest": 2000, "basic_baseline_tax": 220.0, @@ -1845,6 +1963,42 @@ "higher_reform_tax": 660.0, "higher_tax_increase": 30.0 }, + { + "interest": 2100, + "basic_baseline_tax": 242.0, + "basic_reform_tax": 264.0, + "basic_tax_increase": 22.0, + "higher_baseline_tax": 672.0, + "higher_reform_tax": 704.0, + "higher_tax_increase": 32.0 + }, + { + "interest": 2200, + "basic_baseline_tax": 264.0, + "basic_reform_tax": 288.0, + "basic_tax_increase": 24.0, + "higher_baseline_tax": 714.0, + "higher_reform_tax": 748.0, + "higher_tax_increase": 34.0 + }, + { + "interest": 2300, + "basic_baseline_tax": 286.0, + "basic_reform_tax": 312.0, + "basic_tax_increase": 26.0, + "higher_baseline_tax": 756.0, + "higher_reform_tax": 792.0, + "higher_tax_increase": 36.0 + }, + { + "interest": 2400, + "basic_baseline_tax": 308.0, + "basic_reform_tax": 336.0, + "basic_tax_increase": 28.0, + "higher_baseline_tax": 798.0, + "higher_reform_tax": 836.0, + "higher_tax_increase": 38.0 + }, { "interest": 2500, "basic_baseline_tax": 330.0, @@ -1854,6 +2008,42 @@ "higher_reform_tax": 880.0, "higher_tax_increase": 40.0 }, + { + "interest": 2600, + "basic_baseline_tax": 352.0, + "basic_reform_tax": 384.0, + "basic_tax_increase": 32.0, + "higher_baseline_tax": 882.0, + "higher_reform_tax": 924.0, + "higher_tax_increase": 42.0 + }, + { + "interest": 2700, + "basic_baseline_tax": 374.0, + "basic_reform_tax": 408.0, + "basic_tax_increase": 34.0, + "higher_baseline_tax": 924.0, + "higher_reform_tax": 968.0, + "higher_tax_increase": 44.0 + }, + { + "interest": 2800, + "basic_baseline_tax": 396.0, + "basic_reform_tax": 432.0, + "basic_tax_increase": 36.0, + "higher_baseline_tax": 966.0, + "higher_reform_tax": 1012.0, + "higher_tax_increase": 46.0 + }, + { + "interest": 2900, + "basic_baseline_tax": 418.0, + "basic_reform_tax": 456.0, + "basic_tax_increase": 38.0, + "higher_baseline_tax": 1008.0, + "higher_reform_tax": 1056.0, + "higher_tax_increase": 48.0 + }, { "interest": 3000, "basic_baseline_tax": 440.0, @@ -1863,6 +2053,42 @@ "higher_reform_tax": 1100.0, "higher_tax_increase": 50.0 }, + { + "interest": 3100, + "basic_baseline_tax": 462.0, + "basic_reform_tax": 504.0, + "basic_tax_increase": 42.0, + "higher_baseline_tax": 1092.0, + "higher_reform_tax": 1144.0, + "higher_tax_increase": 52.0 + }, + { + "interest": 3200, + "basic_baseline_tax": 484.0, + "basic_reform_tax": 528.0, + "basic_tax_increase": 44.0, + "higher_baseline_tax": 1134.0, + "higher_reform_tax": 1188.0, + "higher_tax_increase": 54.0 + }, + { + "interest": 3300, + "basic_baseline_tax": 506.0, + "basic_reform_tax": 552.0, + "basic_tax_increase": 46.0, + "higher_baseline_tax": 1176.0, + "higher_reform_tax": 1232.0, + "higher_tax_increase": 56.0 + }, + { + "interest": 3400, + "basic_baseline_tax": 528.0, + "basic_reform_tax": 576.0, + "basic_tax_increase": 48.0, + "higher_baseline_tax": 1218.0, + "higher_reform_tax": 1276.0, + "higher_tax_increase": 58.0 + }, { "interest": 3500, "basic_baseline_tax": 550.0, @@ -1872,6 +2098,42 @@ "higher_reform_tax": 1320.0, "higher_tax_increase": 60.0 }, + { + "interest": 3600, + "basic_baseline_tax": 572.0, + "basic_reform_tax": 624.0, + "basic_tax_increase": 52.0, + "higher_baseline_tax": 1302.0, + "higher_reform_tax": 1364.0, + "higher_tax_increase": 62.0 + }, + { + "interest": 3700, + "basic_baseline_tax": 594.0, + "basic_reform_tax": 648.0, + "basic_tax_increase": 54.0, + "higher_baseline_tax": 1344.0, + "higher_reform_tax": 1408.0, + "higher_tax_increase": 64.0 + }, + { + "interest": 3800, + "basic_baseline_tax": 616.0, + "basic_reform_tax": 672.0, + "basic_tax_increase": 56.0, + "higher_baseline_tax": 1386.0, + "higher_reform_tax": 1452.0, + "higher_tax_increase": 66.0 + }, + { + "interest": 3900, + "basic_baseline_tax": 638.0, + "basic_reform_tax": 696.0, + "basic_tax_increase": 58.0, + "higher_baseline_tax": 1428.0, + "higher_reform_tax": 1496.0, + "higher_tax_increase": 68.0 + }, { "interest": 4000, "basic_baseline_tax": 660.0, @@ -1881,6 +2143,42 @@ "higher_reform_tax": 1540.0, "higher_tax_increase": 70.0 }, + { + "interest": 4100, + "basic_baseline_tax": 682.0, + "basic_reform_tax": 744.0, + "basic_tax_increase": 62.0, + "higher_baseline_tax": 1512.0, + "higher_reform_tax": 1584.0, + "higher_tax_increase": 72.0 + }, + { + "interest": 4200, + "basic_baseline_tax": 704.0, + "basic_reform_tax": 768.0, + "basic_tax_increase": 64.0, + "higher_baseline_tax": 1554.0, + "higher_reform_tax": 1628.0, + "higher_tax_increase": 74.0 + }, + { + "interest": 4300, + "basic_baseline_tax": 726.0, + "basic_reform_tax": 792.0, + "basic_tax_increase": 66.0, + "higher_baseline_tax": 1596.0, + "higher_reform_tax": 1672.0, + "higher_tax_increase": 76.0 + }, + { + "interest": 4400, + "basic_baseline_tax": 748.0, + "basic_reform_tax": 816.0, + "basic_tax_increase": 68.0, + "higher_baseline_tax": 1638.0, + "higher_reform_tax": 1716.0, + "higher_tax_increase": 78.0 + }, { "interest": 4500, "basic_baseline_tax": 770.0, @@ -1890,6 +2188,42 @@ "higher_reform_tax": 1760.0, "higher_tax_increase": 80.0 }, + { + "interest": 4600, + "basic_baseline_tax": 792.0, + "basic_reform_tax": 864.0, + "basic_tax_increase": 72.0, + "higher_baseline_tax": 1722.0, + "higher_reform_tax": 1804.0, + "higher_tax_increase": 82.0 + }, + { + "interest": 4700, + "basic_baseline_tax": 814.0, + "basic_reform_tax": 888.0, + "basic_tax_increase": 74.0, + "higher_baseline_tax": 1764.0, + "higher_reform_tax": 1848.0, + "higher_tax_increase": 84.0 + }, + { + "interest": 4800, + "basic_baseline_tax": 836.0, + "basic_reform_tax": 912.0, + "basic_tax_increase": 76.0, + "higher_baseline_tax": 1806.0, + "higher_reform_tax": 1892.0, + "higher_tax_increase": 86.0 + }, + { + "interest": 4900, + "basic_baseline_tax": 858.0, + "basic_reform_tax": 936.0, + "basic_tax_increase": 78.0, + "higher_baseline_tax": 1848.0, + "higher_reform_tax": 1936.0, + "higher_tax_increase": 88.0 + }, { "interest": 5000, "basic_baseline_tax": 880.0, @@ -1912,6 +2246,50 @@ "expenses_75_percent_reform_taxable_profit": 0, "expenses_75_percent_tax_reduction": 0.0 }, + { + "receipts": 600, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 0, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 0.0, + "expenses_75_percent_actual_expenses": 450.0, + "expenses_75_percent_baseline_taxable_profit": 0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 700, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 0, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 0.0, + "expenses_75_percent_actual_expenses": 525.0, + "expenses_75_percent_baseline_taxable_profit": 0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 800, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 0, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 0.0, + "expenses_75_percent_actual_expenses": 600.0, + "expenses_75_percent_baseline_taxable_profit": 0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 900, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 0, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 0.0, + "expenses_75_percent_actual_expenses": 675.0, + "expenses_75_percent_baseline_taxable_profit": 0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 0.0 + }, { "receipts": 1000, "no_expenses_actual_expenses": 0, @@ -1923,6 +2301,61 @@ "expenses_75_percent_reform_taxable_profit": 0, "expenses_75_percent_tax_reduction": 0.0 }, + { + "receipts": 1100, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 100, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 20.0, + "expenses_75_percent_actual_expenses": 825.0, + "expenses_75_percent_baseline_taxable_profit": 100, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 20.0 + }, + { + "receipts": 1200, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 200, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 40.0, + "expenses_75_percent_actual_expenses": 900.0, + "expenses_75_percent_baseline_taxable_profit": 200, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 40.0 + }, + { + "receipts": 1300, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 300, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 60.0, + "expenses_75_percent_actual_expenses": 975.0, + "expenses_75_percent_baseline_taxable_profit": 300, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 60.0 + }, + { + "receipts": 1333.3333333333333, + "no_expenses_actual_expenses": 0.0, + "no_expenses_baseline_taxable_profit": 333.33333333333326, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 66.67, + "expenses_75_percent_actual_expenses": 1000.0, + "expenses_75_percent_baseline_taxable_profit": 333.33333333333326, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 66.67 + }, + { + "receipts": 1400, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 400, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 80.0, + "expenses_75_percent_actual_expenses": 1050.0, + "expenses_75_percent_baseline_taxable_profit": 350.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 70.0 + }, { "receipts": 1500, "no_expenses_actual_expenses": 0, @@ -1934,6 +2367,50 @@ "expenses_75_percent_reform_taxable_profit": 0, "expenses_75_percent_tax_reduction": 75.0 }, + { + "receipts": 1600, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 600, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 120.0, + "expenses_75_percent_actual_expenses": 1200.0, + "expenses_75_percent_baseline_taxable_profit": 400.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 80.0 + }, + { + "receipts": 1700, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 700, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 140.0, + "expenses_75_percent_actual_expenses": 1275.0, + "expenses_75_percent_baseline_taxable_profit": 425.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 85.0 + }, + { + "receipts": 1800, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 800, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 160.0, + "expenses_75_percent_actual_expenses": 1350.0, + "expenses_75_percent_baseline_taxable_profit": 450.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 90.0 + }, + { + "receipts": 1900, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 900, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 180.0, + "expenses_75_percent_actual_expenses": 1425.0, + "expenses_75_percent_baseline_taxable_profit": 475.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 95.0 + }, { "receipts": 2000, "no_expenses_actual_expenses": 0, @@ -1945,6 +2422,50 @@ "expenses_75_percent_reform_taxable_profit": 0, "expenses_75_percent_tax_reduction": 100.0 }, + { + "receipts": 2100, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1100, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 220.0, + "expenses_75_percent_actual_expenses": 1575.0, + "expenses_75_percent_baseline_taxable_profit": 525.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 105.0 + }, + { + "receipts": 2200, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1200, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 240.0, + "expenses_75_percent_actual_expenses": 1650.0, + "expenses_75_percent_baseline_taxable_profit": 550.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 110.0 + }, + { + "receipts": 2300, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1300, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 260.0, + "expenses_75_percent_actual_expenses": 1725.0, + "expenses_75_percent_baseline_taxable_profit": 575.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 115.0 + }, + { + "receipts": 2400, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1400, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 280.0, + "expenses_75_percent_actual_expenses": 1800.0, + "expenses_75_percent_baseline_taxable_profit": 600.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 120.0 + }, { "receipts": 2500, "no_expenses_actual_expenses": 0, @@ -1956,6 +2477,50 @@ "expenses_75_percent_reform_taxable_profit": 0, "expenses_75_percent_tax_reduction": 125.0 }, + { + "receipts": 2600, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1600, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 320.0, + "expenses_75_percent_actual_expenses": 1950.0, + "expenses_75_percent_baseline_taxable_profit": 650.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 130.0 + }, + { + "receipts": 2700, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1700, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 340.0, + "expenses_75_percent_actual_expenses": 2025.0, + "expenses_75_percent_baseline_taxable_profit": 675.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 135.0 + }, + { + "receipts": 2800, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1800, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 360.0, + "expenses_75_percent_actual_expenses": 2100.0, + "expenses_75_percent_baseline_taxable_profit": 700.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 140.0 + }, + { + "receipts": 2900, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 1900, + "no_expenses_reform_taxable_profit": 0, + "no_expenses_tax_reduction": 380.0, + "expenses_75_percent_actual_expenses": 2175.0, + "expenses_75_percent_baseline_taxable_profit": 725.0, + "expenses_75_percent_reform_taxable_profit": 0, + "expenses_75_percent_tax_reduction": 145.0 + }, { "receipts": 3000, "no_expenses_actual_expenses": 0, @@ -1967,6 +2532,50 @@ "expenses_75_percent_reform_taxable_profit": 0, "expenses_75_percent_tax_reduction": 150.0 }, + { + "receipts": 3100, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2100, + "no_expenses_reform_taxable_profit": 100, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2325.0, + "expenses_75_percent_baseline_taxable_profit": 775.0, + "expenses_75_percent_reform_taxable_profit": 100, + "expenses_75_percent_tax_reduction": 135.0 + }, + { + "receipts": 3200, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2200, + "no_expenses_reform_taxable_profit": 200, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2400.0, + "expenses_75_percent_baseline_taxable_profit": 800.0, + "expenses_75_percent_reform_taxable_profit": 200, + "expenses_75_percent_tax_reduction": 120.0 + }, + { + "receipts": 3300, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2300, + "no_expenses_reform_taxable_profit": 300, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2475.0, + "expenses_75_percent_baseline_taxable_profit": 825.0, + "expenses_75_percent_reform_taxable_profit": 300, + "expenses_75_percent_tax_reduction": 105.0 + }, + { + "receipts": 3400, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2400, + "no_expenses_reform_taxable_profit": 400, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2550.0, + "expenses_75_percent_baseline_taxable_profit": 850.0, + "expenses_75_percent_reform_taxable_profit": 400, + "expenses_75_percent_tax_reduction": 90.0 + }, { "receipts": 3500, "no_expenses_actual_expenses": 0, @@ -1978,6 +2587,50 @@ "expenses_75_percent_reform_taxable_profit": 500, "expenses_75_percent_tax_reduction": 75.0 }, + { + "receipts": 3600, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2600, + "no_expenses_reform_taxable_profit": 600, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2700.0, + "expenses_75_percent_baseline_taxable_profit": 900.0, + "expenses_75_percent_reform_taxable_profit": 600, + "expenses_75_percent_tax_reduction": 60.0 + }, + { + "receipts": 3700, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2700, + "no_expenses_reform_taxable_profit": 700, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2775.0, + "expenses_75_percent_baseline_taxable_profit": 925.0, + "expenses_75_percent_reform_taxable_profit": 700, + "expenses_75_percent_tax_reduction": 45.0 + }, + { + "receipts": 3800, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2800, + "no_expenses_reform_taxable_profit": 800, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2850.0, + "expenses_75_percent_baseline_taxable_profit": 950.0, + "expenses_75_percent_reform_taxable_profit": 800, + "expenses_75_percent_tax_reduction": 30.0 + }, + { + "receipts": 3900, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 2900, + "no_expenses_reform_taxable_profit": 900, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 2925.0, + "expenses_75_percent_baseline_taxable_profit": 975.0, + "expenses_75_percent_reform_taxable_profit": 900, + "expenses_75_percent_tax_reduction": 15.0 + }, { "receipts": 4000, "no_expenses_actual_expenses": 0, @@ -1989,6 +2642,50 @@ "expenses_75_percent_reform_taxable_profit": 1000.0, "expenses_75_percent_tax_reduction": 0.0 }, + { + "receipts": 4100, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3100, + "no_expenses_reform_taxable_profit": 1100, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3075.0, + "expenses_75_percent_baseline_taxable_profit": 1025.0, + "expenses_75_percent_reform_taxable_profit": 1025.0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 4200, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3200, + "no_expenses_reform_taxable_profit": 1200, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3150.0, + "expenses_75_percent_baseline_taxable_profit": 1050.0, + "expenses_75_percent_reform_taxable_profit": 1050.0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 4300, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3300, + "no_expenses_reform_taxable_profit": 1300, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3225.0, + "expenses_75_percent_baseline_taxable_profit": 1075.0, + "expenses_75_percent_reform_taxable_profit": 1075.0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 4400, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3400, + "no_expenses_reform_taxable_profit": 1400, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3300.0, + "expenses_75_percent_baseline_taxable_profit": 1100.0, + "expenses_75_percent_reform_taxable_profit": 1100.0, + "expenses_75_percent_tax_reduction": 0.0 + }, { "receipts": 4500, "no_expenses_actual_expenses": 0, @@ -2000,6 +2697,50 @@ "expenses_75_percent_reform_taxable_profit": 1125.0, "expenses_75_percent_tax_reduction": 0.0 }, + { + "receipts": 4600, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3600, + "no_expenses_reform_taxable_profit": 1600, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3450.0, + "expenses_75_percent_baseline_taxable_profit": 1150.0, + "expenses_75_percent_reform_taxable_profit": 1150.0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 4700, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3700, + "no_expenses_reform_taxable_profit": 1700, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3525.0, + "expenses_75_percent_baseline_taxable_profit": 1175.0, + "expenses_75_percent_reform_taxable_profit": 1175.0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 4800, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3800, + "no_expenses_reform_taxable_profit": 1800, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3600.0, + "expenses_75_percent_baseline_taxable_profit": 1200.0, + "expenses_75_percent_reform_taxable_profit": 1200.0, + "expenses_75_percent_tax_reduction": 0.0 + }, + { + "receipts": 4900, + "no_expenses_actual_expenses": 0, + "no_expenses_baseline_taxable_profit": 3900, + "no_expenses_reform_taxable_profit": 1900, + "no_expenses_tax_reduction": 400.0, + "expenses_75_percent_actual_expenses": 3675.0, + "expenses_75_percent_baseline_taxable_profit": 1225.0, + "expenses_75_percent_reform_taxable_profit": 1225.0, + "expenses_75_percent_tax_reduction": 0.0 + }, { "receipts": 5000, "no_expenses_actual_expenses": 0, @@ -2011,5 +2752,35 @@ "expenses_75_percent_reform_taxable_profit": 1250.0, "expenses_75_percent_tax_reduction": 0.0 } - ] + ], + "curve_validation": { + "range_gbp": [ + 500, + 5000 + ], + "validation_interval_gbp": 2, + "points_per_series": 2251, + "series": 4, + "liability_checks": 18008, + "interpolation_checks": 9004, + "chart_interval_gbp": 100, + "savings_breakpoints_gbp": [ + 500, + 1000 + ], + "trading_breakpoints_gbp": [ + 1000, + 1333.3333333333333, + 3000, + 4000 + ], + "chart_rows": { + "savings": 46, + "trading": 47 + }, + "maximum_model_error_gbp": 2.2737367544323206e-13, + "maximum_chart_interpolation_error_gbp": 0.0033000000000242835, + "tolerance_gbp": 0.01, + "method": "All four series checked against pe.uk at every £2; both scenarios compared with independent tax arithmetic; plotted linear interpolation compared with the engine tax changes. The non-integer expense-choice breakpoint is additionally calculated with pe.uk." + } } diff --git a/analysis/uk-budget-2026-income-tax/obr_october_2026.json b/analysis/uk-budget-2026-income-tax/obr_october_2026.json new file mode 100644 index 000000000..b504a48ff --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/obr_october_2026.json @@ -0,0 +1,89 @@ +{ + "vintage": "OBR EFO October 2026", + "source": "OBR, Economic and fiscal outlook, October 2026, Annex A", + "source_url": "https://www.gov.uk/government/publications/october-2026-economic-and-fiscal-outlook", + "replaces": "OBR EFO March 2026, as shipped in policyengine-uk 2.151.0 (gov.economic_assumptions.yoy_growth.obr)", + "applies_to": "Every simulation the dashboard builds, baseline and reform alike (uk_budget_data.forecast.with_forecast). Applied before data load, so the dataset's projected years follow it.", + "notes": [ + "Growth rates are Table A.1 (Economy forecast, EFO page 180), percentage change on a year earlier, calendar years 2026 to 2031, keyed YYYY-01-01.YYYY-12-31. 2025 is outturn in Table A.1 and is left as shipped; after 2031 the engine's long-run path is kept.", + "The engine's March values equal the March Table A.1 rows: the October value minus the Table A.2 change since March, to within 0.1pp rounding (tests/test_forecast_basis.py).", + "Statutory uprating inputs keep their published outturns (September 2026 CPI 3.5%, May-July 2026 earnings 3.9%). Their forecast years are calendar-year growth plus the engine's forecast_gap, which still holds the March 2026 quarterly gaps except where noted below.", + "September 2027 CPI: Table A.3 (EFO page 181) gives the 2027-28 triple-lock guarantee as 3.4%, the highest of Q2 2027 earnings growth, Q3 2027 CPI and 2.5%. Q2 earnings cannot reach 3.4% (calendar-year 2027 earnings growth is 3.0%), so Q3 2027 CPI is 3.4%, equal to calendar-year 2027 CPI: the gap is 0. The March gap (+0.07pp) would have given 3.5%.", + "Every later Table A.3 triple-lock figure (2.5, 2.5, 2.5, 2.6 for 2028-29 to 2031-32) is reproduced by these series and the remaining March gaps (tests/test_forecast_basis.py).", + "Fuel duty (gov.hmrc.fuel_duty.petrol_and_diesel), added in code (uk_budget_data.forecast.fuel_duty_rpi_steps): policyengine-uk stores current law's RPI steps as values from its March RPI. Current law here is the OBR's 60.59p from April 2027 (EFO paragraph 3.19: on 1 July 2027 the 5p cut is reversed with an RPI uprating, 52.95p to 60.59p; the Budget defers that same planned RPI increase from April), then each 1 April the previous calendar year's Table A.1 RPI. The baseline and the fuel duty measure both read this one path.", + "Not updated (the OBR detailed forecast tables could not be retrieved): cpih, non_labour_income, rent, mortgage_interest, per_capita, council_tax, fuel volume and price series. They keep the March 2026 path. consumer_price_index_ahc and social_rent are derived from Table A.1 CPI (see their sources)." + ], + "parameter_changes": { + "gov.economic_assumptions.yoy_growth.obr.consumer_price_index": { + "source": "Table A.1, Inflation: CPI", + "values": { + "2026-01-01.2026-12-31": 0.031, + "2027-01-01.2027-12-31": 0.034, + "2028-01-01.2028-12-31": 0.021, + "2029-01-01.2029-12-31": 0.021, + "2030-01-01.2030-12-31": 0.02, + "2031-01-01.2031-12-31": 0.02 + } + }, + "gov.economic_assumptions.yoy_growth.obr.rpi": { + "source": "Table A.1, Inflation: RPI", + "values": { + "2026-01-01.2026-12-31": 0.036, + "2027-01-01.2027-12-31": 0.043, + "2028-01-01.2028-12-31": 0.03, + "2029-01-01.2029-12-31": 0.03, + "2030-01-01.2030-12-31": 0.023, + "2031-01-01.2031-12-31": 0.022 + } + }, + "gov.economic_assumptions.yoy_growth.obr.average_earnings": { + "source": "Table A.1, Labour market: Average weekly earnings (wages and salaries divided by employees)", + "values": { + "2026-01-01.2026-12-31": 0.037, + "2027-01-01.2027-12-31": 0.03, + "2028-01-01.2028-12-31": 0.022, + "2029-01-01.2029-12-31": 0.023, + "2030-01-01.2030-12-31": 0.025, + "2031-01-01.2031-12-31": 0.026 + } + }, + "gov.economic_assumptions.yoy_growth.obr.house_prices": { + "source": "Table A.1, Household sector: House prices", + "values": { + "2026-01-01.2026-12-31": 0.021, + "2027-01-01.2027-12-31": 0.024, + "2028-01-01.2028-12-31": 0.028, + "2029-01-01.2029-12-31": 0.028, + "2030-01-01.2030-12-31": 0.027, + "2031-01-01.2031-12-31": 0.027 + } + }, + "gov.economic_assumptions.yoy_growth.obr.consumer_price_index_ahc": { + "source": "Table A.1, CPI, as a change: PolicyEngine approximation (not an OBR series), policyengine-uk's March 2026 CPI after housing costs moved by the change in Table A.1 CPI for the same year, as the Living standards tab's October series (living_standards/forecast.py)", + "values": { + "2026-01-01.2026-12-31": 0.0297, + "2027-01-01.2027-12-31": 0.0328, + "2028-01-01.2028-12-31": 0.0204, + "2029-01-01.2029-12-31": 0.0204, + "2030-01-01.2030-12-31": 0.0192, + "2031-01-01.2031-12-31": 0.0192 + } + }, + "gov.economic_assumptions.yoy_growth.obr.social_rent": { + "source": "Table A.1, CPI: England social rent policy cap, the previous calendar year's CPI + 1% (2026 is set by September 2025 CPI outturn and kept), as the Living standards tab's October series", + "values": { + "2027-01-01.2027-12-31": 0.041, + "2028-01-01.2028-12-31": 0.044, + "2029-01-01.2029-12-31": 0.031, + "2030-01-01.2030-12-31": 0.031, + "2031-01-01.2031-12-31": 0.03 + } + }, + "gov.economic_assumptions.statutory_uprating_inputs.forecast_gap.cpi_september": { + "source": "Table A.3, 'Triple-lock' guarantee 2027-28: 3.4 (Q3 2027 CPI) minus Table A.1 calendar-year 2027 CPI 3.4", + "values": { + "2027-09-01.2028-08-31": 0.0 + } + } + } +} diff --git a/analysis/uk-budget-2026-income-tax/provenance.json b/analysis/uk-budget-2026-income-tax/provenance.json index a447c6a34..b63c6a87e 100644 --- a/analysis/uk-budget-2026-income-tax/provenance.json +++ b/analysis/uk-budget-2026-income-tax/provenance.json @@ -56,17 +56,19 @@ ] }, "live_source_check": { - "checked_at_utc": "2026-10-28T16:04:05Z", - "manifest_revision": 15, - "manifest_updated_at": "2026-10-28T16:01:00.454209Z", - "property_income_rates_up": "not_yet_published", - "savings_income_rates_up": "not_yet_published", + "manifest_revision": 17, + "manifest_updated_at": "2026-10-28T16:09:01.451619Z", + "property_income_rates_up": "provisional_reconciliation_failed", + "savings_income_rates_up": "provisional_reconciliation_failed", "unearned_income_rates_up": "withdrawn_due_to_measure_split", "new_trading_artifact": "71f8a26e4f547021", "new_trading_status": "provisional_reconciliation_failed", "new_trading_dataset_matches_pin": true, "replacement_adopted": false, - "forecast_note": "New trading batch has October detailed forecasts but still March council tax; it is not the final forecast batch." + "forecast_note": "Replacement artifacts remain unapproved. The household forecast pin is independent of these national artifacts.", + "property_artifact": "3537bd303ac226cf", + "savings_artifact": "af6aaaee33f616ee", + "source_check_note": "Manifest17 status reported by the parent task during the PTA alignment; manifest_updated_at is the publisher timestamp, not a local fetch timestamp." } }, "treasury_costings": { @@ -114,5 +116,57 @@ "raw_population_accessed": false, "additional_internal_population_numbers_adopted": false, "final_regeneration_note": "Detailed October forecast tables and council tax are expected; retain the recorded first-estimate snapshot until replacement outputs bind the exact dataset and forecast." + }, + "household_forecast": { + "dashboard_commit": "640426575270224db9b04d6c94d30e264a347be2", + "forecast_file_git_blob": "b504a48fffb93714ff358d869cad712b6daea20e", + "forecast_module_git_blob": "b2ca186b6fd514f334ced11934d38b256e6d2127", + "both_baseline_and_reform": true, + "fixed_nominal_inputs": true, + "reference_pr": "https://github.com/PolicyEngine/policyengine-app-v2/pull/1457", + "reference_pr_head": "d282ef870176c81feb87175d02584121bdc50197", + "equivalence": "Exact eight-path equality with source with_forecast(None).parameter_changes was checked; synthetic households have no population data load.", + "national_outputs_regenerated": false, + "national_forecast_still_recorded_separately": true, + "forecast_file_sha256": "dc039d30660d17f30a45e49538dbd22953e02bd4f6b63eda2eaebcf8252baf54" + }, + "chart_methodology": { + "renderer_dependency": "https://github.com/PolicyEngine/policyengine-app-v2/pull/1462", + "type": "numeric line", + "chart_interval_gbp": 100, + "validation_interval_gbp": 2, + "validation_record": "curve-validation.json", + "tolerance_gbp": 0.01, + "breakpoints": "All allowance and expense-choice breakpoints within the plotted £500–£5,000 range.", + "validation_results": { + "range_gbp": [ + 500, + 5000 + ], + "validation_interval_gbp": 2, + "points_per_series": 2251, + "series": 4, + "liability_checks": 18008, + "interpolation_checks": 9004, + "chart_interval_gbp": 100, + "savings_breakpoints_gbp": [ + 500, + 1000 + ], + "trading_breakpoints_gbp": [ + 1000, + 1333.3333333333333, + 3000, + 4000 + ], + "chart_rows": { + "savings": 46, + "trading": 47 + }, + "maximum_model_error_gbp": 2.2737367544323206e-13, + "maximum_chart_interpolation_error_gbp": 0.0033000000000242835, + "tolerance_gbp": 0.01, + "method": "All four series checked against pe.uk at every £2; both scenarios compared with independent tax arithmetic; plotted linear interpolation compared with the engine tax changes. The non-integer expense-choice breakpoint is additionally calculated with pe.uk." + } } } diff --git a/analysis/uk-budget-2026-income-tax/savings-interest-chart.json b/analysis/uk-budget-2026-income-tax/savings-interest-chart.json index 516fc1488..b471abc31 100644 --- a/analysis/uk-budget-2026-income-tax/savings-interest-chart.json +++ b/analysis/uk-budget-2026-income-tax/savings-interest-chart.json @@ -1,12 +1,19 @@ { - "type": "bar", + "type": "line", "title": "Savings tax increases apply above the Personal Savings Allowance", "subtitle": "Annual income tax increase; England, salaries £30,000 and £60,000, 2027–28", "xKey": "interest", - "yLabel": "Extra annual income tax (£)", + "xLabel": "Annual savings interest", + "yLabel": "Extra annual income tax", "format": { "prefix": "£", - "decimals": 0 + "decimals": 0, + "separator": true + }, + "xFormat": { + "prefix": "£", + "decimals": 0, + "separator": true }, "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", "series": [ @@ -21,54 +28,244 @@ "color": "secondary" } ], + "markers": [ + { + "x": 500, + "label": "£60,000 salary: savings allowance" + }, + { + "x": 1000, + "label": "£30,000 salary: savings allowance" + } + ], "data": [ { - "interest": "£500", + "interest": 500, "basic": 0.0, "higher": 0.0 }, { - "interest": "£1,000", + "interest": 600, + "basic": 0.0, + "higher": 2.0 + }, + { + "interest": 700, + "basic": 0.0, + "higher": 4.0 + }, + { + "interest": 800, + "basic": 0.0, + "higher": 6.0 + }, + { + "interest": 900, + "basic": 0.0, + "higher": 8.0 + }, + { + "interest": 1000, "basic": 0.0, "higher": 10.0 }, { - "interest": "£1,500", + "interest": 1100, + "basic": 2.0, + "higher": 12.0 + }, + { + "interest": 1200, + "basic": 4.0, + "higher": 14.0 + }, + { + "interest": 1300, + "basic": 6.0, + "higher": 16.0 + }, + { + "interest": 1400, + "basic": 8.0, + "higher": 18.0 + }, + { + "interest": 1500, "basic": 10.0, "higher": 20.0 }, { - "interest": "£2,000", + "interest": 1600, + "basic": 12.0, + "higher": 22.0 + }, + { + "interest": 1700, + "basic": 14.0, + "higher": 24.0 + }, + { + "interest": 1800, + "basic": 16.0, + "higher": 26.0 + }, + { + "interest": 1900, + "basic": 18.0, + "higher": 28.0 + }, + { + "interest": 2000, "basic": 20.0, "higher": 30.0 }, { - "interest": "£2,500", + "interest": 2100, + "basic": 22.0, + "higher": 32.0 + }, + { + "interest": 2200, + "basic": 24.0, + "higher": 34.0 + }, + { + "interest": 2300, + "basic": 26.0, + "higher": 36.0 + }, + { + "interest": 2400, + "basic": 28.0, + "higher": 38.0 + }, + { + "interest": 2500, "basic": 30.0, "higher": 40.0 }, { - "interest": "£3,000", + "interest": 2600, + "basic": 32.0, + "higher": 42.0 + }, + { + "interest": 2700, + "basic": 34.0, + "higher": 44.0 + }, + { + "interest": 2800, + "basic": 36.0, + "higher": 46.0 + }, + { + "interest": 2900, + "basic": 38.0, + "higher": 48.0 + }, + { + "interest": 3000, "basic": 40.0, "higher": 50.0 }, { - "interest": "£3,500", + "interest": 3100, + "basic": 42.0, + "higher": 52.0 + }, + { + "interest": 3200, + "basic": 44.0, + "higher": 54.0 + }, + { + "interest": 3300, + "basic": 46.0, + "higher": 56.0 + }, + { + "interest": 3400, + "basic": 48.0, + "higher": 58.0 + }, + { + "interest": 3500, "basic": 50.0, "higher": 60.0 }, { - "interest": "£4,000", + "interest": 3600, + "basic": 52.0, + "higher": 62.0 + }, + { + "interest": 3700, + "basic": 54.0, + "higher": 64.0 + }, + { + "interest": 3800, + "basic": 56.0, + "higher": 66.0 + }, + { + "interest": 3900, + "basic": 58.0, + "higher": 68.0 + }, + { + "interest": 4000, "basic": 60.0, "higher": 70.0 }, { - "interest": "£4,500", + "interest": 4100, + "basic": 62.0, + "higher": 72.0 + }, + { + "interest": 4200, + "basic": 64.0, + "higher": 74.0 + }, + { + "interest": 4300, + "basic": 66.0, + "higher": 76.0 + }, + { + "interest": 4400, + "basic": 68.0, + "higher": 78.0 + }, + { + "interest": 4500, "basic": 70.0, "higher": 80.0 }, { - "interest": "£5,000", + "interest": 4600, + "basic": 72.0, + "higher": 82.0 + }, + { + "interest": 4700, + "basic": 74.0, + "higher": 84.0 + }, + { + "interest": 4800, + "basic": 76.0, + "higher": 86.0 + }, + { + "interest": 4900, + "basic": 78.0, + "higher": 88.0 + }, + { + "interest": 5000, "basic": 80.0, "higher": 90.0 } diff --git a/analysis/uk-budget-2026-income-tax/savings-interest-curve.csv b/analysis/uk-budget-2026-income-tax/savings-interest-curve.csv index beb9d0a60..ff48dc299 100644 --- a/analysis/uk-budget-2026-income-tax/savings-interest-curve.csv +++ b/analysis/uk-budget-2026-income-tax/savings-interest-curve.csv @@ -1,11 +1,47 @@ interest,basic_baseline_tax,basic_reform_tax,basic_tax_increase,higher_baseline_tax,higher_reform_tax,higher_tax_increase 500,0.0,0.0,0.0,0.0,0.0,0.0 +600,0.0,0.0,0.0,42.0,44.0,2.0 +700,0.0,0.0,0.0,84.0,88.0,4.0 +800,0.0,0.0,0.0,126.0,132.0,6.0 +900,0.0,0.0,0.0,168.0,176.0,8.0 1000,0.0,0.0,0.0,210.0,220.0,10.0 +1100,22.0,24.0,2.0,252.0,264.0,12.0 +1200,44.0,48.0,4.0,294.0,308.0,14.0 +1300,66.0,72.0,6.0,336.0,352.0,16.0 +1400,88.0,96.0,8.0,378.0,396.0,18.0 1500,110.0,120.0,10.0,420.0,440.0,20.0 +1600,132.0,144.0,12.0,462.0,484.0,22.0 +1700,154.0,168.0,14.0,504.0,528.0,24.0 +1800,176.0,192.0,16.0,546.0,572.0,26.0 +1900,198.0,216.0,18.0,588.0,616.0,28.0 2000,220.0,240.0,20.0,630.0,660.0,30.0 +2100,242.0,264.0,22.0,672.0,704.0,32.0 +2200,264.0,288.0,24.0,714.0,748.0,34.0 +2300,286.0,312.0,26.0,756.0,792.0,36.0 +2400,308.0,336.0,28.0,798.0,836.0,38.0 2500,330.0,360.0,30.0,840.0,880.0,40.0 +2600,352.0,384.0,32.0,882.0,924.0,42.0 +2700,374.0,408.0,34.0,924.0,968.0,44.0 +2800,396.0,432.0,36.0,966.0,1012.0,46.0 +2900,418.0,456.0,38.0,1008.0,1056.0,48.0 3000,440.0,480.0,40.0,1050.0,1100.0,50.0 +3100,462.0,504.0,42.0,1092.0,1144.0,52.0 +3200,484.0,528.0,44.0,1134.0,1188.0,54.0 +3300,506.0,552.0,46.0,1176.0,1232.0,56.0 +3400,528.0,576.0,48.0,1218.0,1276.0,58.0 3500,550.0,600.0,50.0,1260.0,1320.0,60.0 +3600,572.0,624.0,52.0,1302.0,1364.0,62.0 +3700,594.0,648.0,54.0,1344.0,1408.0,64.0 +3800,616.0,672.0,56.0,1386.0,1452.0,66.0 +3900,638.0,696.0,58.0,1428.0,1496.0,68.0 4000,660.0,720.0,60.0,1470.0,1540.0,70.0 +4100,682.0,744.0,62.0,1512.0,1584.0,72.0 +4200,704.0,768.0,64.0,1554.0,1628.0,74.0 +4300,726.0,792.0,66.0,1596.0,1672.0,76.0 +4400,748.0,816.0,68.0,1638.0,1716.0,78.0 4500,770.0,840.0,70.0,1680.0,1760.0,80.0 +4600,792.0,864.0,72.0,1722.0,1804.0,82.0 +4700,814.0,888.0,74.0,1764.0,1848.0,84.0 +4800,836.0,912.0,76.0,1806.0,1892.0,86.0 +4900,858.0,936.0,78.0,1848.0,1936.0,88.0 5000,880.0,960.0,80.0,1890.0,1980.0,90.0 diff --git a/analysis/uk-budget-2026-income-tax/trading-allowance-chart.json b/analysis/uk-budget-2026-income-tax/trading-allowance-chart.json index 3e4ec0a6d..b98422ec4 100644 --- a/analysis/uk-budget-2026-income-tax/trading-allowance-chart.json +++ b/analysis/uk-budget-2026-income-tax/trading-allowance-chart.json @@ -1,12 +1,19 @@ { - "type": "bar", + "type": "line", "title": "Trading allowance: the income tax reduction depends on expenses", "subtitle": "Annual income tax reduction; England, £30,000 salary, 2027–28", "xKey": "receipts", - "yLabel": "Annual income tax reduction (£)", + "xLabel": "Annual side-business receipts", + "yLabel": "Annual income tax reduction", "format": { "prefix": "£", - "decimals": 0 + "decimals": 0, + "separator": true + }, + "xFormat": { + "prefix": "£", + "decimals": 0, + "separator": true }, "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", "series": [ @@ -21,54 +28,253 @@ "color": "secondary" } ], + "markers": [ + { + "x": 1000, + "label": "Current allowance" + }, + { + "x": 3000, + "label": "New allowance" + }, + { + "x": 4000, + "label": "75% expenses equal £3,000" + } + ], "data": [ { - "receipts": "£500", + "receipts": 500, "noExpenses": 0.0, "highExpenses": 0.0 }, { - "receipts": "£1,000", + "receipts": 600, "noExpenses": 0.0, "highExpenses": 0.0 }, { - "receipts": "£1,500", + "receipts": 700, + "noExpenses": 0.0, + "highExpenses": 0.0 + }, + { + "receipts": 800, + "noExpenses": 0.0, + "highExpenses": 0.0 + }, + { + "receipts": 900, + "noExpenses": 0.0, + "highExpenses": 0.0 + }, + { + "receipts": 1000, + "noExpenses": 0.0, + "highExpenses": 0.0 + }, + { + "receipts": 1100, + "noExpenses": 20.0, + "highExpenses": 20.0 + }, + { + "receipts": 1200, + "noExpenses": 40.0, + "highExpenses": 40.0 + }, + { + "receipts": 1300, + "noExpenses": 60.0, + "highExpenses": 60.0 + }, + { + "receipts": 1333.3333333333333, + "noExpenses": 66.67, + "highExpenses": 66.67 + }, + { + "receipts": 1400, + "noExpenses": 80.0, + "highExpenses": 70.0 + }, + { + "receipts": 1500, "noExpenses": 100.0, "highExpenses": 75.0 }, { - "receipts": "£2,000", + "receipts": 1600, + "noExpenses": 120.0, + "highExpenses": 80.0 + }, + { + "receipts": 1700, + "noExpenses": 140.0, + "highExpenses": 85.0 + }, + { + "receipts": 1800, + "noExpenses": 160.0, + "highExpenses": 90.0 + }, + { + "receipts": 1900, + "noExpenses": 180.0, + "highExpenses": 95.0 + }, + { + "receipts": 2000, "noExpenses": 200.0, "highExpenses": 100.0 }, { - "receipts": "£2,500", + "receipts": 2100, + "noExpenses": 220.0, + "highExpenses": 105.0 + }, + { + "receipts": 2200, + "noExpenses": 240.0, + "highExpenses": 110.0 + }, + { + "receipts": 2300, + "noExpenses": 260.0, + "highExpenses": 115.0 + }, + { + "receipts": 2400, + "noExpenses": 280.0, + "highExpenses": 120.0 + }, + { + "receipts": 2500, "noExpenses": 300.0, "highExpenses": 125.0 }, { - "receipts": "£3,000", + "receipts": 2600, + "noExpenses": 320.0, + "highExpenses": 130.0 + }, + { + "receipts": 2700, + "noExpenses": 340.0, + "highExpenses": 135.0 + }, + { + "receipts": 2800, + "noExpenses": 360.0, + "highExpenses": 140.0 + }, + { + "receipts": 2900, + "noExpenses": 380.0, + "highExpenses": 145.0 + }, + { + "receipts": 3000, "noExpenses": 400.0, "highExpenses": 150.0 }, { - "receipts": "£3,500", + "receipts": 3100, + "noExpenses": 400.0, + "highExpenses": 135.0 + }, + { + "receipts": 3200, + "noExpenses": 400.0, + "highExpenses": 120.0 + }, + { + "receipts": 3300, + "noExpenses": 400.0, + "highExpenses": 105.0 + }, + { + "receipts": 3400, + "noExpenses": 400.0, + "highExpenses": 90.0 + }, + { + "receipts": 3500, "noExpenses": 400.0, "highExpenses": 75.0 }, { - "receipts": "£4,000", + "receipts": 3600, + "noExpenses": 400.0, + "highExpenses": 60.0 + }, + { + "receipts": 3700, + "noExpenses": 400.0, + "highExpenses": 45.0 + }, + { + "receipts": 3800, + "noExpenses": 400.0, + "highExpenses": 30.0 + }, + { + "receipts": 3900, + "noExpenses": 400.0, + "highExpenses": 15.0 + }, + { + "receipts": 4000, + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": 4100, + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": 4200, + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": 4300, + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": 4400, + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": 4500, + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": 4600, + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": 4700, + "noExpenses": 400.0, + "highExpenses": 0.0 + }, + { + "receipts": 4800, "noExpenses": 400.0, "highExpenses": 0.0 }, { - "receipts": "£4,500", + "receipts": 4900, "noExpenses": 400.0, "highExpenses": 0.0 }, { - "receipts": "£5,000", + "receipts": 5000, "noExpenses": 400.0, "highExpenses": 0.0 } diff --git a/analysis/uk-budget-2026-income-tax/trading-receipts-curve.csv b/analysis/uk-budget-2026-income-tax/trading-receipts-curve.csv index 32b0d7dee..be6044f8c 100644 --- a/analysis/uk-budget-2026-income-tax/trading-receipts-curve.csv +++ b/analysis/uk-budget-2026-income-tax/trading-receipts-curve.csv @@ -1,11 +1,48 @@ receipts,no_expenses_actual_expenses,no_expenses_baseline_taxable_profit,no_expenses_reform_taxable_profit,no_expenses_tax_reduction,expenses_75_percent_actual_expenses,expenses_75_percent_baseline_taxable_profit,expenses_75_percent_reform_taxable_profit,expenses_75_percent_tax_reduction 500,0,0,0,0.0,375.0,0,0,0.0 +600,0,0,0,0.0,450.0,0,0,0.0 +700,0,0,0,0.0,525.0,0,0,0.0 +800,0,0,0,0.0,600.0,0,0,0.0 +900,0,0,0,0.0,675.0,0,0,0.0 1000,0,0,0,0.0,750.0,0,0,0.0 +1100,0,100,0,20.0,825.0,100,0,20.0 +1200,0,200,0,40.0,900.0,200,0,40.0 +1300,0,300,0,60.0,975.0,300,0,60.0 +1333.3333333333333,0.0,333.33333333333326,0,66.67,1000.0,333.33333333333326,0,66.67 +1400,0,400,0,80.0,1050.0,350.0,0,70.0 1500,0,500,0,100.0,1125.0,375.0,0,75.0 +1600,0,600,0,120.0,1200.0,400.0,0,80.0 +1700,0,700,0,140.0,1275.0,425.0,0,85.0 +1800,0,800,0,160.0,1350.0,450.0,0,90.0 +1900,0,900,0,180.0,1425.0,475.0,0,95.0 2000,0,1000,0,200.0,1500.0,500.0,0,100.0 +2100,0,1100,0,220.0,1575.0,525.0,0,105.0 +2200,0,1200,0,240.0,1650.0,550.0,0,110.0 +2300,0,1300,0,260.0,1725.0,575.0,0,115.0 +2400,0,1400,0,280.0,1800.0,600.0,0,120.0 2500,0,1500,0,300.0,1875.0,625.0,0,125.0 +2600,0,1600,0,320.0,1950.0,650.0,0,130.0 +2700,0,1700,0,340.0,2025.0,675.0,0,135.0 +2800,0,1800,0,360.0,2100.0,700.0,0,140.0 +2900,0,1900,0,380.0,2175.0,725.0,0,145.0 3000,0,2000,0,400.0,2250.0,750.0,0,150.0 +3100,0,2100,100,400.0,2325.0,775.0,100,135.0 +3200,0,2200,200,400.0,2400.0,800.0,200,120.0 +3300,0,2300,300,400.0,2475.0,825.0,300,105.0 +3400,0,2400,400,400.0,2550.0,850.0,400,90.0 3500,0,2500,500,400.0,2625.0,875.0,500,75.0 +3600,0,2600,600,400.0,2700.0,900.0,600,60.0 +3700,0,2700,700,400.0,2775.0,925.0,700,45.0 +3800,0,2800,800,400.0,2850.0,950.0,800,30.0 +3900,0,2900,900,400.0,2925.0,975.0,900,15.0 4000,0,3000,1000,400.0,3000.0,1000.0,1000.0,0.0 +4100,0,3100,1100,400.0,3075.0,1025.0,1025.0,0.0 +4200,0,3200,1200,400.0,3150.0,1050.0,1050.0,0.0 +4300,0,3300,1300,400.0,3225.0,1075.0,1075.0,0.0 +4400,0,3400,1400,400.0,3300.0,1100.0,1100.0,0.0 4500,0,3500,1500,400.0,3375.0,1125.0,1125.0,0.0 +4600,0,3600,1600,400.0,3450.0,1150.0,1150.0,0.0 +4700,0,3700,1700,400.0,3525.0,1175.0,1175.0,0.0 +4800,0,3800,1800,400.0,3600.0,1200.0,1200.0,0.0 +4900,0,3900,1900,400.0,3675.0,1225.0,1225.0,0.0 5000,0,4000,2000,400.0,3750.0,1250.0,1250.0,0.0 diff --git a/analysis/uk-budget-2026-income-tax/trading_extensions.json b/analysis/uk-budget-2026-income-tax/trading_extensions.json index 7a8ae6f2f..370dd58d9 100644 --- a/analysis/uk-budget-2026-income-tax/trading_extensions.json +++ b/analysis/uk-budget-2026-income-tax/trading_extensions.json @@ -1,6 +1,6 @@ { "metadata": { - "generated_at_utc": "2026-10-28T15:19:07.459647+00:00", + "generated_at_utc": "2026-10-28T16:15:44.057920+00:00", "model_year": 2027, "tax_year": "2027–28", "versions": { @@ -23,6 +23,16 @@ "scope": "Five synthetic case pairs; no population data, behavioural responses or national estimates. Annual model calculations; actual UC assessment periods and timing of tax payments can differ.", "assumptions": "Lone parent age35 with child age4, employment as main job, £18,000 annual wages, side business with zero expenses, London/Central London private rent £12,000/year, UC and Child Benefit take-up true. Sole trader age35, full-time35hours/week, £20,000 receipts and £500 costs, no other income, owns home outright, no UC claim. Both: council tax input zero; no childcare costs, capital, disability, pensions, losses or other income. Omitted inputs otherwise retain pinned model defaults. No UC award, floor amount, work allowance, or earnings intermediate is forced.", "oracle_tolerance_gbp": 0.02, + "forecast": { + "dashboard_commit": "640426575270224db9b04d6c94d30e264a347be2", + "source": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/640426575270224db9b04d6c94d30e264a347be2/src/uk_budget_data/forecast/obr_october_2026.json", + "forecast_file_git_blob": "b504a48fffb93714ff358d869cad712b6daea20e", + "forecast_module_git_blob": "b2ca186b6fd514f334ced11934d38b256e6d2127", + "forecast_file_sha256": "dc039d30660d17f30a45e49538dbd22953e02bd4f6b63eda2eaebcf8252baf54", + "baseline_and_reform": true, + "nominal_household_inputs": "Held fixed in 2027; the forecast updates model parameters, not the supplied income amounts.", + "remaining_series": "March paths remain for cpih, non-labour income, private rent, mortgage interest, per-capita series, council tax and fuel volumes/prices, as recorded by this forecast vintage." + }, "independent_arithmetic": "Basic-rate income tax20% above Personal Allowance£12,570; known-receipt taxable profit=max(0,receipts-max(expenses,allowance)); Class4 NI6% above£12,570; active UC award falls55% of extra UC net earnings above its unchanged work allowance. Missing-receipt outputs separately test the pinned fallback, not the legal receipt-based calculation." }, "cases": [ @@ -135,12 +145,12 @@ "child_benefit": 1455.8287353515625 }, "household": { - "household_net_income": 36801.48828125, + "household_net_income": 36821.58984375, "hbai_household_net_income": 34411.92578125, - "household_benefits": 17101.892578125, + "household_benefits": 17121.994140625, "household_tax": 2300.403076171875, "household_market_income": 22000.0, - "household_gross_income": 39101.890625, + "household_gross_income": 39121.9921875, "rent": 12000.0, "council_tax": 0.0 } @@ -200,12 +210,12 @@ "child_benefit": 1455.8287353515625 }, "household": { - "household_net_income": 36981.48828125, + "household_net_income": 37001.58984375, "hbai_household_net_income": 34591.92578125, - "household_benefits": 16881.892578125, + "household_benefits": 16901.994140625, "household_tax": 1900.403076171875, "household_market_income": 22000.0, - "household_gross_income": 38881.890625, + "household_gross_income": 38901.9921875, "rent": 12000.0, "council_tax": 0.0 } @@ -345,12 +355,12 @@ "child_benefit": 1455.8287353515625 }, "household": { - "household_net_income": 35901.48828125, + "household_net_income": 35921.58984375, "hbai_household_net_income": 33511.92578125, - "household_benefits": 18201.892578125, + "household_benefits": 18221.994140625, "household_tax": 1800.403076171875, "household_market_income": 19500.0, - "household_gross_income": 37701.890625, + "household_gross_income": 37721.9921875, "rent": 12000.0, "council_tax": 0.0 } @@ -410,12 +420,12 @@ "child_benefit": 1455.8287353515625 }, "household": { - "household_net_income": 35946.48828125, + "household_net_income": 35966.58984375, "hbai_household_net_income": 33556.92578125, - "household_benefits": 18146.892578125, + "household_benefits": 18166.994140625, "household_tax": 1700.403076171875, "household_market_income": 19500.0, - "household_gross_income": 37646.890625, + "household_gross_income": 37666.9921875, "rent": 12000.0, "council_tax": 0.0 } @@ -550,12 +560,12 @@ "child_benefit": 1455.8287353515625 }, "household": { - "household_net_income": 35811.48828125, + "household_net_income": 35831.58984375, "hbai_household_net_income": 33421.92578125, - "household_benefits": 18311.892578125, + "household_benefits": 18331.994140625, "household_tax": 2000.403076171875, "household_market_income": 19500.0, - "household_gross_income": 37811.890625, + "household_gross_income": 37831.9921875, "rent": 12000.0, "council_tax": 0.0 } @@ -615,12 +625,12 @@ "child_benefit": 1455.8287353515625 }, "household": { - "household_net_income": 35946.48828125, + "household_net_income": 35966.58984375, "hbai_household_net_income": 33556.92578125, - "household_benefits": 18146.892578125, + "household_benefits": 18166.994140625, "household_tax": 1700.403076171875, "household_market_income": 19500.0, - "household_gross_income": 37646.890625, + "household_gross_income": 37666.9921875, "rent": 12000.0, "council_tax": 0.0 } diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md index b13af94b7..572d1e792 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md @@ -1,10 +1,13 @@ -> Draft review note: the national figures below use the earlier recorded forecast snapshot and await replacement by the regenerated savings and property results. The household calculations remain as stated. +> Draft review note: the national figures below are an earlier dashboard snapshot retained for review. The combined snapshot has been withdrawn, and replacement savings and property results have not passed reconciliation. They are not final national results. The Autumn Budget 2026 increases the basic, higher and additional income tax rates on savings and property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%**. Savings rates apply across the UK. The property rates apply in England, Wales and Northern Ireland. Dividend rates remain unchanged. These are the changes announced in the [Budget 2026, paragraphs 6.246 and 6.247](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142 "Budget 2026 #page 142,45"). -PolicyEngine estimates that the measure raises **£664 million in 2027–28**, compared with the Treasury's **£160 million** for that year. These are preliminary static estimates; the Treasury costing includes behavioural responses. +Key figures for 2027–28: -A basic-rate saver with £2,000 of annual interest pays £20 more a year. A landlord in England with £10,000 of property profit and £4,000 of mortgage interest pays £120 more; a Scottish landlord with the same fully usable finance costs pays £80 less. +- A basic-rate saver with £2,000 of annual interest pays £20 more a year. +- A landlord in England with £10,000 of property profit and £4,000 of mortgage interest pays £120 more. +- A Scottish landlord with the same fully usable finance costs pays £80 less, because the finance-cost reduction rises while Scottish property tax rates stay unchanged. +- The Treasury forecasts £160 million of additional revenue. The earlier recorded static estimate is £664 million; replacement dashboard figures are still being checked. The national results below retain that earlier snapshot for draft review, while the Treasury costing includes behavioural responses. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. @@ -20,7 +23,11 @@ The [Budget 2025 technical note](https://www.gov.uk/government/publications/chan The same note sets the ordering from April 2027: employment, pension and trading income first; property next; savings after that; and dividends last. Allowances first reduce income other than property, savings or dividends. Taxable income then fills the bands in that order, so employment and rental income can push savings interest into a higher band. -## Savers pay the higher rates on interest above their allowances +## Household impacts + +The examples below isolate the announced savings and property measures in 2027–28. They show income tax, holding the stated income and expenses fixed. + +### Savers pay the higher rates on interest above their allowances The Personal Savings Allowance remains £1,000 for basic-rate taxpayers, £500 for higher-rate taxpayers and £0 for additional-rate taxpayers. People with low other income can also qualify for a starting rate of 0% on up to £5,000 of savings interest. These allowances depend on total income, as [HMRC's savings guidance](https://www.gov.uk/apply-tax-free-interest-on-savings/how-much-is-tax-free) explains. Interest earned inside an ISA remains exempt from income tax. @@ -34,19 +41,25 @@ These hypothetical adults live in England and receive only the wages and interes For the basic-rate example, £2,000 − £1,000 = £1,000 faces the savings basic rate: £1,000 × 22% = £220 before, against £1,000 × 24% = £240 after. The higher-rate example pays an extra £1,500 × 2% = £30. - The chart varies annual interest for the same two salaries. At these income levels, each additional £500 of interest above the allowance adds £10 to the tax increase. ```chart { - "type": "bar", + "type": "line", "title": "Savings tax increases apply above the Personal Savings Allowance", "subtitle": "Annual income tax increase; England, salaries £30,000 and £60,000, 2027–28", "xKey": "interest", - "yLabel": "Extra annual income tax (£)", + "xLabel": "Annual savings interest", + "yLabel": "Extra annual income tax", "format": { "prefix": "£", - "decimals": 0 + "decimals": 0, + "separator": true + }, + "xFormat": { + "prefix": "£", + "decimals": 0, + "separator": true }, "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", "series": [ @@ -61,54 +74,244 @@ The chart varies annual interest for the same two salaries. At these income leve "color": "secondary" } ], + "markers": [ + { + "x": 500, + "label": "£60,000 salary: savings allowance" + }, + { + "x": 1000, + "label": "£30,000 salary: savings allowance" + } + ], "data": [ { - "interest": "£500", + "interest": 500, "basic": 0.0, "higher": 0.0 }, { - "interest": "£1,000", + "interest": 600, + "basic": 0.0, + "higher": 2.0 + }, + { + "interest": 700, + "basic": 0.0, + "higher": 4.0 + }, + { + "interest": 800, + "basic": 0.0, + "higher": 6.0 + }, + { + "interest": 900, + "basic": 0.0, + "higher": 8.0 + }, + { + "interest": 1000, "basic": 0.0, "higher": 10.0 }, { - "interest": "£1,500", + "interest": 1100, + "basic": 2.0, + "higher": 12.0 + }, + { + "interest": 1200, + "basic": 4.0, + "higher": 14.0 + }, + { + "interest": 1300, + "basic": 6.0, + "higher": 16.0 + }, + { + "interest": 1400, + "basic": 8.0, + "higher": 18.0 + }, + { + "interest": 1500, "basic": 10.0, "higher": 20.0 }, { - "interest": "£2,000", + "interest": 1600, + "basic": 12.0, + "higher": 22.0 + }, + { + "interest": 1700, + "basic": 14.0, + "higher": 24.0 + }, + { + "interest": 1800, + "basic": 16.0, + "higher": 26.0 + }, + { + "interest": 1900, + "basic": 18.0, + "higher": 28.0 + }, + { + "interest": 2000, "basic": 20.0, "higher": 30.0 }, { - "interest": "£2,500", + "interest": 2100, + "basic": 22.0, + "higher": 32.0 + }, + { + "interest": 2200, + "basic": 24.0, + "higher": 34.0 + }, + { + "interest": 2300, + "basic": 26.0, + "higher": 36.0 + }, + { + "interest": 2400, + "basic": 28.0, + "higher": 38.0 + }, + { + "interest": 2500, "basic": 30.0, "higher": 40.0 }, { - "interest": "£3,000", + "interest": 2600, + "basic": 32.0, + "higher": 42.0 + }, + { + "interest": 2700, + "basic": 34.0, + "higher": 44.0 + }, + { + "interest": 2800, + "basic": 36.0, + "higher": 46.0 + }, + { + "interest": 2900, + "basic": 38.0, + "higher": 48.0 + }, + { + "interest": 3000, "basic": 40.0, "higher": 50.0 }, { - "interest": "£3,500", + "interest": 3100, + "basic": 42.0, + "higher": 52.0 + }, + { + "interest": 3200, + "basic": 44.0, + "higher": 54.0 + }, + { + "interest": 3300, + "basic": 46.0, + "higher": 56.0 + }, + { + "interest": 3400, + "basic": 48.0, + "higher": 58.0 + }, + { + "interest": 3500, "basic": 50.0, "higher": 60.0 }, { - "interest": "£4,000", + "interest": 3600, + "basic": 52.0, + "higher": 62.0 + }, + { + "interest": 3700, + "basic": 54.0, + "higher": 64.0 + }, + { + "interest": 3800, + "basic": 56.0, + "higher": 66.0 + }, + { + "interest": 3900, + "basic": 58.0, + "higher": 68.0 + }, + { + "interest": 4000, "basic": 60.0, "higher": 70.0 }, { - "interest": "£4,500", + "interest": 4100, + "basic": 62.0, + "higher": 72.0 + }, + { + "interest": 4200, + "basic": 64.0, + "higher": 74.0 + }, + { + "interest": 4300, + "basic": 66.0, + "higher": 76.0 + }, + { + "interest": 4400, + "basic": 68.0, + "higher": 78.0 + }, + { + "interest": 4500, "basic": 70.0, "higher": 80.0 }, { - "interest": "£5,000", + "interest": 4600, + "basic": 72.0, + "higher": 82.0 + }, + { + "interest": 4700, + "basic": 74.0, + "higher": 84.0 + }, + { + "interest": 4800, + "basic": 76.0, + "higher": 86.0 + }, + { + "interest": 4900, + "basic": 78.0, + "higher": 88.0 + }, + { + "interest": 5000, "basic": 80.0, "higher": 90.0 } @@ -116,7 +319,7 @@ The chart varies annual interest for the same two salaries. At these income leve } ``` -## Landlords' mortgage-interest relief rises too +### Landlords' mortgage-interest relief rises too For individual residential landlords, mortgage interest normally produces a tax reduction rather than a deduction from rental profits. The reduction is limited by finance costs, property profits, adjusted total income and the tax liability. [HMRC's explanation of residential finance-cost relief](https://www.gov.uk/guidance/changes-to-tax-relief-for-residential-landlords-how-its-worked-out-including-case-studies) describes these limits. @@ -137,7 +340,7 @@ Both pay £200 more before relief, while their finance-cost reduction rises by The property **rate** increase excludes Scottish taxpayers, whose rental income follows Scottish rules. Finance-cost relief is a separate calculation. The [Finance Act 2026 amendment](https://www.legislation.gov.uk/ukpga/2026/11/schedule/1/paragraph/40/enacted) ties it to the UK property basic rate without a Scottish exception. Applying that rule, a Scottish landlord able to use the full reduction on £4,000 of eligible finance costs receives £80 more relief, reducing their income tax by £80 if nothing else changes. A mortgage-free Scottish landlord has no change from this measure. The savings increase still applies across the UK. -## When property income pushes savings into a higher band +### When property income pushes savings into a higher band Consider an adult in England with £45,000 of salary, £6,000 of property profit after allowable expenses, £2,000 of interest and no mortgage interest. The £12,570 Personal Allowance leaves £32,430 of taxable salary. That uses £32,430 of the £37,700 basic-rate band, leaving £5,270. @@ -155,9 +358,13 @@ The extra tax is £120 on property plus £30 on savings, or **£150 a year**. Th [Try the Budget dashboard's calculator](https://policyengine.org/uk/budgets/autumn-2026). Its salary input is for 2026–27 and is grown into the target year, while this table fixes salary at £45,000 in 2027–28. On its current earnings path, a £45,000 salary input becomes about £46,080, giving total tax of £9,014 before and £9,164 after. The additional tax remains £150. These values can be entered manually; the existing preset may use different incomes. -## Preliminary national estimates +## Population impacts -The dashboard's [revenue estimate](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/budgetary_impact.csv) estimates that the measure raises **£664 million in 2027–28**, increasing to **£793 million in 2031–32**. These are static annual government-balance effects: savings, rental income and other household circumstances are held fixed. The estimates remain preliminary while the Treasury comparison is reconciled. +### Recorded national estimates + +The earlier dashboard snapshot's [revenue estimate](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/budgetary_impact.csv) estimates that the measure raises **£664 million in 2027–28**, increasing to **£793 million in 2031–32**. These are static annual government-balance effects: savings, rental income and other household circumstances are held fixed. The combined snapshot has been withdrawn following the separation of savings and property into two dashboard measures. These figures remain here for draft review while the replacement results are checked. + +### Household income by decile The [average cash changes](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/winners_losers.csv) show an annual household income reduction of **£23 across all households** in 2027–28, including unaffected households. Households in the top decile lose £107 on average. Each decile contains roughly equal numbers of people, ranked by household income adjusted for household size. The cash figures are household-weighted averages within those groups. @@ -175,11 +382,13 @@ The [average cash changes](https://ab2026-local-preview.vercel.app/uk/autumn-bud | 10 (highest income) | −£107 | | All households | −£23 | +### People affected + The model's [population results](https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/metrics.csv) indicate that **10.67% of people live in households whose net income changes by more than 0.01%** in 2027–28. An average loss within a decile does not mean every household in it loses. The lowest decile's £13 average loss also exceeds the £6 to £11 averages in deciles 2 to 7; an income-source breakdown is needed to establish what drives that pattern. The government estimates that **84% of income tax payers are unaffected** in 2027–28 and that around half the revenue comes from the top 10% of households. Budget paragraph 2.50 and footnote 74 base these estimates on projected HMRC Survey of Personal Incomes data and Treasury household mapping. The model's affected-person share uses a different population and threshold from the taxpayer estimate, so the two reach figures are not directly comparable. The decile means also do not establish a share of government revenue: that comparison requires weighted tax totals by decile. -## The Treasury's costing: £160 million in 2027–28 +### Treasury comparison The Treasury costs savings and property separately. Their combined forecast is £160 million in 2027–28 and £1,045 million in 2031–32. @@ -192,12 +401,21 @@ The Treasury costs savings and property separately. Their combined forecast is The Treasury costings allow for some landlords incorporating and savers moving funds into tax-advantaged products such as ISAs. The static model holds those choices fixed. The published costing notes do not explain the annual profile, including the £15 million savings figure in 2026–27 before the rates take effect. No particular collection-timing explanation is assumed here. A component comparison is needed to distinguish the property and savings contributions to the difference. +## Assumptions and limitations + +- The worked examples are hypothetical single adults aged 35. Their income is fixed at the stated 2027–28 amounts. The examples include no pension contributions, Gift Aid, student loans, property losses, carried-forward finance costs or other reliefs. Savings are outside ISAs. +- The household tables show tax attributable to each income source. They do not estimate household income after means-tested benefits. The mortgage examples assume the full finance-cost reduction can be used. +- The Scottish mortgage example applies the existing Finance Act rule linking relief to the UK property basic rate. The Finance Bill will set the final implementation of the new rates. +- The dashboard calculator grows a 2026–27 salary input into the selected year. Its current earnings path differs from fixing the same nominal salary in 2027–28, as the mixed-income example explains. +- National estimates are static, with no behavioural response. The Treasury forecasts use different data and include behaviour. Their fiscal-year profile cannot be attributed to a particular timing effect without reconciliation. +- The national figures await replacement by checked savings and property results. The income-source explanation for the lowest-decile result, component reconciliation, absolute affected-person counts and separate shares gaining and losing remain outstanding. Average decile changes do not establish shares of government revenue. + ## Methodology -The examples isolate the newly announced 2027–28 changes, including finance-cost relief, holding income and expenses constant. They include no pension contributions, Gift Aid, student loans or other reliefs. They show tax attributable to each income source, rather than household net income after benefits. +The household calculations use the `policyengine` Python package (version 6.11.1), PolicyEngine UK (version 2.151.0) and PolicyEngine core (version 3.33.3). Each comparison applies only the announced savings and property changes, including finance-cost relief, against the already scheduled 2027–28 rules. Both household scenarios use the OBR’s October 2026 forecast update at dashboard commit `64042657`, matching the Pension Tax Allowance analysis. Supplied 2027–28 income stays fixed; the forecast updates the model’s projected parameters. Tax calculations are checked against independent arithmetic. The line chart plots the exact schedule breakpoints and points every £100, and its interpolation agrees with PolicyEngine UK to within one penny at every £2 of interest. -The examples use `policyengine.py` 6.11.1 with PolicyEngine UK 2.151.0 and core 3.33.3. Income is fixed at the stated 2027–28 amounts, and tax changes are checked against independent arithmetic. +The recorded national results reuse the dashboard's certified Microcosm UK 2024–25 dataset, `microcosm-uk-2024-25-national-20261025T091414Z-a6299504`. They apply the initial October 2026 OBR forecast overlay to both baseline and reform. Series not updated by that overlay retain the March forecast path, and the dataset retains its pre-Budget calibration. These aggregate outputs were generated by the dashboard; this article does not claim a new local population run. -The national estimates use the certified Microcosm UK 2024–25 national data and the initial October 2026 OBR forecast overlay on both baseline and reform. Growth series not updated by that overlay retain the model's March forecast path; the dataset retains its pre-Budget calibration. The [analysis files](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460/files) record exact dataset identifiers, checksums, parameter changes and calculation records. +The deciles contain roughly equal numbers of people ranked by equivalised household income. Cash changes are household-weighted means, including unaffected households. Published decile cells meet a floor of at least three distinct survey households. The affected-person calculation uses an absolute net-income percentage change above 0.01%, floors baseline household income at £1 and includes households with a valid decile. -Published decile cells meet a disclosure floor of at least three survey households. The affected-person calculation uses the absolute percentage income change, floors baseline household income at £1 and includes households with a valid decile. It does not supply separate shares gaining and losing or absolute affected-person counts. The income-source explanation for the lowest-decile result and the component reconciliation remain outstanding. +The [analysis files](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460/files) record the calculation inputs, model versions, forecast settings, dataset checksum and source snapshots. Monetary amounts in tables are rounded to whole pounds; the calculation records retain precision. From fc4178564444e4c2df4c427212e3b16aab85ba1b Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 13:28:52 -0400 Subject: [PATCH 11/24] Add illustrated savings and property cover --- analysis/uk-budget-2026-income-tax/README.md | 4 +++ .../cover-prompts.json | 29 ++++++++++++++++++ .../cover.webp | Bin 0 -> 59420 bytes app/src/data/posts/posts.json | 2 +- 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 analysis/uk-budget-2026-income-tax/cover-prompts.json create mode 100644 app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax/cover.webp diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index c6c198a98..e052808bf 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -76,3 +76,7 @@ Pavel’s comparison uses £100 chart sampling plus the true breakpoints and ver The household forecast pin and the archived national forecast are recorded separately. Applying the new household overlay does not regenerate or validate the historical national snapshot. That snapshot still awaits reconciled replacement outputs with execution-bound component results. The October-forecast rerun passed all23 household comparisons and all5 trading extension pairs. All policy deltas remain unchanged. Some absolute levels change: the three Scottish cases’ income-tax levels fall by £2.93 on both sides, and the parent’s total benefits/net income rise by about £20.10 on both sides. These do not change the article’s reported tax or household gains. The new93 displayed chart points passed18,008 model-liability comparisons and9,004 interpolation comparisons over2,251 income points per series. The largest interpolation difference is£0.0033, below the£0.01 tolerance. + +## Editorial cover images + +Both posts use original teal editorial illustrations generated with the built-in image tool. `cover-prompts.json` records the complete prompts, output paths, encoding settings, dimensions and checksums. The WebP files retain the generated1672×941pixel dimensions and are selected by each post's `image` metadata, supplying the article hero, research card and social preview. Original text-based SVG assets remain available in Git for reference. Article text, charts and calculations are unchanged by the cover update. diff --git a/analysis/uk-budget-2026-income-tax/cover-prompts.json b/analysis/uk-budget-2026-income-tax/cover-prompts.json new file mode 100644 index 000000000..40308f1c4 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/cover-prompts.json @@ -0,0 +1,29 @@ +{ + "tool": "built-in image_gen", + "intent": "Original editorial cover illustrations", + "reference_style": "PolicyEngine Autumn Budget 2026 energy and Pension Tax Allowance covers; deep teal, mint, white, restrained dimensional illustration.", + "assets": [ + { + "path": "app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax/cover.webp", + "prompt": "Use case: stylized-concept.\nAsset type: original editorial cover illustration for PolicyEngine's UK Autumn Budget 2026 article on savings and property income tax.\nCreate a polished wide 16:9 landscape illustration, intended final size 1600x900. Match a coherent nonprofit policy research illustration series: deep dark teal background, soft subtle teal vignette, pale mint and turquoise objects, clean vector-like shapes rendered as a raster image, restrained dimensional depth, gentle shadows, crisp edges, professional calm neutral tone.\nScene: a simplified British terraced house and a savings coin stack arranged together beside a large white income-tax statement with a teal header and a few muted grey abstract lines. One mint coin bears a clear British pound symbol (£). House, savings and statement should read as one coherent still life about taxing rental income and savings interest.\nComposition: main objects within the central 65 percent of the canvas, clear at thumbnail size, generous breathing room on every edge, balanced wide layout, a subtle floor line. Avoid tiny details.\nText: only a single £ symbol on the coin; no words, no tax rates, no numbers, no labels, no title, no logos, no watermark.\nConstraints: original illustration, no people, no flags, no political symbolism, no arrows or data charts, no claims about gains or losses. The image should look like a refined flat editorial illustration with subtle depth, not a photograph or a glossy toy render.", + "width": 1672, + "height": 941, + "format": "WebP", + "encoding_quality": 85, + "pixels_resized": false, + "bytes": 59420, + "sha256": "fcaa9776fa6ebfab449034a0423a166f413a9b4a4d5041747ed4610b20e111b6" + }, + { + "path": "app/public/assets/posts/uk-autumn-budget-2026-trading-allowance/cover.webp", + "prompt": "Use case: stylized-concept.\nAsset type: original editorial cover illustration for PolicyEngine's UK Autumn Budget 2026 article about the trading allowance for small businesses and side income.\nCreate a polished wide 16:9 landscape illustration, intended final size 1600x900. Match a coherent nonprofit policy research illustration series: deep dark teal background, soft subtle teal vignette, pale mint and turquoise objects, clean vector-like shapes rendered as a raster image, restrained dimensional depth, gentle shadows, crisp edges, professional calm neutral tone.\nScene: a small-business desktop still life with two simple unbranded parcels, a tidy calculator, a white business receipt or income ledger with a teal header and grey abstract rows, and a small stack of mint coins. One mint coin bears a clear British pound symbol (£). Convey modest self-employment or side-business receipts and expenses. It must not suggest stock-market trading or cryptocurrency.\nComposition: main objects within the central 65 percent of the canvas, readable at thumbnail size, generous breathing room on every edge, balanced wide layout, a subtle floor line. Avoid tiny details.\nText: only a single £ symbol on one coin; no words, no allowance amounts, no numbers on calculator keys, no labels, no title, no logos, no watermark.\nConstraints: original illustration, no people, no flags, no political symbolism, no charts, no arrows or promises of wealth. The image should look like a refined flat editorial illustration with subtle depth, not a photograph or a glossy toy render.", + "width": 1672, + "height": 941, + "format": "WebP", + "encoding_quality": 85, + "pixels_resized": false, + "bytes": 45038, + "sha256": "67f66a172051edf23372d3df5de577fd3724eed21dbb84036bf5cef106b3a9f0" + } + ] +} diff --git a/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax/cover.webp b/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax/cover.webp new file mode 100644 index 0000000000000000000000000000000000000000..e4c17ef588351315f81838d79a3cbb83b2e4786c GIT binary patch literal 59420 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 J=@if400489u7Cgl literal 0 HcmV?d00001 diff --git a/app/src/data/posts/posts.json b/app/src/data/posts/posts.json index 009359750..9f130abbe 100644 --- a/app/src/data/posts/posts.json +++ b/app/src/data/posts/posts.json @@ -13,7 +13,7 @@ "ziming-hua" ], "filename": "uk-autumn-budget-2026-savings-property-income-tax.md", - "image": "uk-autumn-budget-2026-savings-property-income-tax.svg" + "image": "uk-autumn-budget-2026-savings-property-income-tax/cover.webp" }, { "title": "Analysis of the Autumn Budget 2026 energy bill measures", From c65a52f8a879e5ad524cea9fea08c7cb8b90e85b Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 13:29:14 -0400 Subject: [PATCH 12/24] Clarify cover image provenance --- analysis/uk-budget-2026-income-tax/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index e052808bf..04c1f66b9 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -79,4 +79,4 @@ The October-forecast rerun passed all23 household comparisons and all5 trading e ## Editorial cover images -Both posts use original teal editorial illustrations generated with the built-in image tool. `cover-prompts.json` records the complete prompts, output paths, encoding settings, dimensions and checksums. The WebP files retain the generated1672×941pixel dimensions and are selected by each post's `image` metadata, supplying the article hero, research card and social preview. Original text-based SVG assets remain available in Git for reference. Article text, charts and calculations are unchanged by the cover update. +Both posts use original teal editorial illustrations generated with the built-in image tool. `cover-prompts.json` records the complete prompts, output paths, encoding settings, dimensions and checksums. The WebP files retain the generated 1672 × 941 pixel dimensions and are selected by each post's `image` metadata, supplying the article hero, research card and social preview. Original text-based SVG assets remain available in Git for reference. Article text, charts and calculations are unchanged by the cover update. From e7e2e32a483f373f79acd4e2d05dc7df03f2654e Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 13:57:19 -0400 Subject: [PATCH 13/24] Split property income tax explainer from savings draft --- analysis/uk-budget-2026-income-tax/README.md | 14 +- .../cover-prompts.json | 5 +- .../cover.webp | Bin ...udget-2026-savings-property-income-tax.svg | 56 --- ...-autumn-budget-2026-property-income-tax.md | 79 ++++ ...budget-2026-savings-property-income-tax.md | 392 ------------------ app/src/data/posts/posts.json | 19 +- 7 files changed, 95 insertions(+), 470 deletions(-) rename app/public/assets/posts/{uk-autumn-budget-2026-savings-property-income-tax => uk-autumn-budget-2026-property-income-tax}/cover.webp (100%) delete mode 100644 app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax.svg create mode 100644 app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md delete mode 100644 app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index 04c1f66b9..39bc64b84 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -1,6 +1,6 @@ # Autumn Budget 2026 income tax explainers -This directory supports two standalone posts: the combined savings/property rate increase and the trading allowance increase. The articles compare the newly announced measures with the already legislated 2027–28 baseline, one measure at a time. +This shared directory supports three standalone posts: the property income rate increase, the savings income rate increase and the trading allowance increase. Property and savings were split at the author’s request on 28 October 2026; savings remains a separate draft pending its dashboard data release. The articles compare the newly announced measures with the already legislated 2027–28 baseline, one measure at a time. ## Reproduce the household calculations @@ -20,13 +20,13 @@ The article chart blocks reproduce `savings-interest-chart.json` and `trading-al ## Current article scope -Both posts now publish household calculations and Treasury costings only. Model national estimates, decile tables and affected shares from earlier preview batches have been removed from the articles. The dashboard is the linked source for national results. The saved population files below are historical records and must not be treated as the current publication run. +All three posts publish household calculations and Treasury costings only. Model national estimates, decile tables and affected shares from earlier preview batches have been removed from the articles. The dashboard is the linked source for national results. The saved population files below are historical records and must not be treated as the current publication run. ## Dataset decision Retain the dashboard's adopted `policyengine` 6.11.1 bundle, with UK 2.151.0, core 3.33.3 and national data cut `a6299504`. The certificate, full dataset ID and checksum are recorded in `provenance.json`. The newer candidate in policyengine.py PR725 is awaiting certification/adoption. A future update must change the package and dataset provenance together and regenerate the analysis. -No population microdata were downloaded locally. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. Vahid subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The drafts retain its digest-addressed public aggregate outputs as an earlier review snapshot, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. +The household generators need no population microdata. This historical snapshot was retrieved without downloading population microdata. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. Vahid subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The drafts retain its digest-addressed public aggregate outputs as an earlier review snapshot, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. The provisional national outputs use the exact dataset above with the dashboard's October 2026 OBR forecast wrapper on both baseline and reform. Each provision is scored separately. The source commit is `0d9dccb2`; its reform definitions and October forecast input file match household reference commit `b50787aa` byte for byte. Series not updated by the overlay retain the model's March forecast path; the underlying calibration remains pre-Budget. @@ -46,9 +46,9 @@ Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipt - Confirm the treatment of Scottish landlords' finance-cost relief against the final Budget implementation. The pinned model links that relief to the UK property basic rate even for Scotland. - Check trading allowance coverage: gross receipts and actual expenses are needed to model the deduction choice; the pinned model does not apply the allowance to its separate miscellaneous-income input. - Verify the final public dashboard link and add links to these explainers within the dashboard. The source checkout's README supplies the current Vercel dashboard URL. -- Have the policy interpretation and calculations reviewed before merging. This branch is a draft and is not publication approval. +- Have the policy interpretation and calculations reviewed before merging. Draft status and publication approval are tracked on each article’s PR. -The two articles use the site's native chart blocks and cover assets. Household curves use Pavel's shared numeric line renderer from PR1462; no duplicate chart implementation or country-model code is added. +The three articles use the site's native tables, chart blocks and cover assets. Household curves use Pavel's shared numeric line renderer from PR1462; no duplicate chart implementation or country-model code is added. See `REVIEW_NOTES.md` for the independent draft-readiness check, the comparison with Pavel's posts and the remaining publication work. @@ -65,7 +65,7 @@ The earlier addition of provisional national sections passed snapshot verificati analysis/uk-budget-2026-income-tax/.venv/bin/python analysis/uk-budget-2026-income-tax/generate_trading_extensions.py ``` -This checks five additional synthetic pairs requested in Max's review, including UC, Class4 and missing-receipts fallbacks, on the same pinned October forecast as the main generator. `trading_extensions.json` records complete inputs, raw outputs and arithmetic checks. `dashboard_salary_comparison.json` records the calculator's March-index salary comparison. Household examples use no population data. Shared analysis is kept in the savings/property base PR so the trading article can be reviewed in a separate stacked PR. +This checks five additional synthetic pairs requested in Max's review, including UC, Class4 and missing-receipts fallbacks, on the same pinned October forecast as the main generator. `trading_extensions.json` records complete inputs, raw outputs and arithmetic checks. `dashboard_salary_comparison.json` records the calculator's March-index salary comparison. Household examples use no population data. Shared analysis is kept in the property base PR #1460 so the trading article can be reviewed in a separate stacked PR. The savings article is a separate draft PR based on main; its shared-analysis link resolves after #1460 lands. ## Alignment with Pavel’s PTA post @@ -79,4 +79,4 @@ The October-forecast rerun passed all23 household comparisons and all5 trading e ## Editorial cover images -Both posts use original teal editorial illustrations generated with the built-in image tool. `cover-prompts.json` records the complete prompts, output paths, encoding settings, dimensions and checksums. The WebP files retain the generated 1672 × 941 pixel dimensions and are selected by each post's `image` metadata, supplying the article hero, research card and social preview. Original text-based SVG assets remain available in Git for reference. Article text, charts and calculations are unchanged by the cover update. +The posts use original teal editorial illustrations generated with the built-in image tool. Property and savings reuse the original combined-draft cover unchanged under their own asset paths. `cover-prompts.json` records the complete prompts, output paths, encoding settings, dimensions and checksums. The WebP files retain the generated 1672 × 941 pixel dimensions and are selected by each post's `image` metadata, supplying the article hero, research card and social preview. The unused combined-draft SVG cover was removed when the article was split. Article text, charts and calculations are unchanged by the cover update. diff --git a/analysis/uk-budget-2026-income-tax/cover-prompts.json b/analysis/uk-budget-2026-income-tax/cover-prompts.json index 40308f1c4..b33bb315a 100644 --- a/analysis/uk-budget-2026-income-tax/cover-prompts.json +++ b/analysis/uk-budget-2026-income-tax/cover-prompts.json @@ -4,7 +4,7 @@ "reference_style": "PolicyEngine Autumn Budget 2026 energy and Pension Tax Allowance covers; deep teal, mint, white, restrained dimensional illustration.", "assets": [ { - "path": "app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax/cover.webp", + "path": "app/public/assets/posts/uk-autumn-budget-2026-property-income-tax/cover.webp", "prompt": "Use case: stylized-concept.\nAsset type: original editorial cover illustration for PolicyEngine's UK Autumn Budget 2026 article on savings and property income tax.\nCreate a polished wide 16:9 landscape illustration, intended final size 1600x900. Match a coherent nonprofit policy research illustration series: deep dark teal background, soft subtle teal vignette, pale mint and turquoise objects, clean vector-like shapes rendered as a raster image, restrained dimensional depth, gentle shadows, crisp edges, professional calm neutral tone.\nScene: a simplified British terraced house and a savings coin stack arranged together beside a large white income-tax statement with a teal header and a few muted grey abstract lines. One mint coin bears a clear British pound symbol (£). House, savings and statement should read as one coherent still life about taxing rental income and savings interest.\nComposition: main objects within the central 65 percent of the canvas, clear at thumbnail size, generous breathing room on every edge, balanced wide layout, a subtle floor line. Avoid tiny details.\nText: only a single £ symbol on the coin; no words, no tax rates, no numbers, no labels, no title, no logos, no watermark.\nConstraints: original illustration, no people, no flags, no political symbolism, no arrows or data charts, no claims about gains or losses. The image should look like a refined flat editorial illustration with subtle depth, not a photograph or a glossy toy render.", "width": 1672, "height": 941, @@ -12,7 +12,8 @@ "encoding_quality": 85, "pixels_resized": false, "bytes": 59420, - "sha256": "fcaa9776fa6ebfab449034a0423a166f413a9b4a4d5041747ed4610b20e111b6" + "sha256": "fcaa9776fa6ebfab449034a0423a166f413a9b4a4d5041747ed4610b20e111b6", + "reuse_note": "Originally generated for the combined savings/property draft; retained unchanged for the property article when the articles were split." }, { "path": "app/public/assets/posts/uk-autumn-budget-2026-trading-allowance/cover.webp", diff --git a/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax/cover.webp b/app/public/assets/posts/uk-autumn-budget-2026-property-income-tax/cover.webp similarity index 100% rename from app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax/cover.webp rename to app/public/assets/posts/uk-autumn-budget-2026-property-income-tax/cover.webp diff --git a/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax.svg b/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax.svg deleted file mode 100644 index 2fef7afc3..000000000 --- a/app/public/assets/posts/uk-autumn-budget-2026-savings-property-income-tax.svg +++ /dev/null @@ -1,56 +0,0 @@ - - Savings and property income tax - UK Autumn Budget 2026 raises the savings and property income tax rates scheduled for April 2027 from 22, 42 and 47 percent to 24, 44 and 49 percent. The property rates apply in England, Wales and Northern Ireland. - - - - - - - - - - - - - - - - - - - - - - - - - UK Autumn Budget 2026 - Savings and property - income tax - - Basic rate - 22% - - 24% - Before / after Budget 2026 - - Higher rate - 42% - - 44% - Before / after Budget 2026 - - Additional rate - 47% - - 49% - Before / after Budget 2026 - From 6 April 2027 · Savings: UK · Property: England, Wales and Northern Ireland - diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md new file mode 100644 index 000000000..db38f4510 --- /dev/null +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -0,0 +1,79 @@ +The Autumn Budget 2026 increases the basic, higher and additional income tax rates on property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%** in England, Wales and Northern Ireland. The property rate increase does not apply to Scottish taxpayers. The [Budget announcement, paragraph 6.246](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142) also increases the rate of residential landlords' finance-cost relief. + +Key figures for 2027–28: + +- A landlord in England with £10,000 of property profit and £4,000 of fully usable mortgage interest pays £120 more income tax. +- A mortgage-free landlord in England with the same profit pays £200 more. +- A Scottish landlord with £4,000 of fully usable finance costs pays £80 less, because the finance-cost reduction rises while Scottish property tax rates stay unchanged. +- The Treasury forecasts £35 million of additional revenue in 2027–28 and £575 million in 2028–29. + +Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for this and the other Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. The Budget also raises savings income tax rates; we will cover that measure separately. + +## What changes in April 2027? + +The [Budget 2025 technical note](https://www.gov.uk/government/publications/changes-to-tax-rates-for-property-savings-and-dividend-income/change-to-tax-rates-for-property-savings-and-dividend-income-technical-note) had already set property rates at 22%, 42% and 47% from April 2027. The additional two-point increase is measured against those existing 2027 rules. + +| Income tax band | Already scheduled for 2027–28 | Budget 2026 rate | Change | +| --- | ---: | ---: | ---: | +| Basic | 22% | 24% | +2 percentage points | +| Higher | 42% | 44% | +2 percentage points | +| Additional | 47% | 49% | +2 percentage points | + +From April 2027, employment, pension and trading income fill the tax bands before property income. Property income comes before savings and dividends. Allowances first reduce income other than property, savings or dividends. A landlord's other income therefore affects the rate charged on rental profits. + +## Household impacts + +The examples below isolate the announced property measure in 2027–28. They hold the stated income and expenses fixed and show income tax rather than household income after means-tested benefits. + +### Landlords' mortgage-interest relief rises too + +For individual residential landlords, mortgage interest normally produces a tax reduction rather than a deduction from rental profits. The reduction is limited by finance costs, property profits, adjusted total income and the tax liability. [HMRC's explanation of residential finance-cost relief](https://www.gov.uk/guidance/changes-to-tax-relief-for-residential-landlords-how-its-worked-out-including-case-studies) describes these limits. + +From April 2027 the relief follows the property basic rate, as the [Treasury policy costings, pages 74 and 75](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74 "Treasury policy costings #page 74-75") confirm. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. The dashboard calculator has no finance-cost input, so the mortgage examples below illustrate an effect its preset cannot show. + +Consider two adults in England, each with £12,000 of rent, £2,000 of allowable non-finance expenses and £4,000 of qualifying mortgage interest. Deducting actual non-finance expenses leaves £10,000 of property profit. Both can use the full finance-cost reduction. + +| Calculation, 2027–28 | £30,000 salary: before | £30,000 salary: after | £60,000 salary: before | £60,000 salary: after | +| --- | ---: | ---: | ---: | ---: | +| Property profit | £10,000 | £10,000 | £10,000 | £10,000 | +| Rate on that profit | 22% | 24% | 42% | 44% | +| Tax before finance-cost relief | £2,200 | £2,400 | £4,200 | £4,400 | +| Finance-cost reduction | £880 | £960 | £880 | £960 | +| Tax attributable to property | £1,320 | £1,440 | £3,320 | £3,440 | +| Extra annual income tax | — | £120 | — | £120 | + +Both pay £200 more before relief, while their finance-cost reduction rises by £4,000 × 2% = £80. Their net increase is £200 − £80 = £120. A mortgage-free landlord with the same profit pays £200 more. Both tax bands rise by two points, explaining the identical increases despite different starting liabilities. + +The property **rate** increase excludes Scottish taxpayers, whose rental income follows Scottish rules. Finance-cost relief is a separate calculation. The [Finance Act 2026 amendment](https://www.legislation.gov.uk/ukpga/2026/11/schedule/1/paragraph/40/enacted) ties it to the UK property basic rate without a Scottish exception. Applying that rule, a Scottish landlord able to use the full reduction on £4,000 of eligible finance costs receives £80 more relief, reducing their income tax by £80 if nothing else changes. A mortgage-free Scottish landlord has no change from this measure. + +### The dashboard's household example + +[Try the Budget dashboard's calculator](https://www.policyengine.org/uk/autumn-budget-2026?tab=household&policies=property_income_rates_up). Its example labelled “A middle earner who lets a flat” has £6,000 of property income and no mortgage interest. Selecting the property measure alone reduces household income by £120 in 2027–28: £6,000 × 2% = £120. The calculator grows a 2026–27 salary input into the selected year, while the worked examples above hold salary fixed at their stated 2027–28 amounts. + +## Treasury costing + +The Treasury's [Table 6.1, row 61](https://www.gov.uk/government/publications/supporting-documents-for-budget-2026) forecasts the following additional Exchequer revenue. These are the Treasury's figures, on a National Accounts basis. + +| Exchequer revenue, £ million | 2026–27 | 2027–28 | 2028–29 | 2029–30 | 2030–31 | 2031–32 | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| Property income rates | 0 | 35 | 575 | 435 | 445 | 455 | + +**The dashboard marks 2027–28 and 2028–29 as not comparable with the official costing.** PolicyEngine scores each tax year's liabilities in that year. Self Assessment payments on account are normally based on the previous year's tax bill; the balancing payment for 2027–28 is due on 31 January 2029, alongside the first payment on account for 2028–29. [HMRC's payment guidance](https://www.gov.uk/understand-self-assessment-bill/payments-on-account) explains that schedule. + +The [ONS public-finance methodology, section 6.1.2](https://www.ons.gov.uk/economy/governmentpublicsectorandtaxes/publicsectorfinance/methodologies/monthlystatisticsonthepublicsectorfinancesamethodologicalguide) records Self Assessment income tax using cash receipts, without shifting them back to the year the income arose. This can produce a small first-year receipts effect followed by a catch-up. Comparing those first two years with same-year model liabilities requires a collection-timing adjustment; it does not by itself establish a difference in the tax base. + +The Treasury costing also allows for some landlords incorporating. PolicyEngine's national estimates hold that choice fixed. This article reports household calculations and the Treasury costing; the dashboard carries PolicyEngine's national results and their comparability notes. + +## Assumptions and limitations + +- The worked examples are hypothetical single adults aged 35. Their income is fixed at the stated 2027–28 amounts. They include no pension contributions, Gift Aid, student loans, property losses, carried-forward finance costs or other reliefs. +- The household tables show tax attributable to property income. The mortgage examples assume the full finance-cost reduction can be used. +- The Scottish mortgage example applies the existing Finance Act rule linking relief to the UK property basic rate. The Finance Bill will set the final implementation of the new rates. +- The dashboard calculator grows a 2026–27 salary input into the selected year. Its income path differs from fixing the same nominal salary in 2027–28. +- National comparisons need the same income-tax components and collection periods. Benefit changes in a government-balance estimate must also be separated. These household examples do not establish national affected-person counts or distributions. + +## Methodology + +The household calculations use the `policyengine` Python package (version 6.11.1), PolicyEngine UK (version 2.151.0) and PolicyEngine core (version 3.33.3). The comparisons isolate the announced property changes, including finance-cost relief, against the already scheduled 2027–28 rules. Both household scenarios use the OBR’s October 2026 forecast update at dashboard commit `64042657`. Supplied 2027–28 income stays fixed; the forecast updates the model’s projected parameters. Independent arithmetic checks the tax calculations. + +The [shared analysis files](https://github.com/PolicyEngine/policyengine-app-v2/tree/main/analysis/uk-budget-2026-income-tax) record the household inputs, model versions, forecast settings and validation for the property, savings and trading explainers. Monetary amounts in tables are rounded to whole pounds; the calculation records retain precision. The household calculations use hypothetical people and do not require population microdata. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md deleted file mode 100644 index e06df2679..000000000 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-savings-property-income-tax.md +++ /dev/null @@ -1,392 +0,0 @@ -The Autumn Budget 2026 increases the basic, higher and additional income tax rates on savings and property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%**. Savings rates apply across the UK. The property rates apply in England, Wales and Northern Ireland. Dividend rates remain unchanged. These are the changes announced in the [Budget 2026, paragraphs 6.246 and 6.247](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142 "Budget 2026 #page 142,45"). - -Key figures for 2027–28: - -- A basic-rate saver with £2,000 of annual interest pays £20 more a year. -- A landlord in England with £10,000 of property profit and £4,000 of mortgage interest pays £120 more. -- A Scottish landlord with the same fully usable finance costs pays £80 less, because the finance-cost reduction rises while Scottish property tax rates stay unchanged. -- The Treasury forecasts £160 million of additional revenue from these measures in 2027–28: £35 million from property and £125 million from savings. - -Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for these and the other Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. - -## What changes in April 2027? - -The [Budget 2025 technical note](https://www.gov.uk/government/publications/changes-to-tax-rates-for-property-savings-and-dividend-income/change-to-tax-rates-for-property-savings-and-dividend-income-technical-note) had already set savings and property rates at 22%, 42% and 47% from April 2027. The additional two-point increase is measured against those existing 2027 rules. - -| Income tax band | Already scheduled for 2027–28 | Budget 2026 rate | Change | -| --- | ---: | ---: | ---: | -| Basic | 22% | 24% | +2 percentage points | -| Higher | 42% | 44% | +2 percentage points | -| Additional | 47% | 49% | +2 percentage points | - -The same note sets the ordering from April 2027: employment, pension and trading income first; property next; savings after that; and dividends last. Allowances first reduce income other than property, savings or dividends. Taxable income then fills the bands in that order, so employment and rental income can push savings interest into a higher band. - -## Household impacts - -The examples below isolate the announced savings and property measures in 2027–28. They show income tax, holding the stated income and expenses fixed. - -### Savers pay the higher rates on interest above their allowances - -The Personal Savings Allowance remains £1,000 for basic-rate taxpayers, £500 for higher-rate taxpayers and £0 for additional-rate taxpayers. People with low other income can also qualify for a starting rate of 0% on up to £5,000 of savings interest. These allowances depend on total income, as [HMRC's savings guidance](https://www.gov.uk/apply-tax-free-interest-on-savings/how-much-is-tax-free) explains. Interest earned inside an ISA remains exempt from income tax. - -These hypothetical adults live in England and receive only the wages and interest shown. Their wages use the Personal Allowance, and none qualifies for the starting rate for savings. The table isolates income tax on interest. - -| Annual employment income | Annual savings interest | Personal Savings Allowance | Interest taxed above 0% | Tax before the Budget change | Tax after | Extra annual tax | -| --- | ---: | ---: | ---: | ---: | ---: | ---: | -| £30,000 | £500 | £1,000 | £0 | £0 | £0 | £0 | -| £30,000 | £2,000 | £1,000 | £1,000 | £220 | £240 | £20 | -| £60,000 | £2,000 | £500 | £1,500 | £630 | £660 | £30 | - -For the basic-rate example, £2,000 − £1,000 = £1,000 faces the savings basic rate: £1,000 × 22% = £220 before, against £1,000 × 24% = £240 after. The higher-rate example pays an extra £1,500 × 2% = £30. - -The chart varies annual interest for the same two salaries. At these income levels, each additional £500 of interest above the allowance adds £10 to the tax increase. - -```chart -{ - "type": "line", - "title": "Savings tax increases apply above the Personal Savings Allowance", - "subtitle": "Annual income tax increase; England, salaries £30,000 and £60,000, 2027–28", - "xKey": "interest", - "xLabel": "Annual savings interest", - "yLabel": "Extra annual income tax", - "format": { - "prefix": "£", - "decimals": 0, - "separator": true - }, - "xFormat": { - "prefix": "£", - "decimals": 0, - "separator": true - }, - "source": "PolicyEngine 6.11.1 / UK 2.151.0; synthetic adults, 2027–28; incomes held fixed.", - "series": [ - { - "key": "basic", - "name": "£30,000 salary", - "color": "negative" - }, - { - "key": "higher", - "name": "£60,000 salary", - "color": "secondary" - } - ], - "markers": [ - { - "x": 500, - "label": "£60,000 salary: savings allowance" - }, - { - "x": 1000, - "label": "£30,000 salary: savings allowance" - } - ], - "data": [ - { - "interest": 500, - "basic": 0.0, - "higher": 0.0 - }, - { - "interest": 600, - "basic": 0.0, - "higher": 2.0 - }, - { - "interest": 700, - "basic": 0.0, - "higher": 4.0 - }, - { - "interest": 800, - "basic": 0.0, - "higher": 6.0 - }, - { - "interest": 900, - "basic": 0.0, - "higher": 8.0 - }, - { - "interest": 1000, - "basic": 0.0, - "higher": 10.0 - }, - { - "interest": 1100, - "basic": 2.0, - "higher": 12.0 - }, - { - "interest": 1200, - "basic": 4.0, - "higher": 14.0 - }, - { - "interest": 1300, - "basic": 6.0, - "higher": 16.0 - }, - { - "interest": 1400, - "basic": 8.0, - "higher": 18.0 - }, - { - "interest": 1500, - "basic": 10.0, - "higher": 20.0 - }, - { - "interest": 1600, - "basic": 12.0, - "higher": 22.0 - }, - { - "interest": 1700, - "basic": 14.0, - "higher": 24.0 - }, - { - "interest": 1800, - "basic": 16.0, - "higher": 26.0 - }, - { - "interest": 1900, - "basic": 18.0, - "higher": 28.0 - }, - { - "interest": 2000, - "basic": 20.0, - "higher": 30.0 - }, - { - "interest": 2100, - "basic": 22.0, - "higher": 32.0 - }, - { - "interest": 2200, - "basic": 24.0, - "higher": 34.0 - }, - { - "interest": 2300, - "basic": 26.0, - "higher": 36.0 - }, - { - "interest": 2400, - "basic": 28.0, - "higher": 38.0 - }, - { - "interest": 2500, - "basic": 30.0, - "higher": 40.0 - }, - { - "interest": 2600, - "basic": 32.0, - "higher": 42.0 - }, - { - "interest": 2700, - "basic": 34.0, - "higher": 44.0 - }, - { - "interest": 2800, - "basic": 36.0, - "higher": 46.0 - }, - { - "interest": 2900, - "basic": 38.0, - "higher": 48.0 - }, - { - "interest": 3000, - "basic": 40.0, - "higher": 50.0 - }, - { - "interest": 3100, - "basic": 42.0, - "higher": 52.0 - }, - { - "interest": 3200, - "basic": 44.0, - "higher": 54.0 - }, - { - "interest": 3300, - "basic": 46.0, - "higher": 56.0 - }, - { - "interest": 3400, - "basic": 48.0, - "higher": 58.0 - }, - { - "interest": 3500, - "basic": 50.0, - "higher": 60.0 - }, - { - "interest": 3600, - "basic": 52.0, - "higher": 62.0 - }, - { - "interest": 3700, - "basic": 54.0, - "higher": 64.0 - }, - { - "interest": 3800, - "basic": 56.0, - "higher": 66.0 - }, - { - "interest": 3900, - "basic": 58.0, - "higher": 68.0 - }, - { - "interest": 4000, - "basic": 60.0, - "higher": 70.0 - }, - { - "interest": 4100, - "basic": 62.0, - "higher": 72.0 - }, - { - "interest": 4200, - "basic": 64.0, - "higher": 74.0 - }, - { - "interest": 4300, - "basic": 66.0, - "higher": 76.0 - }, - { - "interest": 4400, - "basic": 68.0, - "higher": 78.0 - }, - { - "interest": 4500, - "basic": 70.0, - "higher": 80.0 - }, - { - "interest": 4600, - "basic": 72.0, - "higher": 82.0 - }, - { - "interest": 4700, - "basic": 74.0, - "higher": 84.0 - }, - { - "interest": 4800, - "basic": 76.0, - "higher": 86.0 - }, - { - "interest": 4900, - "basic": 78.0, - "higher": 88.0 - }, - { - "interest": 5000, - "basic": 80.0, - "higher": 90.0 - } - ] -} -``` - -### Landlords' mortgage-interest relief rises too - -For individual residential landlords, mortgage interest normally produces a tax reduction rather than a deduction from rental profits. The reduction is limited by finance costs, property profits, adjusted total income and the tax liability. [HMRC's explanation of residential finance-cost relief](https://www.gov.uk/guidance/changes-to-tax-relief-for-residential-landlords-how-its-worked-out-including-case-studies) describes these limits. - -From April 2027 the relief follows the property basic rate, as the [Treasury policy costings, pages 74 and 75](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74 "Treasury policy costings #page 74-75") confirm. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. The dashboard calculator has no finance-cost input, so the mortgage examples below illustrate an effect its preset cannot show. - -Consider two adults in England, each with £12,000 of rent, £2,000 of allowable non-finance expenses and £4,000 of qualifying mortgage interest. Deducting actual non-finance expenses leaves £10,000 of property profit. Both can use the full finance-cost reduction. - -| Calculation, 2027–28 | £30,000 salary: before | £30,000 salary: after | £60,000 salary: before | £60,000 salary: after | -| --- | ---: | ---: | ---: | ---: | -| Property profit | £10,000 | £10,000 | £10,000 | £10,000 | -| Rate on that profit | 22% | 24% | 42% | 44% | -| Tax before finance-cost relief | £2,200 | £2,400 | £4,200 | £4,400 | -| Finance-cost reduction | £880 | £960 | £880 | £960 | -| Tax attributable to property | £1,320 | £1,440 | £3,320 | £3,440 | -| Extra annual income tax | — | £120 | — | £120 | - -Both pay £200 more before relief, while their finance-cost reduction rises by £4,000 × 2% = £80. Their net increase is £200 − £80 = £120. A mortgage-free landlord with the same profit pays £200 more. Both tax bands rise by two points, explaining the identical increases despite different starting liabilities. - -The property **rate** increase excludes Scottish taxpayers, whose rental income follows Scottish rules. Finance-cost relief is a separate calculation. The [Finance Act 2026 amendment](https://www.legislation.gov.uk/ukpga/2026/11/schedule/1/paragraph/40/enacted) ties it to the UK property basic rate without a Scottish exception. Applying that rule, a Scottish landlord able to use the full reduction on £4,000 of eligible finance costs receives £80 more relief, reducing their income tax by £80 if nothing else changes. A mortgage-free Scottish landlord has no change from this measure. The savings increase still applies across the UK. - -### When property income pushes savings into a higher band - -Consider an adult in England with £45,000 of salary, £6,000 of property profit after allowable expenses, £2,000 of interest and no mortgage interest. The £12,570 Personal Allowance leaves £32,430 of taxable salary. That uses £32,430 of the £37,700 basic-rate band, leaving £5,270. - -Property income fills that remaining £5,270, with £730 entering the higher band. The individual qualifies for a £500 Personal Savings Allowance; the remaining £1,500 of interest falls in the higher savings band. - -| Income tax component, 2027–28 | Before | After | -| --- | ---: | ---: | -| Salary: £32,430 at 20% | £6,486 | £6,486 | -| Property: £5,270 at 22% / 24% | £1,159 | £1,265 | -| Property: £730 at 42% / 44% | £307 | £321 | -| Savings: £1,500 at 42% / 44% | £630 | £660 | -| Total income tax | £8,582 | £8,732 | - -The extra tax is £120 on property plus £30 on savings, or **£150 a year**. The calculation shows why the order of income sources matters even when each rate rises by the same two percentage points. - -[Try the Budget dashboard's calculator](https://www.policyengine.org/uk/autumn-budget-2026?tab=household). Its landlord-and-saver example uses these same inputs: £45,000 salary, £6,000 of property income and £2,000 of interest. In 2027–28, its property measure reduces household income by £120 and its savings measure by £30, matching this table's £150 tax increase. The calculator takes salary for 2026–27 and grows it into the selected year, while the table fixes salary at £45,000 in 2027–28. On the calculator's current earnings path, the £45,000 input becomes about £46,080, giving total tax of £9,014 before and £9,164 after. The additional tax remains £150. - -## Government estimates of reach - -The government estimates that **84% of income tax payers are unaffected** in 2027–28 and that around half the revenue comes from the top 10% of households. Budget paragraph 2.50 and footnote 74 base these figures on HMRC's Survey of Personal Incomes 2023–24, projected to 2027–28 and mapped onto household deciles with the Treasury's Distributional Analysis model. These are the government's estimates of taxpayers and households, respectively. - -## Treasury costing - -The Treasury costs savings and property separately in [Table 6.1, rows 61 and 62](https://www.gov.uk/government/publications/supporting-documents-for-budget-2026). Their combined forecast is £160 million in 2027–28 and £1,045 million in 2031–32. Positive values in the table are additional Exchequer revenue. - -| Exchequer revenue, £ million | 2026–27 | 2027–28 | 2028–29 | 2029–30 | 2030–31 | 2031–32 | -| --- | ---: | ---: | ---: | ---: | ---: | ---: | -| Property income rates | 0 | 35 | 575 | 435 | 445 | 455 | -| Savings income rates | 15 | 125 | 555 | 520 | 555 | 590 | -| Treasury combined | 15 | 160 | 1,130 | 955 | 1,000 | 1,045 | - -The Treasury costings allow for some landlords incorporating and savers moving funds into tax-advantaged products such as ISAs. PolicyEngine's national estimates hold those choices fixed. - -Collection timing also matters. PolicyEngine scores each tax year's liabilities in that year. Self Assessment payments on account are normally based on the previous year's tax bill; the balancing payment for 2027–28 is due on 31 January 2029, alongside the first payment on account for 2028–29. [HMRC's payment guidance](https://www.gov.uk/understand-self-assessment-bill/payments-on-account) explains that schedule. The [ONS public-finance methodology, section 6.1.2](https://www.ons.gov.uk/economy/governmentpublicsectorandtaxes/publicsectorfinance/methodologies/monthlystatisticsonthepublicsectorfinancesamethodologicalguide) records Self Assessment income tax using cash receipts, without shifting them back to the year the income arose. This can produce a small first-year receipts effect followed by a catch-up. A year-by-year comparison of the property's 2027–28 and 2028–29 receipts with same-year liabilities therefore needs a collection-timing adjustment; it does not by itself establish a difference in the tax base. - -The costing notes do not explain the Treasury's £15 million savings figure in 2026–27, before the rates take effect. The model has no rate change in that year. A receipts-timing explanation for property does not establish the source of any savings discrepancy: the savings tax base, collection routes and behavioural assumptions require their own comparison. - -## Assumptions and limitations - -- The worked examples are hypothetical single adults aged 35. Their income is fixed at the stated 2027–28 amounts. The examples include no pension contributions, Gift Aid, student loans, property losses, carried-forward finance costs or other reliefs. Savings are outside ISAs. -- The household tables show tax attributable to each income source. They do not estimate household income after means-tested benefits. The mortgage examples assume the full finance-cost reduction can be used. -- The Scottish mortgage example applies the existing Finance Act rule linking relief to the UK property basic rate. The Finance Bill will set the final implementation of the new rates. -- The dashboard calculator grows a 2026–27 salary input into the selected year. Its current earnings path differs from fixing the same nominal salary in 2027–28, as the mixed-income example explains. -- PolicyEngine's national estimates use a static model, while the Treasury forecasts use different data and include behavioural responses. Comparing them requires the same income-tax components and collection periods; benefit changes in a government-balance estimate must also be separated. -- The household examples do not establish national affected-person counts or distributions. National results require their own population analysis and disclosure checks. - -## Methodology - -The household calculations use the `policyengine` Python package (version 6.11.1), PolicyEngine UK (version 2.151.0) and PolicyEngine core (version 3.33.3). Each comparison applies only the announced savings and property changes, including finance-cost relief, against the already scheduled 2027–28 rules. Both household scenarios use the OBR’s October 2026 forecast update at dashboard commit `64042657`. Supplied 2027–28 income stays fixed; the forecast updates the model’s projected parameters. Tax calculations are checked against independent arithmetic. The line chart plots the exact schedule breakpoints and points every £100, and its interpolation agrees with PolicyEngine UK to within one penny at every £2 of interest. - -The [analysis files](https://github.com/PolicyEngine/policyengine-app-v2/tree/main/analysis/uk-budget-2026-income-tax) record the household inputs, model versions, forecast settings and validation. Monetary amounts in tables are rounded to whole pounds; the calculation records retain precision. The household calculations use hypothetical people and do not require population microdata. diff --git a/app/src/data/posts/posts.json b/app/src/data/posts/posts.json index 83d75d057..3505a0e3a 100644 --- a/app/src/data/posts/posts.json +++ b/app/src/data/posts/posts.json @@ -1,19 +1,12 @@ [ { - "title": "Autumn Budget 2026: higher tax on savings and property income", - "description": "Worked examples of the additional two percentage point increase from April 2027, including savings allowances and landlords' mortgage-interest relief.", + "title": "Autumn Budget 2026: higher tax on property income", + "description": "Worked examples of the additional two percentage point property income tax increase from April 2027, including landlords' mortgage-interest relief and the treatment of Scotland.", "date": "2026-10-28 14:00:00", - "tags": [ - "uk", - "policy", - "tax", - "autumn-budget" - ], - "authors": [ - "ziming-hua" - ], - "filename": "uk-autumn-budget-2026-savings-property-income-tax.md", - "image": "uk-autumn-budget-2026-savings-property-income-tax/cover.webp" + "tags": ["uk", "policy", "tax", "autumn-budget"], + "authors": ["ziming-hua"], + "filename": "uk-autumn-budget-2026-property-income-tax.md", + "image": "uk-autumn-budget-2026-property-income-tax/cover.webp" }, { "title": "The fuel duty cut extension in the Autumn Budget 2026", From be65300fd21507719c5ff3e883bfa69b11691af4 Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 14:10:43 -0400 Subject: [PATCH 14/24] Clarify property sources and shared household methodology --- analysis/uk-budget-2026-income-tax/README.md | 6 ++++-- analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md | 2 ++ .../articles/uk-autumn-budget-2026-property-income-tax.md | 8 ++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index 39bc64b84..e0506f38d 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -1,6 +1,6 @@ # Autumn Budget 2026 income tax explainers -This shared directory supports three standalone posts: the property income rate increase, the savings income rate increase and the trading allowance increase. Property and savings were split at the author’s request on 28 October 2026; savings remains a separate draft pending its dashboard data release. The articles compare the newly announced measures with the already legislated 2027–28 baseline, one measure at a time. +This shared directory supports three standalone posts: the property income rate increase, the savings income rate increase and the trading allowance increase. Property and savings were split at the author’s request on 28 October 2026; savings remains a separate draft pending its dashboard data release. The articles compare the newly announced measures with the already legislated 2027–28 baseline. The shared `SAVINGS_PROPERTY` reform in `generate_households.py` changes savings and property rates together; it is not a separate property-only reform. ## Reproduce the household calculations @@ -16,7 +16,9 @@ The generator uses hypothetical adults, without population microdata. It records The checked outputs include 23 household comparisons and 93 displayed points across the two income curves. The displayed lines use £100 intervals and the exact policy breakpoints. All four series are independently checked against the model at every £2 from £500 to £5,000, including a comparison of the plotted interpolation with the engine results; `curve-validation.json` records counts and maximum errors. The non-integer £1,333⅓ expense-choice breakpoint is also calculated with the model. To also verify the original dashboard parameter builder, pass `--dashboard-checkout /path/to/checkout` with that checkout at the recorded commit. This check is optional and performs no download. -The article chart blocks reproduce `savings-interest-chart.json` and `trading-allowance-chart.json`. Reinsert their contents when regenerating them. +The `landlord_*` records in `households.json` and `households.csv` support the property article. They have no savings income, so the combined reform's savings rate changes do not affect their results. The dashboard preset's property-only component was checked separately. The `saver_*` and mixed `property_then_savings_order` records, savings curves, and savings-rate and Treasury row 62 metadata in `provenance.json` remain shared records for savings draft #1466; they are not property-only results. + +The savings draft (#1466) reproduces `savings-interest-chart.json`; the trading article (#1463) reproduces `trading-allowance-chart.json`. The property article has no line-chart block. Reinsert each chart's contents only into its corresponding article when regenerating it. ## Current article scope diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md index 73d50e0c4..5e55cc464 100644 --- a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md +++ b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md @@ -108,6 +108,8 @@ Max's 16:18:54 UTC webinar update asks authors to introduce each measure for 30 ## Remaining review comments addressed on 28 October +Historical review record: the combined article's Treasury total and mixed £120 property / £30 savings paragraph described below were superseded by the 28 October 2026 split. Property-only PR #1460 no longer contains those combined figures; savings is a separate draft in #1466. The older combined records remain here for reproducibility, and current publication status is tracked on each PR. + The savings/property article removes the withdrawn combined national snapshot, its model fiscal row, decile table and affected share. Its key figures and national table now contain Treasury costings only, separated into property and savings with the combined official total. The archived data and earlier review records remain here for reproducibility; they are not current article results. This follows the cut-or-match-final-run rule Max applied in trading commits8751cf29 andc78cdd60, without substituting unverified replacement figures. The mixed-income paragraph now confirms the dashboard's landlord-45k preset and the £120 property plus£30 savings split. It retains the salary-uprating explanation. Canonical dashboard links use www.policyengine.org/uk/autumn-budget-2026, and publication wording holds before and after the production switch. The model's hypothetical households and chart values are unchanged. diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index db38f4510..63d72e763 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -1,11 +1,11 @@ -The Autumn Budget 2026 increases the basic, higher and additional income tax rates on property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%** in England, Wales and Northern Ireland. The property rate increase does not apply to Scottish taxpayers. The [Budget announcement, paragraph 6.246](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142) also increases the rate of residential landlords' finance-cost relief. +The Autumn Budget 2026 increases the basic, higher and additional income tax rates on property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%** in England, Wales and Northern Ireland, as [Budget paragraph 6.246](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142) sets out. The property rate increase does not apply to Scottish taxpayers. Because finance-cost relief follows the property basic rate, residential landlords' relief rises too. Key figures for 2027–28: - A landlord in England with £10,000 of property profit and £4,000 of fully usable mortgage interest pays £120 more income tax. - A mortgage-free landlord in England with the same profit pays £200 more. - A Scottish landlord with £4,000 of fully usable finance costs pays £80 less, because the finance-cost reduction rises while Scottish property tax rates stay unchanged. -- The Treasury forecasts £35 million of additional revenue in 2027–28 and £575 million in 2028–29. +- The Treasury forecasts £35 million of additional revenue in 2027–28, £575 million in 2028–29, and £435 million to £455 million a year from 2029–30 to 2031–32. Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for this and the other Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. The Budget also raises savings income tax rates; we will cover that measure separately. @@ -29,7 +29,7 @@ The examples below isolate the announced property measure in 2027–28. They hol For individual residential landlords, mortgage interest normally produces a tax reduction rather than a deduction from rental profits. The reduction is limited by finance costs, property profits, adjusted total income and the tax liability. [HMRC's explanation of residential finance-cost relief](https://www.gov.uk/guidance/changes-to-tax-relief-for-residential-landlords-how-its-worked-out-including-case-studies) describes these limits. -From April 2027 the relief follows the property basic rate, as the [Treasury policy costings, pages 74 and 75](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74 "Treasury policy costings #page 74-75") confirm. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. The dashboard calculator has no finance-cost input, so the mortgage examples below illustrate an effect its preset cannot show. +From April 2027 the relief follows the property basic rate, as the [Treasury policy costings](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74) confirm. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. The dashboard calculator has no finance-cost input, so the mortgage examples below illustrate an effect its preset cannot show. Consider two adults in England, each with £12,000 of rent, £2,000 of allowable non-finance expenses and £4,000 of qualifying mortgage interest. Deducting actual non-finance expenses leaves £10,000 of property profit. Both can use the full finance-cost reduction. @@ -74,6 +74,6 @@ The Treasury costing also allows for some landlords incorporating. PolicyEngine' ## Methodology -The household calculations use the `policyengine` Python package (version 6.11.1), PolicyEngine UK (version 2.151.0) and PolicyEngine core (version 3.33.3). The comparisons isolate the announced property changes, including finance-cost relief, against the already scheduled 2027–28 rules. Both household scenarios use the OBR’s October 2026 forecast update at dashboard commit `64042657`. Supplied 2027–28 income stays fixed; the forecast updates the model’s projected parameters. Independent arithmetic checks the tax calculations. +The household calculations use the `policyengine` Python package (version 6.11.1), PolicyEngine UK (version 2.151.0) and PolicyEngine core (version 3.33.3). The shared generator changes savings and property rates together against the already scheduled 2027–28 rules. The landlord examples in this article have no savings income, so the savings rate change has no effect on them: their tax differences isolate the property changes, including finance-cost relief. The dashboard preset's property-only component was checked separately. Both household scenarios use the OBR’s October 2026 forecast update at dashboard commit `64042657`. Supplied 2027–28 income stays fixed; the forecast updates the model’s projected parameters. Independent arithmetic checks the tax calculations. The [shared analysis files](https://github.com/PolicyEngine/policyengine-app-v2/tree/main/analysis/uk-budget-2026-income-tax) record the household inputs, model versions, forecast settings and validation for the property, savings and trading explainers. Monetary amounts in tables are rounded to whole pounds; the calculation records retain precision. The household calculations use hypothetical people and do not require population microdata. From 0bf4f73ce1a7b5bf9a7e434c565872e19f0adfcb Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 14:25:07 -0400 Subject: [PATCH 15/24] docs: clarify budget household generator scope --- analysis/uk-budget-2026-income-tax/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index e0506f38d..6076ae9bb 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -71,7 +71,7 @@ This checks five additional synthetic pairs requested in Max's review, including ## Alignment with Pavel’s PTA post -The exact forecast input is retained as `obr_october_2026.json`; `forecast.py` verifies its Git blob before use and reconstructs the source’s rounded fuel-duty path. Its complete eight-path parameter mapping was checked for exact equality with the immutable dashboard source’s `with_forecast(None).parameter_changes`. `pe.uk.calculate_household` accepts parameter mappings, so both synthetic generators pass that mapping together with only the measure being analysed. There is no population data load to precede, and no other Budget measure is activated. +The exact forecast input is retained as `obr_october_2026.json`; `forecast.py` verifies its Git blob before use and reconstructs the source’s rounded fuel-duty path. Its complete eight-path parameter mapping was checked for exact equality with the immutable dashboard source’s `with_forecast(None).parameter_changes`. Both synthetic generators pass that mapping to `pe.uk.calculate_household`. The savings/property generator uses the combined savings and property reform; its savings changes have no effect on the landlord records because those households have no savings income. The trading generator uses the trading allowance reform. There is no population data load to precede, and no other Budget measure is activated. Pavel’s comparison uses £100 chart sampling plus the true breakpoints and verifies the results on a denser model grid. These drafts now follow that method: numeric income axes, explicit £ formats, named threshold markers and independent validation at every £2. Reader-facing tables continue to use whole pounds per Max’s latest correction; raw analysis retains precision. From 18bc5f75b7f63a5363def6ae6bf6ffbcfc71e815 Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 15:07:25 -0400 Subject: [PATCH 16/24] docs: add property microsimulation to Budget explainer --- analysis/uk-budget-2026-income-tax/README.md | 28 +- .../uk-budget-2026-income-tax/REVIEW_NOTES.md | 84 ++-- .../property-population/README.md | 37 ++ .../property-population/budgetary_impact.csv | 7 + .../distributional_impact.csv | 61 +++ .../property-population/metrics.csv | 7 + .../property-population/receipt.json | 174 +++++++ .../property-population/summary.json | 423 ++++++++++++++++++ .../property-population/winners_losers.csv | 67 +++ ...-autumn-budget-2026-property-income-tax.md | 152 ++++++- 10 files changed, 970 insertions(+), 70 deletions(-) create mode 100644 analysis/uk-budget-2026-income-tax/property-population/README.md create mode 100644 analysis/uk-budget-2026-income-tax/property-population/budgetary_impact.csv create mode 100644 analysis/uk-budget-2026-income-tax/property-population/distributional_impact.csv create mode 100644 analysis/uk-budget-2026-income-tax/property-population/metrics.csv create mode 100644 analysis/uk-budget-2026-income-tax/property-population/receipt.json create mode 100644 analysis/uk-budget-2026-income-tax/property-population/summary.json create mode 100644 analysis/uk-budget-2026-income-tax/property-population/winners_losers.csv diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index 6076ae9bb..ee089ffa3 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -1,6 +1,6 @@ # Autumn Budget 2026 income tax explainers -This shared directory supports three standalone posts: the property income rate increase, the savings income rate increase and the trading allowance increase. Property and savings were split at the author’s request on 28 October 2026; savings remains a separate draft pending its dashboard data release. The articles compare the newly announced measures with the already legislated 2027–28 baseline. The shared `SAVINGS_PROPERTY` reform in `generate_households.py` changes savings and property rates together; it is not a separate property-only reform. +This shared directory supports three standalone posts: the property income rate increase ([PR #1460](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460)), the savings income rate increase ([PR #1466](https://github.com/PolicyEngine/policyengine-app-v2/pull/1466)) and the trading allowance increase ([PR #1463](https://github.com/PolicyEngine/policyengine-app-v2/pull/1463)). Property and savings were split at the author’s request on 28 October 2026; savings remains a separate draft pending its dashboard data release. The articles compare the newly announced measures with the already legislated 2027–28 baseline. The shared `SAVINGS_PROPERTY` reform in `generate_households.py` changes savings and property rates together; it is not a separate property-only reform. ## Reproduce the household calculations @@ -12,23 +12,25 @@ uv pip install --python analysis/uk-budget-2026-income-tax/.venv/bin/python -r a analysis/uk-budget-2026-income-tax/.venv/bin/python analysis/uk-budget-2026-income-tax/generate_households.py ``` -The generator uses hypothetical adults, without population microdata. It records inputs and outputs and checks the results against independent arithmetic. The reform parameters match dashboard PR290 at the immutable commit recorded in `provenance.json`. Both the baseline and reform now also use the same October 2026 forecast as Pavel’s PTA post (dashboard commit `640426575270224db9b04d6c94d30e264a347be2`). Supplied income amounts remain fixed in 2027–28; the forecast updates statutory and other model parameters. Fixed nominal incomes do not remove the need to use the agreed forecast. +The generator uses hypothetical adults, without population microdata. It records inputs and outputs and checks the results against independent arithmetic. The reform parameters match [dashboard PR #290](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/290) at the immutable commit recorded in `provenance.json`. Both the baseline and reform use the same October 2026 forecast as the [Pension Tax Allowance analysis, PR #1457](https://github.com/PolicyEngine/policyengine-app-v2/pull/1457) (dashboard commit `640426575270224db9b04d6c94d30e264a347be2`). Supplied income amounts remain fixed in 2027–28; the forecast updates statutory and other model parameters. Fixed nominal incomes do not remove the need to use the agreed forecast. The checked outputs include 23 household comparisons and 93 displayed points across the two income curves. The displayed lines use £100 intervals and the exact policy breakpoints. All four series are independently checked against the model at every £2 from £500 to £5,000, including a comparison of the plotted interpolation with the engine results; `curve-validation.json` records counts and maximum errors. The non-integer £1,333⅓ expense-choice breakpoint is also calculated with the model. To also verify the original dashboard parameter builder, pass `--dashboard-checkout /path/to/checkout` with that checkout at the recorded commit. This check is optional and performs no download. The `landlord_*` records in `households.json` and `households.csv` support the property article. They have no savings income, so the combined reform's savings rate changes do not affect their results. The dashboard preset's property-only component was checked separately. The `saver_*` and mixed `property_then_savings_order` records, savings curves, and savings-rate and Treasury row 62 metadata in `provenance.json` remain shared records for savings draft #1466; they are not property-only results. -The savings draft (#1466) reproduces `savings-interest-chart.json`; the trading article (#1463) reproduces `trading-allowance-chart.json`. The property article has no line-chart block. Reinsert each chart's contents only into its corresponding article when regenerating it. +The savings draft (#1466) reproduces `savings-interest-chart.json`; the trading article (#1463) reproduces `trading-allowance-chart.json`. The property article's native bar chart uses the verified 2027 and 2031 decile means in `property-population/`. Reinsert each chart's contents only into its corresponding article when regenerating it. ## Current article scope -All three posts publish household calculations and Treasury costings only. Model national estimates, decile tables and affected shares from earlier preview batches have been removed from the articles. The dashboard is the linked source for national results. The saved population files below are historical records and must not be treated as the current publication run. +The property draft now includes national revenue, decile averages and the precisely defined affected-population measure from the approved property-only snapshot in dashboard PR #290. `property-population/` retains the immutable source record, original receipt, four CSVs used by the post and the canonical verification summary. It is an approved branch snapshot, not independently verified as the production deployment. Recheck its identity and figures against the final released dashboard before merging, and have the new article head reviewed. + +The savings and trading posts retain household calculations and Treasury costings only. No withdrawn combined national figures have been restored. The `population-preview/` files described below remain historical records; they are not the property-only source now used by the article. ## Dataset decision Retain the dashboard's adopted `policyengine` 6.11.1 bundle, with UK 2.151.0, core 3.33.3 and national data cut `a6299504`. The certificate, full dataset ID and checksum are recorded in `provenance.json`. The newer candidate in policyengine.py PR725 is awaiting certification/adoption. A future update must change the package and dataset provenance together and regenerate the analysis. -The household generators need no population microdata. This historical snapshot was retrieved without downloading population microdata. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. Vahid subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The drafts retain its digest-addressed public aggregate outputs as an earlier review snapshot, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. +The household generators need no population microdata. This historical snapshot was retrieved without downloading population microdata. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. The dashboard maintainer subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The analysis records retain its digest-addressed public aggregate outputs as an earlier review snapshot, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. The provisional national outputs use the exact dataset above with the dashboard's October 2026 OBR forecast wrapper on both baseline and reform. Each provision is scored separately. The source commit is `0d9dccb2`; its reform definitions and October forecast input file match household reference commit `b50787aa` byte for byte. Series not updated by the overlay retain the model's March forecast path; the underlying calibration remains pre-Budget. @@ -44,15 +46,15 @@ Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipt ## Checks before publication -- Add national revenue and decile results only after final reconciliation if that population scope is restored to the posts. Add absolute affected-person counts and separate winner/loser shares when the producer exports those quantities; do not infer them from average changes or the affected percentage. +- Recheck the property draft's `property-population/` artifact identity, figures and comparison flags against the final released dashboard. The new population section needs review at its new head. Restore national scope in the other posts only from their own reconciled sources. Add absolute affected-person counts and separate winner/loser shares only when the producer exports those quantities; do not infer them from average changes or the affected percentage. - Confirm the treatment of Scottish landlords' finance-cost relief against the final Budget implementation. The pinned model links that relief to the UK property basic rate even for Scotland. - Check trading allowance coverage: gross receipts and actual expenses are needed to model the deduction choice; the pinned model does not apply the allowance to its separate miscellaneous-income input. - Verify the final public dashboard link and add links to these explainers within the dashboard. The source checkout's README supplies the current Vercel dashboard URL. - Have the policy interpretation and calculations reviewed before merging. Draft status and publication approval are tracked on each article’s PR. -The three articles use the site's native tables, chart blocks and cover assets. Household curves use Pavel's shared numeric line renderer from PR1462; no duplicate chart implementation or country-model code is added. +The three articles use the site's native tables, chart blocks and cover assets. Household curves use the shared numeric line renderer from [PR #1462](https://github.com/PolicyEngine/policyengine-app-v2/pull/1462); no duplicate chart implementation or country-model code is added. -See `REVIEW_NOTES.md` for the independent draft-readiness check, the comparison with Pavel's posts and the remaining publication work. +See `REVIEW_NOTES.md` for the historical draft-readiness checks, comparison with the reference Budget explainers and remaining publication work. ## Validation on 28 October 2026 @@ -67,17 +69,17 @@ The earlier addition of provisional national sections passed snapshot verificati analysis/uk-budget-2026-income-tax/.venv/bin/python analysis/uk-budget-2026-income-tax/generate_trading_extensions.py ``` -This checks five additional synthetic pairs requested in Max's review, including UC, Class4 and missing-receipts fallbacks, on the same pinned October forecast as the main generator. `trading_extensions.json` records complete inputs, raw outputs and arithmetic checks. `dashboard_salary_comparison.json` records the calculator's March-index salary comparison. Household examples use no population data. Shared analysis is kept in the property base PR #1460 so the trading article can be reviewed in a separate stacked PR. The savings article is a separate draft PR based on main; its shared-analysis link resolves after #1460 lands. +This checks five additional synthetic pairs requested in the [trading allowance review](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472758764), including UC, Class 4 and missing-receipts fallbacks, on the same pinned October forecast as the main generator. `trading_extensions.json` records complete inputs, raw outputs and arithmetic checks. `dashboard_salary_comparison.json` records the calculator's March-index salary comparison. Household examples use no population data. Shared analysis is kept in the property base PR #1460 so the trading article can be reviewed in a separate stacked PR. The savings article is a separate draft PR based on main; its shared-analysis link resolves after #1460 lands. -## Alignment with Pavel’s PTA post +## Alignment with the Pension Tax Allowance analysis The exact forecast input is retained as `obr_october_2026.json`; `forecast.py` verifies its Git blob before use and reconstructs the source’s rounded fuel-duty path. Its complete eight-path parameter mapping was checked for exact equality with the immutable dashboard source’s `with_forecast(None).parameter_changes`. Both synthetic generators pass that mapping to `pe.uk.calculate_household`. The savings/property generator uses the combined savings and property reform; its savings changes have no effect on the landlord records because those households have no savings income. The trading generator uses the trading allowance reform. There is no population data load to precede, and no other Budget measure is activated. -Pavel’s comparison uses £100 chart sampling plus the true breakpoints and verifies the results on a denser model grid. These drafts now follow that method: numeric income axes, explicit £ formats, named threshold markers and independent validation at every £2. Reader-facing tables continue to use whole pounds per Max’s latest correction; raw analysis retains precision. +The Pension Tax Allowance analysis uses £100 chart sampling plus the true breakpoints and verifies the results on a denser model grid. These drafts follow that method: numeric income axes, explicit £ formats, named threshold markers and independent validation at every £2. Reader-facing tables use whole pounds under the [rounding review](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6473972686); raw analysis retains precision. -The household forecast pin and the archived national forecast are recorded separately. Applying the new household overlay does not regenerate or validate the historical national snapshot. That snapshot still awaits reconciled replacement outputs with execution-bound component results. +The household forecast pin and population forecast pins are recorded separately. Applying the household overlay does not regenerate or validate the historical combined national snapshot. The property article now uses a separate approved property-only source with execution-bound provenance in `property-population/`; the historical combined preview remains superseded. -The October-forecast rerun passed all23 household comparisons and all5 trading extension pairs. All policy deltas remain unchanged. Some absolute levels change: the three Scottish cases’ income-tax levels fall by £2.93 on both sides, and the parent’s total benefits/net income rise by about £20.10 on both sides. These do not change the article’s reported tax or household gains. The new93 displayed chart points passed18,008 model-liability comparisons and9,004 interpolation comparisons over2,251 income points per series. The largest interpolation difference is£0.0033, below the£0.01 tolerance. +The October-forecast rerun passed all 23 household comparisons and all 5 trading extension pairs. All policy deltas remain unchanged. Some absolute levels change: the three Scottish cases’ income-tax levels fall by £2.93 on both sides, and the parent’s total benefits/net income rise by about £20.10 on both sides. These do not change the article’s reported tax or household gains. The 93 displayed chart points passed 18,008 model-liability comparisons and 9,004 interpolation comparisons over 2,251 income points per series. The largest interpolation difference is £0.0033, below the £0.01 tolerance. ## Editorial cover images diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md index 5e55cc464..ff6a9ee23 100644 --- a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md +++ b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md @@ -1,8 +1,10 @@ -# Draft review handoff +# Draft review history and handoff -Both standalone posts are ready for agent review in draft PR #1460. Publication remains a separate decision. +This file preserves the chronological review history. Earlier sections describe the combined savings/property article and the trading article while both were in PR #1460; their readiness and publication statements are historical, not current approvals. -## Internal readiness check +The articles are now separate: property is [PR #1460](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460), trading is [PR #1463](https://github.com/PolicyEngine/policyengine-app-v2/pull/1463), and savings is [PR #1466](https://github.com/PolicyEngine/policyengine-app-v2/pull/1466). Current readiness and publication status are tracked on each PR. The property article's approved national snapshot is documented in `property-population/README.md`; it supersedes the combined preview for that article only. + +## Historical internal readiness check An independent policy/source reviewer and code/reproducibility reviewer examined commit `7f90092fa6e6f28f68b419c4edf1bef166d851b9` on 28 October 2026. The review was complete for draft readiness, with no confirmed critical or should-address findings and one optional clarity suggestion. @@ -13,7 +15,7 @@ An independent policy/source reviewer and code/reproducibility reviewer examined The optional suggestion was to name the Treasury's trading-allowance expense-switching response. The follow-up adds that explanation with its physical-page-23 citation. It also adds an explicit savings/property band calculation using the already reproduced `property_then_savings_order` case (£8,582 to £8,732 income tax) and uses the canonical dashboard address shared in the team channel. These are prose and citation changes; model calculations are unchanged. The band table is checked against the saved component and total taxes. -## What to review +## Historical review scope - Savings/property: income ordering, the transition between basic and higher bands, and the conditional £80 finance-relief gain for Scottish landlords with £4,000 of fully usable finance costs. - Trading: the receipts-versus-expenses choice, the separate miscellaneous-income coverage limitation and the population approximation when gross receipts are missing. @@ -21,7 +23,7 @@ The optional suggestion was to name the Treasury's trading-allowance expense-swi The source preview remains revision 5, with both entries `provisional` and reconciliation `awaiting_source`. The articles retain those labels. Max's later instruction to call approved outputs “first estimates” is conditional on the checks passing; it is not an approval of this cached snapshot. -## Before publication +## Historical publication checklist - Complete reconciliation and confirm or replace the provisional population snapshot. - Obtain absolute affected-person counts and separate winner/loser shares when available; preserve disclosure controls. @@ -31,93 +33,93 @@ The source preview remains revision 5, with both entries `provisional` and recon ## Related team work -Pavel's [Pension Tax Allowance draft, #1457](https://github.com/PolicyEngine/policyengine-app-v2/pull/1457), and [fuel-duty draft, #1459](https://github.com/PolicyEngine/policyengine-app-v2/pull/1459), informed the calculation-first presentation, explicit assumptions and separation of Treasury costings from model results. They were read as comparative examples, not formally approved by this review. The earlier drafts used native bar charts. The current alignment reuses their shared numeric line renderer from PR1462 for the household curves. +The [Pension Tax Allowance draft, #1457](https://github.com/PolicyEngine/policyengine-app-v2/pull/1457) and [fuel-duty draft, #1459](https://github.com/PolicyEngine/policyengine-app-v2/pull/1459) informed the calculation-first presentation, explicit assumptions and separation of Treasury costings from model results. They were read as comparative examples, not formally approved by this review. The earlier drafts used native bar charts. The current alignment reuses the shared numeric line renderer from PR #1462 for the household curves. -## Follow-up to Max's reviews +## Historical follow-up to the editorial reviews -Max's trading review is [comment6472758764](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472758764); savings/property is [comment6472939282](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472939282), with calculator alignment in [comment6473177137](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6473177137). +Max's trading review is [comment 6472758764](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472758764); savings/property is [comment 6472939282](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472939282), with calculator alignment in [comment 6473177137](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6473177137). Addressed in the next draft revision: - Whole-pound prose/summary tables; pence retained in worked calculations and exact source records. - National headlines; England explicitly named for the mortgaged landlord; government reach figures explained with their different denominators. - Clearer source citations and reader-facing methods; build-status fields, identifiers and review history retained here and in provenance rather than the article text. -- The UC parent and full-time sole trader are reproduced by `generate_trading_extensions.py`: five pairs passed. The £4,000-receipts parent gains £180 after £220 of UC withdrawal; the sole trader gains £520 including £120 Class4. -- For the specified £18,000-wage parent at £1,500 receipts, the gain is £45 (tax−£100, UC−£55). Max's £79 case needs exact inputs to resolve; it was not copied into the article. +- The UC parent and full-time sole trader are reproduced by `generate_trading_extensions.py`: five pairs passed. The £4,000-receipts parent gains £180 after £220 of UC withdrawal; the sole trader gains £520 including £120 Class 4. +- For the specified £18,000-wage parent at £1,500 receipts, the gain is £45 (tax −£100, UC −£55). Max's £79 case needs exact inputs to resolve; it was not copied into the article. - Missing-receipts examples demonstrate £300 instead of £100 of tax relief for the small trader, and £0 instead of £520 of tax/NI savings for the sole trader. -- The calculator salary comparison is recorded in `dashboard_salary_comparison.json`: the pinned March earnings index grows a £45,000 2026 salary to about £46,080 in2027; taxes round to£9,014/£9,164, change£150. The article's fixed2027salary remains£45,000, taxes£8,582/£8,732. No finance-cost calculator input exists. -- Companion household-preset work is dashboard [PR292](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/292). At checked head65ea750a, the £45k/£6k/£2k recommendation had not yet replaced its older preset. No unsupported preset deep link is used. +- The calculator salary comparison is recorded in `dashboard_salary_comparison.json`: the pinned March earnings index grows a £45,000 2026 salary to about £46,080 in 2027; taxes round to £9,014/£9,164, change £150. The article's fixed 2027 salary remains £45,000, taxes £8,582/£8,732. No finance-cost calculator input exists. +- Companion household-preset work is dashboard [PR #292](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/292). At checked head `65ea750a`, the £45k/£6k/£2k recommendation had not yet replaced its older preset. No unsupported preset deep link is used. Still needed before publication: -- Final population regeneration, with a component CSV/receipt binding the exact dataset bytes and updated forecast. Max's earlier ad32af7f run reproduces the saved first estimates but does not supply those component artifacts. His later correction on dashboard#290 calls for detailed October forecast tables and council tax in the final regeneration. The dataset pin has not changed automatically. -- Weighted tax/benefit totals and household counts by decile. Person-weighted deciles with household-weighted cash means do not justify dividing one mean by the sum of means to claim a48% revenue share. +- Final population regeneration, with a component CSV/receipt binding the exact dataset bytes and updated forecast. Max's earlier ad32af7f run reproduces the saved first estimates but does not supply those component artifacts. His later correction on dashboard #290 calls for detailed October forecast tables and council tax in the final regeneration. The dataset pin has not changed automatically. +- Weighted tax/benefit totals and household counts by decile. Person-weighted deciles with household-weighted cash means do not justify dividing one mean by the sum of means to claim a 48% revenue share. - A bottom-decile income-source breakdown explaining its higher average loss; no cause has been inferred. -- Max's internal260,000-person income-tax count and£71m miscellaneous-income sensitivity need scripts/aggregate receipts, output definitions and unique source-household support. The latter also needs a single shared trading/miscellaneous allowance and explicit eligibility/expense assumptions; it is not treated as a proven upper bound. These numbers are not added as reproduced results. +- Max's internal 260,000-person income-tax count and £71m miscellaneous-income sensitivity need scripts/aggregate receipts, output definitions and unique source-household support. The latter also needs a single shared trading/miscellaneous allowance and explicit eligibility/expense assumptions; it is not treated as a proven upper bound. These numbers are not added as reproduced results. - Replace preview artifact links when verified public artifacts exist; complete visual preview and editorial review. -The articles remain drafts. Publication approval is separate from readiness for agent review. The trading article will have its own stacked PR, reusing this shared analysis foundation. +At this historical revision, the articles remained drafts. Publication approval was separate from readiness for agent review. The trading article subsequently moved to its own stacked PR, reusing the shared analysis foundation. -## Latest review follow-ups and PR split +## Historical review follow-ups and first PR split -- Savings/property remains draft PR1460. Trading is separate draft PR1463, stacked on1460 for shared analysis. Both link to dashboard292, and the dashboard cross-reference links both articles. -- Max confirmed the savings/property revision at5a70185a in comment6473557134 and withdrew the48% inference. The two remaining requests were precise paragraph citations and final component exports. -- Official Budget PDF physical page142 was checked for paragraphs6.246/6.247 and6.254; physical45 contains paragraph2.50. These are now the rule citations. -- Max's newer trading comment on1463,6473574155, agrees to omit the unsupported260,000 count and£71m sensitivity; the latter ignores the shared allowance. Those figures remain excluded. -- Per that follow-up, only the mutually reproduced£180 UC example is retained in the article. The£1,500 diagnostic pair remains in the raw analysis record, with both input sets distinguished, rather than presented as an explained cross-run comparison. -- The trading lead example is named Alex and remains first: age35, salary30k, receipts4k, costs500, tax reduction400. UC and full-time self-employment are additional examples. -- A fresh complete pass covered all five Max conversation comments on1460 and the follow-up on1463, including edits through15:45:19UTC. Both PRs had no inline review threads or submitted reviews in that pass. +- At this historical revision, savings/property was draft PR #1460, and trading was separate draft PR #1463, stacked on #1460 for shared analysis. Both linked to dashboard PR #292. Property and savings were split later, as recorded above. +- Max confirmed the savings/property revision at `5a70185a` in comment 6473557134 and withdrew the 48% inference. The two remaining requests were precise paragraph citations and final component exports. +- Official Budget PDF physical page 142 was checked for paragraphs 6.246/6.247 and 6.254; physical page 45 contains paragraph 2.50. These are now the rule citations. +- Max's newer trading comment on #1463, 6473574155, agrees to omit the unsupported 260,000 count and £71m sensitivity; the latter ignores the shared allowance. Those figures remain excluded. +- Per that follow-up, only the mutually reproduced £180 UC example is retained in the article. The £1,500 diagnostic pair remains in the raw analysis record, with both input sets distinguished, rather than presented as an explained cross-run comparison. +- The trading lead example is named Alex and remains first: age 35, salary £30,000, receipts £4,000, costs £500, tax reduction £400. UC and full-time self-employment are additional examples. +- A fresh complete pass covered all five Max conversation comments on #1460 and the follow-up on #1463, including edits through 15:45:19 UTC. Both PRs had no inline review threads or submitted reviews in that pass. ## Rounding correction at 16:01 UTC -Max's latest comments on PR1460 (6473972686) and PR1463 (6473966614) supersede the earlier permission to retain pence in worked tables. Reader-facing tables now use whole pounds throughout; pence are permitted only in prose spelling out a formula. Exact model outputs and hashed source files retain their original precision. The rounded band-crossing components still sum to£8,582/£8,732, and the rounded sole-trader totals remain£1,672/£1,152, a£520 change. +Max's latest comments on PR #1460 (6473972686) and PR #1463 (6473966614) supersede the earlier permission to retain pence in worked tables. Reader-facing tables now use whole pounds throughout; pence are permitted only in prose spelling out a formula. Exact model outputs and hashed source files retain their original precision. The rounded band-crossing components still sum to £8,582/£8,732, and the rounded sole-trader totals remain £1,672/£1,152, a £520 change. -The dashboard now defines property and savings as separate measures. The article can continue to analyse them together, but a new measure definition is not a substitute for published execution-bound component outputs. The old first-estimate snapshot remains identified by its original measure IDs until replacement data are verified. +At this stage, the dashboard defined property and savings as separate measures while the article still analysed them together. The article was subsequently split. A new measure definition was not a substitute for published execution-bound component outputs. The old first-estimate snapshot remains identified by its original measure IDs until replacement data are verified. -## Live-source check at16:04UTC +## Historical source check at 16:04 UTC -Preview manifest revision15 (updated16:01:00Z) has no property_income_rates_up or savings_income_rates_up artifacts yet. The old combined result is withdrawn because the measure was split; its archived snapshot remains in the analysis records. A newer trading artifact71f8a26e4f547021 is provisional and failed reconciliation. It uses the same certifieda6299504 dataset and detailed October forecasts, but its source still excludes the council-tax update. Neither it nor Max's rounded internal component figures has replaced the saved first-estimate data. +Preview manifest revision 15 (updated 16:01:00Z) has no property_income_rates_up or savings_income_rates_up artifacts yet. The old combined result is withdrawn because the measure was split; its archived snapshot remains in the analysis records. A newer trading artifact `71f8a26e4f547021` is provisional and failed reconciliation. It uses the same certified `a6299504` dataset and detailed October forecasts, but its source still excludes the council-tax update. Neither it nor Max's rounded internal component figures has replaced the saved first-estimate data. The drafts now explicitly flag the older national snapshot as awaiting replacement. These national sections must not be treated as current approved dashboard outputs or published until replacement execution-bound results are reconciled. Household calculations and their input/output records are unchanged. -## Alignment with Pavel’s current PTA draft +## Historical alignment with the Pension Tax Allowance draft -The user requested the same methodology and styling as Pavel’s PTA PR1457. The reference was read at head `d282ef870176c81feb87175d02584121bdc50197`, whose chart dependency is PR1462. The main article structure follows rules, household examples and curves, population impacts, assumptions and limitations, then methodology. The shared numeric line renderer is reused rather than copied. +The user requested the same methodology and styling as the Pension Tax Allowance analysis in PR #1457. The reference was read at head `d282ef870176c81feb87175d02584121bdc50197`, whose chart dependency is PR #1462. The main article structure follows rules, household examples and curves, population impacts, assumptions and limitations, then methodology. The shared numeric line renderer is reused rather than copied. Both synthetic generators now apply the exact October forecast used by that PTA revision (dashboard commit `640426575270224db9b04d6c94d30e264a347be2`) to the baseline and the isolated reform. Previously the synthetic examples held incomes fixed but retained the model’s March parameter forecast. These are distinct choices: the inputs still stay fixed, while projected model parameters now use the common October overlay. The forecast’s original JSON is saved and hash-checked, and the complete eight-path parameter mapping was compared with the original source’s `with_forecast(None)` for exact equality. The archived national results are not regenerated or relabelled by this household change. -Charts now show numeric axes, £ formatting and named allowance thresholds using Pavel’s PR1462 renderer. Display points include every £100 plus exact breakpoints, including the 75%-expense choice at £1,333⅓ of trading receipts. Both tax scenarios are independently checked against arithmetic at every £2, and linear interpolation of the displayed data is compared with the model changes to a one-penny tolerance. Counts and measured maximum errors are saved in `curve-validation.json`. Max’s latest instruction to use whole pounds in all reader-facing tables remains in force. +Charts now show numeric axes, £ formatting and named allowance thresholds using the PR #1462 renderer. Display points include every £100 plus exact breakpoints, including the 75%-expense choice at £1,333⅓ of trading receipts. Both tax scenarios are independently checked against arithmetic at every £2, and linear interpolation of the displayed data is compared with the model changes to a one-penny tolerance. Counts and measured maximum errors are saved in `curve-validation.json`. Max’s latest instruction to use whole pounds in all reader-facing tables remains in force. -Manifest revision17, updated16:09:01.451619UTC, publishes separate property (`3537bd303ac226cf`) and savings (`af6aaaee33f616ee`) artifacts, but both are provisional and fail reconciliation, as does the newer trading artifact. No replacement is adopted. Max’s16:10 webinar guidance is to use available dashboard figures and say other figures are “still being checked”; the saved older estimates are not cleared for spoken or published headline results by that message. +Manifest revision 17, updated 16:09:01.451619 UTC, publishes separate property (`3537bd303ac226cf`) and savings (`af6aaaee33f616ee`) artifacts, but both are provisional and fail reconciliation, as does the newer trading artifact. No replacement is adopted. The 16:10 webinar guidance is to use available dashboard figures and say other figures are “still being checked”; the saved older estimates are not cleared for spoken or published headline results by that message. -The rerun completed at16:18:33UTC with all23 main household comparisons and all5 trading extension pairs passing. Every policy delta is unchanged. The Scottish income-tax levels change by−£2.93 in baseline and reform, while the UC parent’s total benefits and net income change by about+£20.10 in both; these level changes are retained in raw outputs. UC levels and the£180 and£520 article examples are unchanged. The generated curves contain46 savings points and47 trading points. At2,251 income points per series,18,008 liability comparisons and9,004 chart-interpolation comparisons pass; the maximum interpolation error is£0.0033, below the one-penny tolerance. Both generated line specs are ready to insert into the separate articles. Python compilation and diff-whitespace checks also passed. No population outputs or source artifacts were changed. +The rerun completed at 16:18:33 UTC with all 23 main household comparisons and all 5 trading extension pairs passing. Every policy delta is unchanged. The Scottish income-tax levels change by −£2.93 in baseline and reform, while the UC parent’s total benefits and net income change by about +£20.10 in both; these level changes are retained in raw outputs. UC levels and the £180 and £520 article examples are unchanged. The generated curves contain 46 savings points and 47 trading points. At 2,251 income points per series, 18,008 liability comparisons and 9,004 chart-interpolation comparisons pass; the maximum interpolation error is £0.0033, below the one-penny tolerance. Both generated line specs are ready to insert into the separate articles. Python compilation and diff-whitespace checks also passed. No population outputs or source artifacts were changed. ### PTA presentation alignment validation -Both posts now use the shared line-chart renderer from app-v2 PR1462, the same dependency as Pavel's PTA PR1457. The savings/property PR is stacked on `pavel/blog-line-chart`; the trading PR remains stacked on the savings/property branch. The posts share rules, household impacts, population impacts, assumptions and limitations, and methodology sections. All reader tables use whole pounds. +Both posts now use the shared line-chart renderer from app-v2 PR #1462, the same dependency as the Pension Tax Allowance analysis in PR #1457. The savings/property PR is stacked on `pavel/blog-line-chart`; the trading PR remains stacked on the savings/property branch. The posts share rules, household impacts, population impacts, assumptions and limitations, and methodology sections. All reader tables use whole pounds. The line renderer, bar renderer, article-chart parser and post metadata checks passed (51 tests); website ESLint and TypeScript checks passed. No CI monitoring was performed. The 23 household cases, five extension pairs and dense curve checks passed on the pinned October forecast. Browser approval declined the public dashboard preview origin, so its rendered policy tab and the final visual layout were not verified in this pass. No alternative access to that blocked origin was attempted. Max's 16:18:54 UTC webinar update asks authors to introduce each measure for 30–60 seconds: say what it does and who it reaches, leaving costings to the dashboard. Q&A should use displayed dashboard figures and describe missing figures as still being checked. The archived national figures in these draft articles are not webinar-approved estimates. -## Remaining review comments addressed on 28 October +## Historical review comments addressed on 28 October Historical review record: the combined article's Treasury total and mixed £120 property / £30 savings paragraph described below were superseded by the 28 October 2026 split. Property-only PR #1460 no longer contains those combined figures; savings is a separate draft in #1466. The older combined records remain here for reproducibility, and current publication status is tracked on each PR. -The savings/property article removes the withdrawn combined national snapshot, its model fiscal row, decile table and affected share. Its key figures and national table now contain Treasury costings only, separated into property and savings with the combined official total. The archived data and earlier review records remain here for reproducibility; they are not current article results. This follows the cut-or-match-final-run rule Max applied in trading commits8751cf29 andc78cdd60, without substituting unverified replacement figures. +The savings/property article removes the withdrawn combined national snapshot, its model fiscal row, decile table and affected share. Its key figures and national table now contain Treasury costings only, separated into property and savings with the combined official total. The archived data and earlier review records remain here for reproducibility; they are not current article results. This follows the cut-or-match-final-run rule Max applied in trading commits `8751cf29` and `c78cdd60`, without substituting unverified replacement figures. -The mixed-income paragraph now confirms the dashboard's landlord-45k preset and the £120 property plus£30 savings split. It retains the salary-uprating explanation. Canonical dashboard links use www.policyengine.org/uk/autumn-budget-2026, and publication wording holds before and after the production switch. The model's hypothetical households and chart values are unchanged. +The mixed-income paragraph now confirms the dashboard's landlord-45k preset and the £120 property plus £30 savings split. It retains the salary-uprating explanation. Canonical dashboard links use www.policyengine.org/uk/autumn-budget-2026, and publication wording holds before and after the production switch. The model's hypothetical households and chart values are unchanged. -The Treasury comparison now cites HMRC's payments-on-account guidance and ONS public-finance methodology6.1.2: prior-year instalments, the31January2029 balancing payment and first subsequent-year payment explain why same-year tax liability and early-year receipts require a collection bridge. No fitted cash share or illustrative bridge is published as an independently verified result. Property's timing issue does not establish the source of the savings shortfall. Dashboard review6475368627 recommends marking property2027–28 and2028–29 not comparable; its final-regeneration freeze remains separate from these prose edits. +The Treasury comparison now cites HMRC's payments-on-account guidance and ONS public-finance methodology section 6.1.2: prior-year instalments, the 31 January 2029 balancing payment and first subsequent-year payment explain why same-year tax liability and early-year receipts require a collection bridge. No fitted cash share or illustrative bridge is published as an independently verified result. Property's timing issue does not establish the source of the savings shortfall. Dashboard review comment 6475368627 recommends marking property 2027–28 and 2028–29 not comparable; its final-regeneration freeze remains separate from these prose edits. -Trading inline4403534071 is implemented: an excluded employer/connected-party payment removes allowance relief for the whole tax year across relevant sources, with spouse/civilpartner, connected-partnership and company conditions. Inline4403569478's dashboard-introduction suggestion is also implemented. Primary HMRC/ITTOIA sources were checked. Max's direct edits and all household/table/chart values are retained. +Trading inline comment 4403534071 is implemented: an excluded employer/connected-party payment removes allowance relief for the whole tax year across relevant sources, with spouse or civil partner, connected-partnership and company conditions. Inline comment 4403569478's dashboard-introduction suggestion is also implemented. Primary HMRC/ITTOIA sources were checked. Max's direct edits and all household/table/chart values are retained. -Both PRs remain drafts at the user's explicit request. No merge authorization is given by implementing review comments. +At this historical revision, both PRs remained drafts at the user's request. Implementing those review comments did not grant merge authorization; current status is tracked on each PR. -Validation after these edits and the main-branch metadata merge: make format, make lint, make typecheck and make test passed on Node26.12.1. App:6,042passed/10existing skips; website:529passed; total6,571passed. Existing household-table rows and line-chart JSON compare identically with the previous head. Every main-branch post metadata entry is preserved. No model or generator changes were required, and no CI monitoring was performed. +Validation after these edits and the main-branch metadata merge: make format, make lint, make typecheck and make test passed on Node 26.12.1. App: 6,042 passed / 10 existing skips; website: 529 passed; total 6,571 passed. Existing household-table rows and line-chart JSON compare identically with the previous head. Every main-branch post metadata entry is preserved. No model or generator changes were required, and no CI monitoring was performed. diff --git a/analysis/uk-budget-2026-income-tax/property-population/README.md b/analysis/uk-budget-2026-income-tax/property-population/README.md new file mode 100644 index 000000000..0e2eb4615 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/property-population/README.md @@ -0,0 +1,37 @@ +# Property-only population results + +This folder supports the property article in PR #1460. It retains the approved property-only national results from dashboard PR #290 at immutable commit `637bb26c34264e0491ed182c363df751466458ed`. + +These are approved **branch-snapshot** results. The snapshot has not been independently verified as the production deployment. Before merging the article, compare the final released dashboard's property artifact identity and figures with this record, and update the article if they differ. The article's new population section also requires review at its new head. + +## Source and verification + +- Manifest revision: 14. +- Measure and artifact: `property_income_rates_up/7bf77b35e33233e0`. +- Generation commit: `4de166f05eebbc7e501fcf39206cdc82fd199213`; the later snapshot commit does not mean that the simulation was regenerated. +- Runtime: `policyengine` 6.11.1, PolicyEngine UK 2.151.0, core 3.33.3. +- Certified national dataset: `microcosm-uk-2024-25-national-20261025T091414Z-a6299504`, SHA256 `b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e`. +- Baseline and reform use the detailed October 2026 forecast. The reform changes only the property-income measure, including finance-cost relief. + +The canonical receipt validator returned no document or dashboard problems. The artifact, receipt, outputs, execution identity and approval digests match the manifest; all eight source CSV hashes match the receipt. Reconciliation is `pass`, responsiveness is `responsive`, and disclosure checking records a three-survey-household floor with no thin or withheld cells. `summary.json` retains the exact checks, source URLs, values and definitions. The retained receipt and four CSVs are public national aggregates; no household records or population H5 are stored here. + +## Files and definitions + +- `budgetary_impact.csv`: annual reform-minus-baseline government balance, in £ billion. This includes tax and spending interactions and is not income tax alone. +- `winners_losers.csv`: despite its name, it contains household-weighted **mean income changes**, not winner/loser counts or shares. The article's chart uses the 2027 and 2031 decile means, retaining raw precision and rendering whole pounds. +- `distributional_impact.csv`: change in aggregate household net income divided by aggregate baseline household net income within each decile, as a percentage. It is not the mean of household percentage changes. +- `metrics.csv`: includes the affected-population measure. For 2027–28, 5.9436116% of people live in households whose absolute relative household-income change exceeds 0.01%. The calculation uses at least £1 of baseline household income and restricts the population to valid baseline deciles. It counts either direction, not only tax increases or losses. No taxpayer count, affected-household count, or separate winner/loser shares are available in these exports. + +Decile ranks are recomputed for each year from baseline, person-weighted equivalised HBAI household net income before housing costs. Negative ranking income is reset to zero, and equal-income households share a rank. The displayed averages are annual, unequivalised household-net-income changes over **all households** in each decile, including those unaffected. No top-decile revenue share is inferred from these means. + +The official comparison marks 2027–28 and 2028–29 as not comparable; its comparison values are null. The source Treasury table separately reports £35 million and £575 million, which the article shows with those flags. Later-year Treasury values are £435 million, £445 million and £455 million. All article values round only for presentation. + +## Immutable sources + +- [Approved manifest](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/public/data/manifest.json). +- [Property receipt and aggregate CSVs](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/tree/637bb26c34264e0491ed182c363df751466458ed/public/data/artifacts/property_income_rates_up/7bf77b35e33233e0). +- [Official comparison flags](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/public/data/official_costings.json). +- [Treasury row 61 source values](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/data_inputs/treasury/sources/AB2026-T6.1.csv). +- [National calculator definitions](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/src/uk_budget_data/calculators.py). + +The other four source CSVs are not copied because the article does not use them; their hashes remain in the original receipt and verification summary. This folder supersedes the old combined preview for the property article only. The historical `population-preview/` folder remains unchanged and must not be relabelled as this property-only result. diff --git a/analysis/uk-budget-2026-income-tax/property-population/budgetary_impact.csv b/analysis/uk-budget-2026-income-tax/property-population/budgetary_impact.csv new file mode 100644 index 000000000..91bc389a5 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/property-population/budgetary_impact.csv @@ -0,0 +1,7 @@ +reform_id,reform_name,year,value +property_income_rates_up,Property income tax rates up,2026,0.0 +property_income_rates_up,Property income tax rates up,2027,0.39904530993807763 +property_income_rates_up,Property income tax rates up,2028,0.41197579165650017 +property_income_rates_up,Property income tax rates up,2029,0.4294018583620151 +property_income_rates_up,Property income tax rates up,2030,0.4455556472126524 +property_income_rates_up,Property income tax rates up,2031,0.4594904420641682 diff --git a/analysis/uk-budget-2026-income-tax/property-population/distributional_impact.csv b/analysis/uk-budget-2026-income-tax/property-population/distributional_impact.csv new file mode 100644 index 000000000..d57134cf7 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/property-population/distributional_impact.csv @@ -0,0 +1,61 @@ +reform_id,reform_name,year,decile,value +property_income_rates_up,Property income tax rates up,2026,10th,0.0 +property_income_rates_up,Property income tax rates up,2026,1st,0.0 +property_income_rates_up,Property income tax rates up,2026,2nd,0.0 +property_income_rates_up,Property income tax rates up,2026,3rd,0.0 +property_income_rates_up,Property income tax rates up,2026,4th,0.0 +property_income_rates_up,Property income tax rates up,2026,5th,0.0 +property_income_rates_up,Property income tax rates up,2026,6th,0.0 +property_income_rates_up,Property income tax rates up,2026,7th,0.0 +property_income_rates_up,Property income tax rates up,2026,8th,0.0 +property_income_rates_up,Property income tax rates up,2026,9th,0.0 +property_income_rates_up,Property income tax rates up,2027,10th,-0.03642741783840644 +property_income_rates_up,Property income tax rates up,2027,1st,-0.003280773264211483 +property_income_rates_up,Property income tax rates up,2027,2nd,-0.013350311964002826 +property_income_rates_up,Property income tax rates up,2027,3rd,-0.011525877414268887 +property_income_rates_up,Property income tax rates up,2027,4th,-0.011279160134081867 +property_income_rates_up,Property income tax rates up,2027,5th,-0.008254816852157155 +property_income_rates_up,Property income tax rates up,2027,6th,-0.011073457809747176 +property_income_rates_up,Property income tax rates up,2027,7th,-0.013220674146739093 +property_income_rates_up,Property income tax rates up,2027,8th,-0.022890621117303365 +property_income_rates_up,Property income tax rates up,2027,9th,-0.028773800606848924 +property_income_rates_up,Property income tax rates up,2028,10th,-0.03682928346233305 +property_income_rates_up,Property income tax rates up,2028,1st,-0.00396262869494753 +property_income_rates_up,Property income tax rates up,2028,2nd,-0.014058514806218834 +property_income_rates_up,Property income tax rates up,2028,3rd,-0.012221464774932082 +property_income_rates_up,Property income tax rates up,2028,4th,-0.01059609327640011 +property_income_rates_up,Property income tax rates up,2028,5th,-0.008768780707967789 +property_income_rates_up,Property income tax rates up,2028,6th,-0.009981645101563434 +property_income_rates_up,Property income tax rates up,2028,7th,-0.014231064030165044 +property_income_rates_up,Property income tax rates up,2028,8th,-0.023066587924497953 +property_income_rates_up,Property income tax rates up,2028,9th,-0.028403468574895112 +property_income_rates_up,Property income tax rates up,2029,10th,-0.037463291687989404 +property_income_rates_up,Property income tax rates up,2029,1st,-0.00462627376162737 +property_income_rates_up,Property income tax rates up,2029,2nd,-0.014419047872334282 +property_income_rates_up,Property income tax rates up,2029,3rd,-0.012040446785788873 +property_income_rates_up,Property income tax rates up,2029,4th,-0.009427296076210491 +property_income_rates_up,Property income tax rates up,2029,5th,-0.011131388435235272 +property_income_rates_up,Property income tax rates up,2029,6th,-0.006430151305216017 +property_income_rates_up,Property income tax rates up,2029,7th,-0.017949330941909994 +property_income_rates_up,Property income tax rates up,2029,8th,-0.02299527301085211 +property_income_rates_up,Property income tax rates up,2029,9th,-0.028798712554661515 +property_income_rates_up,Property income tax rates up,2030,10th,-0.03773594112904485 +property_income_rates_up,Property income tax rates up,2030,1st,-0.006202837895635574 +property_income_rates_up,Property income tax rates up,2030,2nd,-0.014112826863091262 +property_income_rates_up,Property income tax rates up,2030,3rd,-0.013047267766294033 +property_income_rates_up,Property income tax rates up,2030,4th,-0.009417348651021297 +property_income_rates_up,Property income tax rates up,2030,5th,-0.011329984886564396 +property_income_rates_up,Property income tax rates up,2030,6th,-0.004905744274060609 +property_income_rates_up,Property income tax rates up,2030,7th,-0.019269608517530193 +property_income_rates_up,Property income tax rates up,2030,8th,-0.023458041818215283 +property_income_rates_up,Property income tax rates up,2030,9th,-0.028992003379557544 +property_income_rates_up,Property income tax rates up,2031,10th,-0.03787213684431531 +property_income_rates_up,Property income tax rates up,2031,1st,-0.007485439939025164 +property_income_rates_up,Property income tax rates up,2031,2nd,-0.013468208570510315 +property_income_rates_up,Property income tax rates up,2031,3rd,-0.013115738483115622 +property_income_rates_up,Property income tax rates up,2031,4th,-0.00963653500158797 +property_income_rates_up,Property income tax rates up,2031,5th,-0.011316030290009606 +property_income_rates_up,Property income tax rates up,2031,6th,-0.004412148335646833 +property_income_rates_up,Property income tax rates up,2031,7th,-0.01972931434903989 +property_income_rates_up,Property income tax rates up,2031,8th,-0.02405452667513538 +property_income_rates_up,Property income tax rates up,2031,9th,-0.028820511996950758 diff --git a/analysis/uk-budget-2026-income-tax/property-population/metrics.csv b/analysis/uk-budget-2026-income-tax/property-population/metrics.csv new file mode 100644 index 000000000..3c35946fb --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/property-population/metrics.csv @@ -0,0 +1,7 @@ +reform_id,reform_name,year,people_affected,gini_change,poverty_change_pp,poverty_change_pct +property_income_rates_up,Property income tax rates up,2026,0.0,0.0,0.0,0.0 +property_income_rates_up,Property income tax rates up,2027,5.943611604537077,-0.00012268724460114496,0.0013589859,0.009870348 +property_income_rates_up,Property income tax rates up,2028,5.952076585287802,-0.00012210013169514702,0.00080776215,0.0059420434 +property_income_rates_up,Property income tax rates up,2029,6.037490519286693,-0.00012215392257318585,0.0013303757,0.009669558 +property_income_rates_up,Property income tax rates up,2030,6.034841349783147,-0.00012083309893889608,0.0019693375,0.014370949 +property_income_rates_up,Property income tax rates up,2031,5.9743860438605845,-0.00012092905458994419,0.0020561218,0.0150401555 diff --git a/analysis/uk-budget-2026-income-tax/property-population/receipt.json b/analysis/uk-budget-2026-income-tax/property-population/receipt.json new file mode 100644 index 000000000..e797e21eb --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/property-population/receipt.json @@ -0,0 +1,174 @@ +{ + "dashboard": { + "basis": { + "calibration": { + "source": "the certified dataset pinned by the installed policyengine bundle: Microcosm UK from policyengine 6.10.1, policyengine-uk-data before it", + "status": "pre_budget", + "vintage": "as pinned by the installed bundle" + }, + "forecast": { + "source": "OBR EFO October 2026", + "status": "updated", + "vintage": "OBR Economic and fiscal outlook, October 2026 (Annex A, Tables A.1 and A.3), applied over policyengine-uk's March 2026 growth rates by src/uk_budget_data/forecast/obr_october_2026.json" + }, + "notes": "The forecast is rebased on the Budget's OBR forecast: every simulation, baseline and reform alike, is built on the October 2026 growth rates in src/uk_budget_data/forecast/obr_october_2026.json (CPI, RPI, average earnings, house prices; the September 2027 CPI gap). Series that file does not list keep the March 2026 path the installed policyengine-uk ships; the receipt records the exact model version." + }, + "composition": null, + "config_baseline": { + "binding": "content", + "kind": "current_law", + "name": "configured baseline", + "reform_sha256": null, + "representation": null + }, + "data_limits": [], + "data_limits_registry_sha256": "c48a8fe082168969b5c3e6d6689a630c9f47ac64fa9de7efd11a055d2cab1a4b", + "dataset_years": [ + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032 + ], + "description": "From 6 April 2027 the income tax rates on property income rise to 24%, 44% and 49% at the basic, higher and additional rates in England, Wales and Northern Ireland: 2 percentage points above current law, which already includes Budget 2025's rises. Finance cost relief for landlords follows the property basic rate, so rises to 24%, Scottish landlords' included. Incomes are held fixed, with no behavioural response.", + "digests": { + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "outputs_sha256": "6748d5ee971f1b8428186ca778b4bd01ee1320c4e9f7cc67f34b5fc398330d47", + "receipt_sha256": "777e8839f0f7c541229eb281de5fd497819c34c07ebad865456bbb639d4806e6" + }, + "disclosure_floor": { + "checked": true, + "survey_households": 3, + "thin_cells": [], + "thin_cells_in_tables": false, + "withheld_cells": [] + }, + "files": { + "age_impact.csv": "58739a9b47fcb4e76983119c87131e88362375275fbd4fe7d8933f8772c0b02a", + "budgetary_impact.csv": "5c2abf677accb05d3616c2038823aa1a8f22897ce6dd19700a8e0444eb6ba4ec", + "distributional_impact.csv": "ea4e02c19d075a12cf4922fbca80e65cc7fbc0eaf40d6526619f6e18024318b3", + "household_scatter_binned.csv": "287909c485122279e4502489da0962d2452fcd10fda1950cfb857facc4b0751c", + "income_curve.csv": "5d8083b7dfc7782b856fac38f6632258f12c6840ed4c119d72bec7319a740916", + "metrics.csv": "a2b3d8532a12002ea330342a548ba9ef6ef2480ebd693e8716c25ad4262579ee", + "poverty_inequality.csv": "e58160aff8fa5d3d3285889c60e1deebc7ed38f2b9ea7121ad76f3f8681e2fde", + "winners_losers.csv": "25a9145c0873baf8fee612a1340414090b82ff1421839d22f8c23e5272941841" + }, + "generated_at": "2026-10-28T17:10:45.376537+00:00", + "generator_argv": [ + "/private/tmp/claude-501/-Users-vahid/59114aef-a9b7-4663-a8bc-32b2c6146551/scratchpad/final/property_income_rates_up/src/uk_budget_data/cli.py", + "generate", + "--artifacts", + "--backend", + "modal", + "--reforms", + "property_income_rates_up" + ], + "git_sha": "4de166f05eebbc7e501fcf39206cdc82fd199213", + "key": "property_income_rates_up", + "measure_ids": [ + "property_income_rates_up" + ], + "member_outputs_sha256": null, + "members": null, + "model_limits": [], + "model_limits_registry_sha256": "9d3479f1f5ac859ab6bd2644aaff443a29c0dad3f2944b1ef98866028f9d4b89", + "modifier_templates": { + "baseline": [], + "reform": [] + }, + "name": "Property income tax rates up", + "publishable": true, + "reasons": [], + "receipt_source": "policyengine==6.11.1", + "tree_clean": true, + "unsupported_years": [] + }, + "execution_receipt": { + "baseline": { + "binding": "content", + "kind": "current_law", + "name": "property_income_rates_up baseline" + }, + "certificate": { + "bundle_version": "6.11.1", + "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", + "certificate_source": "packaged", + "certified_by": "policyengine.py bundle certification", + "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "certified_for_core_version": "3.33.3", + "certified_for_model_version": "2.151.0", + "compatibility_basis": "built_with_model_package", + "country_id": "uk", + "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" + }, + "certification_status": "certified", + "core": { + "name": "policyengine-core", + "version": "3.33.3" + }, + "country_id": "uk", + "data": { + "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "build_model_version": "2.151.0", + "data_package": "microcosm-data", + "dataset": "microcosm_uk_2024_25", + "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_version": "0.1.0" + }, + "fiscal_year": { + "convention": "uk_fiscal_year", + "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", + "period_start": "04-06", + "year_label": "start_year" + }, + "model": { + "name": "policyengine-uk", + "version": "2.151.0" + }, + "outputs_sha256": "6748d5ee971f1b8428186ca778b4bd01ee1320c4e9f7cc67f34b5fc398330d47", + "receipt_type": "policyengine.execution_receipt", + "reform": { + "binding": "content", + "kind": "reform", + "name": "property_income_rates_up", + "reform_sha256": "d46bf10b10b298db4059d7b6a2dccac7997e09afec0a88542c2059ea70646aa0", + "representation": "policyengine-uk.scenario/v1" + }, + "runtime": { + "platform": "linux", + "python_version": "3.13.3" + }, + "schema_version": 1, + "supported_years": [ + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032 + ], + "wrapper": { + "name": "policyengine", + "version": "6.11.1" + }, + "years": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031 + ] + }, + "schema": "uk-budget-dashboard/artifact-receipt/v1" +} diff --git a/analysis/uk-budget-2026-income-tax/property-population/summary.json b/analysis/uk-budget-2026-income-tax/property-population/summary.json new file mode 100644 index 000000000..31056f3d4 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/property-population/summary.json @@ -0,0 +1,423 @@ +{ + "schema": "property-blog/verified-dashboard-snapshot/v1", + "source": { + "repository": "PolicyEngine/uk-autumn-budget-dashboard-2026", + "snapshot_commit": "637bb26c34264e0491ed182c363df751466458ed", + "snapshot_status": "Approved single-measure artifact in dashboard PR290; not independently verified as a production deployment", + "manifest_revision": 14, + "manifest_sha256": "b26a5bd5542157bd23317befd9f6814f33ca610d53e644de18c06db3de1a3ea3", + "manifest_updated_at": "2026-10-28T18:29:07.541727+00:00", + "manifest_url": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/public/data/manifest.json", + "artifact_path": "artifacts/property_income_rates_up/7bf77b35e33233e0", + "artifact_sha256": "7bf77b35e33233e0f8174f4be78c7bd6e4eca46f95f1f72b100a68f19280dcfd", + "receipt_sha256": "777e8839f0f7c541229eb281de5fd497819c34c07ebad865456bbb639d4806e6", + "outputs_sha256": "6748d5ee971f1b8428186ca778b4bd01ee1320c4e9f7cc67f34b5fc398330d47", + "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", + "receipt_url": "https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/public/data/artifacts/property_income_rates_up/7bf77b35e33233e0/receipt.json", + "approval": { + "artifact_sha256": "7bf77b35e33233e0f8174f4be78c7bd6e4eca46f95f1f72b100a68f19280dcfd", + "at": "2026-10-28T18:29:07.541217+00:00", + "by": "vahid-ahmadi", + "outputs_sha256": "6748d5ee971f1b8428186ca778b4bd01ee1320c4e9f7cc67f34b5fc398330d47" + }, + "generation_commit": "4de166f05eebbc7e501fcf39206cdc82fd199213", + "generated_at": "2026-10-28T17:10:45.376537+00:00", + "basis": { + "calibration": { + "source": "the certified dataset pinned by the installed policyengine bundle: Microcosm UK from policyengine 6.10.1, policyengine-uk-data before it", + "status": "pre_budget", + "vintage": "as pinned by the installed bundle" + }, + "forecast": { + "source": "OBR EFO October 2026", + "status": "updated", + "vintage": "OBR Economic and fiscal outlook, October 2026 (Annex A, Tables A.1 and A.3), applied over policyengine-uk's March 2026 growth rates by src/uk_budget_data/forecast/obr_october_2026.json" + }, + "notes": "The forecast is rebased on the Budget's OBR forecast: every simulation, baseline and reform alike, is built on the October 2026 growth rates in src/uk_budget_data/forecast/obr_october_2026.json (CPI, RPI, average earnings, house prices; the September 2027 CPI gap). Series that file does not list keep the March 2026 path the installed policyengine-uk ships; the receipt records the exact model version." + }, + "versions": { + "wrapper": { + "name": "policyengine", + "version": "6.11.1" + }, + "model": { + "name": "policyengine-uk", + "version": "2.151.0" + }, + "core": { + "name": "policyengine-core", + "version": "3.33.3" + } + }, + "data": { + "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "build_model_version": "2.151.0", + "data_package": "microcosm-data", + "dataset": "microcosm_uk_2024_25", + "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", + "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", + "release_version": "0.1.0" + }, + "fiscal_year": { + "convention": "uk_fiscal_year", + "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", + "period_start": "04-06", + "year_label": "start_year" + } + }, + "verification": { + "canonical_document_problems": [], + "canonical_dashboard_problems": [], + "artifact_digest_matches_manifest": true, + "approval_binds_artifact_and_outputs": true, + "entry_and_receipt_digests_match": true, + "file_hashes": { + "age_impact.csv": { + "sha256": "58739a9b47fcb4e76983119c87131e88362375275fbd4fe7d8933f8772c0b02a", + "verified": true + }, + "budgetary_impact.csv": { + "sha256": "5c2abf677accb05d3616c2038823aa1a8f22897ce6dd19700a8e0444eb6ba4ec", + "verified": true + }, + "distributional_impact.csv": { + "sha256": "ea4e02c19d075a12cf4922fbca80e65cc7fbc0eaf40d6526619f6e18024318b3", + "verified": true + }, + "household_scatter_binned.csv": { + "sha256": "287909c485122279e4502489da0962d2452fcd10fda1950cfb857facc4b0751c", + "verified": true + }, + "income_curve.csv": { + "sha256": "5d8083b7dfc7782b856fac38f6632258f12c6840ed4c119d72bec7319a740916", + "verified": true + }, + "metrics.csv": { + "sha256": "a2b3d8532a12002ea330342a548ba9ef6ef2480ebd693e8716c25ad4262579ee", + "verified": true + }, + "poverty_inequality.csv": { + "sha256": "e58160aff8fa5d3d3285889c60e1deebc7ed38f2b9ea7121ad76f3f8681e2fde", + "verified": true + }, + "winners_losers.csv": { + "sha256": "25a9145c0873baf8fee612a1340414090b82ff1421839d22f8c23e5272941841", + "verified": true + } + }, + "disclosure": { + "checked": true, + "survey_households": 3, + "thin_cells": [], + "thin_cells_in_tables": false, + "withheld_cells": [] + }, + "data_limits": [], + "model_limits": [], + "reconciliation": { + "responsiveness_status": "responsive", + "summary_status": "pass" + } + }, + "definitions": { + "revenue": "Change in weighted government balance: reform gov_balance minus baseline gov_balance. Positive is a government gain. Includes tax and spending interactions; not income tax alone.", + "decile_ranking": "Recomputed from the baseline for each reported year. Deciles of person-weighted equivalised HBAI household net income before housing costs; negative ranking income is reset to zero and equal-income households share a rank.", + "decile_mean": "Weighted mean annual unequivalised household_net_income change among all households in the baseline decile, including unaffected households; household-weighted, not per person and not the mean among affected households.", + "relative_change": "Sum of weighted household income change divided by sum of weighted baseline household income within that year's baseline decile, times100; not the mean of individual percentage changes.", + "reach": "Share of people in households whose absolute change in household_net_income divided by max(baseline household_net_income,GBP1) exceeds0.0001 (0.01%). Numerator and denominator are weighted household size, restricted to baseline household_income_decile>=1. Changes in either direction count.", + "gini_change": "(Reformed Gini minus baseline Gini)/baseline Gini, a relative fraction, using equivalised household_net_income with person weights. This is not a percentage-point change in the Gini coefficient." + }, + "annual_revenue": [ + { + "year": 2026, + "fiscal_year": "2026-27", + "net_government_revenue_bn": 0.0, + "net_government_revenue_million": 0.0, + "rounded_net_government_revenue_million": 0, + "treasury_post_behavioural_revenue_bn": 0.0, + "treasury_post_behavioural_revenue_million": 0.0, + "dashboard_marks_comparable": true, + "relative_difference_pct_if_comparable": null + }, + { + "year": 2027, + "fiscal_year": "2027-28", + "net_government_revenue_bn": 0.39904530993807763, + "net_government_revenue_million": 399.04530993807765, + "rounded_net_government_revenue_million": 399, + "treasury_post_behavioural_revenue_bn": 0.035, + "treasury_post_behavioural_revenue_million": 35.0, + "dashboard_marks_comparable": false, + "relative_difference_pct_if_comparable": null + }, + { + "year": 2028, + "fiscal_year": "2028-29", + "net_government_revenue_bn": 0.41197579165650017, + "net_government_revenue_million": 411.9757916565002, + "rounded_net_government_revenue_million": 412, + "treasury_post_behavioural_revenue_bn": 0.575, + "treasury_post_behavioural_revenue_million": 575.0, + "dashboard_marks_comparable": false, + "relative_difference_pct_if_comparable": null + }, + { + "year": 2029, + "fiscal_year": "2029-30", + "net_government_revenue_bn": 0.4294018583620151, + "net_government_revenue_million": 429.4018583620151, + "rounded_net_government_revenue_million": 429, + "treasury_post_behavioural_revenue_bn": 0.435, + "treasury_post_behavioural_revenue_million": 435.0, + "dashboard_marks_comparable": true, + "relative_difference_pct_if_comparable": -1.286929112180435 + }, + { + "year": 2030, + "fiscal_year": "2030-31", + "net_government_revenue_bn": 0.4455556472126524, + "net_government_revenue_million": 445.5556472126524, + "rounded_net_government_revenue_million": 446, + "treasury_post_behavioural_revenue_bn": 0.445, + "treasury_post_behavioural_revenue_million": 445.0, + "dashboard_marks_comparable": true, + "relative_difference_pct_if_comparable": 0.1248645421690675 + }, + { + "year": 2031, + "fiscal_year": "2031-32", + "net_government_revenue_bn": 0.4594904420641682, + "net_government_revenue_million": 459.49044206416823, + "rounded_net_government_revenue_million": 459, + "treasury_post_behavioural_revenue_bn": 0.455, + "treasury_post_behavioural_revenue_million": 455.0, + "dashboard_marks_comparable": true, + "relative_difference_pct_if_comparable": 0.9869103437732285 + } + ], + "distribution_by_year": { + "2026": { + "average_household_change_gbp": { + "1": 0.0, + "10": 0.0, + "2": 0.0, + "3": 0.0, + "4": 0.0, + "5": 0.0, + "6": 0.0, + "7": 0.0, + "8": 0.0, + "9": 0.0, + "all": 0.0 + }, + "relative_household_income_change_pct": { + "10": 0.0, + "1": 0.0, + "2": 0.0, + "3": 0.0, + "4": 0.0, + "5": 0.0, + "6": 0.0, + "7": 0.0, + "8": 0.0, + "9": 0.0 + }, + "people_living_in_affected_households_percent": 0.0, + "gini_relative_fraction_change": 0.0 + }, + "2027": { + "average_household_change_gbp": { + "1": -0.849537805191413, + "10": -57.73388219873782, + "2": -5.331535772669214, + "3": -5.137292004488854, + "4": -5.459680740488306, + "5": -4.476027967687162, + "6": -6.548908036603635, + "7": -8.616921384043795, + "8": -16.837105996038773, + "9": -25.074336564023735, + "all": -13.620114207766957 + }, + "relative_household_income_change_pct": { + "10": -0.03642741783840644, + "1": -0.003280773264211483, + "2": -0.013350311964002826, + "3": -0.011525877414268887, + "4": -0.011279160134081867, + "5": -0.008254816852157155, + "6": -0.011073457809747176, + "7": -0.013220674146739093, + "8": -0.022890621117303365, + "9": -0.028773800606848924 + }, + "people_living_in_affected_households_percent": 5.943611604537077, + "gini_relative_fraction_change": -0.00012268724460114496 + }, + "2028": { + "average_household_change_gbp": { + "1": -1.0282712839047559, + "10": -59.549155329481145, + "2": -5.715677861175117, + "3": -5.584747370215322, + "4": -5.2512098656084465, + "5": -4.798992223420793, + "6": -6.028070282235387, + "7": -9.481668059696128, + "8": -17.197736512628875, + "9": -25.12637604042441, + "all": -14.00541887387593 + }, + "relative_household_income_change_pct": { + "10": -0.03682928346233305, + "1": -0.00396262869494753, + "2": -0.014058514806218834, + "3": -0.012221464774932082, + "4": -0.01059609327640011, + "5": -0.008768780707967789, + "6": -0.009981645101563434, + "7": -0.014231064030165044, + "8": -0.023066587924497953, + "9": -0.028403468574895112 + }, + "people_living_in_affected_households_percent": 5.952076585287802, + "gini_relative_fraction_change": -0.00012210013169514702 + }, + "2029": { + "average_household_change_gbp": { + "1": -1.2188237707516856, + "10": -61.77850851299002, + "2": -5.906583275815774, + "3": -5.601067991807482, + "4": -4.7320101656624844, + "5": -6.2140821405456865, + "6": -3.9427657667675993, + "7": -12.100268466500745, + "8": -17.448636393663204, + "9": -25.887010061766002, + "all": -14.533926712827615 + }, + "relative_household_income_change_pct": { + "10": -0.037463291687989404, + "1": -0.00462627376162737, + "2": -0.014419047872334282, + "3": -0.012040446785788873, + "4": -0.009427296076210491, + "5": -0.011131388435235272, + "6": -0.006430151305216017, + "7": -0.017949330941909994, + "8": -0.02299527301085211, + "9": -0.028798712554661515 + }, + "people_living_in_affected_households_percent": 6.037490519286693, + "gini_relative_fraction_change": -0.00012215392257318585 + }, + "2030": { + "average_household_change_gbp": { + "1": -1.6599752643717125, + "10": -63.76110972653078, + "2": -5.839922483061514, + "3": -6.16570323447446, + "4": -4.815746712350739, + "5": -6.406727790315784, + "6": -3.079084257142678, + "7": -13.212370865292934, + "8": -18.136158769994683, + "9": -26.507196831273163, + "all": -15.013106871297852 + }, + "relative_household_income_change_pct": { + "10": -0.03773594112904485, + "1": -0.006202837895635574, + "2": -0.014112826863091262, + "3": -0.013047267766294033, + "4": -0.009417348651021297, + "5": -0.011329984886564396, + "6": -0.004905744274060609, + "7": -0.019269608517530193, + "8": -0.023458041818215283, + "9": -0.028992003379557544 + }, + "people_living_in_affected_households_percent": 6.034841349783147, + "gini_relative_fraction_change": -0.00012083309893889608 + }, + "2031": { + "average_household_change_gbp": { + "1": -2.0255155229193846, + "10": -65.56126504216287, + "2": -5.635177868688589, + "3": -6.31798337071894, + "4": -5.009629578700846, + "5": -6.514231403074363, + "6": -2.8345851636943533, + "7": -13.776544201366882, + "8": -19.013018309750667, + "9": -26.922877825449845, + "all": -15.416369573636034 + }, + "relative_household_income_change_pct": { + "10": -0.03787213684431531, + "1": -0.007485439939025164, + "2": -0.013468208570510315, + "3": -0.013115738483115622, + "4": -0.00963653500158797, + "5": -0.011316030290009606, + "6": -0.004412148335646833, + "7": -0.01972931434903989, + "8": -0.02405452667513538, + "9": -0.028820511996950758 + }, + "people_living_in_affected_households_percent": 5.9743860438605845, + "gini_relative_fraction_change": -0.00012092905458994419 + } + }, + "official_comparability": { + "2026": { + "post_behavioural": 0.0, + "static_costing": null + }, + "2027": { + "not_comparable": { + "reason": "Self Assessment tax on 2027-28 property income is mostly paid from 31 January 2029, so the Treasury's costing (on a National Accounts basis) has \u00a335m in 2027-28 and about 1.5 years of liability in 2028-29 (\u00a3575m), while the model scores each tax year's liability. From 2029-30 the two agree within 1.5%. Table 6.1 row 61." + }, + "post_behavioural": null, + "static_costing": null + }, + "2028": { + "not_comparable": { + "reason": "Self Assessment tax on 2027-28 property income is mostly paid from 31 January 2029, so the Treasury's costing (on a National Accounts basis) has \u00a335m in 2027-28 and about 1.5 years of liability in 2028-29 (\u00a3575m), while the model scores each tax year's liability. From 2029-30 the two agree within 1.5%. Table 6.1 row 61." + }, + "post_behavioural": null, + "static_costing": null + }, + "2029": { + "post_behavioural": 0.435, + "static_costing": null + }, + "2030": { + "post_behavioural": 0.445, + "static_costing": null + }, + "2031": { + "post_behavioural": 0.455, + "static_costing": null + } + }, + "unavailable_exports": [ + "Absolute affected-person count", + "Winner and loser shares, either nationally or by decile", + "Average change conditional on being affected", + "Income-source decomposition of the bottom decile", + "Household counts and income-tax/revenue totals by decile for revenue-concentration shares" + ], + "important_limits": [ + "The approved artifact was generated at4de166f0. Its approval in the later snapshot does not prove a new post-freeze simulation or a production deployment.", + "Recheck the property artifact identity against the final released manifest before merging the blog. A changed artifact requires re-extracting and reviewing figures.", + "Do not infer loser counts or extra-taxpayer shares from the affected-household metric.", + "Do not derive revenue shares from decile average household changes without weighted counts/totals.", + "Treasury rows2027/2028 are retained from source for a labelled annual table, but the dashboard comparison deliberately suppresses them as not comparable.", + "Static model, fixed incomes/no incorporation response; Treasury figures include behavioural assumptions and a different collection profile." + ] +} diff --git a/analysis/uk-budget-2026-income-tax/property-population/winners_losers.csv b/analysis/uk-budget-2026-income-tax/property-population/winners_losers.csv new file mode 100644 index 000000000..757099871 --- /dev/null +++ b/analysis/uk-budget-2026-income-tax/property-population/winners_losers.csv @@ -0,0 +1,67 @@ +reform_id,reform_name,year,decile,avg_change +property_income_rates_up,Property income tax rates up,2026,1,0.0 +property_income_rates_up,Property income tax rates up,2026,10,0.0 +property_income_rates_up,Property income tax rates up,2026,2,0.0 +property_income_rates_up,Property income tax rates up,2026,3,0.0 +property_income_rates_up,Property income tax rates up,2026,4,0.0 +property_income_rates_up,Property income tax rates up,2026,5,0.0 +property_income_rates_up,Property income tax rates up,2026,6,0.0 +property_income_rates_up,Property income tax rates up,2026,7,0.0 +property_income_rates_up,Property income tax rates up,2026,8,0.0 +property_income_rates_up,Property income tax rates up,2026,9,0.0 +property_income_rates_up,Property income tax rates up,2026,all,0.0 +property_income_rates_up,Property income tax rates up,2027,1,-0.849537805191413 +property_income_rates_up,Property income tax rates up,2027,10,-57.73388219873782 +property_income_rates_up,Property income tax rates up,2027,2,-5.331535772669214 +property_income_rates_up,Property income tax rates up,2027,3,-5.137292004488854 +property_income_rates_up,Property income tax rates up,2027,4,-5.459680740488306 +property_income_rates_up,Property income tax rates up,2027,5,-4.476027967687162 +property_income_rates_up,Property income tax rates up,2027,6,-6.548908036603635 +property_income_rates_up,Property income tax rates up,2027,7,-8.616921384043795 +property_income_rates_up,Property income tax rates up,2027,8,-16.837105996038773 +property_income_rates_up,Property income tax rates up,2027,9,-25.074336564023735 +property_income_rates_up,Property income tax rates up,2027,all,-13.620114207766957 +property_income_rates_up,Property income tax rates up,2028,1,-1.0282712839047559 +property_income_rates_up,Property income tax rates up,2028,10,-59.549155329481145 +property_income_rates_up,Property income tax rates up,2028,2,-5.715677861175117 +property_income_rates_up,Property income tax rates up,2028,3,-5.584747370215322 +property_income_rates_up,Property income tax rates up,2028,4,-5.2512098656084465 +property_income_rates_up,Property income tax rates up,2028,5,-4.798992223420793 +property_income_rates_up,Property income tax rates up,2028,6,-6.028070282235387 +property_income_rates_up,Property income tax rates up,2028,7,-9.481668059696128 +property_income_rates_up,Property income tax rates up,2028,8,-17.197736512628875 +property_income_rates_up,Property income tax rates up,2028,9,-25.12637604042441 +property_income_rates_up,Property income tax rates up,2028,all,-14.00541887387593 +property_income_rates_up,Property income tax rates up,2029,1,-1.2188237707516856 +property_income_rates_up,Property income tax rates up,2029,10,-61.77850851299002 +property_income_rates_up,Property income tax rates up,2029,2,-5.906583275815774 +property_income_rates_up,Property income tax rates up,2029,3,-5.601067991807482 +property_income_rates_up,Property income tax rates up,2029,4,-4.7320101656624844 +property_income_rates_up,Property income tax rates up,2029,5,-6.2140821405456865 +property_income_rates_up,Property income tax rates up,2029,6,-3.9427657667675993 +property_income_rates_up,Property income tax rates up,2029,7,-12.100268466500745 +property_income_rates_up,Property income tax rates up,2029,8,-17.448636393663204 +property_income_rates_up,Property income tax rates up,2029,9,-25.887010061766002 +property_income_rates_up,Property income tax rates up,2029,all,-14.533926712827615 +property_income_rates_up,Property income tax rates up,2030,1,-1.6599752643717125 +property_income_rates_up,Property income tax rates up,2030,10,-63.76110972653078 +property_income_rates_up,Property income tax rates up,2030,2,-5.839922483061514 +property_income_rates_up,Property income tax rates up,2030,3,-6.16570323447446 +property_income_rates_up,Property income tax rates up,2030,4,-4.815746712350739 +property_income_rates_up,Property income tax rates up,2030,5,-6.406727790315784 +property_income_rates_up,Property income tax rates up,2030,6,-3.079084257142678 +property_income_rates_up,Property income tax rates up,2030,7,-13.212370865292934 +property_income_rates_up,Property income tax rates up,2030,8,-18.136158769994683 +property_income_rates_up,Property income tax rates up,2030,9,-26.507196831273163 +property_income_rates_up,Property income tax rates up,2030,all,-15.013106871297852 +property_income_rates_up,Property income tax rates up,2031,1,-2.0255155229193846 +property_income_rates_up,Property income tax rates up,2031,10,-65.56126504216287 +property_income_rates_up,Property income tax rates up,2031,2,-5.635177868688589 +property_income_rates_up,Property income tax rates up,2031,3,-6.31798337071894 +property_income_rates_up,Property income tax rates up,2031,4,-5.009629578700846 +property_income_rates_up,Property income tax rates up,2031,5,-6.514231403074363 +property_income_rates_up,Property income tax rates up,2031,6,-2.8345851636943533 +property_income_rates_up,Property income tax rates up,2031,7,-13.776544201366882 +property_income_rates_up,Property income tax rates up,2031,8,-19.013018309750667 +property_income_rates_up,Property income tax rates up,2031,9,-26.922877825449845 +property_income_rates_up,Property income tax rates up,2031,all,-15.416369573636034 diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index 63d72e763..31820e4fa 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -1,10 +1,11 @@ -The Autumn Budget 2026 increases the basic, higher and additional income tax rates on property income by a further two percentage points from **6 April 2027**, taking them to **24%, 44% and 49%** in England, Wales and Northern Ireland, as [Budget paragraph 6.246](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142) sets out. The property rate increase does not apply to Scottish taxpayers. Because finance-cost relief follows the property basic rate, residential landlords' relief rises too. +The Autumn Budget 2026 announces a further two-percentage-point increase in the basic, higher and additional income tax rates on property income from **6 April 2027**, taking them to **24%, 44% and 49%** in England, Wales and Northern Ireland, as [Budget paragraph 6.246](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142) sets out. The government plans to legislate for the new rates in Finance Bill 2026–27. The property rate increase does not apply to Scottish taxpayers. Because finance-cost relief follows the property basic rate, residential landlords' relief rises too. Key figures for 2027–28: - A landlord in England with £10,000 of property profit and £4,000 of fully usable mortgage interest pays £120 more income tax. - A mortgage-free landlord in England with the same profit pays £200 more. -- A Scottish landlord with £4,000 of fully usable finance costs pays £80 less, because the finance-cost reduction rises while Scottish property tax rates stay unchanged. +- A landlord who lives in Scotland, with £4,000 of fully usable finance costs, pays £80 less income tax. The property income tax rate rise does not apply to Scottish taxpayers, but their finance-cost reduction still rises with the property basic rate. +- PolicyEngine estimates £399 million of additional net government revenue and a £14 reduction in average household net income in 2027–28. - The Treasury forecasts £35 million of additional revenue in 2027–28, £575 million in 2028–29, and £435 million to £455 million a year from 2029–30 to 2031–32. Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for this and the other Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. The Budget also raises savings income tax rates; we will cover that measure separately. @@ -44,36 +45,155 @@ Consider two adults in England, each with £12,000 of rent, £2,000 of allowable Both pay £200 more before relief, while their finance-cost reduction rises by £4,000 × 2% = £80. Their net increase is £200 − £80 = £120. A mortgage-free landlord with the same profit pays £200 more. Both tax bands rise by two points, explaining the identical increases despite different starting liabilities. -The property **rate** increase excludes Scottish taxpayers, whose rental income follows Scottish rules. Finance-cost relief is a separate calculation. The [Finance Act 2026 amendment](https://www.legislation.gov.uk/ukpga/2026/11/schedule/1/paragraph/40/enacted) ties it to the UK property basic rate without a Scottish exception. Applying that rule, a Scottish landlord able to use the full reduction on £4,000 of eligible finance costs receives £80 more relief, reducing their income tax by £80 if nothing else changes. A mortgage-free Scottish landlord has no change from this measure. +The property **rate** increase excludes Scottish taxpayers, whose rental income is taxed under Scottish Income Tax rules. Finance-cost relief is a separate calculation. The [Finance Act 2026 amendment](https://www.legislation.gov.uk/ukpga/2026/11/schedule/1/paragraph/40/enacted) ties it to the UK property basic rate without a Scottish exception. Applying that rule, a Scottish taxpayer who lets property and can use the full reduction on £4,000 of eligible finance costs receives £80 more relief, reducing their income tax by £80 if nothing else changes. A mortgage-free Scottish taxpayer has no change from this measure. -### The dashboard's household example +### A smaller rental profit -[Try the Budget dashboard's calculator](https://www.policyengine.org/uk/autumn-budget-2026?tab=household&policies=property_income_rates_up). Its example labelled “A middle earner who lets a flat” has £6,000 of property income and no mortgage interest. Selecting the property measure alone reduces household income by £120 in 2027–28: £6,000 × 2% = £120. The calculator grows a 2026–27 salary input into the selected year, while the worked examples above hold salary fixed at their stated 2027–28 amounts. +A landlord with a £30,000 salary has already used the Personal Allowance against salary. If they also have £6,000 of taxable property profit after deductions and no eligible finance costs, they pay £120 more income tax in 2027–28: £6,000 × 2% = £120. This property-only calculation holds their income fixed and changes no other Budget measure. -## Treasury costing +## Population impacts -The Treasury's [Table 6.1, row 61](https://www.gov.uk/government/publications/supporting-documents-for-budget-2026) forecasts the following additional Exchequer revenue. These are the Treasury's figures, on a National Accounts basis. +We model the property measure alone on a representative sample of UK households. The [property-only microsimulation results](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/tree/637bb26c34264e0491ed182c363df751466458ed/public/data/artifacts/property_income_rates_up/7bf77b35e33233e0) use the certified Microcosm UK dataset and the OBR's October 2026 forecast. They are static estimates, with no behavioural response. -| Exchequer revenue, £ million | 2026–27 | 2027–28 | 2028–29 | 2029–30 | 2030–31 | 2031–32 | -| --- | ---: | ---: | ---: | ---: | ---: | ---: | -| Property income rates | 0 | 35 | 575 | 435 | 445 | 455 | +### Budgetary impact -**The dashboard marks 2027–28 and 2028–29 as not comparable with the official costing.** PolicyEngine scores each tax year's liabilities in that year. Self Assessment payments on account are normally based on the previous year's tax bill; the balancing payment for 2027–28 is due on 31 January 2029, alongside the first payment on account for 2028–29. [HMRC's payment guidance](https://www.gov.uk/understand-self-assessment-bill/payments-on-account) explains that schedule. +PolicyEngine estimates that the measure raises £399 million of net government revenue in 2027–28, rising to £459 million in 2031–32. The Treasury's [Table 6.1, row 61](https://www.gov.uk/government/publications/supporting-documents-for-budget-2026) reports the official costing on a National Accounts basis. + +| Year | PolicyEngine net government revenue, £ million | Treasury revenue, £ million | Comparison | +| --- | ---: | ---: | --- | +| 2026–27 | 0 | 0 | No modelled policy effect | +| 2027–28 | 399 | 35 | Not comparable | +| 2028–29 | 412 | 575 | Not comparable | +| 2029–30 | 429 | 435 | Later-year comparison | +| 2030–31 | 446 | 445 | Later-year comparison | +| 2031–32 | 459 | 455 | Later-year comparison | + +Positive values are additional revenue. PolicyEngine measures the change in government taxes less spending, including benefit interactions. In 2029–30, its £429 million estimate is £6 million below the Treasury's £435 million. + +**The first two years, 2027–28 and 2028–29, are not comparable without a collection-timing adjustment.** PolicyEngine scores each tax year's liabilities in that year. Self Assessment payments on account are normally based on the previous year's tax bill; the balancing payment for 2027–28 is due on 31 January 2029, alongside the first payment on account for 2028–29. [HMRC's payment guidance](https://www.gov.uk/understand-self-assessment-bill/payments-on-account) explains that schedule. The [ONS public-finance methodology, section 6.1.2](https://www.ons.gov.uk/economy/governmentpublicsectorandtaxes/publicsectorfinance/methodologies/monthlystatisticsonthepublicsectorfinancesamethodologicalguide) records Self Assessment income tax using cash receipts, without shifting them back to the year the income arose. This can produce a small first-year receipts effect followed by a catch-up. Comparing those first two years with same-year model liabilities requires a collection-timing adjustment; it does not by itself establish a difference in the tax base. -The Treasury costing also allows for some landlords incorporating. PolicyEngine's national estimates hold that choice fixed. This article reports household calculations and the Treasury costing; the dashboard carries PolicyEngine's national results and their comparability notes. +The Treasury costing also allows for some landlords incorporating. PolicyEngine holds that choice fixed. Differences in data, behaviour and accounting remain relevant when comparing the later years, even where the rounded estimates are close. + +### Reach and distribution + +In 2027–28, 5.9% of people live in households whose net income changes by more than 0.01% in either direction under the model's affected-population measure. This includes increases and decreases in household income; it is not a count of people paying more property tax. The Scottish finance-cost example above illustrates one way income can rise. + +Across all households, average annual net income falls by £14 in 2027–28 and £15 in 2031–32. In 2027–28, the average reduction ranges from £1 in the lowest income decile to £58 in the highest; in 2031–32, those averages are £2 and £66. + +Income deciles rank people by their household's baseline equivalised net income before housing costs. The analysis calculates rankings separately for each year. The changes below are averages per household in each group, including households whose income does not change. + +| Income decile | Average household net income change, 2027–28 | Average household net income change, 2031–32 | +| --- | ---: | ---: | +| 1 (lowest income) | −£1 | −£2 | +| 2 | −£5 | −£6 | +| 3 | −£5 | −£6 | +| 4 | −£5 | −£5 | +| 5 | −£4 | −£7 | +| 6 | −£7 | −£3 | +| 7 | −£9 | −£14 | +| 8 | −£17 | −£19 | +| 9 | −£25 | −£27 | +| 10 (highest income) | −£58 | −£66 | +| All households | −£14 | −£15 | + +```chart +{ + "type": "bar", + "title": "Average change in household net income by income decile", + "subtitle": "Property income tax measure, all households", + "xKey": "decile", + "series": [ + { + "key": "y2027", + "name": "2027–28", + "color": "negative" + }, + { + "key": "y2031", + "name": "2031–32", + "color": "quinary" + } + ], + "data": [ + { + "decile": "1st", + "y2027": -0.849537805191413, + "y2031": -2.0255155229193846 + }, + { + "decile": "2nd", + "y2027": -5.331535772669214, + "y2031": -5.635177868688589 + }, + { + "decile": "3rd", + "y2027": -5.137292004488854, + "y2031": -6.31798337071894 + }, + { + "decile": "4th", + "y2027": -5.459680740488306, + "y2031": -5.009629578700846 + }, + { + "decile": "5th", + "y2027": -4.476027967687162, + "y2031": -6.514231403074363 + }, + { + "decile": "6th", + "y2027": -6.548908036603635, + "y2031": -2.8345851636943533 + }, + { + "decile": "7th", + "y2027": -8.616921384043795, + "y2031": -13.776544201366882 + }, + { + "decile": "8th", + "y2027": -16.837105996038773, + "y2031": -19.013018309750667 + }, + { + "decile": "9th", + "y2027": -25.074336564023735, + "y2031": -26.922877825449845 + }, + { + "decile": "10th", + "y2027": -57.73388219873782, + "y2031": -65.56126504216287 + } + ], + "yLabel": "Average annual change in net income", + "format": { + "prefix": "£", + "decimals": 0, + "separator": true + }, + "valueLabels": false, + "source": "Source: PolicyEngine UK 2.151.0 microsimulation on the certified Microcosm UK dataset and the OBR's October 2026 forecast." +} +``` ## Assumptions and limitations - The worked examples are hypothetical single adults aged 35. Their income is fixed at the stated 2027–28 amounts. They include no pension contributions, Gift Aid, student loans, property losses, carried-forward finance costs or other reliefs. - The household tables show tax attributable to property income. The mortgage examples assume the full finance-cost reduction can be used. - The Scottish mortgage example applies the existing Finance Act rule linking relief to the UK property basic rate. The Finance Bill will set the final implementation of the new rates. -- The dashboard calculator grows a 2026–27 salary input into the selected year. Its income path differs from fixing the same nominal salary in 2027–28. -- National comparisons need the same income-tax components and collection periods. Benefit changes in a government-balance estimate must also be separated. These household examples do not establish national affected-person counts or distributions. +- National estimates hold households' behaviour fixed. They do not model landlords incorporating in response to the tax change. +- The national affected-population percentage measures people living in households with an income change above the stated threshold. It does not give a taxpayer count or separate shares gaining and losing. +- Population estimates include changes in means-tested benefits. The worked household examples show income tax; a change in benefits can offset part of a household's extra tax. ## Methodology -The household calculations use the `policyengine` Python package (version 6.11.1), PolicyEngine UK (version 2.151.0) and PolicyEngine core (version 3.33.3). The shared generator changes savings and property rates together against the already scheduled 2027–28 rules. The landlord examples in this article have no savings income, so the savings rate change has no effect on them: their tax differences isolate the property changes, including finance-cost relief. The dashboard preset's property-only component was checked separately. Both household scenarios use the OBR’s October 2026 forecast update at dashboard commit `64042657`. Supplied 2027–28 income stays fixed; the forecast updates the model’s projected parameters. Independent arithmetic checks the tax calculations. +The calculations use the `policyengine` Python package (version 6.11.1), PolicyEngine UK (version 2.151.0) and PolicyEngine core (version 3.33.3). + +The household generator changes savings and property rates together against the already scheduled 2027–28 rules. The landlord examples in this article have no savings income, so the savings rate change has no effect on them: their tax differences isolate the property changes, including finance-cost relief. The £6,000 property-only example was checked separately. The baseline and reform household calculations both use the OBR’s October 2026 forecast update. Supplied 2027–28 income stays fixed; the forecast updates the model’s projected parameters. Independent arithmetic checks the tax calculations. + +The population run uses the certified Microcosm UK 2024–25 dataset (`a6299504`) and the detailed October forecast at dashboard commit `4de166f0`, applied to baseline and reform alike. It changes the property measure alone and includes the finance-cost-relief increase. Household net income and government revenue include interactions with the other taxes and benefits in the model. The decile averages are household-weighted means of unequivalised household net income changes; the income ranking uses person-weighted equivalised HBAI income before housing costs. Monetary values are rounded only for presentation. -The [shared analysis files](https://github.com/PolicyEngine/policyengine-app-v2/tree/main/analysis/uk-budget-2026-income-tax) record the household inputs, model versions, forecast settings and validation for the property, savings and trading explainers. Monetary amounts in tables are rounded to whole pounds; the calculation records retain precision. The household calculations use hypothetical people and do not require population microdata. +The [shared analysis files](https://github.com/PolicyEngine/policyengine-app-v2/tree/main/analysis/uk-budget-2026-income-tax) record the household inputs, model versions, forecast settings and validation for the property, savings and trading explainers. The property population records retain the exact source outputs and provenance. Monetary amounts in tables are rounded to whole pounds; the calculation records retain precision. The hypothetical household calculations do not require population microdata. From 3f1cf0656a757bafe0c37d6ed3a3cd60254df25b Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 15:25:52 -0400 Subject: [PATCH 17/24] docs: address property microsimulation review feedback Clarify the timing comparison and landlord residence. Remove internal review notes and uncleared reach, poverty and inequality outputs while retaining verified national revenue and decile results. --- analysis/uk-budget-2026-income-tax/README.md | 8 +- .../uk-budget-2026-income-tax/REVIEW_NOTES.md | 125 ------------------ .../property-population/README.md | 8 +- .../property-population/metrics.csv | 7 - .../property-population/summary.json | 54 ++++---- ...-autumn-budget-2026-property-income-tax.md | 14 +- 6 files changed, 43 insertions(+), 173 deletions(-) delete mode 100644 analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md delete mode 100644 analysis/uk-budget-2026-income-tax/property-population/metrics.csv diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index ee089ffa3..e4a01d480 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -16,19 +16,19 @@ The generator uses hypothetical adults, without population microdata. It records The checked outputs include 23 household comparisons and 93 displayed points across the two income curves. The displayed lines use £100 intervals and the exact policy breakpoints. All four series are independently checked against the model at every £2 from £500 to £5,000, including a comparison of the plotted interpolation with the engine results; `curve-validation.json` records counts and maximum errors. The non-integer £1,333⅓ expense-choice breakpoint is also calculated with the model. To also verify the original dashboard parameter builder, pass `--dashboard-checkout /path/to/checkout` with that checkout at the recorded commit. This check is optional and performs no download. -The `landlord_*` records in `households.json` and `households.csv` support the property article. They have no savings income, so the combined reform's savings rate changes do not affect their results. The dashboard preset's property-only component was checked separately. The `saver_*` and mixed `property_then_savings_order` records, savings curves, and savings-rate and Treasury row 62 metadata in `provenance.json` remain shared records for savings draft #1466; they are not property-only results. +The `landlord_*` records in `households.json` and `households.csv` support the property article. They have no savings income, so the combined reform's savings rate changes do not affect their results. The example with a £30,000 salary, £6,000 of taxable property profit and no eligible finance costs was checked separately with the property-only reform. The `saver_*` and mixed `property_then_savings_order` records, savings curves, and savings-rate and Treasury row 62 metadata in `provenance.json` remain shared records for savings draft #1466; they are not property-only results. The savings draft (#1466) reproduces `savings-interest-chart.json`; the trading article (#1463) reproduces `trading-allowance-chart.json`. The property article's native bar chart uses the verified 2027 and 2031 decile means in `property-population/`. Reinsert each chart's contents only into its corresponding article when regenerating it. ## Current article scope -The property draft now includes national revenue, decile averages and the precisely defined affected-population measure from the approved property-only snapshot in dashboard PR #290. `property-population/` retains the immutable source record, original receipt, four CSVs used by the post and the canonical verification summary. It is an approved branch snapshot, not independently verified as the production deployment. Recheck its identity and figures against the final released dashboard before merging, and have the new article head reviewed. +The property draft now includes national revenue and decile averages from the approved property-only snapshot in dashboard PR #290. `property-population/` retains the immutable source record, original receipt, three aggregate CSVs and the verification summary. Reach, poverty and inequality figures are omitted pending separate disclosure clearance. It is an approved branch snapshot, not independently verified as the production deployment. Recheck its identity and figures against the final released dashboard before merging, and have the new article head reviewed. The savings and trading posts retain household calculations and Treasury costings only. No withdrawn combined national figures have been restored. The `population-preview/` files described below remain historical records; they are not the property-only source now used by the article. ## Dataset decision -Retain the dashboard's adopted `policyengine` 6.11.1 bundle, with UK 2.151.0, core 3.33.3 and national data cut `a6299504`. The certificate, full dataset ID and checksum are recorded in `provenance.json`. The newer candidate in policyengine.py PR725 is awaiting certification/adoption. A future update must change the package and dataset provenance together and regenerate the analysis. +Retain the dashboard's adopted `policyengine` 6.11.1 bundle, with UK 2.151.0, core 3.33.3 and national data cut `a6299504`. The certificate, full dataset ID and checksum are recorded in `provenance.json`. The newer candidate in [policyengine.py PR #725](https://github.com/PolicyEngine/policyengine.py/pull/725) is awaiting certification/adoption. A future update must change the package and dataset provenance together and regenerate the analysis. The household generators need no population microdata. This historical snapshot was retrieved without downloading population microdata. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. The dashboard maintainer subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The analysis records retain its digest-addressed public aggregate outputs as an earlier review snapshot, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. @@ -54,8 +54,6 @@ Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipt The three articles use the site's native tables, chart blocks and cover assets. Household curves use the shared numeric line renderer from [PR #1462](https://github.com/PolicyEngine/policyengine-app-v2/pull/1462); no duplicate chart implementation or country-model code is added. -See `REVIEW_NOTES.md` for the historical draft-readiness checks, comparison with the reference Budget explainers and remaining publication work. - ## Validation on 28 October 2026 `make format`, `make lint`, `make typecheck` and `make test` passed. The tests ran on Node 26.12.1: 6,042 app tests and 508 website tests passed, with 10 app tests skipped by the existing suite. After inserting the final chart data, the chart-parser and post-metadata checks passed again (18 tests). All 23 household comparisons and 20 curve points passed independent arithmetic checks. diff --git a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md b/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md deleted file mode 100644 index ff6a9ee23..000000000 --- a/analysis/uk-budget-2026-income-tax/REVIEW_NOTES.md +++ /dev/null @@ -1,125 +0,0 @@ -# Draft review history and handoff - -This file preserves the chronological review history. Earlier sections describe the combined savings/property article and the trading article while both were in PR #1460; their readiness and publication statements are historical, not current approvals. - -The articles are now separate: property is [PR #1460](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460), trading is [PR #1463](https://github.com/PolicyEngine/policyengine-app-v2/pull/1463), and savings is [PR #1466](https://github.com/PolicyEngine/policyengine-app-v2/pull/1466). Current readiness and publication status are tracked on each PR. The property article's approved national snapshot is documented in `property-population/README.md`; it supersedes the combined preview for that article only. - -## Historical internal readiness check - -An independent policy/source reviewer and code/reproducibility reviewer examined commit `7f90092fa6e6f28f68b419c4edf1bef166d851b9` on 28 October 2026. The review was complete for draft readiness, with no confirmed critical or should-address findings and one optional clarity suggestion. - -- The policy reviewer checked the official Budget, legislation and HMRC guidance, and visually inspected physical pages 23, 74 and 75 of the Treasury costings. The rates, start dates, allowance rules, Scottish finance-cost relief interpretation and Treasury series were corroborated. -- The code reviewer independently reproduced all 23 hypothetical household comparisons and 20 curve points on the pinned bundle. Numeric outputs, CSVs and chart specifications matched the saved results. -- All eight public aggregate CSV hashes matched their receipts. National fiscal signs, decile averages and affected-population percentage units matched the articles. The saved summary reproduced exactly. -- The 18 chart-parser and post-metadata tests passed on the frozen snapshot using Node 26.12.1. The earlier full suite passed 6,550 tests, with 10 existing skips. CI was not monitored. - -The optional suggestion was to name the Treasury's trading-allowance expense-switching response. The follow-up adds that explanation with its physical-page-23 citation. It also adds an explicit savings/property band calculation using the already reproduced `property_then_savings_order` case (£8,582 to £8,732 income tax) and uses the canonical dashboard address shared in the team channel. These are prose and citation changes; model calculations are unchanged. The band table is checked against the saved component and total taxes. - -## Historical review scope - -- Savings/property: income ordering, the transition between basic and higher bands, and the conditional £80 finance-relief gain for Scottish landlords with £4,000 of fully usable finance costs. -- Trading: the receipts-versus-expenses choice, the separate miscellaneous-income coverage limitation and the population approximation when gross receipts are missing. -- Population: the static-model/Treasury comparison and the interpretation of average changes. The producer's `people_affected` field is a percentage of people in households with an absolute income change above 0.01%; it is not a headcount or a separate winner/loser share. - -The source preview remains revision 5, with both entries `provisional` and reconciliation `awaiting_source`. The articles retain those labels. Max's later instruction to call approved outputs “first estimates” is conditional on the checks passing; it is not an approval of this cached snapshot. - -## Historical publication checklist - -- Complete reconciliation and confirm or replace the provisional population snapshot. -- Obtain absolute affected-person counts and separate winner/loser shares when available; preserve disclosure controls. -- Resolve or retain explicit limits for missing trading receipts/expenses and miscellaneous income. -- Complete desktop/mobile visual preview and final editorial review. Browser preview was not verified during this work. -- Link the standalone articles from the dashboard. - -## Related team work - -The [Pension Tax Allowance draft, #1457](https://github.com/PolicyEngine/policyengine-app-v2/pull/1457) and [fuel-duty draft, #1459](https://github.com/PolicyEngine/policyengine-app-v2/pull/1459) informed the calculation-first presentation, explicit assumptions and separation of Treasury costings from model results. They were read as comparative examples, not formally approved by this review. The earlier drafts used native bar charts. The current alignment reuses the shared numeric line renderer from PR #1462 for the household curves. - - -## Historical follow-up to the editorial reviews - -Max's trading review is [comment 6472758764](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472758764); savings/property is [comment 6472939282](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6472939282), with calculator alignment in [comment 6473177137](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6473177137). - -Addressed in the next draft revision: - -- Whole-pound prose/summary tables; pence retained in worked calculations and exact source records. -- National headlines; England explicitly named for the mortgaged landlord; government reach figures explained with their different denominators. -- Clearer source citations and reader-facing methods; build-status fields, identifiers and review history retained here and in provenance rather than the article text. -- The UC parent and full-time sole trader are reproduced by `generate_trading_extensions.py`: five pairs passed. The £4,000-receipts parent gains £180 after £220 of UC withdrawal; the sole trader gains £520 including £120 Class 4. -- For the specified £18,000-wage parent at £1,500 receipts, the gain is £45 (tax −£100, UC −£55). Max's £79 case needs exact inputs to resolve; it was not copied into the article. -- Missing-receipts examples demonstrate £300 instead of £100 of tax relief for the small trader, and £0 instead of £520 of tax/NI savings for the sole trader. -- The calculator salary comparison is recorded in `dashboard_salary_comparison.json`: the pinned March earnings index grows a £45,000 2026 salary to about £46,080 in 2027; taxes round to £9,014/£9,164, change £150. The article's fixed 2027 salary remains £45,000, taxes £8,582/£8,732. No finance-cost calculator input exists. -- Companion household-preset work is dashboard [PR #292](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/pull/292). At checked head `65ea750a`, the £45k/£6k/£2k recommendation had not yet replaced its older preset. No unsupported preset deep link is used. - -Still needed before publication: - -- Final population regeneration, with a component CSV/receipt binding the exact dataset bytes and updated forecast. Max's earlier ad32af7f run reproduces the saved first estimates but does not supply those component artifacts. His later correction on dashboard #290 calls for detailed October forecast tables and council tax in the final regeneration. The dataset pin has not changed automatically. -- Weighted tax/benefit totals and household counts by decile. Person-weighted deciles with household-weighted cash means do not justify dividing one mean by the sum of means to claim a 48% revenue share. -- A bottom-decile income-source breakdown explaining its higher average loss; no cause has been inferred. -- Max's internal 260,000-person income-tax count and £71m miscellaneous-income sensitivity need scripts/aggregate receipts, output definitions and unique source-household support. The latter also needs a single shared trading/miscellaneous allowance and explicit eligibility/expense assumptions; it is not treated as a proven upper bound. These numbers are not added as reproduced results. -- Replace preview artifact links when verified public artifacts exist; complete visual preview and editorial review. - -At this historical revision, the articles remained drafts. Publication approval was separate from readiness for agent review. The trading article subsequently moved to its own stacked PR, reusing the shared analysis foundation. - - -## Historical review follow-ups and first PR split - -- At this historical revision, savings/property was draft PR #1460, and trading was separate draft PR #1463, stacked on #1460 for shared analysis. Both linked to dashboard PR #292. Property and savings were split later, as recorded above. -- Max confirmed the savings/property revision at `5a70185a` in comment 6473557134 and withdrew the 48% inference. The two remaining requests were precise paragraph citations and final component exports. -- Official Budget PDF physical page 142 was checked for paragraphs 6.246/6.247 and 6.254; physical page 45 contains paragraph 2.50. These are now the rule citations. -- Max's newer trading comment on #1463, 6473574155, agrees to omit the unsupported 260,000 count and £71m sensitivity; the latter ignores the shared allowance. Those figures remain excluded. -- Per that follow-up, only the mutually reproduced £180 UC example is retained in the article. The £1,500 diagnostic pair remains in the raw analysis record, with both input sets distinguished, rather than presented as an explained cross-run comparison. -- The trading lead example is named Alex and remains first: age 35, salary £30,000, receipts £4,000, costs £500, tax reduction £400. UC and full-time self-employment are additional examples. -- A fresh complete pass covered all five Max conversation comments on #1460 and the follow-up on #1463, including edits through 15:45:19 UTC. Both PRs had no inline review threads or submitted reviews in that pass. - - -## Rounding correction at 16:01 UTC - -Max's latest comments on PR #1460 (6473972686) and PR #1463 (6473966614) supersede the earlier permission to retain pence in worked tables. Reader-facing tables now use whole pounds throughout; pence are permitted only in prose spelling out a formula. Exact model outputs and hashed source files retain their original precision. The rounded band-crossing components still sum to £8,582/£8,732, and the rounded sole-trader totals remain £1,672/£1,152, a £520 change. - -At this stage, the dashboard defined property and savings as separate measures while the article still analysed them together. The article was subsequently split. A new measure definition was not a substitute for published execution-bound component outputs. The old first-estimate snapshot remains identified by its original measure IDs until replacement data are verified. - - -## Historical source check at 16:04 UTC - -Preview manifest revision 15 (updated 16:01:00Z) has no property_income_rates_up or savings_income_rates_up artifacts yet. The old combined result is withdrawn because the measure was split; its archived snapshot remains in the analysis records. A newer trading artifact `71f8a26e4f547021` is provisional and failed reconciliation. It uses the same certified `a6299504` dataset and detailed October forecasts, but its source still excludes the council-tax update. Neither it nor Max's rounded internal component figures has replaced the saved first-estimate data. - -The drafts now explicitly flag the older national snapshot as awaiting replacement. These national sections must not be treated as current approved dashboard outputs or published until replacement execution-bound results are reconciled. Household calculations and their input/output records are unchanged. - -## Historical alignment with the Pension Tax Allowance draft - -The user requested the same methodology and styling as the Pension Tax Allowance analysis in PR #1457. The reference was read at head `d282ef870176c81feb87175d02584121bdc50197`, whose chart dependency is PR #1462. The main article structure follows rules, household examples and curves, population impacts, assumptions and limitations, then methodology. The shared numeric line renderer is reused rather than copied. - -Both synthetic generators now apply the exact October forecast used by that PTA revision (dashboard commit `640426575270224db9b04d6c94d30e264a347be2`) to the baseline and the isolated reform. Previously the synthetic examples held incomes fixed but retained the model’s March parameter forecast. These are distinct choices: the inputs still stay fixed, while projected model parameters now use the common October overlay. The forecast’s original JSON is saved and hash-checked, and the complete eight-path parameter mapping was compared with the original source’s `with_forecast(None)` for exact equality. The archived national results are not regenerated or relabelled by this household change. - -Charts now show numeric axes, £ formatting and named allowance thresholds using the PR #1462 renderer. Display points include every £100 plus exact breakpoints, including the 75%-expense choice at £1,333⅓ of trading receipts. Both tax scenarios are independently checked against arithmetic at every £2, and linear interpolation of the displayed data is compared with the model changes to a one-penny tolerance. Counts and measured maximum errors are saved in `curve-validation.json`. Max’s latest instruction to use whole pounds in all reader-facing tables remains in force. - -Manifest revision 17, updated 16:09:01.451619 UTC, publishes separate property (`3537bd303ac226cf`) and savings (`af6aaaee33f616ee`) artifacts, but both are provisional and fail reconciliation, as does the newer trading artifact. No replacement is adopted. The 16:10 webinar guidance is to use available dashboard figures and say other figures are “still being checked”; the saved older estimates are not cleared for spoken or published headline results by that message. - -The rerun completed at 16:18:33 UTC with all 23 main household comparisons and all 5 trading extension pairs passing. Every policy delta is unchanged. The Scottish income-tax levels change by −£2.93 in baseline and reform, while the UC parent’s total benefits and net income change by about +£20.10 in both; these level changes are retained in raw outputs. UC levels and the £180 and £520 article examples are unchanged. The generated curves contain 46 savings points and 47 trading points. At 2,251 income points per series, 18,008 liability comparisons and 9,004 chart-interpolation comparisons pass; the maximum interpolation error is £0.0033, below the one-penny tolerance. Both generated line specs are ready to insert into the separate articles. Python compilation and diff-whitespace checks also passed. No population outputs or source artifacts were changed. - - -### PTA presentation alignment validation - -Both posts now use the shared line-chart renderer from app-v2 PR #1462, the same dependency as the Pension Tax Allowance analysis in PR #1457. The savings/property PR is stacked on `pavel/blog-line-chart`; the trading PR remains stacked on the savings/property branch. The posts share rules, household impacts, population impacts, assumptions and limitations, and methodology sections. All reader tables use whole pounds. - -The line renderer, bar renderer, article-chart parser and post metadata checks passed (51 tests); website ESLint and TypeScript checks passed. No CI monitoring was performed. The 23 household cases, five extension pairs and dense curve checks passed on the pinned October forecast. Browser approval declined the public dashboard preview origin, so its rendered policy tab and the final visual layout were not verified in this pass. No alternative access to that blocked origin was attempted. - -Max's 16:18:54 UTC webinar update asks authors to introduce each measure for 30–60 seconds: say what it does and who it reaches, leaving costings to the dashboard. Q&A should use displayed dashboard figures and describe missing figures as still being checked. The archived national figures in these draft articles are not webinar-approved estimates. - - -## Historical review comments addressed on 28 October - -Historical review record: the combined article's Treasury total and mixed £120 property / £30 savings paragraph described below were superseded by the 28 October 2026 split. Property-only PR #1460 no longer contains those combined figures; savings is a separate draft in #1466. The older combined records remain here for reproducibility, and current publication status is tracked on each PR. - -The savings/property article removes the withdrawn combined national snapshot, its model fiscal row, decile table and affected share. Its key figures and national table now contain Treasury costings only, separated into property and savings with the combined official total. The archived data and earlier review records remain here for reproducibility; they are not current article results. This follows the cut-or-match-final-run rule Max applied in trading commits `8751cf29` and `c78cdd60`, without substituting unverified replacement figures. - -The mixed-income paragraph now confirms the dashboard's landlord-45k preset and the £120 property plus £30 savings split. It retains the salary-uprating explanation. Canonical dashboard links use www.policyengine.org/uk/autumn-budget-2026, and publication wording holds before and after the production switch. The model's hypothetical households and chart values are unchanged. - -The Treasury comparison now cites HMRC's payments-on-account guidance and ONS public-finance methodology section 6.1.2: prior-year instalments, the 31 January 2029 balancing payment and first subsequent-year payment explain why same-year tax liability and early-year receipts require a collection bridge. No fitted cash share or illustrative bridge is published as an independently verified result. Property's timing issue does not establish the source of the savings shortfall. Dashboard review comment 6475368627 recommends marking property 2027–28 and 2028–29 not comparable; its final-regeneration freeze remains separate from these prose edits. - -Trading inline comment 4403534071 is implemented: an excluded employer/connected-party payment removes allowance relief for the whole tax year across relevant sources, with spouse or civil partner, connected-partnership and company conditions. Inline comment 4403569478's dashboard-introduction suggestion is also implemented. Primary HMRC/ITTOIA sources were checked. Max's direct edits and all household/table/chart values are retained. - -At this historical revision, both PRs remained drafts at the user's request. Implementing those review comments did not grant merge authorization; current status is tracked on each PR. - -Validation after these edits and the main-branch metadata merge: make format, make lint, make typecheck and make test passed on Node 26.12.1. App: 6,042 passed / 10 existing skips; website: 529 passed; total 6,571 passed. Existing household-table rows and line-chart JSON compare identically with the previous head. Every main-branch post metadata entry is preserved. No model or generator changes were required, and no CI monitoring was performed. diff --git a/analysis/uk-budget-2026-income-tax/property-population/README.md b/analysis/uk-budget-2026-income-tax/property-population/README.md index 0e2eb4615..f4b2cc487 100644 --- a/analysis/uk-budget-2026-income-tax/property-population/README.md +++ b/analysis/uk-budget-2026-income-tax/property-population/README.md @@ -2,7 +2,7 @@ This folder supports the property article in PR #1460. It retains the approved property-only national results from dashboard PR #290 at immutable commit `637bb26c34264e0491ed182c363df751466458ed`. -These are approved **branch-snapshot** results. The snapshot has not been independently verified as the production deployment. Before merging the article, compare the final released dashboard's property artifact identity and figures with this record, and update the article if they differ. The article's new population section also requires review at its new head. +These results identify an approved branch snapshot; the snapshot has not been independently verified as the production deployment. ## Source and verification @@ -13,14 +13,14 @@ These are approved **branch-snapshot** results. The snapshot has not been indepe - Certified national dataset: `microcosm-uk-2024-25-national-20261025T091414Z-a6299504`, SHA256 `b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e`. - Baseline and reform use the detailed October 2026 forecast. The reform changes only the property-income measure, including finance-cost relief. -The canonical receipt validator returned no document or dashboard problems. The artifact, receipt, outputs, execution identity and approval digests match the manifest; all eight source CSV hashes match the receipt. Reconciliation is `pass`, responsiveness is `responsive`, and disclosure checking records a three-survey-household floor with no thin or withheld cells. `summary.json` retains the exact checks, source URLs, values and definitions. The retained receipt and four CSVs are public national aggregates; no household records or population H5 are stored here. +The canonical receipt validator returned no document or dashboard problems. The artifact, receipt, outputs, execution identity and approval digests match the manifest; all eight source CSV hashes match the receipt. Reconciliation is `pass` and responsiveness is `responsive`. The receipt's disclosure-floor result covers the decile, age and binned-scatter tables: the decile and age tables use a three-survey-household floor, while the binned scatter uses its separate ten-household minimum. No thin or withheld cells were recorded in those covered tables. That result does not extend to the reach, poverty or inequality outputs in `metrics.csv` or `poverty_inequality.csv`; neither file is retained here. `summary.json` retains the checks, source URLs, article values and definitions, with reach, poverty and inequality figures omitted pending separate disclosure clearance. The retained receipt and three CSVs are public national aggregates; no household records or population H5 are stored here. ## Files and definitions - `budgetary_impact.csv`: annual reform-minus-baseline government balance, in £ billion. This includes tax and spending interactions and is not income tax alone. - `winners_losers.csv`: despite its name, it contains household-weighted **mean income changes**, not winner/loser counts or shares. The article's chart uses the 2027 and 2031 decile means, retaining raw precision and rendering whole pounds. - `distributional_impact.csv`: change in aggregate household net income divided by aggregate baseline household net income within each decile, as a percentage. It is not the mean of household percentage changes. -- `metrics.csv`: includes the affected-population measure. For 2027–28, 5.9436116% of people live in households whose absolute relative household-income change exceeds 0.01%. The calculation uses at least £1 of baseline household income and restricts the population to valid baseline deciles. It counts either direction, not only tax increases or losses. No taxpayer count, affected-household count, or separate winner/loser shares are available in these exports. +- `summary.json`: retains provenance, validation records, annual revenue, and decile and all-household average income changes. Reach, poverty and inequality figures are omitted pending separate disclosure clearance. No taxpayer count, affected-household count, or separate winner/loser shares are provided. Decile ranks are recomputed for each year from baseline, person-weighted equivalised HBAI household net income before housing costs. Negative ranking income is reset to zero, and equal-income households share a rank. The displayed averages are annual, unequivalised household-net-income changes over **all households** in each decile, including those unaffected. No top-decile revenue share is inferred from these means. @@ -34,4 +34,4 @@ The official comparison marks 2027–28 and 2028–29 as not comparable; its com - [Treasury row 61 source values](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/data_inputs/treasury/sources/AB2026-T6.1.csv). - [National calculator definitions](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/src/uk_budget_data/calculators.py). -The other four source CSVs are not copied because the article does not use them; their hashes remain in the original receipt and verification summary. This folder supersedes the old combined preview for the property article only. The historical `population-preview/` folder remains unchanged and must not be relabelled as this property-only result. +The other five source CSVs are not copied; their hashes remain as source-verification records in the original receipt and verification summary. No reach, poverty or inequality figures from those files are republished here. This folder supersedes the old combined preview for the property article only. The historical `population-preview/` folder remains unchanged and must not be relabelled as this property-only result. diff --git a/analysis/uk-budget-2026-income-tax/property-population/metrics.csv b/analysis/uk-budget-2026-income-tax/property-population/metrics.csv deleted file mode 100644 index 3c35946fb..000000000 --- a/analysis/uk-budget-2026-income-tax/property-population/metrics.csv +++ /dev/null @@ -1,7 +0,0 @@ -reform_id,reform_name,year,people_affected,gini_change,poverty_change_pp,poverty_change_pct -property_income_rates_up,Property income tax rates up,2026,0.0,0.0,0.0,0.0 -property_income_rates_up,Property income tax rates up,2027,5.943611604537077,-0.00012268724460114496,0.0013589859,0.009870348 -property_income_rates_up,Property income tax rates up,2028,5.952076585287802,-0.00012210013169514702,0.00080776215,0.0059420434 -property_income_rates_up,Property income tax rates up,2029,6.037490519286693,-0.00012215392257318585,0.0013303757,0.009669558 -property_income_rates_up,Property income tax rates up,2030,6.034841349783147,-0.00012083309893889608,0.0019693375,0.014370949 -property_income_rates_up,Property income tax rates up,2031,5.9743860438605845,-0.00012092905458994419,0.0020561218,0.0150401555 diff --git a/analysis/uk-budget-2026-income-tax/property-population/summary.json b/analysis/uk-budget-2026-income-tax/property-population/summary.json index 31056f3d4..2aed7ea8c 100644 --- a/analysis/uk-budget-2026-income-tax/property-population/summary.json +++ b/analysis/uk-budget-2026-income-tax/property-population/summary.json @@ -112,22 +112,33 @@ "survey_households": 3, "thin_cells": [], "thin_cells_in_tables": false, - "withheld_cells": [] + "withheld_cells": [], + "covered_tables": [ + "distributional_impact", + "winners_losers", + "age_impact", + "household_scatter_binned" + ], + "coverage_note": "The three-survey-household floor covers the decile and age tables; the binned scatter uses its separate ten-household minimum. The recorded absence of thin or withheld cells applies only to these covered tables, not to reach, poverty or inequality outputs. Reach, poverty and inequality figures are omitted from this summary pending separate disclosure clearance." }, "data_limits": [], "model_limits": [], "reconciliation": { "responsiveness_status": "responsive", "summary_status": "pass" - } + }, + "file_hashes_scope": "Hashes verified against all eight CSVs in the source artifact. Only budgetary_impact.csv, distributional_impact.csv and winners_losers.csv are retained in this folder; the other source hashes do not imply that those files or all their metrics are published here.", + "retained_aggregate_files": [ + "budgetary_impact.csv", + "distributional_impact.csv", + "winners_losers.csv" + ] }, "definitions": { "revenue": "Change in weighted government balance: reform gov_balance minus baseline gov_balance. Positive is a government gain. Includes tax and spending interactions; not income tax alone.", "decile_ranking": "Recomputed from the baseline for each reported year. Deciles of person-weighted equivalised HBAI household net income before housing costs; negative ranking income is reset to zero and equal-income households share a rank.", "decile_mean": "Weighted mean annual unequivalised household_net_income change among all households in the baseline decile, including unaffected households; household-weighted, not per person and not the mean among affected households.", - "relative_change": "Sum of weighted household income change divided by sum of weighted baseline household income within that year's baseline decile, times100; not the mean of individual percentage changes.", - "reach": "Share of people in households whose absolute change in household_net_income divided by max(baseline household_net_income,GBP1) exceeds0.0001 (0.01%). Numerator and denominator are weighted household size, restricted to baseline household_income_decile>=1. Changes in either direction count.", - "gini_change": "(Reformed Gini minus baseline Gini)/baseline Gini, a relative fraction, using equivalised household_net_income with person weights. This is not a percentage-point change in the Gini coefficient." + "relative_change": "Sum of weighted household income change divided by sum of weighted baseline household income within that year's baseline decile, times100; not the mean of individual percentage changes." }, "annual_revenue": [ { @@ -223,9 +234,7 @@ "7": 0.0, "8": 0.0, "9": 0.0 - }, - "people_living_in_affected_households_percent": 0.0, - "gini_relative_fraction_change": 0.0 + } }, "2027": { "average_household_change_gbp": { @@ -252,9 +261,7 @@ "7": -0.013220674146739093, "8": -0.022890621117303365, "9": -0.028773800606848924 - }, - "people_living_in_affected_households_percent": 5.943611604537077, - "gini_relative_fraction_change": -0.00012268724460114496 + } }, "2028": { "average_household_change_gbp": { @@ -281,9 +288,7 @@ "7": -0.014231064030165044, "8": -0.023066587924497953, "9": -0.028403468574895112 - }, - "people_living_in_affected_households_percent": 5.952076585287802, - "gini_relative_fraction_change": -0.00012210013169514702 + } }, "2029": { "average_household_change_gbp": { @@ -310,9 +315,7 @@ "7": -0.017949330941909994, "8": -0.02299527301085211, "9": -0.028798712554661515 - }, - "people_living_in_affected_households_percent": 6.037490519286693, - "gini_relative_fraction_change": -0.00012215392257318585 + } }, "2030": { "average_household_change_gbp": { @@ -339,9 +342,7 @@ "7": -0.019269608517530193, "8": -0.023458041818215283, "9": -0.028992003379557544 - }, - "people_living_in_affected_households_percent": 6.034841349783147, - "gini_relative_fraction_change": -0.00012083309893889608 + } }, "2031": { "average_household_change_gbp": { @@ -368,9 +369,7 @@ "7": -0.01972931434903989, "8": -0.02405452667513538, "9": -0.028820511996950758 - }, - "people_living_in_affected_households_percent": 5.9743860438605845, - "gini_relative_fraction_change": -0.00012092905458994419 + } } }, "official_comparability": { @@ -380,14 +379,14 @@ }, "2027": { "not_comparable": { - "reason": "Self Assessment tax on 2027-28 property income is mostly paid from 31 January 2029, so the Treasury's costing (on a National Accounts basis) has \u00a335m in 2027-28 and about 1.5 years of liability in 2028-29 (\u00a3575m), while the model scores each tax year's liability. From 2029-30 the two agree within 1.5%. Table 6.1 row 61." + "reason": "Self Assessment tax on 2027-28 property income is mostly paid from 31 January 2029, so the Treasury's costing (on a National Accounts basis) has £35m in 2027-28 and about 1.5 years of liability in 2028-29 (£575m), while the model scores each tax year's liability. From 2029-30 the two agree within 1.5%. Table 6.1 row 61." }, "post_behavioural": null, "static_costing": null }, "2028": { "not_comparable": { - "reason": "Self Assessment tax on 2027-28 property income is mostly paid from 31 January 2029, so the Treasury's costing (on a National Accounts basis) has \u00a335m in 2027-28 and about 1.5 years of liability in 2028-29 (\u00a3575m), while the model scores each tax year's liability. From 2029-30 the two agree within 1.5%. Table 6.1 row 61." + "reason": "Self Assessment tax on 2027-28 property income is mostly paid from 31 January 2029, so the Treasury's costing (on a National Accounts basis) has £35m in 2027-28 and about 1.5 years of liability in 2028-29 (£575m), while the model scores each tax year's liability. From 2029-30 the two agree within 1.5%. Table 6.1 row 61." }, "post_behavioural": null, "static_costing": null @@ -419,5 +418,10 @@ "Do not derive revenue shares from decile average household changes without weighted counts/totals.", "Treasury rows2027/2028 are retained from source for a labelled annual table, but the dashboard comparison deliberately suppresses them as not comparable.", "Static model, fixed incomes/no incorporation response; Treasury figures include behavioural assumptions and a different collection profile." + ], + "omitted_outputs_pending_disclosure_clearance": [ + "People living in affected households percentage", + "Poverty changes", + "Inequality changes" ] } diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index 31820e4fa..afbbe0b3d 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -8,6 +8,8 @@ Key figures for 2027–28: - PolicyEngine estimates £399 million of additional net government revenue and a £14 reduction in average household net income in 2027–28. - The Treasury forecasts £35 million of additional revenue in 2027–28, £575 million in 2028–29, and £435 million to £455 million a year from 2029–30 to 2031–32. +The 2027–28 and 2028–29 figures use different collection-timing bases and are not directly comparable; see the [budgetary impact section](#budgetary-impact). + Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for this and the other Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. The Budget also raises savings income tax rates; we will cover that measure separately. ## What changes in April 2027? @@ -30,7 +32,7 @@ The examples below isolate the announced property measure in 2027–28. They hol For individual residential landlords, mortgage interest normally produces a tax reduction rather than a deduction from rental profits. The reduction is limited by finance costs, property profits, adjusted total income and the tax liability. [HMRC's explanation of residential finance-cost relief](https://www.gov.uk/guidance/changes-to-tax-relief-for-residential-landlords-how-its-worked-out-including-case-studies) describes these limits. -From April 2027 the relief follows the property basic rate, as the [Treasury policy costings](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74) confirm. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. The dashboard calculator has no finance-cost input, so the mortgage examples below illustrate an effect its preset cannot show. +From April 2027 the relief follows the property basic rate, as the [Treasury policy costings](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74) confirm. This Budget therefore raises it from the already scheduled 22% to 24%. That offsets part of the tax increase for landlords with eligible finance costs. Consider two adults in England, each with £12,000 of rent, £2,000 of allowable non-finance expenses and £4,000 of qualifying mortgage interest. Deducting actual non-finance expenses leaves £10,000 of property profit. Both can use the full finance-cost reduction. @@ -49,7 +51,7 @@ The property **rate** increase excludes Scottish taxpayers, whose rental income ### A smaller rental profit -A landlord with a £30,000 salary has already used the Personal Allowance against salary. If they also have £6,000 of taxable property profit after deductions and no eligible finance costs, they pay £120 more income tax in 2027–28: £6,000 × 2% = £120. This property-only calculation holds their income fixed and changes no other Budget measure. +A landlord in England with a £30,000 salary has already used the Personal Allowance against salary. If they also have £6,000 of taxable property profit after deductions and no eligible finance costs, they pay £120 more income tax in 2027–28: £6,000 × 2% = £120. This property-only calculation holds their income fixed and changes no other Budget measure. ## Population impacts @@ -61,7 +63,7 @@ PolicyEngine estimates that the measure raises £399 million of net government r | Year | PolicyEngine net government revenue, £ million | Treasury revenue, £ million | Comparison | | --- | ---: | ---: | --- | -| 2026–27 | 0 | 0 | No modelled policy effect | +| 2026–27 | 0 | 0 | Before implementation | | 2027–28 | 399 | 35 | Not comparable | | 2028–29 | 412 | 575 | Not comparable | | 2029–30 | 429 | 435 | Later-year comparison | @@ -76,9 +78,7 @@ The [ONS public-finance methodology, section 6.1.2](https://www.ons.gov.uk/econo The Treasury costing also allows for some landlords incorporating. PolicyEngine holds that choice fixed. Differences in data, behaviour and accounting remain relevant when comparing the later years, even where the rounded estimates are close. -### Reach and distribution - -In 2027–28, 5.9% of people live in households whose net income changes by more than 0.01% in either direction under the model's affected-population measure. This includes increases and decreases in household income; it is not a count of people paying more property tax. The Scottish finance-cost example above illustrates one way income can rise. +### Distribution Across all households, average annual net income falls by £14 in 2027–28 and £15 in 2031–32. In 2027–28, the average reduction ranges from £1 in the lowest income decile to £58 in the highest; in 2031–32, those averages are £2 and £66. @@ -185,7 +185,7 @@ Income deciles rank people by their household's baseline equivalised net income - The household tables show tax attributable to property income. The mortgage examples assume the full finance-cost reduction can be used. - The Scottish mortgage example applies the existing Finance Act rule linking relief to the UK property basic rate. The Finance Bill will set the final implementation of the new rates. - National estimates hold households' behaviour fixed. They do not model landlords incorporating in response to the tax change. -- The national affected-population percentage measures people living in households with an income change above the stated threshold. It does not give a taxpayer count or separate shares gaining and losing. +- We do not report poverty, inequality or people-affected figures while their disclosure checks remain unverified. - Population estimates include changes in means-tested benefits. The worked household examples show income tax; a change in benefits can offset part of a household's extra tax. ## Methodology From 0c6f7c83af20703c650bb1fdb613df4d08b3217e Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 15:32:51 -0400 Subject: [PATCH 18/24] docs: remove withdrawn microsimulation previews Drop the old combined savings/property and trading preview aggregates, their verifier and public references. Keep the approved property-only revenue and decile microsimulation unchanged. --- analysis/uk-budget-2026-income-tax/README.md | 22 +- .../population-preview/manifest.json | 198 --- .../population-preview/summary.json | 1189 ----------------- .../budgetary_impact.csv | 7 - .../distributional_impact.csv | 61 - .../trading_allowance_raise/metrics.csv | 7 - .../trading_allowance_raise/receipt.json | 453 ------- .../winners_losers.csv | 67 - .../budgetary_impact.csv | 7 - .../distributional_impact.csv | 61 - .../unearned_income_rates_up/metrics.csv | 7 - .../unearned_income_rates_up/receipt.json | 173 --- .../winners_losers.csv | 67 - .../property-population/README.md | 2 +- .../uk-budget-2026-income-tax/provenance.json | 56 +- .../verify_population_preview.py | 93 -- 16 files changed, 16 insertions(+), 2454 deletions(-) delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/manifest.json delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/summary.json delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/budgetary_impact.csv delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/distributional_impact.csv delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/metrics.csv delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/receipt.json delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/winners_losers.csv delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/budgetary_impact.csv delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/distributional_impact.csv delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/metrics.csv delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/receipt.json delete mode 100644 analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/winners_losers.csv delete mode 100644 analysis/uk-budget-2026-income-tax/verify_population_preview.py diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index e4a01d480..1af1db429 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -24,29 +24,19 @@ The savings draft (#1466) reproduces `savings-interest-chart.json`; the trading The property draft now includes national revenue and decile averages from the approved property-only snapshot in dashboard PR #290. `property-population/` retains the immutable source record, original receipt, three aggregate CSVs and the verification summary. Reach, poverty and inequality figures are omitted pending separate disclosure clearance. It is an approved branch snapshot, not independently verified as the production deployment. Recheck its identity and figures against the final released dashboard before merging, and have the new article head reviewed. -The savings and trading posts retain household calculations and Treasury costings only. No withdrawn combined national figures have been restored. The `population-preview/` files described below remain historical records; they are not the property-only source now used by the article. +The savings and trading posts retain household calculations and Treasury costings only. Withdrawn combined national outputs are not published in this directory. ## Dataset decision Retain the dashboard's adopted `policyengine` 6.11.1 bundle, with UK 2.151.0, core 3.33.3 and national data cut `a6299504`. The certificate, full dataset ID and checksum are recorded in `provenance.json`. The newer candidate in [policyengine.py PR #725](https://github.com/PolicyEngine/policyengine.py/pull/725) is awaiting certification/adoption. A future update must change the package and dataset provenance together and regenerate the analysis. -The household generators need no population microdata. This historical snapshot was retrieved without downloading population microdata. At 14:32 UTC the checked GitHub flat files still lacked these Budget-day measures. The dashboard maintainer subsequently shared a preview with provisional outputs generated at 14:34 UTC, fetched at 14:46 UTC. The analysis records retain its digest-addressed public aggregate outputs as an earlier review snapshot, with the exact manifest, receipts and eight CSVs retained in `population-preview/`. Older candidate charts and stale GitHub flat files must not be relabelled as the announced policy. The preview has no scored combined artifact; its five-measure chart must not be described as a jointly simulated full Budget package. +The household generators need no population microdata. The property national results reuse the approved single-measure dashboard artifact recorded in `property-population/`; they were not generated locally. Both baseline and reform use the same October 2026 OBR forecast. Series not updated by the overlay retain the model's March forecast path; the underlying calibration remains pre-Budget. -The provisional national outputs use the exact dataset above with the dashboard's October 2026 OBR forecast wrapper on both baseline and reform. Each provision is scored separately. The source commit is `0d9dccb2`; its reform definitions and October forecast input file match household reference commit `b50787aa` byte for byte. Series not updated by the overlay retain the model's March forecast path; the underlying calibration remains pre-Budget. - -Verify the snapshot without downloading microdata or any other files: - -```sh -python3 analysis/uk-budget-2026-income-tax/verify_population_preview.py -``` - -The verifier checks the eight CSV hashes, certified execution identity, dataset checksum, provisional status, disclosure floor and complete decile grids. It writes `population-preview/summary.json`. Both measures are `provisional` and their reconciliation is `awaiting_source`; passing the disclosure floor does not mean final review approval. The snapshots are public aggregates only. - -Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipts with the model's annual government-balance effects, documenting behavioural, timing and coverage differences. Do not attribute a particular discrepancy to one of those factors before reconciliation. No separate winner/loser shares or absolute affected-person counts are exported. The field `people_affected` is a percentage, using an absolute household-income-change threshold of more than 0.01%, not millions of people or a taxpayer count. +Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipts with the model's annual government-balance effects, documenting behavioural, timing and coverage differences. Do not attribute a particular discrepancy to one of those factors before reconciliation. No separate winner/loser shares or absolute affected-person counts are provided. Reach, poverty and inequality figures require separate disclosure clearance before publication. ## Checks before publication -- Recheck the property draft's `property-population/` artifact identity, figures and comparison flags against the final released dashboard. The new population section needs review at its new head. Restore national scope in the other posts only from their own reconciled sources. Add absolute affected-person counts and separate winner/loser shares only when the producer exports those quantities; do not infer them from average changes or the affected percentage. +- Recheck the property draft's `property-population/` artifact identity, figures and comparison flags against the final released dashboard. The new population section needs review at its new head. Restore national scope in the other posts only from their own reconciled sources. Add affected-person counts or shares only when the producer exports them and they have disclosure clearance; do not infer them from average changes. - Confirm the treatment of Scottish landlords' finance-cost relief against the final Budget implementation. The pinned model links that relief to the UK property basic rate even for Scotland. - Check trading allowance coverage: gross receipts and actual expenses are needed to model the deduction choice; the pinned model does not apply the allowance to its separate miscellaneous-income input. - Verify the final public dashboard link and add links to these explainers within the dashboard. The source checkout's README supplies the current Vercel dashboard URL. @@ -58,7 +48,7 @@ The three articles use the site's native tables, chart blocks and cover assets. `make format`, `make lint`, `make typecheck` and `make test` passed. The tests ran on Node 26.12.1: 6,042 app tests and 508 website tests passed, with 10 app tests skipped by the existing suite. After inserting the final chart data, the chart-parser and post-metadata checks passed again (18 tests). All 23 household comparisons and 20 curve points passed independent arithmetic checks. -The earlier addition of provisional national sections passed snapshot verification and article/chart checks; those sections have since been removed pending the final run. Browser access to the local preview was declined, so visual preview remains outstanding. The SVG cover XML and native chart specs were validated, but this does not confirm page layout at desktop or mobile widths. +Browser access to the local preview was declined, so visual preview remains outstanding. Cover assets and native chart specs were validated, but this does not confirm page layout at desktop or mobile widths. ## Additional trading and calculator examples @@ -75,7 +65,7 @@ The exact forecast input is retained as `obr_october_2026.json`; `forecast.py` v The Pension Tax Allowance analysis uses £100 chart sampling plus the true breakpoints and verifies the results on a denser model grid. These drafts follow that method: numeric income axes, explicit £ formats, named threshold markers and independent validation at every £2. Reader-facing tables use whole pounds under the [rounding review](https://github.com/PolicyEngine/policyengine-app-v2/pull/1460#issuecomment-6473972686); raw analysis retains precision. -The household forecast pin and population forecast pins are recorded separately. Applying the household overlay does not regenerate or validate the historical combined national snapshot. The property article now uses a separate approved property-only source with execution-bound provenance in `property-population/`; the historical combined preview remains superseded. +The household forecast pin and property population forecast pin are recorded separately. Applying the household overlay does not regenerate or validate national results. The property article uses an approved property-only source with execution-bound provenance in `property-population/`. The October-forecast rerun passed all 23 household comparisons and all 5 trading extension pairs. All policy deltas remain unchanged. Some absolute levels change: the three Scottish cases’ income-tax levels fall by £2.93 on both sides, and the parent’s total benefits/net income rise by about £20.10 on both sides. These do not change the article’s reported tax or household gains. The 93 displayed chart points passed 18,008 model-liability comparisons and 9,004 interpolation comparisons over 2,251 income points per series. The largest interpolation difference is £0.0033, below the £0.01 tolerance. diff --git a/analysis/uk-budget-2026-income-tax/population-preview/manifest.json b/analysis/uk-budget-2026-income-tax/population-preview/manifest.json deleted file mode 100644 index 85018bfdf..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/manifest.json +++ /dev/null @@ -1,198 +0,0 @@ -{ - "basis": { - "calibration": { - "source": "the certified dataset pinned by the installed policyengine bundle: Microcosm UK from policyengine 6.10.1, policyengine-uk-data before it", - "status": "pre_budget", - "vintage": "as pinned by the installed bundle" - }, - "forecast": { - "source": "OBR EFO October 2026", - "status": "updated", - "vintage": "OBR Economic and fiscal outlook, October 2026 (Annex A, Tables A.1 and A.3), applied over policyengine-uk's March 2026 growth rates by src/uk_budget_data/forecast/obr_october_2026.json" - }, - "notes": "The forecast is rebased on the Budget's OBR forecast: every simulation, baseline and reform alike, is built on the October 2026 growth rates in src/uk_budget_data/forecast/obr_october_2026.json (CPI, RPI, average earnings, house prices; the September 2027 CPI gap). Series that file does not list keep the March 2026 path the installed policyengine-uk ships; the receipt records the exact model version." - }, - "budget": { - "date": "2026-10-28", - "id": "uk-autumn-budget-2026" - }, - "combined": {}, - "execution": { - "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", - "identity": { - "certificate": { - "bundle_version": "6.11.1", - "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", - "certified_by": "policyengine.py bundle certification", - "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "certified_for_core_version": "3.33.3", - "certified_for_model_version": "2.151.0", - "compatibility_basis": "built_with_model_package", - "country_id": "uk" - }, - "certification_status": "certified", - "core": { - "name": "policyengine-core", - "version": "3.33.3" - }, - "country_id": "uk", - "data": { - "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "build_model_version": "2.151.0", - "data_package": "microcosm-data", - "dataset": "microcosm_uk_2024_25", - "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_version": "0.1.0" - }, - "model": { - "name": "policyengine-uk", - "version": "2.151.0" - }, - "schema_version": 1, - "wrapper": { - "name": "policyengine", - "version": "6.11.1" - } - } - }, - "flat_aliases": {}, - "flat_files": {}, - "measures": { - "domestic_electricity_zero_vat": { - "artifact": "artifacts/domestic_electricity_zero_vat/4b0323419c2ff3c6", - "artifact_sha256": "4b0323419c2ff3c650e9b596492711d606e4c6b93cbb47b20f255706f451ee4a", - "data_limits": [], - "description": "VAT on domestic electricity is 0% instead of 5% from 1 October 2026 to 30 June 2027: in Great Britain to March 2027 and across the UK from April 2027. The model's baseline has no zero rate, so the measure covers the whole period, as the Treasury costs it. It applies to electricity spending only. 2026-27 carries the October to March share of a year's electricity use (about 57%), not a share of its days; 2027-28 its 91 days of 366.", - "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", - "name": "Zero VAT on domestic electricity", - "outputs_sha256": "ccfdd7e4fd79735f382cfc95b6323a3331097e4180ec9b1148042d506699b94e", - "receipt_sha256": "f2535334472c0c38387923c0fe3cf72e928a90a107e32005b7098eb776cdf7f6", - "reconciliation": { - "responsiveness_status": "responsive", - "summary_status": "awaiting_source" - }, - "status": "provisional", - "unsupported_years": [], - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - }, - "fuel_duty_rise_deferral": { - "artifact": "artifacts/fuel_duty_rise_deferral/69cf8fc0ef40d810", - "artifact_sha256": "69cf8fc0ef40d810339521eec3efddf9e297da87ecadc22c0fb4b1aad1ce2378", - "data_limits": [], - "description": "The 5p cut in fuel duty is kept: the main rate stays at 52.95p a litre to 30 June 2027, so the rise due on 1 January 2027 and the March and April 2027 steps do not happen. From 1 July 2027 it returns to current law's 60.59p a litre, rising with RPI each April. Rates are day-weighted to fiscal years, and the VAT on the lower pump price is included.", - "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", - "name": "Fuel duty cut extended", - "outputs_sha256": "f035235441044cfb56f3571aba6ec60b2526406338426da61f45e79e8ffa1fc1", - "receipt_sha256": "8f70fcd277ecbb80982e876b54aec7dcfb1fa765d515165def1ddfcfdd1ac194", - "reconciliation": { - "responsiveness_status": "responsive", - "summary_status": "awaiting_source" - }, - "status": "provisional", - "unsupported_years": [], - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - }, - "household_energy_payment_2026": { - "artifact": "artifacts/household_energy_payment_2026/ff7e323670ad8bba", - "artifact_sha256": "ff7e323670ad8bba5b5aed3ec5d3a7d6d68a13a1e28d9d1df068812857c6a496", - "attestation": { - "checker": "PREVIEW ONLY \u2014 not a signature (checker)", - "measure_id": "household_energy_payment_2026", - "reason": "PREVIEW ONLY \u2014 not a signature. Local preview placeholder; nobody has reviewed this receipt. Checked budget_measures.household_energy_payment_2026: in 2026-27 only it adds the payment to ebr_council_tax_rebate for households in England whose council tax band is A, B, C or D, leaving every other household and year at the native amount. The receipt's outputs were compared with the hand-computed households in tests/test_reforms.py.", - "receipt_sha256": "920cbb9051d16e1ca77c4d0c517fbbd93615b8cebef60a4772adf10e1c1fd44a", - "released_at": "2026-10-28T14:40:00+00:00", - "second": "PREVIEW ONLY \u2014 not a signature (second)" - }, - "data_limits": [], - "description": "A one-off \u00a3100 payment from January 2027 to each household in England in property valuation bands A to D (the lowest four of England's eight), up to 20 million households, paid into bank accounts and counted as household income in 2026-27. Scotland, Wales and Northern Ireland receive a share of the funding instead, which is not modelled.", - "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", - "name": "Household Energy Payment", - "outputs_sha256": "07f3c82d557a12ed13094291e5b6c30666447fef161cace174a93cd98af11cca", - "receipt_sha256": "c1bbc5e6e34a2dc78fd922d73b0ed387eda37a8dce56b5ed5d291abaa7a2a63b", - "reconciliation": { - "responsiveness_status": "responsive", - "summary_status": "awaiting_source" - }, - "status": "provisional", - "unsupported_years": [], - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - }, - "trading_allowance_raise": { - "artifact": "artifacts/trading_allowance_raise/230c4665427e0bb1", - "artifact_sha256": "230c4665427e0bb1a8ab3c951753252190ff6f8fe86207e5d336b0616e465baf", - "data_limits": [], - "description": "From 6 April 2027 the trading allowance, which relieves trading receipts in place of actual expenses, rises from \u00a31,000 to \u00a33,000, for income tax and Class 4 National Insurance. Without gross receipts in the data, a profit within the allowance is treated as fully relieved, so the cost may be overstated.", - "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", - "name": "Trading allowance raised to \u00a33,000", - "outputs_sha256": "c98e404df6c02459d8d1c10e8de5417ac538fd7876f2048f7bfcd0c48598d7bc", - "receipt_sha256": "12e5b9f9ecaa3c9f6e967ad30a71c26e0156a8468a8edde5377a1400393a0f3c", - "reconciliation": { - "responsiveness_status": "responsive", - "summary_status": "awaiting_source" - }, - "status": "provisional", - "unsupported_years": [], - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - }, - "unearned_income_rates_up": { - "artifact": "artifacts/unearned_income_rates_up/8bd7d211ae66c19d", - "artifact_sha256": "8bd7d211ae66c19d63f7f47dd1a32645834f41270588ec7a87bcfd700092d242", - "data_limits": [], - "description": "From 6 April 2027 the income tax rates on savings income rise to 24%, 44% and 49% at the basic, higher and additional rates across the UK, and those on property income to the same rates in England, Wales and Northern Ireland: 2 percentage points above current law, which already includes Budget 2025's rises. Finance cost relief for landlords follows the property basic rate, so rises to 24%. Dividend rates are unchanged. Incomes are held fixed, with no behavioural response.", - "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", - "name": "Savings and property income tax rates up", - "outputs_sha256": "1315fa74166dfa15139fe4693bf7df5654244db1b39b8159a0a64e5c64bfe508", - "receipt_sha256": "4d8611bcb02d626dd6a9170d8564325ef8cc10266fb1b62485f604571a3413f4", - "reconciliation": { - "responsiveness_status": "responsive", - "summary_status": "awaiting_source" - }, - "status": "provisional", - "unsupported_years": [], - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - } - }, - "release": "uk-autumn-budget-2026", - "revision": 5, - "schema": "uk-budget-dashboard/publication-manifest/v1", - "superseded": [], - "updated_at": "2026-10-28T14:35:54.732859+00:00" -} diff --git a/analysis/uk-budget-2026-income-tax/population-preview/summary.json b/analysis/uk-budget-2026-income-tax/population-preview/summary.json deleted file mode 100644 index b2ae1496c..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/summary.json +++ /dev/null @@ -1,1189 +0,0 @@ -{ - "status": "Provisional preview; reconciliation awaiting_source; not final approval", - "manifest_url": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/manifest.json", - "manifest_updated_at": "2026-10-28T14:35:54.732859+00:00", - "manifest_sha256": "93148ae1fc473dbb5301ca4ac283891ddf43e6ee377fdc2df0607f0a6b0b1b7a", - "units": { - "budget_change_gbp_bn": "Annual government balance change, GBP billion; positive revenue, negative cost", - "mean_household_change_gbp": "Weighted mean annual net income change, GBP per household; includes unaffected households", - "income_change_pct": "Decile total income change / decile total baseline income * 100", - "people_affected_pct": "Percentage of people in valid-decile households with abs(change / max(baseline income, GBP 1)) > 0.0001" - }, - "limitations": [ - "No affected headcounts, household shares, winner/loser shares or survey support counts exported", - "Static estimates; Treasury post-behavioural fiscal-year forecasts require separate reconciliation", - "Trading allowance lacks gross receipts and may overstate cost" - ], - "measures": { - "unearned_income_rates_up": { - "source_commit": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", - "generated_at": "2026-10-28T14:34:26.864876+00:00", - "description": "From 6 April 2027 the income tax rates on savings income rise to 24%, 44% and 49% at the basic, higher and additional rates across the UK, and those on property income to the same rates in England, Wales and Northern Ireland: 2 percentage points above current law, which already includes Budget 2025's rises. Finance cost relief for landlords follows the property basic rate, so rises to 24%. Dividend rates are unchanged. Incomes are held fixed, with no behavioural response.", - "execution": { - "baseline": { - "binding": "content", - "kind": "current_law", - "name": "unearned_income_rates_up baseline" - }, - "certificate": { - "bundle_version": "6.11.1", - "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", - "certificate_source": "packaged", - "certified_by": "policyengine.py bundle certification", - "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "certified_for_core_version": "3.33.3", - "certified_for_model_version": "2.151.0", - "compatibility_basis": "built_with_model_package", - "country_id": "uk", - "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" - }, - "certification_status": "certified", - "core": { - "name": "policyengine-core", - "version": "3.33.3" - }, - "country_id": "uk", - "data": { - "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "build_model_version": "2.151.0", - "data_package": "microcosm-data", - "dataset": "microcosm_uk_2024_25", - "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_version": "0.1.0" - }, - "fiscal_year": { - "convention": "uk_fiscal_year", - "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", - "period_start": "04-06", - "year_label": "start_year" - }, - "model": { - "name": "policyengine-uk", - "version": "2.151.0" - }, - "outputs_sha256": "1315fa74166dfa15139fe4693bf7df5654244db1b39b8159a0a64e5c64bfe508", - "receipt_type": "policyengine.execution_receipt", - "reform": { - "binding": "content", - "kind": "reform", - "name": "unearned_income_rates_up", - "reform_sha256": "e6238a8a012d3dba63b67c75f812ef5cf7931ee8ca17c35720a94ef520979638", - "representation": "policyengine-uk.scenario/v1" - }, - "runtime": { - "platform": "linux", - "python_version": "3.13.3" - }, - "schema_version": 1, - "supported_years": [ - 2024, - 2025, - 2026, - 2027, - 2028, - 2029, - 2030, - 2031, - 2032 - ], - "wrapper": { - "name": "policyengine", - "version": "6.11.1" - }, - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - }, - "disclosure_floor": { - "checked": true, - "survey_households": 3, - "thin_cells": [], - "thin_cells_in_tables": false - }, - "sources": { - "budgetary_impact": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/budgetary_impact.csv", - "distributional_impact": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/distributional_impact.csv", - "winners_losers": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/winners_losers.csv", - "metrics": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/metrics.csv" - }, - "receipt_url": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/unearned_income_rates_up/8bd7d211ae66c19d/receipt.json", - "years": { - "2026": { - "budget_change_gbp_bn": 0.0, - "mean_household_change_gbp": 0.0, - "people_affected_pct": 0.0, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 2, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 3, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 4, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 5, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 6, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 7, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 8, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 9, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 10, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - } - ] - }, - "2027": { - "budget_change_gbp_bn": 0.6642382271213031, - "mean_household_change_gbp": -22.671638846816318, - "people_affected_pct": 10.673344206596365, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": -12.898118729678712, - "income_change_pct": -0.04985863048727435 - }, - { - "decile": 2, - "mean_household_change_gbp": -5.694578425096933, - "income_change_pct": -0.014274726231957425 - }, - { - "decile": 3, - "mean_household_change_gbp": -6.657553598437464, - "income_change_pct": -0.01493700611440189 - }, - { - "decile": 4, - "mean_household_change_gbp": -7.308607835285808, - "income_change_pct": -0.015130665063043254 - }, - { - "decile": 5, - "mean_household_change_gbp": -5.999313832829491, - "income_change_pct": -0.011040999093289379 - }, - { - "decile": 6, - "mean_household_change_gbp": -9.133481007058295, - "income_change_pct": -0.015457392166954702 - }, - { - "decile": 7, - "mean_household_change_gbp": -10.940919104608044, - "income_change_pct": -0.01679145061801241 - }, - { - "decile": 8, - "mean_household_change_gbp": -21.5078233997643, - "income_change_pct": -0.02924222878277037 - }, - { - "decile": 9, - "mean_household_change_gbp": -37.036157377175726, - "income_change_pct": -0.0424816465100822 - }, - { - "decile": 10, - "mean_household_change_gbp": -107.13162680777542, - "income_change_pct": -0.06764978971604362 - } - ] - }, - "2028": { - "budget_change_gbp_bn": 0.6957731772288318, - "mean_household_change_gbp": -23.653364852788222, - "people_affected_pct": 11.008162293996863, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": -13.41973138237426, - "income_change_pct": -0.051797994354371796 - }, - { - "decile": 2, - "mean_household_change_gbp": -6.338215310184361, - "income_change_pct": -0.01562814402382634 - }, - { - "decile": 3, - "mean_household_change_gbp": -6.89447245599531, - "income_change_pct": -0.01507923160657066 - }, - { - "decile": 4, - "mean_household_change_gbp": -7.530700661654769, - "income_change_pct": -0.015199990369575169 - }, - { - "decile": 5, - "mean_household_change_gbp": -6.8788149502975875, - "income_change_pct": -0.012557869706653325 - }, - { - "decile": 6, - "mean_household_change_gbp": -8.728224096645702, - "income_change_pct": -0.014460880161614037 - }, - { - "decile": 7, - "mean_household_change_gbp": -11.809515330751909, - "income_change_pct": -0.017821793400241998 - }, - { - "decile": 8, - "mean_household_change_gbp": -22.785654721608235, - "income_change_pct": -0.030450986910411898 - }, - { - "decile": 9, - "mean_household_change_gbp": -37.58069636855771, - "income_change_pct": -0.04241102691117292 - }, - { - "decile": 10, - "mean_household_change_gbp": -111.85151093127375, - "income_change_pct": -0.0691861186482591 - } - ] - }, - "2029": { - "budget_change_gbp_bn": 0.7276593169820835, - "mean_household_change_gbp": -24.629016272903616, - "people_affected_pct": 11.211334671637678, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": -13.976437998407777, - "income_change_pct": -0.05322985172426894 - }, - { - "decile": 2, - "mean_household_change_gbp": -6.498855289587565, - "income_change_pct": -0.015861030033688512 - }, - { - "decile": 3, - "mean_household_change_gbp": -7.341434113128795, - "income_change_pct": -0.015820633619852753 - }, - { - "decile": 4, - "mean_household_change_gbp": -8.370488863576746, - "income_change_pct": -0.016640010814691405 - }, - { - "decile": 5, - "mean_household_change_gbp": -6.616069295483351, - "income_change_pct": -0.01186750640488552 - }, - { - "decile": 6, - "mean_household_change_gbp": -9.026024721135434, - "income_change_pct": -0.014739892298832517 - }, - { - "decile": 7, - "mean_household_change_gbp": -12.984868754512368, - "income_change_pct": -0.019256034827620797 - }, - { - "decile": 8, - "mean_household_change_gbp": -23.63377334118966, - "income_change_pct": -0.031114843422502994 - }, - { - "decile": 9, - "mean_household_change_gbp": -38.78140865712871, - "income_change_pct": -0.04317103405831868 - }, - { - "decile": 10, - "mean_household_change_gbp": -116.09418043491492, - "income_change_pct": -0.07041327236762773 - } - ] - }, - "2030": { - "budget_change_gbp_bn": 0.7623675377687243, - "mean_household_change_gbp": -25.68817666790038, - "people_affected_pct": 11.515220448098733, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": -14.981320954576939, - "income_change_pct": -0.05610692023915448 - }, - { - "decile": 2, - "mean_household_change_gbp": -6.531174968146814, - "income_change_pct": -0.015838490300712545 - }, - { - "decile": 3, - "mean_household_change_gbp": -8.030036431729007, - "income_change_pct": -0.016970819222280532 - }, - { - "decile": 4, - "mean_household_change_gbp": -7.324763422872621, - "income_change_pct": -0.01437706071070637 - }, - { - "decile": 5, - "mean_household_change_gbp": -8.224558743431283, - "income_change_pct": -0.014513169605216732 - }, - { - "decile": 6, - "mean_household_change_gbp": -6.414100973437806, - "income_change_pct": -0.010245777552623752 - }, - { - "decile": 7, - "mean_household_change_gbp": -16.555145381069313, - "income_change_pct": -0.024164401723622005 - }, - { - "decile": 8, - "mean_household_change_gbp": -24.719282953845298, - "income_change_pct": -0.03191810416734249 - }, - { - "decile": 9, - "mean_household_change_gbp": -39.874223193190204, - "income_change_pct": -0.04373162273763173 - }, - { - "decile": 10, - "mean_household_change_gbp": -121.49216941209389, - "income_change_pct": -0.07181165560065904 - } - ] - }, - "2031": { - "budget_change_gbp_bn": 0.7933736065368444, - "mean_household_change_gbp": -26.618450973449693, - "people_affected_pct": 11.677047270799843, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": -15.740449373492428, - "income_change_pct": -0.05832341572449926 - }, - { - "decile": 2, - "mean_household_change_gbp": -6.122323367954729, - "income_change_pct": -0.014635606422439709 - }, - { - "decile": 3, - "mean_household_change_gbp": -8.55083626627086, - "income_change_pct": -0.017848939980989183 - }, - { - "decile": 4, - "mean_household_change_gbp": -7.717876836466778, - "income_change_pct": -0.014809745978892685 - }, - { - "decile": 5, - "mean_household_change_gbp": -8.480571400003587, - "income_change_pct": -0.014729454378751861 - }, - { - "decile": 6, - "mean_household_change_gbp": -6.449886317389771, - "income_change_pct": -0.010139823686994792 - }, - { - "decile": 7, - "mean_household_change_gbp": -18.032240662651855, - "income_change_pct": -0.025662723350375474 - }, - { - "decile": 8, - "mean_household_change_gbp": -25.156749151956337, - "income_change_pct": -0.03178995628746156 - }, - { - "decile": 9, - "mean_household_change_gbp": -41.97465710374913, - "income_change_pct": -0.04569066183442702 - }, - { - "decile": 10, - "mean_household_change_gbp": -124.94128651158324, - "income_change_pct": -0.07173645374140333 - } - ] - } - } - }, - "trading_allowance_raise": { - "source_commit": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", - "generated_at": "2026-10-28T14:34:31.676559+00:00", - "description": "From 6 April 2027 the trading allowance, which relieves trading receipts in place of actual expenses, rises from \u00a31,000 to \u00a33,000, for income tax and Class 4 National Insurance. Without gross receipts in the data, a profit within the allowance is treated as fully relieved, so the cost may be overstated.", - "execution": { - "baseline": { - "binding": "content", - "kind": "current_law", - "name": "trading_allowance_raise baseline" - }, - "certificate": { - "bundle_version": "6.11.1", - "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", - "certificate_source": "packaged", - "certified_by": "policyengine.py bundle certification", - "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "certified_for_core_version": "3.33.3", - "certified_for_model_version": "2.151.0", - "compatibility_basis": "built_with_model_package", - "country_id": "uk", - "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" - }, - "certification_status": "certified", - "core": { - "name": "policyengine-core", - "version": "3.33.3" - }, - "country_id": "uk", - "data": { - "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "build_model_version": "2.151.0", - "data_package": "microcosm-data", - "dataset": "microcosm_uk_2024_25", - "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_version": "0.1.0" - }, - "fiscal_year": { - "convention": "uk_fiscal_year", - "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", - "period_start": "04-06", - "year_label": "start_year" - }, - "model": { - "name": "policyengine-uk", - "version": "2.151.0" - }, - "outputs_sha256": "c98e404df6c02459d8d1c10e8de5417ac538fd7876f2048f7bfcd0c48598d7bc", - "receipt_type": "policyengine.execution_receipt", - "reform": { - "binding": "content", - "kind": "reform", - "name": "trading_allowance_raise", - "reform_sha256": "cdcc8b19d5234afe31ae857db16a8f2d6a18578a1d7da1c890b3c5f21832c268", - "representation": "policyengine-uk.scenario/v1" - }, - "runtime": { - "platform": "linux", - "python_version": "3.13.3" - }, - "schema_version": 1, - "supported_years": [ - 2024, - 2025, - 2026, - 2027, - 2028, - 2029, - 2030, - 2031, - 2032 - ], - "wrapper": { - "name": "policyengine", - "version": "6.11.1" - }, - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - }, - "disclosure_floor": { - "checked": true, - "survey_households": 3, - "thin_cells": [ - { - "groups": [ - "0", - "1", - "10", - "11", - "14", - "15", - "16", - "17", - "19", - "20", - "21", - "22", - "23", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "45", - "48", - "5", - "50", - "53", - "55", - "59", - "61", - "62", - "65", - "7", - "70", - "71", - "72", - "76", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2027 - }, - { - "groups": [ - "0", - "1", - "10", - "11", - "14", - "15", - "16", - "17", - "19", - "20", - "21", - "22", - "23", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "45", - "48", - "5", - "50", - "53", - "55", - "59", - "61", - "62", - "65", - "7", - "70", - "71", - "72", - "76", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2028 - }, - { - "groups": [ - "0", - "1", - "10", - "11", - "15", - "16", - "17", - "18", - "20", - "21", - "22", - "23", - "24", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "48", - "49", - "5", - "52", - "53", - "54", - "55", - "59", - "61", - "62", - "64", - "65", - "7", - "70", - "71", - "72", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2029 - }, - { - "groups": [ - "0", - "1", - "10", - "11", - "15", - "16", - "17", - "18", - "21", - "22", - "24", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "48", - "49", - "5", - "52", - "53", - "55", - "59", - "62", - "64", - "65", - "7", - "70", - "71", - "72", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2030 - }, - { - "groups": [ - "0", - "1", - "10", - "11", - "15", - "16", - "17", - "18", - "21", - "22", - "24", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "48", - "49", - "5", - "52", - "53", - "55", - "59", - "62", - "65", - "7", - "70", - "71", - "72", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2031 - } - ], - "thin_cells_in_tables": false - }, - "sources": { - "budgetary_impact": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/budgetary_impact.csv", - "distributional_impact": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/distributional_impact.csv", - "winners_losers": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/winners_losers.csv", - "metrics": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/metrics.csv" - }, - "receipt_url": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/artifacts/trading_allowance_raise/230c4665427e0bb1/receipt.json", - "years": { - "2026": { - "budget_change_gbp_bn": 0.0, - "mean_household_change_gbp": 0.0, - "people_affected_pct": 0.0, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 2, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 3, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 4, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 5, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 6, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 7, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 8, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 9, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - }, - { - "decile": 10, - "mean_household_change_gbp": 0.0, - "income_change_pct": 0.0 - } - ] - }, - "2027": { - "budget_change_gbp_bn": -0.11211049920380475, - "mean_household_change_gbp": 3.8265768397370326, - "people_affected_pct": 0.927300325538701, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": 0.8282869579049835, - "income_change_pct": 0.003201804405520605 - }, - { - "decile": 2, - "mean_household_change_gbp": 3.3868711859576655, - "income_change_pct": 0.00848994523446706 - }, - { - "decile": 3, - "mean_household_change_gbp": 1.0358538798379522, - "income_change_pct": 0.002324060258470595 - }, - { - "decile": 4, - "mean_household_change_gbp": 0.4511768558204679, - "income_change_pct": 0.0009340501013965675 - }, - { - "decile": 5, - "mean_household_change_gbp": 2.110421363657789, - "income_change_pct": 0.0038839709026547995 - }, - { - "decile": 6, - "mean_household_change_gbp": 3.4306001100428425, - "income_change_pct": 0.005805905900275085 - }, - { - "decile": 7, - "mean_household_change_gbp": 5.727796398009129, - "income_change_pct": 0.00879067009340119 - }, - { - "decile": 8, - "mean_household_change_gbp": 8.569167211108919, - "income_change_pct": 0.011650716272284782 - }, - { - "decile": 9, - "mean_household_change_gbp": 6.179334830941979, - "income_change_pct": 0.007087892928041495 - }, - { - "decile": 10, - "mean_household_change_gbp": 7.026181987372866, - "income_change_pct": 0.004436782564734936 - } - ] - }, - "2028": { - "budget_change_gbp_bn": -0.11978275834096004, - "mean_household_change_gbp": 4.072934905418043, - "people_affected_pct": 0.9286182837759142, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": 0.872907442741444, - "income_change_pct": 0.0033692816571870075 - }, - { - "decile": 2, - "mean_household_change_gbp": 3.6466648968587405, - "income_change_pct": 0.008991585395208439 - }, - { - "decile": 3, - "mean_household_change_gbp": 1.050515189648108, - "income_change_pct": 0.0022976321904294946 - }, - { - "decile": 4, - "mean_household_change_gbp": 0.40590253193385906, - "income_change_pct": 0.0008192749723536514 - }, - { - "decile": 5, - "mean_household_change_gbp": 2.1686078274995624, - "income_change_pct": 0.00395898054233744 - }, - { - "decile": 6, - "mean_household_change_gbp": 3.4802353211278247, - "income_change_pct": 0.0057660373239485025 - }, - { - "decile": 7, - "mean_household_change_gbp": 6.274458616898333, - "income_change_pct": 0.009468814090748174 - }, - { - "decile": 8, - "mean_household_change_gbp": 9.526185755176916, - "income_change_pct": 0.01273089412093796 - }, - { - "decile": 9, - "mean_household_change_gbp": 4.193623637417247, - "income_change_pct": 0.004732639416725624 - }, - { - "decile": 10, - "mean_household_change_gbp": 9.397571571174439, - "income_change_pct": 0.005812898693235177 - } - ] - }, - "2029": { - "budget_change_gbp_bn": -0.11258787723929066, - "mean_household_change_gbp": 3.811119143153684, - "people_affected_pct": 0.8154265353796385, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": 0.5034638546034419, - "income_change_pct": 0.0019174632572421628 - }, - { - "decile": 2, - "mean_household_change_gbp": 2.691709987994653, - "income_change_pct": 0.006569355841784248 - }, - { - "decile": 3, - "mean_household_change_gbp": 1.1172971606173472, - "income_change_pct": 0.002407751503349727 - }, - { - "decile": 4, - "mean_household_change_gbp": 0.42974337440005095, - "income_change_pct": 0.000854303077646435 - }, - { - "decile": 5, - "mean_household_change_gbp": 1.422505664856513, - "income_change_pct": 0.0025516049386295437 - }, - { - "decile": 6, - "mean_household_change_gbp": 3.10132878485467, - "income_change_pct": 0.005064605259166233 - }, - { - "decile": 7, - "mean_household_change_gbp": 5.432430546650813, - "income_change_pct": 0.008056074634453826 - }, - { - "decile": 8, - "mean_household_change_gbp": 10.003191487338368, - "income_change_pct": 0.01316961673282176 - }, - { - "decile": 9, - "mean_household_change_gbp": 4.052024387895121, - "income_change_pct": 0.00451066861447806 - }, - { - "decile": 10, - "mean_household_change_gbp": 9.649605980998823, - "income_change_pct": 0.005852664893579923 - } - ] - }, - "2030": { - "budget_change_gbp_bn": -0.12346843268843957, - "mean_household_change_gbp": 4.160227660123491, - "people_affected_pct": 0.8380164892515954, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": 0.5767920953669808, - "income_change_pct": 0.0021601585192287773 - }, - { - "decile": 2, - "mean_household_change_gbp": 2.775295760757472, - "income_change_pct": 0.0067302583689375995 - }, - { - "decile": 3, - "mean_household_change_gbp": 1.1945629291412128, - "income_change_pct": 0.002524610154941521 - }, - { - "decile": 4, - "mean_household_change_gbp": 0.4557512078379667, - "income_change_pct": 0.0008945494080537144 - }, - { - "decile": 5, - "mean_household_change_gbp": 1.4676819568528197, - "income_change_pct": 0.0025898917900408487 - }, - { - "decile": 6, - "mean_household_change_gbp": 3.776272166780537, - "income_change_pct": 0.006032153961907541 - }, - { - "decile": 7, - "mean_household_change_gbp": 5.069190471410754, - "income_change_pct": 0.007399147041305793 - }, - { - "decile": 8, - "mean_household_change_gbp": 11.055837353722, - "income_change_pct": 0.01427555034554112 - }, - { - "decile": 9, - "mean_household_change_gbp": 5.443441193244057, - "income_change_pct": 0.005970035215584783 - }, - { - "decile": 10, - "mean_household_change_gbp": 10.152307691098917, - "income_change_pct": 0.0060008313868543375 - } - ] - }, - "2031": { - "budget_change_gbp_bn": -0.1310177297120496, - "mean_household_change_gbp": 4.395753554915857, - "people_affected_pct": 0.812193590620492, - "deciles": [ - { - "decile": 1, - "mean_household_change_gbp": 0.5941561456709603, - "income_change_pct": 0.0022015391725468156 - }, - { - "decile": 2, - "mean_household_change_gbp": 2.9888686555262742, - "income_change_pct": 0.007144984454694446 - }, - { - "decile": 3, - "mean_household_change_gbp": 1.6211406745780168, - "income_change_pct": 0.003383954703403833 - }, - { - "decile": 4, - "mean_household_change_gbp": 0.4760062856654819, - "income_change_pct": 0.000913403041332967 - }, - { - "decile": 5, - "mean_household_change_gbp": 1.547667019974265, - "income_change_pct": 0.0026880607082914415 - }, - { - "decile": 6, - "mean_household_change_gbp": 3.862405668151834, - "income_change_pct": 0.006072062445056921 - }, - { - "decile": 7, - "mean_household_change_gbp": 5.309079871383469, - "income_change_pct": 0.007555658253083922 - }, - { - "decile": 8, - "mean_household_change_gbp": 12.260235155552552, - "income_change_pct": 0.015492953295148063 - }, - { - "decile": 9, - "mean_household_change_gbp": 6.069320375527061, - "income_change_pct": 0.006606635622003341 - }, - { - "decile": 10, - "mean_household_change_gbp": 9.690703552604862, - "income_change_pct": 0.005564027124521743 - } - ] - } - } - } - } -} diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/budgetary_impact.csv b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/budgetary_impact.csv deleted file mode 100644 index 843856403..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/budgetary_impact.csv +++ /dev/null @@ -1,7 +0,0 @@ -reform_id,reform_name,year,value -trading_allowance_raise,"Trading allowance raised to £3,000",2026,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,-0.11211049920380475 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,-0.11978275834096004 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,-0.11258787723929066 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,-0.12346843268843957 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,-0.1310177297120496 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/distributional_impact.csv b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/distributional_impact.csv deleted file mode 100644 index 0511c06ff..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/distributional_impact.csv +++ /dev/null @@ -1,61 +0,0 @@ -reform_id,reform_name,year,decile,value -trading_allowance_raise,"Trading allowance raised to £3,000",2026,10th,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,1st,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,2nd,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,3rd,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,4th,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,5th,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,6th,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,7th,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,8th,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,9th,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,10th,0.004436782564734936 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,1st,0.003201804405520605 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,2nd,0.00848994523446706 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,3rd,0.002324060258470595 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,4th,0.0009340501013965675 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,5th,0.0038839709026547995 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,6th,0.005805905900275085 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,7th,0.00879067009340119 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,8th,0.011650716272284782 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,9th,0.007087892928041495 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,10th,0.005812898693235177 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,1st,0.0033692816571870075 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,2nd,0.008991585395208439 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,3rd,0.0022976321904294946 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,4th,0.0008192749723536514 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,5th,0.00395898054233744 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,6th,0.0057660373239485025 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,7th,0.009468814090748174 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,8th,0.01273089412093796 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,9th,0.004732639416725624 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,10th,0.005852664893579923 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,1st,0.0019174632572421628 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,2nd,0.006569355841784248 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,3rd,0.002407751503349727 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,4th,0.000854303077646435 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,5th,0.0025516049386295437 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,6th,0.005064605259166233 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,7th,0.008056074634453826 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,8th,0.01316961673282176 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,9th,0.00451066861447806 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,10th,0.0060008313868543375 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,1st,0.0021601585192287773 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,2nd,0.0067302583689375995 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,3rd,0.002524610154941521 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,4th,0.0008945494080537144 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,5th,0.0025898917900408487 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,6th,0.006032153961907541 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,7th,0.007399147041305793 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,8th,0.01427555034554112 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,9th,0.005970035215584783 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,10th,0.005564027124521743 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,1st,0.0022015391725468156 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,2nd,0.007144984454694446 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,3rd,0.003383954703403833 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,4th,0.000913403041332967 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,5th,0.0026880607082914415 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,6th,0.006072062445056921 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,7th,0.007555658253083922 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,8th,0.015492953295148063 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,9th,0.006606635622003341 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/metrics.csv b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/metrics.csv deleted file mode 100644 index 11310714a..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/metrics.csv +++ /dev/null @@ -1,7 +0,0 @@ -reform_id,reform_name,year,people_affected,gini_change,poverty_change_pp,poverty_change_pct -trading_allowance_raise,"Trading allowance raised to £3,000",2026,0.0,0.0,0.0,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,0.927300325538701,-8.349973017775194e-07,0.0,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,0.9286182837759142,-3.244415933840377e-07,0.0,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,0.8154265353796385,9.16297028044841e-06,0.0,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,0.8380164892515954,9.96113804150047e-06,0.0,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,0.812193590620492,5.42499477041384e-06,0.0,0.0 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/receipt.json b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/receipt.json deleted file mode 100644 index 90dd8831f..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/receipt.json +++ /dev/null @@ -1,453 +0,0 @@ -{ - "dashboard": { - "basis": { - "calibration": { - "source": "the certified dataset pinned by the installed policyengine bundle: Microcosm UK from policyengine 6.10.1, policyengine-uk-data before it", - "status": "pre_budget", - "vintage": "as pinned by the installed bundle" - }, - "forecast": { - "source": "OBR EFO October 2026", - "status": "updated", - "vintage": "OBR Economic and fiscal outlook, October 2026 (Annex A, Tables A.1 and A.3), applied over policyengine-uk's March 2026 growth rates by src/uk_budget_data/forecast/obr_october_2026.json" - }, - "notes": "The forecast is rebased on the Budget's OBR forecast: every simulation, baseline and reform alike, is built on the October 2026 growth rates in src/uk_budget_data/forecast/obr_october_2026.json (CPI, RPI, average earnings, house prices; the September 2027 CPI gap). Series that file does not list keep the March 2026 path the installed policyengine-uk ships; the receipt records the exact model version." - }, - "composition": null, - "config_baseline": { - "binding": "content", - "kind": "current_law", - "name": "configured baseline", - "reform_sha256": null, - "representation": null - }, - "data_limits": [], - "data_limits_registry_sha256": "c48a8fe082168969b5c3e6d6689a630c9f47ac64fa9de7efd11a055d2cab1a4b", - "dataset_years": [ - 2024, - 2025, - 2026, - 2027, - 2028, - 2029, - 2030, - 2031, - 2032 - ], - "description": "From 6 April 2027 the trading allowance, which relieves trading receipts in place of actual expenses, rises from \u00a31,000 to \u00a33,000, for income tax and Class 4 National Insurance. Without gross receipts in the data, a profit within the allowance is treated as fully relieved, so the cost may be overstated.", - "digests": { - "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", - "outputs_sha256": "c98e404df6c02459d8d1c10e8de5417ac538fd7876f2048f7bfcd0c48598d7bc", - "receipt_sha256": "12e5b9f9ecaa3c9f6e967ad30a71c26e0156a8468a8edde5377a1400393a0f3c" - }, - "disclosure_floor": { - "checked": true, - "survey_households": 3, - "thin_cells": [ - { - "groups": [ - "0", - "1", - "10", - "11", - "14", - "15", - "16", - "17", - "19", - "20", - "21", - "22", - "23", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "45", - "48", - "5", - "50", - "53", - "55", - "59", - "61", - "62", - "65", - "7", - "70", - "71", - "72", - "76", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2027 - }, - { - "groups": [ - "0", - "1", - "10", - "11", - "14", - "15", - "16", - "17", - "19", - "20", - "21", - "22", - "23", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "45", - "48", - "5", - "50", - "53", - "55", - "59", - "61", - "62", - "65", - "7", - "70", - "71", - "72", - "76", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2028 - }, - { - "groups": [ - "0", - "1", - "10", - "11", - "15", - "16", - "17", - "18", - "20", - "21", - "22", - "23", - "24", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "48", - "49", - "5", - "52", - "53", - "54", - "55", - "59", - "61", - "62", - "64", - "65", - "7", - "70", - "71", - "72", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2029 - }, - { - "groups": [ - "0", - "1", - "10", - "11", - "15", - "16", - "17", - "18", - "21", - "22", - "24", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "48", - "49", - "5", - "52", - "53", - "55", - "59", - "62", - "64", - "65", - "7", - "70", - "71", - "72", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2030 - }, - { - "groups": [ - "0", - "1", - "10", - "11", - "15", - "16", - "17", - "18", - "21", - "22", - "24", - "25", - "26", - "27", - "29", - "30", - "31", - "32", - "34", - "35", - "36", - "38", - "40", - "41", - "44", - "48", - "49", - "5", - "52", - "53", - "55", - "59", - "62", - "65", - "7", - "70", - "71", - "72", - "78", - "79", - "8", - "80", - "82", - "86", - "87", - "88", - "89" - ], - "table": "age_impact", - "year": 2031 - } - ], - "thin_cells_in_tables": false - }, - "files": { - "age_impact.csv": "fba108ffa8b12d2e543a743a4646cb894be14f568377fd46734cd60cd0333af2", - "budgetary_impact.csv": "ed71cf21bfd60b0044cc27868d24b08ab26e415241e1b3eff34b130051c0581b", - "distributional_impact.csv": "18670f3ed2936a5b4e5a94c1c5c6f961b9ad6c47c37a4245cb7789afc09a8a01", - "household_scatter_binned.csv": "d622c921d9da66b23c55910ca01559dfce1d241e95c890c2a3ff4d4f08471fe3", - "income_curve.csv": "447037ac0bdf9f0bde2083a9a0c56764aa0d9dc2e76010c841a70edf3b8ce192", - "metrics.csv": "e6d47c154d8a4b696e2ee7cab5d96d95ce30721945a4b29ec26279a498175627", - "poverty_inequality.csv": "c0a5c9a2b989cb2ce417faf6bd6f03f6fc0c48ad88f1ce5f4229bde2c25956d8", - "winners_losers.csv": "8652a18c4dc237cfb7815000cc40d752176631c3fbd132bd3795f847dced9894" - }, - "generated_at": "2026-10-28T14:34:31.676559+00:00", - "generator_argv": [ - "/private/tmp/claude-501/-Users-vahid/59114aef-a9b7-4663-a8bc-32b2c6146551/scratchpad/run7/src/uk_budget_data/cli.py", - "generate", - "--artifacts", - "--backend", - "modal", - "--reforms", - "trading_allowance_raise" - ], - "git_sha": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", - "key": "trading_allowance_raise", - "measure_ids": [ - "trading_allowance_raise" - ], - "member_outputs_sha256": null, - "members": null, - "model_limits": [], - "model_limits_registry_sha256": "9d3479f1f5ac859ab6bd2644aaff443a29c0dad3f2944b1ef98866028f9d4b89", - "modifier_templates": { - "baseline": [], - "reform": [] - }, - "name": "Trading allowance raised to \u00a33,000", - "publishable": true, - "reasons": [], - "receipt_source": "policyengine==6.11.1", - "tree_clean": true, - "unsupported_years": [] - }, - "execution_receipt": { - "baseline": { - "binding": "content", - "kind": "current_law", - "name": "trading_allowance_raise baseline" - }, - "certificate": { - "bundle_version": "6.11.1", - "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", - "certificate_source": "packaged", - "certified_by": "policyengine.py bundle certification", - "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "certified_for_core_version": "3.33.3", - "certified_for_model_version": "2.151.0", - "compatibility_basis": "built_with_model_package", - "country_id": "uk", - "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" - }, - "certification_status": "certified", - "core": { - "name": "policyengine-core", - "version": "3.33.3" - }, - "country_id": "uk", - "data": { - "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "build_model_version": "2.151.0", - "data_package": "microcosm-data", - "dataset": "microcosm_uk_2024_25", - "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_version": "0.1.0" - }, - "fiscal_year": { - "convention": "uk_fiscal_year", - "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", - "period_start": "04-06", - "year_label": "start_year" - }, - "model": { - "name": "policyengine-uk", - "version": "2.151.0" - }, - "outputs_sha256": "c98e404df6c02459d8d1c10e8de5417ac538fd7876f2048f7bfcd0c48598d7bc", - "receipt_type": "policyengine.execution_receipt", - "reform": { - "binding": "content", - "kind": "reform", - "name": "trading_allowance_raise", - "reform_sha256": "cdcc8b19d5234afe31ae857db16a8f2d6a18578a1d7da1c890b3c5f21832c268", - "representation": "policyengine-uk.scenario/v1" - }, - "runtime": { - "platform": "linux", - "python_version": "3.13.3" - }, - "schema_version": 1, - "supported_years": [ - 2024, - 2025, - 2026, - 2027, - 2028, - 2029, - 2030, - 2031, - 2032 - ], - "wrapper": { - "name": "policyengine", - "version": "6.11.1" - }, - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - }, - "schema": "uk-budget-dashboard/artifact-receipt/v1" -} diff --git a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/winners_losers.csv b/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/winners_losers.csv deleted file mode 100644 index aa99d9ba8..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/trading_allowance_raise/winners_losers.csv +++ /dev/null @@ -1,67 +0,0 @@ -reform_id,reform_name,year,decile,avg_change -trading_allowance_raise,"Trading allowance raised to £3,000",2026,1,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,10,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,2,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,3,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,4,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,5,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,6,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,7,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,8,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,9,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2026,all,0.0 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,1,0.8282869579049835 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,10,7.026181987372866 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,2,3.3868711859576655 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,3,1.0358538798379522 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,4,0.4511768558204679 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,5,2.110421363657789 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,6,3.4306001100428425 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,7,5.727796398009129 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,8,8.569167211108919 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,9,6.179334830941979 -trading_allowance_raise,"Trading allowance raised to £3,000",2027,all,3.8265768397370326 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,1,0.872907442741444 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,10,9.397571571174439 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,2,3.6466648968587405 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,3,1.050515189648108 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,4,0.40590253193385906 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,5,2.1686078274995624 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,6,3.4802353211278247 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,7,6.274458616898333 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,8,9.526185755176916 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,9,4.193623637417247 -trading_allowance_raise,"Trading allowance raised to £3,000",2028,all,4.072934905418043 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,1,0.5034638546034419 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,10,9.649605980998823 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,2,2.691709987994653 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,3,1.1172971606173472 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,4,0.42974337440005095 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,5,1.422505664856513 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,6,3.10132878485467 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,7,5.432430546650813 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,8,10.003191487338368 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,9,4.052024387895121 -trading_allowance_raise,"Trading allowance raised to £3,000",2029,all,3.811119143153684 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,1,0.5767920953669808 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,10,10.152307691098917 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,2,2.775295760757472 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,3,1.1945629291412128 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,4,0.4557512078379667 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,5,1.4676819568528197 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,6,3.776272166780537 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,7,5.069190471410754 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,8,11.055837353722 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,9,5.443441193244057 -trading_allowance_raise,"Trading allowance raised to £3,000",2030,all,4.160227660123491 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,1,0.5941561456709603 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,10,9.690703552604862 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,2,2.9888686555262742 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,3,1.6211406745780168 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,4,0.4760062856654819 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,5,1.547667019974265 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,6,3.862405668151834 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,7,5.309079871383469 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,8,12.260235155552552 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,9,6.069320375527061 -trading_allowance_raise,"Trading allowance raised to £3,000",2031,all,4.395753554915857 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/budgetary_impact.csv b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/budgetary_impact.csv deleted file mode 100644 index da37a0595..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/budgetary_impact.csv +++ /dev/null @@ -1,7 +0,0 @@ -reform_id,reform_name,year,value -unearned_income_rates_up,Savings and property income tax rates up,2026,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2027,0.6642382271213031 -unearned_income_rates_up,Savings and property income tax rates up,2028,0.6957731772288318 -unearned_income_rates_up,Savings and property income tax rates up,2029,0.7276593169820835 -unearned_income_rates_up,Savings and property income tax rates up,2030,0.7623675377687243 -unearned_income_rates_up,Savings and property income tax rates up,2031,0.7933736065368444 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/distributional_impact.csv b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/distributional_impact.csv deleted file mode 100644 index 2d308558a..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/distributional_impact.csv +++ /dev/null @@ -1,61 +0,0 @@ -reform_id,reform_name,year,decile,value -unearned_income_rates_up,Savings and property income tax rates up,2026,10th,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,1st,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,2nd,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,3rd,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,4th,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,5th,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,6th,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,7th,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,8th,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,9th,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2027,10th,-0.06764978971604362 -unearned_income_rates_up,Savings and property income tax rates up,2027,1st,-0.04985863048727435 -unearned_income_rates_up,Savings and property income tax rates up,2027,2nd,-0.014274726231957425 -unearned_income_rates_up,Savings and property income tax rates up,2027,3rd,-0.01493700611440189 -unearned_income_rates_up,Savings and property income tax rates up,2027,4th,-0.015130665063043254 -unearned_income_rates_up,Savings and property income tax rates up,2027,5th,-0.011040999093289379 -unearned_income_rates_up,Savings and property income tax rates up,2027,6th,-0.015457392166954702 -unearned_income_rates_up,Savings and property income tax rates up,2027,7th,-0.01679145061801241 -unearned_income_rates_up,Savings and property income tax rates up,2027,8th,-0.02924222878277037 -unearned_income_rates_up,Savings and property income tax rates up,2027,9th,-0.0424816465100822 -unearned_income_rates_up,Savings and property income tax rates up,2028,10th,-0.0691861186482591 -unearned_income_rates_up,Savings and property income tax rates up,2028,1st,-0.051797994354371796 -unearned_income_rates_up,Savings and property income tax rates up,2028,2nd,-0.01562814402382634 -unearned_income_rates_up,Savings and property income tax rates up,2028,3rd,-0.01507923160657066 -unearned_income_rates_up,Savings and property income tax rates up,2028,4th,-0.015199990369575169 -unearned_income_rates_up,Savings and property income tax rates up,2028,5th,-0.012557869706653325 -unearned_income_rates_up,Savings and property income tax rates up,2028,6th,-0.014460880161614037 -unearned_income_rates_up,Savings and property income tax rates up,2028,7th,-0.017821793400241998 -unearned_income_rates_up,Savings and property income tax rates up,2028,8th,-0.030450986910411898 -unearned_income_rates_up,Savings and property income tax rates up,2028,9th,-0.04241102691117292 -unearned_income_rates_up,Savings and property income tax rates up,2029,10th,-0.07041327236762773 -unearned_income_rates_up,Savings and property income tax rates up,2029,1st,-0.05322985172426894 -unearned_income_rates_up,Savings and property income tax rates up,2029,2nd,-0.015861030033688512 -unearned_income_rates_up,Savings and property income tax rates up,2029,3rd,-0.015820633619852753 -unearned_income_rates_up,Savings and property income tax rates up,2029,4th,-0.016640010814691405 -unearned_income_rates_up,Savings and property income tax rates up,2029,5th,-0.01186750640488552 -unearned_income_rates_up,Savings and property income tax rates up,2029,6th,-0.014739892298832517 -unearned_income_rates_up,Savings and property income tax rates up,2029,7th,-0.019256034827620797 -unearned_income_rates_up,Savings and property income tax rates up,2029,8th,-0.031114843422502994 -unearned_income_rates_up,Savings and property income tax rates up,2029,9th,-0.04317103405831868 -unearned_income_rates_up,Savings and property income tax rates up,2030,10th,-0.07181165560065904 -unearned_income_rates_up,Savings and property income tax rates up,2030,1st,-0.05610692023915448 -unearned_income_rates_up,Savings and property income tax rates up,2030,2nd,-0.015838490300712545 -unearned_income_rates_up,Savings and property income tax rates up,2030,3rd,-0.016970819222280532 -unearned_income_rates_up,Savings and property income tax rates up,2030,4th,-0.01437706071070637 -unearned_income_rates_up,Savings and property income tax rates up,2030,5th,-0.014513169605216732 -unearned_income_rates_up,Savings and property income tax rates up,2030,6th,-0.010245777552623752 -unearned_income_rates_up,Savings and property income tax rates up,2030,7th,-0.024164401723622005 -unearned_income_rates_up,Savings and property income tax rates up,2030,8th,-0.03191810416734249 -unearned_income_rates_up,Savings and property income tax rates up,2030,9th,-0.04373162273763173 -unearned_income_rates_up,Savings and property income tax rates up,2031,10th,-0.07173645374140333 -unearned_income_rates_up,Savings and property income tax rates up,2031,1st,-0.05832341572449926 -unearned_income_rates_up,Savings and property income tax rates up,2031,2nd,-0.014635606422439709 -unearned_income_rates_up,Savings and property income tax rates up,2031,3rd,-0.017848939980989183 -unearned_income_rates_up,Savings and property income tax rates up,2031,4th,-0.014809745978892685 -unearned_income_rates_up,Savings and property income tax rates up,2031,5th,-0.014729454378751861 -unearned_income_rates_up,Savings and property income tax rates up,2031,6th,-0.010139823686994792 -unearned_income_rates_up,Savings and property income tax rates up,2031,7th,-0.025662723350375474 -unearned_income_rates_up,Savings and property income tax rates up,2031,8th,-0.03178995628746156 -unearned_income_rates_up,Savings and property income tax rates up,2031,9th,-0.04569066183442702 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/metrics.csv b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/metrics.csv deleted file mode 100644 index dfb46f33e..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/metrics.csv +++ /dev/null @@ -1,7 +0,0 @@ -reform_id,reform_name,year,people_affected,gini_change,poverty_change_pp,poverty_change_pct -unearned_income_rates_up,Savings and property income tax rates up,2026,0.0,0.0,0.0,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2027,10.673344206596365,-0.00028251218573879843,0.00028419495,0.002069667 -unearned_income_rates_up,Savings and property income tax rates up,2028,11.008162293996863,-0.00028521977216218057,0.0026416779,0.019280192 -unearned_income_rates_up,Savings and property income tax rates up,2029,11.211334671637678,-0.0002876005452886594,0.0005235672,0.0038050439 -unearned_income_rates_up,Savings and property income tax rates up,2030,11.515220448098733,-0.0002894803540428024,0.0011587143,0.008401513 -unearned_income_rates_up,Savings and property income tax rates up,2031,11.677047270799843,-0.0002925173508581513,0.0025806427,0.018773075 diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/receipt.json b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/receipt.json deleted file mode 100644 index 886a56441..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/receipt.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "dashboard": { - "basis": { - "calibration": { - "source": "the certified dataset pinned by the installed policyengine bundle: Microcosm UK from policyengine 6.10.1, policyengine-uk-data before it", - "status": "pre_budget", - "vintage": "as pinned by the installed bundle" - }, - "forecast": { - "source": "OBR EFO October 2026", - "status": "updated", - "vintage": "OBR Economic and fiscal outlook, October 2026 (Annex A, Tables A.1 and A.3), applied over policyengine-uk's March 2026 growth rates by src/uk_budget_data/forecast/obr_october_2026.json" - }, - "notes": "The forecast is rebased on the Budget's OBR forecast: every simulation, baseline and reform alike, is built on the October 2026 growth rates in src/uk_budget_data/forecast/obr_october_2026.json (CPI, RPI, average earnings, house prices; the September 2027 CPI gap). Series that file does not list keep the March 2026 path the installed policyengine-uk ships; the receipt records the exact model version." - }, - "composition": null, - "config_baseline": { - "binding": "content", - "kind": "current_law", - "name": "configured baseline", - "reform_sha256": null, - "representation": null - }, - "data_limits": [], - "data_limits_registry_sha256": "c48a8fe082168969b5c3e6d6689a630c9f47ac64fa9de7efd11a055d2cab1a4b", - "dataset_years": [ - 2024, - 2025, - 2026, - 2027, - 2028, - 2029, - 2030, - 2031, - 2032 - ], - "description": "From 6 April 2027 the income tax rates on savings income rise to 24%, 44% and 49% at the basic, higher and additional rates across the UK, and those on property income to the same rates in England, Wales and Northern Ireland: 2 percentage points above current law, which already includes Budget 2025's rises. Finance cost relief for landlords follows the property basic rate, so rises to 24%. Dividend rates are unchanged. Incomes are held fixed, with no behavioural response.", - "digests": { - "execution_identity_sha256": "3db871d8c1fcebfefdfd938e39512408196621a4f5d7374ad3abd5b586dc0d03", - "outputs_sha256": "1315fa74166dfa15139fe4693bf7df5654244db1b39b8159a0a64e5c64bfe508", - "receipt_sha256": "4d8611bcb02d626dd6a9170d8564325ef8cc10266fb1b62485f604571a3413f4" - }, - "disclosure_floor": { - "checked": true, - "survey_households": 3, - "thin_cells": [], - "thin_cells_in_tables": false - }, - "files": { - "age_impact.csv": "2c5ead6535d59e4ca507059d280ee8543d5ff39d6759ec3b86ebbbb35f54b2c5", - "budgetary_impact.csv": "76a9bcf35b7427af58098ef063a873afdff4b3eccc84b55782b5e7bfc9595bc0", - "distributional_impact.csv": "0d7fc5da79518ad6e255acfd7fb5469eb483117849afea8a2db57c70e936ba48", - "household_scatter_binned.csv": "1930be90eda9c3459a493fc3b2b51626fac93653fd5b22214746e04bcb31d7b3", - "income_curve.csv": "1b470f7215bf16eed979f987e0f87575bb78cfe8a077c9ecbf47e3fbe175dde4", - "metrics.csv": "abf2e4f4fdc4276588ac2d89fdec83df246aa517fda8590fd20d3ccd368aa15c", - "poverty_inequality.csv": "e0ae3a92c9f2341fdd61f51cefd752f307b78e8fd1f9badf9abb153c4a7d76f3", - "winners_losers.csv": "651d1c59976cdb1faab8d5f87ef9099aa67eb37d6c24f85707088e09f27aa8f0" - }, - "generated_at": "2026-10-28T14:34:26.864876+00:00", - "generator_argv": [ - "/private/tmp/claude-501/-Users-vahid/59114aef-a9b7-4663-a8bc-32b2c6146551/scratchpad/run7/src/uk_budget_data/cli.py", - "generate", - "--artifacts", - "--backend", - "modal", - "--reforms", - "unearned_income_rates_up" - ], - "git_sha": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", - "key": "unearned_income_rates_up", - "measure_ids": [ - "unearned_income_rates_up" - ], - "member_outputs_sha256": null, - "members": null, - "model_limits": [], - "model_limits_registry_sha256": "9d3479f1f5ac859ab6bd2644aaff443a29c0dad3f2944b1ef98866028f9d4b89", - "modifier_templates": { - "baseline": [], - "reform": [] - }, - "name": "Savings and property income tax rates up", - "publishable": true, - "reasons": [], - "receipt_source": "policyengine==6.11.1", - "tree_clean": true, - "unsupported_years": [] - }, - "execution_receipt": { - "baseline": { - "binding": "content", - "kind": "current_law", - "name": "unearned_income_rates_up baseline" - }, - "certificate": { - "bundle_version": "6.11.1", - "certificate_sha256": "f2e6fc9faafab32b50c1c76067fb070ae9686b6f375e44417776de16e9c3521f", - "certificate_source": "packaged", - "certified_by": "policyengine.py bundle certification", - "certified_dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "certified_for_core_version": "3.33.3", - "certified_for_model_version": "2.151.0", - "compatibility_basis": "built_with_model_package", - "country_id": "uk", - "tro_composition_fingerprint": "ec8e6c4194b5e1ec0acd64c8718d0eecb6b41648b53f0b453c425b516e5a4489" - }, - "certification_status": "certified", - "core": { - "name": "policyengine-core", - "version": "3.33.3" - }, - "country_id": "uk", - "data": { - "build_id": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "build_model_version": "2.151.0", - "data_package": "microcosm-data", - "dataset": "microcosm_uk_2024_25", - "dataset_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "dataset_sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", - "dataset_uri": "hf://policyengine/populace-uk-private/microcosm_uk_2024_25.h5@microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_manifest_revision": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", - "release_version": "0.1.0" - }, - "fiscal_year": { - "convention": "uk_fiscal_year", - "parameter_annualisation": "policyengine-uk/fiscal-year-parameters", - "period_start": "04-06", - "year_label": "start_year" - }, - "model": { - "name": "policyengine-uk", - "version": "2.151.0" - }, - "outputs_sha256": "1315fa74166dfa15139fe4693bf7df5654244db1b39b8159a0a64e5c64bfe508", - "receipt_type": "policyengine.execution_receipt", - "reform": { - "binding": "content", - "kind": "reform", - "name": "unearned_income_rates_up", - "reform_sha256": "e6238a8a012d3dba63b67c75f812ef5cf7931ee8ca17c35720a94ef520979638", - "representation": "policyengine-uk.scenario/v1" - }, - "runtime": { - "platform": "linux", - "python_version": "3.13.3" - }, - "schema_version": 1, - "supported_years": [ - 2024, - 2025, - 2026, - 2027, - 2028, - 2029, - 2030, - 2031, - 2032 - ], - "wrapper": { - "name": "policyengine", - "version": "6.11.1" - }, - "years": [ - 2026, - 2027, - 2028, - 2029, - 2030, - 2031 - ] - }, - "schema": "uk-budget-dashboard/artifact-receipt/v1" -} diff --git a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/winners_losers.csv b/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/winners_losers.csv deleted file mode 100644 index 630647b07..000000000 --- a/analysis/uk-budget-2026-income-tax/population-preview/unearned_income_rates_up/winners_losers.csv +++ /dev/null @@ -1,67 +0,0 @@ -reform_id,reform_name,year,decile,avg_change -unearned_income_rates_up,Savings and property income tax rates up,2026,1,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,10,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,2,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,3,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,4,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,5,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,6,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,7,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,8,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,9,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2026,all,0.0 -unearned_income_rates_up,Savings and property income tax rates up,2027,1,-12.898118729678712 -unearned_income_rates_up,Savings and property income tax rates up,2027,10,-107.13162680777542 -unearned_income_rates_up,Savings and property income tax rates up,2027,2,-5.694578425096933 -unearned_income_rates_up,Savings and property income tax rates up,2027,3,-6.657553598437464 -unearned_income_rates_up,Savings and property income tax rates up,2027,4,-7.308607835285808 -unearned_income_rates_up,Savings and property income tax rates up,2027,5,-5.999313832829491 -unearned_income_rates_up,Savings and property income tax rates up,2027,6,-9.133481007058295 -unearned_income_rates_up,Savings and property income tax rates up,2027,7,-10.940919104608044 -unearned_income_rates_up,Savings and property income tax rates up,2027,8,-21.5078233997643 -unearned_income_rates_up,Savings and property income tax rates up,2027,9,-37.036157377175726 -unearned_income_rates_up,Savings and property income tax rates up,2027,all,-22.671638846816318 -unearned_income_rates_up,Savings and property income tax rates up,2028,1,-13.41973138237426 -unearned_income_rates_up,Savings and property income tax rates up,2028,10,-111.85151093127375 -unearned_income_rates_up,Savings and property income tax rates up,2028,2,-6.338215310184361 -unearned_income_rates_up,Savings and property income tax rates up,2028,3,-6.89447245599531 -unearned_income_rates_up,Savings and property income tax rates up,2028,4,-7.530700661654769 -unearned_income_rates_up,Savings and property income tax rates up,2028,5,-6.8788149502975875 -unearned_income_rates_up,Savings and property income tax rates up,2028,6,-8.728224096645702 -unearned_income_rates_up,Savings and property income tax rates up,2028,7,-11.809515330751909 -unearned_income_rates_up,Savings and property income tax rates up,2028,8,-22.785654721608235 -unearned_income_rates_up,Savings and property income tax rates up,2028,9,-37.58069636855771 -unearned_income_rates_up,Savings and property income tax rates up,2028,all,-23.653364852788222 -unearned_income_rates_up,Savings and property income tax rates up,2029,1,-13.976437998407777 -unearned_income_rates_up,Savings and property income tax rates up,2029,10,-116.09418043491492 -unearned_income_rates_up,Savings and property income tax rates up,2029,2,-6.498855289587565 -unearned_income_rates_up,Savings and property income tax rates up,2029,3,-7.341434113128795 -unearned_income_rates_up,Savings and property income tax rates up,2029,4,-8.370488863576746 -unearned_income_rates_up,Savings and property income tax rates up,2029,5,-6.616069295483351 -unearned_income_rates_up,Savings and property income tax rates up,2029,6,-9.026024721135434 -unearned_income_rates_up,Savings and property income tax rates up,2029,7,-12.984868754512368 -unearned_income_rates_up,Savings and property income tax rates up,2029,8,-23.63377334118966 -unearned_income_rates_up,Savings and property income tax rates up,2029,9,-38.78140865712871 -unearned_income_rates_up,Savings and property income tax rates up,2029,all,-24.629016272903616 -unearned_income_rates_up,Savings and property income tax rates up,2030,1,-14.981320954576939 -unearned_income_rates_up,Savings and property income tax rates up,2030,10,-121.49216941209389 -unearned_income_rates_up,Savings and property income tax rates up,2030,2,-6.531174968146814 -unearned_income_rates_up,Savings and property income tax rates up,2030,3,-8.030036431729007 -unearned_income_rates_up,Savings and property income tax rates up,2030,4,-7.324763422872621 -unearned_income_rates_up,Savings and property income tax rates up,2030,5,-8.224558743431283 -unearned_income_rates_up,Savings and property income tax rates up,2030,6,-6.414100973437806 -unearned_income_rates_up,Savings and property income tax rates up,2030,7,-16.555145381069313 -unearned_income_rates_up,Savings and property income tax rates up,2030,8,-24.719282953845298 -unearned_income_rates_up,Savings and property income tax rates up,2030,9,-39.874223193190204 -unearned_income_rates_up,Savings and property income tax rates up,2030,all,-25.68817666790038 -unearned_income_rates_up,Savings and property income tax rates up,2031,1,-15.740449373492428 -unearned_income_rates_up,Savings and property income tax rates up,2031,10,-124.94128651158324 -unearned_income_rates_up,Savings and property income tax rates up,2031,2,-6.122323367954729 -unearned_income_rates_up,Savings and property income tax rates up,2031,3,-8.55083626627086 -unearned_income_rates_up,Savings and property income tax rates up,2031,4,-7.717876836466778 -unearned_income_rates_up,Savings and property income tax rates up,2031,5,-8.480571400003587 -unearned_income_rates_up,Savings and property income tax rates up,2031,6,-6.449886317389771 -unearned_income_rates_up,Savings and property income tax rates up,2031,7,-18.032240662651855 -unearned_income_rates_up,Savings and property income tax rates up,2031,8,-25.156749151956337 -unearned_income_rates_up,Savings and property income tax rates up,2031,9,-41.97465710374913 -unearned_income_rates_up,Savings and property income tax rates up,2031,all,-26.618450973449693 diff --git a/analysis/uk-budget-2026-income-tax/property-population/README.md b/analysis/uk-budget-2026-income-tax/property-population/README.md index f4b2cc487..56b5c715f 100644 --- a/analysis/uk-budget-2026-income-tax/property-population/README.md +++ b/analysis/uk-budget-2026-income-tax/property-population/README.md @@ -34,4 +34,4 @@ The official comparison marks 2027–28 and 2028–29 as not comparable; its com - [Treasury row 61 source values](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/data_inputs/treasury/sources/AB2026-T6.1.csv). - [National calculator definitions](https://github.com/PolicyEngine/uk-autumn-budget-dashboard-2026/blob/637bb26c34264e0491ed182c363df751466458ed/src/uk_budget_data/calculators.py). -The other five source CSVs are not copied; their hashes remain as source-verification records in the original receipt and verification summary. No reach, poverty or inequality figures from those files are republished here. This folder supersedes the old combined preview for the property article only. The historical `population-preview/` folder remains unchanged and must not be relabelled as this property-only result. +The other five source CSVs are not copied; their hashes remain as source-verification records in the original receipt and verification summary. No reach, poverty or inequality figures from those files are republished here. This folder is the property article's sole national-results record; withdrawn combined outputs are not published here. diff --git a/analysis/uk-budget-2026-income-tax/provenance.json b/analysis/uk-budget-2026-income-tax/provenance.json index 8e694bcf7..c713c69eb 100644 --- a/analysis/uk-budget-2026-income-tax/provenance.json +++ b/analysis/uk-budget-2026-income-tax/provenance.json @@ -17,7 +17,7 @@ ] }, "population": { - "status": "archived_dashboard_outputs_not_in_current_articles", + "status": "approved_property_branch_snapshot_used_in_property_draft", "dataset": "microcosm-uk-2024-25-national-20261025T091414Z-a6299504", "sha256": "b96a8cd625b645a409c063b1de5158532708a2f0d3c3897a794a8fb0bbd5064e", "certificate": "https://github.com/PolicyEngine/policyengine.py/pull/720", @@ -27,51 +27,13 @@ "replacement_policy": "Retain this adopted bundle until a later explicitly recorded update; do not silently use the candidate in policyengine.py PR725.", "national_results_generated_locally": false, "national_results_reused_from_dashboard": true, - "dashboard_snapshot": { - "manifest_revision": 5, - "manifest_updated_at": "2026-10-28T14:35:54.732859Z", - "fetched_at": "2026-10-28T14:46:46Z", - "base_url": "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/", - "source_commit": "0d9dccb23e4b4181dad49c0004fc9c65348d408b", - "reform_and_forecast_files_match_household_reference": true, - "measures": { - "unearned_income_rates_up": { - "artifact": "artifacts/unearned_income_rates_up/8bd7d211ae66c19d", - "generated_at": "2026-10-28T14:34:26.864876Z" - }, - "trading_allowance_raise": { - "artifact": "artifacts/trading_allowance_raise/230c4665427e0bb1", - "generated_at": "2026-10-28T14:34:31.676559Z" - } - }, - "manifest_status": "provisional", - "reconciliation_status": "awaiting_source", - "combined_artifact_available": false, - "disclosure_floor_survey_households": 3, - "thin_decile_cells_recorded": false, - "limitations": [ - "No absolute affected-person counts or separate winner/loser shares are exported.", - "people_affected is a percentage of people in households whose absolute net-income percentage change exceeds 0.01%; it is not a headcount.", - "Trading gross receipts are missing; the receipt warns this may overstate cost." - ] - }, - "live_source_check": { - "manifest_revision": 17, - "manifest_updated_at": "2026-10-28T16:09:01.451619Z", - "property_income_rates_up": "provisional_reconciliation_failed", - "savings_income_rates_up": "provisional_reconciliation_failed", - "unearned_income_rates_up": "withdrawn_due_to_measure_split", - "new_trading_artifact": "71f8a26e4f547021", - "new_trading_status": "provisional_reconciliation_failed", - "new_trading_dataset_matches_pin": true, - "replacement_adopted": false, - "forecast_note": "Replacement artifacts remain unapproved. The household forecast pin is independent of these national artifacts.", - "property_artifact": "3537bd303ac226cf", - "savings_artifact": "af6aaaee33f616ee", - "source_check_note": "Manifest17 status reported by the parent task during the PTA alignment; manifest_updated_at is the publisher timestamp, not a local fetch timestamp." - }, "article_national_results_published": false, - "article_scope_note": "Both current articles omit earlier model national estimates, decile tables and affected shares. Retained population-preview files are historical public aggregates for reproducibility, not current publication figures. National estimates are linked through the dashboard pending final execution-bound results." + "article_scope_note": "The property draft includes national revenue and decile averages from the approved property-only dashboard artifact recorded in property-population/. Savings and trading retain household calculations and Treasury costings only. Withdrawn combined outputs are not published. Reach, poverty and inequality figures are omitted pending separate disclosure clearance.", + "national_results_record": "property-population/summary.json", + "retained_national_measures": [ + "property_income_rates_up" + ], + "national_results_scope": "Approved property-only national revenue and decile outputs; reach, poverty and inequality outputs are omitted pending separate disclosure clearance." }, "treasury_costings": { "source": "https://www.gov.uk/government/publications/budget-2026-document/budget-2026-html", @@ -117,8 +79,8 @@ "additional_household_pairs": 5, "raw_population_accessed": false, "additional_internal_population_numbers_adopted": false, - "final_regeneration_note": "Detailed October forecast tables and council tax are expected; retain the recorded first-estimate snapshot until replacement outputs bind the exact dataset and forecast.", - "remaining_comments_resolution": "Withdrawn combined national results removed from savings/property, following the same cut-or-match-final-run approach Max applied to trading. Confirmed dashboard household matching, updated canonical links, added primary-source collection-timing explanation and retained separate Treasury costings. Trading whole-year exclusions and pre-switch dashboard wording corrected." + "final_regeneration_note": "Compare the approved property artifact recorded in property-population/ with the final released dashboard before publication; update and review the article if its execution-bound results change.", + "remaining_comments_resolution": "The property draft uses approved property-only national revenue and decile results alongside verified household examples and separate Treasury costings. Savings and trading retain household calculations and Treasury costings only. Withdrawn combined outputs and uncleared reach, poverty and inequality figures are not published." }, "household_forecast": { "dashboard_commit": "640426575270224db9b04d6c94d30e264a347be2", diff --git a/analysis/uk-budget-2026-income-tax/verify_population_preview.py b/analysis/uk-budget-2026-income-tax/verify_population_preview.py deleted file mode 100644 index b494b2ebc..000000000 --- a/analysis/uk-budget-2026-income-tax/verify_population_preview.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Verify the saved public preview aggregates offline and rebuild their summary.""" - -import csv -import hashlib -import json -from pathlib import Path - -BASE = Path(__file__).resolve().parent -SNAPSHOT = BASE / "population-preview" -SOURCE = "https://ab2026-local-preview.vercel.app/uk/autumn-budget-2026/data/" -MEASURES = ("unearned_income_rates_up", "trading_allowance_raise") -TABLES = ("budgetary_impact", "distributional_impact", "winners_losers", "metrics") - - -def require(condition, message): - if not condition: - raise ValueError(message) - - -def read_json(path): - return json.loads(path.read_text()) - - -def main(): - provenance = read_json(BASE / "provenance.json") - manifest = read_json(SNAPSHOT / "manifest.json") - summary = { - "status": "Provisional preview; reconciliation awaiting_source; not final approval", - "manifest_url": SOURCE + "manifest.json", - "manifest_updated_at": manifest["updated_at"], - "manifest_sha256": hashlib.sha256((SNAPSHOT / "manifest.json").read_bytes()).hexdigest(), - "units": { - "budget_change_gbp_bn": "Annual government balance change, GBP billion; positive revenue, negative cost", - "mean_household_change_gbp": "Weighted mean annual net income change, GBP per household; includes unaffected households", - "income_change_pct": "Decile total income change / decile total baseline income * 100", - "people_affected_pct": "Percentage of people in valid-decile households with abs(change / max(baseline income, GBP 1)) > 0.0001", - }, - "limitations": [ - "No affected headcounts, household shares, winner/loser shares or survey support counts exported", - "Static estimates; Treasury post-behavioural fiscal-year forecasts require separate reconciliation", - "Trading allowance lacks gross receipts and may overstate cost", - ], - "measures": {}, - } - for mid in MEASURES: - entry = manifest["measures"][mid] - receipt = read_json(SNAPSHOT / mid / "receipt.json") - dashboard, execution = receipt["dashboard"], receipt["execution_receipt"] - require(entry["status"] == "provisional", f"{mid}: unexpected publication status") - require(entry["reconciliation"]["summary_status"] == "awaiting_source", f"{mid}: unexpected reconciliation") - require(dashboard["publishable"] and execution["certification_status"] == "certified", f"{mid}: not publishable/certified") - for package, key in (("policyengine", "wrapper"), ("policyengine-uk", "model"), ("policyengine-core", "core")): - expected = provenance["package_versions"][package] - require(execution[key]["version"] == expected == manifest["execution"]["identity"][key]["version"], f"{mid}: {package} mismatch") - require(execution["data"]["dataset_sha256"] == provenance["population"]["sha256"], f"{mid}: dataset hash mismatch") - require(manifest["execution"]["identity"]["data"]["dataset_sha256"] == execution["data"]["dataset_sha256"], f"{mid}: manifest dataset mismatch") - require(execution["data"]["build_id"] == provenance["population"]["dataset"], f"{mid}: dataset build mismatch") - require(execution["certificate"]["certified_dataset_sha256"] == execution["data"]["dataset_sha256"], f"{mid}: certificate mismatch") - require(dashboard["digests"]["receipt_sha256"] == entry["receipt_sha256"], f"{mid}: receipt identity mismatch") - floor = dashboard["disclosure_floor"] - require(floor["checked"] and floor["survey_households"] == 3 and not floor["thin_cells_in_tables"], f"{mid}: disclosure floor failed") - require(not any(cell["table"] in TABLES for cell in floor["thin_cells"]), f"{mid}: thin decile cells") - tables = {} - for name in TABLES: - path = SNAPSHOT / mid / f"{name}.csv" - require(hashlib.sha256(path.read_bytes()).hexdigest() == dashboard["files"][path.name], f"{mid}: {path.name} hash mismatch") - tables[name] = list(csv.DictReader(path.open())) - years = {} - for year in entry["years"]: - rows = {name: [row for row in data if int(row["year"]) == year] for name, data in tables.items()} - cash = {row["decile"]: float(row["avg_change"]) for row in rows["winners_losers"]} - percent = {int("".join(filter(str.isdigit, row["decile"]))): float(row["value"]) for row in rows["distributional_impact"]} - require(set(cash) == {str(i) for i in range(1, 11)} | {"all"} and set(percent) == set(range(1, 11)), f"{mid}/{year}: incomplete deciles") - require(len(rows["budgetary_impact"]) == len(rows["metrics"]) == 1, f"{mid}/{year}: incomplete headline") - years[str(year)] = { - "budget_change_gbp_bn": float(rows["budgetary_impact"][0]["value"]), - "mean_household_change_gbp": cash["all"], - "people_affected_pct": float(rows["metrics"][0]["people_affected"]), - "deciles": [{"decile": i, "mean_household_change_gbp": cash[str(i)], "income_change_pct": percent[i]} for i in range(1, 11)], - } - summary["measures"][mid] = { - "source_commit": dashboard["git_sha"], "generated_at": dashboard["generated_at"], - "description": dashboard["description"], "execution": execution, - "disclosure_floor": floor, - "sources": {name: SOURCE + entry["artifact"] + f"/{name}.csv" for name in TABLES}, - "receipt_url": SOURCE + entry["artifact"] + "/receipt.json", "years": years, - } - (SNAPSHOT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n") - print("Verified 8 aggregate CSV hashes, certified provenance and provisional disclosure gates; rebuilt population-preview/summary.json") - - -if __name__ == "__main__": - main() From 5772c917d53131ea9674fb242e256d09e4d007a2 Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 15:42:56 -0400 Subject: [PATCH 19/24] docs: remove internal review-status wording --- analysis/uk-budget-2026-income-tax/README.md | 6 +++--- .../articles/uk-autumn-budget-2026-property-income-tax.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/analysis/uk-budget-2026-income-tax/README.md b/analysis/uk-budget-2026-income-tax/README.md index 1af1db429..1a088e993 100644 --- a/analysis/uk-budget-2026-income-tax/README.md +++ b/analysis/uk-budget-2026-income-tax/README.md @@ -22,7 +22,7 @@ The savings draft (#1466) reproduces `savings-interest-chart.json`; the trading ## Current article scope -The property draft now includes national revenue and decile averages from the approved property-only snapshot in dashboard PR #290. `property-population/` retains the immutable source record, original receipt, three aggregate CSVs and the verification summary. Reach, poverty and inequality figures are omitted pending separate disclosure clearance. It is an approved branch snapshot, not independently verified as the production deployment. Recheck its identity and figures against the final released dashboard before merging, and have the new article head reviewed. +The property draft now includes national revenue and decile averages from the approved property-only snapshot in dashboard PR #290. `property-population/` retains the immutable source record, original receipt, three aggregate CSVs and the verification summary. Reach, poverty and inequality figures are omitted pending separate disclosure clearance. It is an approved branch snapshot, not independently verified as the production deployment. Recheck its identity and figures against the final released dashboard before merging. The savings and trading posts retain household calculations and Treasury costings only. Withdrawn combined national outputs are not published in this directory. @@ -36,7 +36,7 @@ Treasury forecasts are labelled separately. Compare fiscal-year Treasury receipt ## Checks before publication -- Recheck the property draft's `property-population/` artifact identity, figures and comparison flags against the final released dashboard. The new population section needs review at its new head. Restore national scope in the other posts only from their own reconciled sources. Add affected-person counts or shares only when the producer exports them and they have disclosure clearance; do not infer them from average changes. +- Recheck the property draft's `property-population/` artifact identity, figures and comparison flags against the final released dashboard. Restore national scope in the other posts only from their own reconciled sources. Add affected-person counts or shares only when the producer exports them and they have disclosure clearance; do not infer them from average changes. - Confirm the treatment of Scottish landlords' finance-cost relief against the final Budget implementation. The pinned model links that relief to the UK property basic rate even for Scotland. - Check trading allowance coverage: gross receipts and actual expenses are needed to model the deduction choice; the pinned model does not apply the allowance to its separate miscellaneous-income input. - Verify the final public dashboard link and add links to these explainers within the dashboard. The source checkout's README supplies the current Vercel dashboard URL. @@ -48,7 +48,7 @@ The three articles use the site's native tables, chart blocks and cover assets. `make format`, `make lint`, `make typecheck` and `make test` passed. The tests ran on Node 26.12.1: 6,042 app tests and 508 website tests passed, with 10 app tests skipped by the existing suite. After inserting the final chart data, the chart-parser and post-metadata checks passed again (18 tests). All 23 household comparisons and 20 curve points passed independent arithmetic checks. -Browser access to the local preview was declined, so visual preview remains outstanding. Cover assets and native chart specs were validated, but this does not confirm page layout at desktop or mobile widths. +Cover assets and native chart specifications have been validated. The rendered page layout has not been checked at desktop or mobile widths. ## Additional trading and calculator examples diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index afbbe0b3d..5236d1842 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -185,7 +185,7 @@ Income deciles rank people by their household's baseline equivalised net income - The household tables show tax attributable to property income. The mortgage examples assume the full finance-cost reduction can be used. - The Scottish mortgage example applies the existing Finance Act rule linking relief to the UK property basic rate. The Finance Bill will set the final implementation of the new rates. - National estimates hold households' behaviour fixed. They do not model landlords incorporating in response to the tax change. -- We do not report poverty, inequality or people-affected figures while their disclosure checks remain unverified. +- This post does not report poverty, inequality or people-affected estimates. - Population estimates include changes in means-tested benefits. The worked household examples show income tax; a change in benefits can offset part of a household's extra tax. ## Methodology From 2afba85997ffa9d51b4d05cca4f0384cc58fea80 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 28 Oct 2026 16:40:21 -0400 Subject: [PATCH 20/24] docs: compare property estimate with the OBR's income tax line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Max's rule (28 Oct): cite primary sources. Compare PolicyEngine with the income tax line of measure 61 in the OBR's detailed policy table (Table 1.1, policy.xlsx sha256 cdcc2a06): 0, 0, 539, 394, 403, 412 £m. Table 6.1's total (the lines rounded to the nearest £5m) stays as context, and the other lines are named by the table's own labels. From 2029-30 the estimate is 9%, 10% and 11% above that line (unrounded figures). Co-Authored-By: Claude Opus 5.5 --- .../property-population/README.md | 2 +- ...-autumn-budget-2026-property-income-tax.md | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/analysis/uk-budget-2026-income-tax/property-population/README.md b/analysis/uk-budget-2026-income-tax/property-population/README.md index 56b5c715f..58e8e4462 100644 --- a/analysis/uk-budget-2026-income-tax/property-population/README.md +++ b/analysis/uk-budget-2026-income-tax/property-population/README.md @@ -24,7 +24,7 @@ The canonical receipt validator returned no document or dashboard problems. The Decile ranks are recomputed for each year from baseline, person-weighted equivalised HBAI household net income before housing costs. Negative ranking income is reset to zero, and equal-income households share a rank. The displayed averages are annual, unequivalised household-net-income changes over **all households** in each decile, including those unaffected. No top-decile revenue share is inferred from these means. -The official comparison marks 2027–28 and 2028–29 as not comparable; its comparison values are null. The source Treasury table separately reports £35 million and £575 million, which the article shows with those flags. Later-year Treasury values are £435 million, £445 million and £455 million. All article values round only for presentation. +The official comparison marks 2027–28 and 2028–29 as not comparable; its comparison values are null. The source Treasury table separately reports £35 million and £575 million, which the article shows with those flags. Later-year Treasury values are £435 million, £445 million and £455 million. The article compares PolicyEngine with the income tax line of measure 61 in the OBR's October 2026 detailed policy table (`efo-october-2026-detailed-forecast-tables-policy.xlsx`, sheet 1.1, rows 297 to 302, SHA-256 `cdcc2a06b100241bf3010bd159a4e5d43daef2348a3850797b1e88a308fd45fd`): £0, £0, £539.10 million, £394.29 million, £403.38 million and £412.24 million for 2026–27 to 2031–32. The measure's lines there total £0.23 million, £33.86 million, £575.47 million, £433.16 million, £444.91 million and £456.93 million, which Table 6.1 rounds to the nearest £5 million; the article shows that total for context. All article values round only for presentation. ## Immutable sources diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index 5236d1842..4b3c035ff 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -6,9 +6,9 @@ Key figures for 2027–28: - A mortgage-free landlord in England with the same profit pays £200 more. - A landlord who lives in Scotland, with £4,000 of fully usable finance costs, pays £80 less income tax. The property income tax rate rise does not apply to Scottish taxpayers, but their finance-cost reduction still rises with the property basic rate. - PolicyEngine estimates £399 million of additional net government revenue and a £14 reduction in average household net income in 2027–28. -- The Treasury forecasts £35 million of additional revenue in 2027–28, £575 million in 2028–29, and £435 million to £455 million a year from 2029–30 to 2031–32. +- The government's costing, certified by the OBR, has £394 million to £412 million a year of extra income tax from 2029–30 to 2031–32, £539 million in 2028–29 and none in 2027–28. Its total in the Budget's Table 6.1, which adds the costing's other lines, is £35 million in 2027–28, £575 million in 2028–29 and £435 million to £455 million a year from 2029–30. -The 2027–28 and 2028–29 figures use different collection-timing bases and are not directly comparable; see the [budgetary impact section](#budgetary-impact). +The 2027–28 and 2028–29 figures use different collection-timing bases and are not directly comparable. From 2029–30, PolicyEngine's estimate is 9% to 11% above the costing's income tax line; see the [budgetary impact section](#budgetary-impact). Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for this and the other Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. The Budget also raises savings income tax rates; we will cover that measure separately. @@ -59,24 +59,24 @@ We model the property measure alone on a representative sample of UK households. ### Budgetary impact -PolicyEngine estimates that the measure raises £399 million of net government revenue in 2027–28, rising to £459 million in 2031–32. The Treasury's [Table 6.1, row 61](https://www.gov.uk/government/publications/supporting-documents-for-budget-2026) reports the official costing on a National Accounts basis. +PolicyEngine estimates that the measure raises £399 million of net government revenue in 2027–28, rising to £459 million in 2031–32. We compare it with the income tax line of the government's costing, certified by the OBR, in the OBR's [detailed policy table](https://obr.uk/download/october-2026-economic-and-fiscal-outlook-detailed-forecast-tables-zip-file/) (Table 1.1, measure 61). That line is the part of the costing we model. The costing's other lines are labelled “Onshore CT”, “Scottish BGA (current)” and “Scottish self-financed expenditure”. The Budget's [Table 6.1, row 61](https://www.gov.uk/government/publications/supporting-documents-for-budget-2026) gives the total of all the lines, rounded to the nearest £5 million and on a National Accounts basis; we show it for context. -| Year | PolicyEngine net government revenue, £ million | Treasury revenue, £ million | Comparison | -| --- | ---: | ---: | --- | -| 2026–27 | 0 | 0 | Before implementation | -| 2027–28 | 399 | 35 | Not comparable | -| 2028–29 | 412 | 575 | Not comparable | -| 2029–30 | 429 | 435 | Later-year comparison | -| 2030–31 | 446 | 445 | Later-year comparison | -| 2031–32 | 459 | 455 | Later-year comparison | +| Year | PolicyEngine net government revenue, £ million | OBR income tax line, £ million | PolicyEngine against the OBR line | Table 6.1 total, £ million | +| --- | ---: | ---: | --- | ---: | +| 2026–27 | 0 | 0 | Before implementation | 0 | +| 2027–28 | 399 | 0 | Not comparable | 35 | +| 2028–29 | 412 | 539 | Not comparable | 575 | +| 2029–30 | 429 | 394 | 9% higher | 435 | +| 2030–31 | 446 | 403 | 10% higher | 445 | +| 2031–32 | 459 | 412 | 11% higher | 455 | -Positive values are additional revenue. PolicyEngine measures the change in government taxes less spending, including benefit interactions. In 2029–30, its £429 million estimate is £6 million below the Treasury's £435 million. +Positive values are additional revenue. PolicyEngine measures the change in government taxes less spending, including benefit interactions. In 2029–30, its £429 million estimate is £35 million, or about 9%, above the OBR's £394 million income tax line. Percentages use unrounded figures. **The first two years, 2027–28 and 2028–29, are not comparable without a collection-timing adjustment.** PolicyEngine scores each tax year's liabilities in that year. Self Assessment payments on account are normally based on the previous year's tax bill; the balancing payment for 2027–28 is due on 31 January 2029, alongside the first payment on account for 2028–29. [HMRC's payment guidance](https://www.gov.uk/understand-self-assessment-bill/payments-on-account) explains that schedule. The [ONS public-finance methodology, section 6.1.2](https://www.ons.gov.uk/economy/governmentpublicsectorandtaxes/publicsectorfinance/methodologies/monthlystatisticsonthepublicsectorfinancesamethodologicalguide) records Self Assessment income tax using cash receipts, without shifting them back to the year the income arose. This can produce a small first-year receipts effect followed by a catch-up. Comparing those first two years with same-year model liabilities requires a collection-timing adjustment; it does not by itself establish a difference in the tax base. -The Treasury costing also allows for some landlords incorporating. PolicyEngine holds that choice fixed. Differences in data, behaviour and accounting remain relevant when comparing the later years, even where the rounded estimates are close. +The government's costing also allows for some landlords incorporating, as the [policy costings](https://assets.publishing.service.gov.uk/media/6ae1883fe4367e5c8b0467df/AB26_Policy_Costing.pdf#page=74) set out. PolicyEngine holds that choice fixed. We have not yet explained the later-year gap; differences in data, behaviour and accounting could each contribute. ### Distribution From 47965517a1c5f59b42ff5e28c8f480d51eb780e2 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 28 Oct 2026 16:47:09 -0400 Subject: [PATCH 21/24] docs: say the OBR income tax line is the closest comparison, not the same scope Co-Authored-By: Claude Opus 5.5 --- .../posts/articles/uk-autumn-budget-2026-property-income-tax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index 4b3c035ff..2c50291cc 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -59,7 +59,7 @@ We model the property measure alone on a representative sample of UK households. ### Budgetary impact -PolicyEngine estimates that the measure raises £399 million of net government revenue in 2027–28, rising to £459 million in 2031–32. We compare it with the income tax line of the government's costing, certified by the OBR, in the OBR's [detailed policy table](https://obr.uk/download/october-2026-economic-and-fiscal-outlook-detailed-forecast-tables-zip-file/) (Table 1.1, measure 61). That line is the part of the costing we model. The costing's other lines are labelled “Onshore CT”, “Scottish BGA (current)” and “Scottish self-financed expenditure”. The Budget's [Table 6.1, row 61](https://www.gov.uk/government/publications/supporting-documents-for-budget-2026) gives the total of all the lines, rounded to the nearest £5 million and on a National Accounts basis; we show it for context. +PolicyEngine estimates that the measure raises £399 million of net government revenue in 2027–28, rising to £459 million in 2031–32. We compare it with the income tax line of the government's costing, certified by the OBR, in the OBR's [detailed policy table](https://obr.uk/download/october-2026-economic-and-fiscal-outlook-detailed-forecast-tables-zip-file/) (Table 1.1, measure 61). We use that line as the closest comparison; PolicyEngine's estimate also includes interactions with other taxes and benefits. The costing's other non-zero lines are labelled “Onshore CT”, “Scottish BGA (current)” and “Scottish self-financed expenditure”. The Budget's [Table 6.1, row 61](https://www.gov.uk/government/publications/supporting-documents-for-budget-2026) gives the total of all the lines, rounded to the nearest £5 million and on a National Accounts basis; we show it for context. | Year | PolicyEngine net government revenue, £ million | OBR income tax line, £ million | PolicyEngine against the OBR line | Table 6.1 total, £ million | | --- | ---: | ---: | --- | ---: | From 91f812f9af738192765541ac01a0c99a6f1127ef Mon Sep 17 00:00:00 2001 From: ZimingHua Date: Wed, 28 Oct 2026 16:51:40 -0400 Subject: [PATCH 22/24] docs: broaden property explainer key figures heading --- .../posts/articles/uk-autumn-budget-2026-property-income-tax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index 2c50291cc..4cb98472d 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -1,6 +1,6 @@ The Autumn Budget 2026 announces a further two-percentage-point increase in the basic, higher and additional income tax rates on property income from **6 April 2027**, taking them to **24%, 44% and 49%** in England, Wales and Northern Ireland, as [Budget paragraph 6.246](https://assets.publishing.service.gov.uk/media/6ae1ec57bdb574cf1c9b3f12/E03668986_HMT_Budget_2026_ELAY__2_.pdf#page=142) sets out. The government plans to legislate for the new rates in Finance Bill 2026–27. The property rate increase does not apply to Scottish taxpayers. Because finance-cost relief follows the property basic rate, residential landlords' relief rises too. -Key figures for 2027–28: +Key figures: - A landlord in England with £10,000 of property profit and £4,000 of fully usable mortgage interest pays £120 more income tax. - A mortgage-free landlord in England with the same profit pays £200 more. From d17842fe557dbfc809aa32729c0f2b1331f5dacf Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 28 Oct 2026 17:09:07 -0400 Subject: [PATCH 23/24] docs: say 'exceeds' rather than 'is above' (style) Co-Authored-By: Claude Opus 5.5 --- .../articles/uk-autumn-budget-2026-property-income-tax.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index 4cb98472d..37b0ac273 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -8,7 +8,7 @@ Key figures: - PolicyEngine estimates £399 million of additional net government revenue and a £14 reduction in average household net income in 2027–28. - The government's costing, certified by the OBR, has £394 million to £412 million a year of extra income tax from 2029–30 to 2031–32, £539 million in 2028–29 and none in 2027–28. Its total in the Budget's Table 6.1, which adds the costing's other lines, is £35 million in 2027–28, £575 million in 2028–29 and £435 million to £455 million a year from 2029–30. -The 2027–28 and 2028–29 figures use different collection-timing bases and are not directly comparable. From 2029–30, PolicyEngine's estimate is 9% to 11% above the costing's income tax line; see the [budgetary impact section](#budgetary-impact). +The 2027–28 and 2028–29 figures use different collection-timing bases and are not directly comparable. From 2029–30, PolicyEngine's estimate exceeds the costing's income tax line by 9% to 11%; see the [budgetary impact section](#budgetary-impact). Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for this and the other Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. The Budget also raises savings income tax rates; we will cover that measure separately. @@ -70,7 +70,7 @@ PolicyEngine estimates that the measure raises £399 million of net government r | 2030–31 | 446 | 403 | 10% higher | 445 | | 2031–32 | 459 | 412 | 11% higher | 455 | -Positive values are additional revenue. PolicyEngine measures the change in government taxes less spending, including benefit interactions. In 2029–30, its £429 million estimate is £35 million, or about 9%, above the OBR's £394 million income tax line. Percentages use unrounded figures. +Positive values are additional revenue. PolicyEngine measures the change in government taxes less spending, including benefit interactions. In 2029–30, its £429 million estimate exceeds the OBR's £394 million income tax line by £35 million, or about 9%. Percentages use unrounded figures. **The first two years, 2027–28 and 2028–29, are not comparable without a collection-timing adjustment.** PolicyEngine scores each tax year's liabilities in that year. Self Assessment payments on account are normally based on the previous year's tax bill; the balancing payment for 2027–28 is due on 31 January 2029, alongside the first payment on account for 2028–29. [HMRC's payment guidance](https://www.gov.uk/understand-self-assessment-bill/payments-on-account) explains that schedule. From 0620d73d0a62e8fbf7d8fe58ff5a4dfc5fc5c175 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 28 Oct 2026 17:10:00 -0400 Subject: [PATCH 24/24] docs: dashboard line covers the Budget measures we model Co-Authored-By: Claude Opus 5.5 --- .../posts/articles/uk-autumn-budget-2026-property-income-tax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md index 37b0ac273..e78edda0a 100644 --- a/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md +++ b/app/src/data/posts/articles/uk-autumn-budget-2026-property-income-tax.md @@ -10,7 +10,7 @@ Key figures: The 2027–28 and 2028–29 figures use different collection-timing bases and are not directly comparable. From 2029–30, PolicyEngine's estimate exceeds the costing's income tax line by 9% to 11%; see the [budgetary impact section](#budgetary-impact). -Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for this and the other Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. The Budget also raises savings income tax rates; we will cover that measure separately. +Our [Autumn Budget 2026 dashboard](https://www.policyengine.org/uk/autumn-budget-2026) is where we publish estimates for the Budget measures we model. A [separate explainer](/uk/research/uk-autumn-budget-2026-trading-allowance) covers the trading allowance increase. The Budget also raises savings income tax rates; we will cover that measure separately. ## What changes in April 2027?