diff --git a/iot/inverse_optimal_tax.py b/iot/inverse_optimal_tax.py index abe353e..c262d05 100644 --- a/iot/inverse_optimal_tax.py +++ b/iot/inverse_optimal_tax.py @@ -383,7 +383,9 @@ def sw_weights(self): + ((self.theta_z * self.eti * self.mtr) / (1 - self.mtr)) + ((self.eti * self.z * self.mtr_prime) / (1 - self.mtr) ** 2) ) - integral = np.trapz(g_z * self.f, self.z) # renormalize to integrate to 1 + integral = np.trapz( + g_z * self.f, self.z + ) # renormalize to integrate to 1 g_z = g_z / integral # use Lockwood and Weinzierl formula, which should be equivalent but using numerical differentiation @@ -402,7 +404,7 @@ def sw_weights(self): return g_z, g_z_numerical -def find_eti(iot, g_z = None, eti_0 = 0.25): +def find_eti(iot, g_z=None, eti_0=0.25): """ This function solves for the ETI that would result in the policy represented via MTRs in IOT being consistent with the @@ -420,12 +422,16 @@ def find_eti(iot, g_z = None, eti_0 = 0.25): Returns: eti_beliefs (array-like): vector of ETI beliefs over z """ - + if g_z is None: g_z = iot.g_z - + # we solve an ODE of the form f'(z) + P(z)f(z) = Q(z) - P_z = 1/iot.z + iot.f_prime/iot.f + iot.mtr_prime/(iot.mtr * (1-iot.mtr)) + P_z = ( + 1 / iot.z + + iot.f_prime / iot.f + + iot.mtr_prime / (iot.mtr * (1 - iot.mtr)) + ) # integrating factor for ODE: mu(z) * f'(z) + mu(z) * P(z) * f(z) = mu(z) * Q(z) mu_z = np.exp(np.cumsum(P_z)) Q_z = (g_z - 1) * (1 - iot.mtr) / (iot.mtr * iot.z) diff --git a/iot/iot_user.py b/iot/iot_user.py index 265f4cc..e392d58 100644 --- a/iot/iot_user.py +++ b/iot/iot_user.py @@ -226,14 +226,12 @@ def JJZFig4(self, policy="Current Law", var="g_z", upper_bound=500_000): g_weights = df.g_z_numerical # g1 with mtr_prime = 0 - g1 = ( - ((df.theta_z * self.iot[k].eti * df.mtr) / (1 - df.mtr)) - + ((self.iot[k].eti * df.z * 0) / (1 - df.mtr) ** 2) + g1 = ((df.theta_z * self.iot[k].eti * df.mtr) / (1 - df.mtr)) + ( + (self.iot[k].eti * df.z * 0) / (1 - df.mtr) ** 2 ) # g2 with theta_z = 0 - g2 = ( - ((0 * self.iot[k].eti * df.mtr) / (1 - df.mtr)) - + ((self.iot[k].eti * df.z * df.mtr_prime) / (1 - df.mtr) ** 2) + g2 = ((0 * self.iot[k].eti * df.mtr) / (1 - df.mtr)) + ( + (self.iot[k].eti * df.z * df.mtr_prime) / (1 - df.mtr) ** 2 ) integral = np.trapz(g1, df.z) # g1 = g1 / integral @@ -244,7 +242,10 @@ def JJZFig4(self, policy="Current Law", var="g_z", upper_bound=500_000): self.income_measure: df.z, "Overall Weight": g_weights, "Tax Base Elasticity": 1 + g1, - "Nonconstant MTRs": 1 + g1 + g2 + np.abs(g1) * (np.sign(g1) != np.sign(g2)) + "Nonconstant MTRs": 1 + + g1 + + g2 + + np.abs(g1) * (np.sign(g1) != np.sign(g2)), } )