From f6b389cc7892503df19210015e0eeed41818b96b Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 16 Jan 2026 18:29:14 -0500 Subject: [PATCH 1/6] feat: add Scottish Budget 2026-27 tax and benefit changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the Scottish Budget 2026-27 reforms announced by Finance Secretary Shona Robison on 13 January 2026: ## Income Tax Threshold Uplift (7.4% increase) - Basic rate threshold: £16,537 total (£3,967 above PA) - Intermediate rate threshold: £29,526 total (£16,956 above PA) - Higher, Advanced, and Top rate thresholds remain frozen ## SCP Premium for Under-Ones (£40/week) - Children under 1 receive £40/week total (vs £27.15 standard rate) - This is a FIXED total amount, not a bonus on top of standard SCP - Controlled by gov.contrib.scotland.scottish_child_payment.in_effect - Amount now parametric via premium_under_one_amount.yaml These changes take effect from 6 April 2026 (2026-04-06). References: - https://www.gov.scot/publications/scottish-budget-2026-2027/ - https://www.gov.scot/publications/scottish-income-tax-technical-factsheet/ Co-Authored-By: Claude Opus 4.5 --- .../scottish_child_payment/in_effect.yaml | 10 ++++++-- .../hmrc/income_tax/rates/scotland/rates.yaml | 8 +++++++ .../premium_under_one_amount.yaml | 14 +++++++++++ .../scottish_child_payment.py | 24 +++++++++---------- 4 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml diff --git a/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/in_effect.yaml b/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/in_effect.yaml index 110e9768d..c0bc168a8 100644 --- a/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/in_effect.yaml +++ b/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/in_effect.yaml @@ -1,7 +1,13 @@ -description: Whether the Scottish Child Payment baby bonus reform is in effect. +description: Whether the Scottish Child Payment Premium for under-ones is in effect. values: 0001-01-01: false + # Scottish Budget 2026-27: SCP Premium for under-ones (£40/week) + # announced by Finance Secretary Shona Robison, 13 January 2026 + 2026-04-06: true metadata: unit: bool period: year - label: Scottish Child Payment baby bonus reform in effect + label: Scottish Child Payment Premium for under-ones in effect + reference: + - title: Scottish Budget 2026-27 - Finance Secretary's Statement + href: https://www.gov.scot/publications/scottish-budget-2026-2027/ diff --git a/policyengine_uk/parameters/gov/hmrc/income_tax/rates/scotland/rates.yaml b/policyengine_uk/parameters/gov/hmrc/income_tax/rates/scotland/rates.yaml index 328ef24ec..ec9a5681b 100644 --- a/policyengine_uk/parameters/gov/hmrc/income_tax/rates/scotland/rates.yaml +++ b/policyengine_uk/parameters/gov/hmrc/income_tax/rates/scotland/rates.yaml @@ -19,6 +19,9 @@ brackets: 2023-04-06: 2_162 2024-04-06: 2_306 2025-04-06: 2_827 + # Scottish Budget 2026-27: Basic rate threshold £16,537 total + # (above £12,570 PA = £3,967). 7.4% increase. + 2026-04-06: 3_967 metadata: uprating: gov.economic_assumptions.indices.obr.consumer_price_index rate: @@ -32,6 +35,9 @@ brackets: 2023-04-06: 13_118 2024-04-06: 13_991 2025-04-06: 14_921 + # Scottish Budget 2026-27: Intermediate rate threshold £29,526 total + # (above £12,570 PA = £16,956). 7.4% increase. + 2026-04-06: 16_956 metadata: uprating: gov.economic_assumptions.indices.obr.consumer_price_index rate: @@ -81,3 +87,5 @@ metadata: reference: - title: GOV.UK href: https://www.gov.uk/government/publications/rates-and-allowances-income-tax/income-tax-rates-and-allowances-current-and-past + - title: Scottish Budget 2026-27 - Income Tax Technical Factsheet + href: https://www.gov.scot/publications/scottish-income-tax-technical-factsheet/ diff --git a/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml b/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml new file mode 100644 index 000000000..f930f1fc1 --- /dev/null +++ b/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml @@ -0,0 +1,14 @@ +description: Weekly amount of Scottish Child Payment Premium for children under 1. +values: + # Scottish Budget 2026-27: £40/week for under-ones + # This is a TOTAL amount, not a bonus on top of standard SCP + 2026-04-06: 40 +metadata: + unit: currency-GBP + period: week + label: Scottish Child Payment Premium for under-ones weekly amount + reference: + - title: Scottish Budget 2026-27 - Finance Secretary's Statement + href: https://www.gov.scot/publications/scottish-budget-2026-2027/ + - title: Scottish Government announcement + href: https://www.gov.scot/news/income-tax-proposals-for-2026-27-3/ diff --git a/policyengine_uk/variables/gov/social_security_scotland/scottish_child_payment.py b/policyengine_uk/variables/gov/social_security_scotland/scottish_child_payment.py index dfff3862f..89a56da92 100644 --- a/policyengine_uk/variables/gov/social_security_scotland/scottish_child_payment.py +++ b/policyengine_uk/variables/gov/social_security_scotland/scottish_child_payment.py @@ -77,22 +77,22 @@ def formula(benunit, period, parameters): | receives_pension_credit ) - # Check if SCP Premium for under-ones is enabled (parametric reform) - # This allows enabling via parameter_changes without structural reform - baby_bonus_in_effect = parameters( + # Check if SCP Premium for under-ones is enabled + # Scottish Budget 2026-27: £40/week for children under 1 + contrib_params = parameters( period - ).gov.contrib.scotland.scottish_child_payment.in_effect + ).gov.contrib.scotland.scottish_child_payment + baby_bonus_in_effect = contrib_params.in_effect - # SCP Premium for under-ones: Fixed £40/week total for babies under 1 - # Policy: Children under 1 get £40/week, children 1+ get standard rate - # Source: Scottish Budget 2026-27 - PREMIUM_RATE_UNDER_ONE = 40.0 # £40/week fixed total + # Get the premium rate from parameters (£40/week from April 2026) + premium_rate = p.premium_under_one_amount - # Calculate per-child weekly amount based on age (if reform is active) + # Calculate per-child weekly amount based on age + # Under-1s get premium rate when in effect, others get standard rate per_child_weekly = where( - baby_bonus_in_effect & (age < 1), - PREMIUM_RATE_UNDER_ONE, # £40/week for under-1s (TOTAL, not bonus) - weekly_amount, # Standard SCP rate for 1+ or when reform inactive + baby_bonus_in_effect & (age < 1) & (premium_rate > 0), + premium_rate, # Premium for under-1s (TOTAL amount, not bonus) + weekly_amount, # Standard SCP rate for 1+ or when premium not in effect ) # Calculate total weekly payment for all eligible children From 67d3b5456d8457c3b31ab848eacc69c919aa4ce3 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 16 Jan 2026 18:30:04 -0500 Subject: [PATCH 2/6] Add changelog entry for Scottish Budget 2026-27 Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb..d52e18d99 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,6 @@ +- bump: minor + changes: + added: + - Scottish Budget 2026-27 income tax threshold uplift (7.4% increase to basic and intermediate rate thresholds) + - Scottish Budget 2026-27 SCP Premium for under-ones (£40/week for children under 1) + - New parameter premium_under_one_amount for SCP Premium rate From a7edf75ec37e459d478767d8a1d4e828acc3e405 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 16 Jan 2026 19:07:25 -0500 Subject: [PATCH 3/6] Move SCP baby boost from contrib to main parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the contrib/scotland/scottish_child_payment parameters and reforms since the Scottish Budget 2026-27 policy is now enacted. Changes: - Add premium_under_one_amount parameter with £40/week from 2026-04-06 - Update scottish_child_payment variable to use main parameter directly - Delete contrib parameters (baby_bonus.yaml, in_effect.yaml) - Delete scotland reforms directory - Remove scottish_child_payment_reform from reforms.py - Rewrite tests to verify 2025 (standard rate) vs 2026 (premium rate) Co-Authored-By: Claude Opus 4.5 --- .../scottish_child_payment/baby_bonus.yaml | 23 --- .../scottish_child_payment/in_effect.yaml | 13 -- .../premium_under_one_amount.yaml | 2 + policyengine_uk/reforms/reforms.py | 2 - policyengine_uk/reforms/scotland/__init__.py | 1 - .../scotland/scottish_child_payment_reform.py | 176 ------------------ .../scottish_child_payment_baby_bonus.yaml | 68 +++---- .../scottish_child_payment.py | 17 +- 8 files changed, 35 insertions(+), 267 deletions(-) delete mode 100644 policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/baby_bonus.yaml delete mode 100644 policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/in_effect.yaml delete mode 100644 policyengine_uk/reforms/scotland/__init__.py delete mode 100644 policyengine_uk/reforms/scotland/scottish_child_payment_reform.py diff --git a/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/baby_bonus.yaml b/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/baby_bonus.yaml deleted file mode 100644 index 444a404aa..000000000 --- a/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/baby_bonus.yaml +++ /dev/null @@ -1,23 +0,0 @@ -description: Additional weekly amount for Scottish Child Payment based on child age. -brackets: - - threshold: - values: - 0001-01-01: 0 - amount: - values: - 0001-01-01: 12.85 - - threshold: - values: - 0001-01-01: 1 - amount: - values: - 0001-01-01: 0 -metadata: - type: single_amount - threshold_unit: year - amount_unit: currency-GBP - period: week - label: Scottish Child Payment baby bonus by age - reference: - - title: Scottish Government - Scottish Child Payment - href: https://www.gov.scot/policies/social-security/scottish-child-payment/ diff --git a/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/in_effect.yaml b/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/in_effect.yaml deleted file mode 100644 index c0bc168a8..000000000 --- a/policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/in_effect.yaml +++ /dev/null @@ -1,13 +0,0 @@ -description: Whether the Scottish Child Payment Premium for under-ones is in effect. -values: - 0001-01-01: false - # Scottish Budget 2026-27: SCP Premium for under-ones (£40/week) - # announced by Finance Secretary Shona Robison, 13 January 2026 - 2026-04-06: true -metadata: - unit: bool - period: year - label: Scottish Child Payment Premium for under-ones in effect - reference: - - title: Scottish Budget 2026-27 - Finance Secretary's Statement - href: https://www.gov.scot/publications/scottish-budget-2026-2027/ diff --git a/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml b/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml index f930f1fc1..aba341614 100644 --- a/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml +++ b/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml @@ -1,5 +1,7 @@ description: Weekly amount of Scottish Child Payment Premium for children under 1. values: + # No premium before Scottish Budget 2026-27 + 0001-01-01: 0 # Scottish Budget 2026-27: £40/week for under-ones # This is a TOTAL amount, not a bonus on top of standard SCP 2026-04-06: 40 diff --git a/policyengine_uk/reforms/reforms.py b/policyengine_uk/reforms/reforms.py index be00af9a3..b27f2aab9 100644 --- a/policyengine_uk/reforms/reforms.py +++ b/policyengine_uk/reforms/reforms.py @@ -4,7 +4,6 @@ disable_simulated_benefits, ) from .policyengine.adjust_budgets import adjust_budgets -from .scotland import create_scottish_child_payment_reform from policyengine_core.model_api import * from policyengine_core import periods @@ -16,7 +15,6 @@ def create_structural_reforms_from_parameters(parameters, period): create_household_based_hitc_reform(parameters, period), disable_simulated_benefits(parameters, period), adjust_budgets(parameters, period), - create_scottish_child_payment_reform(parameters, period), ] reforms = tuple(filter(lambda x: x is not None, reforms)) diff --git a/policyengine_uk/reforms/scotland/__init__.py b/policyengine_uk/reforms/scotland/__init__.py deleted file mode 100644 index d33418501..000000000 --- a/policyengine_uk/reforms/scotland/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .scottish_child_payment_reform import create_scottish_child_payment_reform diff --git a/policyengine_uk/reforms/scotland/scottish_child_payment_reform.py b/policyengine_uk/reforms/scotland/scottish_child_payment_reform.py deleted file mode 100644 index 68050badd..000000000 --- a/policyengine_uk/reforms/scotland/scottish_child_payment_reform.py +++ /dev/null @@ -1,176 +0,0 @@ -from policyengine_uk.model_api import * -from policyengine_core.periods import period as period_ - - -def create_scottish_child_payment_baby_bonus_reform() -> Reform: - """ - Reform that implements SCP Premium for under-ones. - - Policy: Children under 1 receive a FIXED £40/week total payment. - Children 1+ receive the standard SCP rate (inflates with inflation). - - This is NOT a fixed bonus added to the base - it's a fixed total amount. - As the base SCP rate inflates, the "bonus" for under-1s effectively - decreases to maintain the £40 total. - - Source: Scottish Budget 2026-27 - https://www.gov.scot/publications/scottish-budget-2026-2027-finance-secretarys-statement-13-january-2026-2/ - """ - - class scottish_child_payment(Variable): - label = "Scottish Child Payment" - documentation = ( - "Scottish Child Payment provides financial support to low-income " - "families in Scotland. It is paid per eligible child to families " - "receiving qualifying benefits such as Universal Credit." - ) - entity = BenUnit - definition_period = YEAR - value_type = float - unit = GBP - reference = [ - "https://www.gov.scot/policies/social-security/scottish-child-payment/", - "https://www.socialsecurity.gov.scot/", - ] - - def formula(benunit, period, parameters): - # Check if household is in Scotland - in_scotland = ( - benunit.household("country", period).decode_to_str() - == "SCOTLAND" - ) - - # Get SCP parameters - p = parameters( - period - ).gov.social_security_scotland.scottish_child_payment - weekly_amount = p.amount - - # SCP only available when amount > 0 (i.e., after Feb 2021) - scp_available = weekly_amount > 0 - - # Count eligible children in the benefit unit - is_eligible_child = benunit.members( - "is_scp_eligible_child", period - ) - eligible_children = benunit.sum(is_eligible_child) - - # Get ages for baby bonus calculation - age = benunit.members("age", period) - - # Count children under 6 and 6+ for takeup rate calculation - is_child = benunit.members("is_child", period) - children_6_and_over = benunit.sum( - is_child & (age >= 6) & (age < 16) - ) - - # Check if receiving a qualifying benefit - qb = p.qualifying_benefits - - receives_uc = ( - benunit("universal_credit", period) > 0 - ) & qb.universal_credit - receives_ctc = ( - benunit("child_tax_credit", period) > 0 - ) & qb.child_tax_credit - receives_wtc = ( - benunit("working_tax_credit", period) > 0 - ) & qb.working_tax_credit - receives_income_support = ( - benunit("income_support", period) > 0 - ) & qb.income_support - receives_jsa_income = ( - benunit("jsa_income", period) > 0 - ) & qb.jsa_income - receives_esa_income = ( - benunit("esa_income", period) > 0 - ) & qb.esa_income - receives_pension_credit = ( - benunit("pension_credit", period) > 0 - ) & qb.pension_credit - - receives_qualifying_benefit = ( - receives_uc - | receives_ctc - | receives_wtc - | receives_income_support - | receives_jsa_income - | receives_esa_income - | receives_pension_credit - ) - - # SCP Premium for under-ones: Fixed £40/week total (not base + bonus) - # Policy: Children under 1 get £40/week, children 1+ get standard rate - PREMIUM_RATE_UNDER_ONE = 40.0 # £40/week fixed total - - # Calculate per-child weekly amount based on age - per_child_weekly = where( - age < 1, - PREMIUM_RATE_UNDER_ONE, # £40/week for under-1s (TOTAL, not bonus) - weekly_amount, # Standard SCP rate for 1+ (inflates with inflation) - ) - - # Calculate total weekly payment for all eligible children - total_weekly = benunit.sum(per_child_weekly * is_eligible_child) - - # Convert to annual amount - annual_amount = total_weekly * WEEKS_IN_YEAR - - # Apply age-specific take-up rates in microsimulation - takeup_under_6 = p.takeup_rate.under_6 - takeup_6_and_over = p.takeup_rate.age_6_and_over - - has_children_6_and_over = children_6_and_over > 0 - takeup_rate = where( - has_children_6_and_over, takeup_6_and_over, takeup_under_6 - ) - - takes_up = random(benunit) < takeup_rate - is_in_microsimulation = benunit.simulation.dataset is not None - if is_in_microsimulation: - receives_payment = takes_up - else: - receives_payment = True - - return ( - in_scotland - * scp_available - * receives_qualifying_benefit - * receives_payment - * annual_amount - ) - - class reform(Reform): - def apply(self): - self.update_variable(scottish_child_payment) - - return reform - - -def create_scottish_child_payment_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_scottish_child_payment_baby_bonus_reform() - - p = parameters.gov.contrib.scotland.scottish_child_payment - - # Check if reform is active in current period or next 5 years - reform_active = False - current_period = period_(period) - - for i in range(5): - if p(current_period).in_effect: - reform_active = True - break - current_period = current_period.offset(1, "year") - - if reform_active: - return create_scottish_child_payment_baby_bonus_reform() - else: - return None - - -scottish_child_payment_reform = ( - create_scottish_child_payment_baby_bonus_reform() -) diff --git a/policyengine_uk/tests/policy/baseline/gov/social_security_scotland/scottish_child_payment_baby_bonus.yaml b/policyengine_uk/tests/policy/baseline/gov/social_security_scotland/scottish_child_payment_baby_bonus.yaml index 70e1bf72c..361bdec50 100644 --- a/policyengine_uk/tests/policy/baseline/gov/social_security_scotland/scottish_child_payment_baby_bonus.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/social_security_scotland/scottish_child_payment_baby_bonus.yaml @@ -1,7 +1,10 @@ -# Tests for Scottish Child Payment Premium for under-ones reform +# Tests for Scottish Child Payment Premium for under-ones # -# POLICY: Children under 1 receive FIXED £40/week TOTAL payment -# Children 1+ receive standard SCP rate (£27.15 in 2026, inflates thereafter) +# POLICY: Children under 1 receive FIXED £40/week TOTAL payment (from April 2026) +# Children 1+ receive standard SCP rate (£27.15 in 2025, inflates thereafter) +# +# Source: Scottish Budget 2026-27 +# https://www.gov.scot/publications/scottish-budget-2026-2027/ # # This is NOT a fixed bonus - it's a fixed total amount. # As standard rate inflates, the effective "premium" decreases to maintain £40 total. @@ -9,11 +12,10 @@ # 2026 calculations: # - Standard SCP: £27.15/week * 52 = £1,411.80/year # - Premium for under-1s: £40/week * 52 = £2,080/year (TOTAL, not base + bonus) -# - Effective premium: £40 - £27.15 = £12.85/week (but this changes as base inflates) -# Test 1: Scottish family with 1 baby (age 0) - WITHOUT reform -- name: Scottish family with 1 baby - baseline (no baby bonus) - period: 2026 +# Test 1: Scottish family with 1 baby (age 0) - BEFORE premium (2025) +- name: Scottish family with 1 baby - before premium (2025) + period: 2025 absolute_error_margin: 1 input: people: @@ -34,16 +36,14 @@ - baby region: SCOTLAND output: - # 1 child * £27.15/week * 52 weeks = £1,411.80 + # 1 child * £27.15/week * 52 weeks = £1,411.80 (no premium before 2026) scottish_child_payment: 1412 -# Test 2: Scottish family with 1 baby (age 0) - WITH reform -- name: Scottish family with 1 baby - with baby bonus +# Test 2: Scottish family with 1 baby (age 0) - WITH premium (2026) +- name: Scottish family with 1 baby - with premium (2026) period: 2026 absolute_error_margin: 1 - reforms: policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform input: - gov.contrib.scotland.scottish_child_payment.in_effect: true people: parent: age: 30 @@ -65,13 +65,11 @@ # 1 baby * £40/week * 52 = £2,080/year (TOTAL payment for under-1) scottish_child_payment: 2080 -# Test 3: Scottish family with 2 babies (both age 0) - WITH reform -- name: Scottish family with 2 babies - with baby bonus +# Test 3: Scottish family with 2 babies (both age 0) - 2026 +- name: Scottish family with 2 babies - with premium (2026) period: 2026 absolute_error_margin: 1 - reforms: policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform input: - gov.contrib.scotland.scottish_child_payment.in_effect: true people: parent: age: 30 @@ -94,16 +92,14 @@ - baby2 region: SCOTLAND output: - # 2 babies * £40/week * 52 = £4,160/year (TOTAL payment for 2 under-1s) + # 2 babies * £40/week * 52 = £4,160/year scottish_child_payment: 4160 -# Test 4: Scottish family with 1 baby and 1 older child - WITH reform -- name: Scottish family with 1 baby and 1 older child - with baby bonus +# Test 4: Scottish family with 1 baby and 1 older child - 2026 +- name: Scottish family with 1 baby and 1 older child (2026) period: 2026 absolute_error_margin: 1 - reforms: policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform input: - gov.contrib.scotland.scottish_child_payment.in_effect: true people: parent: age: 30 @@ -130,13 +126,11 @@ # £67.15 * 52 = £3,491.80/year scottish_child_payment: 3492 -# Test 5: Scottish family with only older children (no babies) - WITH reform -- name: Scottish family with older children only - no baby bonus +# Test 5: Scottish family with only older children (no babies) - 2026 +- name: Scottish family with older children only (2026) period: 2026 absolute_error_margin: 1 - reforms: policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform input: - gov.contrib.scotland.scottish_child_payment.in_effect: true people: parent: age: 30 @@ -162,13 +156,11 @@ # 2 older children @ £27.15/week * 52 = £2,823.60 (standard rate, no premium) scottish_child_payment: 2824 -# Test 6: English family with baby - no SCP regardless of reform +# Test 6: English family with baby - no SCP (not in Scotland) - name: English family with baby - no SCP period: 2026 absolute_error_margin: 1 - reforms: policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform input: - gov.contrib.scotland.scottish_child_payment.in_effect: true people: parent: age: 30 @@ -189,13 +181,11 @@ output: scottish_child_payment: 0 -# Test 7: Child at age boundary (exactly 1 year old) - no baby bonus -- name: Scottish family with 1 year old child - no baby bonus +# Test 7: Child at age boundary (exactly 1 year old) - no premium +- name: Scottish family with 1 year old child - no premium period: 2026 absolute_error_margin: 1 - reforms: policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform input: - gov.contrib.scotland.scottish_child_payment.in_effect: true people: parent: age: 30 @@ -214,16 +204,14 @@ - child region: SCOTLAND output: - # 1 child @ £27.15/week * 52 = £1,411.80 (standard rate - age >= 1, no premium) + # 1 child @ £27.15/week * 52 = £1,411.80 (standard rate - age >= 1) scottish_child_payment: 1412 -# Test 8: Higher income (£45k) - no qualifying benefit, no SCP -- name: Scottish family with £45k income - no SCP (no qualifying benefit) +# Test 8: Higher income - no qualifying benefit, no SCP +- name: Scottish family with £45k income - no SCP period: 2026 absolute_error_margin: 1 - reforms: policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform input: - gov.contrib.scotland.scottish_child_payment.in_effect: true people: parent: age: 30 @@ -245,13 +233,11 @@ # No UC at £45k income, so no SCP eligibility scottish_child_payment: 0 -# Test 9: Higher income (£50k) - no qualifying benefit, no SCP -- name: Scottish family with £50k income - no SCP (no qualifying benefit) +# Test 9: High income - no qualifying benefit, no SCP +- name: Scottish family with £50k income - no SCP period: 2026 absolute_error_margin: 1 - reforms: policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform input: - gov.contrib.scotland.scottish_child_payment.in_effect: true people: parent: age: 30 diff --git a/policyengine_uk/variables/gov/social_security_scotland/scottish_child_payment.py b/policyengine_uk/variables/gov/social_security_scotland/scottish_child_payment.py index 89a56da92..5d7b85b66 100644 --- a/policyengine_uk/variables/gov/social_security_scotland/scottish_child_payment.py +++ b/policyengine_uk/variables/gov/social_security_scotland/scottish_child_payment.py @@ -77,22 +77,17 @@ def formula(benunit, period, parameters): | receives_pension_credit ) - # Check if SCP Premium for under-ones is enabled - # Scottish Budget 2026-27: £40/week for children under 1 - contrib_params = parameters( - period - ).gov.contrib.scotland.scottish_child_payment - baby_bonus_in_effect = contrib_params.in_effect - - # Get the premium rate from parameters (£40/week from April 2026) + # SCP Premium for under-ones (Scottish Budget 2026-27) + # Children under 1 receive £40/week total from April 2026 + # When premium_under_one_amount > 0, it applies to under-1s premium_rate = p.premium_under_one_amount # Calculate per-child weekly amount based on age - # Under-1s get premium rate when in effect, others get standard rate + # Under-1s get premium rate when available, others get standard rate per_child_weekly = where( - baby_bonus_in_effect & (age < 1) & (premium_rate > 0), + (age < 1) & (premium_rate > 0), premium_rate, # Premium for under-1s (TOTAL amount, not bonus) - weekly_amount, # Standard SCP rate for 1+ or when premium not in effect + weekly_amount, # Standard SCP rate for 1+ or when no premium ) # Calculate total weekly payment for all eligible children From c6c3c527f13549dd3c4661f5259221c8670543b4 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 16 Jan 2026 19:33:52 -0500 Subject: [PATCH 4/6] Add tests for Scottish Budget 2026-27 income tax thresholds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests verify: - Basic rate threshold at £3,967 above PA (£16,537 total) - Intermediate rate threshold at £16,956 above PA (£29,526 total) - Threshold uplift effect (2025 vs 2026 comparison) - English taxpayers unaffected by Scottish thresholds Source: Scottish Income Tax 2026-27 Technical Factsheet, Table 1 https://www.gov.scot/publications/scottish-income-tax-technical-factsheet/ Co-Authored-By: Claude Opus 4.5 --- .../scottish_budget_2026_thresholds.yaml | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/scottish_budget_2026_thresholds.yaml diff --git a/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/scottish_budget_2026_thresholds.yaml b/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/scottish_budget_2026_thresholds.yaml new file mode 100644 index 000000000..7f7bcc804 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/scottish_budget_2026_thresholds.yaml @@ -0,0 +1,151 @@ +# Tests for Scottish Budget 2026-27 income tax threshold changes +# +# Source: Scottish Income Tax 2026-27 Technical Factsheet, Table 1 +# https://www.gov.scot/publications/scottish-income-tax-technical-factsheet/ +# +# Scottish income tax thresholds for 2026-27: +# - Starter rate (19%): £0 - £16,537 (first £16,537 of taxable income) +# - Basic rate (20%): £16,538 - £29,526 +# - Intermediate rate (21%): £29,527 - £43,662 +# - Higher rate (42%): £43,663 - £75,000 +# - Advanced rate (45%): £75,001 - £125,140 +# - Top rate (48%): Over £125,140 +# +# PolicyEngine stores thresholds as amounts ABOVE personal allowance (£12,570): +# - Starter rate threshold: £0 (bracket 0) +# - Basic rate threshold: £3,967 (£16,537 - £12,570) (bracket 1) +# - Intermediate rate threshold: £16,956 (£29,526 - £12,570) (bracket 2) + +# Test 1: Scottish taxpayer in basic rate band (2026) +# Income: £25,000 → taxable = £12,430 (after £12,570 PA) +# Tax calculation: +# Starter rate (19%): £3,967 × 0.19 = £753.73 +# Basic rate (20%): (£12,430 - £3,967) × 0.20 = £8,463 × 0.20 = £1,692.60 +# Total: £2,446.33 +- name: Scottish taxpayer in basic rate band (2026) + period: 2026 + absolute_error_margin: 5 + input: + people: + person: + age: 35 + employment_income: 25000 + benunits: + benunit: + members: + - person + households: + household: + members: + - person + region: SCOTLAND + output: + income_tax: 2446 + +# Test 2: Scottish taxpayer at intermediate threshold boundary (2026) +# Income: £42,096 (£29,526 + £12,570 PA) → taxable = £29,526 +# Tax calculation: +# Starter rate (19%): £3,967 × 0.19 = £753.73 +# Basic rate (20%): (£16,956 - £3,967) × 0.20 = £12,989 × 0.20 = £2,597.80 +# Intermediate rate (21%): (£29,526 - £16,956) × 0.21 = £12,570 × 0.21 = £2,639.70 +# Total: £5,991.23 +- name: Scottish taxpayer at intermediate threshold boundary (2026) + period: 2026 + absolute_error_margin: 5 + input: + people: + person: + age: 35 + employment_income: 42096 + benunits: + benunit: + members: + - person + households: + household: + members: + - person + region: SCOTLAND + output: + income_tax: 5991 + +# Test 3: Compare 2025 vs 2026 for same income +# Shows the threshold uplift effect +# Income: £20,000 → taxable = £7,430 (after £12,570 PA) +# +# 2025 thresholds (pre-uplift): +# Basic rate threshold: £2,827 above PA +# Starter rate (19%): £2,827 × 0.19 = £537.13 +# Basic rate (20%): (£7,430 - £2,827) × 0.20 = £4,603 × 0.20 = £920.60 +# Total 2025: £1,457.73 +# +# 2026 thresholds (post-uplift): +# Basic rate threshold: £3,967 above PA +# Starter rate (19%): £3,967 × 0.19 = £753.73 +# Basic rate (20%): (£7,430 - £3,967) × 0.20 = £3,463 × 0.20 = £692.60 +# Total 2026: £1,446.33 +# +# Difference: £11.40 less tax in 2026 due to threshold uplift +- name: Scottish taxpayer - threshold uplift comparison (2025) + period: 2025 + absolute_error_margin: 5 + input: + people: + person: + age: 35 + employment_income: 20000 + benunits: + benunit: + members: + - person + households: + household: + members: + - person + region: SCOTLAND + output: + income_tax: 1458 + +- name: Scottish taxpayer - threshold uplift comparison (2026) + period: 2026 + absolute_error_margin: 5 + input: + people: + person: + age: 35 + employment_income: 20000 + benunits: + benunit: + members: + - person + households: + household: + members: + - person + region: SCOTLAND + output: + income_tax: 1446 + +# Test 4: English taxpayer unaffected by Scottish thresholds (2026) +# Income: £25,000 → taxable = £12,430 (after £12,570 PA) +# Uses UK rates, not Scottish rates +- name: English taxpayer unaffected by Scottish thresholds (2026) + period: 2026 + absolute_error_margin: 5 + input: + people: + person: + age: 35 + employment_income: 25000 + benunits: + benunit: + members: + - person + households: + household: + members: + - person + region: NORTH_EAST + output: + # UK basic rate (20%) on full £12,430: £2,486 + income_tax: 2486 From f996e6afefadfea974721062d4354d837cd51063 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 16 Jan 2026 23:22:42 -0500 Subject: [PATCH 5/6] Fix SCP timing: baby boost starts 2027-28, add 2026 inflation rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Scottish Budget 2026-27: - SCP inflation increase to £28.20/week from April 2026 - Baby boost (£40/week for under-1s) "will be paid in 2027-28" Source: https://www.gov.scot/publications/scottish-budget-2026-2027/pages/6/ Co-Authored-By: Claude Opus 4.5 --- .../scottish_child_payment/amount.yaml | 1 + .../premium_under_one_amount.yaml | 8 +++++--- uv.lock | 10 +++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/amount.yaml b/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/amount.yaml index 40f091ffe..2944a3ab1 100644 --- a/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/amount.yaml +++ b/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/amount.yaml @@ -6,6 +6,7 @@ values: 2022-11-14: 25 2024-04-01: 26.70 2025-04-01: 27.15 + 2026-04-01: 28.20 metadata: unit: currency-GBP period: week diff --git a/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml b/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml index aba341614..506a6e8c6 100644 --- a/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml +++ b/policyengine_uk/parameters/gov/social_security_scotland/scottish_child_payment/premium_under_one_amount.yaml @@ -1,10 +1,12 @@ description: Weekly amount of Scottish Child Payment Premium for children under 1. values: - # No premium before Scottish Budget 2026-27 + # No premium before 2027-28 0001-01-01: 0 - # Scottish Budget 2026-27: £40/week for under-ones + # Scottish Budget 2026-27 announced this for 2027-28 + # Source: "will be paid in 2027-28" + # https://www.gov.scot/publications/scottish-budget-2026-2027/pages/6/ # This is a TOTAL amount, not a bonus on top of standard SCP - 2026-04-06: 40 + 2027-04-06: 40 metadata: unit: currency-GBP period: week diff --git a/uv.lock b/uv.lock index f668d9358..607079549 100644 --- a/uv.lock +++ b/uv.lock @@ -1170,7 +1170,7 @@ wheels = [ [[package]] name = "policyengine-core" -version = "3.19.3" +version = "3.23.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "dpath" }, @@ -1190,14 +1190,14 @@ dependencies = [ { name = "standard-imghdr" }, { name = "wheel" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8d/fb/4425c2bba1095d78c5aa326e92eb697d84d1b88ffd84f7ce8e6a470b0579/policyengine_core-3.19.3.tar.gz", hash = "sha256:acf9d668f2d193949f307785c1d3dee63908d2df35f12b4eff7578d85d125290", size = 159388, upload-time = "2025-07-24T18:11:58.184Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5d/7e/561ca775a40ff52084858854aa9d12ded2f5b4ccdca32109902640d8553e/policyengine_core-3.23.2.tar.gz", hash = "sha256:af7d0dacb74fa8ece9c219dc322a833d7d07b985f8e58eeccb4790c9164923a8", size = 162869, upload-time = "2026-01-15T22:18:15.008Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1c/75/6f032d03c62011a5958a336bd2b7c1d83c1a6eb3fbd0df1daf117a48e9d5/policyengine_core-3.19.3-py3-none-any.whl", hash = "sha256:3bee1abce0eb27f26e4de7f639d099fb31f5e3ed5a8094144d6fdc4a2cc18af1", size = 220722, upload-time = "2025-07-24T18:11:56.407Z" }, + { url = "https://files.pythonhosted.org/packages/ea/4b/64c8988e18cf36d3eeb892b9cf791eaa91d8ca380d61c3ef63b3d01cdfa6/policyengine_core-3.23.2-py3-none-any.whl", hash = "sha256:06ca92d83f0da037245ed3727e3e15ef411fcf5ad0537199e45a9937fe5761a6", size = 224717, upload-time = "2026-01-15T22:18:13.423Z" }, ] [[package]] name = "policyengine-uk" -version = "2.65.0" +version = "2.69.0" source = { editable = "." } dependencies = [ { name = "microdf-python" }, @@ -1233,7 +1233,7 @@ requires-dist = [ { name = "jupyter-book", marker = "extra == 'dev'", specifier = ">=2.0.0a0" }, { name = "linecheck", marker = "extra == 'dev'" }, { name = "microdf-python", specifier = ">=1.0.2" }, - { name = "policyengine-core", specifier = ">=3.19.3" }, + { name = "policyengine-core", specifier = ">=3.23.0" }, { name = "pydantic", specifier = ">=2.11.7" }, { name = "pytest", marker = "extra == 'dev'" }, { name = "pytest-cov", marker = "extra == 'dev'" }, From 81c02f5c55514f9fd306bf10b8b049f3ac965a48 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 16 Jan 2026 23:31:54 -0500 Subject: [PATCH 6/6] =?UTF-8?q?Fix=20SCP=20tests:=20baby=20boost=20starts?= =?UTF-8?q?=202027,=20use=20=C2=A328.20=20for=202026?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 2026: £28.20/week standard rate (no baby boost) - 2027: £40/week for babies, £28.20/week for older children Per Scottish Budget: baby boost "will be paid in 2027-28" Co-Authored-By: Claude Opus 4.5 --- .../scottish_child_payment_baby_bonus.yaml | 117 +++++++++--------- 1 file changed, 60 insertions(+), 57 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/social_security_scotland/scottish_child_payment_baby_bonus.yaml b/policyengine_uk/tests/policy/baseline/gov/social_security_scotland/scottish_child_payment_baby_bonus.yaml index 361bdec50..f79ba990b 100644 --- a/policyengine_uk/tests/policy/baseline/gov/social_security_scotland/scottish_child_payment_baby_bonus.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/social_security_scotland/scottish_child_payment_baby_bonus.yaml @@ -1,20 +1,23 @@ # Tests for Scottish Child Payment Premium for under-ones # -# POLICY: Children under 1 receive FIXED £40/week TOTAL payment (from April 2026) -# Children 1+ receive standard SCP rate (£27.15 in 2025, inflates thereafter) +# POLICY: Children under 1 receive FIXED £40/week TOTAL payment (from April 2027) +# Children 1+ receive standard SCP rate (£28.20 in 2026-27) # # Source: Scottish Budget 2026-27 -# https://www.gov.scot/publications/scottish-budget-2026-2027/ +# https://www.gov.scot/publications/scottish-budget-2026-2027/pages/6/ +# "will be paid in 2027-28" # # This is NOT a fixed bonus - it's a fixed total amount. -# As standard rate inflates, the effective "premium" decreases to maintain £40 total. # -# 2026 calculations: -# - Standard SCP: £27.15/week * 52 = £1,411.80/year +# 2026 calculations (no baby boost yet): +# - Standard SCP: £28.20/week * 52 = £1,466.40/year +# +# 2027 calculations (WITH baby boost): +# - Standard SCP: £28.20/week * 52 = £1,466.40/year # - Premium for under-1s: £40/week * 52 = £2,080/year (TOTAL, not base + bonus) -# Test 1: Scottish family with 1 baby (age 0) - BEFORE premium (2025) -- name: Scottish family with 1 baby - before premium (2025) +# Test 1: Scottish family with 1 baby (age 0) - 2025 (before inflation increase) +- name: Scottish family with 1 baby - 2025 period: 2025 absolute_error_margin: 1 input: @@ -36,13 +39,39 @@ - baby region: SCOTLAND output: - # 1 child * £27.15/week * 52 weeks = £1,411.80 (no premium before 2026) + # 1 child * £27.15/week * 52 weeks = £1,411.80 scottish_child_payment: 1412 -# Test 2: Scottish family with 1 baby (age 0) - WITH premium (2026) -- name: Scottish family with 1 baby - with premium (2026) +# Test 2: Scottish family with 1 baby (age 0) - 2026 (no baby boost yet) +- name: Scottish family with 1 baby - 2026 no baby boost period: 2026 absolute_error_margin: 1 + input: + people: + parent: + age: 30 + baby: + age: 0 + benunits: + family: + members: + - parent + - baby + universal_credit: 5000 + households: + household: + members: + - parent + - baby + region: SCOTLAND + output: + # 1 baby * £28.20/week * 52 = £1,466.40/year (no baby boost until 2027) + scottish_child_payment: 1466 + +# Test 3: Scottish family with 1 baby (age 0) - 2027 (WITH baby boost) +- name: Scottish family with 1 baby - 2027 with baby boost + period: 2027 + absolute_error_margin: 1 input: people: parent: @@ -65,9 +94,9 @@ # 1 baby * £40/week * 52 = £2,080/year (TOTAL payment for under-1) scottish_child_payment: 2080 -# Test 3: Scottish family with 2 babies (both age 0) - 2026 -- name: Scottish family with 2 babies - with premium (2026) - period: 2026 +# Test 4: Scottish family with 2 babies (both age 0) - 2027 +- name: Scottish family with 2 babies - 2027 with baby boost + period: 2027 absolute_error_margin: 1 input: people: @@ -95,9 +124,9 @@ # 2 babies * £40/week * 52 = £4,160/year scottish_child_payment: 4160 -# Test 4: Scottish family with 1 baby and 1 older child - 2026 -- name: Scottish family with 1 baby and 1 older child (2026) - period: 2026 +# Test 5: Scottish family with 1 baby and 1 older child - 2027 +- name: Scottish family with 1 baby and 1 older child - 2027 + period: 2027 absolute_error_margin: 1 input: people: @@ -122,12 +151,12 @@ - older_child region: SCOTLAND output: - # 1 baby @ £40/week + 1 older child @ £27.15/week = £67.15/week - # £67.15 * 52 = £3,491.80/year - scottish_child_payment: 3492 + # 1 baby @ £40/week + 1 older child @ £28.20/week = £68.20/week + # £68.20 * 52 = £3,546.40/year + scottish_child_payment: 3546 -# Test 5: Scottish family with only older children (no babies) - 2026 -- name: Scottish family with older children only (2026) +# Test 6: Scottish family with only older children (no babies) - 2026 +- name: Scottish family with older children only - 2026 period: 2026 absolute_error_margin: 1 input: @@ -153,12 +182,12 @@ - child2 region: SCOTLAND output: - # 2 older children @ £27.15/week * 52 = £2,823.60 (standard rate, no premium) - scottish_child_payment: 2824 + # 2 older children @ £28.20/week * 52 = £2,932.80 (standard rate) + scottish_child_payment: 2933 -# Test 6: English family with baby - no SCP (not in Scotland) +# Test 7: English family with baby - no SCP (not in Scotland) - name: English family with baby - no SCP - period: 2026 + period: 2027 absolute_error_margin: 1 input: people: @@ -181,9 +210,9 @@ output: scottish_child_payment: 0 -# Test 7: Child at age boundary (exactly 1 year old) - no premium +# Test 8: Child at age boundary (exactly 1 year old) - no premium - name: Scottish family with 1 year old child - no premium - period: 2026 + period: 2027 absolute_error_margin: 1 input: people: @@ -204,38 +233,12 @@ - child region: SCOTLAND output: - # 1 child @ £27.15/week * 52 = £1,411.80 (standard rate - age >= 1) - scottish_child_payment: 1412 - -# Test 8: Higher income - no qualifying benefit, no SCP -- name: Scottish family with £45k income - no SCP - period: 2026 - absolute_error_margin: 1 - input: - people: - parent: - age: 30 - employment_income: 45000 - baby: - age: 0 - benunits: - family: - members: - - parent - - baby - households: - household: - members: - - parent - - baby - region: SCOTLAND - output: - # No UC at £45k income, so no SCP eligibility - scottish_child_payment: 0 + # 1 child @ £28.20/week * 52 = £1,466.40 (standard rate - age >= 1) + scottish_child_payment: 1466 # Test 9: High income - no qualifying benefit, no SCP - name: Scottish family with £50k income - no SCP - period: 2026 + period: 2027 absolute_error_margin: 1 input: people: