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 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 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 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 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 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 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_steady_state(ss_parameters, iterative_params, get_baseline=False, calibrate_model=False, output_dir="./OUTPUT"): ''' ------------------------------------------------------------------------ Run SS ------------------------------------------------------------------------ ''' if get_baseline: # Generate initial guesses for chi^b_j and chi^n_s chi_params = np.zeros(S + J) chi_params[:J] = chi_b_guess chi_params[J:] = chi_n_guess # First run SS simulation with guesses at initial values for b, n, w, r, etc # For inital guesses of b and n, we choose very small b, and medium n b_guess = np.ones((S, J)).flatten() * .01 n_guess = np.ones((S, J)).flatten() * .5 * ltilde # For initial guesses of w, r, T_H, and factor, we use values that are close # to some steady state values. wguess = 1.2 rguess = .06 T_Hguess = 0 factorguess = 100000 solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) if calibrate_model: outputs = {'solutions': solutions, 'chi_params': chi_params} ss_init_path = os.path.join(output_dir, "Saved_moments/SS_init_solutions.pkl") pickle.dump(outputs, open(ss_init_path, "wb")) function_to_minimize_X = lambda x: function_to_minimize( x, chi_params, ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir) bnds = tuple([(1e-6, None)] * (S + J)) # In order to scale all the parameters to estimate in the minimizer, we have the minimizer fit a vector of ones that # will be multiplied by the chi initial guesses inside the function. Otherwise, if chi^b_j=1e5 for some j, and the # minimizer peturbs that value by 1e-8, the % difference will be extremely small, outside of the tolerance of the # minimizer, and it will not change that parameter. chi_params_scalars = np.ones(S + J) chi_params_scalars = opt.minimize(function_to_minimize_X, chi_params_scalars, method='TNC', tol=MINIMIZER_TOL, bounds=bnds, options=MINIMIZER_OPTIONS).x chi_params *= chi_params_scalars print 'The final scaling params', chi_params_scalars print 'The final bequest parameter values:', chi_params solutions_dict = pickle.load(open(ss_init_path, "rb")) solutions = solutions_dict['solutions'] b_guess = solutions[:S * J] n_guess = solutions[S * J:2 * S * J] wguess, rguess, factorguess, T_Hguess = solutions[2 * S * J:] solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) else: variables = pickle.load(open(ss_init_path, "rb")) solutions = solutions_dict['solutions'] chi_params = solutions_dict['chi_params'] b_guess = solutions[:S * J] n_guess = solutions[S * J:2 * S * J] wguess, rguess, factorguess, T_Hguess = solutions[2 * S * J:] solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' if get_baseline: outputs = {'solutions': solutions, 'chi_params': chi_params} ss_init_dir = os.path.join(output_dir, "Saved_moments/SS_init_solutions.pkl") pickle.dump(outputs, open(ss_init_dir, "wb")) else: outputs = {'solutions': solutions, 'chi_params': chi_params} ss_exp_dir = os.path.join(output_dir, "Saved_moments/SS_experiment_solutions.pkl") pickle.dump(outputs, open(ss_exp_dir, "wb")) bssmat = solutions[0:(S - 1) * J].reshape(S - 1, J) bq = solutions[(S - 1) * J:S * J] bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat)) bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J))) nssmat = solutions[S * J:2 * S * J].reshape(S, J) wss, rss, factor_ss, T_Hss = solutions[2 * S * J:] Kss = household.get_K(bssmat_splus1, omega_SS.reshape(S, 1), lambdas, g_n_ss, 'SS') Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas, 'SS') Yss = firm.get_Y(Kss, Lss, ss_parameters) Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss) theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, e, J, omega_SS.reshape(S, 1), lambdas) BQss = household.get_BQ(rss, bssmat_splus1, omega_SS.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_ss, 'SS') b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas, factor_ss, T_Hss, None, 'SS', False, ss_parameters, theta, tau_bq) cssmat = household.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape(1, J), lambdas.reshape(1, J), bssmat_splus1, ss_parameters, taxss) Css = household.get_C(cssmat, omega_SS.reshape(S, 1), lambdas, 'SS') resource_constraint = Yss - (Css + Iss) print 'Resource Constraint Difference:', resource_constraint household.constraint_checker_SS(bssmat, nssmat, cssmat, ss_parameters) b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) b_splus1 = bssmat_splus1 b_splus2 = np.array( list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J)))) chi_b = np.tile(chi_params[:J].reshape(1, J), (S, 1)) chi_n = np.array(chi_params[J:]) euler_savings = np.zeros((S, J)) euler_labor_leisure = np.zeros((S, J)) for j in xrange(J): euler_savings[:, j] = household.euler_savings_func( wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], b_splus2[:, j], BQss[j], factor_ss, T_Hss, chi_b[:, j], ss_parameters, theta[j], tau_bq[j], rho, lambdas[j]) euler_labor_leisure[:, j] = household.euler_labor_leisure_func( wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], BQss[j], factor_ss, T_Hss, chi_n, ss_parameters, theta[j], tau_bq[j], lambdas[j]) ''' ------------------------------------------------------------------------ Save the values in various ways, depending on the stage of the simulation, to be used in TPI or graphing functions ------------------------------------------------------------------------ ''' # Pickle variables output = { 'Kss': Kss, 'bssmat': bssmat, 'Lss': Lss, 'nssmat': nssmat, 'Yss': Yss, 'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'T_Hss': T_Hss, 'euler_savings': euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n, 'chi_b': chi_b } if get_baseline: utils.mkdirs(os.path.join(output_dir, "SSinit")) ss_init_dir = os.path.join(output_dir, "SSinit/ss_init_vars.pkl") pickle.dump(output, open(ss_init_dir, "wb")) bssmat_init = bssmat_splus1 nssmat_init = nssmat # Pickle variables for TPI initial values output2 = {'bssmat_init': bssmat_init, 'nssmat_init': nssmat_init} ss_init_tpi = os.path.join(output_dir, "SSinit/ss_init_tpi_vars.pkl") pickle.dump(output2, open(ss_init_tpi, "wb")) else: utils.mkdirs(os.path.join(output_dir, "SS")) ss_vars = os.path.join(output_dir, "SS/ss_vars.pkl") pickle.dump(output, open(ss_vars, "wb")) return output
def run_TPI(income_tax_params, tpi_params, iterative_params, initial_values, SS_values, fix_transfers=False, output_dir="./OUTPUT"): # unpack tuples of parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params maxiter, mindist_SS, mindist_TPI = iterative_params J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\ factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP = initial_values Kss, Lss, rss, wss, BQss, T_Hss, Gss, bssmat_splus1, nssmat = SS_values TPI_FIG_DIR = output_dir # Initialize guesses at time paths domain = np.linspace(0, T, T) r = np.ones(T + S) * rss BQ = np.zeros((T + S, J)) BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') BQ0 = household.get_BQ(r[0], initial_b, BQ0_params) for j in xrange(J): BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQ = np.array(BQ) # print "BQ values = ", BQ[0, :], BQ[100, :], BQ[-1, :], BQss # print "K0 vs Kss = ", K0-Kss if fix_transfers: T_H = T_H_baseline else: if np.abs(T_Hss) < 1e-13 : T_Hss2 = 0.0 # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below else: T_Hss2 = T_Hss T_H = np.ones(T + S) * T_Hss2 * (r/rss) G = np.ones(T + S) * Gss # # print "T_H values = ", T_H[0], T_H[100], T_H[-1], T_Hss # # print "omega diffs = ", (omega_S_preTP-omega[-1]).max(), (omega[10]-omega[-1]).max() # # Make array of initial guesses for labor supply and savings domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) # print 'diff btwn start and end b: ', (guesses_b[0]-guesses_b[-1]).max() # domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) # b_mat = np.zeros((T + S, S, J)) # n_mat = np.zeros((T + S, S, J)) ind = np.arange(S) # # print 'diff btwn start and end n: ', (guesses_n[0]-guesses_n[-1]).max() # # # find economic aggregates K = np.zeros(T+S) L = np.zeros(T+S) K[0] = K0 K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(guesses_b[:T-1], K_params) K[T:] = Kss L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(guesses_n[:T], L_params) L[T:] = Lss Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) r[:T] = firm.get_r(Y[:T], K[:T], r_params) # uncomment lines below if want to use starting values from prior run r = TPI_START_VALUES['r'] K = TPI_START_VALUES['K'] L = TPI_START_VALUES['L'] Y = TPI_START_VALUES['Y'] T_H = TPI_START_VALUES['T_H'] BQ = TPI_START_VALUES['BQ'] G = TPI_START_VALUES['G'] guesses_b = TPI_START_VALUES['b_mat'] guesses_n = TPI_START_VALUES['n_mat'] TPIiter = 0 TPIdist = 10 PLOT_TPI = False euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) # print 'analytical mtrs in tpi = ', analytical_mtrs while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: K_plot = list(K) + list(np.ones(10) * Kss) L_plot = list(L) + list(np.ones(10) * Lss) plt.figure() plt.axhline( y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange( T + 10), Kpath_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) guesses = (guesses_b, guesses_n) w_params = (Z, alpha, delta) w = firm.get_w_from_r(r, w_params) # print 'r and rss diff = ', r-rss # print 'w and wss diff = ', w-wss # print 'BQ and BQss diff = ', BQ-BQss # print 'T_H and T_Hss diff = ', T_H - T_Hss # print 'guess b and bss = ', (bssmat_splus1 - guesses_b).max() # print 'guess n and nss = ', (nssmat - guesses_n).max() outer_loop_vars = (r, w, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, ind) # Solve HH problem in inner loop euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) # print 'guess b and bss = ', (b_mat - guesses_b).max() # print 'guess n and nss over time = ', (n_mat - guesses_n).max(axis=2).max(axis=1) # print 'guess n and nss over age = ', (n_mat - guesses_n).max(axis=0).max(axis=1) # print 'guess n and nss over ability = ', (n_mat - guesses_n).max(axis=0).max(axis=0) # quit() print 'Max Euler error: ', (np.abs(euler_errors)).max() bmat_s = np.zeros((T, S, J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[:T, :, :] K[0] = K0 K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1, S, 1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(bmat_splus1[:T-1], K_params) L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(n_mat[:T], L_params) # print 'K diffs = ', K-K0 # print 'L diffs = ', L-L[0] Y_params = (alpha, Z) Ynew = firm.get_Y(K[:T], L[:T], Y_params) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) wnew = firm.get_w_from_r(rnew, w_params) omega_shift = np.append(omega_S_preTP.reshape(1, S), omega[:T-1, :], axis=0) BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') # b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)), # b_mat[:T-1, :, :], axis=0) b_mat_shift = bmat_splus1[:T, :, :] # print 'b diffs = ', (bmat_splus1[100, :, :] - initial_b).max(), (bmat_splus1[0, :, :] - initial_b).max(), (bmat_splus1[1, :, :] - initial_b).max() # print 'r diffs = ', rnew[1]-r[1], rnew[100]-r[100], rnew[-1]-r[-1] BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params) BQss2 = np.empty(J) for j in range(J): BQss_params = (omega[1, :], lambdas[j], rho, g_n_vector[1], 'SS') BQss2[j] = household.get_BQ(rnew[1], bmat_splus1[1, :, j], BQss_params) # print 'BQ test = ', BQss2-BQss, BQss-BQnew[1], BQss-BQnew[100], BQss-BQnew[-1] total_tax_params = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): total_tax_params[:, :, :, i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) tax_receipt_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)), bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S) r[:T] = utils.convex_combo(rnew[:T], r[:T], nu) BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu) if fix_transfers: T_H_new = T_H G[:T] = net_tax_receipts[:T] - T_H[:T] else: T_H_new = net_tax_receipts T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu) G[:T] = 0.0 etr_params_path = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_path[:,:,:,i] = np.tile( np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas, 'TPI', retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) b_to_use = np.zeros((T, S, J)) b_to_use[0, 1:, :] = initial_b[:-1, :] b_to_use[1:, 1:, :] = b_mat[:T-1, :-1, :] tax_path = tax.total_taxes( np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), b_to_use, n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * b_to_use[:T, :, :] + np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) * np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :]) cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), b_to_use[:T,:,:], b_mat[:T,:,:], n_mat[:T,:,:], BQ[:T].reshape(T, 1, J), tax_path, cons_params) guesses_b = utils.convex_combo(b_mat, guesses_b, nu) guesses_n = utils.convex_combo(n_mat, guesses_n, nu) if T_H.all() != 0: TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() print 'r dist = ', np.array(list(utils.pct_diff_func(rnew[:T], r[:T]))).max() print 'BQ dist = ', np.array(list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten())).max() print 'T_H dist = ', np.array(list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() print 'T_H path = ', T_H[:20] # print 'r old = ', r[:T] # print 'r new = ', rnew[:T] # print 'K old = ', K[:T] # print 'L old = ', L[:T] # print 'income = ', y_path[:, :, -1] # print 'taxes = ', tax_path[:, :, -1] # print 'labor supply = ', n_mat[:, :, -1] # print 'max and min labor = ', n_mat.max(), n_mat.min() # print 'max and min labor = ', np.argmax(n_mat), np.argmin(n_mat) # print 'max and min labor, j = 7 = ', n_mat[:,:,-1].max(), n_mat[:,:,-1].min() # print 'max and min labor, j = 6 = ', n_mat[:,:,-2].max(), n_mat[:,:,-2].min() # print 'max and min labor, j = 5 = ', n_mat[:,:,4].max(), n_mat[:,:,4].min() # print 'max and min labor, j = 4 = ', n_mat[:,:,3].max(), n_mat[:,:,3].min() # print 'max and min labor, j = 3 = ', n_mat[:,:,2].max(), n_mat[:,:,2].min() # print 'max and min labor, j = 2 = ', n_mat[:,:,1].max(), n_mat[:,:,1].min() # print 'max and min labor, j = 1 = ', n_mat[:,:,0].max(), n_mat[:,:,0].min() # print 'max and min labor, S = 80 = ', n_mat[:,-1,-1].max(), n_mat[:,-1,-1].min() # print "number > 1 = ", (n_mat > 1).sum() # print "number < 0, = ", (n_mat < 0).sum() # print "number > 1, j=7 = ", (n_mat[:T,:,-1] > 1).sum() # print "number < 0, j=7 = ", (n_mat[:T,:,-1] < 0).sum() # print "number > 1, s=80, j=7 = ", (n_mat[:T,-1,-1] > 1).sum() # print "number < 0, s=80, j=7 = ", (n_mat[:T,-1,-1] < 0).sum() # print "number > 1, j= 7, age 80= ", (n_mat[:T,-1,-1] > 1).sum() # print "number < 0, j = 7, age 80= ", (n_mat[:T,-1,-1] < 0).sum() # print "number > 1, j= 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] > 1).sum() # print "number < 0, j = 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] < 0).sum() # print "number > 1, j= 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80,-1] > 1).sum() # print "number < 0, j = 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80 ,-1] < 0).sum() # diag_dict = {'n_mat': n_mat, 'b_mat': b_mat, 'y_path': y_path, 'c_path': c_path} # pickle.dump(diag_dict, open('tpi_iter1.pkl', 'wb')) else: TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(np.abs(T_H_new[:T]-T_H[:T]))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print '\tIteration:', TPIiter print '\t\tDistance:', TPIdist Y[:T] = Ynew # Solve HH problem in inner loop guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, ind) euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) bmat_s = np.zeros((T, S, J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[:T, :, :] K[0] = K0 K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(bmat_splus1[:T-1], K_params) L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(n_mat[:T], L_params) Y_params = (alpha, Z) Ynew = firm.get_Y(K[:T], L[:T], Y_params) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) wnew = firm.get_w_from_r(rnew, w_params) omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0) BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') b_mat_shift = np.append(np.reshape(initial_b,(1,S,J)),b_mat[:T-1,:,:],axis=0) BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params) total_tax_params = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): total_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) tax_receipt_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)), bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S) if fix_transfers: G[:T] = net_tax_receipts[:T] - T_H[:T] else: T_H[:T] = net_tax_receipts[:T] G[:T] = 0.0 etr_params_path = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas, 'TPI', retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), bmat_s, n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T,:,:], BQ[:T].reshape(T, 1, J), tax_path, cons_params) C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI') C = household.get_C(c_path, C_params) I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI') I = firm.get_I(bmat_splus1[:T], K[1:T+1], K[:T], I_params) rc_error = Y[:T] - C[:T] - I[:T] - G[:T] print 'Resource Constraint Difference:', rc_error # compute utility u_params = (sigma, np.tile(chi_n.reshape(1, S, 1), (T, 1, J)), b_ellipse, ltilde, upsilon, np.tile(rho.reshape(1, S, 1), (T, 1, J)), np.tile(chi_b.reshape(1, 1, J), (T, S, 1))) utility_path = household.get_u(c_path[:T, :, :], n_mat[:T, :, :], bmat_splus1[:T, :, :], u_params) # compute before and after-tax income y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * bmat_s[:T, :, :] + np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) * np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :]) inctax_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), etr_params_path) y_aftertax_path = (y_path - tax.tau_income(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)), bmat_s[:T,:,:], n_mat[:T,:,:], factor, inctax_params)) # compute after-tax wealth wtax_params = (h_wealth, p_wealth, m_wealth) b_aftertax_path = bmat_s[:T,:,:] - tax.tau_wealth(bmat_s[:T,:,:], wtax_params) print'Checking time path for violations of constaints.' for t in xrange(T): household.constraint_checker_TPI( b_mat[t], n_mat[t], c_path[t], t, ltilde) eul_savings = euler_errors[:, :S, :].max(1).max(1) eul_laborleisure = euler_errors[:, S:, :].max(1).max(1) print 'Max Euler error, savings: ', eul_savings print 'Max Euler error labor supply: ', eul_laborleisure ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 'c_path': c_path, 'tax_path': tax_path, 'bmat_s': bmat_s, 'utility_path': utility_path, 'b_aftertax_path': b_aftertax_path, 'y_aftertax_path': y_aftertax_path, 'y_path': y_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure} macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w, 'tax_path': tax_path} # if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS : # raise RuntimeError("Transition path equlibrium not found") # # if ((np.any(np.absolute(rc_error) >= 1e-6)) # and ENFORCE_SOLUTION_CHECKS): # raise RuntimeError("Transition path equlibrium not found") # # if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or # (np.any(np.absolute(eul_laborleisure) > mindist_TPI))) # and ENFORCE_SOLUTION_CHECKS): # raise RuntimeError("Transition path equlibrium not found") return output, macro_output
def SS_solver(b_guess_init, n_guess_init, wss, rss, T_Hss, factor_ss, params, fsolve_flag=False): ''' -------------------------------------------------------------------- Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using a bisection method similar to TPI. -------------------------------------------------------------------- INPUTS: b_guess_init = [S,J] array, initial guesses for savings n_guess_init = [S,J] array, initial guesses for labor supply wguess = scalar, initial guess for SS real wage rate rguess = scalar, initial guess for SS real interest rate T_Hguess = scalar, initial guess for lump sum transfer factorguess = scalar, initial guess for scaling factor to dollars chi_b = [J,] vector, chi^b_j, the utility weight on bequests chi_n = [S,] vector, chi^n_s utility weight on labor supply params = lenght X tuple, list of parameters iterative_params = length X tuple, list of parameters that determine the convergence of the while loop tau_bq = [J,] vector, bequest tax rate rho = [S,] vector, mortality rates by age lambdas = [J,] vector, fraction of population with each ability type omega = [S,] vector, stationary population weights e = [S,J] array, effective labor units by age and ability type OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: 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() utils.convex_combo() utils.pct_diff_func() OBJECTS CREATED WITHIN FUNCTION: b_guess = [S,] vector, initial guess at household savings n_guess = [S,] vector, initial guess at household labor supply b_s = [S,] vector, wealth enter period with b_splus1 = [S,] vector, household savings b_splus2 = [S,] vector, household savings one period ahead BQ = scalar, aggregate bequests to lifetime income group theta = scalar, replacement rate for social security benenfits error1 = [S,] vector, errors from FOC for savings error2 = [S,] vector, errors from FOC for labor supply tax1 = [S,] vector, total income taxes paid cons = [S,] vector, household consumption RETURNS: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 array) OUTPUT: None -------------------------------------------------------------------- ''' bssmat, nssmat, chi_params, ss_params, income_tax_params, iterative_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 maxiter, mindist_SS = iterative_params # Rename the inputs w = wss r = rss T_H = T_Hss factor = factor_ss 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 outer_loop_vars = (bssmat, nssmat, r, w, T_H, factor) inner_loop_params = (ss_params, income_tax_params, chi_params) euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_factor, new_BQ, average_income_model = inner_loop(outer_loop_vars, inner_loop_params) 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.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [utils.pct_diff_func(new_T_H, T_H)] + [utils.pct_diff_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.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [abs(new_T_H - T_H)] + [utils.pct_diff_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 ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' bssmat_s = np.append(np.zeros((1,J)),bssmat[:-1,:],axis=0) bssmat_splus1 = bssmat wss = w rss = r factor_ss = factor T_Hss = T_H Kss_params = (omega_SS.reshape(S, 1), lambdas, g_n_ss, 'SS') Kss = household.get_K(bssmat_splus1, Kss_params) Lss_params = (e, omega_SS.reshape(S, 1), lambdas, 'SS') Lss = firm.get_L(nssmat, Lss_params) Yss_params = (alpha, Z) Yss = firm.get_Y(Kss, Lss, Yss_params) Iss_params = (delta, g_y, g_n_ss) Iss = firm.get_I(Kss, Kss, Iss_params) BQss = new_BQ theta = np.zeros(J) # zero out payroll taxes since included in tax functions # # theta_params = (e, J, omega_SS.reshape(S, 1), lambdas) # # tax.replacement_rate_vals(nssmat, wss, factor_ss, theta_params) # solve resource constraint etr_params_3D = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1)) mtrx_params_3D = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1)) ''' ------------------------------------------------------------------------ The code below is to calulate and save model MTRs - only exists help debug ------------------------------------------------------------------------ ''' # etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:] # etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1)) # mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:] # mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1)) # e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J))) # nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J))) # mtry_ss_params = (e_extended[1:,:], etr_params_extended_3D, mtry_params_extended_3D, analytical_mtrs) # mtry_ss = tax.MTR_capital(rss, wss, bssmat_splus1, nss_extended[1:,:], factor_ss, mtry_ss_params) # mtrx_ss_params = (e, etr_params_3D, mtrx_params_3D, analytical_mtrs) # mtrx_ss = tax.MTR_labor(rss, wss, bssmat_s, nssmat, factor_ss, mtrx_ss_params) # np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",") # np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",") # solve resource constraint taxss_params = (e, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) taxss = tax.total_taxes(rss, wss, bssmat_s, nssmat, BQss, factor_ss, T_Hss, None, False, taxss_params) css_params = (e, lambdas.reshape(1, J), g_y) cssmat = household.get_cons(rss, wss, bssmat_s, bssmat_splus1, nssmat, BQss.reshape( 1, J), taxss, css_params) Css_params = (omega_SS.reshape(S, 1), lambdas, 'SS') Css = household.get_C(cssmat, Css_params) resource_constraint = Yss - (Css + Iss) print 'Resource Constraint Difference:', resource_constraint if ENFORCE_SOLUTION_CHECKS and np.absolute(resource_constraint) > 1e-8: err = "Steady state aggregate resource constraint not satisfied" raise RuntimeError(err) # check constraints household.constraint_checker_SS(bssmat, nssmat, cssmat, ltilde) euler_savings = euler_errors[:S,:] euler_labor_leisure = euler_errors[S:,:] ''' ------------------------------------------------------------------------ Return dictionary of SS results ------------------------------------------------------------------------ ''' output = {'Kss': Kss, 'bssmat': bssmat, 'Lss': Lss, 'Css':Css, 'nssmat': nssmat, 'Yss': Yss, 'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'T_Hss': T_Hss, 'euler_savings': euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n, 'chi_b': chi_b} return output
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): ''' 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): ''' 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 SS_solver(b_guess_init, n_guess_init, rss, wss, T_Hss, factor_ss, Yss, params, baseline, fsolve_flag=False, baseline_spending=False): ''' -------------------------------------------------------------------- Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using a bisection method similar to TPI. -------------------------------------------------------------------- INPUTS: b_guess_init = [S,J] array, initial guesses for savings n_guess_init = [S,J] array, initial guesses for labor supply wguess = scalar, initial guess for SS real wage rate rguess = scalar, initial guess for SS real interest rate T_Hguess = scalar, initial guess for lump sum transfer factorguess = scalar, initial guess for scaling factor to dollars chi_b = [J,] vector, chi^b_j, the utility weight on bequests chi_n = [S,] vector, chi^n_s utility weight on labor supply params = length X tuple, list of parameters iterative_params = length X tuple, list of parameters that determine the convergence of the while loop tau_bq = [J,] vector, bequest tax rate rho = [S,] vector, mortality rates by age lambdas = [J,] vector, fraction of population with each ability type omega = [S,] vector, stationary population weights e = [S,J] array, effective labor units by age and ability type OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: 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() utils.convex_combo() utils.pct_diff_func() OBJECTS CREATED WITHIN FUNCTION: b_guess = [S,] vector, initial guess at household savings n_guess = [S,] vector, initial guess at household labor supply b_s = [S,] vector, wealth enter period with b_splus1 = [S,] vector, household savings b_splus2 = [S,] vector, household savings one period ahead BQ = scalar, aggregate bequests to lifetime income group theta = scalar, replacement rate for social security benenfits error1 = [S,] vector, errors from FOC for savings error2 = [S,] vector, errors from FOC for labor supply tax1 = [S,] vector, total income taxes paid cons = [S,] vector, household consumption OBJECTS CREATED WITHIN FUNCTION - SMALL OPEN ONLY Bss = scalar, aggregate household wealth in the steady state BIss = scalar, aggregate household net investment in the steady state RETURNS: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 array) OUTPUT: None -------------------------------------------------------------------- ''' bssmat, nssmat, chi_params, ss_params, income_tax_params, iterative_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 maxiter, mindist_SS = iterative_params small_open, ss_firm_r, ss_hh_r = small_open_params # Rename the inputs r = rss w = wss T_H = T_Hss factor = factor_ss if budget_balance == False: if baseline_spending == True: Y = Yss else: Y = T_H / alpha_T if small_open == True: r = ss_hh_r 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, Y and # factor if budget_balance: outer_loop_vars = (bssmat, nssmat, r, w, T_H, factor) else: outer_loop_vars = (bssmat, nssmat, r, w, Y, T_H, factor) inner_loop_params = (ss_params, income_tax_params, chi_params, small_open_params) euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_Y, new_factor, new_BQ, average_income_model = inner_loop(outer_loop_vars, inner_loop_params, baseline, baseline_spending) r = utils.convex_combo(new_r, r, nu) w = utils.convex_combo(new_w, w, nu) factor = utils.convex_combo(new_factor, factor, nu) if budget_balance: T_H = utils.convex_combo(new_T_H, T_H, nu) dist = np.array([utils.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [utils.pct_diff_func(new_T_H, T_H)] + [utils.pct_diff_func(new_factor, factor)]).max() else: Y = utils.convex_combo(new_Y, Y, nu) if Y != 0: dist = np.array( [utils.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [utils.pct_diff_func(new_Y, Y)] + [utils.pct_diff_func(new_factor, factor)]).max() else: # If Y is zero (if there is no output), a percent difference # will throw NaN's, so we use an absoluate difference dist = np.array( [utils.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [abs(new_Y - Y)] + [utils.pct_diff_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 ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' bssmat_s = np.append(np.zeros((1, J)), bssmat[:-1, :], axis=0) bssmat_splus1 = bssmat rss = r wss = w factor_ss = factor T_Hss = T_H Lss_params = (e, omega_SS.reshape(S, 1), lambdas, 'SS') Lss = firm.get_L(nssmat, Lss_params) if small_open == False: Kss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS') Bss = household.get_K(bssmat_splus1, Kss_params) if budget_balance: debt_ss = 0.0 else: debt_ss = debt_ratio_ss * Y Kss = Bss - debt_ss Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS') Iss = firm.get_I(bssmat_splus1, Kss, Kss, Iss_params) else: # Compute capital (K) and wealth (B) separately Kss_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) Kss = firm.get_K(Lss, ss_firm_r, Kss_params) Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS') InvestmentPlaceholder = np.zeros(bssmat_splus1.shape) Iss = firm.get_I(InvestmentPlaceholder, Kss, Kss, Iss_params) Bss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS') Bss = household.get_K(bssmat_splus1, Bss_params) BIss_params = (0.0, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS') BIss = firm.get_I(bssmat_splus1, Bss, Bss, BIss_params) if budget_balance: debt_ss = 0.0 else: debt_ss = debt_ratio_ss * Y # Yss_params = (alpha, Z) Yss_params = (Z, gamma, epsilon) Yss = firm.get_Y(Kss, Lss, Yss_params) # Verify that T_Hss = alpha_T*Yss # transfer_error = T_Hss - alpha_T*Yss # if np.absolute(transfer_error) > mindist_SS: # print 'Transfers exceed alpha_T percent of GDP by:', transfer_error # err = "Transfers do not match correct share of GDP in SS_solver" # raise RuntimeError(err) BQss = new_BQ theta_params = (e, S, retire) theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, theta_params) # Next 5 lines pulled out of inner_loop where they are used to calculate tax revenue. Now calculating G to balance gov't budget. b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) lump_sum_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) revenue_ss = tax.revenue(new_r, new_w, b_s, nssmat, new_BQ, Yss, Lss, Kss, factor, lump_sum_params) r_gov_ss = rss debt_service_ss = r_gov_ss * debt_ratio_ss * Yss new_borrowing = debt_ratio_ss * Yss * ((1 + g_n_ss) * np.exp(g_y) - 1) # government spends such that it expands its debt at the same rate as GDP if budget_balance: Gss = 0.0 else: Gss = revenue_ss + new_borrowing - (T_Hss + debt_service_ss) # solve resource constraint etr_params_3D = np.tile( np.reshape(etr_params, (S, 1, etr_params.shape[1])), (1, J, 1)) mtrx_params_3D = np.tile( np.reshape(mtrx_params, (S, 1, mtrx_params.shape[1])), (1, J, 1)) ''' ------------------------------------------------------------------------ The code below is to calulate and save model MTRs - only exists to help debug ------------------------------------------------------------------------ ''' # etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:] # etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1)) # mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:] # mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1)) # e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J))) # nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J))) # mtry_ss_params = (e_extended[1:,:], etr_params_extended_3D, mtry_params_extended_3D, analytical_mtrs) # mtry_ss = tax.MTR_capital(rss, wss, bssmat_splus1, nss_extended[1:,:], factor_ss, mtry_ss_params) # mtrx_ss_params = (e, etr_params_3D, mtrx_params_3D, analytical_mtrs) # mtrx_ss = tax.MTR_labor(rss, wss, bssmat_s, nssmat, factor_ss, mtrx_ss_params) # np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",") # np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",") # solve resource constraint taxss_params = (e, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) taxss = tax.total_taxes(rss, wss, bssmat_s, nssmat, BQss, factor_ss, T_Hss, None, False, taxss_params) css_params = (e, lambdas.reshape(1, J), g_y) cssmat = household.get_cons(rss, wss, bssmat_s, bssmat_splus1, nssmat, BQss.reshape(1, J), taxss, css_params) biz_params = (tau_b, delta_tau) business_revenue = tax.get_biz_tax(wss, Yss, Lss, Kss, biz_params) Css_params = (omega_SS.reshape(S, 1), lambdas, 'SS') Css = household.get_C(cssmat, Css_params) if small_open == False: resource_constraint = Yss - (Css + Iss + Gss) print 'Yss= ', Yss, '\n', 'Gss= ', Gss, '\n', 'Css= ', Css, '\n', 'Kss = ', Kss, '\n', 'Iss = ', Iss, '\n', 'Lss = ', Lss, '\n', 'Debt service = ', debt_service_ss print 'D/Y:', debt_ss / Yss, 'T/Y:', T_Hss / Yss, 'G/Y:', Gss / Yss, 'Rev/Y:', revenue_ss / Yss, 'business rev/Y: ', business_revenue / Yss, 'Int payments to GDP:', ( rss * debt_ss) / Yss print 'Check SS budget: ', Gss - (np.exp(g_y) * (1 + g_n_ss) - 1 - rss) * debt_ss - revenue_ss + T_Hss print 'resource constraint: ', resource_constraint else: # include term for current account resource_constraint = Yss + new_borrowing - (Css + BIss + Gss) + ( ss_hh_r * Bss - (delta + ss_firm_r) * Kss - debt_service_ss) print 'Yss= ', Yss, '\n', 'Css= ', Css, '\n', 'Bss = ', Bss, '\n', 'BIss = ', BIss, '\n', 'Kss = ', Kss, '\n', 'Iss = ', Iss, '\n', 'Lss = ', Lss, '\n', 'T_H = ', T_H, '\n', 'Gss= ', Gss print 'D/Y:', debt_ss / Yss, 'T/Y:', T_Hss / Yss, 'G/Y:', Gss / Yss, 'Rev/Y:', revenue_ss / Yss, 'Int payments to GDP:', ( rss * debt_ss) / Yss print 'resource constraint: ', resource_constraint if Gss < 0: print 'Steady state government spending is negative to satisfy budget' if ENFORCE_SOLUTION_CHECKS and np.absolute( resource_constraint) > mindist_SS: print 'Resource Constraint Difference:', resource_constraint err = "Steady state aggregate resource constraint not satisfied" raise RuntimeError(err) # check constraints household.constraint_checker_SS(bssmat, nssmat, cssmat, ltilde) euler_savings = euler_errors[:S, :] euler_labor_leisure = euler_errors[S:, :] ''' ------------------------------------------------------------------------ Return dictionary of SS results ------------------------------------------------------------------------ ''' output = { 'Kss': Kss, 'bssmat': bssmat, 'Bss': Bss, 'Lss': Lss, 'Css': Css, 'Iss': Iss, 'nssmat': nssmat, 'Yss': Yss, 'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'T_Hss': T_Hss, 'Gss': Gss, 'revenue_ss': revenue_ss, 'euler_savings': euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n, 'chi_b': chi_b } return output
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 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 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_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 SS_solver(b_guess_init, n_guess_init, wss, rss, T_Hss, BQss, factor_ss, params, baseline, fsolve_flag=False): ''' -------------------------------------------------------------------- Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using a bisection method similar to TPI. -------------------------------------------------------------------- INPUTS: b_guess_init = [S,J] array, initial guesses for savings n_guess_init = [S,J] array, initial guesses for labor supply wguess = scalar, initial guess for SS real wage rate rguess = scalar, initial guess for SS real interest rate T_Hguess = scalar, initial guess for lump sum transfer factorguess = scalar, initial guess for scaling factor to dollars chi_b = [J,] vector, chi^b_j, the utility weight on bequests chi_n = [S,] vector, chi^n_s utility weight on labor supply params = lenght X tuple, list of parameters iterative_params = length X tuple, list of parameters that determine the convergence of the while loop tau_bq = [J,] vector, bequest tax rate rho = [S,] vector, mortality rates by age lambdas = [J,] vector, fraction of population with each ability type omega = [S,] vector, stationary population weights e = [S,J] array, effective labor units by age and ability type OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: 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() utils.convex_combo() utils.pct_diff_func() OBJECTS CREATED WITHIN FUNCTION: b_guess = [S,] vector, initial guess at household savings n_guess = [S,] vector, initial guess at household labor supply b_s = [S,] vector, wealth enter period with b_splus1 = [S,] vector, household savings b_splus2 = [S,] vector, household savings one period ahead BQ = scalar, aggregate bequests to lifetime income group theta = scalar, replacement rate for social security benenfits error1 = [S,] vector, errors from FOC for savings error2 = [S,] vector, errors from FOC for labor supply tax1 = [S,] vector, total income taxes paid cons = [S,] vector, household consumption RETURNS: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 array) OUTPUT: None -------------------------------------------------------------------- ''' bssmat, nssmat, chi_params, ss_params, income_tax_params, iterative_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 maxiter, mindist_SS = iterative_params # Rename the inputs w = wss r = rss T_H = T_Hss BQ = BQss factor = factor_ss 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 outer_loop_vars = (bssmat, nssmat, r, w, T_H, factor) inner_loop_params = (ss_params, income_tax_params, chi_params) euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_BQ, new_theta, new_factor, average_income_model = inner_loop(outer_loop_vars, inner_loop_params, baseline) # print 'T_H: ', T_H, new_T_H # print 'factor: ', factor, new_factor # print 'interest rate: ', r, new_r # print 'wage rate: ', w, new_w 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) BQ = utils.convex_combo(new_BQ, BQ, nu) theta = utils.convex_combo(new_theta, theta, nu) if T_H != 0: dist = np.array([utils.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [utils.pct_diff_func(new_T_H, T_H)] + [utils.pct_diff_func(new_BQ, BQ)] + [utils.pct_diff_func(new_theta, theta)] + [utils.pct_diff_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.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [abs(new_T_H - T_H)] + [utils.pct_diff_func(new_BQ, BQ)] + [utils.pct_diff_func(new_theta, theta)] + [utils.pct_diff_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 ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' bssmat_s = np.append(np.zeros((1,J)),bssmat[:-1,:],axis=0) bssmat_splus1 = bssmat wss = w rss = r factor_ss = factor T_Hss = T_H Kss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS') Kss = household.get_K(bssmat_splus1, Kss_params) Lss_params = (e, omega_SS.reshape(S, 1), lambdas, 'SS') Lss = firm.get_L(nssmat, Lss_params) Yss_params = (alpha, Z) Yss = firm.get_Y(Kss, Lss, Yss_params) Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS') Iss = firm.get_I(bssmat_splus1, Kss, Kss, Iss_params) BQss = new_BQ # theta_params = (e, S, J, omega_SS.reshape(S, 1), lambdas,retire) # theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, theta_params) # solve resource constraint etr_params_3D = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1)) mtrx_params_3D = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1)) taxss_params = (e, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) taxss = tax.total_taxes(rss, wss, bssmat_s, nssmat, BQss, factor_ss, T_Hss, None, False, taxss_params) css_params = (e, lambdas.reshape(1, J), g_y) cssmat = household.get_cons(rss, wss, bssmat_s, bssmat_splus1, nssmat, BQss.reshape( 1, J), taxss, css_params) Css_params = (omega_SS.reshape(S, 1), lambdas, 'SS') Css = household.get_C(cssmat, Css_params) resource_constraint = Yss - (Css + Iss) ''' ------------------------------------------------------------------------ The code below is to calulate and save model MTRs - only exists to help debug ------------------------------------------------------------------------ ''' # etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:] # etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1)) # mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:] # mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1)) # e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J))) # nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J))) # mtry_ss_params = (e_extended[1:,:], etr_params_extended_3D, mtry_params_extended_3D, analytical_mtrs) # mtry_ss = tax.MTR_capital(rss, wss, bssmat_splus1, nss_extended[1:,:], factor_ss, mtry_ss_params) # mtrx_ss_params = (e, etr_params_3D, mtrx_params_3D, analytical_mtrs) # mtrx_ss = tax.MTR_labor(rss, wss, bssmat_s, nssmat, factor_ss, mtrx_ss_params) # # etr_ss_params = (e, etr_params_3D) # etr_ss = tax.tau_income(rss, wss, bssmat_s, nssmat, factor_ss, etr_ss_params) # # np.savetxt("etr_ss.csv", etr_ss, delimiter=",") # np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",") # np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",") print 'interest rate: ', rss print 'wage rate: ', wss print 'factor: ', factor_ss print 'T_H', T_Hss print 'Resource Constraint Difference:', resource_constraint print 'Max Euler Error: ', (np.absolute(euler_errors)).max() if ENFORCE_SOLUTION_CHECKS and np.absolute(resource_constraint) > 1e-8: err = "Steady state aggregate resource constraint not satisfied" raise RuntimeError(err) # check constraints household.constraint_checker_SS(bssmat, nssmat, cssmat, ltilde) if np.absolute(resource_constraint) > 1e-8 or (np.absolute(euler_errors)).max() > 1e-8: ss_flag = 1 else: ss_flag = 0 euler_savings = euler_errors[:S,:] euler_labor_leisure = euler_errors[S:,:] ''' ------------------------------------------------------------------------ Return dictionary of SS results ------------------------------------------------------------------------ ''' output = {'Kss': Kss, 'bssmat': bssmat, 'Lss': Lss, 'Css':Css, 'Iss':Iss, 'nssmat': nssmat, 'Yss': Yss,'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'T_Hss': T_Hss, 'euler_savings': euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n, 'chi_b': chi_b, 'ss_flag':ss_flag} return output
def run_steady_state(income_tax_parameters, ss_parameters, iterative_params, get_baseline=False, calibrate_model=False, output_dir="./OUTPUT"): ''' ------------------------------------------------------------------------ Run SS ------------------------------------------------------------------------ ''' 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 = ss_parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_parameters # Generate initial guesses for chi^b_j and chi^n_s chi_params = np.zeros(S + J) chi_params[:J] = chi_b_guess chi_params[J:] = chi_n_guess # First run SS simulation with guesses at initial values for b, n, w, r, etc # For inital guesses of b and n, we choose very small b, and medium n b_guess = np.ones((S, J)).flatten() * .05 n_guess = np.ones((S, J)).flatten() * .4 * ltilde # For initial guesses of w, r, T_H, and factor, we use values that are close # to some steady state values. wguess = 1.2 rguess = .06 T_Hguess = 0.12 factorguess = 70000.0 guesses = [wguess, rguess, T_Hguess, factorguess] args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params[J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve, guesses, args=args_, xtol=mindist_SS, full_output=True) [wguess, rguess, T_Hguess, factorguess] = solutions fsolve_flag = True solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e, fsolve_flag) if calibrate_model: global Nfeval, value_all, chi_params_all Nfeval = 1 value_all = np.zeros((10000)) chi_params_all = np.zeros((S + J, 10000)) outputs = {'solutions': solutions, 'chi_params': chi_params} ss_init_path = os.path.join(output_dir, "Saved_moments/SS_init_solutions.pkl") pickle.dump(outputs, open(ss_init_path, "wb")) function_to_minimize_X = lambda x: function_to_minimize( x, chi_params, income_tax_parameters, ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir) bnds = tuple([(1e-6, None)] * (S + J)) # In order to scale all the parameters to estimate in the minimizer, we have the minimizer fit a vector of ones that # will be multiplied by the chi initial guesses inside the function. Otherwise, if chi^b_j=1e5 for some j, and the # minimizer peturbs that value by 1e-8, the % difference will be extremely small, outside of the tolerance of the # minimizer, and it will not change that parameter. chi_params_scalars = np.ones(S + J) #chi_params_scalars = opt.minimize(function_to_minimize_X, chi_params_scalars, # method='TNC', tol=MINIMIZER_TOL, bounds=bnds, callback=callbackF(chi_params_scalars), options=MINIMIZER_OPTIONS).x # chi_params_scalars = opt.minimize(function_to_minimize, chi_params_scalars, # args=(chi_params, income_tax_parameters, ss_parameters, iterative_params, # omega_SS, rho, lambdas, tau_bq, e, output_dir), # method='TNC', tol=MINIMIZER_TOL, bounds=bnds, # callback=callbackF(chi_params_scalars,chi_params, income_tax_parameters, # ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir), # options=MINIMIZER_OPTIONS).x chi_params_scalars = opt.minimize( function_to_minimize, chi_params_scalars, args=(chi_params, income_tax_parameters, ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir), method='TNC', tol=MINIMIZER_TOL, bounds=bnds, options=MINIMIZER_OPTIONS).x chi_params *= chi_params_scalars print 'The final scaling params', chi_params_scalars print 'The final bequest parameter values:', chi_params solutions_dict = pickle.load(open(ss_init_path, "rb")) solutions = solutions_dict['solutions'] b_guess = solutions[:S * J] n_guess = solutions[S * J:2 * S * J] wguess, rguess, factorguess, T_Hguess = solutions[2 * S * J:] guesses = [wguess, rguess, T_Hguess, factorguess] args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params[J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve, guesses, args=args_, xtol=mindist_SS, full_output=True) [wguess, rguess, T_Hguess, factorguess] = solutions fsolve_flag = True solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e, fsolve_flag) ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' if get_baseline: outputs = {'solutions': solutions, 'chi_params': chi_params} ss_init_dir = os.path.join(output_dir, "Saved_moments/SS_baseline_solutions.pkl") pickle.dump(outputs, open(ss_init_dir, "wb")) else: outputs = {'solutions': solutions, 'chi_params': chi_params} ss_exp_dir = os.path.join(output_dir, "Saved_moments/SS_reform_solutions.pkl") pickle.dump(outputs, open(ss_exp_dir, "wb")) bssmat = solutions[0:(S - 1) * J].reshape(S - 1, J) bq = solutions[ (S - 1) * J:S * J] # technically, this is just the intentional bequests - wealth of those with max age bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat)) bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J))) nssmat = solutions[S * J:2 * S * J].reshape(S, J) wss, rss, factor_ss, T_Hss = solutions[2 * S * J:] Kss = household.get_K(bssmat_splus1, omega_SS.reshape(S, 1), lambdas, g_n_ss, 'SS') Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas, 'SS') Yss = firm.get_Y(Kss, Lss, ss_parameters) Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss) theta = np.zeros(J) #tax.replacement_rate_vals( #nssmat, wss, factor_ss, e, J, omega_SS.reshape(S, 1), lambdas) BQss = household.get_BQ(rss, bssmat_splus1, omega_SS.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_ss, 'SS') b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) etr_params_3D = np.tile( np.reshape(etr_params, (S, 1, etr_params.shape[1])), (1, J, 1)) mtrx_params_3D = np.tile( np.reshape(mtrx_params, (S, 1, mtrx_params.shape[1])), (1, J, 1)) etr_params_extended = np.append(etr_params, np.reshape(etr_params[-1, :], (1, etr_params.shape[1])), axis=0)[1:, :] etr_params_extended_3D = np.tile( np.reshape(etr_params_extended, (S, 1, etr_params_extended.shape[1])), (1, J, 1)) mtry_params_extended = np.append(mtry_params, np.reshape(mtry_params[-1, :], (1, mtry_params.shape[1])), axis=0)[1:, :] mtry_params_extended_3D = np.tile( np.reshape(mtry_params_extended, (S, 1, mtry_params_extended.shape[1])), (1, J, 1)) e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J))) nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J))) mtry_ss = tax.MTR_capital(rss, bssmat_splus1, wss, e_extended[1:, :], nss_extended[1:, :], factor_ss, analytical_mtrs, etr_params_extended_3D, mtry_params_extended_3D) mtrx_ss = tax.MTR_labor(rss, bssmat_s, wss, e, nssmat, factor_ss, analytical_mtrs, etr_params_3D, mtrx_params_3D) np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",") np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",") taxss_params = (J, S, retire, np.tile( np.reshape(etr_params, (S, 1, etr_params.shape[1])), (1, J, 1)), h_wealth, p_wealth, m_wealth, tau_payroll) taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas, factor_ss, T_Hss, None, 'SS', False, taxss_params, theta, tau_bq) cssmat = household.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape(1, J), lambdas.reshape(1, J), bssmat_splus1, ss_parameters, taxss) Css = household.get_C(cssmat, omega_SS.reshape(S, 1), lambdas, 'SS') resource_constraint = Yss - (Css + Iss) print 'Resource Constraint Difference:', resource_constraint constraint_params = ltilde household.constraint_checker_SS(bssmat, nssmat, cssmat, constraint_params) b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) b_splus1 = bssmat_splus1 b_splus2 = np.array( list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J)))) chi_b = np.tile(chi_params[:J].reshape(1, J), (S, 1)) chi_n = np.array(chi_params[J:]) euler_savings = np.zeros((S, J)) euler_labor_leisure = np.zeros((S, J)) for j in xrange(J): euler_savings[:, j] = household.euler_savings_func( wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], b_splus2[:, j], BQss[j], factor_ss, T_Hss, chi_b[:, j], income_tax_parameters, ss_parameters, theta[j], tau_bq[j], rho, lambdas[j]) euler_labor_leisure[:, j] = household.euler_labor_leisure_func( wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], BQss[j], factor_ss, T_Hss, chi_n, income_tax_parameters, ss_parameters, theta[j], tau_bq[j], lambdas[j]) ''' ------------------------------------------------------------------------ Save the values in various ways, depending on the stage of the simulation, to be used in TPI or graphing functions ------------------------------------------------------------------------ ''' # Pickle variables output = { 'Kss': Kss, 'bssmat': bssmat, 'Lss': Lss, 'Css': Css, 'nssmat': nssmat, 'Yss': Yss, 'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'T_Hss': T_Hss, 'euler_savings': euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n, 'chi_b': chi_b } utils.mkdirs(os.path.join(output_dir, "SSinit")) ss_init_dir = os.path.join(output_dir, "SSinit/ss_init_vars.pkl") pickle.dump(output, open(ss_init_dir, "wb")) bssmat_init = bssmat_splus1 nssmat_init = nssmat # Pickle variables for TPI initial values output2 = {'bssmat_init': bssmat_init, 'nssmat_init': nssmat_init} ss_init_tpi = os.path.join(output_dir, "SSinit/ss_init_tpi_vars.pkl") pickle.dump(output2, open(ss_init_tpi, "wb")) return output
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 run_steady_state(ss_parameters, iterative_params, get_baseline=False, calibrate_model=False): ''' ------------------------------------------------------------------------ Run SS ------------------------------------------------------------------------ ''' if get_baseline: # Generate initial guesses for chi^b_j and chi^n_s chi_params = np.zeros(S+J) chi_params[:J] = chi_b_guess chi_params[J:] = chi_n_guess # First run SS simulation with guesses at initial values for b, n, w, r, etc # For inital guesses of b and n, we choose very small b, and medium n b_guess = np.ones((S, J)).flatten() * .01 n_guess = np.ones((S, J)).flatten() * .5 * ltilde # For initial guesses of w, r, T_H, and factor, we use values that are close # to some steady state values. wguess = 1.2 rguess = .06 T_Hguess = 0 factorguess = 100000 solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) if calibrate_model: outputs = {'solutions':solutions, 'chi_params':chi_params} pickle.dump(outputs, open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "wb")) function_to_minimize_X = lambda x: function_to_minimize(x, chi_params, ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e) bnds = tuple([(1e-6, None)] * (S + J)) # In order to scale all the parameters to estimate in the minimizer, we have the minimizer fit a vector of ones that # will be multiplied by the chi initial guesses inside the function. Otherwise, if chi^b_j=1e5 for some j, and the # minimizer peturbs that value by 1e-8, the % difference will be extremely small, outside of the tolerance of the # minimizer, and it will not change that parameter. chi_params_scalars = np.ones(S+J) chi_params_scalars = opt.minimize(function_to_minimize_X, chi_params_scalars, method='TNC', tol=MINIMIZER_TOL, bounds=bnds, options=MINIMIZER_OPTIONS).x chi_params *= chi_params_scalars print 'The final scaling params', chi_params_scalars print 'The final bequest parameter values:', chi_params solutions_dict = pickle.load(open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "rb")) solutions = solutions_dict['solutions'] b_guess = solutions[:S*J] n_guess = solutions[S*J:2*S*J] wguess, rguess, factorguess, T_Hguess = solutions[2*S*J:] solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) else: variables = pickle.load(open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "rb")) solutions = solutions_dict['solutions'] chi_params = solutions_dict['chi_params'] b_guess = solutions[:S*J] n_guess = solutions[S*J:2*S*J] wguess, rguess, factorguess, T_Hguess = solutions[2*S*J:] solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' if get_baseline: outputs = {'solutions':solutions, 'chi_params':chi_params} pickle.dump(outputs, open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "wb")) else: outputs = {'solutions':solutions, 'chi_params':chi_params} pickle.dump(outputs, open("OUTPUT/Saved_moments/SS_experiment_solutions.pkl", "wb")) bssmat = solutions[0:(S-1) * J].reshape(S-1, J) bq = solutions[(S-1)*J:S*J] bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat)) bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J))) nssmat = solutions[S * J:2*S*J].reshape(S, J) wss, rss, factor_ss, T_Hss = solutions[2*S*J:] Kss = household.get_K(bssmat_splus1, omega_SS.reshape(S, 1), lambdas, g_n_ss, 'SS') Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas, 'SS') Yss = firm.get_Y(Kss, Lss, ss_parameters) Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss) theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, e, J, omega_SS.reshape(S, 1), lambdas) BQss = household.get_BQ(rss, bssmat_splus1, omega_SS.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_ss, 'SS') b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas, factor_ss, T_Hss, None, 'SS', False, ss_parameters, theta, tau_bq) cssmat = household.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape(1, J), lambdas.reshape(1, J), bssmat_splus1, ss_parameters, taxss) Css = household.get_C(cssmat, omega_SS.reshape(S, 1), lambdas, 'SS') resource_constraint = Yss - (Css + Iss) print 'Resource Constraint Difference:', resource_constraint household.constraint_checker_SS(bssmat, nssmat, cssmat, ss_parameters) b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) b_splus1 = bssmat_splus1 b_splus2 = np.array(list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J)))) chi_b = np.tile(chi_params[:J].reshape(1, J), (S, 1)) chi_n = np.array(chi_params[J:]) euler_savings = np.zeros((S, J)) euler_labor_leisure = np.zeros((S, J)) for j in xrange(J): euler_savings[:, j] = household.euler_savings_func(wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], b_splus2[:, j], BQss[j], factor_ss, T_Hss, chi_b[:, j], ss_parameters, theta[j], tau_bq[j], rho, lambdas[j]) euler_labor_leisure[:, j] = household.euler_labor_leisure_func(wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], BQss[j], factor_ss, T_Hss, chi_n, ss_parameters, theta[j], tau_bq[j], lambdas[j]) ''' ------------------------------------------------------------------------ Save the values in various ways, depending on the stage of the simulation, to be used in TPI or graphing functions ------------------------------------------------------------------------ ''' # Pickle variables output = {'Kss':Kss, 'bssmat':bssmat, 'Lss':Lss, 'nssmat':nssmat, 'Yss':Yss, 'wss':wss, 'rss':rss, 'theta':theta, 'BQss':BQss, 'factor_ss':factor_ss, 'bssmat_s':bssmat_s, 'cssmat':cssmat, 'bssmat_splus1':bssmat_splus1, 'T_Hss':T_Hss, 'euler_savings':euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'chi_n':chi_n, 'chi_b':chi_b} if get_baseline: pickle.dump(output, open("OUTPUT/SSinit/ss_init_vars.pkl", "wb")) bssmat_init = bssmat_splus1 nssmat_init = nssmat # Pickle variables for TPI initial values output2 = {'bssmat_init':bssmat_init, 'nssmat_init':nssmat_init} pickle.dump(output2, open("OUTPUT/SSinit/ss_init_tpi_vars.pkl", "wb")) else: pickle.dump(output, open("OUTPUT/SS/ss_vars.pkl", "wb")) return output
def TP_solutions(winit, rinit, T_H_init, BQinit2, 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): ''' This function returns the solutions for all variables along the time path. ''' 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 print 'Computing final solutions' # Extend time paths past T winit = np.array(list(winit) + list(np.ones(S) * wss)) rinit = np.array(list(rinit) + list(np.ones(S) * rss)) T_H_init = np.array(list(T_H_init) + list(np.ones(S) * T_Hss)) BQinit = np.zeros((T + S, J)) for j in xrange(J): BQinit[:, j] = list(BQinit2[:,j]) + [BQss[j]] * S BQinit = np.array(BQinit) # Make array of initial guesses 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) # initialize array of Euler errors euler_errors = np.zeros((T, 2 * S, J)) # 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, income_tax_params, 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)) # 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 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)) b_mat[0, :, :] = initial_b ''' ------------------------------------------------------------------------ Generate variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' 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') 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, :, :] # initialize array 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 = J, S, retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll tax_path = tax.total_taxes(np.tile(rinit[:T].reshape(T, 1, 1),(1,S,J)), b_s, np.tile(winit[:T].reshape(T, 1, 1),(1,S,J)), np.tile(e.reshape(1, S, J),(T,1,1)), n_mat[:T,:,:], BQinit[:T, :].reshape(T, 1, J), lambdas, factor_ss, T_H_init[:T].reshape(T, 1, 1), None, 'TPI', False, tax_path_params, 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.' hh_constraint_params = ltilde for t in xrange(T): household.constraint_checker_TPI( b_mat[t], n_mat[t], c_path[t], t, hh_constraint_params) 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 ''' ------------------------------------------------------------------------ Create the unstationarized versions of the paths of macro aggregates ------------------------------------------------------------------------ ''' # tvec = np.linspace(0, len(C_path), len(C_path)) # growth_path = np.exp(g_y*tvec) # pop_path = np.zeros(len(C_path)) # for i in range(0,len(C_path)): # pop_path[i] = np.exp(g_n_vector[:i].sum()) # note that this normalizes the pop in the initial period to one # growth_pop_path = growth_path*pop_path # C_ns_path = C_path * growth_pop_path # K_ns_path = Kinit * growth_pop_path # BQ_ns_path = growth_pop_path * BQinit[:T] # L_ns_path = Linit * pop_path # T_H_ns_path = T_H_init[:T] * growth_pop_path # w_ns_path = winit*growth_path # I_ns_path = I_path * growth_pop_path # Y_ns_path = Y_path * growth_pop_path ''' ------------------------------------------------------------------------ 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, 'Y_path': Y_path, 'T_H_init': T_H_init, 'tax_path': tax_path, 'winit': winit} macro_output = {'Kpath_TPI': Kpath_TPI, 'C_path': C_path, 'I_path': I_path, 'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI, 'rinit': rinit, 'Y_path': Y_path, 'T_H_init': T_H_init, 'winit': winit, 'tax_path': tax_path} # 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} 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")) tpi_dir = os.path.join(output_dir, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_macro_vars.pkl") pickle.dump(macro_output, open(tpi_vars, "wb"))
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 SS_solver(b_guess_init, n_guess_init, rss, wss, T_Hss, factor_ss, Yss, params, baseline, fsolve_flag=False, baseline_spending=False): ''' -------------------------------------------------------------------- Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using a bisection method similar to TPI. -------------------------------------------------------------------- INPUTS: b_guess_init = [S,J] array, initial guesses for savings n_guess_init = [S,J] array, initial guesses for labor supply wguess = scalar, initial guess for SS real wage rate rguess = scalar, initial guess for SS real interest rate T_Hguess = scalar, initial guess for lump sum transfer factorguess = scalar, initial guess for scaling factor to dollars chi_b = [J,] vector, chi^b_j, the utility weight on bequests chi_n = [S,] vector, chi^n_s utility weight on labor supply params = length X tuple, list of parameters iterative_params = length X tuple, list of parameters that determine the convergence of the while loop tau_bq = [J,] vector, bequest tax rate rho = [S,] vector, mortality rates by age lambdas = [J,] vector, fraction of population with each ability type omega = [S,] vector, stationary population weights e = [S,J] array, effective labor units by age and ability type OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: 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() utils.convex_combo() utils.pct_diff_func() OBJECTS CREATED WITHIN FUNCTION: b_guess = [S,] vector, initial guess at household savings n_guess = [S,] vector, initial guess at household labor supply b_s = [S,] vector, wealth enter period with b_splus1 = [S,] vector, household savings b_splus2 = [S,] vector, household savings one period ahead BQ = scalar, aggregate bequests to lifetime income group theta = scalar, replacement rate for social security benenfits error1 = [S,] vector, errors from FOC for savings error2 = [S,] vector, errors from FOC for labor supply tax1 = [S,] vector, total income taxes paid cons = [S,] vector, household consumption OBJECTS CREATED WITHIN FUNCTION - SMALL OPEN ONLY Bss = scalar, aggregate household wealth in the steady state BIss = scalar, aggregate household net investment in the steady state RETURNS: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 array) OUTPUT: None -------------------------------------------------------------------- ''' bssmat, nssmat, chi_params, ss_params, income_tax_params, iterative_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 maxiter, mindist_SS = iterative_params small_open, ss_firm_r, ss_hh_r = small_open_params # Rename the inputs r = rss w = wss T_H = T_Hss factor = factor_ss if budget_balance == False: if baseline_spending == True: Y = Yss else: Y = T_H / alpha_T if small_open == True: r = ss_hh_r 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, Y and # factor if budget_balance: outer_loop_vars = (bssmat, nssmat, r, w, T_H, factor) else: outer_loop_vars = (bssmat, nssmat, r, w, Y, T_H, factor) inner_loop_params = (ss_params, income_tax_params, chi_params, small_open_params) euler_errors, bssmat, nssmat, new_r, new_w, \ new_T_H, new_Y, new_factor, new_BQ, average_income_model = inner_loop(outer_loop_vars, inner_loop_params, baseline, baseline_spending) r = utils.convex_combo(new_r, r, nu) w = utils.convex_combo(new_w, w, nu) factor = utils.convex_combo(new_factor, factor, nu) if budget_balance: T_H = utils.convex_combo(new_T_H, T_H, nu) dist = np.array([utils.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [utils.pct_diff_func(new_T_H, T_H)] + [utils.pct_diff_func(new_factor, factor)]).max() else: Y = utils.convex_combo(new_Y, Y, nu) if Y != 0: dist = np.array([utils.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [utils.pct_diff_func(new_Y, Y)] + [utils.pct_diff_func(new_factor, factor)]).max() else: # If Y is zero (if there is no output), a percent difference # will throw NaN's, so we use an absoluate difference dist = np.array([utils.pct_diff_func(new_r, r)] + [utils.pct_diff_func(new_w, w)] + [abs(new_Y - Y)] + [utils.pct_diff_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 ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' bssmat_s = np.append(np.zeros((1,J)),bssmat[:-1,:],axis=0) bssmat_splus1 = bssmat rss = r wss = w factor_ss = factor T_Hss = T_H Lss_params = (e, omega_SS.reshape(S, 1), lambdas, 'SS') Lss = firm.get_L(nssmat, Lss_params) if small_open == False: Kss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS') Bss = household.get_K(bssmat_splus1, Kss_params) if budget_balance: debt_ss = 0.0 else: debt_ss = debt_ratio_ss*Y Kss = Bss - debt_ss Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS') Iss = firm.get_I(bssmat_splus1, Kss, Kss, Iss_params) else: # Compute capital (K) and wealth (B) separately Kss_params = (Z, gamma, epsilon, delta, tau_b, delta_tau) Kss = firm.get_K(Lss, ss_firm_r, Kss_params) Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS') InvestmentPlaceholder = np.zeros(bssmat_splus1.shape) Iss = firm.get_I(InvestmentPlaceholder, Kss, Kss, Iss_params) Bss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS') Bss = household.get_K(bssmat_splus1, Bss_params) BIss_params = (0.0, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS') BIss = firm.get_I(bssmat_splus1, Bss, Bss, BIss_params) if budget_balance: debt_ss = 0.0 else: debt_ss = debt_ratio_ss*Y # Yss_params = (alpha, Z) Yss_params = (Z, gamma, epsilon) Yss = firm.get_Y(Kss, Lss, Yss_params) # Verify that T_Hss = alpha_T*Yss # transfer_error = T_Hss - alpha_T*Yss # if np.absolute(transfer_error) > mindist_SS: # print 'Transfers exceed alpha_T percent of GDP by:', transfer_error # err = "Transfers do not match correct share of GDP in SS_solver" # raise RuntimeError(err) BQss = new_BQ theta_params = (e, S, retire) theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, theta_params) # Next 5 lines pulled out of inner_loop where they are used to calculate tax revenue. Now calculating G to balance gov't budget. b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) lump_sum_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) revenue_ss = tax.revenue(new_r, new_w, b_s, nssmat, new_BQ, Yss, Lss, Kss, factor, lump_sum_params) r_gov_ss = rss debt_service_ss = r_gov_ss*debt_ratio_ss*Yss new_borrowing = debt_ratio_ss*Yss*((1+g_n_ss)*np.exp(g_y)-1) # government spends such that it expands its debt at the same rate as GDP if budget_balance: Gss = 0.0 else: Gss = revenue_ss + new_borrowing - (T_Hss + debt_service_ss) # solve resource constraint etr_params_3D = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1)) mtrx_params_3D = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1)) ''' ------------------------------------------------------------------------ The code below is to calulate and save model MTRs - only exists to help debug ------------------------------------------------------------------------ ''' # etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:] # etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1)) # mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:] # mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1)) # e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J))) # nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J))) # mtry_ss_params = (e_extended[1:,:], etr_params_extended_3D, mtry_params_extended_3D, analytical_mtrs) # mtry_ss = tax.MTR_capital(rss, wss, bssmat_splus1, nss_extended[1:,:], factor_ss, mtry_ss_params) # mtrx_ss_params = (e, etr_params_3D, mtrx_params_3D, analytical_mtrs) # mtrx_ss = tax.MTR_labor(rss, wss, bssmat_s, nssmat, factor_ss, mtrx_ss_params) # np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",") # np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",") # solve resource constraint taxss_params = (e, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) taxss = tax.total_taxes(rss, wss, bssmat_s, nssmat, BQss, factor_ss, T_Hss, None, False, taxss_params) css_params = (e, lambdas.reshape(1, J), g_y) cssmat = household.get_cons(rss, wss, bssmat_s, bssmat_splus1, nssmat, BQss.reshape( 1, J), taxss, css_params) biz_params = (tau_b, delta_tau) business_revenue = tax.get_biz_tax(wss, Yss, Lss, Kss, biz_params) Css_params = (omega_SS.reshape(S, 1), lambdas, 'SS') Css = household.get_C(cssmat, Css_params) if small_open == False: resource_constraint = Yss - (Css + Iss + Gss) print 'Yss= ', Yss, '\n', 'Gss= ', Gss, '\n', 'Css= ', Css, '\n', 'Kss = ', Kss, '\n', 'Iss = ', Iss, '\n', 'Lss = ', Lss, '\n', 'Debt service = ', debt_service_ss print 'D/Y:', debt_ss/Yss, 'T/Y:', T_Hss/Yss, 'G/Y:', Gss/Yss, 'Rev/Y:', revenue_ss/Yss, 'business rev/Y: ', business_revenue/Yss, 'Int payments to GDP:', (rss*debt_ss)/Yss print 'Check SS budget: ', Gss - (np.exp(g_y)*(1+g_n_ss)-1-rss)*debt_ss - revenue_ss + T_Hss print 'resource constraint: ', resource_constraint else: # include term for current account resource_constraint = Yss + new_borrowing - (Css + BIss + Gss) + (ss_hh_r * Bss - (delta + ss_firm_r) * Kss - debt_service_ss) print 'Yss= ', Yss, '\n', 'Css= ', Css, '\n', 'Bss = ', Bss, '\n', 'BIss = ', BIss, '\n', 'Kss = ', Kss, '\n', 'Iss = ', Iss, '\n', 'Lss = ', Lss, '\n', 'T_H = ', T_H,'\n', 'Gss= ', Gss print 'D/Y:', debt_ss/Yss, 'T/Y:', T_Hss/Yss, 'G/Y:', Gss/Yss, 'Rev/Y:', revenue_ss/Yss, 'Int payments to GDP:', (rss*debt_ss)/Yss print 'resource constraint: ', resource_constraint if Gss < 0: print 'Steady state government spending is negative to satisfy budget' if ENFORCE_SOLUTION_CHECKS and np.absolute(resource_constraint) > mindist_SS: print 'Resource Constraint Difference:', resource_constraint err = "Steady state aggregate resource constraint not satisfied" raise RuntimeError(err) # check constraints household.constraint_checker_SS(bssmat, nssmat, cssmat, ltilde) euler_savings = euler_errors[:S,:] euler_labor_leisure = euler_errors[S:,:] ''' ------------------------------------------------------------------------ Return dictionary of SS results ------------------------------------------------------------------------ ''' output = {'Kss': Kss, 'bssmat': bssmat, 'Bss': Bss, 'Lss': Lss, 'Css':Css, 'Iss':Iss, 'nssmat': nssmat, 'Yss': Yss, 'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'T_Hss': T_Hss, 'Gss': Gss, 'revenue_ss': revenue_ss, 'euler_savings': euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n, 'chi_b': chi_b} return output
def run_TPI(income_tax_params, tpi_params, iterative_params, initial_values, SS_values, fix_transfers=False, output_dir="./OUTPUT"): # unpack tuples of parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params maxiter, mindist_SS, mindist_TPI = iterative_params J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\ factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP = initial_values Kss, Lss, rss, wss, BQss, T_Hss, Gss, bssmat_splus1, nssmat = SS_values TPI_FIG_DIR = output_dir # Initialize guesses at time paths domain = np.linspace(0, T, T) r = np.ones(T + S) * rss BQ = np.zeros((T + S, J)) BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS') BQ0 = household.get_BQ(r[0], initial_b, BQ0_params) for j in xrange(J): BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQ = np.array(BQ) # print "BQ values = ", BQ[0, :], BQ[100, :], BQ[-1, :], BQss # print "K0 vs Kss = ", K0-Kss if fix_transfers: T_H = T_H_baseline else: if np.abs(T_Hss) < 1e-13: T_Hss2 = 0.0 # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below else: T_Hss2 = T_Hss T_H = np.ones(T + S) * T_Hss2 * (r / rss) G = np.ones(T + S) * Gss # # print "T_H values = ", T_H[0], T_H[100], T_H[-1], T_Hss # # print "omega diffs = ", (omega_S_preTP-omega[-1]).max(), (omega[10]-omega[-1]).max() # # Make array of initial guesses for labor supply and savings domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) # print 'diff btwn start and end b: ', (guesses_b[0]-guesses_b[-1]).max() # domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) # b_mat = np.zeros((T + S, S, J)) # n_mat = np.zeros((T + S, S, J)) ind = np.arange(S) # # print 'diff btwn start and end n: ', (guesses_n[0]-guesses_n[-1]).max() # # # find economic aggregates K = np.zeros(T + S) L = np.zeros(T + S) K[0] = K0 K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(guesses_b[:T - 1], K_params) K[T:] = Kss L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(guesses_n[:T], L_params) L[T:] = Lss Y_params = (alpha, Z) Y = firm.get_Y(K, L, Y_params) r_params = (alpha, delta) r[:T] = firm.get_r(Y[:T], K[:T], r_params) # uncomment lines below if want to use starting values from prior run r = TPI_START_VALUES['r'] K = TPI_START_VALUES['K'] L = TPI_START_VALUES['L'] Y = TPI_START_VALUES['Y'] T_H = TPI_START_VALUES['T_H'] BQ = TPI_START_VALUES['BQ'] G = TPI_START_VALUES['G'] guesses_b = TPI_START_VALUES['b_mat'] guesses_n = TPI_START_VALUES['n_mat'] TPIiter = 0 TPIdist = 10 PLOT_TPI = False euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) # print 'analytical mtrs in tpi = ', analytical_mtrs while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: K_plot = list(K) + list(np.ones(10) * Kss) L_plot = list(L) + list(np.ones(10) * Lss) plt.figure() plt.axhline(y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange(T + 10), Kpath_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) guesses = (guesses_b, guesses_n) w_params = (Z, alpha, delta) w = firm.get_w_from_r(r, w_params) # print 'r and rss diff = ', r-rss # print 'w and wss diff = ', w-wss # print 'BQ and BQss diff = ', BQ-BQss # print 'T_H and T_Hss diff = ', T_H - T_Hss # print 'guess b and bss = ', (bssmat_splus1 - guesses_b).max() # print 'guess n and nss = ', (nssmat - guesses_n).max() outer_loop_vars = (r, w, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, ind) # Solve HH problem in inner loop euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) # print 'guess b and bss = ', (b_mat - guesses_b).max() # print 'guess n and nss over time = ', (n_mat - guesses_n).max(axis=2).max(axis=1) # print 'guess n and nss over age = ', (n_mat - guesses_n).max(axis=0).max(axis=1) # print 'guess n and nss over ability = ', (n_mat - guesses_n).max(axis=0).max(axis=0) # quit() print 'Max Euler error: ', (np.abs(euler_errors)).max() bmat_s = np.zeros((T, S, J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:T - 1, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[:T, :, :] K[0] = K0 K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(bmat_splus1[:T - 1], K_params) L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(n_mat[:T], L_params) # print 'K diffs = ', K-K0 # print 'L diffs = ', L-L[0] Y_params = (alpha, Z) Ynew = firm.get_Y(K[:T], L[:T], Y_params) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) wnew = firm.get_w_from_r(rnew, w_params) omega_shift = np.append(omega_S_preTP.reshape(1, S), omega[:T - 1, :], axis=0) BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') # b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)), # b_mat[:T-1, :, :], axis=0) b_mat_shift = bmat_splus1[:T, :, :] # print 'b diffs = ', (bmat_splus1[100, :, :] - initial_b).max(), (bmat_splus1[0, :, :] - initial_b).max(), (bmat_splus1[1, :, :] - initial_b).max() # print 'r diffs = ', rnew[1]-r[1], rnew[100]-r[100], rnew[-1]-r[-1] BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params) BQss2 = np.empty(J) for j in range(J): BQss_params = (omega[1, :], lambdas[j], rho, g_n_vector[1], 'SS') BQss2[j] = household.get_BQ(rnew[1], bmat_splus1[1, :, j], BQss_params) # print 'BQ test = ', BQss2-BQss, BQss-BQnew[1], BQss-BQnew[100], BQss-BQnew[-1] total_tax_params = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): total_tax_params[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) tax_receipt_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = np.array( list( tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), ( 1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), ( 1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape( T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S) r[:T] = utils.convex_combo(rnew[:T], r[:T], nu) BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu) if fix_transfers: T_H_new = T_H G[:T] = net_tax_receipts[:T] - T_H[:T] else: T_H_new = net_tax_receipts T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu) G[:T] = 0.0 etr_params_path = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_path[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas, 'TPI', retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) b_to_use = np.zeros((T, S, J)) b_to_use[0, 1:, :] = initial_b[:-1, :] b_to_use[1:, 1:, :] = b_mat[:T - 1, :-1, :] tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)), b_to_use, n_mat[:T, :, :], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * b_to_use[:T, :, :] + np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) * np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :]) cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), b_to_use[:T, :, :], b_mat[:T, :, :], n_mat[:T, :, :], BQ[:T].reshape(T, 1, J), tax_path, cons_params) guesses_b = utils.convex_combo(b_mat, guesses_b, nu) guesses_n = utils.convex_combo(n_mat, guesses_n, nu) if T_H.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() print 'r dist = ', np.array( list(utils.pct_diff_func(rnew[:T], r[:T]))).max() print 'BQ dist = ', np.array( list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten())).max() print 'T_H dist = ', np.array( list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max() print 'T_H path = ', T_H[:20] # print 'r old = ', r[:T] # print 'r new = ', rnew[:T] # print 'K old = ', K[:T] # print 'L old = ', L[:T] # print 'income = ', y_path[:, :, -1] # print 'taxes = ', tax_path[:, :, -1] # print 'labor supply = ', n_mat[:, :, -1] # print 'max and min labor = ', n_mat.max(), n_mat.min() # print 'max and min labor = ', np.argmax(n_mat), np.argmin(n_mat) # print 'max and min labor, j = 7 = ', n_mat[:,:,-1].max(), n_mat[:,:,-1].min() # print 'max and min labor, j = 6 = ', n_mat[:,:,-2].max(), n_mat[:,:,-2].min() # print 'max and min labor, j = 5 = ', n_mat[:,:,4].max(), n_mat[:,:,4].min() # print 'max and min labor, j = 4 = ', n_mat[:,:,3].max(), n_mat[:,:,3].min() # print 'max and min labor, j = 3 = ', n_mat[:,:,2].max(), n_mat[:,:,2].min() # print 'max and min labor, j = 2 = ', n_mat[:,:,1].max(), n_mat[:,:,1].min() # print 'max and min labor, j = 1 = ', n_mat[:,:,0].max(), n_mat[:,:,0].min() # print 'max and min labor, S = 80 = ', n_mat[:,-1,-1].max(), n_mat[:,-1,-1].min() # print "number > 1 = ", (n_mat > 1).sum() # print "number < 0, = ", (n_mat < 0).sum() # print "number > 1, j=7 = ", (n_mat[:T,:,-1] > 1).sum() # print "number < 0, j=7 = ", (n_mat[:T,:,-1] < 0).sum() # print "number > 1, s=80, j=7 = ", (n_mat[:T,-1,-1] > 1).sum() # print "number < 0, s=80, j=7 = ", (n_mat[:T,-1,-1] < 0).sum() # print "number > 1, j= 7, age 80= ", (n_mat[:T,-1,-1] > 1).sum() # print "number < 0, j = 7, age 80= ", (n_mat[:T,-1,-1] < 0).sum() # print "number > 1, j= 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] > 1).sum() # print "number < 0, j = 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] < 0).sum() # print "number > 1, j= 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80,-1] > 1).sum() # print "number < 0, j = 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80 ,-1] < 0).sum() # diag_dict = {'n_mat': n_mat, 'b_mat': b_mat, 'y_path': y_path, 'c_path': c_path} # pickle.dump(diag_dict, open('tpi_iter1.pkl', 'wb')) else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(np.abs(T_H_new[:T] - T_H[:T]))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print '\tIteration:', TPIiter print '\t\tDistance:', TPIdist Y[:T] = Ynew # Solve HH problem in inner loop guesses = (guesses_b, guesses_n) outer_loop_vars = (r, w, BQ, T_H) inner_loop_params = (income_tax_params, tpi_params, initial_values, ind) euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params) bmat_s = np.zeros((T, S, J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:T - 1, :-1, :] bmat_splus1 = np.zeros((T, S, J)) bmat_splus1[:, :, :] = b_mat[:T, :, :] K[0] = K0 K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI') K[1:T] = household.get_K(bmat_splus1[:T - 1], K_params) L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') L[:T] = firm.get_L(n_mat[:T], L_params) Y_params = (alpha, Z) Ynew = firm.get_Y(K[:T], L[:T], Y_params) r_params = (alpha, delta) rnew = firm.get_r(Ynew[:T], K[:T], r_params) wnew = firm.get_w_from_r(rnew, w_params) omega_shift = np.append(omega_S_preTP.reshape(1, S), omega[:T - 1, :], axis=0) BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)), b_mat[:T - 1, :, :], axis=0) BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params) total_tax_params = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): total_tax_params[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) tax_receipt_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J) net_tax_receipts = np.array( list( tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), ( 1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), ( 1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape( T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S) if fix_transfers: G[:T] = net_tax_receipts[:T] - T_H[:T] else: T_H[:T] = net_tax_receipts[:T] G[:T] = 0.0 etr_params_path = np.zeros((T, S, J, etr_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_path[:, :, :, i] = np.tile( np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)), (1, 1, J)) tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas, 'TPI', retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S) tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)), bmat_s, n_mat[:T, :, :], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y) c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T, :, :], BQ[:T].reshape(T, 1, J), tax_path, cons_params) C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI') C = household.get_C(c_path, C_params) I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T + 1], 'TPI') I = firm.get_I(bmat_splus1[:T], K[1:T + 1], K[:T], I_params) rc_error = Y[:T] - C[:T] - I[:T] - G[:T] print 'Resource Constraint Difference:', rc_error # compute utility u_params = (sigma, np.tile(chi_n.reshape(1, S, 1), (T, 1, J)), b_ellipse, ltilde, upsilon, np.tile(rho.reshape(1, S, 1), (T, 1, J)), np.tile(chi_b.reshape(1, 1, J), (T, S, 1))) utility_path = household.get_u(c_path[:T, :, :], n_mat[:T, :, :], bmat_splus1[:T, :, :], u_params) # compute before and after-tax income y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * bmat_s[:T, :, :] + np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) * np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :]) inctax_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), etr_params_path) y_aftertax_path = (y_path - tax.tau_income( np.tile(r[:T].reshape(T, 1, 1), (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)), bmat_s[:T, :, :], n_mat[:T, :, :], factor, inctax_params)) # compute after-tax wealth wtax_params = (h_wealth, p_wealth, m_wealth) b_aftertax_path = bmat_s[:T, :, :] - tax.tau_wealth( bmat_s[:T, :, :], wtax_params) print 'Checking time path for violations of constaints.' for t in xrange(T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_path[t], t, ltilde) eul_savings = euler_errors[:, :S, :].max(1).max(1) eul_laborleisure = euler_errors[:, S:, :].max(1).max(1) print 'Max Euler error, savings: ', eul_savings print 'Max Euler error labor supply: ', eul_laborleisure ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 'c_path': c_path, 'tax_path': tax_path, 'bmat_s': bmat_s, 'utility_path': utility_path, 'b_aftertax_path': b_aftertax_path, 'y_aftertax_path': y_aftertax_path, 'y_path': y_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure } macro_output = { 'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w, 'tax_path': tax_path } # if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS : # raise RuntimeError("Transition path equlibrium not found") # # if ((np.any(np.absolute(rc_error) >= 1e-6)) # and ENFORCE_SOLUTION_CHECKS): # raise RuntimeError("Transition path equlibrium not found") # # if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or # (np.any(np.absolute(eul_laborleisure) > mindist_TPI))) # and ENFORCE_SOLUTION_CHECKS): # raise RuntimeError("Transition path equlibrium not found") return output, macro_output
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['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 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 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 run_steady_state(income_tax_parameters, ss_parameters, iterative_params, get_baseline=False, calibrate_model=False, output_dir="./OUTPUT"): ''' ------------------------------------------------------------------------ Run SS ------------------------------------------------------------------------ ''' 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 = ss_parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_parameters # Generate initial guesses for chi^b_j and chi^n_s chi_params = np.zeros(S + J) chi_params[:J] = chi_b_guess chi_params[J:] = chi_n_guess # First run SS simulation with guesses at initial values for b, n, w, r, etc # For inital guesses of b and n, we choose very small b, and medium n b_guess = np.ones((S, J)).flatten() * 0.05 n_guess = np.ones((S, J)).flatten() * .4 * ltilde # For initial guesses of w, r, T_H, and factor, we use values that are close # to some steady state values. wguess = 1.2 rguess = .06 T_Hguess = 0.12 factorguess = 70000.0 guesses = [wguess, rguess, T_Hguess, factorguess] args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params[J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve, guesses, args=args_, xtol=mindist_SS, full_output=True) [wguess, rguess, T_Hguess, factorguess] = solutions fsolve_flag = True solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[ J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e, fsolve_flag) if calibrate_model: global Nfeval, value_all, chi_params_all Nfeval = 1 value_all = np.zeros((10000)) chi_params_all = np.zeros((S+J,10000)) outputs = {'solutions': solutions, 'chi_params': chi_params} ss_init_path = os.path.join( output_dir, "Saved_moments/SS_init_solutions.pkl") pickle.dump(outputs, open(ss_init_path, "wb")) function_to_minimize_X = lambda x: function_to_minimize( x, chi_params, income_tax_parameters, ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir) bnds = tuple([(1e-6, None)] * (S + J)) # In order to scale all the parameters to estimate in the minimizer, we have the minimizer fit a vector of ones that # will be multiplied by the chi initial guesses inside the function. Otherwise, if chi^b_j=1e5 for some j, and the # minimizer peturbs that value by 1e-8, the % difference will be extremely small, outside of the tolerance of the # minimizer, and it will not change that parameter. chi_params_scalars = np.ones(S + J) #chi_params_scalars = opt.minimize(function_to_minimize_X, chi_params_scalars, # method='TNC', tol=MINIMIZER_TOL, bounds=bnds, callback=callbackF(chi_params_scalars), options=MINIMIZER_OPTIONS).x # chi_params_scalars = opt.minimize(function_to_minimize, chi_params_scalars, # args=(chi_params, income_tax_parameters, ss_parameters, iterative_params, # omega_SS, rho, lambdas, tau_bq, e, output_dir), # method='TNC', tol=MINIMIZER_TOL, bounds=bnds, # callback=callbackF(chi_params_scalars,chi_params, income_tax_parameters, # ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir), # options=MINIMIZER_OPTIONS).x chi_params_scalars = opt.minimize(function_to_minimize, chi_params_scalars, args=(chi_params, income_tax_parameters, ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir), method='TNC', tol=MINIMIZER_TOL, bounds=bnds, options=MINIMIZER_OPTIONS).x chi_params *= chi_params_scalars print 'The final scaling params', chi_params_scalars print 'The final bequest parameter values:', chi_params solutions_dict = pickle.load(open(ss_init_path, "rb")) solutions = solutions_dict['solutions'] b_guess = solutions[:S * J] n_guess = solutions[S * J:2 * S * J] wguess, rguess, factorguess, T_Hguess = solutions[2 * S * J:] guesses = [wguess, rguess, T_Hguess, factorguess] args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params[J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve, guesses, args=args_, xtol=mindist_SS, full_output=True) [wguess, rguess, T_Hguess, factorguess] = solutions fsolve_flag = True solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[ J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e, fsolve_flag) ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' if get_baseline: outputs = {'solutions': solutions, 'chi_params': chi_params} ss_init_dir = os.path.join( output_dir, "Saved_moments/SS_baseline_solutions.pkl") pickle.dump(outputs, open(ss_init_dir, "wb")) else: outputs = {'solutions': solutions, 'chi_params': chi_params} ss_exp_dir = os.path.join( output_dir, "Saved_moments/SS_reform_solutions.pkl") pickle.dump(outputs, open(ss_exp_dir, "wb")) bssmat = solutions[0:(S - 1) * J].reshape(S - 1, J) bq = solutions[(S - 1) * J:S * J] # technically, this is just the intentional bequests - wealth of those with max age bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat)) bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J))) nssmat = solutions[S * J:2 * S * J].reshape(S, J) wss, rss, factor_ss, T_Hss = solutions[2 * S * J:] Kss = household.get_K(bssmat_splus1, omega_SS.reshape( S, 1), lambdas, g_n_ss, 'SS') Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas, 'SS') Yss = firm.get_Y(Kss, Lss, ss_parameters) Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss) theta = np.zeros(J) #tax.replacement_rate_vals( #nssmat, wss, factor_ss, e, J, omega_SS.reshape(S, 1), lambdas) BQss = household.get_BQ(rss, bssmat_splus1, omega_SS.reshape( S, 1), lambdas, rho.reshape(S, 1), g_n_ss, 'SS') b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) etr_params_3D = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1)) mtrx_params_3D = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1)) etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:] etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1)) mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:] mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1)) e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J))) nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J))) mtry_ss = tax.MTR_capital(rss, bssmat_splus1, wss, e_extended[1:,:], nss_extended[1:,:], factor_ss, analytical_mtrs, etr_params_extended_3D, mtry_params_extended_3D) mtrx_ss = tax.MTR_labor(rss, bssmat_s, wss, e, nssmat, factor_ss, analytical_mtrs, etr_params_3D, mtrx_params_3D) #np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",") #np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",") taxss_params = (J,S, retire, np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1)), h_wealth, p_wealth, m_wealth, tau_payroll) taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas, factor_ss, T_Hss, None, 'SS', False, taxss_params, theta, tau_bq) cssmat = household.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape( 1, J), lambdas.reshape(1, J), bssmat_splus1, ss_parameters, taxss) Css = household.get_C(cssmat, omega_SS.reshape(S, 1), lambdas, 'SS') resource_constraint = Yss - (Css + Iss) print 'Resource Constraint Difference:', resource_constraint constraint_params = ltilde household.constraint_checker_SS(bssmat, nssmat, cssmat, constraint_params) b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) b_splus1 = bssmat_splus1 b_splus2 = np.array(list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J)))) chi_b = np.tile(chi_params[:J].reshape(1, J), (S, 1)) chi_n = np.array(chi_params[J:]) euler_savings = np.zeros((S, J)) euler_labor_leisure = np.zeros((S, J)) for j in xrange(J): euler_savings[:, j] = household.euler_savings_func(wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], b_splus2[:, j], BQss[j], factor_ss, T_Hss, chi_b[:, j], income_tax_parameters, ss_parameters, theta[j], tau_bq[j], rho, lambdas[j]) euler_labor_leisure[:, j] = household.euler_labor_leisure_func(wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], BQss[j], factor_ss, T_Hss, chi_n, income_tax_parameters, ss_parameters, theta[j], tau_bq[j], lambdas[j]) ''' ------------------------------------------------------------------------ Save the values in various ways, depending on the stage of the simulation, to be used in TPI or graphing functions ------------------------------------------------------------------------ ''' # Pickle variables output = {'Kss': Kss, 'bssmat': bssmat, 'Lss': Lss, 'Css':Css, 'nssmat': nssmat, 'Yss': Yss, 'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'T_Hss': T_Hss, 'euler_savings': euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n, 'chi_b': chi_b} utils.mkdirs(os.path.join(output_dir, "SSinit")) ss_init_dir = os.path.join(output_dir, "SSinit/ss_init_vars.pkl") pickle.dump(output, open(ss_init_dir, "wb")) bssmat_init = bssmat_splus1 nssmat_init = nssmat # Pickle variables for TPI initial values output2 = {'bssmat_init': bssmat_init, 'nssmat_init': nssmat_init} ss_init_tpi = os.path.join(output_dir, "SSinit/ss_init_tpi_vars.pkl") pickle.dump(output2, open(ss_init_tpi, "wb")) return output
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