From 54e68e2614668d1d8ee83665f2d970a34a364845 Mon Sep 17 00:00:00 2001 From: "Anthony V." Date: Tue, 19 Nov 2024 11:13:50 +0100 Subject: [PATCH] Fix cliff impacts (#997) * fix: Refactor cliff vars and params to mimic US * chore: Changelog * fix: Refactor MTR to use marginal_tax_rate_adults param * chore: Changelog modification * fix: Make corrections to cliff_evaluated * chore: Lint --- changelog_entry.yaml | 8 ++++ .../simulation/marginal_tax_rate_adults.yaml | 6 +++ .../simulation/marginal_tax_rate_delta.yaml | 5 +++ policyengine_uk/variables/household/cliff.py | 41 ++++--------------- .../variables/household/marginal_tax_rate.py | 10 +++-- 5 files changed, 33 insertions(+), 37 deletions(-) create mode 100644 policyengine_uk/parameters/gov/simulation/marginal_tax_rate_adults.yaml create mode 100644 policyengine_uk/parameters/gov/simulation/marginal_tax_rate_delta.yaml diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb..6cae82e57 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,8 @@ +- bump: patch + changes: + added: + - marginal_tax_rate_delta parameter + - marginal_tax_rate_adults parameter + changed: + - Refactored cliff_gap variable to use marginal_tax_rate_delta parameter + - Refactored marginal_tax_rate variable to use both new parameters \ No newline at end of file diff --git a/policyengine_uk/parameters/gov/simulation/marginal_tax_rate_adults.yaml b/policyengine_uk/parameters/gov/simulation/marginal_tax_rate_adults.yaml new file mode 100644 index 000000000..1f1ae60a4 --- /dev/null +++ b/policyengine_uk/parameters/gov/simulation/marginal_tax_rate_adults.yaml @@ -0,0 +1,6 @@ +description: Number of adults to simulate a marginal tax rate for, in each household. +values: + 0000-01-01: 2 +metadata: + unit: int + label: Number of adults to simulate a marginal tax rate for diff --git a/policyengine_uk/parameters/gov/simulation/marginal_tax_rate_delta.yaml b/policyengine_uk/parameters/gov/simulation/marginal_tax_rate_delta.yaml new file mode 100644 index 000000000..11f9a380a --- /dev/null +++ b/policyengine_uk/parameters/gov/simulation/marginal_tax_rate_delta.yaml @@ -0,0 +1,5 @@ +description: Amount by which employment_income is increased to calculate marginal tax rate. +values: + 0000-01-01: 1_000 +metadata: + unit: currency-GBP diff --git a/policyengine_uk/variables/household/cliff.py b/policyengine_uk/variables/household/cliff.py index e111e06f7..19060c1e8 100644 --- a/policyengine_uk/variables/household/cliff.py +++ b/policyengine_uk/variables/household/cliff.py @@ -11,7 +11,9 @@ class cliff_evaluated(Variable): def formula(person, period, parameters): adult_index_values = person("adult_index", period) - cliff_adult_count = 2 + cliff_adult_count = parameters( + period + ).gov.simulation.marginal_tax_rate_adults return adult_index_values <= cliff_adult_count @@ -20,47 +22,20 @@ class cliff_gap(Variable): entity = Person label = "cliff gap" unit = GBP - documentation = "Amount of income lost if this person's employment income increased by £2,000." + documentation = "Amount of income lost if this person's employment income increased by delta amount." definition_period = YEAR def formula(person, period, parameters): - DELTA = 2_000 - cliff_values = np.zeros(person.count, dtype=np.float32) - simulation = person.simulation - adult_index_values = person("adult_index", period) - cliff_adult_count = 2 - for adult_index in range(1, 1 + cliff_adult_count): - alt_simulation = simulation.get_branch( - f"adult_{adult_index}_2k_pay_rise" - ) - mask = adult_index_values == adult_index - for variable in simulation.tax_benefit_system.variables: - if variable not in simulation.input_variables: - alt_simulation.delete_arrays(variable) - alt_simulation.set_input( - "employment_income", - period, - person("employment_income", period) + mask * DELTA, - ) - alt_person = alt_simulation.person - household_net_income = person.household( - "household_net_income", period - ) - household_net_income_higher_earnings = alt_person.household( - "household_net_income", period - ) - increase = ( - household_net_income_higher_earnings - household_net_income - ) - cliff_values += where(mask & (increase < 0), -increase, 0) - return cliff_values + delta = parameters(period).gov.simulation.marginal_tax_rate_delta + mtr = person("marginal_tax_rate", period) + return max_(0, (mtr - 1) * delta) class is_on_cliff(Variable): value_type = bool entity = Person label = "is on a tax-benefit cliff" - documentation = "Whether this person would be worse off if their employment income were $2,000 higher." + documentation = "Whether this person would be worse off if their employment income were higher by delta amount." definition_period = YEAR def formula(person, period, parameters): diff --git a/policyengine_uk/variables/household/marginal_tax_rate.py b/policyengine_uk/variables/household/marginal_tax_rate.py index 15cb10143..3e4d56253 100644 --- a/policyengine_uk/variables/household/marginal_tax_rate.py +++ b/policyengine_uk/variables/household/marginal_tax_rate.py @@ -11,11 +11,13 @@ class marginal_tax_rate(Variable): unit = "/1" def formula(person, period, parameters): + p = parameters(period).gov.simulation mtr_values = np.zeros(person.count, dtype=np.float32) simulation = person.simulation adult_index_values = person("adult_index", period) - DELTA = 1_000 - for adult_index in [1, 2]: + delta = p.marginal_tax_rate_delta + adult_count = p.marginal_tax_rate_adults + for adult_index in range(1, 1 + adult_count): alt_simulation = simulation.get_branch( f"adult_{adult_index}_pay_rise" ) @@ -32,7 +34,7 @@ def formula(person, period, parameters): alt_simulation.set_input( "employment_income", period, - person("employment_income", period) + mask * DELTA, + person("employment_income", period) + mask * delta, ) alt_person = alt_simulation.person household_net_income = person.household( @@ -44,5 +46,5 @@ def formula(person, period, parameters): increase = ( household_net_income_higher_earnings - household_net_income ) - mtr_values += where(mask, 1 - increase / DELTA, 0) + mtr_values += where(mask, 1 - increase / delta, 0) return mtr_values