policyengine-uk 2.40.1__py3-none-any.whl → 2.65.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- policyengine_uk/__init__.py +5 -3
- policyengine_uk/data/__init__.py +1 -0
- policyengine_uk/data/dataset_schema.py +70 -18
- policyengine_uk/data/economic_assumptions.py +36 -10
- policyengine_uk/data/filter_dataset.py +52 -0
- policyengine_uk/dynamics/labour_supply.py +343 -0
- policyengine_uk/dynamics/participation.py +629 -0
- policyengine_uk/dynamics/progression.py +384 -0
- policyengine_uk/microsimulation.py +105 -0
- policyengine_uk/model_api.py +1 -0
- policyengine_uk/parameters/gov/boe/base_rate.yaml +34 -0
- policyengine_uk/parameters/gov/boe/index.yaml +2 -0
- policyengine_uk/parameters/gov/contrib/behavioral_responses/employee_salary_sacrifice_reduction_rate.yaml +14 -0
- policyengine_uk/parameters/gov/contrib/behavioral_responses/salary_sacrifice_broad_base_haircut_rate.yaml +22 -0
- policyengine_uk/parameters/gov/contrib/cec/state_pension_increase.yaml +1 -1
- policyengine_uk/parameters/gov/contrib/ubi_center/carbon_tax.yaml +2 -2
- policyengine_uk/parameters/gov/contrib/ubi_center/land_value_tax.yaml +3 -3
- policyengine_uk/parameters/gov/dcms/bbc/tv_licence/colour.yaml +5 -5
- policyengine_uk/parameters/gov/dfe/education_spending.yaml +1 -1
- policyengine_uk/parameters/gov/dft/rail/fare_index.yaml +32 -0
- policyengine_uk/parameters/gov/dft/rail/prior_law_fare_index.yaml +32 -0
- policyengine_uk/parameters/gov/dft/rail/ridership_index.yaml +30 -0
- policyengine_uk/parameters/gov/dft/spending.yaml +2 -2
- policyengine_uk/parameters/gov/dwp/ESA/income/earn_disregard.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/ESA/income/income_disregard_couple.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/ESA/income/income_disregard_lone_parent.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/ESA/income/income_disregard_single.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/ESA/income/pension_disregard.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/IIDB/maximum.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/JSA/contrib/amount_over_25.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/JSA/contrib/earn_disregard.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/JSA/contrib/pension_disregard.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/JSA/income/amount_18_24.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/JSA/income/amount_over_25.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/JSA/income/income_disregard_couple.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/JSA/income/income_disregard_lone_parent.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/JSA/income/income_disregard_single.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/LHA/shared_accommodation_age_threshold.yaml +12 -0
- policyengine_uk/parameters/gov/dwp/attendance_allowance/higher.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/attendance_allowance/lower.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/benefit_cap.yaml +3 -3
- policyengine_uk/parameters/gov/dwp/carer_premium/couple.yaml +2 -2
- policyengine_uk/parameters/gov/dwp/carer_premium/single.yaml +6 -6
- policyengine_uk/parameters/gov/dwp/carers_allowance/rate.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/disability_premia/disability_couple.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/disability_premia/enhanced_couple.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/disability_premia/enhanced_single.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/disability_premia/severe_couple.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/dla/mobility/higher.yaml +4 -4
- policyengine_uk/parameters/gov/dwp/dla/mobility/lower.yaml +8 -8
- policyengine_uk/parameters/gov/dwp/dla/self_care/higher.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/dla/self_care/lower.yaml +8 -8
- policyengine_uk/parameters/gov/dwp/dla/self_care/middle.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/aged.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/older.yaml +3 -3
- policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/aged.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/older.yaml +3 -3
- policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/worker.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/amount.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/housing_benefit/takeup.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/income_support/amounts/amount_16_24.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/income_support/amounts/amount_couples_over_18.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/income_support/means_test/earn_disregard.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/income_support/means_test/income_disregard_couple.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/income_support/means_test/income_disregard_lone_parent.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/income_support/means_test/income_disregard_single.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/income_support/means_test/pension_disregard.yaml +1 -1
- policyengine_uk/parameters/gov/dwp/income_support/takeup.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/pension_credit/guarantee_credit/carer/addition.yaml +4 -4
- policyengine_uk/parameters/gov/dwp/pension_credit/guarantee_credit/minimum_guarantee.yaml +9 -9
- policyengine_uk/parameters/gov/dwp/pension_credit/guarantee_credit/severe_disability/addition.yaml +3 -3
- policyengine_uk/parameters/gov/dwp/pension_credit/savings_credit/threshold.yaml +5 -5
- policyengine_uk/parameters/gov/dwp/pip/daily_living/enhanced.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/pip/daily_living/standard.yaml +8 -8
- policyengine_uk/parameters/gov/dwp/pip/mobility/enhanced.yaml +4 -4
- policyengine_uk/parameters/gov/dwp/pip/mobility/standard.yaml +9 -9
- policyengine_uk/parameters/gov/dwp/sda/maximum.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/state_pension/basic_state_pension/amount.yaml +11 -11
- policyengine_uk/parameters/gov/dwp/state_pension/new_state_pension/amount.yaml +4 -4
- policyengine_uk/parameters/gov/dwp/tax_credits/child_tax_credit/limit/child_count.yaml +10 -1
- policyengine_uk/parameters/gov/dwp/tax_credits/child_tax_credit/takeup.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/tax_credits/working_tax_credit/takeup.yaml +7 -7
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/carer/amount.yaml +3 -3
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/child/amount.yaml +2 -4
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/child/disabled/amount.yaml +2 -4
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/child/first/higher_amount.yaml +6 -8
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/child/limit/child_count.yaml +6 -1
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/child/severely_disabled/amount.yaml +3 -5
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/childcare/cap.yaml +2 -6
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/disabled/amount.yaml +4 -6
- policyengine_uk/parameters/gov/dwp/universal_credit/elements/housing/non_dep_deduction/amount.yaml +4 -1
- policyengine_uk/parameters/gov/dwp/universal_credit/rebalancing/active.yaml +9 -0
- policyengine_uk/parameters/gov/dwp/universal_credit/rebalancing/new_claimant_health_element.yaml +9 -0
- policyengine_uk/parameters/gov/dwp/universal_credit/rebalancing/standard_allowance_uplift.yaml +13 -0
- policyengine_uk/parameters/gov/dwp/universal_credit/standard_allowance/amount.yaml +5 -5
- policyengine_uk/parameters/gov/dwp/winter_fuel_payment/eligibility/taxable_income_test/maximum_taxable_income.yaml +2 -1
- policyengine_uk/parameters/gov/dwp/winter_fuel_payment/eligibility/taxable_income_test/use_maximum_taxable_income.yaml +1 -0
- policyengine_uk/parameters/gov/dynamic/obr_labour_supply_assumptions.yaml +9 -0
- policyengine_uk/parameters/gov/economic_assumptions/create_economic_assumption_indices.py +1 -1
- policyengine_uk/parameters/gov/economic_assumptions/yoy_growth.yaml +522 -153
- policyengine_uk/parameters/gov/hmrc/cgt/additional_rate.yaml +5 -0
- policyengine_uk/parameters/gov/hmrc/cgt/basic_rate.yaml +5 -0
- policyengine_uk/parameters/gov/hmrc/cgt/higher_rate.yaml +4 -0
- policyengine_uk/parameters/gov/hmrc/child_benefit/amount/additional.yaml +6 -6
- policyengine_uk/parameters/gov/hmrc/child_benefit/amount/eldest.yaml +8 -8
- policyengine_uk/parameters/gov/hmrc/child_benefit/takeup/by_age.yaml +1 -1
- policyengine_uk/parameters/gov/hmrc/fuel_duty/calculate_fuel_duty_rates.py +464 -0
- policyengine_uk/parameters/gov/hmrc/fuel_duty/petrol_and_diesel.yaml +86 -10
- policyengine_uk/parameters/gov/hmrc/income_tax/allowances/personal_allowance/amount.yaml +6 -0
- policyengine_uk/parameters/gov/hmrc/income_tax/earned_taxable_income_exclusions.yaml +2 -1
- policyengine_uk/parameters/gov/hmrc/income_tax/income_tax_additions.yaml +1 -0
- policyengine_uk/parameters/gov/hmrc/income_tax/rates/dividends.yaml +12 -0
- policyengine_uk/parameters/gov/hmrc/income_tax/rates/property.yaml +46 -0
- policyengine_uk/parameters/gov/hmrc/income_tax/rates/savings.yaml +46 -0
- policyengine_uk/parameters/gov/hmrc/income_tax/rates/scotland/rates.yaml +2 -2
- policyengine_uk/parameters/gov/hmrc/income_tax/rates/uk.yaml +14 -2
- policyengine_uk/parameters/gov/hmrc/national_insurance/class_1/rates/employee/additional.yaml +4 -6
- policyengine_uk/parameters/gov/hmrc/national_insurance/class_1/rates/employer.yaml +3 -3
- policyengine_uk/parameters/gov/hmrc/national_insurance/class_1/thresholds/secondary_threshold.yaml +14 -4
- policyengine_uk/parameters/gov/hmrc/national_insurance/class_2/flat_rate.yaml +2 -2
- policyengine_uk/parameters/gov/hmrc/national_insurance/salary_sacrifice_pension_cap.yaml +16 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/interest_rates/index.yaml +12 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/interest_rates/plan_1/boe_margin.yaml +11 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/interest_rates/plan_2/additional_rate.yaml +27 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/interest_rates/plan_2/index.yaml +16 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/interest_rates/plan_2/upper_threshold.yaml +48 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/interest_rates/postgraduate_additional_rate.yaml +11 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/postgraduate_repayment_rate.yaml +9 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/repayment_rate.yaml +9 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/thresholds/plan_1.yaml +25 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/thresholds/plan_2.yaml +58 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/thresholds/plan_4.yaml +19 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/thresholds/plan_5.yaml +16 -0
- policyengine_uk/parameters/gov/hmrc/student_loans/thresholds/postgraduate.yaml +21 -0
- policyengine_uk/parameters/gov/hmrc/vat/reduced_rate_share.yaml +3 -3
- policyengine_uk/parameters/gov/indices/private_rent_index.yaml +9 -9
- policyengine_uk/parameters/gov/revenue_scotland/lbtt/non_residential.yaml +2 -2
- policyengine_uk/parameters/gov/revenue_scotland/lbtt/rent.yaml +2 -2
- policyengine_uk/parameters/gov/revenue_scotland/lbtt/residential/first_time_buyer_rate.yaml +2 -2
- policyengine_uk/parameters/gov/revenue_scotland/lbtt/residential/rate.yaml +2 -2
- policyengine_uk/parameters/gov/wra/land_transaction_tax/non_residential.yaml +2 -2
- policyengine_uk/parameters/gov/wra/land_transaction_tax/rent.yaml +2 -2
- policyengine_uk/parameters/gov/wra/land_transaction_tax/residential/higher_rate.yaml +1 -1
- policyengine_uk/parameters/gov/wra/land_transaction_tax/residential/primary.yaml +2 -2
- policyengine_uk/parameters/household/consumption/carbon/consumption.yaml +8 -6
- policyengine_uk/parameters/household/consumption/carbon/intensity.yaml +4 -1
- policyengine_uk/parameters/household/consumption/carbon/production.yaml +12 -7
- policyengine_uk/parameters/household/consumption/carbon/production_by_source.yaml +76 -41
- policyengine_uk/parameters/household/consumption/fuel/prices/petrol.yaml +1 -1
- policyengine_uk/parameters/household/poverty/absolute_poverty_threshold_bhc.yaml +1 -1
- policyengine_uk/reforms/policyengine/adjust_budgets.py +0 -1
- policyengine_uk/scenarios/__init__.py +4 -0
- policyengine_uk/scenarios/pip_reform.py +23 -0
- policyengine_uk/scenarios/reindex_benefit_cap.py +32 -0
- policyengine_uk/scenarios/repeal_two_child_limit.py +10 -0
- policyengine_uk/scenarios/uc_reform.py +50 -0
- policyengine_uk/simulation.py +619 -0
- policyengine_uk/system.py +3 -257
- policyengine_uk/tax_benefit_system.py +141 -0
- policyengine_uk/tests/behavioral_responses/test_labor_supply_responses.yaml +183 -0
- policyengine_uk/tests/microsimulation/reforms_config.yaml +8 -8
- policyengine_uk/tests/microsimulation/test_reform_impacts.py +2 -2
- policyengine_uk/tests/microsimulation/test_salary_sacrifice_cap_reform.py +401 -0
- policyengine_uk/tests/microsimulation/test_validity.py +2 -3
- policyengine_uk/tests/microsimulation/update_reform_impacts.py +104 -40
- policyengine_uk/tests/policy/baseline/contrib/policyengine/employer_ni/employer_ni_fixed_employer_cost_change.yaml +105 -0
- policyengine_uk/tests/policy/baseline/finance/benefit/family/child_benefit.yaml +2 -0
- policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support.yaml +0 -23
- policyengine_uk/tests/policy/baseline/gov/dcms/bbc/tv-licence/tv_licence.yaml +3 -0
- policyengine_uk/tests/policy/baseline/gov/dfe/extended_childcare_entitlement/extended_childcare_entitlement.yaml +17 -17
- policyengine_uk/tests/policy/baseline/gov/dwp/basic_state_pension.yaml +44 -0
- policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/allowances/gift_aid.yaml +71 -0
- policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/allowances/personal_allowance.yaml +161 -0
- policyengine_uk/tests/policy/baseline/gov/hmrc/national_insurance/salary_sacrifice_pension_ni_employee.yaml +107 -0
- policyengine_uk/tests/policy/baseline/gov/hmrc/national_insurance/salary_sacrifice_pension_ni_employer.yaml +95 -0
- policyengine_uk/tests/policy/baseline/gov/hmrc/student_loans/student_loan_interest_rate.yaml +153 -0
- policyengine_uk/tests/policy/baseline/gov/hmrc/student_loans/student_loan_repayment.yaml +130 -0
- policyengine_uk/tests/policy/baseline/household/wealth/vehicle.yaml +27 -0
- policyengine_uk/tests/policy/reforms/nov_2025_budget/income_source_tax_rates.yaml +235 -0
- policyengine_uk/tests/policy/reforms/nov_2025_budget/income_tax_freeze.yaml +83 -0
- policyengine_uk/tests/policy/reforms/parametric/basic_income/basic_income.yaml +1 -0
- policyengine_uk/tests/test_behavioral_responses.py +215 -0
- policyengine_uk/tests/test_fiscal_year_parameters.py +131 -0
- policyengine_uk/utils/__init__.py +1 -0
- policyengine_uk/utils/compare.py +28 -0
- policyengine_uk/utils/create_ahc_deflator.py +169 -0
- policyengine_uk/utils/create_triple_lock.py +1 -1
- policyengine_uk/utils/dependencies.py +259 -0
- policyengine_uk/utils/parameters.py +12 -1
- policyengine_uk/utils/scenario.py +225 -0
- policyengine_uk/utils/solve_private_school_attendance_factor.py +4 -6
- policyengine_uk/variables/contrib/policyengine/education_budget_change.py +0 -1
- policyengine_uk/variables/contrib/policyengine/employer_ni/baseline_employer_cost.py +5 -1
- policyengine_uk/variables/contrib/policyengine/employer_ni/employer_ni_fixed_employer_cost_change.py +23 -23
- policyengine_uk/variables/contrib/policyengine/employer_ni/employer_ni_response_capital_incidence.py +1 -1
- policyengine_uk/variables/contrib/policyengine/employer_ni/employer_ni_response_consumer_incidence.py +1 -1
- policyengine_uk/variables/contrib/policyengine/other_public_spending_budget_change.py +0 -1
- policyengine_uk/variables/gov/dfe/targeted_childcare_entitlement/targeted_childcare_entitlement_eligible.py +0 -1
- policyengine_uk/variables/gov/dft/rail_subsidy_spending.py +16 -1
- policyengine_uk/variables/gov/dft/rail_usage.py +16 -0
- policyengine_uk/variables/gov/dwp/BRMA_LHA_rate.py +7 -2
- policyengine_uk/variables/gov/dwp/LHA_category.py +4 -2
- policyengine_uk/variables/gov/dwp/additional_state_pension.py +4 -2
- policyengine_uk/variables/gov/dwp/basic_state_pension.py +26 -8
- policyengine_uk/variables/gov/dwp/is_CTC_eligible.py +1 -1
- policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt.py +9 -13
- policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_earnings.py +66 -0
- policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py +75 -0
- policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_other.py +66 -0
- policyengine_uk/variables/gov/dwp/winter_fuel_allowance.py +5 -4
- policyengine_uk/variables/gov/gov_tax.py +0 -2
- policyengine_uk/variables/gov/hmrc/household_tax.py +0 -1
- policyengine_uk/variables/gov/hmrc/income_tax/allowances/gift_aid.py +23 -0
- policyengine_uk/variables/gov/hmrc/income_tax/allowances/personal_allowance.py +9 -2
- policyengine_uk/variables/gov/hmrc/income_tax/income_tax_pre_charges.py +1 -0
- policyengine_uk/variables/gov/hmrc/income_tax/liability/property_income_tax.py +75 -0
- policyengine_uk/variables/gov/hmrc/income_tax/liability/savings_income_tax.py +4 -4
- policyengine_uk/variables/gov/hmrc/national_insurance/salary_sacrifice_broad_base_haircut.py +43 -0
- policyengine_uk/variables/gov/hmrc/national_insurance/salary_sacrifice_pension_ni_employee.py +38 -0
- policyengine_uk/variables/gov/hmrc/national_insurance/salary_sacrifice_pension_ni_employer.py +27 -0
- policyengine_uk/variables/gov/hmrc/pensions/pension_contributions_via_salary_sacrifice_adjusted.py +31 -0
- policyengine_uk/variables/gov/hmrc/pensions/salary_sacrifice_returned_to_income.py +41 -0
- policyengine_uk/variables/gov/hmrc/student_loans/__init__.py +2 -0
- policyengine_uk/variables/gov/hmrc/student_loans/plan_1_interest_rate.py +23 -0
- policyengine_uk/variables/gov/hmrc/student_loans/plan_2_interest_rate.py +31 -0
- policyengine_uk/variables/gov/hmrc/student_loans/plan_4_interest_rate.py +22 -0
- policyengine_uk/variables/gov/hmrc/student_loans/plan_5_interest_rate.py +18 -0
- policyengine_uk/variables/gov/hmrc/student_loans/postgraduate_interest_rate.py +23 -0
- policyengine_uk/variables/gov/hmrc/student_loans/student_loan_plan.py +27 -0
- policyengine_uk/variables/gov/hmrc/student_loans/student_loan_repayment.py +91 -0
- policyengine_uk/variables/gov/hmrc/student_loans/student_loan_repayment_rate.py +31 -0
- policyengine_uk/variables/gov/hmrc/would_claim_child_benefit.py +5 -1
- policyengine_uk/variables/household/demographic/benunit/benunit_count_adults.py +11 -0
- policyengine_uk/variables/household/demographic/is_disabled_for_benefits.py +13 -1
- policyengine_uk/variables/household/income/hbai_household_net_income.py +29 -1
- policyengine_uk/variables/household/income/hbai_household_net_income_ahc.py +13 -0
- policyengine_uk/variables/household/income/household_net_income.py +5 -1
- policyengine_uk/variables/household/income/inflation_adjustment.py +24 -0
- policyengine_uk/variables/household/post_tax_income.py +12 -0
- policyengine_uk/variables/household/wealth/num_vehicles.py +9 -0
- policyengine_uk/variables/household/wealth/owns_vehicle.py +17 -0
- policyengine_uk/variables/input/consumption/property/council_tax.py +0 -35
- policyengine_uk/variables/input/consumption/property/employee_pension_contributions.py +8 -1
- policyengine_uk/variables/input/consumption/property/employee_pension_contributions_reported.py +16 -0
- policyengine_uk/variables/input/consumption/property/pension_contributions_via_salary_sacrifice.py +16 -0
- policyengine_uk/variables/input/employment_income.py +2 -0
- policyengine_uk/variables/input/rent.py +0 -40
- policyengine_uk/variables/input/savings_interest_income.py +3 -1
- {policyengine_uk-2.40.1.dist-info → policyengine_uk-2.65.6.dist-info}/METADATA +17 -8
- {policyengine_uk-2.40.1.dist-info → policyengine_uk-2.65.6.dist-info}/RECORD +252 -173
- {policyengine_uk-2.40.1.dist-info → policyengine_uk-2.65.6.dist-info}/WHEEL +1 -1
- policyengine_uk/repo.py +0 -3
- policyengine_uk/tests/policy/baseline/gov/abolitions/abolition_parameters.yaml +0 -250
- policyengine_uk/variables/contrib/policyengine/high_income_incident_tax_change.py +0 -22
- policyengine_uk-2.40.1.data/data/share/openfisca/openfisca-country-template/CHANGELOG.md +0 -2285
- policyengine_uk-2.40.1.data/data/share/openfisca/openfisca-country-template/README.md +0 -37
- policyengine_uk-2.40.1.dist-info/licenses/LICENSE +0 -661
- {policyengine_uk-2.40.1.data/data/share/openfisca/openfisca-country-template → policyengine_uk-2.65.6.dist-info/licenses}/LICENSE +0 -0
|
@@ -3,8 +3,23 @@ from policyengine_uk.model_api import *
|
|
|
3
3
|
|
|
4
4
|
class rail_subsidy_spending(Variable):
|
|
5
5
|
label = "rail subsidy spending"
|
|
6
|
-
documentation =
|
|
6
|
+
documentation = (
|
|
7
|
+
"Total spending on rail subsidies for this household. "
|
|
8
|
+
"Computed as rail_usage × fare_index, allowing reforms to "
|
|
9
|
+
"modify fare prices independently of usage quantity."
|
|
10
|
+
)
|
|
7
11
|
entity = Household
|
|
8
12
|
definition_period = YEAR
|
|
9
13
|
value_type = float
|
|
10
14
|
unit = GBP
|
|
15
|
+
|
|
16
|
+
def formula(household, period, parameters):
|
|
17
|
+
# Get rail usage (quantity at base year prices)
|
|
18
|
+
# This should be provided by policyengine-uk-data
|
|
19
|
+
rail_usage = household("rail_usage", period)
|
|
20
|
+
|
|
21
|
+
# Get the fare index for the current period
|
|
22
|
+
fare_index = parameters(period).gov.dft.rail.fare_index
|
|
23
|
+
|
|
24
|
+
# Spending = quantity × price
|
|
25
|
+
return rail_usage * fare_index
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from policyengine_uk.model_api import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class rail_usage(Variable):
|
|
5
|
+
label = "rail usage"
|
|
6
|
+
documentation = (
|
|
7
|
+
"Rail usage quantity in base year (2020) price terms. "
|
|
8
|
+
"Should be provided by policyengine-uk-data, derived from "
|
|
9
|
+
"rail_subsidy_spending / fare_index at survey year. "
|
|
10
|
+
"Uprated by rail ridership growth trends (~1.9% annually)."
|
|
11
|
+
)
|
|
12
|
+
entity = Household
|
|
13
|
+
definition_period = YEAR
|
|
14
|
+
value_type = float
|
|
15
|
+
unit = GBP
|
|
16
|
+
uprating = "gov.dft.rail.ridership_index"
|
|
@@ -51,13 +51,18 @@ class BRMA_LHA_rate(Variable):
|
|
|
51
51
|
["brma", "lha_category"]
|
|
52
52
|
).weekly_rent.quantile(percentile)
|
|
53
53
|
|
|
54
|
+
# Convert MultiIndex Series to DataFrame for merge
|
|
55
|
+
lha_rates_df = lha_rates.reset_index()
|
|
56
|
+
lha_rates_df.columns = ["brma", "lha_category", "weekly_rent"]
|
|
57
|
+
|
|
54
58
|
lha_lookup_table = pd.DataFrame(
|
|
55
59
|
{
|
|
56
60
|
"brma": brma,
|
|
57
61
|
"lha_category": category,
|
|
58
62
|
}
|
|
59
63
|
)
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
# Use merge instead of row-by-row apply for vectorised lookup
|
|
65
|
+
lha_lookup_table = lha_lookup_table.merge(
|
|
66
|
+
lha_rates_df, on=["brma", "lha_category"], how="left"
|
|
62
67
|
)
|
|
63
68
|
return lha_lookup_table.weekly_rent.values * 52
|
|
@@ -36,11 +36,13 @@ class LHA_category(Variable):
|
|
|
36
36
|
household.max(person("age", period))
|
|
37
37
|
)
|
|
38
38
|
has_children = benunit.any(person("is_child", period))
|
|
39
|
-
# Households with only one adult, if under
|
|
39
|
+
# Households with only one adult, if under age threshold, can only
|
|
40
|
+
# claim shared if without children:
|
|
40
41
|
# https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/28
|
|
42
|
+
p = parameters(period).gov.dwp.LHA
|
|
41
43
|
can_only_claim_shared = (
|
|
42
44
|
(num_adults_in_hh == 1)
|
|
43
|
-
& (eldest_adult_age_in_hh <
|
|
45
|
+
& (eldest_adult_age_in_hh < p.shared_accommodation_age_threshold)
|
|
44
46
|
& ~has_children
|
|
45
47
|
)
|
|
46
48
|
return select(
|
|
@@ -12,8 +12,10 @@ class additional_state_pension(Variable):
|
|
|
12
12
|
simulation = person.simulation
|
|
13
13
|
if simulation.dataset is None:
|
|
14
14
|
return 0
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
try:
|
|
16
|
+
data_year = min(simulation.dataset.years)
|
|
17
|
+
except:
|
|
18
|
+
data_year = period.start.year
|
|
17
19
|
reported = person("state_pension_reported", data_year) / WEEKS_IN_YEAR
|
|
18
20
|
type = person("state_pension_type", data_year)
|
|
19
21
|
maximum_basic_sp = parameters(
|
|
@@ -10,20 +10,38 @@ class basic_state_pension(Variable):
|
|
|
10
10
|
|
|
11
11
|
def formula(person, period, parameters):
|
|
12
12
|
simulation = person.simulation
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
has_dataset = simulation.dataset is not None
|
|
14
|
+
|
|
15
|
+
# Determine the data year: from dataset if available, otherwise current
|
|
16
|
+
if has_dataset:
|
|
17
|
+
try:
|
|
18
|
+
data_year = min(simulation.dataset.years)
|
|
19
|
+
except:
|
|
20
|
+
data_year = period.start.year
|
|
21
|
+
else:
|
|
22
|
+
data_year = period.start.year
|
|
15
23
|
|
|
16
|
-
data_year = simulation.dataset.time_period
|
|
17
24
|
reported = person("state_pension_reported", data_year) / WEEKS_IN_YEAR
|
|
18
|
-
|
|
25
|
+
pension_type = person("state_pension_type", period)
|
|
19
26
|
maximum_basic_sp = parameters(
|
|
20
27
|
data_year
|
|
21
28
|
).gov.dwp.state_pension.basic_state_pension.amount
|
|
29
|
+
|
|
30
|
+
# For BASIC pension type, cap at the maximum; otherwise return 0
|
|
22
31
|
amount_in_data_year = where(
|
|
23
|
-
|
|
32
|
+
pension_type == pension_type.possible_values.BASIC,
|
|
24
33
|
min_(reported, maximum_basic_sp),
|
|
25
34
|
0,
|
|
26
35
|
)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
|
|
37
|
+
# Apply triple lock uprating only when using dataset
|
|
38
|
+
# (i.e., when data year differs from simulation period)
|
|
39
|
+
if has_dataset:
|
|
40
|
+
triple_lock = (
|
|
41
|
+
parameters.gov.economic_assumptions.indices.triple_lock
|
|
42
|
+
)
|
|
43
|
+
uprating = triple_lock(period) / triple_lock(data_year)
|
|
44
|
+
else:
|
|
45
|
+
uprating = 1
|
|
46
|
+
|
|
47
|
+
return amount_in_data_year * uprating * WEEKS_IN_YEAR
|
|
@@ -11,7 +11,7 @@ class is_CTC_eligible(Variable):
|
|
|
11
11
|
def formula(benunit, period, parameters):
|
|
12
12
|
already_claiming = (
|
|
13
13
|
add(benunit, period, ["child_tax_credit_reported"]) > 0
|
|
14
|
-
)
|
|
14
|
+
) & (~add(benunit, period, ["would_claim_uc"]) > 0)
|
|
15
15
|
return (
|
|
16
16
|
benunit.any(benunit.members("is_child_for_CTC", period))
|
|
17
17
|
& already_claiming
|
|
@@ -4,20 +4,16 @@ from policyengine_uk.model_api import *
|
|
|
4
4
|
class is_benefit_cap_exempt(Variable):
|
|
5
5
|
value_type = bool
|
|
6
6
|
entity = BenUnit
|
|
7
|
-
label =
|
|
7
|
+
label = (
|
|
8
|
+
"Whether exempt from the benefits cap because of health or disability"
|
|
9
|
+
)
|
|
8
10
|
definition_period = YEAR
|
|
11
|
+
reference = "https://www.gov.uk/benefit-cap/when-youre-not-affected"
|
|
9
12
|
|
|
10
13
|
def formula(benunit, period, parameters):
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
"dla",
|
|
14
|
-
"esa_contrib",
|
|
15
|
-
]
|
|
16
|
-
QUAL_BENUNIT_BENEFITS = ["working_tax_credit", "esa_income"]
|
|
17
|
-
qualifying_benunit_benefits = add(
|
|
18
|
-
benunit, period, QUAL_BENUNIT_BENEFITS
|
|
14
|
+
exempt_health = benunit(
|
|
15
|
+
"is_benefit_cap_exempt_health_disability", period
|
|
19
16
|
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return (qualifying_personal_benefits + qualifying_benunit_benefits) > 0
|
|
17
|
+
exempt_other = benunit("is_benefit_cap_exempt_other", period)
|
|
18
|
+
exempt_earnings = benunit("is_benefit_cap_exempt_earnings", period)
|
|
19
|
+
return exempt_health | exempt_earnings | exempt_other
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from policyengine_uk.model_api import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class is_benefit_cap_exempt_earnings(Variable):
|
|
5
|
+
value_type = bool
|
|
6
|
+
entity = BenUnit
|
|
7
|
+
label = "Whether exempt from the benefits cap for non-health/disability reasons"
|
|
8
|
+
definition_period = YEAR
|
|
9
|
+
reference = "https://www.gov.uk/benefit-cap/when-youre-not-affected"
|
|
10
|
+
|
|
11
|
+
def formula(benunit, period, parameters):
|
|
12
|
+
# Check if anyone in benefit unit is over state pension age
|
|
13
|
+
person = benunit.members
|
|
14
|
+
over_pension_age = person("is_SP_age", period)
|
|
15
|
+
has_pensioner = benunit.any(over_pension_age)
|
|
16
|
+
|
|
17
|
+
# UC-specific exemptions
|
|
18
|
+
# Limited capability for work and work-related activity
|
|
19
|
+
has_lcwra = benunit.any(
|
|
20
|
+
person("uc_limited_capability_for_WRA", period)
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Carer element in UC indicates caring for someone with disability
|
|
24
|
+
gets_uc_carer_element = benunit("uc_carer_element", period) > 0
|
|
25
|
+
|
|
26
|
+
# Earnings exemption for UC (£846/month = £10,152/year)
|
|
27
|
+
# Note: Only check earned income, not UC amount itself to avoid circular dependency
|
|
28
|
+
uc_earned = benunit.sum(
|
|
29
|
+
benunit.members("employment_income", period)
|
|
30
|
+
+ benunit.members("self_employment_income", period)
|
|
31
|
+
- benunit.members("income_tax", period)
|
|
32
|
+
- benunit.members("national_insurance", period)
|
|
33
|
+
)
|
|
34
|
+
earnings_threshold = 10_152
|
|
35
|
+
meets_earnings_test = uc_earned >= earnings_threshold
|
|
36
|
+
|
|
37
|
+
# Disability and carer benefits that exempt from cap
|
|
38
|
+
QUAL_PERSONAL_BENEFITS = [
|
|
39
|
+
"attendance_allowance",
|
|
40
|
+
"carers_allowance",
|
|
41
|
+
"dla", # Disability Living Allowance (includes components)
|
|
42
|
+
"pip_dl", # PIP daily living component
|
|
43
|
+
"pip_m", # PIP mobility component
|
|
44
|
+
"iidb", # Industrial injuries disability benefit
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
# ESA and Working Tax Credit
|
|
48
|
+
QUAL_BENUNIT_BENEFITS = [
|
|
49
|
+
"esa_income", # Income-based ESA
|
|
50
|
+
"working_tax_credit", # If getting WTC, likely working enough
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
qualifying_personal_benefits = add(
|
|
54
|
+
benunit, period, QUAL_PERSONAL_BENEFITS
|
|
55
|
+
)
|
|
56
|
+
qualifying_benunit_benefits = add(
|
|
57
|
+
benunit, period, QUAL_BENUNIT_BENEFITS
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Check for Armed Forces Compensation Scheme payments
|
|
61
|
+
afcs = benunit("afcs", period) > 0
|
|
62
|
+
|
|
63
|
+
# ESA contribution-based with support component
|
|
64
|
+
esa_support_component = benunit("esa_contrib", period) > 0
|
|
65
|
+
|
|
66
|
+
return meets_earnings_test
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from policyengine_uk.model_api import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class is_benefit_cap_exempt_health_disability(Variable):
|
|
5
|
+
value_type = bool
|
|
6
|
+
entity = BenUnit
|
|
7
|
+
label = (
|
|
8
|
+
"Whether exempt from the benefits cap because of health or disability"
|
|
9
|
+
)
|
|
10
|
+
definition_period = YEAR
|
|
11
|
+
reference = "https://www.gov.uk/benefit-cap/when-youre-not-affected"
|
|
12
|
+
|
|
13
|
+
def formula(benunit, period, parameters):
|
|
14
|
+
# Check if anyone in benefit unit is over state pension age
|
|
15
|
+
person = benunit.members
|
|
16
|
+
over_pension_age = person("is_SP_age", period)
|
|
17
|
+
has_pensioner = benunit.any(over_pension_age)
|
|
18
|
+
|
|
19
|
+
# UC-specific exemptions
|
|
20
|
+
# Limited capability for work and work-related activity
|
|
21
|
+
has_lcwra = benunit.any(
|
|
22
|
+
person("uc_limited_capability_for_WRA", period)
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Carer element in UC indicates caring for someone with disability
|
|
26
|
+
gets_uc_carer_element = benunit("uc_carer_element", period) > 0
|
|
27
|
+
|
|
28
|
+
# Earnings exemption for UC (£846/month = £10,152/year)
|
|
29
|
+
# Note: Only check earned income, not UC amount itself to avoid circular dependency
|
|
30
|
+
uc_earned = benunit.sum(
|
|
31
|
+
benunit.members("employment_income", period)
|
|
32
|
+
+ benunit.members("self_employment_income", period)
|
|
33
|
+
- benunit.members("income_tax", period)
|
|
34
|
+
- benunit.members("national_insurance", period)
|
|
35
|
+
)
|
|
36
|
+
earnings_threshold = 10_152
|
|
37
|
+
meets_earnings_test = uc_earned >= earnings_threshold
|
|
38
|
+
|
|
39
|
+
# Disability and carer benefits that exempt from cap
|
|
40
|
+
QUAL_PERSONAL_BENEFITS = [
|
|
41
|
+
"attendance_allowance",
|
|
42
|
+
"carers_allowance",
|
|
43
|
+
"dla", # Disability Living Allowance (includes components)
|
|
44
|
+
"pip_dl", # PIP daily living component
|
|
45
|
+
"pip_m", # PIP mobility component
|
|
46
|
+
"iidb", # Industrial injuries disability benefit
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
# ESA and Working Tax Credit
|
|
50
|
+
QUAL_BENUNIT_BENEFITS = [
|
|
51
|
+
"esa_income", # Income-based ESA
|
|
52
|
+
"working_tax_credit", # If getting WTC, likely working enough
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
qualifying_personal_benefits = add(
|
|
56
|
+
benunit, period, QUAL_PERSONAL_BENEFITS
|
|
57
|
+
)
|
|
58
|
+
qualifying_benunit_benefits = add(
|
|
59
|
+
benunit, period, QUAL_BENUNIT_BENEFITS
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Check for Armed Forces Compensation Scheme payments
|
|
63
|
+
afcs = benunit("afcs", period) > 0
|
|
64
|
+
|
|
65
|
+
# ESA contribution-based with support component
|
|
66
|
+
esa_support_component = benunit("esa_contrib", period) > 0
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
has_lcwra
|
|
70
|
+
| gets_uc_carer_element
|
|
71
|
+
| (qualifying_personal_benefits > 0)
|
|
72
|
+
| (qualifying_benunit_benefits > 0)
|
|
73
|
+
| afcs
|
|
74
|
+
| esa_support_component
|
|
75
|
+
)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from policyengine_uk.model_api import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class is_benefit_cap_exempt_other(Variable):
|
|
5
|
+
value_type = bool
|
|
6
|
+
entity = BenUnit
|
|
7
|
+
label = "Whether exempt from the benefits cap for non-health/disability reasons"
|
|
8
|
+
definition_period = YEAR
|
|
9
|
+
reference = "https://www.gov.uk/benefit-cap/when-youre-not-affected"
|
|
10
|
+
|
|
11
|
+
def formula(benunit, period, parameters):
|
|
12
|
+
# Check if anyone in benefit unit is over state pension age
|
|
13
|
+
person = benunit.members
|
|
14
|
+
over_pension_age = person("is_SP_age", period)
|
|
15
|
+
has_pensioner = benunit.any(over_pension_age)
|
|
16
|
+
|
|
17
|
+
# UC-specific exemptions
|
|
18
|
+
# Limited capability for work and work-related activity
|
|
19
|
+
has_lcwra = benunit.any(
|
|
20
|
+
person("uc_limited_capability_for_WRA", period)
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Carer element in UC indicates caring for someone with disability
|
|
24
|
+
gets_uc_carer_element = benunit("uc_carer_element", period) > 0
|
|
25
|
+
|
|
26
|
+
# Earnings exemption for UC (£846/month = £10,152/year)
|
|
27
|
+
# Note: Only check earned income, not UC amount itself to avoid circular dependency
|
|
28
|
+
uc_earned = benunit.sum(
|
|
29
|
+
benunit.members("employment_income", period)
|
|
30
|
+
+ benunit.members("self_employment_income", period)
|
|
31
|
+
- benunit.members("income_tax", period)
|
|
32
|
+
- benunit.members("national_insurance", period)
|
|
33
|
+
)
|
|
34
|
+
earnings_threshold = 10_152
|
|
35
|
+
meets_earnings_test = uc_earned >= earnings_threshold
|
|
36
|
+
|
|
37
|
+
# Disability and carer benefits that exempt from cap
|
|
38
|
+
QUAL_PERSONAL_BENEFITS = [
|
|
39
|
+
"attendance_allowance",
|
|
40
|
+
"carers_allowance",
|
|
41
|
+
"dla", # Disability Living Allowance (includes components)
|
|
42
|
+
"pip_dl", # PIP daily living component
|
|
43
|
+
"pip_m", # PIP mobility component
|
|
44
|
+
"iidb", # Industrial injuries disability benefit
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
# ESA and Working Tax Credit
|
|
48
|
+
QUAL_BENUNIT_BENEFITS = [
|
|
49
|
+
"esa_income", # Income-based ESA
|
|
50
|
+
"working_tax_credit", # If getting WTC, likely working enough
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
qualifying_personal_benefits = add(
|
|
54
|
+
benunit, period, QUAL_PERSONAL_BENEFITS
|
|
55
|
+
)
|
|
56
|
+
qualifying_benunit_benefits = add(
|
|
57
|
+
benunit, period, QUAL_BENUNIT_BENEFITS
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Check for Armed Forces Compensation Scheme payments
|
|
61
|
+
afcs = benunit("afcs", period) > 0
|
|
62
|
+
|
|
63
|
+
# ESA contribution-based with support component
|
|
64
|
+
esa_support_component = benunit("esa_contrib", period) > 0
|
|
65
|
+
|
|
66
|
+
return has_pensioner | afcs | esa_support_component
|
|
@@ -45,11 +45,12 @@ class winter_fuel_allowance(Variable):
|
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
meets_mtb_requirement = (
|
|
48
|
-
on_mtb
|
|
48
|
+
on_mtb
|
|
49
|
+
| (not wfp.eligibility.require_benefits)
|
|
50
|
+
| meets_income_passport
|
|
49
51
|
)
|
|
50
|
-
meets_spa_requirement = (
|
|
51
|
-
|
|
52
|
-
| ~wfp.eligibility.state_pension_age_requirement
|
|
52
|
+
meets_spa_requirement = household.any(is_SP_age) | (
|
|
53
|
+
not wfp.eligibility.state_pension_age_requirement
|
|
53
54
|
)
|
|
54
55
|
meets_higher_age_requirement = household.any(
|
|
55
56
|
age >= wfp.eligibility.higher_age_requirement
|
|
@@ -26,12 +26,10 @@ class gov_tax(Variable):
|
|
|
26
26
|
"national_insurance",
|
|
27
27
|
"LVT",
|
|
28
28
|
"carbon_tax",
|
|
29
|
-
"vat_change",
|
|
30
29
|
"capital_gains_tax",
|
|
31
30
|
"private_school_vat",
|
|
32
31
|
"corporate_incident_tax_revenue_change",
|
|
33
32
|
"consumer_incident_tax_revenue_change",
|
|
34
|
-
"high_income_incident_tax_change",
|
|
35
33
|
"ni_employer",
|
|
36
34
|
"student_loan_repayments",
|
|
37
35
|
"vat",
|
|
@@ -29,7 +29,6 @@ class household_tax(Variable):
|
|
|
29
29
|
"private_school_vat",
|
|
30
30
|
"corporate_incident_tax_revenue_change",
|
|
31
31
|
"consumer_incident_tax_revenue_change",
|
|
32
|
-
"high_income_incident_tax_change",
|
|
33
32
|
"employer_ni_response_capital_incidence",
|
|
34
33
|
"employer_ni_response_consumer_incidence",
|
|
35
34
|
"student_loan_repayments",
|
|
@@ -7,3 +7,26 @@ class gift_aid(Variable):
|
|
|
7
7
|
label = "Expenditure under Gift Aid"
|
|
8
8
|
definition_period = YEAR
|
|
9
9
|
unit = GBP
|
|
10
|
+
reference = dict(
|
|
11
|
+
title="Income Tax Act 2007, Part 8 Chapter 2 (Gift Aid)",
|
|
12
|
+
href="https://www.legislation.gov.uk/ukpga/2007/3/part/8/chapter/2",
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class gift_aid_grossed_up(Variable):
|
|
17
|
+
value_type = float
|
|
18
|
+
entity = Person
|
|
19
|
+
label = "Gift Aid grossed up by basic rate"
|
|
20
|
+
definition_period = YEAR
|
|
21
|
+
unit = GBP
|
|
22
|
+
reference = dict(
|
|
23
|
+
title="Income Tax Act 2007, s. 58 (2)",
|
|
24
|
+
href="https://www.legislation.gov.uk/ukpga/2007/3/section/58",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
def formula(person, period, parameters):
|
|
28
|
+
gift_aid = person("gift_aid", period)
|
|
29
|
+
basic_rate = parameters(period).gov.hmrc.income_tax.rates.uk.rates[0]
|
|
30
|
+
# Grossed up amount = gift_aid / (1 - basic_rate)
|
|
31
|
+
# With basic_rate = 0.2: gift_aid / 0.8 = gift_aid * 1.25
|
|
32
|
+
return gift_aid / (1 - basic_rate)
|
|
@@ -7,13 +7,20 @@ class personal_allowance(Variable):
|
|
|
7
7
|
label = "Personal Allowance for the year"
|
|
8
8
|
unit = GBP
|
|
9
9
|
definition_period = YEAR
|
|
10
|
-
reference =
|
|
10
|
+
reference = dict(
|
|
11
|
+
title="Income Tax Act 2007 s. 35, s. 58",
|
|
12
|
+
href="https://www.legislation.gov.uk/ukpga/2007/3/section/35",
|
|
13
|
+
)
|
|
11
14
|
|
|
12
15
|
def formula(person, period, parameters):
|
|
13
16
|
params = parameters(period)
|
|
14
17
|
PA = params.gov.hmrc.income_tax.allowances.personal_allowance
|
|
15
18
|
personal_allowance = PA.amount
|
|
16
19
|
ANI = person("adjusted_net_income", period)
|
|
17
|
-
|
|
20
|
+
# Per ITA 2007 s.58, deduct grossed-up Gift Aid from ANI
|
|
21
|
+
# when calculating Personal Allowance taper
|
|
22
|
+
gift_aid_grossed_up = person("gift_aid_grossed_up", period)
|
|
23
|
+
ANI_for_taper = ANI - gift_aid_grossed_up
|
|
24
|
+
excess = max_(0, ANI_for_taper - PA.maximum_ANI)
|
|
18
25
|
reduction = excess * PA.reduction_rate
|
|
19
26
|
return max_(0, personal_allowance - reduction)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from policyengine_uk.model_api import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class property_income_tax(Variable):
|
|
5
|
+
value_type = float
|
|
6
|
+
entity = Person
|
|
7
|
+
label = "Income tax on property income"
|
|
8
|
+
definition_period = YEAR
|
|
9
|
+
reference = [
|
|
10
|
+
dict(
|
|
11
|
+
title="Income Tax (Trading and Other Income) Act 2005, s. 268",
|
|
12
|
+
href="https://www.legislation.gov.uk/ukpga/2005/5/section/268",
|
|
13
|
+
),
|
|
14
|
+
dict(
|
|
15
|
+
title="OBR Economic and Fiscal Outlook November 2025",
|
|
16
|
+
href="https://obr.uk/efo/economic-and-fiscal-outlook-november-2025/",
|
|
17
|
+
),
|
|
18
|
+
]
|
|
19
|
+
unit = GBP
|
|
20
|
+
|
|
21
|
+
def formula(person, period, parameters):
|
|
22
|
+
"""
|
|
23
|
+
Calculate income tax on property income.
|
|
24
|
+
|
|
25
|
+
For Scottish taxpayers, property income is taxed using the normal
|
|
26
|
+
Scottish income tax rates (the new property-specific rates do not
|
|
27
|
+
apply to Scotland).
|
|
28
|
+
|
|
29
|
+
For rUK taxpayers, property income is taxed using property-specific
|
|
30
|
+
rates. From April 2027, these are 2pp higher than standard UK rates
|
|
31
|
+
(22%, 42%, 47% vs 20%, 40%, 45%).
|
|
32
|
+
|
|
33
|
+
Property income is stacked on top of other earned income for
|
|
34
|
+
determining which tax band it falls into.
|
|
35
|
+
"""
|
|
36
|
+
rates = parameters(period).gov.hmrc.income_tax.rates
|
|
37
|
+
taxable_property = person("taxable_property_income", period)
|
|
38
|
+
earned_taxable = person("earned_taxable_income", period)
|
|
39
|
+
other_earned_taxable = max_(0, earned_taxable - taxable_property)
|
|
40
|
+
is_scottish = person("pays_scottish_income_tax", period)
|
|
41
|
+
|
|
42
|
+
# Scottish taxpayers: use Scottish rates via calc method
|
|
43
|
+
# Tax on (other earned + property) minus tax on (other earned)
|
|
44
|
+
scottish_tax = rates.scotland.rates.calc(
|
|
45
|
+
other_earned_taxable + taxable_property
|
|
46
|
+
) - rates.scotland.rates.calc(other_earned_taxable)
|
|
47
|
+
|
|
48
|
+
# rUK taxpayers: use property-specific rates
|
|
49
|
+
property_rates = rates.property
|
|
50
|
+
thresholds = rates.uk.thresholds
|
|
51
|
+
basic_upper = thresholds[1] # Higher rate threshold
|
|
52
|
+
higher_upper = thresholds[2] # Additional rate threshold
|
|
53
|
+
|
|
54
|
+
# Property income in basic rate band
|
|
55
|
+
basic_rate_space = max_(0, basic_upper - other_earned_taxable)
|
|
56
|
+
property_in_basic = min_(taxable_property, basic_rate_space)
|
|
57
|
+
|
|
58
|
+
# Property income in higher rate band
|
|
59
|
+
higher_start = max_(other_earned_taxable, basic_upper)
|
|
60
|
+
higher_rate_space = max_(0, higher_upper - higher_start)
|
|
61
|
+
remaining_after_basic = max_(0, taxable_property - property_in_basic)
|
|
62
|
+
property_in_higher = min_(remaining_after_basic, higher_rate_space)
|
|
63
|
+
|
|
64
|
+
# Property income in additional rate band
|
|
65
|
+
property_in_additional = max_(
|
|
66
|
+
0, taxable_property - property_in_basic - property_in_higher
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
ruk_tax = (
|
|
70
|
+
property_rates.basic * property_in_basic
|
|
71
|
+
+ property_rates.higher * property_in_higher
|
|
72
|
+
+ property_rates.additional * property_in_additional
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
return where(is_scottish, scottish_tax, ruk_tax)
|
|
@@ -13,12 +13,12 @@ class savings_income_tax(Variable):
|
|
|
13
13
|
unit = GBP
|
|
14
14
|
|
|
15
15
|
def formula(person, period, parameters):
|
|
16
|
-
|
|
16
|
+
savings_rates = parameters(period).gov.hmrc.income_tax.rates.savings
|
|
17
17
|
basic_rate_amount = person("basic_rate_savings_income", period)
|
|
18
18
|
higher_rate_amount = person("higher_rate_savings_income", period)
|
|
19
19
|
add_rate_amount = person("add_rate_savings_income", period)
|
|
20
20
|
return (
|
|
21
|
-
|
|
22
|
-
+
|
|
23
|
-
+
|
|
21
|
+
savings_rates.basic * basic_rate_amount
|
|
22
|
+
+ savings_rates.higher * higher_rate_amount
|
|
23
|
+
+ savings_rates.additional * add_rate_amount
|
|
24
24
|
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from policyengine_uk.model_api import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class salary_sacrifice_broad_base_haircut(Variable):
|
|
5
|
+
label = "Salary sacrifice broad-base employment income haircut"
|
|
6
|
+
documentation = (
|
|
7
|
+
"Reduction in employment income for ALL workers due to employers spreading "
|
|
8
|
+
"the increased NI costs from the salary sacrifice cap across all employees. "
|
|
9
|
+
"This is a negative value that reduces employment_income. "
|
|
10
|
+
"\n\n"
|
|
11
|
+
"When the salary sacrifice cap is active, employers face increased NI costs "
|
|
12
|
+
"on excess contributions. They spread these costs across ALL employees (not "
|
|
13
|
+
"just salary sacrificers), as they cannot target only affected workers without "
|
|
14
|
+
"those workers negotiating to recoup the loss. "
|
|
15
|
+
"\n\n"
|
|
16
|
+
"See https://policyengine.org/uk/research/uk-salary-sacrifice-cap for methodology."
|
|
17
|
+
)
|
|
18
|
+
entity = Person
|
|
19
|
+
definition_period = YEAR
|
|
20
|
+
value_type = float
|
|
21
|
+
unit = GBP
|
|
22
|
+
reference = "https://policyengine.org/uk/research/uk-salary-sacrifice-cap"
|
|
23
|
+
|
|
24
|
+
def formula(person, period, parameters):
|
|
25
|
+
cap = parameters(
|
|
26
|
+
period
|
|
27
|
+
).gov.hmrc.national_insurance.salary_sacrifice_pension_cap
|
|
28
|
+
|
|
29
|
+
# If cap is infinite, no haircut applies
|
|
30
|
+
if np.isinf(cap):
|
|
31
|
+
return 0
|
|
32
|
+
|
|
33
|
+
# Get the broad-base haircut rate (applies to ALL workers)
|
|
34
|
+
haircut_rate = parameters(
|
|
35
|
+
period
|
|
36
|
+
).gov.contrib.behavioral_responses.salary_sacrifice_broad_base_haircut_rate
|
|
37
|
+
|
|
38
|
+
# Apply haircut to employment income before any salary sacrifice adjustments
|
|
39
|
+
# Use employment_income_before_lsr to avoid circular dependency
|
|
40
|
+
employment_income = person("employment_income_before_lsr", period)
|
|
41
|
+
|
|
42
|
+
# Return negative value (this reduces employment income for everyone)
|
|
43
|
+
return -employment_income * haircut_rate
|