Skip to content

Commit

Permalink
edited the main class accordingly
Browse files Browse the repository at this point in the history
  • Loading branch information
masterismail committed Jul 30, 2024
1 parent 9412b9d commit 06f0d2c
Show file tree
Hide file tree
Showing 4 changed files with 289 additions and 23 deletions.
62 changes: 40 additions & 22 deletions policyengine/economic_impact/budgetary_impact/overall/overall.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from policyengine.economic_impact.base_metric_calculator import BaseMetricCalculator
from policyengine_uk import Microsimulation
from policyengine_core.reforms import Reform


class BudgetaryImpact(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
Expand All @@ -8,64 +10,80 @@ def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default
self.reformed = reformed

def calculate(self):

baseline_total_tax = self.baseline.calculate("household_tax").sum()
reformed_total_tax = self.reformed.calculate("household_tax").sum()

tax_revenue_impact = reformed_total_tax - baseline_total_tax

baseline_total_benefits = self.baseline.calculate("household_benefits").sum()
reformed_total_benefits = self.reformed.calculate("household_benefits").sum()


benefit_spending_impact = reformed_total_benefits - baseline_total_benefits

budgetary_impact = tax_revenue_impact - benefit_spending_impact



return {
"budgetary_impact" : round(budgetary_impact,2)
"budgetary_impact": round(budgetary_impact, 2)
}


class BenefitSpendingImpact(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
super().__init__(baseline, reformed, default_period)
self.baseline = baseline
self.reformed = reformed

def calculate(self):

baseline_total_benefits = self.baseline.calculate("household_benefits").sum()
reformed_total_benefits = self.reformed.calculate("household_benefits").sum()


benefit_spending_impact = reformed_total_benefits - baseline_total_benefits



return {
"baseline_total_benefits": round(baseline_total_benefits,2),
"reformed_total_benefits": round(reformed_total_benefits,2),
"benefit_spending_impact": round(benefit_spending_impact,2)
"baseline_total_benefits": round(baseline_total_benefits, 2),
"reformed_total_benefits": round(reformed_total_benefits, 2),
"benefit_spending_impact": round(benefit_spending_impact, 2)
}


class TaxRevenueImpact(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
super().__init__(baseline, reformed, default_period)
self.baseline = baseline
self.reformed = reformed

def calculate(self):

baseline_total_tax = self.baseline.calculate("household_tax").sum()
reformed_total_tax = self.reformed.calculate("household_tax").sum()

tax_revenue_impact = reformed_total_tax - baseline_total_tax


return {
"baseline_total_tax": round(baseline_total_tax,2),
"reformed_total_tax": round(reformed_total_tax,2),
"tax_revenue_impact": round(tax_revenue_impact,2)
}
"baseline_total_tax": round(baseline_total_tax, 2),
"reformed_total_tax": round(reformed_total_tax, 2),
"tax_revenue_impact": round(tax_revenue_impact, 2)
}



# from policyengine_uk import Microsimulation
# # Define your reform
# reformm = Reform.from_dict({
# "gov.hmrc.income_tax.rates.uk[0].rate": {
# "2024-01-01.2100-12-31": 0.55
# }
# }, country_id="uk")

# # Create baseline and reformed simulations
# baseline = Microsimulation() # Ensure this initializes correctly
# reformed = Microsimulation(reform=reformm) # Ensure this applies the reform correctly

# # Set default calculation period
# baseline.default_calculation_period = 2024
# reformed.default_calculation_period = 2024

# # Create metric calculators
# b1 = BenefitSpendingImpact(reformed=reformed, baseline=baseline)
# a1 = BudgetaryImpact(reformed=reformed, baseline=baseline)
# c1 = TaxRevenueImpact(reformed=reformed, baseline=baseline)

# # Print results
# print(b1.calculate())
# print(a1.calculate())
# print(c1.calculate())
30 changes: 29 additions & 1 deletion policyengine/economic_impact/economic_impact.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,23 @@
TaxRevenueImpact
)

from .labour_supply_impact.earnings.overall.relative.relative import IncomeLSR , SubstitutionLSR , NetLSRChange

from .labour_supply_impact.earnings.overall.absolute.absolute import (
IncomeLSR as AbsoluteIncomeLSR,
SubstitutionLSR as AbsoluteSubstitutionLSR,
NetLSRChange as AbsoluteNetLSRChange
)

from .labour_supply_impact.earnings.by_decile.relative.substitution_effect.substitutional_effect import SubstitutionEffect
from .labour_supply_impact.earnings.by_decile.relative.income_effect.income_effect import IncomeEffect
from .labour_supply_impact.earnings.by_decile.relative.total.total import Total

from .labour_supply_impact.earnings.by_decile.absolute.substitution_effect.substitution_effect import SubstitutionEffect as AbsoluteSubstutionEffect
from .labour_supply_impact.earnings.by_decile.absolute.income_effect.income_effect import IncomeEffect as AbsoluteIncomeEffect
from .labour_supply_impact.earnings.by_decile.absolute.total.total import Total as AbsoluteTotal


from typing import Dict

class EconomicImpact:
Expand Down Expand Up @@ -105,7 +122,18 @@ def __init__(self, reform: dict, country: str) -> None:
"poverty/deep/male": DeepMalePoverty(self.baseline, self.reformed),
"poverty/deep/female": DeepFemalePoverty(self.baseline, self.reformed),
"poverty/deep/gender/all": DeepGenderAllPoverty(self.baseline, self.reformed),

"labour_supply_impact/earnings/overall/relative/IncomeLSR" : IncomeLSR(self.baseline,self.reformed),
"labour_supply_impact/earnings/overall/relative/SubstitutionLSR" : SubstitutionLSR(self.baseline,self.reformed),
"labour_supply_impact/earnings/overall/relative/NetLSRChange" : NetLSRChange(self.baseline,self.reformed),
"labour_supply_impact/earnings/overall/absolute/IncomeLSR" : AbsoluteIncomeLSR(self.baseline,self.reformed),
"labour_supply_impact/earnings/overall/absolute/SubstitutionLSR" : AbsoluteSubstitutionLSR(self.baseline,self.reformed),
"labour_supply_impact/earnings/overall/absolute/NetLSRChange" : AbsoluteNetLSRChange(self.baseline,self.reformed),
"labour_supply_impact/earnings/by_decile/relative/IncomeEffect" : IncomeEffect(self.baseline,self.reformed),
"labour_supply_impact/earnings/by_decile/relative/SubstitutionEffect" : SubstitutionEffect(self.baseline,self.reformed),
"labour_supply_impact/earnings/by_decile/relative/Total" : Total(self.baseline,self.reformed),
"labour_supply_impact/earnings/by_decile/absolute/income_effect" : AbsoluteIncomeEffect(self.baseline,self.reformed),
"labour_supply_impact/earnings/by_decile/absolute/substitution_effect" : AbsoluteSubstutionEffect(self.baseline,self.reformed),
"labour_supply_impact/earnings/by_decile/absolute/total" : AbsoluteTotal(self.baseline,self.reformed),
}

def _get_simulation_class(self) -> type:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from policyengine.economic_impact.base_metric_calculator import BaseMetricCalculator
from policyengine_uk import Microsimulation
from policyengine_core.reforms import Reform
from microdf import MicroSeries
import numpy as np


class IncomeLSR(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
super().__init__(baseline, reformed, default_period)
self.baseline = baseline
self.reformed = reformed

def calculate(self):
income_lsr_baseline = 0
income_lsr_reformed = 0

if "employment_income_behavioral_response" in self.baseline.tax_benefit_system.variables:
if any(self.baseline.calculate("employment_income_behavioral_response") != 0):
income_lsr_baseline = self.baseline.calculate("income_elasticity_lsr").sum()

if "employment_income_behavioral_response" in self.reformed.tax_benefit_system.variables:
if any(self.reformed.calculate("employment_income_behavioral_response") != 0):
income_lsr_reformed = self.reformed.calculate("income_elasticity_lsr").sum()

income_lsr = income_lsr_reformed - income_lsr_baseline
# Convert to billions and round to 2 decimal places
income_lsr_billion = round(income_lsr / 1e9, 2)

return {
"income_lsr": income_lsr_billion
}

class SubstitutionLSR(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
super().__init__(baseline, reformed, default_period)
self.baseline = baseline
self.reformed = reformed

def calculate(self):
substitution_lsr_baseline = 0
substitution_lsr_reformed = 0

if "employment_income_behavioral_response" in self.baseline.tax_benefit_system.variables:
if any(self.baseline.calculate("employment_income_behavioral_response") != 0):
substitution_lsr_baseline = self.baseline.calculate("substitution_elasticity_lsr").sum()

if "employment_income_behavioral_response" in self.reformed.tax_benefit_system.variables:
if any(self.reformed.calculate("employment_income_behavioral_response") != 0):
substitution_lsr_reformed = self.reformed.calculate("substitution_elasticity_lsr").sum()

substitution_lsr = substitution_lsr_reformed - substitution_lsr_baseline
# Convert to billions and round to 2 decimal places
substitution_lsr_billion = round(substitution_lsr / 1e9, 2)

return {
"substitution_lsr": substitution_lsr_billion
}

class NetLSRChange(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
super().__init__(baseline, reformed, default_period)
self.baseline = baseline
self.reformed = reformed

def calculate(self):
income_result = IncomeLSR(baseline=self.baseline, reformed=self.reformed).calculate()
substitution_result = SubstitutionLSR(baseline=self.baseline, reformed=self.reformed).calculate()

income_value = income_result["income_lsr"]
substitution_value = substitution_result["substitution_lsr"]

net_change = (income_value + substitution_value)
# Round to 2 decimal places
net_change_billion = round(net_change, 2)

return {"net_change": net_change_billion}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
from policyengine.economic_impact.base_metric_calculator import BaseMetricCalculator
from policyengine_uk import Microsimulation
from policyengine_core.reforms import Reform
from microdf import MicroSeries
import numpy as np

class IncomeLSR(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
super().__init__(baseline, reformed, default_period)
self.baseline = baseline
self.reformed = reformed

def calculate(self):
# Calculate household counts
# household_count_people_baseline = self.baseline.calculate("household_count_people")
# household_count_people_reformed = self.reformed.calculate("household_count_people")

# Calculate baseline and reformed substitution LSR
substitution_lsr_hh_baseline = self._calculate_substitution_lsr(self.baseline)
substitution_lsr_hh_reformed = self._calculate_substitution_lsr(self.reformed)

# Compute the change in substitution LSR
substitution_lsr_hh = np.array(substitution_lsr_hh_reformed) - np.array(substitution_lsr_hh_baseline)

# Calculate baseline and reformed income LSR
income_lsr_hh_baseline = self._calculate_income_lsr(self.baseline)
income_lsr_hh_reformed = self._calculate_income_lsr(self.reformed)

# Compute the change in income LSR
income_lsr_hh = np.array(income_lsr_hh_reformed) - np.array(income_lsr_hh_baseline)

# Calculate weights and earnings
household_weight = self.baseline.calculate("household_weight")
emp_income = MicroSeries(
self.baseline.calculate("employment_income", map_to="household").astype(float).tolist(),
weights=household_weight
)
self_emp_income = MicroSeries(
self.baseline.calculate("self_employment_income", map_to="household").astype(float).tolist(),
weights=household_weight
)
total_lsr_hh = substitution_lsr_hh + income_lsr_hh
earnings = emp_income + self_emp_income
original_earnings = earnings - total_lsr_hh

# Calculate income LSR ratio
income_lsr_hh = MicroSeries(income_lsr_hh, weights=household_weight)
income = income_lsr_hh.sum() / original_earnings.sum() * 100

return {"income": round(income,2)}

def _calculate_substitution_lsr(self, simulation: Microsimulation):
"""Calculate substitution LSR for a given simulation."""
if "employment_income_behavioral_response" in simulation.tax_benefit_system.variables:
if any(simulation.calculate("employment_income_behavioral_response") != 0):
return simulation.calculate("substitution_elasticity_lsr", map_to="household").astype(float).tolist()
return (self.baseline.calculate("household_count_people") * 0).astype(float).tolist()

def _calculate_income_lsr(self, simulation: Microsimulation):
"""Calculate income LSR for a given simulation."""
if "employment_income_behavioral_response" in simulation.tax_benefit_system.variables:
if any(simulation.calculate("employment_income_behavioral_response") != 0):
return simulation.calculate("income_elasticity_lsr", map_to="household").astype(float).tolist()
return (self.baseline.calculate("household_count_people") * 0).astype(float).tolist()


class SubstitutionLSR(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
super().__init__(baseline, reformed, default_period)
self.baseline = baseline
self.reformed = reformed

def calculate(self):
# Calculate household counts
# household_count_people_baseline = self.baseline.calculate("household_count_people")
# household_count_people_reformed = self.reformed.calculate("household_count_people")

# Calculate baseline and reformed income LSR
income_lsr_hh_baseline = self._calculate_income_lsr(self.baseline)
income_lsr_hh_reformed = self._calculate_income_lsr(self.reformed)

# Calculate baseline and reformed substitution LSR
substitution_lsr_hh_baseline = self._calculate_substitution_lsr(self.baseline)
substitution_lsr_hh_reformed = self._calculate_substitution_lsr(self.reformed)

# Compute the change in substitution LSR
substitution_lsr_hh = np.array(substitution_lsr_hh_reformed) - np.array(substitution_lsr_hh_baseline)
household_weight = self.baseline.calculate("household_weight")

# Convert to MicroSeries and compute total LSR
substitution_lsr_hh = MicroSeries(substitution_lsr_hh, weights=household_weight)
income_lsr_hh = np.array(income_lsr_hh_reformed) - np.array(income_lsr_hh_baseline)
total_lsr_hh = substitution_lsr_hh + income_lsr_hh

# Calculate earnings
emp_income = MicroSeries(
self.baseline.calculate("employment_income", map_to="household").astype(float).tolist(),
weights=household_weight
)
self_emp_income = MicroSeries(
self.baseline.calculate("self_employment_income", map_to="household").astype(float).tolist(),
weights=household_weight
)
earnings = emp_income + self_emp_income
original_earnings = earnings - total_lsr_hh

# Calculate substitution ratio
substitution = substitution_lsr_hh.sum() / original_earnings.sum() * 100

return {"substitution": round(substitution,2)}

def _calculate_substitution_lsr(self, simulation: Microsimulation):
"""Calculate substitution LSR for a given simulation."""
if "employment_income_behavioral_response" in simulation.tax_benefit_system.variables:
if any(simulation.calculate("employment_income_behavioral_response") != 0):
return simulation.calculate("substitution_elasticity_lsr", map_to="household").astype(float).tolist()
return (self.baseline.calculate("household_count_people") * 0).astype(float).tolist()

def _calculate_income_lsr(self, simulation: Microsimulation):
"""Calculate income LSR for a given simulation."""
if "employment_income_behavioral_response" in simulation.tax_benefit_system.variables:
if any(simulation.calculate("employment_income_behavioral_response") != 0):
return simulation.calculate("income_elasticity_lsr", map_to="household").astype(float).tolist()
return (self.baseline.calculate("household_count_people") * 0).astype(float).tolist()



class NetLSRChange(BaseMetricCalculator):
def __init__(self, baseline: Microsimulation, reformed: Microsimulation, default_period: int = 2024) -> None:
super().__init__(baseline, reformed, default_period)
self.baseline = baseline
self.reformed = reformed

def calculate(self):
income_result = IncomeLSR(baseline=self.baseline, reformed=self.reformed).calculate()
substitution_result = SubstitutionLSR(baseline=self.baseline, reformed=self.reformed).calculate()

income_value = income_result["income"]
substitution_value = substitution_result["substitution"]

net_change = (income_value + substitution_value)

return {"net_change": round(net_change,2)}

0 comments on commit 06f0d2c

Please sign in to comment.