def solve_ss(r_init, params): ''' Solves for the steady-state equlibrium of the OG model ''' beta, sigma, n, alpha, A, delta, xi = params ss_dist = 7.0 ss_tol = 1e-8 ss_iter = 0 ss_max_iter = 300 r = r_init while (ss_dist > ss_tol) & (ss_iter < ss_max_iter): # get w w = firm.get_w(r, alpha, A, delta) # solve HH problem foc_args = (beta, sigma, r, w, n, 0.0) b_sp1_guess = [0.05, 0.05] result = opt.root(hh.FOCs, b_sp1_guess, args=foc_args) b_sp1 = result.x euler_errors = result.fun b_s = np.append(0.0, b_sp1) # use market clearing L = agg.get_L(n) K = agg.get_K(b_s) # find implied r r_prime = firm.get_r(L, K, alpha, A, delta) # check distance ss_dist = np.absolute(r - r_prime) print('Iteration = ', ss_iter, ', Distance = ', ss_dist, ', r = ', r) # update r r = xi * r_prime + (1 - xi) * r # update iteration counter ss_iter += 1 return r, b_sp1, euler_errors
def solve_tp(r_path_init, params): ''' Solves for the time path equlibrium using TPI ''' (beta, sigma, n, alpha, A, delta, T, xi, b_sp1_pre, r_ss, b_sp1_ss) = params tpi_dist = 7.0 tpi_tol = 1e-8 tpi_iter = 0 tpi_max_iter = 300 r_path = np.append(r_path_init, np.ones(2) * r_ss) while (tpi_dist > tpi_tol) & (tpi_iter < tpi_max_iter): w_path = firm.get_w(r_path, alpha, A, delta) # Solve HH problem b_sp1_mat = np.zeros((T + 2, 2)) euler_errors_mat = np.zeros((T + 2, 2)) # solve upper right corner foc_args = (beta, sigma, r_path[:2], w_path[:2], n[-2:], b_sp1_pre[0]) b_sp1_guess = b_sp1_ss[-1] result = opt.root(hh.FOCs, b_sp1_guess, args=foc_args) b_sp1_mat[0, -1] = result.x euler_errors_mat[0, -1] = result.fun # solve all full lifetimes DiagMaskb = np.eye(2, dtype=bool) for t in range(T): foc_args = (beta, sigma, r_path[t:t + 3], w_path[t:t + 3], n, 0.0) b_sp1_guess = b_sp1_ss result = opt.root(hh.FOCs, b_sp1_guess, args=foc_args) b_sp1_mat[t:t + 2, :] = (DiagMaskb * result.x + b_sp1_mat[t:t + 2, :]) euler_errors_mat[t:t + 2, :] = (DiagMaskb * result.fun + euler_errors_mat[t:t + 2, :]) # create a b_s_mat b_s_mat = np.zeros((T, 3)) b_s_mat[0, 1:] = b_sp1_pre b_s_mat[1:, 1:] = b_sp1_mat[:T - 1, :] # use market clearing L_path = np.ones(T) * agg.get_L(n) K_path = agg.get_K(b_s_mat) # find implied r r_path_prime = firm.get_r(L_path, K_path, alpha, A, delta) # check distance tpi_dist = np.absolute(r_path[:T] - r_path_prime[:T]).max() print('Iteration = ', tpi_iter, ', Distance = ', tpi_dist) # update r r_path[:T] = xi * r_path_prime[:T] + (1 - xi) * r_path[:T] # update iteration counter tpi_iter += 1 if tpi_iter < tpi_max_iter: print('The time path solved') else: print('The time path did not solve') return r_path[:T], euler_errors_mat[:T, :]
def test_get_r(): ''' Teset of the firm.get_r() function ''' A = 1.0 alpha = 0.5 delta = 0.1 L = 4.0 K = 16.0 expected_value = 0.15 test_value = firm.get_r(L, K, alpha, A, delta) assert np.allclose(test_value, expected_value)
def solve_ss(r_init, params): ''' Solves for the steady-state equlibrium of the OG model ''' beta, sigma, alpha, A, delta, xi, omega_SS, imm_rates_SS, S = params ss_dist = 7.0 ss_tol = 1e-8 ss_iter = 0 ss_max_iter = 300 r = r_init # w = w_init # Why do we need w as well? Are we not going to get it by providing r_init to firm.get_w()? # I think Jason said this too and I'm going to stick to what we did in class. while (ss_dist > ss_tol) & (ss_iter < ss_max_iter): # get w w = firm.get_w(r, alpha, A, delta) # solve HH problem foc_args = (beta, sigma, r, w, 0.0) n_s_guess = np.ones(S) b_sp1_guess = np.ones(S - 1) * 0.5 HH_guess = np.append(b_sp1_guess, n_s_guess) result = opt.root(hh.FOCs, HH_guess, args=foc_args) b_sp1 = result.x[0:S - 1] n_s = result.x[S - 1:] euler_errors = result.fun b_s = np.append(0.0, b_sp1) # use market clearing L = agg.get_L(n_s, omega_SS) K = agg.get_K(b_s, omega_SS, imm_rates_SS) # find implied r r_prime = firm.get_r(L, K, alpha, A, delta) # find implied w w_prime = firm.get_w(r, alpha, A, delta) # check distance ss_dist_r = np.absolute(r - r_prime) ss_dist_w = np.absolute(w - w_prime) print('Iteration = ', ss_iter, ', Distance r = ', ss_dist_r, ', r = ', r, ', w = ', w) # update r r = xi * r_prime + (1 - xi) * r # update iteration counter ss_iter += 1 return r, w, b_sp1, euler_errors
def solve_ss(r_init, w_init, params): ''' Solves for the steady-state equlibrium of the OG model ''' beta, sigma, n, alpha, A, delta, xi = params ss_dist = 7.0 ss_tol = 1e-8 ss_iter = 0 ss_max_iter = 300 r = r_init w = w_init while (ss_dist > ss_tol) & (ss_iter < ss_max_iter): # solve HH problem foc_args = (beta, sigma, r, w, 0.0) n_s_guess = np.ones(S) b_sp1_guess = np.ones(S-1) * 0.5 HH_guess = np.append(b_sp1_guess, n_s_guess) result = opt.root(hh.FOCs, HH_guess, args=foc_args) b_sp1 = result.x[0: S-1] n_s = result.x[S-1:] euler_errors = result.fun b_s = np.append(0.0, b_sp1) # use market clearing L = agg.get_L(n) K = agg.get_K(b_s) # find implied r r_prime = firm.get_r(L, K, alpha, A, delta) # find implied w w_prime = firm.get_w(L, K, G, alpha, A) # check distance ss_dist_r = np.absolute(r - r_prime) ss_dist_w = np.absolute(w - w_prime) print('Iteration = ', ss_iter, ', Distance r = ', ss_dist_r, ', Disrance w = ' ss_dist_w, ', r = ', r, ', w = ', w) # update r r = xi * r_prime + (1 - xi) * r # update w w = xi * w_prime + (1 - xi) * w # update iteration counter ss_iter += 1 return r, w, b_sp1, euler_errors
def solve_ss(r_init, params): ''' Solves for the steady-state equlibrium of the OG model ''' beta, sigma, alpha, A, delta, xi, l_tilde, chi, theta, omega_SS, imm_rates_SS, rho_s, S = params ss_dist = 7.0 ss_tol = 1e-8 ss_iter = 0 ss_max_iter = 300 r = r_init while (ss_dist > ss_tol) & (ss_iter < ss_max_iter): # get w w = firm.get_w(r, alpha, A, delta) # solve HH problem foc_args = (beta, sigma, r, w, 0.0, l_tilde, chi, theta, omega_SS, rho_s) n_s_guess = np.ones(S) b_sp1_guess = np.ones(S-1) * 0.5 HH_guess = np.append(b_sp1_guess, n_s_guess) result = opt.root(hh.FOCs, HH_guess, args=foc_args) b_sp1 = result.x[0: S-1] n_s = result.x[S-1:] euler_errors = result.fun b_s = np.append(0.0, b_sp1) # use market clearing L = agg.get_L(n_s, omega_SS) K = agg.get_K(b_s, omega_SS, imm_rates_SS) # find implied r r_prime = firm.get_r(L, K, alpha, A, delta) # check distance ss_dist_r = np.absolute(r - r_prime) print('Iteration = ', ss_iter, ', Distance r = ', ss_dist_r, ', r = ', r) # update r r = xi * r_prime + (1 - xi) * r # update iteration counter ss_iter += 1 return ss_iter, r, w, b_sp1, euler_errors
def TPI_fsolve(guesses, Kss, Lss, Yss, BQss, theta, income_tax_params, wealth_tax_params, ellipse_params, parameters, g_n_vector, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, chi_n, output_dir="./OUTPUT", **kwargs): 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 = parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params # create full time paths with guesses and SS values rinit = np.zeros(T+S) winit = np.zeros(T+S) T_H_init = np.zeros(T+S) BQinit = np.zeros((T+S,J)) rinit[:T] = guesses[0:T].reshape(T) winit[:T] = guesses[T:2*T].reshape(T) rinit[T:] = rss winit[T:] = wss T_H_init[:T] = guesses[2*T:3*T].reshape(T) BQinit[:T,:] = guesses[3*T:].reshape(T,J) T_H_init[T:] = T_Hss BQinit[T:,:] = BQss # Make array of initial guesses for distribution of # savings and labor supply domain = np.linspace(0, T, T) 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) 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) euler_errors = np.zeros((T, 2 * S, J)) # Solve hh problem over time path: # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, income_tax_params, parameters, theta, tau_bq), xtol=1e-13)) # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6: # print 'minidoughnut:', # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, # factor_ss, j, parameters, theta, tau_bq)).max() for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag( guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) # initialize array of diagonal elements length_diag = (np.diag(np.transpose(etr_params[:S,:,0]),S-(s+2))).shape[0] etr_params_to_use = np.zeros((length_diag,etr_params.shape[2])) mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2])) mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:S,:,i]),S-(s+2)) mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:S,:,i]),S-(s+2)) mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:S,:,i]),S-(s+2)) inc_tax_params_upper = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, inc_tax_params_upper, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6: # print 's-loop:', # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, # theta, tau_bq, rho, lambdas, e, initial_b, chi_b, # chi_n))).max() for t in xrange(0, T): b_guesses_to_use = .75 * \ np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) # initialize array of diagonal elements length_diag = (np.diag(np.transpose(etr_params[:,t:t+S,i]))).shape[0] etr_params_to_use = np.zeros((length_diag,etr_params.shape[2])) mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2])) mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:,t:t+S,i])) mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:,t:t+S,i])) mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:,t:t+S,i])) inc_tax_params_TP = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver( inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[ :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') # Plotting of Kpath and Lpath to check convergence # make vectors of Kpath and Lpath to plot Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss) Lpath_TPI = list(Linit) + list(np.ones(10) * Lss) # Plot TPI for K for each iteration, so we can see if there is a # problem TPI_FIG_DIR = output_dir if PLOT_TPI is True: plt.figure() plt.axhline( y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange( T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) Ynew = firm.get_Y(Kinit, Linit, parameters) wnew = firm.get_w(Ynew, Linit, parameters) rnew = firm.get_r(Ynew, Kinit, parameters) # the following needs a g_n term BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] # initialize array TH_tax_params = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): TH_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) T_H_new = np.array(list(tax.get_lump_sum(np.tile(rnew.reshape(T, 1, 1),(1,S,J)), bmat_s, np.tile(wnew.reshape( T, 1, 1),(1,S,J)), np.tile(e.reshape(1, S, J),(T,1,1)), n_mat[:T,:,:], BQnew.reshape(T, 1, J), lambdas.reshape( 1, 1, J), factor_ss, omega_stationary[:T].reshape(T, S, 1), 'TPI', TH_tax_params, parameters, theta, tau_bq)) + [T_Hss] * S) error1 = rinit[:T]-rnew[:T] error2 = winit[:T]-wnew[:T] error3 = T_H_init[:T]-T_H_new[:T] error4 = BQinit[:T] - BQnew[:T] # Check and punish constraing violations mask1 = rinit[:T] <= 0 mask2 = winit[:T] <= 0 mask3 = np.isnan(rinit[:T]) mask4 = np.isnan(winit[:T]) error1[mask1] = 1e14 error2[mask2] = 1e14 error1[mask3] = 1e14 error2[mask4] = 1e14 mask5 = T_H_init[:T] < 0 mask6 = np.isnan(T_H_init[:T]) mask7 = BQinit[:T] < 0 mask8 = np.isnan(BQinit[:T]) error3[mask5] = 1e14 error3[mask6] = 1e14 error4[mask7] = 1e14 error4[mask8] = 1e14 errors = np.array(list(error1) +list(error2) + list(error3) + list(error4.flatten())) print '\t\tDistance:', np.absolute(errors).max() return errors
def run_time_path_iteration(Kss, Lss, Yss, BQss, theta, income_tax_params, wealth_tax_params, ellipse_params, parameters, g_n_vector, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, chi_n, output_dir="./OUTPUT", **kwargs): 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 = parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params TPI_FIG_DIR = output_dir # Initialize Time paths domain = np.linspace(0, T, T) Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss Kinit[-1] = Kss Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss)) Linit = np.ones(T + S) * Lss Yinit = firm.get_Y(Kinit, Linit, parameters) winit = firm.get_w(Yinit, Linit, parameters) rinit = firm.get_r(Yinit, Kinit, parameters) BQinit = np.zeros((T + S, J)) for j in xrange(J): BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQinit = np.array(BQinit) if T_Hss < 1e-13 and T_Hss > 0.0 : 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_init = np.ones(T + S) * T_Hss2 # Make array of initial guesses 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) 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) TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss) Lpath_TPI = list(Linit) + list(np.ones(10) * Lss) # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: plt.figure() plt.axhline( y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange( T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, income_tax_params, parameters, theta, tau_bq), xtol=1e-13)) # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6: # print 'minidoughnut:', # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, # factor_ss, j, parameters, theta, tau_bq)).max() for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag( guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) # initialize array of diagonal elements length_diag = (np.diag(np.transpose(etr_params[:S,:,0]),S-(s+2))).shape[0] etr_params_to_use = np.zeros((length_diag,etr_params.shape[2])) mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2])) mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:S,:,i]),S-(s+2)) mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:S,:,i]),S-(s+2)) mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:S,:,i]),S-(s+2)) inc_tax_params_upper = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, inc_tax_params_upper, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6: # print 's-loop:', # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, # theta, tau_bq, rho, lambdas, e, initial_b, chi_b, # chi_n))).max() for t in xrange(0, T): b_guesses_to_use = .75 * \ np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) # initialize array of diagonal elements length_diag = (np.diag(np.transpose(etr_params[:,t:t+S,i]))).shape[0] etr_params_to_use = np.zeros((length_diag,etr_params.shape[2])) mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2])) mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:,t:t+S,i])) mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:,t:t+S,i])) mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:,t:t+S,i])) inc_tax_params_TP = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver( inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[ :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') Ynew = firm.get_Y(Kinit, Linit, parameters) wnew = firm.get_w(Ynew, Linit, parameters) rnew = firm.get_r(Ynew, Kinit, parameters) # the following needs a g_n term BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] # initialize array TH_tax_params = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): TH_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) T_H_new = np.array(list(tax.get_lump_sum(np.tile(rnew.reshape(T, 1, 1),(1,S,J)), bmat_s, np.tile(wnew.reshape( T, 1, 1),(1,S,J)), np.tile(e.reshape(1, S, J),(T,1,1)), n_mat[:T,:,:], BQnew.reshape(T, 1, J), lambdas.reshape( 1, 1, J), factor_ss, omega_stationary[:T].reshape(T, S, 1), 'TPI', TH_tax_params, parameters, theta, tau_bq)) + [T_Hss] * S) winit[:T] = utils.convex_combo(wnew, winit[:T], nu) rinit[:T] = utils.convex_combo(rnew, rinit[:T], nu) BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], nu) T_H_init[:T] = utils.convex_combo(T_H_new[:T], T_H_init[:T], nu) guesses_b = utils.convex_combo(b_mat, guesses_b, nu) guesses_n = utils.convex_combo(n_mat, guesses_n, nu) if T_H_init.all() != 0: TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list( utils.perc_dif_func(wnew, winit[:T])) + list(utils.perc_dif_func(T_H_new, T_H_init))).max() else: TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list( utils.perc_dif_func(wnew, winit[:T])) + list(np.abs(T_H_new, T_H_init))).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 return winit[:T], rinit[:T], T_H_init[:T], BQinit[:T], Yinit
def inner_loop(outer_loop_vars, params): ''' This function solves for the inner loop of the SS. That is, given the guesses of the outer loop variables (r, w, T_H, factor) this function solves the households' problems in the SS. Inputs: r = [T,] vector, interest rate w = [T,] vector, wage rate b = [T,S,J] array, wealth holdings n = [T,S,J] array, labor supply BQ = [T,J] vector, bequest amounts factor = scalar, model income scaling factor T_H = [T,] vector, lump sum transfer amount(s) Functions called: euler_equation_solver() household.get_K() firm.get_L() firm.get_Y() firm.get_r() firm.get_w() household.get_BQ() tax.replacement_rate_vals() tax.get_lump_sum() Objects in function: Returns: euler_errors, bssmat, nssmat, new_r, new_w new_T_H, new_factor, new_BQ ''' # unpack variables and parameters pass to function bssmat, nssmat, r, w, T_H, factor = outer_loop_vars ss_params, income_tax_params, chi_params = params J, S, T, BQ_dist, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, e, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params chi_b, chi_n = chi_params etr_params = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1)) mtrx_params = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1)) mtry_params = np.tile(np.reshape(mtry_params,(S,1,mtry_params.shape[1])),(1,J,1)) euler_errors = np.zeros((2*S,J)) guesses = np.hstack((bssmat, nssmat)) euler_params = [r, w, T_H, factor, J, S, BQ_dist, beta, sigma, ltilde, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\ chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\ analytical_mtrs, etr_params, mtrx_params,\ mtry_params] [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9, args=euler_params, xtol=MINIMIZER_TOL, full_output=True) euler_errors = infodict['fvec'] print 'Max Euler errors: ', np.absolute(euler_errors).max() euler_errors = euler_errors.reshape(S, 2 *J) solutions = solutions.reshape(S, 2*J) bssmat = solutions[:, :J] nssmat = solutions[:, J:] K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS') K = household.get_K(bssmat, K_params) L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS') L = firm.get_L(nssmat, L_params) Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) new_r = firm.get_r(Y, K, r_params) new_w = firm.get_w(Y, L, alpha) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * omega_SS.reshape(S, 1) * lambdas.reshape(1, J)).sum() new_factor = mean_income_data / average_income_model BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') new_BQ = household.get_BQ(new_r, bssmat, BQ_params) theta_params = (e, J, omega_SS.reshape(S, 1), lambdas) theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params) T_H_params = (e, BQ_dist, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params) return euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_factor, new_BQ, average_income_model
def inner_loop(outer_loop_vars, params, baseline): ''' This function solves for the inner loop of the SS. That is, given the guesses of the outer loop variables (r, w, T_H, factor) this function solves the households' problems in the SS. Inputs: r = [T,] vector, interest rate w = [T,] vector, wage rate b = [T,S,J] array, wealth holdings n = [T,S,J] array, labor supply BQ = [T,J] vector, bequest amounts factor = scalar, model income scaling factor T_H = [T,] vector, lump sum transfer amount(s) Functions called: euler_equation_solver() household.get_K() firm.get_L() firm.get_Y() firm.get_r() firm.get_w() household.get_BQ() tax.replacement_rate_vals() tax.get_lump_sum() Objects in function: Returns: euler_errors, bssmat, nssmat, new_r, new_w new_T_H, new_factor, new_BQ ''' # unpack variables and parameters pass to function bssmat, nssmat, r, w, T_H, BQ, theta, factor = outer_loop_vars ss_params, income_tax_params, chi_params = params J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params chi_b, chi_n = chi_params # bssmat = START_VALUES['bssmat_splus1'] # nssmat = START_VALUES['nssmat'] cssmat = np.zeros((S,J)) euler_errors = np.zeros((2*S,J)) for j in xrange(J): # Solve the euler equations if j == 0: b_Sp1_guess = bssmat[-1, j] else: b_Sp1_guess = bssmat[-1, j-1]*10 euler_params = [r, w, T_H, BQ, theta, factor, j, J, S, beta, sigma, ltilde, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\ j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\ analytical_mtrs, etr_params, mtrx_params,\ mtry_params] [solution, infodict, ier, message] = opt.fsolve(lc_error, b_Sp1_guess, args=euler_params, xtol=MINIMIZER_TOL, full_output=True) # [x0, r_out] = opt.bisect(lc_error, -1.0, 10.0, args=euler_params, xtol=MINIMIZER_TOL, full_output=True, disp=False) print 'j = ', j print 'b[0] error = ', infodict['fvec'] print 'message: ', message # print 'b[S]= ', x0 # print 'converged= ', r_out.converged b_out, nssmat[:, j], cssmat[:, j] = lifecycle_solver(solution,euler_params) bssmat[:, j] = b_out[1:] # print solutions # quit() # # euler_errors[:,j] = infodict['fvec'] # print 'j = ', j # print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max() # print 'bssmat: ', bssmat # print 'nssmat: ', nssmat # print 'cssmat: ', cssmat quit() K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS') K = household.get_K(bssmat, K_params) L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS') L = firm.get_L(nssmat, L_params) Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) new_r = firm.get_r(Y, K, r_params) new_w = firm.get_w(Y, L, alpha) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * omega_SS.reshape(S, 1) * lambdas.reshape(1, J)).sum() if baseline: new_factor = mean_income_data / average_income_model else: new_factor = factor BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') new_BQ = household.get_BQ(new_r, bssmat, BQ_params) theta_params = (e, S, J, omega_SS.reshape(S, 1), lambdas,retire) new_theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params) T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params) print 'Inner Loop Max Euler Error: ', (np.absolute(euler_errors)).max() # print 'K: ', K # print 'L: ', L #print 'bssmat: ', bssmat return euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_BQ, new_theta, new_factor, average_income_model
def create_tpi_params(a_tax_income, b_tax_income, c_tax_income, d_tax_income, b_ellipse, upsilon, J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, tau_payroll, retire, mean_income_data, get_baseline=True, input_dir="./OUTPUT", **kwargs): if get_baseline: ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl") variables = pickle.load(open(ss_init, "rb")) for key in variables: globals()[key] = variables[key] else: params_path = os.path.join( input_dir, "Saved_moments/params_changed.pkl") variables = pickle.load(open(params_path, "rb")) for key in variables: globals()[key] = variables[key] var_path = os.path.join(input_dir, "SS/ss_vars.pkl") variables = pickle.load(open(var_path, "rb")) for key in variables: globals()[key] = variables[key] init_tpi_vars = os.path.join(input_dir, "SSinit/ss_init_tpi_vars.pkl") variables = pickle.load(open(init_tpi_vars, "rb")) for key in variables: globals()[key] = variables[key] ''' ------------------------------------------------------------------------ Set other parameters and initial values ------------------------------------------------------------------------ ''' # Make a vector of all one dimensional parameters, to be used in the # following functions income_tax_params = [a_tax_income, b_tax_income, c_tax_income, d_tax_income] wealth_tax_params = [h_wealth, p_wealth, m_wealth] ellipse_params = [b_ellipse, upsilon] parameters = [J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data] + income_tax_params + wealth_tax_params + ellipse_params N_tilde = omega.sum(1) omega_stationary = omega / N_tilde.reshape(T + S, 1) if get_baseline: initial_b = bssmat_splus1 initial_n = nssmat else: initial_b = bssmat_init initial_n = nssmat_init # Get an initial distribution of capital with the initial population # distribution K0 = household.get_K(initial_b, omega_stationary[ 0].reshape(S, 1), lambdas, g_n_vector[0], 'SS') b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1])) b_splus1init = initial_b L0 = firm.get_L(e, initial_n, omega_stationary[ 0].reshape(S, 1), lambdas, 'SS') Y0 = firm.get_Y(K0, L0, parameters) w0 = firm.get_w(Y0, L0, parameters) r0 = firm.get_r(Y0, K0, parameters) BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape( S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[ 0].reshape(S, 1), 'SS', parameters, theta, tau_bq) tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, T_H_0, None, 'SS', False, parameters, theta, tau_bq) c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape( 1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0) return (income_tax_params, wealth_tax_params, ellipse_params, parameters, N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, w0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n)
def create_tpi_params(**sim_params): ''' ------------------------------------------------------------------------ Set factor and initial capital stock to SS from baseline ------------------------------------------------------------------------ ''' baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl") ss_baseline_vars = pickle.load(open(baseline_ss, "rb")) factor = ss_baseline_vars['factor_ss'] #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas initial_b = ss_baseline_vars['bssmat_splus1'] initial_n = ss_baseline_vars['nssmat'] SS_values = (ss_baseline_vars['Kss'], ss_baseline_vars['Lss'], ss_baseline_vars['rss'], ss_baseline_vars['wss'], ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'], ss_baseline_vars['bssmat_splus1'], ss_baseline_vars['nssmat']) # Make a vector of all one dimensional parameters, to be used in the # following functions wealth_tax_params = [ sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth'] ] ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']] chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']] N_tilde = sim_params['omega'].sum( 1 ) #this should just be one in each year given how we've constructed omega sim_params['omega'] = sim_params['omega'] / N_tilde.reshape( sim_params['T'] + sim_params['S'], 1) tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BW'], sim_params['beta'], sim_params['sigma'], sim_params['alpha'], sim_params['Z'], sim_params['delta'], sim_params['ltilde'], sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'], sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde, sim_params['lambdas'], sim_params['e'], sim_params['retire'], sim_params['mean_income_data'], factor] + \ wealth_tax_params + ellipse_params + chi_params iterative_params = [ sim_params['maxiter'], sim_params['mindist_SS'], sim_params['mindist_TPI'] ] 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 ## Assumption for tax functions is that policy in last year of BW is # extended permanently etr_params_TP = np.zeros((S, T + S, sim_params['etr_params'].shape[2])) etr_params_TP[:, :BW, :] = sim_params['etr_params'] etr_params_TP[:, BW:, :] = np.reshape( sim_params['etr_params'][:, BW - 1, :], (S, 1, sim_params['etr_params'].shape[2])) mtrx_params_TP = np.zeros((S, T + S, sim_params['mtrx_params'].shape[2])) mtrx_params_TP[:, :BW, :] = sim_params['mtrx_params'] mtrx_params_TP[:, BW:, :] = np.reshape( sim_params['mtrx_params'][:, BW - 1, :], (S, 1, sim_params['mtrx_params'].shape[2])) mtry_params_TP = np.zeros((S, T + S, sim_params['mtry_params'].shape[2])) mtry_params_TP[:, :BW, :] = sim_params['mtry_params'] mtry_params_TP[:, BW:, :] = np.reshape( sim_params['mtry_params'][:, BW - 1, :], (S, 1, sim_params['mtry_params'].shape[2])) income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP, mtrx_params_TP, mtry_params_TP) ''' ------------------------------------------------------------------------ Set other parameters and initial values ------------------------------------------------------------------------ ''' # Get an initial distribution of capital with the initial population # distribution K0_params = (omega[0].reshape(S, 1), lambdas, g_n_vector[0], 'SS') K0 = household.get_K(initial_b, K0_params) b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1])) b_splus1init = initial_b L0_params = (e, omega[0].reshape(S, 1), lambdas, 'SS') L0 = firm.get_L(initial_n, L0_params) Y0_params = (alpha, Z) Y0 = firm.get_Y(K0, L0, Y0_params) w0 = firm.get_w(Y0, L0, alpha) r0_params = (alpha, delta) r0 = firm.get_r(Y0, K0, r0_params) BQ0_params = (omega[0].reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') BQ0 = household.get_BQ(r0, initial_b, BQ0_params) theta_params = (e, J, omega[0].reshape(S, 1), lambdas) theta = tax.replacement_rate_vals(initial_n, w0, factor, theta_params) T_H_params = (e, lambdas, omega[0].reshape(S, 1), 'SS', etr_params_TP[:, 0, :], theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) T_H_0 = tax.get_lump_sum(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_params) etr_params_3D = np.tile( np.reshape(etr_params_TP[:, 0, :], (S, 1, etr_params_TP.shape[2])), (1, J, 1)) tax0_params = (e, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax0 = tax.total_taxes(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_0, None, False, tax0_params) c0_params = (e, lambdas.reshape(1, J), g_y) c0 = household.get_cons(r0, w0, b_sinit, b_splus1init, initial_n, BQ0.reshape(1, J), tax0, c0_params) initial_values = (K0, b_sinit, b_splus1init, L0, Y0, w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n) return (income_tax_params, tpi_params, iterative_params, initial_values, SS_values)
def run_TPI(income_tax_params, tpi_params, iterative_params, small_open_params, initial_values, SS_values, fiscal_params, biz_tax_params, output_dir="./OUTPUT", baseline_spending=False): # 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, gamma, epsilon, 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, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params # K0, b_sinit, b_splus1init, L0, Y0,\ # w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n, omega_S_preTP = initial_values small_open, tpi_firm_r, tpi_hh_r = small_open_params B0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP, initial_debt = initial_values Kss, Bss, Lss, rss, wss, BQss, T_Hss, revenue_ss, bssmat_splus1, nssmat, Yss, Gss = SS_values tau_b, delta_tau = biz_tax_params if baseline_spending==False: budget_balance, ALPHA_T, ALPHA_G, tG1, tG2, rho_G, debt_ratio_ss = fiscal_params else: budget_balance, ALPHA_T, ALPHA_G, tG1, tG2, rho_G, debt_ratio_ss, T_Hbaseline, Gbaseline = fiscal_params print 'Government spending breakpoints are tG1: ', tG1, '; and tG2:', tG2 TPI_FIG_DIR = output_dir # Initialize guesses at time paths # Make array of initial guesses for labor supply and savings domain = np.linspace(0, T, T) 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) 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 = guesses_b#np.zeros((T + S, S, J)) n_mat = guesses_n#np.zeros((T + S, S, J)) ind = np.arange(S) L_init = np.ones((T+S,))*Lss B_init = np.ones((T+S,))*Bss L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L_init[:T] = firm.get_L(n_mat[:T], L_params) B_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') B_init[1:T] = household.get_K(b_mat[:T-1], B_params) B_init[0] = B0 if small_open == False: if budget_balance: K_init = B_init else: K_init = B_init * Kss/Bss else: K_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) K_init = firm.get_K(L_init, tpi_firm_r, K_params) K = K_init # if np.any(K < 0): # print 'K_init has negative elements. Setting them positive to prevent NAN.' # K[:T] = np.fmax(K[:T], 0.05*B[:T]) L = L_init B = B_init Y_params = (Z, gamma, epsilon) Y = firm.get_Y(K, L, Y_params) w_params = (Z, gamma, epsilon) w = firm.get_w(Y, L, w_params) if small_open == False: r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) r = firm.get_r(Y, K, r_params) else: r = tpi_hh_r 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) if budget_balance: 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 REVENUE = T_H G = np.zeros(T + S) elif baseline_spending==False: T_H = ALPHA_T * Y elif baseline_spending==True: T_H = T_Hbaseline T_H_new = T_H # Need to set T_H_new for later reference G = Gbaseline G_0 = Gbaseline[0] # Initialize some inputs # D = np.zeros(T + S) D = debt_ratio_ss*Y 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') tax_params = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) # print 'D/Y:', D[:T]/Y[:T] # print 'T/Y:', T_H[:T]/Y[:T] # print 'G/Y:', G[:T]/Y[:T] # print 'Int payments to GDP:', (r[:T]*D[:T])/Y[:T] # quit() TPIiter = 0 TPIdist = 10 PLOT_TPI = False report_tG1 = 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) D_plot = list(D) + list(np.ones(10) * Yss * debt_ratio_ss) plt.figure() plt.axhline( y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange( T + 10), D_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_D")) if report_tG1 is True: print '\tAt time tG1-1:' print '\t\tG = ', G[tG1-1] print '\t\tK = ', K[tG1-1] print '\t\tr = ', r[tG1-1] print '\t\tD = ', D[tG1-1] guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, K, 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) 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, :, :] #L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') # defined above L[:T] = firm.get_L(n_mat[:T], L_params) #B_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') # defined above B[1:T] = household.get_K(bmat_splus1[:T-1], B_params) if np.any(B) < 0: print 'B has negative elements. B[0:9]:', B[0:9] print 'B[T-2:T]:', B[T-2,T] if small_open == False: if budget_balance: K[:T] = B[:T] else: if baseline_spending == False: Y = T_H/ALPHA_T #SBF 3/3: This seems totally unnecessary as both these variables are defined above. # tax_params = np.zeros((T,S,J,etr_params.shape[2])) # for i in range(etr_params.shape[2]): # tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) # REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', # tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) # define above REVENUE = np.array(list(tax.revenue(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), Y[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S) D_0 = initial_debt * Y[0] other_dg_params = (T, r, g_n_vector, g_y) if baseline_spending==False: G_0 = ALPHA_G[0] * Y[0] dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0) Dnew, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending) K[:T] = B[:T] - Dnew[:T] if np.any(K < 0): print 'K has negative elements. Setting them positive to prevent NAN.' K[:T] = np.fmax(K[:T], 0.05*B[:T]) else: # K_params previously set to = (Z, gamma, epsilon, delta, tau_b, delta_tau) K[:T] = firm.get_K(L[:T], tpi_firm_r[:T], K_params) Y_params = (Z, gamma, epsilon) Ynew = firm.get_Y(K[:T], L[:T], Y_params) Y = Ynew w_params = (Z, gamma, epsilon) wnew = firm.get_w(Ynew[:T], L[:T], w_params) if small_open == False: r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) rnew = firm.get_r(Ynew[:T], K[:T], r_params) else: rnew = r.copy() print 'Y and T_H: ', Y[3], T_H[3] # omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0) # defined above # 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') # defined above 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) # tax_params = np.zeros((T,S,J,etr_params.shape[2])) # for i in range(etr_params.shape[2]): # tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) # REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', # tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) # defined above REVENUE = np.array(list(tax.revenue(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), Y[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S) if budget_balance: T_H_new = REVENUE elif baseline_spending==False: T_H_new = ALPHA_T[:T] * Y[:T] # If baseline_spending==True, no need to update T_H, which remains fixed. if small_open==True and budget_balance==False: # Loop through years to calculate debt and gov't spending. This is done earlier when small_open=False. D_0 = initial_debt * Y[0] other_dg_params = (T, r, g_n_vector, g_y) if baseline_spending==False: G_0 = ALPHA_G[0] * Y[0] dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0) Dnew, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending) w[:T] = utils.convex_combo(wnew[:T], w[:T], nu) r[:T] = utils.convex_combo(rnew[:T], r[:T], nu) BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu) # D[:T] = utils.convex_combo(Dnew[:T], D[:T], nu) D = Dnew Y[:T] = utils.convex_combo(Ynew[:T], Y[:T], nu) if baseline_spending==False: T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu) guesses_b = utils.convex_combo(b_mat, guesses_b, nu) guesses_n = utils.convex_combo(n_mat, guesses_n, nu) print 'r diff: ', (rnew[:T]-r[:T]).max(), (rnew[:T]-r[:T]).min() print 'w diff: ', (wnew[:T]-w[:T]).max(), (wnew[:T]-w[:T]).min() print 'BQ diff: ', (BQnew[:T]-BQ[:T]).max(), (BQnew[:T]-BQ[:T]).min() print 'T_H diff: ', (T_H_new[:T]-T_H[:T]).max(), (T_H_new[:T]-T_H[:T]).min() if baseline_spending==False: 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(wnew[:T], w[:T])) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() else: 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(wnew[:T], w[:T])) + list(np.abs(T_H[:T]))).max() else: # 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(wnew[:T], w[:T])) + list(utils.pct_diff_func(Dnew[:T], D[:T]))).max() 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(wnew[:T], w[:T])) + list(utils.pct_diff_func(Ynew[:T], Y[: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 'Iteration:', TPIiter print '\tDistance:', TPIdist # print 'D/Y:', (D[:T]/Ynew[:T]).max(), (D[:T]/Ynew[:T]).min(), np.median(D[:T]/Ynew[:T]) # print 'T/Y:', (T_H_new[:T]/Ynew[:T]).max(), (T_H_new[:T]/Ynew[:T]).min(), np.median(T_H_new[:T]/Ynew[:T]) # print 'G/Y:', (G[:T]/Ynew[:T]).max(), (G[:T]/Ynew[:T]).min(), np.median(G[:T]/Ynew[:T]) # print 'Int payments to GDP:', ((r[:T]*D[:T])/Ynew[:T]).max(), ((r[:T]*D[:T])/Ynew[:T]).min(), np.median((r[:T]*D[:T])/Ynew[:T]) # # print 'D/Y:', (D[:T]/Ynew[:T]) # print 'T/Y:', (T_H_new[:T]/Ynew[:T]) # print 'G/Y:', (G[:T]/Ynew[:T]) # # print 'deficit: ', REVENUE[:T] - T_H_new[:T] - G[:T] # Loop through years to calculate debt and gov't spending. The re-assignment of G0 & D0 is necessary because Y0 may change in the TPI loop. if budget_balance == False: D_0 = initial_debt * Y[0] other_dg_params = (T, r, g_n_vector, g_y) if baseline_spending==False: G_0 = ALPHA_G[0] * Y[0] dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0) D, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending) # Solve HH problem in inner loop guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, K, 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, :, :] #L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') # defined above L[:T] = firm.get_L(n_mat[:T], L_params) #B_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') # defined above B[1:T] = household.get_K(bmat_splus1[:T-1], B_params) if small_open == False: K[:T] = B[:T] - D[:T] else: # K_params previously set to = (Z, gamma, epsilon, delta, tau_b, delta_tau) K[:T] = firm.get_K(L[:T], tpi_firm_r[:T], K_params) # Y_params previously set to = (Z, gamma, epsilon) Ynew = firm.get_Y(K[:T], L[:T], Y_params) # testing for change in Y ydiff = Ynew[:T] - Y[:T] ydiff_max = np.amax(np.abs(ydiff)) print 'ydiff_max = ', ydiff_max w_params = (Z, gamma, epsilon) wnew = firm.get_w(Ynew[:T], L[:T], w_params) if small_open == False: # r_params previously set to = (Z, gamma, epsilon, delta, tau_b, delta_tau) rnew = firm.get_r(Ynew[:T], K[:T], r_params) else: rnew = r # Note: previously, Y was not reassigned to equal Ynew at this point. Y = Ynew[:] # 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) # tax_params = np.zeros((T,S,J,etr_params.shape[2])) # for i in range(etr_params.shape[2]): # tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) # REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', # tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) REVENUE = np.array(list(tax.revenue(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), Ynew[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S) 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) if budget_balance==False: D_0 = initial_debt * Y[0] other_dg_params = (T, r, g_n_vector, g_y) if baseline_spending==False: G_0 = ALPHA_G[0] * Y[0] dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0) D, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending) if small_open == False: 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] else: #InvestmentPlaceholder = np.zeros(bmat_splus1[:T].shape) #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 = (1+g_n_vector[:T])*np.exp(g_y)*K[1:T+1] - (1.0 - delta) * K[:T] #firm.get_I(InvestmentPlaceholder, K[1:T+1], K[:T], I_params) BI_params = (0.0, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI') BI = firm.get_I(bmat_splus1[:T], B[1:T+1], B[:T], BI_params) new_borrowing = D[1:T]*(1+g_n_vector[1:T])*np.exp(g_y) - D[:T-1] rc_error = Y[:T-1] + new_borrowing - (C[:T-1] + BI[:T-1] + G[:T-1] ) + (tpi_hh_r[:T-1] * B[:T-1] - (delta + tpi_firm_r[:T-1])*K[:T-1] - tpi_hh_r[:T-1]*D[:T-1]) #print 'Y(T-1):', Y[T-1], '\n','C(T-1):', C[T-1], '\n','K(T-1):', K[T-1], '\n','B(T-1):', B[T-1], '\n','BI(T-1):', BI[T-1], '\n','I(T-1):', I[T-1] rce_max = np.amax(np.abs(rc_error)) print 'Max absolute value resource constraint error:', rce_max print'Checking time path for violations of constraints.' 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, 'REVENUE': REVENUE, 'T_H': T_H, 'G': G, 'D': D, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 'c_path': c_path, 'tax_path': tax_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure} tpi_dir = os.path.join(output_dir, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb")) macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w, 'tax_path': tax_path} growth = (1+g_n_vector)*np.exp(g_y) with open('TPI_output.csv', 'wb') as csvfile: tpiwriter = csv.writer(csvfile) tpiwriter.writerow(Y) tpiwriter.writerow(D) tpiwriter.writerow(REVENUE) tpiwriter.writerow(G) tpiwriter.writerow(T_H) tpiwriter.writerow(C) tpiwriter.writerow(K) tpiwriter.writerow(I) tpiwriter.writerow(r) if small_open == True: tpiwriter.writerow(B) tpiwriter.writerow(BI) tpiwriter.writerow(new_borrowing) tpiwriter.writerow(growth) tpiwriter.writerow(rc_error) tpiwriter.writerow(ydiff) if np.any(G) < 0: print 'Government spending is negative along transition path to satisfy budget' if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS : raise RuntimeError("Transition path equlibrium not found (TPIdist)") if ((np.any(np.absolute(rc_error) >= mindist_TPI)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError("Transition path equlibrium not found (rc_error)") 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 (eulers)") # Non-stationary output # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path, # 'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path, # 'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path, # 'w_ns_path': w_ns_path} return output, macro_output
def inner_loop(outer_loop_vars, params, baseline, baseline_spending=False): ''' This function solves for the inner loop of the SS. That is, given the guesses of the outer loop variables (r, w, Y, factor) this function solves the households' problems in the SS. Inputs: r = [T,] vector, interest rate w = [T,] vector, wage rate b = [T,S,J] array, wealth holdings n = [T,S,J] array, labor supply BQ = [T,J] vector, bequest amounts factor = scalar, model income scaling factor Y = [T,] vector, lump sum transfer amount(s) Functions called: euler_equation_solver() household.get_K() firm.get_L() firm.get_Y() firm.get_r() firm.get_w() household.get_BQ() tax.replacement_rate_vals() tax.revenue() Objects in function: Returns: euler_errors, bssmat, nssmat, new_r, new_w new_T_H, new_factor, new_BQ ''' # unpack variables and parameters pass to function ss_params, income_tax_params, chi_params, small_open_params = params J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, tau_bq, rho, omega_SS, budget_balance, \ alpha_T, debt_ratio_ss, tau_b, delta_tau,\ lambdas, imm_rates, e, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params chi_b, chi_n = chi_params small_open, ss_firm_r, ss_hh_r = small_open_params if budget_balance: bssmat, nssmat, r, w, T_H, factor = outer_loop_vars else: bssmat, nssmat, r, w, Y, T_H, factor = outer_loop_vars euler_errors = np.zeros((2*S,J)) for j in xrange(J): # Solve the euler equations if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j-1], nssmat[:, j-1]) euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\ j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\ analytical_mtrs, etr_params, mtrx_params,\ mtry_params] [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9, args=euler_params, xtol=MINIMIZER_TOL, full_output=True) euler_errors[:,j] = infodict['fvec'] # print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max() bssmat[:, j] = solutions[:S] nssmat[:, j] = solutions[S:] L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS') L = firm.get_L(nssmat, L_params) if small_open == False: K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS') B = household.get_K(bssmat, K_params) if budget_balance: K = B else: K = B - debt_ratio_ss*Y else: K_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) K = firm.get_K(L, ss_firm_r, K_params) # Y_params = (alpha, Z) Y_params = (Z, gamma, epsilon) new_Y = firm.get_Y(K, L, Y_params) #print 'inner K, L, Y: ', K, L, new_Y if budget_balance: Y = new_Y if small_open == False: r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) new_r = firm.get_r(Y, K, r_params) else: new_r = ss_hh_r w_params = (Z, gamma, epsilon) new_w = firm.get_w(Y, L, w_params) print 'inner factor prices: ', new_r, new_w b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * omega_SS.reshape(S, 1) * lambdas.reshape(1, J)).sum() if baseline: new_factor = mean_income_data / average_income_model else: new_factor = factor BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') new_BQ = household.get_BQ(new_r, bssmat, BQ_params) theta_params = (e, S, retire) theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params) if budget_balance: T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) new_T_H = tax.revenue(new_r, new_w, b_s, nssmat, new_BQ, new_Y, L, K, factor, T_H_params) elif baseline_spending: new_T_H = T_H else: new_T_H = alpha_T*new_Y return euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_Y, new_factor, new_BQ, average_income_model
def SS_solver(b_guess_init, n_guess_init, wguess, rguess, T_Hguess, factorguess, chi_n, chi_b, tax_params, params, iterative_params, tau_bq, rho, lambdas, weights, e, fsolve_flag=False): ''' Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using an iterative method similar to TPI. Inputs: b_guess_init = guesses for b (SxJ array) n_guess_init = guesses for n (SxJ array) wguess = guess for wage rate (scalar) rguess = guess for rental rate (scalar) T_Hguess = guess for lump sum tax (scalar) factorguess = guess for scaling factor to dollars (scalar) chi_n = chi^n_s (Sx1 array) chi_b = chi^b_j (Jx1 array) params = list of parameters (list) iterative_params = list of parameters that determine the convergence of the while loop (list) tau_bq = bequest tax rate (Jx1 array) rho = mortality rates (Sx1 array) lambdas = ability weights (Jx1 array) weights = population weights (Sx1 array) e = ability levels (SxJ array) Outputs: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 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 maxiter, mindist_SS = iterative_params # Rename the inputs w = wguess r = rguess T_H = T_Hguess factor = factorguess bssmat = b_guess_init nssmat = n_guess_init dist = 10 iteration = 0 dist_vec = np.zeros(maxiter) if fsolve_flag == True: maxiter = 1 while (dist > mindist_SS) and (iteration < maxiter): # Solve for the steady state levels of b and n, given w, r, T_H and # factor for j in xrange(J): # Solve the euler equations if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j - 1], nssmat[:, j - 1]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) print 'Max Euler errors: ', np.absolute(infodict['fvec']).max() bssmat[:, j] = solutions[:S] nssmat[:, j] = solutions[S:] # print np.array(Euler_equation_solver(np.append(bssmat[:, j], # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n, # theta, tau_bq, rho, lambdas, e)).max() K = household.get_K(bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS') L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J), 'SS') Y = firm.get_Y(K, L, params) new_r = firm.get_r(Y, K, params) new_w = firm.get_w(Y, L, params) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * weights.reshape(S, 1) * lambdas.reshape(1, J)).sum() new_factor = mean_income_data / average_income_model new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J, weights.reshape(S, 1), lambdas) # lump_sum_tax_params = (a_etr_income, b_etr_income, c_etr_income, d_etr_income, # e_etr_income, f_etr_income, min_x_etr_income, max_x_etr_income, # min_y_etr_income, max_y_etr_income) new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ, lambdas.reshape(1, J), factor, weights.reshape(S, 1), 'SS', etr_params, params, theta, tau_bq) r = utils.convex_combo(new_r, r, nu) w = utils.convex_combo(new_w, w, nu) factor = utils.convex_combo(new_factor, factor, nu) T_H = utils.convex_combo(new_T_H, T_H, nu) if T_H != 0: dist = np.array([utils.perc_dif_func(new_r, r)] + [utils.perc_dif_func(new_w, w)] + [utils.perc_dif_func(new_T_H, T_H)] + [utils.perc_dif_func(new_factor, factor)]).max() else: # If T_H is zero (if there are no taxes), a percent difference # will throw NaN's, so we use an absoluate difference dist = np.array([utils.perc_dif_func(new_r, r)] + [utils.perc_dif_func(new_w, w)] + [abs(new_T_H - T_H)] + [utils.perc_dif_func(new_factor, factor)]).max() dist_vec[iteration] = dist # Similar to TPI: if the distance between iterations increases, then # decrease the value of nu to prevent cycling if iteration > 10: if dist_vec[iteration] - dist_vec[iteration - 1] > 0: nu /= 2.0 print 'New value of nu:', nu iteration += 1 print "Iteration: %02d" % iteration, " Distance: ", dist eul_errors = np.ones(J) b_mat = np.zeros((S, J)) n_mat = np.zeros((S, J)) # Given the final w, r, T_H and factor, solve for the SS b and n (if you # don't do a final fsolve, there will be a slight mismatch, # with high euler errors) for j in xrange(J): guesses = np.append(bssmat[:, j], nssmat[:, j]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions1, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) eul_errors[j] = np.array(infodict['fvec']).max() print 'Max Euler errors: ', np.absolute(infodict['fvec']).max() b_mat[:, j] = solutions1[:S] n_mat[:, j] = solutions1[S:] print 'SS fsolve euler error:', eul_errors.max() solutions = np.append(b_mat.flatten(), n_mat.flatten()) other_vars = np.array([w, r, factor, T_H]) solutions = np.append(solutions, other_vars) return solutions
def SS_fsolve(guesses, b_guess_init, n_guess_init, chi_n, chi_b, tax_params, params, iterative_params, tau_bq, rho, lambdas, weights, e): ''' Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using an iterative method similar to TPI. Inputs: b_guess_init = guesses for b (SxJ array) n_guess_init = guesses for n (SxJ array) wguess = guess for wage rate (scalar) rguess = guess for rental rate (scalar) T_Hguess = guess for lump sum tax (scalar) factorguess = guess for scaling factor to dollars (scalar) chi_n = chi^n_s (Sx1 array) chi_b = chi^b_j (Jx1 array) params = list of parameters (list) iterative_params = list of parameters that determine the convergence of the while loop (list) tau_bq = bequest tax rate (Jx1 array) rho = mortality rates (Sx1 array) lambdas = ability weights (Jx1 array) weights = population weights (Sx1 array) e = ability levels (SxJ array) Outputs: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 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 maxiter, mindist_SS = iterative_params # Rename the inputs w = guesses[0] r = guesses[1] T_H = guesses[2] factor = guesses[3] bssmat = b_guess_init nssmat = n_guess_init # Solve for the steady state levels of b and n, given w, r, T_H and # factor for j in xrange(J): # Solve the euler equations if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j - 1], nssmat[:, j - 1]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) print 'Max Euler errors: ', np.absolute(infodict['fvec']).max() bssmat[:, j] = solutions[:S] nssmat[:, j] = solutions[S:] # print np.array(Euler_equation_solver(np.append(bssmat[:, j], # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n, # theta, tau_bq, rho, lambdas, e)).max() K = household.get_K(bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS') L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J), 'SS') Y = firm.get_Y(K, L, params) new_r = firm.get_r(Y, K, params) new_w = firm.get_w(Y, L, params) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * weights.reshape(S, 1) * lambdas.reshape(1, J)).sum() new_factor = mean_income_data / average_income_model new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J, weights.reshape(S, 1), lambdas) new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ, lambdas.reshape(1, J), factor, weights.reshape(S, 1), 'SS', etr_params, params, theta, tau_bq) error1 = new_w - w error2 = new_r - r error3 = new_T_H - T_H error4 = new_factor - factor print 'errors: ', error1, error2, error3, error4 print 'T_H: ', new_T_H print 'factor: ', new_factor # Check and punish violations if r <= 0: error1 += 1e9 #if r > 1: # error1 += 1e9 if w <= 0: error2 += 1e9 return [error1, error2, error3, error4]
def inner_loop(outer_loop_vars, params): ''' This function solves for the inner loop of the SS. That is, given the guesses of the outer loop variables (r, w, T_H, factor) this function solves the households' problems in the SS. Inputs: r = [T,] vector, interest rate w = [T,] vector, wage rate b = [T,S,J] array, wealth holdings n = [T,S,J] array, labor supply BQ = [T,J] vector, bequest amounts factor = scalar, model income scaling factor T_H = [T,] vector, lump sum transfer amount(s) Functions called: euler_equation_solver() household.get_K() firm.get_L() firm.get_Y() firm.get_r() firm.get_w() household.get_BQ() tax.replacement_rate_vals() tax.get_lump_sum() Objects in function: Returns: euler_errors, bssmat, nssmat, new_r, new_w new_T_H, new_factor, new_BQ ''' # unpack variables and parameters pass to function bssmat, nssmat, r, w, T_H, factor = outer_loop_vars ss_params, income_tax_params, chi_params = params J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, e, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params chi_b, chi_n = chi_params euler_errors = np.zeros((2*S,J)) for j in xrange(J): # Solve the euler equations if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j-1], nssmat[:, j-1]) euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\ j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\ analytical_mtrs, etr_params, mtrx_params,\ mtry_params] [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9, args=euler_params, xtol=MINIMIZER_TOL, full_output=True) euler_errors[:,j] = infodict['fvec'] print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max() bssmat[:, j] = solutions[:S] nssmat[:, j] = solutions[S:] K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS') K = household.get_K(bssmat, K_params) L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS') L = firm.get_L(nssmat, L_params) Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) new_r = firm.get_r(Y, K, r_params) new_w = firm.get_w(Y, L, alpha) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * omega_SS.reshape(S, 1) * lambdas.reshape(1, J)).sum() new_factor = mean_income_data / average_income_model BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') new_BQ = household.get_BQ(new_r, bssmat, BQ_params) theta_params = (e, J, omega_SS.reshape(S, 1), lambdas) theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params) T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params) return euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_factor, new_BQ, average_income_model
def inner_loop(outer_loop_vars, params, baseline, baseline_spending=False): ''' This function solves for the inner loop of the SS. That is, given the guesses of the outer loop variables (r, w, Y, factor) this function solves the households' problems in the SS. Inputs: r = [T,] vector, interest rate w = [T,] vector, wage rate b = [T,S,J] array, wealth holdings n = [T,S,J] array, labor supply BQ = [T,J] vector, bequest amounts factor = scalar, model income scaling factor Y = [T,] vector, lump sum transfer amount(s) Functions called: euler_equation_solver() aggr.get_K() aggr.get_L() firm.get_Y() firm.get_r() firm.get_w() aggr.get_BQ() tax.replacement_rate_vals() aggr.revenue() Objects in function: Returns: euler_errors, bssmat, nssmat, new_r, new_w new_T_H, new_factor, new_BQ ''' # unpack variables and parameters pass to function ss_params, income_tax_params, chi_params, small_open_params = params J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, tau_bq, rho, omega_SS, budget_balance, \ alpha_T, debt_ratio_ss, tau_b, delta_tau,\ lambdas, imm_rates, e, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params chi_b, chi_n = chi_params small_open, ss_firm_r, ss_hh_r = small_open_params if budget_balance: bssmat, nssmat, r, w, T_H, factor = outer_loop_vars else: bssmat, nssmat, r, w, Y, T_H, factor = outer_loop_vars euler_errors = np.zeros((2 * S, J)) for j in xrange(J): # Solve the euler equations if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j - 1], nssmat[:, j - 1]) euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\ j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\ analytical_mtrs, etr_params, mtrx_params,\ mtry_params] [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9, args=euler_params, xtol=MINIMIZER_TOL, full_output=True) euler_errors[:, j] = infodict['fvec'] # print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max() bssmat[:, j] = solutions[:S] nssmat[:, j] = solutions[S:] L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS') L = aggr.get_L(nssmat, L_params) if small_open == False: K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS') B = aggr.get_K(bssmat, K_params) if budget_balance: K = B else: K = B - debt_ratio_ss * Y else: K_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) K = firm.get_K(L, ss_firm_r, K_params) # Y_params = (alpha, Z) Y_params = (Z, gamma, epsilon) new_Y = firm.get_Y(K, L, Y_params) #print 'inner K, L, Y: ', K, L, new_Y if budget_balance: Y = new_Y if small_open == False: r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) new_r = firm.get_r(Y, K, r_params) else: new_r = ss_hh_r w_params = (Z, gamma, epsilon) new_w = firm.get_w(Y, L, w_params) print 'inner factor prices: ', new_r, new_w b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * omega_SS.reshape(S, 1) * lambdas.reshape(1, J)).sum() if baseline: new_factor = mean_income_data / average_income_model else: new_factor = factor BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') new_BQ = aggr.get_BQ(new_r, bssmat, BQ_params) theta_params = (e, S, retire) theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params) if budget_balance: T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) new_T_H = aggr.revenue(new_r, new_w, b_s, nssmat, new_BQ, new_Y, L, K, factor, T_H_params) elif baseline_spending: new_T_H = T_H else: new_T_H = alpha_T * new_Y return euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_Y, new_factor, new_BQ, average_income_model
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 create_tpi_params(analytical_mtrs, etr_params, mtrx_params, mtry_params, b_ellipse, upsilon, J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, tau_payroll, retire, mean_income_data, run_params, input_dir="./OUTPUT", baseline_dir="./OUTPUT", **kwargs): globals().update(run_params) ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl") variables = pickle.load(open(ss_init, "rb")) for key in variables: globals()[key] = variables[key] ''' ------------------------------------------------------------------------ Set factor and initial capital stock to SS from baseline ------------------------------------------------------------------------ ''' baseline_ss = os.path.join(baseline_dir, "SSinit/ss_init_vars.pkl") ss_baseline_vars = pickle.load(open(baseline_ss, "rb")) factor = ss_baseline_vars['factor_ss'] #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas initial_b= ss_baseline_vars['bssmat_splus1'] ''' ------------------------------------------------------------------------ Set other parameters and initial values ------------------------------------------------------------------------ ''' # Make a vector of all one dimensional parameters, to be used in the # following functions # Put income tax parameters in a tuple # Assumption here is that tax parameters of last year of budget # window continue forever and so will be SS values etr_params_TP = np.zeros((S,T+S,etr_params.shape[2])) etr_params_TP[:,:BW,:] = etr_params etr_params_TP[:,BW:,:] = np.reshape(etr_params[:,BW-1,:],(S,1,etr_params.shape[2])) mtrx_params_TP = np.zeros((S,T+S,mtrx_params.shape[2])) mtrx_params_TP[:,:BW,:] = mtrx_params mtrx_params_TP[:,BW:,:] = np.reshape(mtrx_params[:,BW-1,:],(S,1,mtrx_params.shape[2])) mtry_params_TP = np.zeros((S,T+S,mtry_params.shape[2])) mtry_params_TP[:,:BW,:] = mtry_params mtry_params_TP[:,BW:,:] = np.reshape(mtry_params[:,BW-1,:],(S,1,mtry_params.shape[2])) income_tax_params = (analytical_mtrs, etr_params_TP, mtrx_params_TP, mtry_params_TP) wealth_tax_params = [h_wealth, p_wealth, m_wealth] ellipse_params = [b_ellipse, upsilon] parameters = [J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data] + wealth_tax_params + ellipse_params N_tilde = omega.sum(1) omega_stationary = omega / N_tilde.reshape(T + S, 1) initial_n = nssmat # Get an initial distribution of capital with the initial population # distribution K0 = household.get_K(initial_b, omega_stationary[ 0].reshape(S, 1), lambdas, g_n_vector[0], 'SS') b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1])) b_splus1init = initial_b L0 = firm.get_L(e, initial_n, omega_stationary[ 0].reshape(S, 1), lambdas, 'SS') Y0 = firm.get_Y(K0, L0, parameters) w0 = firm.get_w(Y0, L0, parameters) r0 = firm.get_r(Y0, K0, parameters) BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape( S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[ 0].reshape(S, 1), 'SS', etr_params_TP[:,0,:], parameters, theta, tau_bq) tax0_params = (J, S, retire, np.tile(np.reshape(etr_params_TP[:,0,:],(S,1,etr_params_TP.shape[2])),(1,J,1)), h_wealth, p_wealth, m_wealth, tau_payroll) tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, T_H_0, None, 'SS', False, tax0_params, theta, tau_bq) c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape( 1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0) return (income_tax_params, wealth_tax_params, ellipse_params, parameters, N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n)
def run_time_path_iteration(Kss, Lss, Yss, BQss, theta, parameters, g_n_vector, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, chi_n, get_baseline=False, output_dir="./OUTPUT", **kwargs): TPI_FIG_DIR = output_dir # Initialize Time paths domain = np.linspace(0, T, T) Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss Kinit[-1] = Kss Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss)) Linit = np.ones(T + S) * Lss Yinit = firm.get_Y(Kinit, Linit, parameters) winit = firm.get_w(Yinit, Linit, parameters) rinit = firm.get_r(Yinit, Kinit, parameters) BQinit = np.zeros((T + S, J)) for j in xrange(J): BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQinit = np.array(BQinit) T_H_init = np.ones(T + S) * T_Hss # Make array of initial guesses 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) 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) TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss) Lpath_TPI = list(Linit) + list(np.ones(10) * Lss) # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: plt.figure() plt.axhline(y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange(T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array( opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13)) # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6: # print 'minidoughnut:', # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, # factor_ss, j, parameters, theta, tau_bq)).max() for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) solutions = opt.fsolve( Steady_state_TPI_solver, list(b_guesses_to_use) + list(n_guesses_to_use), args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6: # print 's-loop:', # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, # theta, tau_bq, rho, lambdas, e, initial_b, chi_b, # chi_n))).max() for t in xrange(0, T): b_guesses_to_use = .75 * \ np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) solutions = opt.fsolve( Steady_state_TPI_solver, list(b_guesses_to_use) + list(n_guesses_to_use), args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs( Steady_state_TPI_solver(inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') Ynew = firm.get_Y(Kinit, Linit, parameters) wnew = firm.get_w(Ynew, Linit, parameters) rnew = firm.get_r(Ynew, Kinit, parameters) # the following needs a g_n term BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] T_H_new = np.array( list( tax.get_lump_sum( rnew.reshape(T, 1, 1), bmat_s, wnew.reshape(T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQnew.reshape(T, 1, J), lambdas.reshape(1, 1, J), factor_ss, omega_stationary[:T]. reshape(T, S, 1), 'TPI', parameters, theta, tau_bq)) + [T_Hss] * S) winit[:T] = utils.convex_combo(wnew, winit[:T], parameters) rinit[:T] = utils.convex_combo(rnew, rinit[:T], parameters) BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], parameters) T_H_init[:T] = utils.convex_combo(T_H_new[:T], T_H_init[:T], parameters) guesses_b = utils.convex_combo(b_mat, guesses_b, parameters) guesses_n = utils.convex_combo(n_mat, guesses_n, parameters) if T_H_init.all() != 0: TPIdist = np.array( list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list(utils.perc_dif_func(wnew, winit[:T])) + list(utils.perc_dif_func(T_H_new, T_H_init))).max() else: TPIdist = np.array( list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list(utils.perc_dif_func(wnew, winit[:T])) + list(np.abs(T_H_new, T_H_init))).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 print 'Computing final solutions' # As in SS, you need the final distributions of b and n to match the final # w, r, BQ, etc. Otherwise the euler errors are large. You need one more # fsolve. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array( opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13)) for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) solutions = opt.fsolve( Steady_state_TPI_solver, list(b_guesses_to_use) + list(n_guesses_to_use), args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec for t in xrange(0, T): b_guesses_to_use = .75 * np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) solutions = opt.fsolve( Steady_state_TPI_solver, list(b_guesses_to_use) + list(n_guesses_to_use), args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs( Steady_state_TPI_solver(inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) b_mat[0, :, :] = initial_b ''' ------------------------------------------------------------------------ Generate variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' Kpath_TPI = np.array(list(Kinit) + list(np.ones(10) * Kss)) Lpath_TPI = np.array(list(Linit) + list(np.ones(10) * Lss)) BQpath_TPI = np.array(list(BQinit) + list(np.ones((10, J)) * BQss)) b_s = np.zeros((T, S, J)) b_s[:, 1:, :] = b_mat[:T, :-1, :] b_splus1 = np.zeros((T, S, J)) b_splus1[:, :, :] = b_mat[1:T + 1, :, :] tax_path = tax.total_taxes(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQinit[:T, :].reshape(T, 1, J), lambdas, factor_ss, T_H_init[:T].reshape(T, 1, 1), None, 'TPI', False, parameters, theta, tau_bq) c_path = household.get_cons(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQinit[:T].reshape(T, 1, J), lambdas.reshape(1, 1, J), b_splus1, parameters, tax_path) Y_path = firm.get_Y(Kpath_TPI[:T], Lpath_TPI[:T], parameters) C_path = household.get_C(c_path, omega_stationary[:T].reshape(T, S, 1), lambdas, 'TPI') I_path = firm.get_I(Kpath_TPI[1:T + 1], Kpath_TPI[:T], delta, g_y, g_n_vector[:T]) print 'Resource Constraint Difference:', Y_path - C_path - I_path 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, parameters) eul_savings = euler_errors[:, :S, :].max(1).max(1) eul_laborleisure = euler_errors[:, S:, :].max(1).max(1) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Kpath_TPI': Kpath_TPI, 'b_mat': b_mat, 'c_path': c_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI, 'n_mat': n_mat, 'rinit': rinit, 'Yinit': Yinit, 'T_H_init': T_H_init, 'tax_path': tax_path, 'winit': winit } if get_baseline: tpi_init_dir = os.path.join(output_dir, "TPIinit") utils.mkdirs(tpi_init_dir) tpi_init_vars = os.path.join(tpi_init_dir, "TPIinit_vars.pkl") pickle.dump(output, open(tpi_init_vars, "wb")) else: tpi_dir = os.path.join(output_dir, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb"))
def solve_tp(g_n_path, omega_S_preTP, rho_s, imm_rates_path, omega_SS, omega_path_S, params): ''' Solves for the time path equilibrium using TPI ''' # Missing some elements of params b_ss, r_ss, n_s, r_11, alpha, A, delta, beta, sigma, T, S = params dist = 8.0 mindist = 1e-08 maxiter = 300 tpi_iter = 0 xi = 0.2 while dist > mindist and tpi_iter < maxiter: # Define paths b_11 = 1.1 * b_ss BQ_params = (g_n_path[0], omega_S_preTP, rho_s) K_params = (g_n_path[0], omega_S_preTP, imm_rates_path[0, :]) BQ_11 = agg.get_BQ(b_11, r_11, BQ_params, method = "TPI") BQ_ss = agg.get_BQ(b_ss, r_ss, BQ_params, method = "SS") K_11 = agg.get_K(b_11, K_params) BQpath_init = np.zeros(T + S - 1) BQpath_init[:T] = np.linspace(BQ_11, BQ_ss, T) BQpath_init[T:] = BQ_ss L_ss = agg.get_L(n_s, omega_SS) r_11 = firm.get_r(L_ss, K_11, alpha, A, delta) # I can't figure out how r_11 and r_path differ ''' Is r_11 an initial guess? Depending on how you're defining r_11, the arguments passed to the function call above and below will vary ''' r_path = firm.get_r(L_ss, K_11, alpha, A, delta) w_path = firm.get_w(r_path, alpha, A, delta) bmat = np.zeros((S - 1, T + S - 1)) # What is b_1 supposed to be? bmat[:, 0] = b_1 # Solve for households for p in range(2, S): b_guess = np.diagonal(bmat[S - p:, :p - 1]) b_init = bmat[S - p - 1, 0] b_params = (b_init, n_s[-p:], r_path[:p], w_path[:p], BQpath_init[:p], rho_s[-p:], beta, sigma) results_bp = opt.root(hh.FOCs, b_guess, args=(b_params)) b_solve_p = results_bp.x DiagMaskbp = np.eye(p - 1, dtype=bool) bmat[S - p:, 1:p] = DiagMaskbp * b_solve_p + bmat[S - p:, 1:p] for t in range(1, T + 1): b_guess = np.diagonal(bmat[:, t - 1:t + S - 2]) b_init = 0.0 b_params = (b_init, n_s, r_path[t - 1:t + S - 1], w_path[t - 1:t + S - 1], BQpath_init[t - 1:t + S - 1], rho_s, beta, sigma) results_bt = opt.root(hh.FOCs, b_guess, args=(b_params)) b_solve_t = results_bt.x DiagMaskbt = np.eye(S - 1, dtype=bool) bmat[:, t:t + S - 1] = (DiagMaskbt * b_solve_t + bmat[:, t:t + S - 1]) new_Kpath = np.zeros(T) new_Kpath[0] = K_11 new_Kpath[1:] = \ (1 / (omega_path_S[:T - 1, :-1]) * bmat[:, 1:T].T + imm_rates_path[:T - 1, 1:] * omega_path_S[:T - 1, 1:] * bmat[:, 1:T].T).sum(axis=1) new_BQpath = np.zeros(T) new_BQpath[0] = BQ_11 new_BQpath[1:] = \ ((1 + r_path[1:T]) / (rho_s[:-1]) * omega_path_S[:T - 1, :-1] * bmat[:, 1:T].T).sum(axis=1) dist = ((BQ_init - new_BQ) ** 2).sum() BQpath_init[:T] = xi * new_BQpath[:T] + (1 - xi) * BQpath_init[:T] # update iteration counter tpi_iter += 1 if tpi_iter < maxiter: print('The time path solved! ->', ' iter:', tpi_iter, ', dist: ', dist) else: print('The time path did not solve.') return [new_Kpath, new_BQpath]
def run_TPI(income_tax_params, tpi_params, iterative_params, initial_values, SS_values, 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, BQ_dist, 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 K0, b_sinit, b_splus1init, L0, Y0,\ w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n = initial_values Kss, Lss, rss, wss, BQss, T_Hss, bssmat_splus1, nssmat = SS_values TPI_FIG_DIR = output_dir # Initialize guesses at time paths domain = np.linspace(0, T, T) K_init = (-1 / (domain + 1)) * (Kss - K0) + Kss K_init[-1] = Kss K_init = np.array(list(K_init) + list(np.ones(S) * Kss)) L_init = np.ones(T + S) * Lss K = K_init L = L_init Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) w = firm.get_w(Y, L, alpha) r_params = (alpha, delta) r = firm.get_r(Y, K, r_params) BQ = np.zeros((T + S, J)) for j in xrange(J): BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQ = np.array(BQ) if T_Hss < 1e-13 and T_Hss > 0.0 : 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 # 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) 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) TPIiter = 0 TPIdist = 10 PLOT_TPI = False euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) 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")) # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. # 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,)) guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, K, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, theta, ind) # Solve HH problem in inner loop euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') K[:T] = household.get_K(b_mat[:T], 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) wnew = firm.get_w(Ynew[:T], L[:T], alpha) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) BQ_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat[:T,:,:], BQ_params) bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[1:T + 1, :, :] TH_tax_params = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): TH_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) T_H_params = (np.tile(e.reshape(1, S, J),(T,1,1)), BQ_dist, lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', TH_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) T_H_new = 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, T_H_params)) + [T_Hss] * S) w[:T] = utils.convex_combo(wnew[:T], w[:T], nu) r[:T] = utils.convex_combo(rnew[:T], r[:T], nu) BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu) T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu) 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(wnew[:T], w[:T])) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() else: 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(wnew[:T], w[:T])) + 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 if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS : raise RuntimeError("Transition path equlibrium not found") Y[:T] = Ynew # Solve HH problem in inner loop guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, K, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, theta, ind) euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) b_mat[0, :, :] = initial_b K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') K[:T] = household.get_K(b_mat[:T], K_params) # this is what old code does, but it's strange - why use # b_mat -- what is going on with initial period, etc. 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)), BQ_dist, 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), BQ_dist, lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(omega[:T].reshape(T,S,1), 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, g_n_vector[:T]) I = firm.get_I(K[1:T+1], K[:T], I_params) print 'Resource Constraint Difference:', Y[:T] - C[:T] - I[:T] 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 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") ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 'c_path': c_path, 'tax_path': tax_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure} tpi_dir = os.path.join(output_dir, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb")) macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w, 'tax_path': tax_path} # Non-stationary output # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path, # 'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path, # 'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path, # 'w_ns_path': w_ns_path} return output, macro_output
def run_time_path_iteration(Kss, Lss, Yss, BQss, theta, parameters, g_n_vector, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, chi_n, get_baseline=False, output_dir="./OUTPUT", **kwargs): TPI_FIG_DIR = output_dir # Initialize Time paths domain = np.linspace(0, T, T) Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss Kinit[-1] = Kss Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss)) Linit = np.ones(T + S) * Lss Yinit = firm.get_Y(Kinit, Linit, parameters) winit = firm.get_w(Yinit, Linit, parameters) rinit = firm.get_r(Yinit, Kinit, parameters) BQinit = np.zeros((T + S, J)) for j in xrange(J): BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQinit = np.array(BQinit) T_H_init = np.ones(T + S) * T_Hss # Make array of initial guesses 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) 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) TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss) Lpath_TPI = list(Linit) + list(np.ones(10) * Lss) # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: plt.figure() plt.axhline( y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange( T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13)) # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6: # print 'minidoughnut:', # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, # factor_ss, j, parameters, theta, tau_bq)).max() for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag( guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6: # print 's-loop:', # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, # theta, tau_bq, rho, lambdas, e, initial_b, chi_b, # chi_n))).max() for t in xrange(0, T): b_guesses_to_use = .75 * \ np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver( inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[ :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') Ynew = firm.get_Y(Kinit, Linit, parameters) wnew = firm.get_w(Ynew, Linit, parameters) rnew = firm.get_r(Ynew, Kinit, parameters) # the following needs a g_n term BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] T_H_new = np.array(list(tax.get_lump_sum(rnew.reshape(T, 1, 1), bmat_s, wnew.reshape( T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQnew.reshape(T, 1, J), lambdas.reshape( 1, 1, J), factor_ss, omega_stationary[:T].reshape(T, S, 1), 'TPI', parameters, theta, tau_bq)) + [T_Hss] * S) winit[:T] = utils.convex_combo(wnew, winit[:T], parameters) rinit[:T] = utils.convex_combo(rnew, rinit[:T], parameters) BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], parameters) T_H_init[:T] = utils.convex_combo( T_H_new[:T], T_H_init[:T], parameters) guesses_b = utils.convex_combo(b_mat, guesses_b, parameters) guesses_n = utils.convex_combo(n_mat, guesses_n, parameters) if T_H_init.all() != 0: TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list( utils.perc_dif_func(wnew, winit[:T])) + list(utils.perc_dif_func(T_H_new, T_H_init))).max() else: TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list( utils.perc_dif_func(wnew, winit[:T])) + list(np.abs(T_H_new, T_H_init))).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 print 'Computing final solutions' # As in SS, you need the final distributions of b and n to match the final # w, r, BQ, etc. Otherwise the euler errors are large. You need one more # fsolve. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13)) for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec for t in xrange(0, T): b_guesses_to_use = .75 * np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver( inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) b_mat[0, :, :] = initial_b ''' ------------------------------------------------------------------------ Generate variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' Kpath_TPI = np.array(list(Kinit) + list(np.ones(10) * Kss)) Lpath_TPI = np.array(list(Linit) + list(np.ones(10) * Lss)) BQpath_TPI = np.array(list(BQinit) + list(np.ones((10, J)) * BQss)) b_s = np.zeros((T, S, J)) b_s[:, 1:, :] = b_mat[:T, :-1, :] b_splus1 = np.zeros((T, S, J)) b_splus1[:, :, :] = b_mat[1:T + 1, :, :] tax_path = tax.total_taxes(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape( 1, S, J), n_mat[:T], BQinit[:T, :].reshape(T, 1, J), lambdas, factor_ss, T_H_init[:T].reshape(T, 1, 1), None, 'TPI', False, parameters, theta, tau_bq) c_path = household.get_cons(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape( 1, S, J), n_mat[:T], BQinit[:T].reshape(T, 1, J), lambdas.reshape(1, 1, J), b_splus1, parameters, tax_path) Y_path = firm.get_Y(Kpath_TPI[:T], Lpath_TPI[:T], parameters) C_path = household.get_C(c_path, omega_stationary[ :T].reshape(T, S, 1), lambdas, 'TPI') I_path = firm.get_I(Kpath_TPI[1:T + 1], Kpath_TPI[:T], delta, g_y, g_n_vector[:T]) print 'Resource Constraint Difference:', Y_path - C_path - I_path 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, parameters) eul_savings = euler_errors[:, :S, :].max(1).max(1) eul_laborleisure = euler_errors[:, S:, :].max(1).max(1) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = {'Kpath_TPI': Kpath_TPI, 'b_mat': b_mat, 'c_path': c_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI, 'n_mat': n_mat, 'rinit': rinit, 'Yinit': Yinit, 'T_H_init': T_H_init, 'tax_path': tax_path, 'winit': winit} if get_baseline: tpi_init_dir = os.path.join(output_dir, "TPIinit") utils.mkdirs(tpi_init_dir) tpi_init_vars = os.path.join(tpi_init_dir, "TPIinit_vars.pkl") pickle.dump(output, open(tpi_init_vars, "wb")) else: tpi_dir = os.path.join(output_dir, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb"))
def inner_loop(outer_loop_vars, params, baseline): ''' This function solves for the inner loop of the SS. That is, given the guesses of the outer loop variables (r, w, T_H, factor) this function solves the households' problems in the SS. Inputs: r = [T,] vector, interest rate w = [T,] vector, wage rate b = [T,S,J] array, wealth holdings n = [T,S,J] array, labor supply BQ = [T,J] vector, bequest amounts factor = scalar, model income scaling factor T_H = [T,] vector, lump sum transfer amount(s) Functions called: euler_equation_solver() household.get_K() firm.get_L() firm.get_Y() firm.get_r() firm.get_w() household.get_BQ() tax.replacement_rate_vals() tax.get_lump_sum() Objects in function: Returns: euler_errors, bssmat, nssmat, new_r, new_w new_T_H, new_factor, new_BQ ''' # unpack variables and parameters pass to function bssmat, nssmat, r, w, T_H, BQ, theta, factor = outer_loop_vars ss_params, income_tax_params, chi_params = params J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params chi_b, chi_n = chi_params # bssmat = START_VALUES['bssmat_splus1'] # nssmat = START_VALUES['nssmat'] cssmat = np.zeros((S, J)) euler_errors = np.zeros((2 * S, J)) for j in xrange(J): # Solve the euler equations if j == 0: b_Sp1_guess = bssmat[-1, j] else: b_Sp1_guess = bssmat[-1, j - 1] * 10 euler_params = [r, w, T_H, BQ, theta, factor, j, J, S, beta, sigma, ltilde, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\ j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\ analytical_mtrs, etr_params, mtrx_params,\ mtry_params] [solution, infodict, ier, message] = opt.fsolve(lc_error, b_Sp1_guess, args=euler_params, xtol=MINIMIZER_TOL, full_output=True) # [x0, r_out] = opt.bisect(lc_error, -1.0, 10.0, args=euler_params, xtol=MINIMIZER_TOL, full_output=True, disp=False) print 'j = ', j print 'b[0] error = ', infodict['fvec'] print 'message: ', message # print 'b[S]= ', x0 # print 'converged= ', r_out.converged b_out, nssmat[:, j], cssmat[:, j] = lifecycle_solver(solution, euler_params) bssmat[:, j] = b_out[1:] # print solutions # quit() # # euler_errors[:,j] = infodict['fvec'] # print 'j = ', j # print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max() # print 'bssmat: ', bssmat # print 'nssmat: ', nssmat # print 'cssmat: ', cssmat quit() K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS') K = household.get_K(bssmat, K_params) L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS') L = firm.get_L(nssmat, L_params) Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) new_r = firm.get_r(Y, K, r_params) new_w = firm.get_w(Y, L, alpha) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * omega_SS.reshape(S, 1) * lambdas.reshape(1, J)).sum() if baseline: new_factor = mean_income_data / average_income_model else: new_factor = factor BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') new_BQ = household.get_BQ(new_r, bssmat, BQ_params) theta_params = (e, S, J, omega_SS.reshape(S, 1), lambdas, retire) new_theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params) T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params) print 'Inner Loop Max Euler Error: ', (np.absolute(euler_errors)).max() # print 'K: ', K # print 'L: ', L #print 'bssmat: ', bssmat return euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_BQ, new_theta, new_factor, average_income_model
def run_TPI(income_tax_params, tpi_params, iterative_params, initial_values, SS_values, 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, e, retire, mean_income_data,\ factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params K0, b_sinit, b_splus1init, L0, Y0,\ w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n = initial_values Kss, Lss, rss, wss, BQss, T_Hss, bssmat_splus1, nssmat = SS_values TPI_FIG_DIR = output_dir # Initialize guesses at time paths domain = np.linspace(0, T, T) K_init = (-1 / (domain + 1)) * (Kss - K0) + Kss K_init[-1] = Kss K_init = np.array(list(K_init) + list(np.ones(S) * Kss)) L_init = np.ones(T + S) * Lss K = K_init L = L_init Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) w = firm.get_w(Y, L, alpha) r_params = (alpha, delta) r = firm.get_r(Y, K, r_params) BQ = np.zeros((T + S, J)) for j in xrange(J): BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQ = np.array(BQ) if T_Hss < 1e-13 and T_Hss > 0.0: 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 # 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) 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) TPIiter = 0 TPIdist = 10 PLOT_TPI = False euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) 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")) # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. # 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, )) guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, K, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, theta, ind) # Solve HH problem in inner loop euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') K[:T] = household.get_K(b_mat[:T], 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) wnew = firm.get_w(Ynew[:T], L[:T], alpha) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) BQ_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat[:T, :, :], BQ_params) bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[1:T + 1, :, :] TH_tax_params = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): TH_tax_params[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) T_H_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', TH_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) T_H_new = 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, T_H_params)) + [T_Hss] * S) w[:T] = utils.convex_combo(wnew[:T], w[:T], nu) r[:T] = utils.convex_combo(rnew[:T], r[:T], nu) BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu) T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu) 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(wnew[:T], w[:T])) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() else: 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(wnew[:T], w[:T])) + 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 if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS: raise RuntimeError("Transition path equlibrium not found") Y[:T] = Ynew # Solve HH problem in inner loop guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, K, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, theta, ind) euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) b_mat[0, :, :] = initial_b K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') K[:T] = household.get_K( b_mat[:T], K_params) # this is what old code does, but it's strange - why use # b_mat -- what is going on with initial period, etc. 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, g_n_vector[:T]) I = firm.get_I(K[1:T + 1], K[:T], I_params) print 'Resource Constraint Difference:', Y[:T] - C[:T] - I[:T] 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 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") ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 'c_path': c_path, 'tax_path': tax_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure } tpi_dir = os.path.join(output_dir, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb")) macro_output = { 'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w, 'tax_path': tax_path } # Non-stationary output # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path, # 'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path, # 'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path, # 'w_ns_path': w_ns_path} return output, macro_output
def SS_fsolve(guesses, b_guess_init, n_guess_init, chi_n, chi_b, tax_params, params, iterative_params, tau_bq, rho, lambdas, weights, e): ''' Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using an iterative method similar to TPI. Inputs: b_guess_init = guesses for b (SxJ array) n_guess_init = guesses for n (SxJ array) wguess = guess for wage rate (scalar) rguess = guess for rental rate (scalar) T_Hguess = guess for lump sum tax (scalar) factorguess = guess for scaling factor to dollars (scalar) chi_n = chi^n_s (Sx1 array) chi_b = chi^b_j (Jx1 array) params = list of parameters (list) iterative_params = list of parameters that determine the convergence of the while loop (list) tau_bq = bequest tax rate (Jx1 array) rho = mortality rates (Sx1 array) lambdas = ability weights (Jx1 array) weights = population weights (Sx1 array) e = ability levels (SxJ array) Outputs: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 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 maxiter, mindist_SS = iterative_params # Rename the inputs w = guesses[0] r = guesses[1] T_H = guesses[2] factor = guesses[3] bssmat = b_guess_init nssmat = n_guess_init # Solve for the steady state levels of b and n, given w, r, T_H and # factor for j in xrange(J): # Solve the euler equations if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j-1], nssmat[:, j-1]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) print 'Max Euler errors: ', np.absolute(infodict['fvec']).max() bssmat[:, j] = solutions[:S] nssmat[:, j] = solutions[S:] # print np.array(Euler_equation_solver(np.append(bssmat[:, j], # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n, # theta, tau_bq, rho, lambdas, e)).max() K = household.get_K(bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS') L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J), 'SS') Y = firm.get_Y(K, L, params) new_r = firm.get_r(Y, K, params) new_w = firm.get_w(Y, L, params) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * weights.reshape(S, 1) * lambdas.reshape(1, J)).sum() new_factor = mean_income_data / average_income_model new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J, weights.reshape(S, 1), lambdas) new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ, lambdas.reshape(1, J), factor, weights.reshape(S, 1), 'SS', etr_params, params, theta, tau_bq) error1 = new_w - w error2 = new_r - r error3 = new_T_H - T_H error4 = new_factor - factor print 'errors: ', error1, error2, error3, error4 print 'T_H: ', new_T_H print 'factor: ', new_factor # Check and punish violations if r <= 0: error1 += 1e9 #if r > 1: # error1 += 1e9 if w <= 0: error2 += 1e9 return [error1, error2, error3, error4]
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 solve_tp(g_n_path, omega_S_preTP, rho_s, imm_rates_path, params): ''' Solves for the time path equilibrium using TPI ''' # Missing some elements of params b_ss, r_11, T, S = params dist = 8.0 mindist = 1e-08 maxiter = 300 tpi_iter = 0 xi = 0.2 while dist > mindist and tpi_iter < maxiter: # Define paths b_11 = 1.1 * b_ss BQ_params = (g_n_path[0], omega_S_preTP, rho_s) K_params = (g_n_path[0], omega_S_preTP, imm_rates_path[0, :]) BQ_11 = agg.get_BQ(b_11, r_11, BQ_params) K_11 = agg.get_K(b_11, K_params) BQpath_init = np.zeros(T + S - 1) BQpath_init[:T] = np.linspace(BQ_11, BQ_ss, T) BQpath_init[T:] = BQ_ss r_11 = firm.get_r(K_11, L_ss, r_params) r_path = firm.get_r(L_ss, r_params) w_path = firm.get_w(L_ss, w_params) bmat = np.zeros((S - 1, T + S - 1)) bmat[:, 0] = b_1 # Solve for households for p in range(2, S): b_guess = np.diagonal(bmat[S - p:, :p - 1]) b_init = bmat[S - p - 1, 0] b_params = (b_init, n[-p:], r_path[:p], w_path[:p], BQpath_init[:p], rho_s[-p:], beta, sigma) results_bp = opt.root(hh.FOCs, b_guess, args=(b_params)) b_solve_p = results_bp.x DiagMaskbp = np.eye(p - 1, dtype=bool) bmat[S - p:, 1:p] = DiagMaskbp * b_solve_p + bmat[S - p:, 1:p] for t in range(1, T + 1): b_guess = np.diagonal(bmat[:, t - 1:t + S - 2]) b_init = 0.0 b_params = (b_init, n, r_path[t - 1:t + S - 1], w_path[t - 1:t + S - 1], BQpath_init[t - 1:t + S - 1], rho_s, beta, sigma) results_bt = opt.root(hh.FOCs, b_guess, args=(b_params)) b_solve_t = results_bt.x DiagMaskbt = np.eye(S - 1, dtype=bool) bmat[:, t:t + S - 1] = (DiagMaskbt * b_solve_t + bmat[:, t:t + S - 1]) new_Kpath = np.zeros(T) new_Kpath[0] = K_1 new_Kpath[1:] = \ (1 / (omega_path_S[:T - 1, :-1]) * bmat[:, 1:T].T + imm_rates_path[:T - 1, 1:] * omega_path_S[:T - 1, 1:] * bmat[:, 1:T].T).sum(axis=1) new_BQpath = np.zeros(T) new_BQpath[0] = BQ_1 new_BQpath[1:] = \ ((1 + r_path[1:T]) / (rho_s[:-1]) * omega_path_S[:T - 1, :-1] * bmat[:, 1:T].T).sum(axis=1) dist = ((BQ_init - new_BQ)**2).sum() BQpath_init[:T] = xi * new_BQpath[:T] + (1 - xi) * BQpath_init[:T] # update iteration counter tpi_iter += 1 if tpi_iter < maxiter: print('The time path solved! ->', ' iter:', tpi_iter, ', dist: ', dist) else: print('The time path did not solve.') return [new_Kpath, new_BQpath]
def create_tpi_params(a_tax_income, b_tax_income, c_tax_income, d_tax_income, b_ellipse, upsilon, J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, tau_payroll, retire, mean_income_data, get_baseline=True, input_dir="./OUTPUT", **kwargs): if get_baseline: ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl") variables = pickle.load(open(ss_init, "rb")) for key in variables: globals()[key] = variables[key] else: params_path = os.path.join(input_dir, "Saved_moments/params_changed.pkl") variables = pickle.load(open(params_path, "rb")) for key in variables: globals()[key] = variables[key] var_path = os.path.join(input_dir, "SS/ss_vars.pkl") variables = pickle.load(open(var_path, "rb")) for key in variables: globals()[key] = variables[key] init_tpi_vars = os.path.join(input_dir, "SSinit/ss_init_tpi_vars.pkl") variables = pickle.load(open(init_tpi_vars, "rb")) for key in variables: globals()[key] = variables[key] ''' ------------------------------------------------------------------------ Set other parameters and initial values ------------------------------------------------------------------------ ''' # Make a vector of all one dimensional parameters, to be used in the # following functions income_tax_params = [ a_tax_income, b_tax_income, c_tax_income, d_tax_income ] wealth_tax_params = [h_wealth, p_wealth, m_wealth] ellipse_params = [b_ellipse, upsilon] parameters = [ J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data ] + income_tax_params + wealth_tax_params + ellipse_params N_tilde = omega.sum(1) omega_stationary = omega / N_tilde.reshape(T + S, 1) if get_baseline: initial_b = bssmat_splus1 initial_n = nssmat else: initial_b = bssmat_init initial_n = nssmat_init # Get an initial distribution of capital with the initial population # distribution K0 = household.get_K(initial_b, omega_stationary[0].reshape(S, 1), lambdas, g_n_vector[0], 'SS') b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1])) b_splus1init = initial_b L0 = firm.get_L(e, initial_n, omega_stationary[0].reshape(S, 1), lambdas, 'SS') Y0 = firm.get_Y(K0, L0, parameters) w0 = firm.get_w(Y0, L0, parameters) r0 = firm.get_r(Y0, K0, parameters) BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[0].reshape(S, 1), 'SS', parameters, theta, tau_bq) tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, T_H_0, None, 'SS', False, parameters, theta, tau_bq) c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0) return (income_tax_params, wealth_tax_params, ellipse_params, parameters, N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, w0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n)
def SS_solver(b_guess_init, n_guess_init, wguess, rguess, T_Hguess, factorguess, chi_n, chi_b, tax_params, params, iterative_params, tau_bq, rho, lambdas, weights, e, fsolve_flag=False): ''' Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using an iterative method similar to TPI. Inputs: b_guess_init = guesses for b (SxJ array) n_guess_init = guesses for n (SxJ array) wguess = guess for wage rate (scalar) rguess = guess for rental rate (scalar) T_Hguess = guess for lump sum tax (scalar) factorguess = guess for scaling factor to dollars (scalar) chi_n = chi^n_s (Sx1 array) chi_b = chi^b_j (Jx1 array) params = list of parameters (list) iterative_params = list of parameters that determine the convergence of the while loop (list) tau_bq = bequest tax rate (Jx1 array) rho = mortality rates (Sx1 array) lambdas = ability weights (Jx1 array) weights = population weights (Sx1 array) e = ability levels (SxJ array) Outputs: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 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 maxiter, mindist_SS = iterative_params # Rename the inputs w = wguess r = rguess T_H = T_Hguess factor = factorguess bssmat = b_guess_init nssmat = n_guess_init dist = 10 iteration = 0 dist_vec = np.zeros(maxiter) if fsolve_flag == True: maxiter = 1 while (dist > mindist_SS) and (iteration < maxiter): # Solve for the steady state levels of b and n, given w, r, T_H and # factor for j in xrange(J): # Solve the euler equations if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j-1], nssmat[:, j-1]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) print 'Max Euler errors: ', np.absolute(infodict['fvec']).max() bssmat[:, j] = solutions[:S] nssmat[:, j] = solutions[S:] # print np.array(Euler_equation_solver(np.append(bssmat[:, j], # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n, # theta, tau_bq, rho, lambdas, e)).max() K = household.get_K(bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS') L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J), 'SS') Y = firm.get_Y(K, L, params) new_r = firm.get_r(Y, K, params) new_w = firm.get_w(Y, L, params) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * weights.reshape(S, 1) * lambdas.reshape(1, J)).sum() new_factor = mean_income_data / average_income_model new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J, weights.reshape(S, 1), lambdas) # lump_sum_tax_params = (a_etr_income, b_etr_income, c_etr_income, d_etr_income, # e_etr_income, f_etr_income, min_x_etr_income, max_x_etr_income, # min_y_etr_income, max_y_etr_income) new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ, lambdas.reshape(1, J), factor, weights.reshape(S, 1), 'SS', etr_params, params, theta, tau_bq) r = utils.convex_combo(new_r, r, nu) w = utils.convex_combo(new_w, w, nu) factor = utils.convex_combo(new_factor, factor, nu) T_H = utils.convex_combo(new_T_H, T_H, nu) if T_H != 0: dist = np.array([utils.perc_dif_func(new_r, r)] + [utils.perc_dif_func(new_w, w)] + [utils.perc_dif_func(new_T_H, T_H)] + [utils.perc_dif_func(new_factor, factor)]).max() else: # If T_H is zero (if there are no taxes), a percent difference # will throw NaN's, so we use an absoluate difference dist = np.array([utils.perc_dif_func(new_r, r)] + [utils.perc_dif_func(new_w, w)] + [abs(new_T_H - T_H)] + [utils.perc_dif_func(new_factor, factor)]).max() dist_vec[iteration] = dist # Similar to TPI: if the distance between iterations increases, then # decrease the value of nu to prevent cycling if iteration > 10: if dist_vec[iteration] - dist_vec[iteration - 1] > 0: nu /= 2.0 print 'New value of nu:', nu iteration += 1 print "Iteration: %02d" % iteration, " Distance: ", dist eul_errors = np.ones(J) b_mat = np.zeros((S, J)) n_mat = np.zeros((S, J)) # Given the final w, r, T_H and factor, solve for the SS b and n (if you # don't do a final fsolve, there will be a slight mismatch, # with high euler errors) for j in xrange(J): guesses = np.append(bssmat[:, j], nssmat[:, j]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions1, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) eul_errors[j] = np.array(infodict['fvec']).max() print 'Max Euler errors: ', np.absolute(infodict['fvec']).max() b_mat[:, j] = solutions1[:S] n_mat[:, j] = solutions1[S:] print 'SS fsolve euler error:', eul_errors.max() solutions = np.append(b_mat.flatten(), n_mat.flatten()) other_vars = np.array([w, r, factor, T_H]) solutions = np.append(solutions, other_vars) return solutions
def create_tpi_params(**sim_params): ''' ------------------------------------------------------------------------ Set factor and initial capital stock to SS from baseline ------------------------------------------------------------------------ ''' baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl") ss_baseline_vars = pickle.load(open(baseline_ss, "rb")) factor = ss_baseline_vars['factor_ss'] #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas initial_b = ss_baseline_vars['bssmat_splus1'] initial_n = ss_baseline_vars['nssmat'] SS_values = (ss_baseline_vars['Kss'],ss_baseline_vars['Lss'], ss_baseline_vars['rss'], ss_baseline_vars['wss'], ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'], ss_baseline_vars['bssmat_splus1'], ss_baseline_vars['nssmat']) # Make a vector of all one dimensional parameters, to be used in the # following functions wealth_tax_params = [sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth']] ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']] chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']] N_tilde = sim_params['omega'].sum(1) #this should just be one in each year given how we've constructed omega sim_params['omega'] = sim_params['omega'] / N_tilde.reshape(sim_params['T'] + sim_params['S'], 1) tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BQ_dist'], sim_params['BW'], sim_params['beta'], sim_params['sigma'], sim_params['alpha'], sim_params['Z'], sim_params['delta'], sim_params['ltilde'], sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'], sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde, sim_params['lambdas'], sim_params['e'], sim_params['retire'], sim_params['mean_income_data'], factor] + \ wealth_tax_params + ellipse_params + chi_params iterative_params = [sim_params['maxiter'], sim_params['mindist_SS'], sim_params['mindist_TPI']] J, S, T, BQ_dist, 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 ## Assumption for tax functions is that policy in last year of BW is # extended permanently etr_params_TP = np.zeros((S,T+S,sim_params['etr_params'].shape[2])) etr_params_TP[:,:BW,:] = sim_params['etr_params'] etr_params_TP[:,BW:,:] = np.reshape(sim_params['etr_params'][:,BW-1,:],(S,1,sim_params['etr_params'].shape[2])) mtrx_params_TP = np.zeros((S,T+S,sim_params['mtrx_params'].shape[2])) mtrx_params_TP[:,:BW,:] = sim_params['mtrx_params'] mtrx_params_TP[:,BW:,:] = np.reshape(sim_params['mtrx_params'][:,BW-1,:],(S,1,sim_params['mtrx_params'].shape[2])) mtry_params_TP = np.zeros((S,T+S,sim_params['mtry_params'].shape[2])) mtry_params_TP[:,:BW,:] = sim_params['mtry_params'] mtry_params_TP[:,BW:,:] = np.reshape(sim_params['mtry_params'][:,BW-1,:],(S,1,sim_params['mtry_params'].shape[2])) income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP, mtrx_params_TP, mtry_params_TP) ''' ------------------------------------------------------------------------ Set other parameters and initial values ------------------------------------------------------------------------ ''' # Get an initial distribution of capital with the initial population # distribution K0_params = (omega[0].reshape(S, 1), lambdas, g_n_vector[0], 'SS') K0 = household.get_K(initial_b, K0_params) b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1])) b_splus1init = initial_b L0_params = (e, omega[0].reshape(S, 1), lambdas, 'SS') L0 = firm.get_L(initial_n, L0_params) Y0_params = (alpha, Z) Y0 = firm.get_Y(K0, L0, Y0_params) w0 = firm.get_w(Y0, L0, alpha) r0_params = (alpha, delta) r0 = firm.get_r(Y0, K0, r0_params) BQ0_params = (omega[0].reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') BQ0 = household.get_BQ(r0, initial_b, BQ0_params) theta_params = (e, J, omega[0].reshape(S, 1), lambdas) theta = tax.replacement_rate_vals(initial_n, w0, factor, theta_params) T_H_params = (e, BQ_dist, lambdas, omega[0].reshape(S, 1), 'SS', etr_params_TP[:,0,:], theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) T_H_0 = tax.get_lump_sum(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_params) etr_params_3D = np.tile(np.reshape(etr_params_TP[:,0,:],(S,1,etr_params_TP.shape[2])),(1,J,1)) tax0_params = (e, BQ_dist, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax0 = tax.total_taxes(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_0, None, False, tax0_params) c0_params = (e, BQ_dist, lambdas.reshape(1, J), g_y) c0 = household.get_cons(omega[0].reshape(S, 1), r0, w0, b_sinit, b_splus1init, initial_n, BQ0.reshape( 1, J), tax0, c0_params) initial_values = (K0, b_sinit, b_splus1init, L0, Y0, w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n) return (income_tax_params, tpi_params, iterative_params, initial_values, SS_values)
def inner_loop(outer_loop_vars, params, baseline): ''' This function solves for the inner loop of the SS. That is, given the guesses of the outer loop variables (r, w, T_H, factor) this function solves the households' problems in the SS. Inputs: r = [T,] vector, interest rate w = [T,] vector, wage rate b = [T,S,J] array, wealth holdings n = [T,S,J] array, labor supply BQ = [T,J] vector, bequest amounts factor = scalar, model income scaling factor T_H = [T,] vector, lump sum transfer amount(s) Functions called: euler_equation_solver() household.get_K() firm.get_L() firm.get_Y() firm.get_r() firm.get_w() household.get_BQ() tax.replacement_rate_vals() tax.get_lump_sum() Objects in function: Returns: euler_errors, bssmat, nssmat, new_r, new_w new_T_H, new_factor, new_BQ ''' # unpack variables and parameters pass to function bssmat, nssmat, r, w, T_H, factor = outer_loop_vars ss_params, income_tax_params, chi_params = params J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params chi_b, chi_n = chi_params # bssmat = START_VALUES['bssmat_splus1'] # nssmat = START_VALUES['nssmat'] euler_errors = np.zeros((2*S,J)) for j in xrange(J): # Solve the euler equations # if j == 0: # guesses = np.append(bssmat[:, j], nssmat[:, j]) # elif j == J - 1: # guesses = np.append(bssmat[:, j-1]*2.0, nssmat[:, j-1]) # else: # guesses = np.append(bssmat[:, j-1], nssmat[:, j-1]) guesses = np.append(bssmat[:, j], nssmat[:, j]) euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\ j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\ analytical_mtrs, etr_params, mtrx_params,\ mtry_params] [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9, args=euler_params, xtol=MINIMIZER_TOL, full_output=True) euler_errors[:,j] = infodict['fvec'] bssmat[:, j] = solutions[:S] nssmat[:, j] = solutions[S:] K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS') K = household.get_K(bssmat, K_params) L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS') L = firm.get_L(nssmat, L_params) Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) new_r = firm.get_r(Y, K, r_params) new_w = firm.get_w(Y, L, alpha) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * omega_SS.reshape(S, 1) * lambdas.reshape(1, J)).sum() if baseline: new_factor = mean_income_data / average_income_model else: new_factor = factor BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') new_BQ = household.get_BQ(new_r, bssmat, BQ_params) theta_params = (e, S, retire) theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params) T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params) print 'Inner Loop Max Euler Error: ', (np.absolute(euler_errors)).max() return euler_errors, bssmat, nssmat, new_r, new_w, \ net_tax_receipts, new_factor, new_BQ, average_income_model