def FOC_savings(r, w, b, b_splus1, b_splus2, n, BQ, factor, T_H, params): ''' Computes Euler errors for the FOC for savings in the steady state. This function is usually looped through over J, so it does one lifetime income group at a time. Inputs: r = scalar, interest rate w = scalar, wage rate b = [S,J] array, distribution of wealth/capital holdings b_splus1 = [S,J] array, distribution of wealth/capital holdings one period ahead b_splus2 = [S,J] array, distribution of wealth/capital holdings two periods ahead n = [S,J] array, distribution of labor supply BQ = [J,] vector, aggregate bequests by lifetime income group factor = scalar, scaling factor to convert model income to dollars T_H = scalar, lump sum transfer params = length 18 tuple (e, sigma, beta, g_y, chi_b, theta, tau_bq, rho, lambdas, J, S, etr_params, mtry_params, h_wealth, p_wealth, m_wealth, tau_payroll, tau_bq) e = [S,J] array, effective labor units sigma = scalar, coefficient of relative risk aversion beta = scalar, discount factor g_y = scalar, exogenous labor augmenting technological growth chi_b = [J,] vector, utility weight on bequests for each lifetime income group theta = [J,] vector, replacement rate for each lifetime income group tau_bq = scalar, bequest tax rate (scalar) rho = [S,] vector, mortality rates lambdas = [J,] vector, ability weights J = integer, number of lifetime income groups S = integer, number of economically active periods in lifetime etr_params = [S,10] array, parameters of effective income tax rate function mtry_params = [S,10] array, parameters of marginal tax rate on capital income function h_wealth = scalar, parameter in wealth tax function p_wealth = scalar, parameter in wealth tax function m_wealth = scalar, parameter in wealth tax function tau_payroll = scalar, payroll tax rate tau_bq = scalar, bequest tax rate Functions called: get_cons marg_ut_cons tax.total_taxes tax.MTR_capital Objects in function: tax1 = [S,J] array, net taxes in the current period tax2 = [S,J] array, net taxes one period ahead cons1 = [S,J] array, consumption in the current period cons2 = [S,J] array, consumption one period ahead deriv = [S,J] array, after-tax return on capital savings_ut = [S,J] array, marginal utility from savings euler = [S,J] array, Euler error from FOC for savings Returns: euler ''' e, sigma, beta, g_y, chi_b, theta, tau_bq, rho, lambdas, J, S, \ analytical_mtrs, etr_params, mtry_params, h_wealth, p_wealth, m_wealth, tau_payroll, retire, method = params # In order to not have 2 savings euler equations (one that solves the first S-1 equations, and one that solves the last one), # we combine them. In order to do this, we have to compute a consumption term in period t+1, which requires us to have a shifted # e and n matrix. We append a zero on the end of both of these so they will be the right size. We could append any value to them, # since in the euler equation, the coefficient on the marginal utility of # consumption for this term will be zero (since rho is one). if method == 'TPI_scalar': e_extended = np.array([e] + [0]) n_extended = np.array([n] + [0]) etr_params_to_use = etr_params mtry_params_to_use = mtry_params else: e_extended = np.array(list(e) + [0]) n_extended = np.array(list(n) + [0]) etr_params_to_use = np.append(etr_params, np.reshape(etr_params[-1, :], (1, etr_params.shape[1])), axis=0)[1:, :] mtry_params_to_use = np.append(mtry_params, np.reshape(mtry_params[-1, :], (1, mtry_params.shape[1])), axis=0)[1:, :] # tax1_params = (e, lambdas, method, retire, etr_params, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) # tax1 = tax.total_taxes(r, w, b, n, BQ, factor, T_H, None, False, tax1_params) # tax2_params = (e_extended[1:], lambdas, method, retire, # np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:], # h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) # tax2 = tax.total_taxes(r, w, b_splus1, n_extended[1:], BQ, factor, T_H, None, True, tax2_params) # cons1_params = (e, lambdas, g_y) # cons1 = get_cons(r, w, b, b_splus1, n, BQ, tax1, cons1_params) # cons2_params = (e_extended[1:], lambdas, g_y) # cons2 = get_cons(r, w, b_splus1, b_splus2, n_extended[1:], BQ, tax2, cons2_params) # mtr_cap_params = (e_extended[1:], np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:], # np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:],analytical_mtrs) # deriv = (1+r) - r*(tax.MTR_capital(r, w, b_splus1, n_extended[1:], factor, mtr_cap_params)) tax1_params = (e, lambdas, method, retire, etr_params, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax1 = tax.total_taxes(r, w, b, n, BQ, factor, T_H, None, False, tax1_params) tax2_params = (e_extended[1:], lambdas, method, retire, etr_params_to_use, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax2 = tax.total_taxes(r, w, b_splus1, n_extended[1:], BQ, factor, T_H, None, True, tax2_params) cons1_params = (e, lambdas, g_y) cons1 = get_cons(r, w, b, b_splus1, n, BQ, tax1, cons1_params) cons2_params = (e_extended[1:], lambdas, g_y) cons2 = get_cons(r, w, b_splus1, b_splus2, n_extended[1:], BQ, tax2, cons2_params) mtr_cap_params = (e_extended[1:], etr_params_to_use, mtry_params_to_use, analytical_mtrs) deriv = (1 + r) - r * (tax.MTR_capital(r, w, b_splus1, n_extended[1:], factor, mtr_cap_params)) savings_ut = rho * np.exp(-sigma * g_y) * chi_b * b_splus1**(-sigma) # Again, note timing in this equation, the (1-rho) term will zero out in the last period, so the last entry of cons2 can be complete # gibberish (which it is). It just has to exist so cons2 is the right # size to match all other arrays in the equation. euler = marg_ut_cons(cons1, sigma) - beta * (1 - rho) * deriv * marg_ut_cons( cons2, sigma) * np.exp(-sigma * g_y) - savings_ut return euler
def FOC_savings(r, w, b, b_splus1, b_splus2, n, BQ, factor, T_H, params): ''' Computes Euler errors for the FOC for savings in the steady state. This function is usually looped through over J, so it does one lifetime income group at a time. Inputs: r = scalar, interest rate w = scalar, wage rate b = [S,J] array, distribution of wealth/capital b_splus1 = [S,J] array, distribution of wealth/capital, one period ahead b_splus2 = [S,J] array, distribution of wealth/capital, two periods ahead n = [S,J] array, distribution of labor supply BQ = [J,] vector, aggregate bequests by lifetime income group factor = scalar, scaling factor to convert model income to dollars T_H = scalar, lump sum transfer params = length 18 tuple (e, sigma, beta, g_y, chi_b, theta, tau_bq, rho, lambdas, J, S, etr_params, mtry_params, h_wealth, p_wealth, m_wealth, tau_payroll, tau_bq) e = [S,J] array, effective labor units sigma = scalar, coefficient of relative risk aversion beta = scalar, discount factor g_y = scalar, exogenous labor augmenting technological growth chi_b = [J,] vector, utility weight on bequests for each lifetime income group theta = [J,] vector, replacement rate for each lifetime income group tau_bq = scalar, bequest tax rate (scalar) rho = [S,] vector, mortality rates lambdas = [J,] vector, ability weights J = integer, number of lifetime income groups S = integer, number of economically active periods in lifetime etr_params = [S,12] array, parameters of effective income tax rate function mtry_params = [S,12] array, parameters of marginal tax rate on capital income function h_wealth = scalar, parameter in wealth tax function p_wealth = scalar, parameter in wealth tax function m_wealth = scalar, parameter in wealth tax function tau_payroll = scalar, payroll tax rate tau_bq = scalar, bequest tax rate Functions called: get_cons marg_ut_cons tax.total_taxes tax.MTR_capital Objects in function: tax1 = [S,J] array, net taxes in the current period tax2 = [S,J] array, net taxes one period ahead cons1 = [S,J] array, consumption in the current period cons2 = [S,J] array, consumption one period ahead deriv = [S,J] array, after-tax return on capital savings_ut = [S,J] array, marginal utility from savings euler = [S,J] array, Euler error from FOC for savings Returns: euler ''' (e, sigma, beta, g_y, chi_b, theta, tau_bq, rho, lambdas, j, J, S, analytical_mtrs, etr_params, mtry_params, h_wealth, p_wealth, m_wealth, tau_payroll, retire, method) = params # In order to not have 2 savings euler equations (one that solves # the first S-1 equations, and one that solves the last one), we # combine them. In order to do this, we have to compute a # consumption term in period t+1, which requires us to have a shifted # e and n matrix. We append a zero on the end of both of these so # they will be the right size. We could append any value to them, # since in the euler equation, the coefficient on the marginal # utility of consumption for this term will be zero (since rho is # one). e_extended = np.array(list(e) + [0]) n_extended = np.array(list(n) + [0]) etr_params_extended = np.append(etr_params, np.reshape(etr_params[-1, :], (1, etr_params.shape[1])), axis=0)[1:, :] mtry_params_extended = np.append(mtry_params, np.reshape(mtry_params[-1, :], (1, mtry_params.shape[1])), axis=0)[1:, :] if method == 'TPI': r_extended = np.append(r, r[-1]) w_extended = np.append(w, w[-1]) BQ_extended = np.append(BQ, BQ[-1]) T_H_extended = np.append(T_H, T_H[-1]) elif method == 'SS': r_extended = np.array([r, r]) w_extended = np.array([w, w]) BQ_extended = np.array([BQ, BQ]) T_H_extended = np.array([T_H, T_H]) tax1_params = (e, lambdas, method, retire, etr_params, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax1 = tax.total_taxes(r, w, b, n, BQ, factor, T_H, j, False, tax1_params) tax2_params = (e_extended[1:], lambdas, method, retire, etr_params_extended, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax2 = tax.total_taxes(r_extended[1:], w_extended[1:], b_splus1, n_extended[1:], BQ_extended[1:], factor, T_H_extended[1:], j, True, tax2_params) cons1_params = (e, lambdas, g_y) cons1 = get_cons(r, w, b, b_splus1, n, BQ, tax1, cons1_params) cons2_params = (e_extended[1:], lambdas, g_y) cons2 = get_cons(r_extended[1:], w_extended[1:], b_splus1, b_splus2, n_extended[1:], BQ_extended[1:], tax2, cons2_params) cons2[-1] = 0.01 # set to small positive number to avoid exception # errors when negative b/c this period value doesn't matter - # it's consumption after the last period of life mtr_cap_params = (e_extended[1:], etr_params_extended, mtry_params_extended, analytical_mtrs) deriv = ((1 + r_extended[1:]) - r_extended[1:] * (tax.MTR_capital(r_extended[1:], w_extended[1:], b_splus1, n_extended[1:], factor, mtr_cap_params)) - (tax.tau_w_prime(b_splus1, (h_wealth, p_wealth, m_wealth)) * b_splus1) - tax.tau_wealth(b_splus1, (h_wealth, p_wealth, m_wealth))) savings_ut = (rho * np.exp(-sigma * g_y) * chi_b * b_splus1 ** (-sigma)) euler_error = (marg_ut_cons(cons1, sigma) - beta * (1 - rho) * deriv * marg_ut_cons(cons2, sigma) * np.exp(-sigma * g_y) - savings_ut) return euler_error
def twist_doughnut(guesses, r, w, BQ, T_H, j, s, t, params): ''' Parameters: guesses = distribution of capital and labor (various length list) w = wage rate ((T+S)x1 array) r = rental rate ((T+S)x1 array) BQ = aggregate bequests ((T+S)x1 array) T_H = lump sum tax over time ((T+S)x1 array) factor = scaling factor (scalar) j = which ability type is being solved for (scalar) s = which upper triangle loop is being solved for (scalar) t = which diagonal is being solved for (scalar) params = list of parameters (list) theta = replacement rates (Jx1 array) tau_bq = bequest tax rate (Jx1 array) rho = mortalit rate (Sx1 array) lambdas = ability weights (Jx1 array) e = ability type (SxJ array) initial_b = capital stock distribution in period 0 (SxJ array) chi_b = chi^b_j (Jx1 array) chi_n = chi^n_s (Sx1 array) Output: Value of Euler error (various length list) ''' income_tax_params, tpi_params, initial_b = params analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\ factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params length = len(guesses) / 2 b_guess = np.array(guesses[:length]) n_guess = np.array(guesses[length:]) if length == S: b_s = np.array([0] + list(b_guess[:-1])) else: b_s = np.array([(initial_b[-(s + 3), j])] + list(b_guess[:-1])) b_splus1 = b_guess b_splus2 = np.array(list(b_guess[1:]) + [0]) w_s = w[t:t + length] w_splus1 = w[t + 1:t + length + 1] r_s = r[t:t + length] r_splus1 = r[t + 1:t + length + 1] n_s = n_guess n_extended = np.array(list(n_guess[1:]) + [0]) e_s = e[-length:, j] e_extended = np.array(list(e[-length + 1:, j]) + [0]) BQ_s = BQ[t:t + length] BQ_splus1 = BQ[t + 1:t + length + 1] T_H_s = T_H[t:t + length] T_H_splus1 = T_H[t + 1:t + length + 1] # Savings euler equations # theta_params = (e[-1, j], 1, omega[0].reshape(S, 1), lambdas[j]) # theta = tax.replacement_rate_vals(n, w, factor, theta_params) theta = np.zeros((J, )) tax_s_params = (e_s, lambdas[j], 'TPI', retire, etr_params, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax_s = tax.total_taxes(r_s, w_s, b_s, n_s, BQ_s, factor, T_H_s, j, False, tax_s_params) etr_params_sp1 = np.append(etr_params, np.reshape(etr_params[-1, :], (1, etr_params.shape[1])), axis=0)[1:, :] taxsp1_params = (e_extended, lambdas[j], 'TPI', retire, etr_params_sp1, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax_splus1 = tax.total_taxes(r_splus1, w_splus1, b_splus1, n_extended, BQ_splus1, factor, T_H_splus1, j, True, taxsp1_params) cons_s_params = (e_s, lambdas[j], g_y) cons_s = household.get_cons(r_s, w_s, b_s, b_splus1, n_s, BQ_s, tax_s, cons_s_params) cons_sp1_params = (e_extended, lambdas[j], g_y) cons_splus1 = household.get_cons(r_splus1, w_splus1, b_splus1, b_splus2, n_extended, BQ_splus1, tax_splus1, cons_sp1_params) income_splus1 = (r_splus1 * b_splus1 + w_splus1 * e_extended * n_extended) * factor savings_ut = rho[-(length):] * np.exp(-sigma * g_y) * \ chi_b[j] * b_splus1 ** (-sigma) mtry_params_sp1 = np.append(mtry_params, np.reshape(mtry_params[-1, :], (1, mtry_params.shape[1])), axis=0)[1:, :] mtr_capital_params = (e_extended, etr_params_sp1, mtry_params_sp1, analytical_mtrs) deriv_savings = 1 + r_splus1 * (1 - tax.MTR_capital( r_splus1, w_splus1, b_splus1, n_extended, factor, mtr_capital_params)) error1 = household.marg_ut_cons( cons_s, sigma) - beta * (1 - rho[-(length):]) * np.exp( -sigma * g_y) * deriv_savings * household.marg_ut_cons( cons_splus1, sigma) - savings_ut # Labor leisure euler equations income_s = (r_s * b_s + w_s * e_s * n_s) * factor mtr_labor_params = (e_s, etr_params, mtrx_params, analytical_mtrs) deriv_laborleisure = 1 - tau_payroll - tax.MTR_labor( r_s, w_s, b_s, n_s, factor, mtr_labor_params) mu_labor_params = (b_ellipse, upsilon, ltilde, chi_n[-length:]) error2 = household.marg_ut_cons(cons_s, sigma) * w_s * e[ -(length):, j] * deriv_laborleisure - household.marg_ut_labor( n_s, mu_labor_params) # Check and punish constraint violations mask1 = n_guess < 0 error2[mask1] += 1e12 mask2 = n_guess > ltilde error2[mask2] += 1e12 mask3 = cons_s < 0 error2[mask3] += 1e12 mask4 = b_guess <= 0 error2[mask4] += 1e12 mask5 = cons_splus1 < 0 error2[mask5] += 1e12 return list(error1.flatten()) + list(error2.flatten())
def euler_savings_func(w, r, e, n_guess, b_s, b_splus1, b_splus2, BQ, factor, T_H, chi_b, tax_params, params, theta, tau_bq, rho, lambdas): ''' This function is usually looped through over J, so it does one ability group at a time. Inputs: w = wage rate (scalar) r = rental rate (scalar) e = ability levels (Sx1 array) n_guess = labor distribution (Sx1 array) b_s = wealth holdings at the start of a period (Sx1 array) b_splus1 = wealth holdings for the next period (Sx1 array) b_splus2 = wealth holdings for 2 periods ahead (Sx1 array) BQ = aggregate bequests for a certain ability (scalar) factor = scaling factor to convert to dollars (scalar) T_H = lump sum tax (scalar) chi_b = chi^b_j for a certain ability (scalar) params = parameter list (list) theta = replacement rate for a certain ability (scalar) tau_bq = bequest tax rate (scalar) rho = mortality rate (Sx1 array) lambdas = ability weight (scalar) Output: euler = Value of savings euler error (Sx1 array) ''' J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_params # In order to not have 2 savings euler equations (one that solves the first S-1 equations, and one that solves the last one), # we combine them. In order to do this, we have to compute a consumption term in period t+1, which requires us to have a shifted # e and n matrix. We append a zero on the end of both of these so they will be the right size. We could append any value to them, # since in the euler equation, the coefficient on the marginal utility of # consumption for this term will be zero (since rho is one). e_extended = np.array(list(e) + [0]) n_extended = np.array(list(n_guess) + [0]) tax1_params = (J, S, retire, etr_params, h_wealth, p_wealth, m_wealth, tau_payroll) tax1 = tax.total_taxes(r, b_s, w, e, n_guess, BQ, lambdas, factor, T_H, None, 'SS', False, tax1_params, theta, tau_bq) etr_params_extended = np.append(etr_params, np.reshape(etr_params[-1, :], (1, etr_params.shape[1])), axis=0)[1:, :] tax2_params = (J, S, retire, etr_params_extended, h_wealth, p_wealth, m_wealth, tau_payroll) tax2 = tax.total_taxes(r, b_splus1, w, e_extended[1:], n_extended[1:], BQ, lambdas, factor, T_H, None, 'SS', True, tax2_params, theta, tau_bq) cons1 = get_cons(r, b_s, w, e, n_guess, BQ, lambdas, b_splus1, params, tax1) cons2 = get_cons(r, b_splus1, w, e_extended[1:], n_extended[1:], BQ, lambdas, b_splus2, params, tax2) income = (r * b_splus1 + w * e_extended[1:] * n_extended[1:]) * factor mtr_cap_params = np.append(mtry_params, np.reshape(mtry_params[-1, :], (1, mtry_params.shape[1])), axis=0)[1:, :] deriv = (1 + r) - r * (tax.MTR_capital( r, b_splus1, w, e_extended[1:], n_extended[1:], factor, analytical_mtrs, etr_params_extended, mtr_cap_params)) savings_ut = rho * np.exp(-sigma * g_y) * chi_b * b_splus1**(-sigma) # Again, note timing in this equation, the (1-rho) term will zero out in the last period, so the last entry of cons2 can be complete # gibberish (which it is). It just has to exist so cons2 is the right # size to match all other arrays in the equation. euler = marg_ut_cons(cons1, params) - beta * (1 - rho) * deriv * marg_ut_cons( cons2, params) * np.exp(-sigma * g_y) - savings_ut return euler