def euler_labor_leisure_func(w, r, e, n_guess, b_s, b_splus1, BQ, factor, T_H, chi_n, params, theta, tau_bq, 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) BQ = aggregate bequests for a certain ability (scalar) factor = scaling factor to convert to dollars (scalar) T_H = lump sum tax (scalar) chi_n = chi^n_s (Sx1 array) params = parameter list (list) theta = replacement rate for a certain ability (scalar) tau_bq = bequest tax rate (scalar) lambdas = ability weight (scalar) Output: euler = Value of labor leisure euler error (Sx1 array) """ J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, a_tax_income, b_tax_income, c_tax_income, d_tax_income, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ( params ) tax1 = tax.total_taxes(r, b_s, w, e, n_guess, BQ, lambdas, factor, T_H, None, "SS", False, params, theta, tau_bq) cons = get_cons(r, b_s, w, e, n_guess, BQ, lambdas, b_splus1, params, tax1) income = (r * b_s + w * e * n_guess) * factor deriv = ( 1 - tau_payroll - tax.tau_income(r, b_s, w, e, n_guess, factor, params) - tax.tau_income_deriv(r, b_s, w, e, n_guess, factor, params) * income ) euler = marg_ut_cons(cons, params) * w * deriv * e - marg_ut_labor(n_guess, chi_n, params) return euler
def euler_labor_leisure_func(w, r, e, n_guess, b_s, b_splus1, BQ, factor, T_H, chi_n, params, theta, tau_bq, 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) BQ = aggregate bequests for a certain ability (scalar) factor = scaling factor to convert to dollars (scalar) T_H = lump sum tax (scalar) chi_n = chi^n_s (Sx1 array) params = parameter list (list) theta = replacement rate for a certain ability (scalar) tau_bq = bequest tax rate (scalar) lambdas = ability weight (scalar) Output: euler = Value of labor leisure euler error (Sx1 array) ''' J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \ a_tax_income, b_tax_income, c_tax_income, d_tax_income, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params tax1 = tax.total_taxes(r, b_s, w, e, n_guess, BQ, lambdas, factor, T_H, None, 'SS', False, params, theta, tau_bq) cons = get_cons(r, b_s, w, e, n_guess, BQ, lambdas, b_splus1, params, tax1) income = (r * b_s + w * e * n_guess) * factor deriv = 1 - tau_payroll - tax.tau_income( r, b_s, w, e, n_guess, factor, params) - tax.tau_income_deriv( r, b_s, w, e, n_guess, factor, params) * income euler = marg_ut_cons(cons, params) * w * deriv * e - \ marg_ut_labor(n_guess, chi_n, params) return euler
def euler_savings_func(w, r, e, n_guess, b_s, b_splus1, b_splus2, BQ, factor, T_H, chi_b, 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, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \ a_tax_income, b_tax_income, c_tax_income, d_tax_income, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = 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 = tax.total_taxes(r, b_s, w, e, n_guess, BQ, lambdas, factor, T_H, None, 'SS', False, params, theta, tau_bq) tax2 = tax.total_taxes(r, b_splus1, w, e_extended[1:], n_extended[1:], BQ, lambdas, factor, T_H, None, 'SS', True, 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 deriv = (1 + r * (1 - tax.tau_income(r, b_splus1, w, e_extended[1:], n_extended[1:], factor, params) - tax.tau_income_deriv(r, b_splus1, w, e_extended[1:], n_extended[1:], factor, params) * income) - tax.tau_w_prime(b_splus1, params) * b_splus1 - tax.tau_wealth(b_splus1, params)) savings_ut = rho * np.exp(-sigma * g_y) * chi_b * b_splus1**(-sigma) # Again, not who 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
def SS_TPI_firstdoughnutring(guesses, winit, rinit, BQinit, T_H_init, initial_b, factor_ss, j, parameters, theta, tau_bq): ''' Solves the first entries of the upper triangle of the twist doughnut. This is separate from the main TPI function because the the values of b and n are scalars, so it is easier to just have a separate function for these cases. Inputs: guesses = guess for b and n (2x1 list) winit = initial wage rate (scalar) rinit = initial rental rate (scalar) BQinit = initial aggregate bequest (scalar) T_H_init = initial lump sum tax (scalar) initial_b = initial distribution of capital (SxJ array) factor_ss = steady state scaling factor (scalar) j = which ability type is being solved for (scalar) parameters = list of parameters (list) theta = replacement rates (Jx1 array) tau_bq = bequest tax rates (Jx1 array) Output: euler errors (2x1 list) ''' b2 = float(guesses[0]) n1 = float(guesses[1]) b1 = float(initial_b[-2, j]) # Euler 1 equations tax1 = tax.total_taxes(rinit, b1, winit, e[-1, j], n1, BQinit, lambdas[j], factor_ss, T_H_init, j, 'TPI_scalar', False, parameters, theta, tau_bq) cons1 = household.get_cons(rinit, b1, winit, e[-1, j], n1, BQinit, lambdas[j], b2, parameters, tax1) bequest_ut = rho[-1] * np.exp(-sigma * g_y) * chi_b[-1, j] * b2**(-sigma) error1 = household.marg_ut_cons(cons1, parameters) - bequest_ut # Euler 2 equations income2 = (rinit * b1 + winit * e[-1, j] * n1) * factor_ss deriv2 = 1 - tau_payroll - tax.tau_income( rinit, b1, winit, e[-1, j], n1, factor_ss, parameters) - tax.tau_income_deriv( rinit, b1, winit, e[-1, j], n1, factor_ss, parameters) * income2 error2 = household.marg_ut_cons(cons1, parameters) * winit * \ e[-1, j] * deriv2 - household.marg_ut_labor(n1, chi_n[-1], parameters) if n1 <= 0 or n1 >= 1: error2 += 1e12 if b2 <= 0: error1 += 1e12 if cons1 <= 0: error1 += 1e12 return [error1] + [error2]
def euler_savings_func(w, r, e, n_guess, b_s, b_splus1, b_splus2, BQ, factor, T_H, chi_b, 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, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \ a_tax_income, b_tax_income, c_tax_income, d_tax_income, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = 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 = tax.total_taxes(r, b_s, w, e, n_guess, BQ, lambdas, factor, T_H, None, 'SS', False, params, theta, tau_bq) tax2 = tax.total_taxes(r, b_splus1, w, e_extended[1:], n_extended[1:], BQ, lambdas, factor, T_H, None, 'SS', True, 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 deriv = ( 1 + r*(1-tax.tau_income(r, b_splus1, w, e_extended[1:], n_extended[1:], factor, params)-tax.tau_income_deriv( r, b_splus1, w, e_extended[1:], n_extended[1:], factor, params)*income)-tax.tau_w_prime(b_splus1, params)*b_splus1-tax.tau_wealth(b_splus1, params)) savings_ut = rho * np.exp(-sigma * g_y) * chi_b * b_splus1 ** (-sigma) # Again, not who 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
def SS_TPI_firstdoughnutring(guesses, winit, rinit, BQinit, T_H_init, initial_b, factor_ss, j, parameters, theta, tau_bq): ''' Solves the first entries of the upper triangle of the twist doughnut. This is separate from the main TPI function because the the values of b and n are scalars, so it is easier to just have a separate function for these cases. Inputs: guesses = guess for b and n (2x1 list) winit = initial wage rate (scalar) rinit = initial rental rate (scalar) BQinit = initial aggregate bequest (scalar) T_H_init = initial lump sum tax (scalar) initial_b = initial distribution of capital (SxJ array) factor_ss = steady state scaling factor (scalar) j = which ability type is being solved for (scalar) parameters = list of parameters (list) theta = replacement rates (Jx1 array) tau_bq = bequest tax rates (Jx1 array) Output: euler errors (2x1 list) ''' b2 = float(guesses[0]) n1 = float(guesses[1]) b1 = float(initial_b[-2, j]) # Euler 1 equations tax1 = tax.total_taxes(rinit, b1, winit, e[-1, j], n1, BQinit, lambdas[ j], factor_ss, T_H_init, j, 'TPI_scalar', False, parameters, theta, tau_bq) cons1 = household.get_cons( rinit, b1, winit, e[-1, j], n1, BQinit, lambdas[j], b2, parameters, tax1) bequest_ut = rho[-1] * np.exp(-sigma * g_y) * chi_b[-1, j] * b2 ** (-sigma) error1 = household.marg_ut_cons(cons1, parameters) - bequest_ut # Euler 2 equations income2 = (rinit * b1 + winit * e[-1, j] * n1) * factor_ss deriv2 = 1 - tau_payroll - tax.tau_income(rinit, b1, winit, e[ -1, j], n1, factor_ss, parameters) - tax.tau_income_deriv( rinit, b1, winit, e[-1, j], n1, factor_ss, parameters) * income2 error2 = household.marg_ut_cons(cons1, parameters) * winit * \ e[-1, j] * deriv2 - household.marg_ut_labor(n1, chi_n[-1], parameters) if n1 <= 0 or n1 >= 1: error2 += 1e12 if b2 <= 0: error1 += 1e12 if cons1 <= 0: error1 += 1e12 return [error1] + [error2]
def Steady_state_TPI_solver(guesses, winit, rinit, BQinit, T_H_init, factor, j, s, t, params, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n): ''' Parameters: guesses = distribution of capital and labor (various length list) winit = wage rate ((T+S)x1 array) rinit = rental rate ((T+S)x1 array) BQinit = aggregate bequests ((T+S)x1 array) T_H_init = 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) ''' J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \ a_tax_income, b_tax_income, c_tax_income, d_tax_income, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = 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 = winit[t:t + length] w_splus1 = winit[t + 1:t + length + 1] r_s = rinit[t:t + length] r_splus1 = rinit[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 = BQinit[t:t + length] BQ_splus1 = BQinit[t + 1:t + length + 1] T_H_s = T_H_init[t:t + length] T_H_splus1 = T_H_init[t + 1:t + length + 1] # Savings euler equations tax_s = tax.total_taxes(r_s, b_s, w_s, e_s, n_s, BQ_s, lambdas[j], factor, T_H_s, j, 'TPI', False, params, theta, tau_bq) tax_splus1 = tax.total_taxes(r_splus1, b_splus1, w_splus1, e_extended, n_extended, BQ_splus1, lambdas[j], factor, T_H_splus1, j, 'TPI', True, params, theta, tau_bq) cons_s = household.get_cons(r_s, b_s, w_s, e_s, n_s, BQ_s, lambdas[j], b_splus1, params, tax_s) cons_splus1 = household.get_cons(r_splus1, b_splus1, w_splus1, e_extended, n_extended, BQ_splus1, lambdas[j], b_splus2, params, tax_splus1) income_splus1 = (r_splus1 * b_splus1 + w_splus1 * e_extended * n_extended) * factor savings_ut = rho[-(length):] * np.exp(-sigma * g_y) * \ chi_b[-(length):, j] * b_splus1 ** (-sigma) deriv_savings = 1 + r_splus1 * ( 1 - tax.tau_income(r_splus1, b_splus1, w_splus1, e_extended, n_extended, factor, params) - tax.tau_income_deriv(r_splus1, b_splus1, w_splus1, e_extended, n_extended, factor, params) * income_splus1 ) - tax.tau_w_prime(b_splus1, params) * b_splus1 - tax.tau_wealth( b_splus1, params) error1 = household.marg_ut_cons( cons_s, params) - beta * (1 - rho[-(length):]) * np.exp( -sigma * g_y) * deriv_savings * household.marg_ut_cons( cons_splus1, params) - savings_ut # Labor leisure euler equations income_s = (r_s * b_s + w_s * e_s * n_s) * factor deriv_laborleisure = 1 - tau_payroll - tax.tau_income( r_s, b_s, w_s, e_s, n_s, factor, params) - tax.tau_income_deriv( r_s, b_s, w_s, e_s, n_s, factor, params) * income_s error2 = household.marg_ut_cons(cons_s, params) * w_s * e[ -(length):, j] * deriv_laborleisure - household.marg_ut_labor( n_s, chi_n[-length:], 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 Steady_state_TPI_solver(guesses, winit, rinit, BQinit, T_H_init, factor, j, s, t, params, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n): ''' Parameters: guesses = distribution of capital and labor (various length list) winit = wage rate ((T+S)x1 array) rinit = rental rate ((T+S)x1 array) BQinit = aggregate bequests ((T+S)x1 array) T_H_init = 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) ''' J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \ a_tax_income, b_tax_income, c_tax_income, d_tax_income, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = 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 = winit[t:t + length] w_splus1 = winit[t + 1:t + length + 1] r_s = rinit[t:t + length] r_splus1 = rinit[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 = BQinit[t:t + length] BQ_splus1 = BQinit[t + 1:t + length + 1] T_H_s = T_H_init[t:t + length] T_H_splus1 = T_H_init[t + 1:t + length + 1] # Savings euler equations tax_s = tax.total_taxes(r_s, b_s, w_s, e_s, n_s, BQ_s, lambdas[ j], factor, T_H_s, j, 'TPI', False, params, theta, tau_bq) tax_splus1 = tax.total_taxes(r_splus1, b_splus1, w_splus1, e_extended, n_extended, BQ_splus1, lambdas[ j], factor, T_H_splus1, j, 'TPI', True, params, theta, tau_bq) cons_s = household.get_cons(r_s, b_s, w_s, e_s, n_s, BQ_s, lambdas[ j], b_splus1, params, tax_s) cons_splus1 = household.get_cons(r_splus1, b_splus1, w_splus1, e_extended, n_extended, BQ_splus1, lambdas[ j], b_splus2, params, tax_splus1) income_splus1 = (r_splus1 * b_splus1 + w_splus1 * e_extended * n_extended) * factor savings_ut = rho[-(length):] * np.exp(-sigma * g_y) * \ chi_b[-(length):, j] * b_splus1 ** (-sigma) deriv_savings = 1 + r_splus1 * (1 - tax.tau_income( r_splus1, b_splus1, w_splus1, e_extended, n_extended, factor, params) - tax.tau_income_deriv( r_splus1, b_splus1, w_splus1, e_extended, n_extended, factor, params) * income_splus1) - tax.tau_w_prime( b_splus1, params) * b_splus1 - tax.tau_wealth(b_splus1, params) error1 = household.marg_ut_cons(cons_s, params) - beta * (1 - rho[-(length):]) * np.exp(-sigma * g_y) * deriv_savings * household.marg_ut_cons( cons_splus1, params) - savings_ut # Labor leisure euler equations income_s = (r_s * b_s + w_s * e_s * n_s) * factor deriv_laborleisure = 1 - tau_payroll - tax.tau_income(r_s, b_s, w_s, e_s, n_s, factor, params) - tax.tau_income_deriv( r_s, b_s, w_s, e_s, n_s, factor, params) * income_s error2 = household.marg_ut_cons(cons_s, params) * w_s * e[-( length):, j] * deriv_laborleisure - household.marg_ut_labor(n_s, chi_n[-length:], 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 run_TPI(income_tax_params, tpi_params, iterative_params, initial_values, SS_values, fix_transfers=False, output_dir="./OUTPUT"): # unpack tuples of parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params maxiter, mindist_SS, mindist_TPI = iterative_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, imm_rates, e, retire, mean_income_data,\ factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP = initial_values Kss, Lss, rss, wss, BQss, T_Hss, Gss, bssmat_splus1, nssmat = SS_values TPI_FIG_DIR = output_dir # Initialize guesses at time paths domain = np.linspace(0, T, T) r = np.ones(T + S) * rss BQ = np.zeros((T + S, J)) BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') BQ0 = household.get_BQ(r[0], initial_b, BQ0_params) for j in xrange(J): BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQ = np.array(BQ) # print "BQ values = ", BQ[0, :], BQ[100, :], BQ[-1, :], BQss # print "K0 vs Kss = ", K0-Kss if fix_transfers: T_H = T_H_baseline else: if np.abs(T_Hss) < 1e-13: T_Hss2 = 0.0 # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below else: T_Hss2 = T_Hss T_H = np.ones(T + S) * T_Hss2 * (r / rss) G = np.ones(T + S) * Gss # # print "T_H values = ", T_H[0], T_H[100], T_H[-1], T_Hss # # print "omega diffs = ", (omega_S_preTP-omega[-1]).max(), (omega[10]-omega[-1]).max() # # Make array of initial guesses for labor supply and savings domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) # print 'diff btwn start and end b: ', (guesses_b[0]-guesses_b[-1]).max() # domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) # b_mat = np.zeros((T + S, S, J)) # n_mat = np.zeros((T + S, S, J)) ind = np.arange(S) # # print 'diff btwn start and end n: ', (guesses_n[0]-guesses_n[-1]).max() # # # find economic aggregates K = np.zeros(T + S) L = np.zeros(T + S) K[0] = K0 K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(guesses_b[:T - 1], K_params) K[T:] = Kss L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(guesses_n[:T], L_params) L[T:] = Lss Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) r[:T] = firm.get_r(Y[:T], K[:T], r_params) # uncomment lines below if want to use starting values from prior run r = TPI_START_VALUES['r'] K = TPI_START_VALUES['K'] L = TPI_START_VALUES['L'] Y = TPI_START_VALUES['Y'] T_H = TPI_START_VALUES['T_H'] BQ = TPI_START_VALUES['BQ'] G = TPI_START_VALUES['G'] guesses_b = TPI_START_VALUES['b_mat'] guesses_n = TPI_START_VALUES['n_mat'] TPIiter = 0 TPIdist = 10 PLOT_TPI = False euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) # print 'analytical mtrs in tpi = ', analytical_mtrs while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: K_plot = list(K) + list(np.ones(10) * Kss) L_plot = list(L) + list(np.ones(10) * Lss) plt.figure() plt.axhline(y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange(T + 10), Kpath_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) guesses = (guesses_b, guesses_n) w_params = (Z, alpha, delta) w = firm.get_w_from_r(r, w_params) # print 'r and rss diff = ', r-rss # print 'w and wss diff = ', w-wss # print 'BQ and BQss diff = ', BQ-BQss # print 'T_H and T_Hss diff = ', T_H - T_Hss # print 'guess b and bss = ', (bssmat_splus1 - guesses_b).max() # print 'guess n and nss = ', (nssmat - guesses_n).max() outer_loop_vars = (r, w, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, ind) # Solve HH problem in inner loop euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) # print 'guess b and bss = ', (b_mat - guesses_b).max() # print 'guess n and nss over time = ', (n_mat - guesses_n).max(axis=2).max(axis=1) # print 'guess n and nss over age = ', (n_mat - guesses_n).max(axis=0).max(axis=1) # print 'guess n and nss over ability = ', (n_mat - guesses_n).max(axis=0).max(axis=0) # quit() print 'Max Euler error: ', (np.abs(euler_errors)).max() bmat_s = np.zeros((T, S, J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:T - 1, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[:T, :, :] K[0] = K0 K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(bmat_splus1[:T - 1], K_params) L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(n_mat[:T], L_params) # print 'K diffs = ', K-K0 # print 'L diffs = ', L-L[0] Y_params = (alpha, Z) Ynew = firm.get_Y(K[:T], L[:T], Y_params) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) wnew = firm.get_w_from_r(rnew, w_params) omega_shift = np.append(omega_S_preTP.reshape(1, S), omega[:T - 1, :], axis=0) BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') # b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)), # b_mat[:T-1, :, :], axis=0) b_mat_shift = bmat_splus1[:T, :, :] # print 'b diffs = ', (bmat_splus1[100, :, :] - initial_b).max(), (bmat_splus1[0, :, :] - initial_b).max(), (bmat_splus1[1, :, :] - initial_b).max() # print 'r diffs = ', rnew[1]-r[1], rnew[100]-r[100], rnew[-1]-r[-1] BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params) BQss2 = np.empty(J) for j in range(J): BQss_params = (omega[1, :], lambdas[j], rho, g_n_vector[1], 'SS') BQss2[j] = household.get_BQ(rnew[1], bmat_splus1[1, :, j], BQss_params) # print 'BQ test = ', BQss2-BQss, BQss-BQnew[1], BQss-BQnew[100], BQss-BQnew[-1] total_tax_params = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): total_tax_params[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) tax_receipt_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = np.array( list( tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), ( 1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), ( 1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape( T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S) r[:T] = utils.convex_combo(rnew[:T], r[:T], nu) BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu) if fix_transfers: T_H_new = T_H G[:T] = net_tax_receipts[:T] - T_H[:T] else: T_H_new = net_tax_receipts T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu) G[:T] = 0.0 etr_params_path = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_path[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas, 'TPI', retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) b_to_use = np.zeros((T, S, J)) b_to_use[0, 1:, :] = initial_b[:-1, :] b_to_use[1:, 1:, :] = b_mat[:T - 1, :-1, :] tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)), b_to_use, n_mat[:T, :, :], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * b_to_use[:T, :, :] + np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) * np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :]) cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), b_to_use[:T, :, :], b_mat[:T, :, :], n_mat[:T, :, :], BQ[:T].reshape(T, 1, J), tax_path, cons_params) guesses_b = utils.convex_combo(b_mat, guesses_b, nu) guesses_n = utils.convex_combo(n_mat, guesses_n, nu) if T_H.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() print 'r dist = ', np.array( list(utils.pct_diff_func(rnew[:T], r[:T]))).max() print 'BQ dist = ', np.array( list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten())).max() print 'T_H dist = ', np.array( list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() print 'T_H path = ', T_H[:20] # print 'r old = ', r[:T] # print 'r new = ', rnew[:T] # print 'K old = ', K[:T] # print 'L old = ', L[:T] # print 'income = ', y_path[:, :, -1] # print 'taxes = ', tax_path[:, :, -1] # print 'labor supply = ', n_mat[:, :, -1] # print 'max and min labor = ', n_mat.max(), n_mat.min() # print 'max and min labor = ', np.argmax(n_mat), np.argmin(n_mat) # print 'max and min labor, j = 7 = ', n_mat[:,:,-1].max(), n_mat[:,:,-1].min() # print 'max and min labor, j = 6 = ', n_mat[:,:,-2].max(), n_mat[:,:,-2].min() # print 'max and min labor, j = 5 = ', n_mat[:,:,4].max(), n_mat[:,:,4].min() # print 'max and min labor, j = 4 = ', n_mat[:,:,3].max(), n_mat[:,:,3].min() # print 'max and min labor, j = 3 = ', n_mat[:,:,2].max(), n_mat[:,:,2].min() # print 'max and min labor, j = 2 = ', n_mat[:,:,1].max(), n_mat[:,:,1].min() # print 'max and min labor, j = 1 = ', n_mat[:,:,0].max(), n_mat[:,:,0].min() # print 'max and min labor, S = 80 = ', n_mat[:,-1,-1].max(), n_mat[:,-1,-1].min() # print "number > 1 = ", (n_mat > 1).sum() # print "number < 0, = ", (n_mat < 0).sum() # print "number > 1, j=7 = ", (n_mat[:T,:,-1] > 1).sum() # print "number < 0, j=7 = ", (n_mat[:T,:,-1] < 0).sum() # print "number > 1, s=80, j=7 = ", (n_mat[:T,-1,-1] > 1).sum() # print "number < 0, s=80, j=7 = ", (n_mat[:T,-1,-1] < 0).sum() # print "number > 1, j= 7, age 80= ", (n_mat[:T,-1,-1] > 1).sum() # print "number < 0, j = 7, age 80= ", (n_mat[:T,-1,-1] < 0).sum() # print "number > 1, j= 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] > 1).sum() # print "number < 0, j = 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] < 0).sum() # print "number > 1, j= 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80,-1] > 1).sum() # print "number < 0, j = 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80 ,-1] < 0).sum() # diag_dict = {'n_mat': n_mat, 'b_mat': b_mat, 'y_path': y_path, 'c_path': c_path} # pickle.dump(diag_dict, open('tpi_iter1.pkl', 'wb')) else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(np.abs(T_H_new[:T] - T_H[:T]))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print '\tIteration:', TPIiter print '\t\tDistance:', TPIdist Y[:T] = Ynew # Solve HH problem in inner loop guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, ind) euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) bmat_s = np.zeros((T, S, J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:T - 1, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[:T, :, :] K[0] = K0 K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(bmat_splus1[:T - 1], K_params) L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(n_mat[:T], L_params) Y_params = (alpha, Z) Ynew = firm.get_Y(K[:T], L[:T], Y_params) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) wnew = firm.get_w_from_r(rnew, w_params) omega_shift = np.append(omega_S_preTP.reshape(1, S), omega[:T - 1, :], axis=0) BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)), b_mat[:T - 1, :, :], axis=0) BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params) total_tax_params = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): total_tax_params[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) tax_receipt_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = np.array( list( tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), ( 1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), ( 1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape( T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S) if fix_transfers: G[:T] = net_tax_receipts[:T] - T_H[:T] else: T_H[:T] = net_tax_receipts[:T] G[:T] = 0.0 etr_params_path = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_path[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas, 'TPI', retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)), bmat_s, n_mat[:T, :, :], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T, :, :], BQ[:T].reshape(T, 1, J), tax_path, cons_params) C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI') C = household.get_C(c_path, C_params) I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T + 1], 'TPI') I = firm.get_I(bmat_splus1[:T], K[1:T + 1], K[:T], I_params) rc_error = Y[:T] - C[:T] - I[:T] - G[:T] print 'Resource Constraint Difference:', rc_error # compute utility u_params = (sigma, np.tile(chi_n.reshape(1, S, 1), (T, 1, J)), b_ellipse, ltilde, upsilon, np.tile(rho.reshape(1, S, 1), (T, 1, J)), np.tile(chi_b.reshape(1, 1, J), (T, S, 1))) utility_path = household.get_u(c_path[:T, :, :], n_mat[:T, :, :], bmat_splus1[:T, :, :], u_params) # compute before and after-tax income y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * bmat_s[:T, :, :] + np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) * np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :]) inctax_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), etr_params_path) y_aftertax_path = (y_path - tax.tau_income( np.tile(r[:T].reshape(T, 1, 1), (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)), bmat_s[:T, :, :], n_mat[:T, :, :], factor, inctax_params)) # compute after-tax wealth wtax_params = (h_wealth, p_wealth, m_wealth) b_aftertax_path = bmat_s[:T, :, :] - tax.tau_wealth( bmat_s[:T, :, :], wtax_params) print 'Checking time path for violations of constaints.' for t in xrange(T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_path[t], t, ltilde) eul_savings = euler_errors[:, :S, :].max(1).max(1) eul_laborleisure = euler_errors[:, S:, :].max(1).max(1) print 'Max Euler error, savings: ', eul_savings print 'Max Euler error labor supply: ', eul_laborleisure ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 'c_path': c_path, 'tax_path': tax_path, 'bmat_s': bmat_s, 'utility_path': utility_path, 'b_aftertax_path': b_aftertax_path, 'y_aftertax_path': y_aftertax_path, 'y_path': y_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure } macro_output = { 'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w, 'tax_path': tax_path } # if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS : # raise RuntimeError("Transition path equlibrium not found") # # if ((np.any(np.absolute(rc_error) >= 1e-6)) # and ENFORCE_SOLUTION_CHECKS): # raise RuntimeError("Transition path equlibrium not found") # # if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or # (np.any(np.absolute(eul_laborleisure) > mindist_TPI))) # and ENFORCE_SOLUTION_CHECKS): # raise RuntimeError("Transition path equlibrium not found") return output, macro_output
def run_TPI(income_tax_params, tpi_params, iterative_params, initial_values, SS_values, fix_transfers=False, output_dir="./OUTPUT"): # unpack tuples of parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params maxiter, mindist_SS, mindist_TPI = iterative_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, imm_rates, e, retire, mean_income_data,\ factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP = initial_values Kss, Lss, rss, wss, BQss, T_Hss, Gss, bssmat_splus1, nssmat = SS_values TPI_FIG_DIR = output_dir # Initialize guesses at time paths domain = np.linspace(0, T, T) r = np.ones(T + S) * rss BQ = np.zeros((T + S, J)) BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') BQ0 = household.get_BQ(r[0], initial_b, BQ0_params) for j in xrange(J): BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQ = np.array(BQ) # print "BQ values = ", BQ[0, :], BQ[100, :], BQ[-1, :], BQss # print "K0 vs Kss = ", K0-Kss if fix_transfers: T_H = T_H_baseline else: if np.abs(T_Hss) < 1e-13 : T_Hss2 = 0.0 # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below else: T_Hss2 = T_Hss T_H = np.ones(T + S) * T_Hss2 * (r/rss) G = np.ones(T + S) * Gss # # print "T_H values = ", T_H[0], T_H[100], T_H[-1], T_Hss # # print "omega diffs = ", (omega_S_preTP-omega[-1]).max(), (omega[10]-omega[-1]).max() # # Make array of initial guesses for labor supply and savings domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) # print 'diff btwn start and end b: ', (guesses_b[0]-guesses_b[-1]).max() # domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) # b_mat = np.zeros((T + S, S, J)) # n_mat = np.zeros((T + S, S, J)) ind = np.arange(S) # # print 'diff btwn start and end n: ', (guesses_n[0]-guesses_n[-1]).max() # # # find economic aggregates K = np.zeros(T+S) L = np.zeros(T+S) K[0] = K0 K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(guesses_b[:T-1], K_params) K[T:] = Kss L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(guesses_n[:T], L_params) L[T:] = Lss Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) r[:T] = firm.get_r(Y[:T], K[:T], r_params) # uncomment lines below if want to use starting values from prior run r = TPI_START_VALUES['r'] K = TPI_START_VALUES['K'] L = TPI_START_VALUES['L'] Y = TPI_START_VALUES['Y'] T_H = TPI_START_VALUES['T_H'] BQ = TPI_START_VALUES['BQ'] G = TPI_START_VALUES['G'] guesses_b = TPI_START_VALUES['b_mat'] guesses_n = TPI_START_VALUES['n_mat'] TPIiter = 0 TPIdist = 10 PLOT_TPI = False euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) # print 'analytical mtrs in tpi = ', analytical_mtrs while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: K_plot = list(K) + list(np.ones(10) * Kss) L_plot = list(L) + list(np.ones(10) * Lss) plt.figure() plt.axhline( y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange( T + 10), Kpath_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) guesses = (guesses_b, guesses_n) w_params = (Z, alpha, delta) w = firm.get_w_from_r(r, w_params) # print 'r and rss diff = ', r-rss # print 'w and wss diff = ', w-wss # print 'BQ and BQss diff = ', BQ-BQss # print 'T_H and T_Hss diff = ', T_H - T_Hss # print 'guess b and bss = ', (bssmat_splus1 - guesses_b).max() # print 'guess n and nss = ', (nssmat - guesses_n).max() outer_loop_vars = (r, w, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, ind) # Solve HH problem in inner loop euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) # print 'guess b and bss = ', (b_mat - guesses_b).max() # print 'guess n and nss over time = ', (n_mat - guesses_n).max(axis=2).max(axis=1) # print 'guess n and nss over age = ', (n_mat - guesses_n).max(axis=0).max(axis=1) # print 'guess n and nss over ability = ', (n_mat - guesses_n).max(axis=0).max(axis=0) # quit() print 'Max Euler error: ', (np.abs(euler_errors)).max() bmat_s = np.zeros((T, S, J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[:T, :, :] K[0] = K0 K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1, S, 1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(bmat_splus1[:T-1], K_params) L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(n_mat[:T], L_params) # print 'K diffs = ', K-K0 # print 'L diffs = ', L-L[0] Y_params = (alpha, Z) Ynew = firm.get_Y(K[:T], L[:T], Y_params) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) wnew = firm.get_w_from_r(rnew, w_params) omega_shift = np.append(omega_S_preTP.reshape(1, S), omega[:T-1, :], axis=0) BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') # b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)), # b_mat[:T-1, :, :], axis=0) b_mat_shift = bmat_splus1[:T, :, :] # print 'b diffs = ', (bmat_splus1[100, :, :] - initial_b).max(), (bmat_splus1[0, :, :] - initial_b).max(), (bmat_splus1[1, :, :] - initial_b).max() # print 'r diffs = ', rnew[1]-r[1], rnew[100]-r[100], rnew[-1]-r[-1] BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params) BQss2 = np.empty(J) for j in range(J): BQss_params = (omega[1, :], lambdas[j], rho, g_n_vector[1], 'SS') BQss2[j] = household.get_BQ(rnew[1], bmat_splus1[1, :, j], BQss_params) # print 'BQ test = ', BQss2-BQss, BQss-BQnew[1], BQss-BQnew[100], BQss-BQnew[-1] total_tax_params = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): total_tax_params[:, :, :, i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) tax_receipt_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)), bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S) r[:T] = utils.convex_combo(rnew[:T], r[:T], nu) BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu) if fix_transfers: T_H_new = T_H G[:T] = net_tax_receipts[:T] - T_H[:T] else: T_H_new = net_tax_receipts T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu) G[:T] = 0.0 etr_params_path = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_path[:,:,:,i] = np.tile( np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas, 'TPI', retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) b_to_use = np.zeros((T, S, J)) b_to_use[0, 1:, :] = initial_b[:-1, :] b_to_use[1:, 1:, :] = b_mat[:T-1, :-1, :] tax_path = tax.total_taxes( np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), b_to_use, n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * b_to_use[:T, :, :] + np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) * np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :]) cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), b_to_use[:T,:,:], b_mat[:T,:,:], n_mat[:T,:,:], BQ[:T].reshape(T, 1, J), tax_path, cons_params) guesses_b = utils.convex_combo(b_mat, guesses_b, nu) guesses_n = utils.convex_combo(n_mat, guesses_n, nu) if T_H.all() != 0: TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() print 'r dist = ', np.array(list(utils.pct_diff_func(rnew[:T], r[:T]))).max() print 'BQ dist = ', np.array(list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten())).max() print 'T_H dist = ', np.array(list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() print 'T_H path = ', T_H[:20] # print 'r old = ', r[:T] # print 'r new = ', rnew[:T] # print 'K old = ', K[:T] # print 'L old = ', L[:T] # print 'income = ', y_path[:, :, -1] # print 'taxes = ', tax_path[:, :, -1] # print 'labor supply = ', n_mat[:, :, -1] # print 'max and min labor = ', n_mat.max(), n_mat.min() # print 'max and min labor = ', np.argmax(n_mat), np.argmin(n_mat) # print 'max and min labor, j = 7 = ', n_mat[:,:,-1].max(), n_mat[:,:,-1].min() # print 'max and min labor, j = 6 = ', n_mat[:,:,-2].max(), n_mat[:,:,-2].min() # print 'max and min labor, j = 5 = ', n_mat[:,:,4].max(), n_mat[:,:,4].min() # print 'max and min labor, j = 4 = ', n_mat[:,:,3].max(), n_mat[:,:,3].min() # print 'max and min labor, j = 3 = ', n_mat[:,:,2].max(), n_mat[:,:,2].min() # print 'max and min labor, j = 2 = ', n_mat[:,:,1].max(), n_mat[:,:,1].min() # print 'max and min labor, j = 1 = ', n_mat[:,:,0].max(), n_mat[:,:,0].min() # print 'max and min labor, S = 80 = ', n_mat[:,-1,-1].max(), n_mat[:,-1,-1].min() # print "number > 1 = ", (n_mat > 1).sum() # print "number < 0, = ", (n_mat < 0).sum() # print "number > 1, j=7 = ", (n_mat[:T,:,-1] > 1).sum() # print "number < 0, j=7 = ", (n_mat[:T,:,-1] < 0).sum() # print "number > 1, s=80, j=7 = ", (n_mat[:T,-1,-1] > 1).sum() # print "number < 0, s=80, j=7 = ", (n_mat[:T,-1,-1] < 0).sum() # print "number > 1, j= 7, age 80= ", (n_mat[:T,-1,-1] > 1).sum() # print "number < 0, j = 7, age 80= ", (n_mat[:T,-1,-1] < 0).sum() # print "number > 1, j= 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] > 1).sum() # print "number < 0, j = 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] < 0).sum() # print "number > 1, j= 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80,-1] > 1).sum() # print "number < 0, j = 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80 ,-1] < 0).sum() # diag_dict = {'n_mat': n_mat, 'b_mat': b_mat, 'y_path': y_path, 'c_path': c_path} # pickle.dump(diag_dict, open('tpi_iter1.pkl', 'wb')) else: TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(np.abs(T_H_new[:T]-T_H[:T]))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print '\tIteration:', TPIiter print '\t\tDistance:', TPIdist Y[:T] = Ynew # Solve HH problem in inner loop guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, ind) euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) bmat_s = np.zeros((T, S, J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[:T, :, :] K[0] = K0 K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(bmat_splus1[:T-1], K_params) L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(n_mat[:T], L_params) Y_params = (alpha, Z) Ynew = firm.get_Y(K[:T], L[:T], Y_params) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) wnew = firm.get_w_from_r(rnew, w_params) omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0) BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') b_mat_shift = np.append(np.reshape(initial_b,(1,S,J)),b_mat[:T-1,:,:],axis=0) BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params) total_tax_params = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): total_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) tax_receipt_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)), bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S) if fix_transfers: G[:T] = net_tax_receipts[:T] - T_H[:T] else: T_H[:T] = net_tax_receipts[:T] G[:T] = 0.0 etr_params_path = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas, 'TPI', retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), bmat_s, n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T,:,:], BQ[:T].reshape(T, 1, J), tax_path, cons_params) C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI') C = household.get_C(c_path, C_params) I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI') I = firm.get_I(bmat_splus1[:T], K[1:T+1], K[:T], I_params) rc_error = Y[:T] - C[:T] - I[:T] - G[:T] print 'Resource Constraint Difference:', rc_error # compute utility u_params = (sigma, np.tile(chi_n.reshape(1, S, 1), (T, 1, J)), b_ellipse, ltilde, upsilon, np.tile(rho.reshape(1, S, 1), (T, 1, J)), np.tile(chi_b.reshape(1, 1, J), (T, S, 1))) utility_path = household.get_u(c_path[:T, :, :], n_mat[:T, :, :], bmat_splus1[:T, :, :], u_params) # compute before and after-tax income y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * bmat_s[:T, :, :] + np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) * np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :]) inctax_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), etr_params_path) y_aftertax_path = (y_path - tax.tau_income(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)), bmat_s[:T,:,:], n_mat[:T,:,:], factor, inctax_params)) # compute after-tax wealth wtax_params = (h_wealth, p_wealth, m_wealth) b_aftertax_path = bmat_s[:T,:,:] - tax.tau_wealth(bmat_s[:T,:,:], wtax_params) print'Checking time path for violations of constaints.' for t in xrange(T): household.constraint_checker_TPI( b_mat[t], n_mat[t], c_path[t], t, ltilde) eul_savings = euler_errors[:, :S, :].max(1).max(1) eul_laborleisure = euler_errors[:, S:, :].max(1).max(1) print 'Max Euler error, savings: ', eul_savings print 'Max Euler error labor supply: ', eul_laborleisure ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 'c_path': c_path, 'tax_path': tax_path, 'bmat_s': bmat_s, 'utility_path': utility_path, 'b_aftertax_path': b_aftertax_path, 'y_aftertax_path': y_aftertax_path, 'y_path': y_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure} macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w, 'tax_path': tax_path} # if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS : # raise RuntimeError("Transition path equlibrium not found") # # if ((np.any(np.absolute(rc_error) >= 1e-6)) # and ENFORCE_SOLUTION_CHECKS): # raise RuntimeError("Transition path equlibrium not found") # # if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or # (np.any(np.absolute(eul_laborleisure) > mindist_TPI))) # and ENFORCE_SOLUTION_CHECKS): # raise RuntimeError("Transition path equlibrium not found") return output, macro_output