def feasible(bmat, nmat, rpath, args): ''' -------------------------------------------------------------------- This function checks whether any constraints are violated by matrices for savings and labor supply given a time path for interest rates -------------------------------------------------------------------- -------------------------------------------------------------------- ''' (lambdas, emat, omega_vec, mort_rates, zeta_mat, g_y, l_tilde, g_n_SS, Z, gamma, delta) = args J = len(lambdas) b_feas = bmat > 0.0 if (bmat <= 0.0).sum() > 0.0: err_msg = ('SS ERROR: Some value of initial guess for ' + 'bmat_ss is less than or equal to zero. ' + 'b_{j,s}<=0 for some j and s.') print('b_feas:', b_feas) raise RuntimeError(err_msg) n_feas = (nmat > 0.0) & (nmat < l_tilde) if ((nmat <= 0.0) | (nmat >= l_tilde)).sum() > 0.0: err_msg = ('SS ERROR: Some value of initial guess for ' + 'nmat_ss is less than or equal to zero or greater ' + 'than or equal to l_tilde. n_{j,s}<=0 or ' + 'n_{j,s}>=l_tildefor some j and s.') print('n_feas:', n_feas) raise RuntimeError(err_msg) w_params = (Z, gamma, delta) wpath = firms.get_w(rpath, w_params) b_s_mat = np.vstack((np.zeros(J), bmat[:-1, :])) b_sp1_mat = bmat BQ_args = (lambdas, omega_vec, mort_rates, g_n_SS) BQ = aggr.get_BQ(bmat, rpath, BQ_args) c_args = (emat, zeta_mat, lambdas, omega_vec, g_y) cmat = get_cons(rpath, wpath, b_s_mat, b_sp1_mat, nmat, BQ, c_args) c_feas = cmat > 0.0 if (cmat <= 0.0).sum() > 0.0: err_msg = ('SS ERROR: Some value of initial guess for ' + 'bmat_ss or nmat_ss is not feasible because ' + 'resulting cmat_ss has a value that is less than ' + 'or equal to zero. c_{j,s}<=0 for some j and s.') print('c_feas:', c_feas) raise RuntimeError(err_msg) return b_feas, n_feas, c_feas
def FOCs(b_sp1, n_s, *args): (b_init, BQ, rho_s, omega, g_n, beta, sigma, l_tilde, chi, b_ellipse, upsilon, r, w, method) = args b_s = np.append(b_init, b_sp1) b_sp1 = np.append(b_sp1, 0.0) if method == 'SS': # if method is SS, solve for BQ, else (case of TPI), use BQ # as guessed in the "outer loop" BQ_params = (omega, g_n, rho_s) BQ = agg.get_BQ(b_s, r, BQ_params, method) c = get_c(r, w, n_s, b_s, b_sp1, BQ) b_args = (rho_s, beta, sigma, r) b_errors = FOC_save(c, b_args) n_args = (sigma, w, l_tilde, chi, b_ellipse, upsilon) n_errors = FOC_labor(c, n_s, n_args) errors = np.append(b_errors, n_errors) return errors
def solve_tp(g_n_path, omega_S_preTP, rho_s, imm_rates_path, omega_SS, omega_path_S, params): ''' Solves for the time path equilibrium using TPI ''' # Missing some elements of params b_ss, r_ss, n_s, r_11, alpha, A, delta, beta, sigma, T, S = params dist = 8.0 mindist = 1e-08 maxiter = 300 tpi_iter = 0 xi = 0.2 while dist > mindist and tpi_iter < maxiter: # Define paths b_11 = 1.1 * b_ss BQ_params = (g_n_path[0], omega_S_preTP, rho_s) K_params = (g_n_path[0], omega_S_preTP, imm_rates_path[0, :]) BQ_11 = agg.get_BQ(b_11, r_11, BQ_params, method = "TPI") BQ_ss = agg.get_BQ(b_ss, r_ss, BQ_params, method = "SS") K_11 = agg.get_K(b_11, K_params) BQpath_init = np.zeros(T + S - 1) BQpath_init[:T] = np.linspace(BQ_11, BQ_ss, T) BQpath_init[T:] = BQ_ss L_ss = agg.get_L(n_s, omega_SS) r_11 = firm.get_r(L_ss, K_11, alpha, A, delta) # I can't figure out how r_11 and r_path differ ''' Is r_11 an initial guess? Depending on how you're defining r_11, the arguments passed to the function call above and below will vary ''' r_path = firm.get_r(L_ss, K_11, alpha, A, delta) w_path = firm.get_w(r_path, alpha, A, delta) bmat = np.zeros((S - 1, T + S - 1)) # What is b_1 supposed to be? bmat[:, 0] = b_1 # Solve for households for p in range(2, S): b_guess = np.diagonal(bmat[S - p:, :p - 1]) b_init = bmat[S - p - 1, 0] b_params = (b_init, n_s[-p:], r_path[:p], w_path[:p], BQpath_init[:p], rho_s[-p:], beta, sigma) results_bp = opt.root(hh.FOCs, b_guess, args=(b_params)) b_solve_p = results_bp.x DiagMaskbp = np.eye(p - 1, dtype=bool) bmat[S - p:, 1:p] = DiagMaskbp * b_solve_p + bmat[S - p:, 1:p] for t in range(1, T + 1): b_guess = np.diagonal(bmat[:, t - 1:t + S - 2]) b_init = 0.0 b_params = (b_init, n_s, r_path[t - 1:t + S - 1], w_path[t - 1:t + S - 1], BQpath_init[t - 1:t + S - 1], rho_s, beta, sigma) results_bt = opt.root(hh.FOCs, b_guess, args=(b_params)) b_solve_t = results_bt.x DiagMaskbt = np.eye(S - 1, dtype=bool) bmat[:, t:t + S - 1] = (DiagMaskbt * b_solve_t + bmat[:, t:t + S - 1]) new_Kpath = np.zeros(T) new_Kpath[0] = K_11 new_Kpath[1:] = \ (1 / (omega_path_S[:T - 1, :-1]) * bmat[:, 1:T].T + imm_rates_path[:T - 1, 1:] * omega_path_S[:T - 1, 1:] * bmat[:, 1:T].T).sum(axis=1) new_BQpath = np.zeros(T) new_BQpath[0] = BQ_11 new_BQpath[1:] = \ ((1 + r_path[1:T]) / (rho_s[:-1]) * omega_path_S[:T - 1, :-1] * bmat[:, 1:T].T).sum(axis=1) dist = ((BQ_init - new_BQ) ** 2).sum() BQpath_init[:T] = xi * new_BQpath[:T] + (1 - xi) * BQpath_init[:T] # update iteration counter tpi_iter += 1 if tpi_iter < maxiter: print('The time path solved! ->', ' iter:', tpi_iter, ', dist: ', dist) else: print('The time path did not solve.') return [new_Kpath, new_BQpath]
def get_SS(init_vals, args, graphs=False): ''' -------------------------------------------------------------------- Solve for the steady-state solution of the S-period-lived agent OG model with endogenous labor supply using the bisection method in K and L for the outer loop -------------------------------------------------------------------- INPUTS: init_vals = length 3 tuple, (r_init, c1_init, factor_init) args = length 19 tuple, (J, S, lambdas, emat, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec_hat, Z, gamma, delta, Bsct_Tol, Eul_Tol, xi, maxiter, mean_ydata, init_calc) graphs = boolean, =True if output steady-state graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: firms.get_r() firms.get_w() utils.print_time() inner_loop() creat_graphs() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar > 0, clock time at beginning of program r_init = scalar > -delta, initial guess for steady-state interest rate c1_init = (J,) vector, initial guess for first period consumption by all J ability types factor_init = scalar > 0, initial guess for factor that scales model units to data units J = integer >= 1, number of heterogeneous ability groups S = integer in [3, 80], number of periods an individual lives lambdas = (J,) vector, income percentiles for distribution of ability within each cohort emat = (S, J) matrix, lifetime ability profiles for each lifetime income group j beta = scalar in (0,1), discount factor for each model per sigma = scalar > 0, coefficient of relative risk aversion l_tilde = scalar > 0, time endowment of each agent each period b_ellip = scalar > 0, fitted value of b for elliptical disutility of labor upsilon = scalar > 1, fitted value of upsilon for elliptical disutility of labor chi_n_vec_hat = (S,) vector, values for chi^n_s hat from data Z = scalar > 0, total factor productivity parameter in firms' production function gamma = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital Bsct_Tol = scalar > 0, tolerance level for outer-loop bisection method Eul_Tol = scalar > 0, tolerance level for inner-loop root finder xi = scalar in (0, 1], SS updating parameter in outer- loop bisection method maxiter = integer >= 1, maximum number of iterations in outer- loop bisection method mean_ydata = scalar > 0, average household income from the data init_calc = boolean, =True if initial steady-state calculation with chi_n_vec = 1 for all s iter_SS = integer >= 0, index of iteration number dist = scalar > 0, distance metric for current iteration c1_options = length 1 dict, options to pass into opt.root(c1_bSp1err,...) rw_params = length 3 tuple, (Z, gamma, delta) args to pass into firms.get_w() c1ss_init = (J,) vector, initial guess for css_{j,1}, updates each iteration lambda_mat = (S, J) matrix, lambdas vector copied down S rows w_init = scalar, initial value for wage chi_n_vec = (S,) vector, chi^n_s values that scale the disutility of labor supply inner_args = length 16 tuple, args to pass into inner_loop() K_new = scalar > 0, updated K given r_init and w_init L_new = scalar > 0, updated L given r_init and w_init cmat = (S, J) matrix, lifetime household consumption by age s and ability j nmat = (S, J) matrix, lifetime household labor supply by age s and ability j bmat = (S, J) matrix, lifetime household savings by age s and ability j (b1, b2,...bS) b_Sp1_vec = (J,) vector, household savings in last period for each ability type, should be arbitrarily close to 0 r_new = scalar > 0, updated interest rate given nmat, bmat w_new = scalar > 0, updated wage given nmat and bmat n_err_mat = (S, J) matrix, labor supply Euler errors given r_init and w_init b_err_mat = (S, J) matrix, savings Euler errors given r_init and w_init. First row is identically zeros all_errors = (2JS + J,) vector, (n_errors, b_errors, b_Sp1_vec) avg_inc_model = scalar > 0, average household income in model factor_new = scalar > 0, updated factor value given nmat, bmat, r_new, and w_new c_ss = (S, J) matrix, steady-state lifetime consumption n_ss = (S, J) matrix, steady-state lifetime labor supply b_ss = (S, J) matrix, steady-state wealth (savings) at beginning of each period (b1, b2, ...bS) b_Sp1_ss = (J,) vector, steady-state savings in last period of life for all J ability types, approx. 0 in equilbrm n_err_ss = (S, J) matrix, lifetime labor supply Euler errors b_err_ss = (S, J) matrix, lifetime savings Euler errors r_ss = scalar > 0, steady-state interest rate w_ss = scalar > 0, steady-state wage K_ss = scalar > 0, steady-state aggregate capital stock L_ss = scalar > 0, steady-state aggregate labor Y_params = length 2 tuple, (Z, gamma) Y_ss = scalar > 0, steady-state aggregate output (GDP) C_ss = scalar > 0, steady-state aggregate consumption RCerr_ss = scalar, resource constraint error ss_time = scalar, seconds elapsed for steady-state computation ss_output = length 16 dict, steady-state objects {c_ss, n_ss, b_ss, b_Sp1_ss, w_ss, r_ss, K_ss, L_ss, Y_ss, C_ss, n_err_ss, b_err_ss, RCerr_ss, ss_time, chi_n_vec, factor_ss} FILES CREATED BY THIS FUNCTION: None RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() r_init, BQ_init, factor_init, bmat_init, nmat_init = init_vals (J, E, S, lambdas, emat, mort_rates, imm_rates, omega_SS, g_n_SS, zeta_mat, chi_n_vec_hat, chi_b_vec, beta, sigma, l_tilde, b_ellip, upsilon, g_y, Z, gamma, delta, SS_tol_outer, SS_tol_inner, xi, maxiter, mean_ydata, init_calc) = args iter_SS = 0 dist = 10 rw_params = (Z, gamma, delta) BQ_args = (lambdas, omega_SS, mort_rates, g_n_SS) lambda_mat = np.tile(lambdas.reshape((1, J)), (S, 1)) omega_mat = np.tile(omega_SS.reshape((S, 1)), (1, J)) while (iter_SS < maxiter) and (dist >= SS_tol_outer): iter_SS += 1 w_init = firms.get_w(r_init, rw_params) if init_calc: print('Factor init is one. No modification performed to ' + 'chi_n_vec. Dist calculated without factor.') chi_n_vec = chi_n_vec_hat else: chi_n_vec = chi_n_vec_hat * (factor_init**(sigma - 1)) rpath = r_init * np.ones(S) wpath = w_init * np.ones(S) BQpath = BQ_init * np.ones(S) cnb_args = (S, lambdas, emat, mort_rates, omega_SS, zeta_mat, chi_n_vec, chi_b_vec, beta, sigma, l_tilde, b_ellip, upsilon, g_y, g_n_SS, SS_tol_inner) cmat, nmat, bmat, n_err_mat, b_err_mat = \ hh.get_cnb_mats(bmat_init, nmat_init, np.zeros(J), rpath, wpath, BQpath, cnb_args) K_args = (lambdas, omega_SS, imm_rates, g_n_SS) K_new, K_cstr = aggr.get_K(bmat, K_args) L_args = (emat, lambdas, omega_SS) L_new, L_cstr = aggr.get_L(nmat, L_args) r_new = firms.get_r(K_new, L_new, rw_params) w_new = firms.get_w(r_new, rw_params) BQ_new = aggr.get_BQ(bmat, r_new, BQ_args) all_errors = \ np.hstack((b_err_mat.flatten(), n_err_mat.flatten())) if init_calc: dist = max(np.absolute((r_new - r_init) / r_init), np.absolute((BQ_new - BQ_init) / BQ_init)) else: avg_inc_model = (omega_mat * lambda_mat * (r_new * bmat + w_new * emat * nmat)).sum() factor_new = mean_ydata / avg_inc_model print('mean_ydata: ', mean_ydata, ', avg_inc_model: ', avg_inc_model) print('r_new: ', r_new, 'BQ_new', BQ_new, 'factor_new: ', factor_new) dist = max(np.absolute((r_new - r_init) / r_init), np.absolute((BQ_new - BQ_init) / BQ_init), np.absolute((factor_new - factor_init) / factor_init)) factor_init = xi * factor_new + (1 - xi) * factor_init r_init = xi * r_new + (1 - xi) * r_init BQ_init = xi * BQ_new + (1 - xi) * BQ_init print('SS Iter=', iter_SS, ', SS Dist=', '%10.4e' % (dist), ', Max Abs Err=', '%10.4e' % (np.absolute(all_errors).max())) bmat_init = bmat nmat_init = nmat chi_n_vec = chi_n_vec_hat * (factor_init**(sigma - 1)) c_ss = cmat.copy() n_ss = nmat.copy() b_ss = bmat.copy() n_err_ss = n_err_mat.copy() b_err_ss = b_err_mat.copy() r_ss = r_new.copy() w_ss = w_new.copy() BQ_ss = BQ_new.copy() K_ss = K_new.copy() L_ss = L_new.copy() factor_ss = factor_init I_args = (lambdas, omega_SS, imm_rates, g_n_SS, g_y, delta) I_ss = aggr.get_I(b_ss, I_args) NX_args = (lambdas, omega_SS, imm_rates, g_y) NX_ss = aggr.get_NX(b_ss, NX_args) Y_params = (Z, gamma) Y_ss = aggr.get_Y(K_ss, L_ss, Y_params) C_args = (lambdas, omega_SS) C_ss = aggr.get_C(c_ss, C_args) RCerr_ss = Y_ss - C_ss - I_ss - NX_ss ss_time = time.clock() - start_time ss_output = { 'c_ss': c_ss, 'n_ss': n_ss, 'b_ss': b_ss, 'BQ_ss': BQ_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'I_ss': I_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'NX_ss': NX_ss, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time, 'chi_n_vec': chi_n_vec, 'factor_ss': factor_ss } print('n_ss is: ', n_ss) print('b_ss is: ', b_ss) print('c_ss is: ', c_ss) print('K_ss=', K_ss, ', L_ss=', L_ss, 'Y_ss=', Y_ss) print('r_ss=', r_ss, ', w_ss=', w_ss, 'C_ss=', C_ss) print('BQ_ss=', BQ_ss, ', I_ss=', I_ss, ', NX_ss=', NX_ss) print('Maximum abs. labor supply Euler error is: ', np.absolute(n_err_ss).max()) print('Maximum abs. savings Euler error is: ', np.absolute(b_err_ss).max()) print('Resource constraint error is: ', RCerr_ss) print('Final chi_n_vec from SS:', chi_n_vec) print('SS factor is: ', factor_ss) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: gr_args = (E, S, J, chi_n_vec, lambdas) create_graphs(c_ss, b_ss, n_ss, gr_args) return ss_output
def get_TPI(bmat1, args, graphs): ''' -------------------------------------------------------------------- Solves for transition path equilibrium using time path iteration (TPI) -------------------------------------------------------------------- INPUTS: bmat1 = (S, J) matrix, initial period wealth (savings) distribution args = length 25 tuple, (J, S, T1, T2, lambdas, emat, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, Z, gamma, delta, r_ss, K_ss, L_ss, C_ss, b_ss, n_ss, maxiter, Out_Tol, In_Tol, xi) graphs = Boolean, =True if want graphs of TPI objects OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: get_path() firms.get_r() firms.get_w() get_cnbpath() aggr.get_K() aggr.get_L() aggr.get_Y() aggr.get_C() utils.print_time() create_graphs() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar, current processor time in seconds (float) J = integer >= 1, number of heterogeneous ability groups S = integer in [3,80], number of periods an individual lives T1 = integer > S, number of time periods until steady state is assumed to be reached T2 = integer > T1, number of time periods after which steady-state is forced in TPI lambdas = (J,) vector, income percentiles for distribution of ability within each cohort emat = (S, J) matrix, lifetime ability profiles for each lifetime income group j beta = scalar in (0,1), discount factor for model period sigma = scalar > 0, coefficient of relative risk aversion l_tilde = scalar > 0, time endowment for each agent each period b_ellip = scalar > 0, fitted value of b for elliptical disutility of labor upsilon = scalar > 1, fitted value of upsilon for elliptical disutility of labor chi_n_vec = (S,) vector, values for chi^n_s Z = scalar > 0, total factor productivity parameter in firms' production function gamma = scalar in (0,1), capital share of income delta = scalar in [0,1], per-period capital depreciation rt r_ss = scalar > 0, steady-state aggregate interest rate K_ss = scalar > 0, steady-state aggregate capital stock L_ss = scalar > 0, steady-state aggregate labor C_ss = scalar > 0, steady-state aggregate consumption b_ss = (S,) vector, steady-state savings distribution (b1, b2,... bS) n_ss = (S,) vector, steady-state labor supply distribution (n1, n2,... nS) maxiter = integer >= 1, Maximum number of iterations for TPI Out_Tol = scalar > 0, convergence criterion for TPI outer loop In_Tol = scalar > 0, tolerance level for TPI inner-loop root finders xi = scalar in (0,1], TPI path updating parameter K1 = scalar > 0, initial aggregate capital stock K1_cnstr = Boolean, =True if K1 <= 0 rpath_init = (T2+S-1,) vector, initial guess for the time path of interest rates iter_TPI = integer >= 0, current iteration of TPI dist = scalar >= 0, distance measure between initial and new paths rw_params = length 3 tuple, (Z, gamma, delta) Y_params = length 2 tuple, (Z, gamma) cnb_args = length 13 tuple, args to pass into get_cnbpath() rpath = (T2+S-1,) vector, time path of the interest rates wpath = (T2+S-1,) vector, time path of the wages cpath = (S, J, T2+S-1) array, time path of distribution of household consumption c_{j,s,t} npath = (S, J, T2+S-1) matrix, time path of distribution of household labor supply n_{j,s,t} bpath = (S, J, T2+S-1) matrix, time path of distribution of household savings b_{j,s,t} n_err_path = (S, J, T2+S-1) matrix, time path of distribution of household labor supply Euler errors b_err_path = (S, J, T2+S-1) matrix, time path of distribution of household savings Euler errors. b_{j,1,t} = 0 for all j and t Kpath_new = (T2+S-1,) vector, new path of aggregate capital stock implied by household and firm optimization Kpath_cnstr = (T2+S-1,) Boolean vector, =True if K_t<=epsilon Lpath_new = (T2+S-1,) vector, new path of aggregate labor implied by household and firm optimization Lpath_cstr = (T2+S-1,) Boolean vector, =True if L_t<=epsilon rpath_new = (T2+S-1,) vector, updated time path of interest rate Ypath = (T2+S-1,) vector, equilibrium time path of aggregate output (GDP) Y_t Cpath = (T2+S-1,) vector, equilibrium time path of aggregate consumption C_t RCerrPath = (T2+S-2,) vector, equilibrium time path of the resource constraint error. Should be 0 in eqlb'm Y_t - C_t - K_{t+1} + (1-delta)*K_t MaxAbsEulErr = scalar > 0, maximum absolute Euler error. Includes both labor supply and savings Euler errors Kpath = (T2+S-1,) vector, equilibrium time path of aggregate capital stock K_t Lpath = (T2+S-1,) vector, equilibrium time path of aggregate labor L_t tpi_time = scalar, time to compute TPI solution (seconds) tpi_output = length 13 dictionary, {cpath, npath, bpath, wpath, rpath, Kpath, Lpath, Ypath, Cpath, n_err_path, b_err_path, RCerrPath, tpi_time} graph_args = length 4 tuple, (J, S, T2, lambdas) FILES CREATED BY THIS FUNCTION: Kpath.png Lpath.png rpath.png wpath.png Ypath.png C_aggr_path.png cpath_avg_s.png cpath_avg_j.png npath_avg_s.png npath_avg_j.png bpath_avg_s.png bpath_avg_j.png RETURNS: tpi_output -------------------------------------------------------------------- ''' start_time = time.clock() (J, E, S, T1, T2, lambdas, emat, mort_rates, imm_rates_mat, omega_path, g_n_path, zeta_mat, chi_n_vec, chi_b_vec, beta, sigma, l_tilde, b_ellip, upsilon, g_y, Z, gamma, delta, r_ss, BQ_ss, K_ss, L_ss, C_ss, b_ss, n_ss, maxiter, Out_Tol, In_Tol, xi) = args K1, K1_cnstr = aggr.get_K(bmat1, lambdas) # Create time paths for r and BQ rpath_init = np.zeros(T2 + S - 1) BQpath_init = np.zeros(T2 + S - 1) rpath_init[:T1] = get_path(r_ss, r_ss, T1, 'quadratic') rpath_init[T1:] = r_ss BQ_args = (lambdas, omega_path[0, :], mort_rates, g_n_path[0]) BQ_1 = aggr.get_BQ(bmat1, r_ss, BQ_args) BQpath_init[:T1] = get_path(BQ_1, BQ_ss, T1, 'quadratic') BQpath_init[T1:] = BQ_ss iter_TPI = int(0) dist = 10.0 rw_params = (Z, gamma, delta) Y_params = (Z, gamma) cnb_args = (J, S, T2, lambdas, emat, omega_path, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, bmat1, n_ss, In_Tol) while (iter_TPI < maxiter) and (dist >= Out_Tol): iter_TPI += 1 rpath = rpath_init BQpath = BQpath_init wpath = firms.get_w(rpath_init, rw_params) cpath, npath, bpath, n_err_path, b_err_path = \ get_cnbpath(rpath, wpath, cnb_args) Kpath_new = np.zeros(T2 + S - 1) Kpath_new[:T2], Kpath_cstr = aggr.get_K(bpath[:, :, :T2], lambdas) Kpath_new[T2:] = K_ss Kpath_cstr = np.append(Kpath_cstr, np.zeros(S - 1, dtype=bool)) Lpath_new = np.zeros(T2 + S - 1) Lpath_new[:T2], Lpath_cstr = aggr.get_L(npath[:, :, :T2], lambdas, emat) Lpath_new[T2:] = L_ss Lpath_cstr = np.append(Lpath_cstr, np.zeros(S - 1, dtype=bool)) rpath_new = firms.get_r(Kpath_new, Lpath_new, rw_params) BQpath_new = aggr.get_BQ() Ypath = aggr.get_Y(Kpath_new, Lpath_new, Y_params) Cpath = np.zeros(T2 + S - 1) Cpath[:T2] = aggr.get_C(cpath[:, :, :T2], lambdas) Cpath[T2:] = C_ss RCerrPath = np.zeros(T2 + S - 1) RCerrPath[:-1] = (Ypath[:-1] - Cpath[:-1] - Kpath_new[1:] + (1 - delta) * Kpath_new[:-1]) RCerrPath[-1] = RCerrPath[-2] # Check the distance of rpath_new dist = (np.absolute(rpath_new[:T2] - rpath_init[:T2])).max() MaxAbsEulErr = np.absolute(np.hstack((n_err_path, b_err_path))).max() print('TPI iter: ', iter_TPI, ', dist: ', "%10.4e" % (dist), ', max abs all errs: ', "%10.4e" % MaxAbsEulErr) # The resource constraint does not bind across the transition # path until the equilibrium is solved rpath_init[:T2] = (xi * rpath_new[:T2] + (1 - xi) * rpath_init[:T2]) if (iter_TPI == maxiter) and (dist > Out_Tol): print('TPI reached maxiter and did not converge.') elif (iter_TPI == maxiter) and (dist <= Out_Tol): print('TPI converged in the last iteration. ' + 'Should probably increase maxiter_TPI.') Kpath = Kpath_new Lpath = Lpath_new tpi_time = time.clock() - start_time tpi_output = { 'cpath': cpath, 'npath': npath, 'bpath': bpath, 'wpath': wpath, 'rpath': rpath, 'Kpath': Kpath, 'Lpath': Lpath, 'Ypath': Ypath, 'Cpath': Cpath, 'n_err_path': n_err_path, 'b_err_path': b_err_path, 'RCerrPath': RCerrPath, 'tpi_time': tpi_time } # Print maximum resource constraint error. Only look at resource # constraint up to period T2 - 1 because period T2 includes K_{t+1}, # which was forced to be the steady-state print('Max abs. RC error: ', "%10.4e" % (np.absolute(RCerrPath[:T2 - 1]).max())) # Print TPI computation time utils.print_time(tpi_time, 'TPI') if graphs: graph_args = (J, S, T2, lambdas) create_graphs(tpi_output, graph_args) return tpi_output
Frisch_elast, CFE_scale) calibrate = pjp.process_calibration_parameters() init_chi1 = pickle.load(open('init_chi1.pkl', 'rb')) # rss_init = 0.15 rss_init = init_chi1['r_ss'] # bmat_init = 0.01 * np.ones((S, J)) bmat_init = init_chi1['b_ss'] # nmat_init = 0.5 * l_tilde * np.ones((S, J)) nmat_init = init_chi1['n_ss'] rss_path = rss_init * np.ones(S) f_args = (lambdas, emat, omega_SS, mort_rates, zeta_mat, g_y, l_tilde, g_n_SS, Z, gamma, delta) b_feas, n_feas, c_feas = hh.feasible(bmat_init, nmat_init, rss_path, f_args) BQ_args = (lambdas, omega_SS, mort_rates, g_n_SS) BQ_init = aggr.get_BQ(bmat_init, rss_init, BQ_args) factor_init = 1.0 init_calc = True mean_ydata = calibrate.get_avg_ydata() chi_n_vec = 1.0 * np.ones(S) ss_init_vals = (rss_init, BQ_init, factor_init, bmat_init, nmat_init) ss_args_noclb = (J, E, S, lambdas, emat, mort_rates, imm_rates_adj, omega_SS, g_n_SS, zeta_mat, chi_n_vec, chi_b_vec, beta, sigma, l_tilde, b_ellip, upsilon, g_y, Z, gamma, delta, SS_tol_outer, SS_tol_inner, xi_SS, SS_maxiter, mean_ydata, init_calc) print(ss_args_noclb) ss_output_noclb = ss.get_SS(ss_init_vals, ss_args_noclb, False) # Save ss_output as pickle pickle.dump(ss_output_noclb, open(ss_outfile_noclb, 'wb'))
def solve_tp(g_n_path, omega_S_preTP, rho_s, imm_rates_path, params): ''' Solves for the time path equilibrium using TPI ''' # Missing some elements of params b_ss, r_11, T, S = params dist = 8.0 mindist = 1e-08 maxiter = 300 tpi_iter = 0 xi = 0.2 while dist > mindist and tpi_iter < maxiter: # Define paths b_11 = 1.1 * b_ss BQ_params = (g_n_path[0], omega_S_preTP, rho_s) K_params = (g_n_path[0], omega_S_preTP, imm_rates_path[0, :]) BQ_11 = agg.get_BQ(b_11, r_11, BQ_params) K_11 = agg.get_K(b_11, K_params) BQpath_init = np.zeros(T + S - 1) BQpath_init[:T] = np.linspace(BQ_11, BQ_ss, T) BQpath_init[T:] = BQ_ss r_11 = firm.get_r(K_11, L_ss, r_params) r_path = firm.get_r(L_ss, r_params) w_path = firm.get_w(L_ss, w_params) bmat = np.zeros((S - 1, T + S - 1)) bmat[:, 0] = b_1 # Solve for households for p in range(2, S): b_guess = np.diagonal(bmat[S - p:, :p - 1]) b_init = bmat[S - p - 1, 0] b_params = (b_init, n[-p:], r_path[:p], w_path[:p], BQpath_init[:p], rho_s[-p:], beta, sigma) results_bp = opt.root(hh.FOCs, b_guess, args=(b_params)) b_solve_p = results_bp.x DiagMaskbp = np.eye(p - 1, dtype=bool) bmat[S - p:, 1:p] = DiagMaskbp * b_solve_p + bmat[S - p:, 1:p] for t in range(1, T + 1): b_guess = np.diagonal(bmat[:, t - 1:t + S - 2]) b_init = 0.0 b_params = (b_init, n, r_path[t - 1:t + S - 1], w_path[t - 1:t + S - 1], BQpath_init[t - 1:t + S - 1], rho_s, beta, sigma) results_bt = opt.root(hh.FOCs, b_guess, args=(b_params)) b_solve_t = results_bt.x DiagMaskbt = np.eye(S - 1, dtype=bool) bmat[:, t:t + S - 1] = (DiagMaskbt * b_solve_t + bmat[:, t:t + S - 1]) new_Kpath = np.zeros(T) new_Kpath[0] = K_1 new_Kpath[1:] = \ (1 / (omega_path_S[:T - 1, :-1]) * bmat[:, 1:T].T + imm_rates_path[:T - 1, 1:] * omega_path_S[:T - 1, 1:] * bmat[:, 1:T].T).sum(axis=1) new_BQpath = np.zeros(T) new_BQpath[0] = BQ_1 new_BQpath[1:] = \ ((1 + r_path[1:T]) / (rho_s[:-1]) * omega_path_S[:T - 1, :-1] * bmat[:, 1:T].T).sum(axis=1) dist = ((BQ_init - new_BQ)**2).sum() BQpath_init[:T] = xi * new_BQpath[:T] + (1 - xi) * BQpath_init[:T] # update iteration counter tpi_iter += 1 if tpi_iter < maxiter: print('The time path solved! ->', ' iter:', tpi_iter, ', dist: ', dist) else: print('The time path did not solve.') return [new_Kpath, new_BQpath]
def 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] = aggr.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] = aggr.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 = aggr.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] = aggr.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] = aggr.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(aggr.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 = aggr.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(aggr.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] = aggr.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] = aggr.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 = aggr.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(aggr.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 = aggr.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 = aggr.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] #aggr.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 = aggr.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, 'REVENUE': REVENUE, '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