From 660db83b08e084c518e2154d601f1c05dcb73d22 Mon Sep 17 00:00:00 2001 From: Nikhil Woodruff <35577657+nikhilwoodruff@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:49:56 +0100 Subject: [PATCH] Add employer NI incidence (#961) * Add renames and employer NI logic * Add employer NI logic * Bump version * Bump version * Fix employer cost logic for emp_income < threshold * Remove debugging line --- CHANGELOG.md | 7 + changelog.yaml | 5 + changelog_entry.yaml | 4 - emp_ni_test.ipynb | 67 +++ employer_ni.ipynb | 70 +++ employer_ni_example.ipynb | 132 ++++++ .../policyengine/employer_ni/README.md | 1 + .../employer_ni/employee_incidence.yaml | 6 + ...exempt_employer_pension_contributions.yaml | 6 + .../hmrc/income_tax/income_tax_additions.yaml | 2 +- .../gov/hmrc/pensions/pensions_programs.yaml | 4 +- .../benefit/family/universal_credit.yaml | 6 +- .../gov/hmrc/income_tax/income_tax.yaml | 2 +- .../hmrc/pensions/pension_contributions.yaml | 32 +- .../pension_contributions_relief.yaml | 8 +- .../employer_ni_fixed_employer_cost_change.py | 110 +++++ .../class_1/ni_class_1_employer.py | 11 +- .../class_1/ni_class_1_income.py | 2 +- .../pensions/pension_contributions_relief.py | 2 +- .../private_pension_contributions_tax.py | 10 +- .../consumption/consumption_share.py | 20 + .../variables/input/consumption/coicop.py | 19 - .../input/consumption/property/maintenance.py | 21 + policyengine_uk/variables/input/income.py | 1 + setup.py | 4 +- test.ipynb | 427 ------------------ 26 files changed, 492 insertions(+), 487 deletions(-) create mode 100644 emp_ni_test.ipynb create mode 100644 employer_ni.ipynb create mode 100644 employer_ni_example.ipynb create mode 100644 policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/README.md create mode 100644 policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/employee_incidence.yaml create mode 100644 policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/exempt_employer_pension_contributions.yaml create mode 100644 policyengine_uk/variables/contrib/policyengine/employer_ni/employer_ni_fixed_employer_cost_change.py create mode 100644 policyengine_uk/variables/household/consumption/consumption_share.py delete mode 100644 test.ipynb diff --git a/CHANGELOG.md b/CHANGELOG.md index e69e9b03f..52e4cf330 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.2.0] - 2024-10-16 11:52:07 + +### Fixed + +- Add employer NI incidence. + ## [2.1.1] - 2024-09-18 11:12:23 ## [2.1.0] - 2024-09-18 11:04:12 @@ -1488,6 +1494,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +[2.2.0]: https://github.com/PolicyEngine/openfisca-uk/compare/2.1.1...2.2.0 [2.1.1]: https://github.com/PolicyEngine/openfisca-uk/compare/2.1.0...2.1.1 [2.1.0]: https://github.com/PolicyEngine/openfisca-uk/compare/2.0.0...2.1.0 [2.0.0]: https://github.com/PolicyEngine/openfisca-uk/compare/1.8.0...2.0.0 diff --git a/changelog.yaml b/changelog.yaml index d3c46224b..19709397d 100644 --- a/changelog.yaml +++ b/changelog.yaml @@ -1249,3 +1249,8 @@ removed: - Survey-Enhance as a dependency. date: 2024-09-18 11:12:23 +- bump: minor + changes: + fixed: + - Add employer NI incidence. + date: 2024-10-16 11:52:07 diff --git a/changelog_entry.yaml b/changelog_entry.yaml index 53a790adb..e69de29bb 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,4 +0,0 @@ -- bump: minor - changes: - fixed: - - Set the Winter Fuel Allowance to only true in FY24-25. diff --git a/emp_ni_test.ipynb b/emp_ni_test.ipynb new file mode 100644 index 000000000..ec6016f16 --- /dev/null +++ b/emp_ni_test.ipynb @@ -0,0 +1,67 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_uk import Simulation\n", + "from policyengine_core.reforms import Reform\n", + "\n", + "Reform.from_dict({\n", + " \"gov.hmrc.national_insurance.class_1.rates.employer\": {\n", + " \"year:2025:10\": 0.148,\n", + " },\n", + "}\n", + "\n", + "sim = Simulation(reform=), situation={\n", + " \"employment_income\": {\n", + " 2025: 40_000,\n", + " },\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([37500.], dtype=float32)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sim.calculate(\"employment_income\", 2025)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/employer_ni.ipynb b/employer_ni.ipynb new file mode 100644 index 000000000..e7c2225eb --- /dev/null +++ b/employer_ni.ipynb @@ -0,0 +1,70 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Employer NI in PolicyEngine" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_uk import Microsimulation" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "baseline = Microsimulation()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "baseline.calculate(\"employee_pension_contributions\").sum() / 1e9" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/employer_ni_example.ipynb b/employer_ni_example.ipynb new file mode 100644 index 000000000..9afee3629 --- /dev/null +++ b/employer_ni_example.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_uk import Simulation\n", + "from policyengine_core.reforms import Reform\n", + "\n", + "\n", + "def get_employer_cost(employment_income, ni_rate, ni_threshold):\n", + " return employment_income + ni_rate * (employment_income - ni_threshold)\n", + " raise_emp_ni = Reform.from_dict(\n", + " {\n", + " \"gov.hmrc.national_insurance.class_1.rates.employer\": {\n", + " \"2025-01-01.2030-01-01\": ni_rate\n", + " },\n", + " \"gov.hmrc.national_insurance.class_1.thresholds.secondary_threshold\": {\n", + " \"2025-01-01.2030-01-01\": ni_threshold\n", + " },\n", + " }\n", + " )\n", + "\n", + " raised_ni_simulation = Simulation(\n", + " situation={\n", + " \"employment_income\": employment_income,\n", + " },\n", + " reform=raise_emp_ni,\n", + " )\n", + "\n", + " # return employment_income + raised_ni_simulation.calculate(\"ni_employer\", 2025)[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "45495.47096412556" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from policyengine_uk.system import system\n", + "\n", + "parameters = system.parameters(2025).gov.hmrc.national_insurance\n", + "\n", + "RATE = parameters.class_1.rates.employer # 13.8%\n", + "THRESHOLD = parameters.class_1.thresholds.secondary_threshold # 9100\n", + "\n", + "\n", + "def get_new_i(cost, rate, threshold):\n", + " return (cost + rate * threshold) / (1 + rate)\n", + "\n", + "\n", + "baseline_emp_cost = get_employer_cost(40_000, RATE, THRESHOLD)\n", + "baseline_emp_cost" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "39584.463443166314" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new_i = get_new_i(baseline_emp_cost, 0.15, THRESHOLD)\n", + "new_i" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "45495.47096412557" + ] + }, + "execution_count": 73, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_employer_cost(new_i, 0.15, THRESHOLD)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/README.md b/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/README.md new file mode 100644 index 000000000..079c942a0 --- /dev/null +++ b/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/README.md @@ -0,0 +1 @@ +# Employer NI diff --git a/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/employee_incidence.yaml b/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/employee_incidence.yaml new file mode 100644 index 000000000..eebcf37df --- /dev/null +++ b/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/employee_incidence.yaml @@ -0,0 +1,6 @@ +description: Assume that employers keep employment costs constant in response to employer NI changes. +values: + 2010-01-01: true +metadata: + label: Employer NI employee incidence + unit: bool diff --git a/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/exempt_employer_pension_contributions.yaml b/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/exempt_employer_pension_contributions.yaml new file mode 100644 index 000000000..2cff6955e --- /dev/null +++ b/policyengine_uk/parameters/gov/contrib/policyengine/employer_ni/exempt_employer_pension_contributions.yaml @@ -0,0 +1,6 @@ +description: Whether to exempt employer pension contributions from employer NI. +values: + 2010-01-01: true +metadata: + unit: bool + label: exempt employer pension contributions from employers' NI \ No newline at end of file diff --git a/policyengine_uk/parameters/gov/hmrc/income_tax/income_tax_additions.yaml b/policyengine_uk/parameters/gov/hmrc/income_tax/income_tax_additions.yaml index 7ddbb71f4..e6e575a4d 100644 --- a/policyengine_uk/parameters/gov/hmrc/income_tax/income_tax_additions.yaml +++ b/policyengine_uk/parameters/gov/hmrc/income_tax/income_tax_additions.yaml @@ -8,4 +8,4 @@ values: - savings_income_tax - dividend_income_tax - CB_HITC - - private_pension_contributions_tax + - personal_pension_contributions_tax diff --git a/policyengine_uk/parameters/gov/hmrc/pensions/pensions_programs.yaml b/policyengine_uk/parameters/gov/hmrc/pensions/pensions_programs.yaml index a373b6fcf..694ad69c3 100644 --- a/policyengine_uk/parameters/gov/hmrc/pensions/pensions_programs.yaml +++ b/policyengine_uk/parameters/gov/hmrc/pensions/pensions_programs.yaml @@ -1,8 +1,8 @@ description: Pensions programs values: 0000-01-01: - - private_pension_contributions - - occupational_pension_contributions + - personal_pension_contributions + - employee_pension_contributions metadata: unit: list diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit.yaml index 9d59d344e..23bdfdb85 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit.yaml @@ -6,7 +6,7 @@ person: age: 30 employment_income: 30_000 - private_pension_contributions: 1_000 + personal_pension_contributions: 1_000 weekly_hours: 20 benunits: benunit: @@ -30,7 +30,7 @@ person: age: 30 employment_income: 3_000 - private_pension_contributions: 1_000 + personal_pension_contributions: 1_000 weekly_hours: 20 benunits: benunit: @@ -85,7 +85,7 @@ age: 20 weekly_hours: 25 employment_income: 12_000 - private_pension_contributions: 57 + personal_pension_contributions: 57 dla_m: 62.55 * 52 uc_limited_capability_for_WRA: true person_2: diff --git a/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/income_tax.yaml b/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/income_tax.yaml index b45256684..5a0ad5ce0 100644 --- a/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/income_tax.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/income_tax.yaml @@ -10,6 +10,6 @@ absolute_error_margin: 10 input: employment_income: 34000 - private_pension_contributions: 1200 + personal_pension_contributions: 1200 output: income_tax: (34000 - 1200 - 12500) * 0.2 diff --git a/policyengine_uk/tests/policy/baseline/gov/hmrc/pensions/pension_contributions.yaml b/policyengine_uk/tests/policy/baseline/gov/hmrc/pensions/pension_contributions.yaml index 7d0fa5dbe..31dd24bff 100644 --- a/policyengine_uk/tests/policy/baseline/gov/hmrc/pensions/pension_contributions.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/hmrc/pensions/pension_contributions.yaml @@ -1,63 +1,63 @@ - name: No pension contributions period: 2024 input: - private_pension_contributions: 0 - occupational_pension_contributions: 0 + personal_pension_contributions: 0 + employee_pension_contributions: 0 output: pension_contributions: 0 - name: Only private pension contributions period: 2024 input: - private_pension_contributions: 5000 - occupational_pension_contributions: 0 + personal_pension_contributions: 5000 + employee_pension_contributions: 0 output: pension_contributions: 5000 - name: Only occupational pension contributions period: 2024 input: - private_pension_contributions: 0 - occupational_pension_contributions: 7500 + personal_pension_contributions: 0 + employee_pension_contributions: 7500 output: pension_contributions: 7500 - name: Both types of pension contributions period: 2024 input: - private_pension_contributions: 3000 - occupational_pension_contributions: 4000 + personal_pension_contributions: 3000 + employee_pension_contributions: 4000 output: pension_contributions: 7000 - name: High contribution amounts period: 2024 input: - private_pension_contributions: 20000 - occupational_pension_contributions: 30000 + personal_pension_contributions: 20000 + employee_pension_contributions: 30000 output: pension_contributions: 50000 - name: Very low positive contributions period: 2024 input: - private_pension_contributions: 1 - occupational_pension_contributions: 1 + personal_pension_contributions: 1 + employee_pension_contributions: 1 output: pension_contributions: 2 - name: Uneven contributions period: 2024 input: - private_pension_contributions: 1234.56 - occupational_pension_contributions: 9876.54 + personal_pension_contributions: 1234.56 + employee_pension_contributions: 9876.54 output: pension_contributions: 11111.10 - name: Maximum allowed annual contributions (for 2023/2024 tax year) period: 2024 input: - private_pension_contributions: 40000 - occupational_pension_contributions: 20000 + personal_pension_contributions: 40000 + employee_pension_contributions: 20000 output: pension_contributions: 60000 \ No newline at end of file diff --git a/policyengine_uk/tests/policy/baseline/gov/hmrc/pensions/pension_contributions_relief.yaml b/policyengine_uk/tests/policy/baseline/gov/hmrc/pensions/pension_contributions_relief.yaml index f3a8d9b5c..bf9728992 100644 --- a/policyengine_uk/tests/policy/baseline/gov/hmrc/pensions/pension_contributions_relief.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/hmrc/pensions/pension_contributions_relief.yaml @@ -3,7 +3,7 @@ absolute_error_margin: 0 input: employment_income: 76000 - private_pension_contributions: 40000 + personal_pension_contributions: 40000 output: pension_contributions_relief: 40000 - name: Pension relief excessive @@ -11,7 +11,7 @@ absolute_error_margin: 0 input: employment_income: 2000000 - private_pension_contributions: 400000 + personal_pension_contributions: 400000 output: pension_contributions_relief: 4000 - name: £30k self-employment income, no private pension contributions @@ -27,7 +27,7 @@ absolute_error_margin: 0.01 input: self_employment_income: 30_000 - private_pension_contributions: 3_000 + personal_pension_contributions: 3_000 output: pension_contributions_relief: 3_000 income_tax: 3286 - 3000 * 0.2 @@ -45,7 +45,7 @@ absolute_error_margin: 0.01 input: self_employment_income: 60_000 - private_pension_contributions: 6_000 + personal_pension_contributions: 6_000 output: pension_contributions_relief: 6_000 income_tax: 11032 - 6000 * 0.4 diff --git a/policyengine_uk/variables/contrib/policyengine/employer_ni/employer_ni_fixed_employer_cost_change.py b/policyengine_uk/variables/contrib/policyengine/employer_ni/employer_ni_fixed_employer_cost_change.py new file mode 100644 index 000000000..039384f7a --- /dev/null +++ b/policyengine_uk/variables/contrib/policyengine/employer_ni/employer_ni_fixed_employer_cost_change.py @@ -0,0 +1,110 @@ +from policyengine_uk.model_api import * + + +class employer_cost(Variable): + label = "employer cost" + entity = Person + definition_period = YEAR + value_type = float + unit = GBP + + def formula(person, period, parameters): + return person("employment_income", period) + person( + "ni_employer", period + ) + + +class employer_ni_fixed_employer_cost_change(Variable): + label = "employer NI reform incidence" + entity = Person + definition_period = YEAR + value_type = float + unit = GBP + + def formula(person, period, parameters): + if not parameters( + period + ).gov.contrib.policyengine.employer_ni.employee_incidence: + return 0 + # First, calculate baseline and reformed employer NI contributions. + + prior_employment_income = person( + "employment_income_before_lsr", period + ) + employment_income_behavioral_response = person( + "employment_income_behavioral_response", period + ) + benefits = add( + person, + period, + [ + "household_statutory_sick_pay", + "household_statutory_maternity_pay", + "household_statutory_paternity_pay", + ], + ) + employer_pension_contributions = person( + "employer_pension_contributions", period + ) + ni_class_1_income = ( + prior_employment_income + + employment_income_behavioral_response + + benefits + + employer_pension_contributions + ) + + # Calculate baseline employer cost + baseline_parameters = parameters(period).baseline + baseline_class_1 = ( + baseline_parameters.gov.hmrc.national_insurance.class_1 + ) + r_b = baseline_class_1.rates.employer + t_b = baseline_class_1.thresholds.secondary_threshold * WEEKS_IN_YEAR + p_b = ( + baseline_parameters.gov.contrib.policyengine.employer_ni.exempt_employer_pension_contributions + ) + pen_con_subtracted_b = employer_pension_contributions + if p_b: + pen_con_subtracted_b = employer_pension_contributions + else: + pen_con_subtracted_b = 0 + + baseline_employer_ni = r_b * ( + ni_class_1_income - pen_con_subtracted_b - t_b + ) + c_b = ni_class_1_income + baseline_employer_ni + + # Calculate new employment income keeping employer cost constant + + reform_parameters = parameters(period) + reform_class_1 = reform_parameters.gov.hmrc.national_insurance.class_1 + r_r = reform_class_1.rates.employer + t_r = reform_class_1.thresholds.secondary_threshold * WEEKS_IN_YEAR + p_r = ( + reform_parameters.gov.contrib.policyengine.employer_ni.exempt_employer_pension_contributions + ) + if p_r: + pen_con_subtracted_r = employer_pension_contributions + else: + pen_con_subtracted_r = 0 + + new_ni_class_1_income = (c_b + r_r * (pen_con_subtracted_r + t_r)) / ( + 1 + r_r + ) + + # Find difference in employment income + + previous_employment_income = ( + ni_class_1_income - benefits + ) - employer_pension_contributions + new_employment_income = ( + new_ni_class_1_income - benefits + ) - employer_pension_contributions + + pay_change = new_employment_income - previous_employment_income + + # Where a person's prior employment income was below the secondary threshold, the formula doesn't hold, so assume no change. + + below_threshold = previous_employment_income < t_b + + return where(below_threshold, 0, pay_change) diff --git a/policyengine_uk/variables/gov/hmrc/national_insurance/class_1/ni_class_1_employer.py b/policyengine_uk/variables/gov/hmrc/national_insurance/class_1/ni_class_1_employer.py index 4e763c8bc..9189d68a5 100644 --- a/policyengine_uk/variables/gov/hmrc/national_insurance/class_1/ni_class_1_employer.py +++ b/policyengine_uk/variables/gov/hmrc/national_insurance/class_1/ni_class_1_employer.py @@ -13,13 +13,22 @@ class ni_class_1_employer(Variable): def formula(person, period, parameters): class_1 = parameters(period).gov.hmrc.national_insurance.class_1 earnings = person("ni_class_1_income", period) + if not parameters( + period + ).gov.contrib.policyengine.employer_ni.exempt_employer_pension_contributions: + added_pension_contributions = person( + "employer_pension_contributions", period + ) + taxed_earnings = earnings + added_pension_contributions + else: + taxed_earnings = earnings secondary_threshold = ( class_1.thresholds.secondary_threshold * WEEKS_IN_YEAR / MONTHS_IN_YEAR ) main_earnings = max_( - earnings - secondary_threshold, + taxed_earnings - secondary_threshold, 0, ) return class_1.rates.employer * main_earnings diff --git a/policyengine_uk/variables/gov/hmrc/national_insurance/class_1/ni_class_1_income.py b/policyengine_uk/variables/gov/hmrc/national_insurance/class_1/ni_class_1_income.py index ec122e8fc..097b4f307 100644 --- a/policyengine_uk/variables/gov/hmrc/national_insurance/class_1/ni_class_1_income.py +++ b/policyengine_uk/variables/gov/hmrc/national_insurance/class_1/ni_class_1_income.py @@ -13,5 +13,5 @@ class ni_class_1_income(Variable): "household_statutory_sick_pay", "household_statutory_maternity_pay", "household_statutory_paternity_pay", - ] + ] # Employee pension contributions are not deducted reference = "https://www.legislation.gov.uk/ukpga/1992/4/section/3" diff --git a/policyengine_uk/variables/gov/hmrc/pensions/pension_contributions_relief.py b/policyengine_uk/variables/gov/hmrc/pensions/pension_contributions_relief.py index 52bf0e3f7..564f8d84a 100644 --- a/policyengine_uk/variables/gov/hmrc/pensions/pension_contributions_relief.py +++ b/policyengine_uk/variables/gov/hmrc/pensions/pension_contributions_relief.py @@ -13,7 +13,7 @@ class pension_contributions_relief(Variable): unit = GBP def formula(person, period, parameters): - contributions = person("private_pension_contributions", period) + contributions = person("pension_contributions", period) pension_allowance = person("pension_annual_allowance", period) age_limit = parameters( period diff --git a/policyengine_uk/variables/gov/hmrc/pensions/private_pension_contributions_tax.py b/policyengine_uk/variables/gov/hmrc/pensions/private_pension_contributions_tax.py index 0007164c8..8ae0b3295 100644 --- a/policyengine_uk/variables/gov/hmrc/pensions/private_pension_contributions_tax.py +++ b/policyengine_uk/variables/gov/hmrc/pensions/private_pension_contributions_tax.py @@ -1,7 +1,7 @@ from policyengine_uk.model_api import * -class private_pension_contributions_tax(Variable): +class personal_pension_contributions_tax(Variable): value_type = float entity = Person label = "Reduction in taxable income from pension contributions to pensions other than the State Pension" @@ -16,12 +16,12 @@ def formula(person, period, parameters): p = parameters(period).gov.hmrc.income_tax.rates.uk taxed_income = person("taxed_income", period) - private_pension_contributions = person( - "private_pension_contributions", period - ) + personal_pension_contributions = person( + "employee_pension_contributions", period + ) + person("personal_pension_contributions", period) pension_annual_allowance = person("pension_annual_allowance", period) taxable_contributions = ( - private_pension_contributions - pension_annual_allowance + personal_pension_contributions - pension_annual_allowance ) tax_rate = p.marginal_rates(taxed_income) diff --git a/policyengine_uk/variables/household/consumption/consumption_share.py b/policyengine_uk/variables/household/consumption/consumption_share.py new file mode 100644 index 000000000..3646ee73f --- /dev/null +++ b/policyengine_uk/variables/household/consumption/consumption_share.py @@ -0,0 +1,20 @@ +from policyengine_uk.model_api import * + + +class consumption_shareholding(Variable): + label = "share of UK consumption" + documentation = "Exposure to taxes on consumption" + entity = Household + definition_period = YEAR + value_type = float + unit = GBP + + def formula(household, period, parameters): + consumption = household("consumption", period) + if ( + household.simulation.dataset is not None + and household("consumption", period).sum() != 0 + ): + weight = household("household_weight", period) + return consumption / (consumption * weight).sum() + return 0 diff --git a/policyengine_uk/variables/input/consumption/coicop.py b/policyengine_uk/variables/input/consumption/coicop.py index 335b37bec..d551109ea 100644 --- a/policyengine_uk/variables/input/consumption/coicop.py +++ b/policyengine_uk/variables/input/consumption/coicop.py @@ -171,25 +171,6 @@ class childcare_expenses(Variable): uprating = "gov.obr.consumer_price_index" -class private_pension_contributions(Variable): - value_type = float - entity = Person - label = "private pension contributions" - documentation = "Total amount spent on private pension contributions" - definition_period = YEAR - unit = GBP - uprating = "gov.obr.average_earnings" - - -class occupational_pension_contributions(Variable): - value_type = float - entity = Person - label = "occupational pension contributions" - documentation = "Total amount spent on occupational pension contributions" - definition_period = YEAR - unit = GBP - - class consumption(Variable): label = "consumption" entity = Household diff --git a/policyengine_uk/variables/input/consumption/property/maintenance.py b/policyengine_uk/variables/input/consumption/property/maintenance.py index 44e752acf..22e8de159 100644 --- a/policyengine_uk/variables/input/consumption/property/maintenance.py +++ b/policyengine_uk/variables/input/consumption/property/maintenance.py @@ -27,6 +27,27 @@ class employer_pension_contributions(Variable): documentation = "Total amount spent on employer pension contributions" definition_period = YEAR unit = GBP + uprating = "gov.obr.average_earnings" + + +class employee_pension_contributions(Variable): + label = "Label" + documentation = "Description" + entity = Person + definition_period = YEAR + value_type = float + unit = GBP + uprating = "gov.obr.average_earnings" + + +class personal_pension_contributions(Variable): + label = "Label" + documentation = "Description" + entity = Person + definition_period = YEAR + value_type = float + unit = GBP + uprating = "gov.obr.average_earnings" class maintenance_expenses(Variable): diff --git a/policyengine_uk/variables/input/income.py b/policyengine_uk/variables/input/income.py index 33de5ab07..69c803a4b 100644 --- a/policyengine_uk/variables/input/income.py +++ b/policyengine_uk/variables/input/income.py @@ -16,6 +16,7 @@ class employment_income(Variable): adds = [ "employment_income_before_lsr", "employment_income_behavioral_response", + "employer_ni_fixed_employer_cost_change", ] uprating = "gov.obr.average_earnings" diff --git a/setup.py b/setup.py index fe91be890..ef22cadab 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ setup( name="PolicyEngine-UK", - version="2.1.1", + version="2.2.0", author="PolicyEngine", author_email="nikhil@policyengine.org", classifiers=[ @@ -27,7 +27,7 @@ ], install_requires=[ "PolicyEngine-Core>=3.6.4", - "PolicyEngine-UK-Data>=1.2.5,<1.3", + "PolicyEngine-UK-Data>=1.4,<1.5", "microdf_python", ], extras_require={ diff --git a/test.ipynb b/test.ipynb deleted file mode 100644 index 2b43b083b..000000000 --- a/test.ipynb +++ /dev/null @@ -1,427 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from policyengine_uk import Microsimulation" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([24039.1], dtype=float32)" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from policyengine_uk import Simulation\n", - "\n", - "sim = Simulation(situation={\n", - " \"employment_income\": 30_000,\n", - "})\n", - "\n", - "sim.calculate(\"household_net_income\")" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "sim = Microsimulation()" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/var/folders/vj/qc1d1nbd409ct142dvm7qp700000gn/T/ipykernel_95967/2760475092.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0msim\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"income_tax\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2028\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;36m1e9\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/microsimulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, use_weights, decode_enums)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_period\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmap_to\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0muse_weights\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, decode_enums)\u001b[0m\n\u001b[1;32m 461\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 462\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 463\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_calculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 464\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mEnumArray\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode_to_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_calculate\u001b[0;34m(self, variable_name, period)\u001b[0m\n\u001b[1;32m 686\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 687\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_for_cycle\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 688\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_run_formula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 689\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 690\u001b[0m \u001b[0;31m# If no result, use the default value and cache it\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_run_formula\u001b[0;34m(self, variable, population, period)\u001b[0m\n\u001b[1;32m 968\u001b[0m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 969\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 970\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters_at\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 971\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 972\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0marray\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/policyengine/policyengine-uk/policyengine_uk/variables/gov/hmrc/income_tax/income_tax.py\u001b[0m in \u001b[0;36mformula\u001b[0;34m(person, period, parameters)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgov\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhmrc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mincome_tax\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0madditions\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperson\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mincome_tax_additions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0msubtractions\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperson\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mincome_tax_subtractions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/commons/formulas.py\u001b[0m in \u001b[0;36madd\u001b[0;34m(entity, period, variables, options)\u001b[0m\n\u001b[1;32m 225\u001b[0m \u001b[0mArrayLike\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mThe\u001b[0m \u001b[0mresult\u001b[0m \u001b[0mof\u001b[0m \u001b[0mthe\u001b[0m \u001b[0moperation\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 226\u001b[0m \"\"\"\n\u001b[0;32m--> 227\u001b[0;31m return for_each_variable(\n\u001b[0m\u001b[1;32m 228\u001b[0m \u001b[0mentity\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvariables\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0magg_func\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"add\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0moptions\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 229\u001b[0m )\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/commons/formulas.py\u001b[0m in \u001b[0;36mfor_each_variable\u001b[0;34m(entity, period, variables, agg_func, group_agg_func, options)\u001b[0m\n\u001b[1;32m 181\u001b[0m \u001b[0mvariable_entity\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mentity\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mentity\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_variable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mentity\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 182\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvariable_entity\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkey\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mentity\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mentity\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 183\u001b[0;31m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mentity\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0moptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 184\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mvariable_entity\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_person\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 185\u001b[0m values = group_agg_func(\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/populations/population.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, variable_name, period, options)\u001b[0m\n\u001b[1;32m 135\u001b[0m )\n\u001b[1;32m 136\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 137\u001b[0;31m return self.simulation.calculate(\n\u001b[0m\u001b[1;32m 138\u001b[0m \u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mcalculate_kwargs\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 139\u001b[0m )\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/microsimulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, use_weights, decode_enums)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_period\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmap_to\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0muse_weights\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, decode_enums)\u001b[0m\n\u001b[1;32m 461\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 462\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 463\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_calculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 464\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mEnumArray\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode_to_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_calculate\u001b[0;34m(self, variable_name, period)\u001b[0m\n\u001b[1;32m 686\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 687\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_for_cycle\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 688\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_run_formula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 689\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 690\u001b[0m \u001b[0;31m# If no result, use the default value and cache it\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_run_formula\u001b[0;34m(self, variable, population, period)\u001b[0m\n\u001b[1;32m 968\u001b[0m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 969\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 970\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters_at\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 971\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 972\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0marray\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/policyengine/policyengine-uk/policyengine_uk/variables/gov/hmrc/income_tax/charges/child_benefit_hitc.py\u001b[0m in \u001b[0;36mformula\u001b[0;34m(person, period, parameters)\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperson\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m \u001b[0mCB_received\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mperson\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbenunit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"child_benefit\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 15\u001b[0m \u001b[0mhitc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgov\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhmrc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mincome_tax\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcharges\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCB_HITC\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0mincome\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mperson\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"adjusted_net_income\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/projectors/projector.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 32\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 33\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreference_entity\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 34\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtransform_and_bubble_up\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/populations/group_population.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, variable_name, period, options)\u001b[0m\n\u001b[1;32m 36\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmembers\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 38\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 39\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 40\u001b[0m def clone(\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/populations/population.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, variable_name, period, options)\u001b[0m\n\u001b[1;32m 135\u001b[0m )\n\u001b[1;32m 136\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 137\u001b[0;31m return self.simulation.calculate(\n\u001b[0m\u001b[1;32m 138\u001b[0m \u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mcalculate_kwargs\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 139\u001b[0m )\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/microsimulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, use_weights, decode_enums)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_period\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmap_to\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0muse_weights\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, decode_enums)\u001b[0m\n\u001b[1;32m 461\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 462\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 463\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_calculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 464\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mEnumArray\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode_to_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_calculate\u001b[0;34m(self, variable_name, period)\u001b[0m\n\u001b[1;32m 670\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvariable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefined_for\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 671\u001b[0m mask = (\n\u001b[0;32m--> 672\u001b[0;31m self.calculate(\n\u001b[0m\u001b[1;32m 673\u001b[0m \u001b[0mvariable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefined_for\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmap_to\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mentity\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 674\u001b[0m )\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/microsimulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, use_weights, decode_enums)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_period\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmap_to\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0muse_weights\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, decode_enums)\u001b[0m\n\u001b[1;32m 461\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 462\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 463\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_calculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 464\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mEnumArray\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode_to_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_calculate\u001b[0;34m(self, variable_name, period)\u001b[0m\n\u001b[1;32m 686\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 687\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_for_cycle\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 688\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_run_formula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 689\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 690\u001b[0m \u001b[0;31m# If no result, use the default value and cache it\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_run_formula\u001b[0;34m(self, variable, population, period)\u001b[0m\n\u001b[1;32m 968\u001b[0m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 969\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 970\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters_at\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 971\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 972\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0marray\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/policyengine/policyengine-uk/policyengine_uk/variables/gov/hmrc/child_benefit.py\u001b[0m in \u001b[0;36mformula\u001b[0;34m(benunit, period, parameters)\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0mtakeup_rate\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgov\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhmrc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchild_benefit\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtakeup\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[0moverall_p\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtakeup_rate\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moverall\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 26\u001b[0;31m return (random(benunit) < overall_p) * ~benunit(\n\u001b[0m\u001b[1;32m 27\u001b[0m \u001b[0;34m\"child_benefit_opts_out\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m )\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/populations/group_population.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, variable_name, period, options)\u001b[0m\n\u001b[1;32m 36\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmembers\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 38\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 39\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 40\u001b[0m def clone(\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/populations/population.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, variable_name, period, options)\u001b[0m\n\u001b[1;32m 135\u001b[0m )\n\u001b[1;32m 136\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 137\u001b[0;31m return self.simulation.calculate(\n\u001b[0m\u001b[1;32m 138\u001b[0m \u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mcalculate_kwargs\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 139\u001b[0m )\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/microsimulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, use_weights, decode_enums)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0mperiod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_period\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_calculation_period\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmap_to\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0muse_weights\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36mcalculate\u001b[0;34m(self, variable_name, period, map_to, decode_enums)\u001b[0m\n\u001b[1;32m 461\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 462\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 463\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_calculate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 464\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mEnumArray\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mdecode_enums\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode_to_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_calculate\u001b[0;34m(self, variable_name, period)\u001b[0m\n\u001b[1;32m 686\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 687\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_for_cycle\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 688\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_run_formula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 689\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 690\u001b[0m \u001b[0;31m# If no result, use the default value and cache it\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/simulations/simulation.py\u001b[0m in \u001b[0;36m_run_formula\u001b[0;34m(self, variable, population, period)\u001b[0m\n\u001b[1;32m 968\u001b[0m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 969\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 970\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mformula\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpopulation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters_at\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 971\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 972\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0marray\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/policyengine/policyengine-uk/policyengine_uk/variables/gov/hmrc/child_benefit.py\u001b[0m in \u001b[0;36mformula\u001b[0;34m(benunit, period, parameters)\u001b[0m\n\u001b[1;32m 47\u001b[0m return where(\n\u001b[1;32m 48\u001b[0m \u001b[0mbenunit\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0min_phase_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 49\u001b[0;31m \u001b[0mrandom\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbenunit\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mcb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopt_out_rate\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 50\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 51\u001b[0m )\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/commons/formulas.py\u001b[0m in \u001b[0;36mrandom\u001b[0;34m(population)\u001b[0m\n\u001b[1;32m 331\u001b[0m \u001b[0;31m# Generate random values for each entity\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 332\u001b[0m values = np.array(\n\u001b[0;32m--> 333\u001b[0;31m [\n\u001b[0m\u001b[1;32m 334\u001b[0m np.random.default_rng(\n\u001b[1;32m 335\u001b[0m \u001b[0mseed\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mid\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;36m100\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mpopulation\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msimulation\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcount_random_calls\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/site-packages/policyengine_core/commons/formulas.py\u001b[0m in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 332\u001b[0m values = np.array(\n\u001b[1;32m 333\u001b[0m [\n\u001b[0;32m--> 334\u001b[0;31m np.random.default_rng(\n\u001b[0m\u001b[1;32m 335\u001b[0m \u001b[0mseed\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mid\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;36m100\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mpopulation\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msimulation\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcount_random_calls\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 336\u001b[0m ).random()\n", - "\u001b[0;32mnumpy/random/_generator.pyx\u001b[0m in \u001b[0;36mnumpy.random._generator.default_rng\u001b[0;34m()\u001b[0m\n", - "\u001b[0;32m_pcg64.pyx\u001b[0m in \u001b[0;36mnumpy.random._pcg64.PCG64.__init__\u001b[0;34m()\u001b[0m\n", - "\u001b[0;32m~/anaconda3/lib/python3.11/contextlib.py\u001b[0m in \u001b[0;36minner\u001b[0;34m(*args, **kwds)\u001b[0m\n\u001b[1;32m 79\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0minner\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_recreate_cm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 81\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 82\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0minner\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 83\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: " - ] - } - ], - "source": [ - "sim.calculate(\"income_tax\", 2028).sum()/1e9" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
National Insurance (£bn)Income Tax (£bn)Population (millions)
SOUTH_EAST13.247.89.4
LONDON16.249.48.9
NORTH_WEST6.517.48.4
EAST_OF_ENGLAND8.531.46.4
WEST_MIDLANDS5.515.26.0
SOUTH_WEST6.119.15.8
YORKSHIRE6.223.25.5
SCOTLAND5.318.55.5
EAST_MIDLANDS5.514.04.9
WALES2.58.13.1
NORTH_EAST2.56.22.7
NORTHERN_IRELAND1.43.41.9
\n", - "
" - ], - "text/plain": [ - " National Insurance (£bn) Income Tax (£bn) \\\n", - "SOUTH_EAST 13.2 47.8 \n", - "LONDON 16.2 49.4 \n", - "NORTH_WEST 6.5 17.4 \n", - "EAST_OF_ENGLAND 8.5 31.4 \n", - "WEST_MIDLANDS 5.5 15.2 \n", - "SOUTH_WEST 6.1 19.1 \n", - "YORKSHIRE 6.2 23.2 \n", - "SCOTLAND 5.3 18.5 \n", - "EAST_MIDLANDS 5.5 14.0 \n", - "WALES 2.5 8.1 \n", - "NORTH_EAST 2.5 6.2 \n", - "NORTHERN_IRELAND 1.4 3.4 \n", - "\n", - " Population (millions) \n", - "SOUTH_EAST 9.4 \n", - "LONDON 8.9 \n", - "NORTH_WEST 8.4 \n", - "EAST_OF_ENGLAND 6.4 \n", - "WEST_MIDLANDS 6.0 \n", - "SOUTH_WEST 5.8 \n", - "YORKSHIRE 5.5 \n", - "SCOTLAND 5.5 \n", - "EAST_MIDLANDS 4.9 \n", - "WALES 3.1 \n", - "NORTH_EAST 2.7 \n", - "NORTHERN_IRELAND 1.9 " - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from policyengine_uk import Microsimulation\n", - "import pandas as pd\n", - "\n", - "sim = Microsimulation()\n", - "\n", - "df = sim.df([\"national_insurance\", \"income_tax\", \"people\"])\n", - "\n", - "summary = pd.DataFrame(\n", - " df.groupby(sim.calc(\"region\", map_to=\"person\")).sum()\n", - ").sort_values(by=\"people\", ascending=False)\n", - "summary.national_insurance = summary.national_insurance.apply(\n", - " lambda x: round(x / 1e9, 1)\n", - ")\n", - "summary.income_tax = summary.income_tax.apply(lambda x: round(x / 1e9, 1))\n", - "summary.people = summary.people.apply(lambda x: round(x / 1e6, 1))\n", - "summary.columns = [\n", - " \"National Insurance (£bn)\",\n", - " \"Income Tax (£bn)\",\n", - " \"Population (millions)\",\n", - "]\n", - "summary" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "sim = Microsimulation()\n", - "\n", - "df = sim.df([\"tv_licence_discount\", \"income_tax\", \"people\"])\n" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Index(['tv_licence_discount', 'income_tax', 'people'], dtype='object')" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df.columns" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from policyengine_uk import Microsimulation\n", - "from policyengine_core.reforms import Reform\n", - "\n", - "reform = Reform.from_dict({\n", - " \"gov.contrib.labour.private_school_vat\": {\n", - " \"2024-01-01.2100-12-31\": 0.2\n", - " }\n", - "}, country_id=\"uk\")\n", - "\n", - "\n", - "baseline = Microsimulation()\n", - "reformed = Microsimulation(reform=reform)\n", - "baseline_income = baseline.calculate(\"household_net_income\", period=2025)\n", - "reformed_income = reformed.calculate(\"household_net_income\", period=2025)\n", - "difference_income = reformed_income - baseline_income" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from policyengine_uk import Microsimulation\n", - "from policyengine_core.reforms import Reform\n", - "\n", - "reform = Reform.from_dict({\n", - " \"gov.contrib.labour.private_school_vat.private_school_factor\": {\n", - " \"2024-01-01.2100-12-31\": 30\n", - " }\n", - "}, country_id=\"uk\")\n", - "\n", - "simulation = Microsimulation(reform=reform)\n", - "\n", - "simulation.calculate(\"attends_private_school\", 2025).sum()/1e3" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-1.7893123377486972" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "reformed_income.sum()/1e9 - baseline_income.sum()/1e9" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "693.0988961628248" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "reformed.calculate(\"attends_private_school\", 2025).sum()/1e3" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "817.9906490054437" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "(reformed.calculate(\"attends_private_school\", 2025) > 0).sum()/1e3" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.5" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -}