def get_SS(c1_guess, r_old, params): beta, sigma, p, ltilde, b, upsilon, chi_n_vec, A, alpha, delta, ss_max_iter, ss_tol, xi_ss = params abs_ss = 1 ss_iter = 0 while abs_ss > ss_tol and ss_iter < ss_max_iter: ss_iter += 1 r_old = r_old * np.ones(p) w_old = firms.get_w(r_old, (A, alpha, delta)) * np.ones(p) # Calculate household decisions that make last-period savings zero c1_args = (r_old, w_old, beta, sigma, ltilde, b, upsilon, chi_n_vec, p, 0.0) result_c1 = opt.root(hh.get_b_last, c1_guess, args = (c1_args)) if result_c1.success: c1 = result_c1.x else: raise ValueError("failed to find an appropriate initial consumption") # Calculate aggregate supplies for capital and labor cvec = hh.get_c(c1, r_old, beta, sigma, p) nvec = hh.get_n(cvec, sigma, ltilde, b, upsilon, chi_n_vec, w_old, p) bvec = hh.get_b(cvec, nvec, r_old, w_old, p) K = aggr.get_K(bvec)[0] L = aggr.get_L(nvec)[0] C = aggr.get_C(cvec) Y = aggr.get_Y(K, L, (A, alpha)) b_err = abs(hh.get_b_errors(cvec, r_old[0], beta, sigma)).max() n_err = abs(hh.get_n_errors(nvec, cvec, sigma, ltilde, b, upsilon, chi_n_vec, w_old[0])).max() b_last = hh.get_b_last(cvec[0], r_old, w_old, beta, sigma, ltilde, b, upsilon, chi_n_vec, p, 0.0) r_new = firms.get_r(K, L, (A, alpha, delta)) # Check market clearing abs_ss = ((r_new - r_old) ** 2).max() # Update guess r_old = xi_ss * r_new + (1 - xi_ss) * r_old print('iteration:', ss_iter, ' squared distance: ', abs_ss) return r_old[0], w_old[0], cvec, nvec, bvec, K, L, C, Y, b_err, n_err, b_last
def get_TPI(bvec1, params, graphs): ''' -------------------------------------------------------------------- Generates steady-state time path for all endogenous objects from initial state (K1, Gamma1) to the steady state. -------------------------------------------------------------------- INPUTS: params = length 16 tuple, (S, T, beta, sigma, nvec, A, alpha, delta, b_ss, K_ss, C_ss, maxiter_TPI, mindist_TPI, TPI_tol, xi, EulDiff) bvec1 = (S-1,) vector, initial period distribution of savings graphs = Boolean, =True if want graphs of TPI objects OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: c5ssf.get_K() get_path() c5ssf.get_r() c5ssf.get_w() get_cbepath() c5ssf.get_Y() c5ssf.get_C() c5ssf.print_time() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar, current processor time in seconds (float) (S, T, beta, sigma, nvec, A, alpha, delta, b_ss, K_ss, C_ss, maxiter_TPI, mindist_TPI, TPI_tol, xi_TPI, TPI_EulDiff) S = integer in [3,80], number of periods an individual lives T = integer > S, number of time periods until steady state beta = scalar in (0,1), discount factor for model period sigma = scalar > 0, coefficient of relative risk aversion nvec = (S,) vector, exogenous labor supply n_{s,t} A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital b_ss = (S-1,) vector, steady-state distribution of savings K_ss = scalar > 0, steady-state aggregate capital stock C_ss = scalar > 0, steady-state aggregate consumption maxiter_TPI = integer >= 1, Maximum number of iterations for TPI mindist_TPI = scalar > 0, Convergence criterion for TPI TPI_tol = scalar > 0, tolerance level for fsolve's in TPI xi = scalar in (0,1], TPI path updating parameter EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 L = scalar > 0, exogenous aggregate labor K1 = scalar > 0, initial aggregate capital stock K1_cstr = boolean, =True if K1 <= 0 Kpath_init = (T+S-2,) vector, initial guess for the time path of the aggregate capital stock iter_TPI = integer >= 0, current iteration of TPI dist_TPI = scalar >= 0, distance measure for fixed point Kpath_new = (T+S-2,) vector, new path of the aggregate capital stock implied by household and firm optimization r_params = length 3 tuple, (A, alpha, delta) w_params = length 2 tuple, (A, alpha) cbe_params = length 9 tuple, (S, T, beta, sigma, nvec, bvec1, b_ss, TPI_tol, EulDiff) rpath = (T+S-2,) vector, time path of the interest rate wpath = (T+S-2,) vector, time path of the wage cpath = (S, T+S-2) matrix, time path values of distribution of consumption c_{s,t} bpath = (S-1, T+S-2) matrix, time path of distribution of individual savings b_{s,t} EulErrPath = (S-1, T+S-2) matrix, time path of individual Euler errors corresponding to individual savings b_{s,t} (first column is zeros) Kpath_cnstr = (T+S-2,) Boolean vector, =True if K_t<=0 Kpath = (T+S-2,) vector, equilibrium time path of aggregate capital stock K_t Y_params = length 2 tuple, (A, alpha) Ypath = (T+S-2,) vector, equilibrium time path of aggregate output (GDP) Y_t Cpath = (T+S-2,) vector, equilibrium time path of aggregate consumption C_t RCerrPath = (T+S-1,) vector, equilibrium time path of the resource constraint error: Y_t - C_t - K_{t+1} + (1-delta)*K_t tpi_time = scalar, time to compute TPI solution (seconds) tpi_output = length 10 dictionary, {bpath, cpath, wpath, rpath, Kpath, Ypath, Cpath, EulErrPath, RCerrPath, tpi_time} FILES CREATED BY THIS FUNCTION: Kpath.png Ypath.png Cpath.png wpath.png rpath.png bpath.png cpath.png RETURNS: tpi_output -------------------------------------------------------------------- ''' start_time = time.clock() (S, T, beta, sigma, nvec, A, alpha, delta, b_ss, K_ss, C_ss, maxiter_TPI, mindist_TPI, TPI_tol, xi, EulDiff) = params L = aggr.get_L(nvec) K1, K1_cstr = aggr.get_K(bvec1) # Create time paths for K and L Kpath_init = np.zeros(T + S - 2) Kpath_init[:T] = get_path(K1, K_ss, T, "quadratic") Kpath_init[T:] = K_ss iter_TPI = int(0) dist_TPI = 10. Kpath_new = Kpath_init.copy() r_params = (A, alpha, delta) w_params = (A, alpha) cbe_params = (S, T, beta, sigma, nvec, bvec1, b_ss, TPI_tol, EulDiff) while (iter_TPI < maxiter_TPI) and (dist_TPI >= mindist_TPI): iter_TPI += 1 Kpath_init = xi * Kpath_new + (1 - xi) * Kpath_init rpath = firms.get_r(Kpath_init, L, r_params) wpath = firms.get_w(Kpath_init, L, w_params) cpath, bpath, EulErrPath = get_cbepath(cbe_params, rpath, wpath) Kpath_new = np.zeros(T + S - 2) Kpath_new[:T], Kpath_cstr = aggr.get_K(bpath[:, :T]) Kpath_new[T:] = K_ss * np.ones(S - 2) Kpath_cstr = np.append(Kpath_cstr, np.zeros(S - 2, dtype=bool)) Kpath_new[Kpath_cstr] = 0.1 # Check the distance of Kpath_new1 dist_TPI = ((Kpath_new[1:T] - Kpath_init[1:T]) ** 2).sum() # dist_TPI = np.absolute((Kpath_new[1:T] - Kpath_init[1:T]) / # Kpath_init[1:T]).max() print( 'TPI iter: ', iter_TPI, ', dist: ', "%10.4e" % (dist_TPI), ', max. abs. Euler errs: ', "%10.4e" % (np.absolute(EulErrPath).max())) if iter_TPI == maxiter_TPI and dist_TPI > mindist_TPI: print('TPI reached maxiter and did not converge.') elif iter_TPI == maxiter_TPI and dist_TPI <= mindist_TPI: print('TPI converged in the last iteration. ' + 'Should probably increase maxiter_TPI.') Kpath = Kpath_new Y_params = (A, alpha) Ypath = aggr.get_Y(Kpath, L, Y_params) Cpath = np.zeros(T + S - 2) Cpath[:T - 1] = aggr.get_C(cpath[:, :T - 1]) Cpath[T - 1:] = C_ss * np.ones(S - 1) RCerrPath = (Ypath[:-1] - Cpath[:-1] - Kpath[1:] + (1 - delta) * Kpath[:-1]) tpi_time = time.clock() - start_time tpi_output = { 'bpath': bpath, 'cpath': cpath, 'wpath': wpath, 'rpath': rpath, 'Kpath': Kpath, 'Ypath': Ypath, 'Cpath': Cpath, 'EulErrPath': EulErrPath, 'RCerrPath': RCerrPath, 'tpi_time': tpi_time} # Print TPI computation time util.print_time(tpi_time, 'TPI') if graphs: ''' ---------------------------------------------------------------- cur_path = string, path name of current directory output_fldr = string, folder in current path to save files output_dir = string, total path of images folder output_path = string, path of file name of figure to be saved tvec = (T+S-2,) vector, time period vector tgridTm1 = (T-1,) vector, time period vector to T-1 tgridT = (T,) vector, time period vector to T-1 sgrid = (S,) vector, all ages from 1 to S sgrid2 = (S-1,) vector, all ages from 2 to S tmatb = (S-1, T) matrix, time periods for all savings decisions ages (S-1) and time periods (T) smatb = (S-1, T) matrix, ages for all savings decision ages (S-1) and time periods (T) tmatc = (3, T-1) matrix, time periods for all consumption decisions ages (S) and time periods (T-1) smatc = (3, T-1) matrix, ages for all consumption decisions ages (S) and time periods (T-1) ---------------------------------------------------------------- ''' # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = "images" output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot time path of aggregate capital stock tvec = np.linspace(1, T + S - 2, T + S - 2) minorLocator = MultipleLocator(1) fig, ax = plt.subplots() plt.plot(tvec, Kpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate capital stock K') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate capital $K_{t}$') output_path = os.path.join(output_dir, "Kpath") plt.savefig(output_path) # plt.show() # Plot time path of aggregate output (GDP) fig, ax = plt.subplots() plt.plot(tvec, Ypath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate output (GDP) Y') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate output $Y_{t}$') output_path = os.path.join(output_dir, "Ypath") plt.savefig(output_path) # plt.show() # Plot time path of aggregate consumption fig, ax = plt.subplots() plt.plot(tvec, Cpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate consumption C') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate consumption $C_{t}$') output_path = os.path.join(output_dir, "C_aggr_path") plt.savefig(output_path) # plt.show() # Plot time path of real wage fig, ax = plt.subplots() plt.plot(tvec, wpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for real wage w') plt.xlabel(r'Period $t$') plt.ylabel(r'Real wage $w_{t}$') output_path = os.path.join(output_dir, "wpath") plt.savefig(output_path) # plt.show() # Plot time path of real interest rate fig, ax = plt.subplots() plt.plot(tvec, rpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for real interest rate r') plt.xlabel(r'Period $t$') plt.ylabel(r'Real interest rate $r_{t}$') output_path = os.path.join(output_dir, "rpath") plt.savefig(output_path) # plt.show() # Plot time path of individual savings distribution tgridT = np.linspace(1, T, T) sgrid2 = np.linspace(2, S, S - 1) tmatb, smatb = np.meshgrid(tgridT, sgrid2) cmap_bp = matplotlib.cm.get_cmap('summer') fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'period-$t$') ax.set_ylabel(r'age-$s$') ax.set_zlabel(r'individual savings $b_{s,t}$') strideval = max(int(1), int(round(S / 10))) ax.plot_surface(tmatb, smatb, bpath[:, :T], rstride=strideval, cstride=strideval, cmap=cmap_bp) output_path = os.path.join(output_dir, "bpath") plt.savefig(output_path) # plt.show() # Plot time path of individual consumption distribution tgridTm1 = np.linspace(1, T - 1, T - 1) sgrid = np.linspace(1, S, S) tmatc, smatc = np.meshgrid(tgridTm1, sgrid) cmap_cp = matplotlib.cm.get_cmap('summer') fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'period-$t$') ax.set_ylabel(r'age-$s$') ax.set_zlabel(r'individual consumption $c_{s,t}$') strideval = max(int(1), int(round(S / 10))) ax.plot_surface(tmatc, smatc, cpath[:, :T - 1], rstride=strideval, cstride=strideval, cmap=cmap_cp) output_path = os.path.join(output_dir, "cpath") plt.savefig(output_path) # plt.show() return tpi_output
def get_SS_bsct(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 for the outer loop -------------------------------------------------------------------- INPUTS: init_vals = length 5 tuple, (Kss_init, Lss_init, rss_init, wss_init,c1_init) args = length 16 tuple, (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, tax_params, fiscal_params, SS_tol, EulDiff, hh_fsolve, KL_outer) graphs = boolean, =True if output steady-state graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: firms.get_r() firms.get_w() hh.bn_solve() hh.c1_bSp1err() hh.get_cnb_vecs() aggr.get_K() aggr.get_L() aggr.get_Y() aggr.get_C() hh.get_cons() hh.get_n_errors() hh.get_b_errors() utils.print_time() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar > 0, clock time at beginning of program Kss_init = scalar > 0, initial guess for steady-state aggregate capital stock Lss_init = scalar > 0, initial guess for steady-state aggregate labor rss_init = scalar > 0, initial guess for steady-state interest rate wss_init = scalar > 0, initial guess for steady-state wage c1_init = scalar > 0, initial guess for first period consumpt'n S = integer in [3, 80], number of periods an individual lives 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 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 A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital tax_params = length 3 tuple, (tau_l, tau_k, tau_c) fiscal_params = length 7 tuple, (tG1, tG2, alpha_X, alpha_G, rho_G, alpha_D, alpha_D0) SS_tol = scalar > 0, tolerance level for steady-state fsolve EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 hh_fsolve = Boolean, =True if want to solve HH problem with one large root finder call tau_l = scalar, marginal tax rate on labor income tau_k = scalar, marginal tax rate on capital income tau_c = scalar, marginal tax rate on corporate income tG1 = integer, model period when budget closure rule begins tG2 = integer, model period when budget is closed alpha_X = scalar, ratio of lump sum transfers to GDP alpha_G = scalar, ratio of government spending to GDP prior to budget closure rule beginning rho_G = scalar in (0,1), rate of convergence to SS budget alpha_D = scalar, steady-state debt to GDP ratio alpha_D0 = scalar, debt to GDP ratio in the initial period maxiter_SS = integer >= 1, maximum number of iterations in outer loop bisection method iter_SS = integer >= 0, index of iteration number mindist_SS = scalar > 0, minimum distance tolerance for convergence dist_SS = scalar > 0, distance metric for current iteration xi_SS = scalar in (0,1], updating parameter KL_init = (2,) vector, (K_init, L_init) c1_options = length 1 dict, options to pass into opt.root(c1_bSp1err,...) cnb_args = length 9 tuple, args to pass into get_cnb_vecs() r_params = length 3 tuple, args to pass into get_r() w_params = length 2 tuple, args to pass into get_w() Y_params = length 2 tuple, args to pass into get_Y() K_init = scalar, initial value of aggregate capital stock L_init = scalar, initial value of aggregate labor r_init = scalar, initial value for interest rate w_init = scalar, initial value for wage Y_init = scalar, initial value for output x_init = scalar, initial value for per household lump sum transfers rpath = (S,) vector, lifetime path of interest rates wpath = (S,) vector, lifetime path of wages xpath = (S,) vector, lifetime path of lump sum transfers c1_args = length 10 tuple, args to pass into c1_bSp1err() results_c1 = results object, root finder results from opt.root(c1_bSp1err,...) c1_new = scalar, updated value of optimal c1 given r_init and w_init cvec_new = (S,) vector, updated values for lifetime consumption nvec_new = (S,) vector, updated values for lifetime labor supply b_splus1_vec_new = (S,) vector, updated values for lifetime savings (b1, b2,...bS) b_s_vec_new = (S,) vector, updated values for lifetime savings enter period with (b0, b1,...bS) b_Sp1_new = scalar, updated value for savings in last period, should be arbitrarily close to zero B_new = scalar, aggregate household savings given bvec_new B_cnstr = boolean, =True if K_new <= 0 L_new = scalar, updated L given nvec_new debt_ss = scalar, government debt in the SS K_new = scalar, updated K given bvec_new and SS debt K_cnstr = boolean, =True if K_new <= 0 KL_new = (2,) vector, updated K and L given bvec_new, nvec_new K_ss = scalar > 0, steady-state aggregate capital stock L_ss = scalar > 0, steady-state aggregate labor B_ss = scalar > 0, steady-state aggregate savings r_ss = scalar > 0, steady-state interest rate w_ss = scalar > 0, steady-state wage x_ss = scalar > 0, steady-state per household lump sum transfers c1_ss = scalar > 0, steady-state consumption in first period c_ss = (S,) vector, steady-state lifetime consumption n_ss = (S,) vector, steady-state lifetime labor supply b_splus1_ss = (S,) vector, steady-state lifetime savings (b1_ss, b2_ss, ...bS+1_ss) b_s_ss = (S,) vector, steady-state lifetime savings enter period with (b0_ss, b2_ss, ...bS_ss) where b0_ss=0 b_Sp1_ss = scalar, steady-state savings for period after last period of life. b_Sp1_ss approx. 0 in equilibrium Y_ss = scalar > 0, steady-state aggregate output (GDP) C_ss = scalar > 0, steady-state aggregate consumption n_err_params = length 5 tuple, args to pass into get_n_errors() n_err_ss = (S,) vector, lifetime labor supply Euler errors b_err_params = length 2 tuple, args to pass into get_b_errors() b_err_ss = (S-1) vector, lifetime savings Euler errors rev_params = length 4 tuple, (A, alpha, delta, tax_params) R_ss = scalar, steady-state tax revenue X_ss = scalar, total steady-state government transfers debt_service_ss = scalar, steady-state debt service cost G_ss = steady-state government spending RCerr_ss = scalar, resource constraint error ss_time = scalar, seconds elapsed to run steady-state comput'n ss_output = length 17 dict, steady-state objects {n_ss, b_s_ss, b_splus1_ss, c_ss, b_Sp1_ss, w_ss, r_ss, B_ss, K_ss, L_ss, Y_ss, C_ss, G_ss, n_err_ss, b_err_ss, RCerr_ss, ss_time} FILES CREATED BY THIS FUNCTION: SS_bc.png SS_n.png RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() Kss_init, Lss_init, rss_init, wss_init, c1_init = init_vals (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, tax_params, fiscal_params, SS_tol, EulDiff, hh_fsolve) = args tau_l, tau_k, tau_c = tax_params tG1, tG2, alpha_X, alpha_G, rho_G, alpha_D, alpha_D0 = fiscal_params maxiter_SS = 200 iter_SS = 0 mindist_SS = 1e-10 dist_SS = 10 xi_SS = 0.15 KL_init = np.array([Kss_init, Lss_init]) r_params = (A, alpha, delta, tau_c) w_params = (A, alpha) Y_params = (A, alpha) inner_loop_params = (c1_init, S, beta, sigma, l_tilde, \ b_ellip, upsilon, chi_n_vec, A, alpha, delta,\ tax_params, fiscal_params,\ EulDiff, hh_fsolve, SS_tol) while (iter_SS < maxiter_SS) and (dist_SS >= mindist_SS): iter_SS += 1 K_init, L_init = KL_init r_init = firms.get_r(r_params, K_init, L_init) w_init = firms.get_w(w_params, K_init, L_init) Y_init = aggr.get_Y(Y_params, K_init, L_init) x_init = (alpha_X * Y_init) / S B_new, K_new, L_new, Y_new, debt, cvec, nvec, b_s_vec, b_splus1_vec,\ b_Sp1, x_new, r_new, w_new\ = inner_loop(r_init, w_init, Y_init, x_init, inner_loop_params) KL_new = np.array([K_new, L_new]) dist_SS = ((KL_new - KL_init)**2).sum() KL_init = xi_SS * KL_new + (1 - xi_SS) * KL_init rev_params = (A, alpha, delta, tax_params) R_new = tax.revenue(r_new, w_new, b_s_vec, nvec, K_new, L_new, rev_params) X_new = x_new * S G_new = R_new - (X_new + debt * r_new) print('tax rev to GDP: ', R_new / Y_new) print('SS outlays to GDP: ', ((debt * r_new) + X_new + G_new) / Y_new) print('SS G spending to GDP: ', G_new / Y_new) print('factor prices: ', r_new, w_new) print('SS Iteration=', iter_SS, ', SS Distance=', dist_SS) B_ss, K_ss, L_ss, Y_ss, debt_ss, c_ss, n_ss, b_s_ss, b_splus1_ss,\ b_Sp1_ss, x_ss, r_ss, w_ss\ = inner_loop(r_new, w_new, Y_new, x_new, inner_loop_params) C_ss = aggr.get_C(c_ss) n_err_args = (w_ss, c_ss, sigma, l_tilde, chi_n_vec, b_ellip, upsilon, tau_l, EulDiff) n_err_ss = hh.get_n_errors(n_ss, n_err_args) b_err_params = (beta, sigma, tau_k) b_err_ss = hh.get_b_errors(b_err_params, r_ss, c_ss, EulDiff) rev_params = (A, alpha, delta, tax_params) R_ss = tax.revenue(r_ss, w_ss, b_s_ss, n_ss, K_ss, L_ss, rev_params) X_ss = x_ss * S debt_service_ss = r_ss * alpha_D * Y_ss G_ss = R_ss - (X_ss + debt_service_ss) RCerr_ss = Y_ss - C_ss - delta * K_ss - G_ss print('SS tax rev to GDP: ', R_ss / Y_ss) print('SS outlays to GDP: ', (debt_service_ss + X_ss + G_ss) / Y_ss) print('SS G spending to GDP: ', G_ss / Y_ss) ss_time = time.clock() - start_time ss_output = { 'n_ss': n_ss, 'b_s_ss': b_s_ss, 'b_splus1_ss': b_splus1_ss, 'c_ss': c_ss, 'b_Sp1_ss': b_Sp1_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'B_ss': B_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'G_ss': G_ss, 'X_ss': X_ss, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('n_ss is: ', n_ss) print('b_s_ss is: ', b_s_ss) print('K_ss=', K_ss, ', L_ss=', L_ss) print('r_ss=', r_ss, ', w_ss=', w_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('Steay-state government spending is: ', G_ss) if G_ss < 0: print('WARNING: SS debt to GDP ratio and tax policy are generating ' + 'negative government spending.') print('Steay-state tax revenue, transfers, and debt service are: ', R_ss, X_ss, debt_service_ss) print('Steady-state residual savings b_Sp1 is: ', b_Sp1_ss) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: ''' ---------------------------------------------------------------- cur_path = string, path name of current directory output_fldr = string, folder in current path to save files output_dir = string, total path of images folder output_path = string, path of file name of figure to be saved age_pers = (S,) vector, ages from 1 to S ---------------------------------------------------------------- ''' # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = 'images' output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot steady-state consumption and savings distributions age_pers = np.arange(1, S + 1) fig, ax = plt.subplots() plt.plot(age_pers, c_ss, marker='D', label='Consumption') plt.plot(age_pers, b_splus1_ss, marker='D', label='Savings') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state consumption and savings', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Units of consumption') plt.xlim((0, S + 1)) # plt.ylim((-1.0, 1.15 * (b_ss.max()))) plt.legend(loc='upper left') output_path = os.path.join(output_dir, 'SS_bc') plt.savefig(output_path) # plt.show() plt.close() # Plot steady-state labor supply distributions fig, ax = plt.subplots() plt.plot(age_pers, n_ss, marker='D', label='Labor supply') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state labor supply', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Labor supply') plt.xlim((0, S + 1)) # plt.ylim((-0.1, 1.15 * (n_ss.max()))) plt.legend(loc='upper right') output_path = os.path.join(output_dir, 'SS_n') plt.savefig(output_path) # plt.show() plt.close() return ss_output
def get_SS(args, graph=False): (init_vals, beta, sigma, chi_n_vec, l_tilde, b_ellip, upsilon, S, alpha, A, delta, etrparam_vec, mtrxparam_vec, mtryparam_vec, avg_inc_data) = args dist = 10 mindist = 1e-08 maxiter = 500 ss_iter = 0 xi = 0.2 r_params = (alpha, A, delta) w_params = (alpha, A) Y_params = (alpha, A) while dist > mindist and ss_iter < maxiter: ss_iter += 1 K, L, X = init_vals Y = aggr.get_Y(K, L, Y_params) factor = (S * avg_inc_data) / (Y - delta * K) r = firms.get_r(K, L, r_params) w = firms.get_w(K, L, w_params) c1_guess = 0.1 c1_args = (r, w, X, factor, beta, sigma, chi_n_vec, l_tilde, b_ellip, upsilon, S, etrparam_vec, mtrxparam_vec, mtryparam_vec) results_c1 = opt.root(hh.get_bSp1, c1_guess, args=(c1_args)) c1 = results_c1.x cvec, nvec, bvec = hh.get_cnbvecs(c1, c1_args) # print('cvec: ', cvec) # print('nvec: ', nvec) # print('bvec: ', bvec) bs_vec = np.append(0, bvec[:-1]) K_new = max(aggr.get_K(bvec[:-1]), 0.001) L_new = max(aggr.get_L(nvec), 0.001) lab_inc = w * nvec cap_inc = r * bs_vec tot_tax_liab_all = tax.get_tot_tax_liab(lab_inc, cap_inc, factor, etrparam_vec) X_new = (1 / S) * (tot_tax_liab_all.sum()) # factor_new = avg_inc_data / ((1 / S) * # (r * bs_vec + w * nvec).sum()) new_vals = np.array([K_new, L_new, X_new]) dist = ((((new_vals - init_vals) / init_vals) * 100)**2).sum() init_vals = xi * new_vals + (1 - xi) * init_vals print('iter:', ss_iter, ' dist: ', dist) print(init_vals) c_ss = cvec n_ss = nvec b_ss = bs_vec K_ss = K_new L_ss = L_new r_ss = r w_ss = w Y_params = (alpha, A) Y_ss = aggr.get_Y(K_ss, L_ss, Y_params) C_ss = aggr.get_C(c_ss) X_ss = X_new factor_ss = factor tot_tax_liab_all_ss = tot_tax_liab_all tot_tax_liab_ss = X_ss * S ss_output = { 'c_ss': c_ss, 'n_ss': n_ss, 'b_ss': b_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'r_ss': r_ss, 'w_ss': w_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'X_ss': X_ss, 'factor_ss': factor_ss, 'tot_tax_liab_all_ss': tot_tax_liab_all_ss, 'tot_tax_liab_ss': tot_tax_liab_ss } if graph: # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = 'images' output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot c_ss, n_ss, b_ss # Plot steady-state consumption and savings distributions age_pers = np.arange(1, S + 1) fig, ax = plt.subplots() plt.plot(age_pers, c_ss, marker='D', label='Consumption') plt.plot(age_pers, np.append(0, b_ss[:-1]), marker='D', label='Savings') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state consumption and savings', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Units of consumption') plt.xlim((0, S + 1)) # plt.ylim((-1.0, 1.15 * (b_ss.max()))) plt.legend(loc='upper left') output_path = os.path.join(output_dir, 'SS_bc') plt.savefig(output_path) # plt.show() plt.close() # Plot steady-state labor supply distributions fig, ax = plt.subplots() plt.plot(age_pers, n_ss, marker='D', label='Labor supply') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state labor supply', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Labor supply') plt.xlim((0, S + 1)) # plt.ylim((-0.1, 1.15 * (n_ss.max()))) plt.legend(loc='upper right') output_path = os.path.join(output_dir, 'SS_n') plt.savefig(output_path) # plt.show() plt.close() return ss_output
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
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
def get_SS_bsct(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 for the outer loop -------------------------------------------------------------------- INPUTS: init_vals = length 3 tuple, (Kss_init, Lss_init, c1_init) args = length 15 tuple, (J, S, lambdas, emat, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, SS_tol, EulDiff) graphs = boolean, =True if output steady-state graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: firms.get_r() firms.get_w() hh.bn_solve() hh.c1_bSp1err() hh.get_cnb_vecs() aggr.get_K() aggr.get_L() aggr.get_Y() aggr.get_C() hh.get_cons() hh.get_n_errors() hh.get_b_errors() utils.print_time() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar > 0, clock time at beginning of program rss_init = scalar > 0, initial guess for steady-state interest rate c1_init = scalar > 0, initial guess for first period consumpt'n S = integer in [3, 80], number of periods an individual lives 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 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 A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital SS_tol = scalar > 0, tolerance level for steady-state fsolve EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 hh_fsolve = boolean, =True if solve inner-loop household problem by choosing c_1 to set final period savings b_{S+1}=0 KL_outer = boolean, =True if guess K and L in outer loop Otherwise, guess r and w in outer loop maxiter_SS = integer >= 1, maximum number of iterations in outer loop bisection method iter_SS = integer >= 0, index of iteration number mindist_SS = scalar > 0, minimum distance tolerance for convergence dist_SS = scalar > 0, distance metric for current iteration xi_SS = scalar in (0,1], updating parameter KL_init = (2,) vector, (K_init, L_init) c1_options = length 1 dict, options to pass into opt.root(c1_bSp1err,...) cnb_args = length 8 tuple, args to pass into get_cnb_vecs() r_params = length 3 tuple, args to pass into get_r() w_params = length 2 tuple, args to pass into get_w() K_init = scalar, initial value of aggregate capital stock L_init = scalar, initial value of aggregate labor r_init = scalar, initial value for interest rate w_init = scalar, initial value for wage rpath = (S,) vector, lifetime path of interest rates wpath = (S,) vector, lifetime path of wages c1_args = length 10 tuple, args to pass into c1_bSp1err() results_c1 = results object, root finder results from opt.root(c1_bSp1err,...) c1_new = scalar, updated value of optimal c1 given r_init and w_init cvec_new = (S,) vector, updated values for lifetime consumption nvec_new = (S,) vector, updated values for lifetime labor supply bvec_new = (S,) vector, updated values for lifetime savings (b1, b2,...bS) b_Sp1_new = scalar, updated value for savings in last period, should be arbitrarily close to zero K_new = scalar, updated K given bvec_new K_cnstr = boolean, =True if K_new <= 0 L_new = scalar, updated L given nvec_new KL_new = (2,) vector, updated K and L given bvec_new, nvec_new K_ss = scalar > 0, steady-state aggregate capital stock L_ss = scalar > 0, steady-state aggregate labor r_ss = scalar > 0, steady-state interest rate w_ss = scalar > 0, steady-state wage c1_ss = scalar > 0, steady-state consumption in first period c_ss = (S,) vector, steady-state lifetime consumption n_ss = (S,) vector, steady-state lifetime labor supply b_ss = (S,) vector, steady-state lifetime savings (b1_ss, b2_ss, ...bS_ss) where b1_ss=0 b_Sp1_ss = scalar, steady-state savings for period after last period of life. b_Sp1_ss approx. 0 in equilibrium Y_params = length 2 tuple, (A, alpha) Y_ss = scalar > 0, steady-state aggregate output (GDP) C_ss = scalar > 0, steady-state aggregate consumption n_err_params = length 5 tuple, args to pass into get_n_errors() n_err_ss = (S,) vector, lifetime labor supply Euler errors b_err_params = length 2 tuple, args to pass into get_b_errors() b_err_ss = (S-1) vector, lifetime savings Euler errors RCerr_ss = scalar, resource constraint error ss_time = scalar, seconds elapsed to run steady-state comput'n ss_output = length 14 dict, steady-state objects {n_ss, b_ss, c_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} FILES CREATED BY THIS FUNCTION: SS_bc.png SS_n.png RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() r_init, c1_init = init_vals (J, S, lambdas, emat, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, SS_tol, EulDiff) = args maxiter_SS = 200 iter_SS = 0 mindist_SS = 1e-12 dist_SS = 10 xi_SS = 0.2 c1_options = {'maxiter': 500} rw_params = (A, alpha, delta) nmat_init = np.ones((S, J)) * 0.4 bmat_init = np.ones((S - 1, J)) * 0.03 nmat = nmat_init bmat = bmat_init while (iter_SS < maxiter_SS) and (dist_SS >= mindist_SS): iter_SS += 1 w_init = firms.get_w_from_r(r_init, rw_params) inner_args = (nmat, bmat, S, J, beta, sigma, emat, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, lambdas, EulDiff, SS_tol) (K_new, L_new, cmat, nmat, bmat, b_Sp1_vec, r_new, w_new, n_err_mat, b_err_mat) = inner_loop(r_init, w_init, inner_args) dist_SS = np.absolute(r_new - r_init).sum() r_init = xi_SS * r_new + (1 - xi_SS) * r_init print('SS Iteration=', iter_SS, ', SS Distance=', '%10.4e' % (dist_SS), ',r:', '%10.4e' % (r_new), ', Max Abs Errors=', '%10.4e' % (np.absolute(n_err_mat).max()), (np.absolute(n_err_mat).max())) K_ss = K_new L_ss = L_new r_ss = r_init w_ss = firms.get_w_from_r(r_ss, rw_params) c_ss = cmat n_ss = nmat b_ss = np.append(np.zeros((1, J)), bmat, axis=0) b_Sp1_ss = b_Sp1_vec Y_params = (A, alpha) Y_ss = aggr.get_Y(K_ss, L_ss, Y_params) C_ss = aggr.get_C(c_ss, lambdas) n_err_ss = n_err_mat b_err_ss = b_err_mat RCerr_ss = Y_ss - C_ss - delta * K_ss ss_time = time.clock() - start_time ss_output = { 'n_ss': n_ss, 'b_ss': b_ss, 'c_ss': c_ss, 'b_Sp1_ss': b_Sp1_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('K_ss=', K_ss, ', L_ss=', L_ss) print('r_ss=', r_ss, ', w_ss=', w_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('Max. absolute SS residual savings b_Sp1_j is: ', np.absolute(b_Sp1_ss).max()) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: ''' ---------------------------------------------------------------- cur_path = string, path name of current directory output_fldr = string, folder in current path to save files output_dir = string, total path of images folder output_path = string, path of file name of figure to be saved sgrid = (S,) vector, ages from 1 to S lamcumsum = (J,) vector, cumulative sum of lambdas vector jmidgrid = (J,) vector, midpoints of ability percentile bins smat = (J, S) matrix, sgrid copied down J rows jmat = (J, S) matrix, jmidgrid copied across S columns ---------------------------------------------------------------- ''' # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = 'images' output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot 3D steady-state consumption distribution sgrid = np.arange(1, S + 1) lamcumsum = lambdas.cumsum() jmidgrid = 0.5 * lamcumsum + 0.5 * (lamcumsum - lambdas) smat, jmat = np.meshgrid(sgrid, jmidgrid) cmap_c = cm.get_cmap('summer') fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'ability-$j$') ax.set_zlabel(r'indiv. consumption $c_{j,s}$') ax.plot_surface(smat, jmat, c_ss.T, rstride=1, cstride=6, cmap=cmap_c) output_path = os.path.join(output_dir, 'c_ss_3D') plt.savefig(output_path) # plt.show() plt.close() # Plot 2D steady-state consumption distribution minorLocator = MultipleLocator(1) fig, ax = plt.subplots() linestyles = np.array(["-", "--", "-.", ":"]) markers = np.array(["x", "v", "o", "d", ">", "|"]) pct_lb = 0 for j in range(J): this_label = (str(int(np.rint(pct_lb))) + " - " + str(int(np.rint(pct_lb + 100 * lambdas[j]))) + "%") pct_lb += 100 * lambdas[j] if j <= 3: ax.plot(sgrid, c_ss[:, j], label=this_label, linestyle=linestyles[j], color='black') elif j > 3: ax.plot(sgrid, c_ss[:, j], label=this_label, marker=markers[j - 4], color='black') ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'indiv. consumption $c_{j,s}$') output_path = os.path.join(output_dir, 'c_ss_2D') plt.savefig(output_path) # plt.show() plt.close() # Plot 3D steady-state labor supply distribution fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'ability-$j$') ax.set_zlabel(r'labor supply $n_{j,s}$') ax.plot_surface(smat, jmat, n_ss.T, rstride=1, cstride=6, cmap=cmap_c) output_path = os.path.join(output_dir, 'n_ss_3D') plt.savefig(output_path) # plt.show() plt.close() # Plot 2D steady-state labor supply distribution minorLocator = MultipleLocator(1) fig, ax = plt.subplots() linestyles = np.array(["-", "--", "-.", ":"]) markers = np.array(["x", "v", "o", "d", ">", "|"]) pct_lb = 0 for j in range(J): this_label = (str(int(np.rint(pct_lb))) + " - " + str(int(np.rint(pct_lb + 100 * lambdas[j]))) + "%") pct_lb += 100 * lambdas[j] if j <= 3: ax.plot(sgrid, n_ss[:, j], label=this_label, linestyle=linestyles[j], color='black') elif j > 3: ax.plot(sgrid, n_ss[:, j], label=this_label, marker=markers[j - 4], color='black') ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'labor supply $n_{j,s}$') output_path = os.path.join(output_dir, 'n_ss_2D') plt.savefig(output_path) # plt.show() plt.close() # Plot 3D steady-state savings/wealth distribution fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'ability-$j$') ax.set_zlabel(r'indiv. savings $b_{j,s}$') ax.plot_surface(smat, jmat, b_ss.T, rstride=1, cstride=6, cmap=cmap_c) output_path = os.path.join(output_dir, 'b_ss_3D') plt.savefig(output_path) # plt.show() plt.close() # Plot 2D steady-state savings/wealth distribution fig, ax = plt.subplots() linestyles = np.array(["-", "--", "-.", ":"]) markers = np.array(["x", "v", "o", "d", ">", "|"]) pct_lb = 0 for j in range(J): this_label = (str(int(np.rint(pct_lb))) + " - " + str(int(np.rint(pct_lb + 100 * lambdas[j]))) + "%") pct_lb += 100 * lambdas[j] if j <= 3: ax.plot(sgrid, b_ss[:, j], label=this_label, linestyle=linestyles[j], color='black') elif j > 3: ax.plot(sgrid, b_ss[:, j], label=this_label, marker=markers[j - 4], color='black') ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'indiv. savings $b_{j,s}$') output_path = os.path.join(output_dir, 'b_ss_2D') plt.savefig(output_path) # plt.show() plt.close() return ss_output
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 and a small open economy. -------------------------------------------------------------------- INPUTS: init_vals = length 5 tuple, (Kss_init, Lss_init, rss_init, wss_init,c1_init) args = length 14 tuple, (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, SS_tol, EulDiff, hh_fsolve, KL_outer) graphs = boolean, =True if output steady-state graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: firms.get_r() firms.get_w() hh.bn_solve() hh.c1_bSp1err() hh.get_cnb_vecs() aggr.get_K() aggr.get_L() aggr.get_Y() aggr.get_C() hh.get_cons() hh.get_n_errors() hh.get_b_errors() utils.print_time() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar > 0, clock time at beginning of program Kss_init = scalar > 0, initial guess for steady-state aggregate capital stock supplied Lss_init = scalar > 0, initial guess for steady-state aggregate labor rss_init = scalar > 0, initial guess for steady-state interest rate wss_init = scalar > 0, initial guess for steady-state wage c1_init = scalar > 0, initial guess for first period consumpt'n S = integer in [3, 80], number of periods an individual lives 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 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 A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital SS_tol = scalar > 0, tolerance level for steady-state fsolve EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 maxiter_SS = integer >= 1, maximum number of iterations in outer loop bisection method iter_SS = integer >= 0, index of iteration number mindist_SS = scalar > 0, minimum distance tolerance for convergence dist_SS = scalar > 0, distance metric for current iteration xi_SS = scalar in (0,1], updating parameter KL_init = (2,) vector, (K_init, L_init) c1_options = length 1 dict, options to pass into opt.root(c1_bSp1err,...) cnb_args = length 8 tuple, args to pass into get_cnb_vecs() #r_params = length 3 tuple, args to pass into get_r() w_params = length 2 tuple, args to pass into get_w() K_init = scalar, initial value of aggregate capital stock supplied L_init = scalar, initial value of aggregate labor r_init = scalar, initial value for interest rate w_init = scalar, initial value for wage K_d = scalar, capital demand rpath = (S,) vector, lifetime path of interest rates wpath = (S,) vector, lifetime path of wages c1_args = length 10 tuple, args to pass into c1_bSp1err() results_c1 = results object, root finder results from opt.root(c1_bSp1err,...) c1_new = scalar, updated value of optimal c1 given r_init and w_init cvec_new = (S,) vector, updated values for lifetime consumption nvec_new = (S,) vector, updated values for lifetime labor supply b_s_new = (S,) vector, updated values for lifetime wealth b_splus1_new = (S,) vector, updated values for lifetime savings (b1, b2,...bS) b_Sp1_new = scalar, updated value for savings in last period, should be arbitrarily close to zero K_new = scalar, updated K given bvec_new K_cnstr = boolean, =True if K_new <= 0 L_new = scalar, updated L given nvec_new KL_new = (2,) vector, updated K and L given bvec_new, nvec_new K_ss = scalar > 0, steady-state aggregate capital stock supplied K_d_ss = scalar > 0, steady-state aggregate capital stock demanded L_ss = scalar > 0, steady-state aggregate labor r_ss = scalar > 0, steady-state interest rate w_ss = scalar > 0, steady-state wage c1_ss = scalar > 0, steady-state consumption in first period c_ss = (S,) vector, steady-state lifetime consumption n_ss = (S,) vector, steady-state lifetime labor supply b_s_ss = (S,) vector, steady-state wealth enter period with b_splus1_ss = (S,) vector, steady-state lifetime savings (b1_ss, b2_ss, ...bS_ss) where b1_ss=0 b_Sp1_ss = scalar, steady-state savings for period after last period of life. b_Sp1_ss approx. 0 in equilibrium Y_params = length 2 tuple, (A, alpha) Y_ss = scalar > 0, steady-state aggregate output (GDP) C_ss = scalar > 0, steady-state aggregate consumption n_err_params = length 5 tuple, args to pass into get_n_errors() n_err_ss = (S,) vector, lifetime labor supply Euler errors b_err_params = length 2 tuple, args to pass into get_b_errors() b_err_ss = (S-1) vector, lifetime savings Euler errors RCerr_ss = scalar, resource constraint error ss_time = scalar, seconds elapsed to run steady-state comput'n ss_output = length 14 dict, steady-state objects {n_ss, b_ss, c_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} FILES CREATED BY THIS FUNCTION: SS_bc.png SS_n.png RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() c1_init = init_vals (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, r_star, SS_tol, EulDiff, hh_fsolve) = args c1_options = {'maxiter': 500} cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, EulDiff) w_params = (A, alpha, delta) K_params = (A, alpha, delta) r_ss = r_star w_ss = firms.get_w(r_ss, w_params) if hh_fsolve: b_init = np.ones((S - 1, 1)) * 0.05 n_init = np.ones((S, 1)) * 0.4 guesses = np.append(b_init, n_init) bn_params = (r_ss, w_ss, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, EulDiff) [solutions, infodict, ier, message] = \ opt.fsolve(hh.bn_solve, guesses, args=bn_params, xtol=SS_tol, full_output=True) euler_errors = infodict['fvec'] print('Max Euler errors: ', np.absolute(euler_errors).max()) b_splus1_ss = np.append(solutions[:S - 1], 0.0) n_ss = solutions[S - 1:] b_Sp1_ss = 0.0 b_s_ss = np.append(0.0, b_splus1_ss[:-1]) c_ss = hh.get_cons(r_ss, w_ss, b_s_ss, b_splus1_ss, n_ss) else: rpath = r_ss * np.ones(S) wpath = w_ss * np.ones(S) c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, rpath, wpath, EulDiff) c1_options = {'maxiter': 500} results_c1 = \ opt.root(hh.c1_bSp1err, c1_new, args=(c1_args), method='lm', tol=SS_tol, options=(c1_options)) c1_ss = results_c1.x cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, EulDiff) c_ss, n_ss, b_s_ss, b_Sp1_ss = hh.get_cnb_vecs(c1_ss, rpath, wpath, cnb_args) b_splus1_ss = np.append(b_s_ss[1:], b_Sp1_ss) L_ss = aggr.get_L_s(n_ss) K_s_ss, K_cnstr = aggr.get_K_s(b_s_ss) K_d_ss = firms.get_K_d(r_ss, L_ss, K_params) Y_params = (A, alpha) Y_ss = aggr.get_Y(Y_params, K_d_ss, L_ss) C_ss = aggr.get_C(c_ss) n_err_args = (w_ss, c_ss, sigma, l_tilde, chi_n_vec, b_ellip, upsilon, EulDiff) n_err_ss = hh.get_n_errors(n_ss, n_err_args) b_err_params = (beta, sigma) b_err_ss = hh.get_b_errors(b_err_params, r_ss, c_ss, EulDiff) NX_ss = Y_ss - C_ss - delta * K_s_ss RCerr_ss = Y_ss - C_ss - delta * K_s_ss - NX_ss ss_time = time.clock() - start_time ss_output = { 'n_ss': n_ss, 'b_s_ss': b_s_ss, 'b_splus1_ss': b_splus1_ss, 'c_ss': c_ss, 'b_Sp1_ss': b_Sp1_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'K_s_ss': K_s_ss, 'K_d_ss': K_d_ss, 'L_ss': L_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('n_ss is: ', n_ss) print('b_splus1_ss is: ', b_splus1_ss) print('K_s_ss=', K_s_ss, 'K_d_ss=', K_d_ss, ', L_ss=', L_ss) print('r_ss=', r_ss, ', w_ss=', w_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('Net Exports = ', NX_ss) print('Output and consumption: ', Y_ss, C_ss) print('Steady-state residual savings b_Sp1 is: ', b_Sp1_ss) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: ''' ---------------------------------------------------------------- cur_path = string, path name of current directory output_fldr = string, folder in current path to save files output_dir = string, total path of images folder output_path = string, path of file name of figure to be saved age_pers = (S,) vector, ages from 1 to S ---------------------------------------------------------------- ''' # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = 'images' output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot steady-state consumption and savings distributions age_pers = np.arange(1, S + 1) fig, ax = plt.subplots() plt.plot(age_pers, c_ss, marker='D', label='Consumption') plt.plot(age_pers, b_splus1_ss, marker='D', label='Savings') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state consumption and savings', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Units of consumption') plt.xlim((0, S + 1)) # plt.ylim((-1.0, 1.15 * (b_ss.max()))) plt.legend(loc='upper left') output_path = os.path.join(output_dir, 'SS_bc') plt.savefig(output_path) # plt.show() plt.close() # Plot steady-state labor supply distributions fig, ax = plt.subplots() plt.plot(age_pers, n_ss, marker='D', label='Labor supply') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state labor supply', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Labor supply') plt.xlim((0, S + 1)) # plt.ylim((-0.1, 1.15 * (n_ss.max()))) plt.legend(loc='upper right') output_path = os.path.join(output_dir, 'SS_n') plt.savefig(output_path) # plt.show() plt.close() return ss_output
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 2 tuple, (rss_init, c1_init) args = length 15 tuple, (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, Bsct_Tol, Eul_Tol, EulDiff, xi, maxiter) 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 = scalar > 0, initial guess for first period consumpt'n S = integer in [3, 80], number of periods an individual lives 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 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 A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital Bsct_Tol = scalar > 0, tolderance level for outer-loop bisection method Eul_Tol = scalar > 0, tolerance level for inner-loop root finder EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 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 iter_SS = integer >= 0, index of iteration number dist = scalar > 0, distance metric for current iteration rw_params = length 3 tuple, (A, alpha, delta) args to pass into firms.get_r() and firms.get_w() w_init = scalar, initial value for wage inner_args = length 14 tuple, args to pass into inner_loop() K_new = scalar > 0, updated K given r_init, w_init, and bvec L_new = scalar > 0, updated L given r_init, w_init, and nvec cvec = (S,) vector, updated values for lifetime consumption nvec = (S,) vector, updated values for lifetime labor supply bvec = (S,) vector, updated values for lifetime savings (b1, b2,...bS) b_Sp1 = scalar, updated value for savings in last period, should be arbitrarily close to zero r_new = scalar > 0, updated interest rate given bvec and nvec w_new = scalar > 0, updated wage given bvec and nvec n_errors = (S,) vector, labor supply Euler errors given r_init and w_init b_errors = (S-1,) vector, savings Euler errors given r_init and w_init all_errors = (2S,) vector, (n_errors, b_errors, b_Sp1) c_ss = (S,) vector, steady-state lifetime consumption n_ss = (S,) vector, steady-state lifetime labor supply b_ss = (S,) vector, steady-state wealth enter period with (b1, b2, ...bS) b_Sp1_ss = scalar, steady-state savings for period after last period of life. b_Sp1_ss approx. 0 in equilibrium n_err_ss = (S,) vector, lifetime labor supply Euler errors b_err_ss = (S-1) vector, 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, (A, alpha) 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 14 dict, steady-state objects {n_ss, b_ss, c_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} FILES CREATED BY THIS FUNCTION: SS_bc.png SS_n.png RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() r_init, c1_init = init_vals (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, Bsct_Tol, Eul_Tol, EulDiff, xi, maxiter) = args iter_SS = 0 dist = 10 nvec_init = np.ones(S) * 0.4 bvec_init = np.append(0.0, np.ones(S - 1) * 0.05) rw_params = (A, alpha, delta) while (iter_SS < maxiter) and (dist >= Bsct_Tol): iter_SS += 1 w_init = firms.get_w(r_init, rw_params) inner_args = (nvec_init, bvec_init, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, EulDiff, Eul_Tol) (K_new, L_new, cvec, nvec, bvec, b_Sp1, r_new, w_new, n_errors, b_errors) = inner_loop(r_init, w_init, inner_args) all_errors = np.hstack((n_errors, b_errors, b_Sp1)) dist = (np.absolute(r_new - r_init)).sum() r_init = xi * r_new + (1 - xi) * r_init print('SS Iter=', iter_SS, ', SS Dist=', '%10.4e' % (dist), ', Max Abs Err=', '%10.4e' % (np.absolute(all_errors).max())) c_ss = cvec n_ss = nvec b_ss = bvec b_Sp1_ss = b_Sp1 n_err_ss = n_errors b_err_ss = b_errors r_ss = r_new w_ss = w_new K_ss = K_new L_ss = L_new Y_params = (A, alpha) Y_ss = aggr.get_Y(K_ss, L_ss, Y_params) C_ss = aggr.get_C(c_ss) RCerr_ss = Y_ss - C_ss - delta * K_ss ss_time = time.clock() - start_time ss_output = { 'c_ss': c_ss, 'n_ss': n_ss, 'b_ss': b_ss, 'b_Sp1_ss': b_Sp1_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('n_ss is: ', n_ss) print('b_ss is: ', b_ss) print('K_ss=', K_ss, ', L_ss=', L_ss) print('r_ss=', r_ss, ', w_ss=', w_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('Steady-state residual savings b_Sp1 is: ', b_Sp1_ss) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: create_graphs(c_ss, b_ss, n_ss) return ss_output
def get_SS(bss_guess, args, graphs=False): ''' -------------------------------------------------------------------- Solve for the steady-state solution of the S-period-lived agent OG model with exogenous labor supply using one root finder in bvec -------------------------------------------------------------------- INPUTS: bss_guess = (S-1,) vector, initial guess for b_ss args = length 8 tuple, (nvec, beta, sigma, A, alpha, delta, SS_tol, SS_EulDiff) graphs = boolean, =True if output steady-state graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: SS_EulErrs() aggr.get_K() aggr.get_L() aggr.get_Y() aggr.get_C() firms.get_r() firms.get_w() hh.get_cons() utils.print_time() get_ss_graphs() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar > 0, clock time at beginning of program nvec = (S,) vector, exogenous lifetime labor supply n_s beta = scalar in (0,1), discount factor for each model per sigma = scalar > 0, coefficient of relative risk aversion A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital SS_tol = scalar > 0, tolerance level for steady-state fsolve SS_EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 b_args = length 7 tuple, args passed to opt.root(SS_EulErrs,...) results_b = results object, output from opt.root(SS_EulErrs,...) b_ss = (S-1,) vector, steady-state savings b_{s+1} K_ss = scalar > 0, steady-state aggregate capital stock Kss_cstr = boolean, =True if K_ss < epsilon L = scalar > 0, exogenous aggregate labor r_params = length 3 tuple, (A, alpha, delta) r_ss = scalar > 0, steady-state interest rate w_params = length 2 tuple, (A, alpha) w_ss = scalar > 0, steady-state wage c_args = length 3 tuple, (nvec, r_ss, w_ss) c_ss = (S,) vector, steady-state individual consumption c_s Y_params = length 2 tuple, (A, alpha) Y_ss = scalar > 0, steady-state aggregate output (GDP) C_ss = scalar > 0, steady-state aggregate consumption b_err_ss = (S-1,) vector, Euler errors associated with b_ss RCerr_ss = scalar, steady-state resource constraint error ss_time = scalar > 0, time elapsed during SS computation (in seconds) ss_output = length 10 dict, steady-state objects {b_ss, c_ss, w_ss, r_ss, K_ss, Y_ss, C_ss, b_err_ss, RCerr_ss, ss_time} FILES CREATED BY THIS FUNCTION: None RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() nvec, beta, sigma, A, alpha, delta, SS_tol, SS_EulDiff = args b_args = (nvec, beta, sigma, A, alpha, delta, SS_EulDiff) results_b = opt.root(SS_EulErrs, bss_guess, args=(b_args)) b_ss = results_b.x K_ss, Kss_cstr = aggr.get_K(b_ss) L = aggr.get_L(nvec) r_params = (A, alpha, delta) r_ss = firms.get_r(K_ss, L, r_params) w_params = (A, alpha) w_ss = firms.get_w(K_ss, L, w_params) c_args = (nvec, r_ss, w_ss) c_ss = hh.get_cons(b_ss, 0.0, c_args) Y_params = (A, alpha) Y_ss = aggr.get_Y(K_ss, L, Y_params) C_ss = aggr.get_C(c_ss) b_err_ss = results_b.fun RCerr_ss = Y_ss - C_ss - delta * K_ss ss_time = time.clock() - start_time ss_output = { 'b_ss': b_ss, 'c_ss': c_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'K_ss': K_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('b_ss is: ', b_ss) print('K_ss=', K_ss, ', r_ss=', r_ss, ', w_ss=', w_ss) print('Max. abs. savings Euler error is: ', np.absolute(b_err_ss).max()) print('Max. abs. resource constraint error is: ', np.absolute(RCerr_ss).max()) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: get_ss_graphs(c_ss, b_ss) return ss_output
def get_TPI(params, bmat1, graphs): ''' -------------------------------------------------------------------- Solves for transition path equilibrium using time path iteration (TPI) -------------------------------------------------------------------- INPUTS: params = length 23 tuple, (J, S, T1, T2, lambdas, emat, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, K_ss, L_ss, C_ss, maxiter, mindist, TPI_tol, xi, diff) bmat1 = (S, J) matrix, initial period savings distribution graphs = Boolean, =True if want graphs of TPI objects OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: aggr.get_K() get_path() firms.get_r() firms.get_w() get_cnbpath() aggr.get_L() aggr.get_Y() aggr.get_C() utils.print_time() 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, e_{j,s} ability by age and income group 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 A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], per-period capital depreciation rt K_ss = scalar > 0, steady-state aggregate capital stock L_ss = scalar > 0, steady-state aggregate labor supply C_ss = scalar > 0, steady-state aggregate consumption maxiter = integer >= 1, Maximum number of iterations for TPI mindist = scalar > 0, convergence criterion for TPI TPI_tol = scalar > 0, tolerance level for TPI root finders xi = scalar in (0,1], TPI path updating parameter diff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 K1 = scalar > 0, initial aggregate capital stock K1_cstr = Boolean, =True if K1 <= 0 Kpath_init = (T2+S-1,) vector, initial guess for the time path of the aggregate capital stock Lpath_init = (T2+S-1,) vector, initial guess for the time path of aggregate labor iter_TPI = integer >= 0, current iteration of TPI dist = scalar >= 0, distance measure between initial and new paths r_params = length 3 tuple, (A, alpha, delta) w_params = length 2 tuple, (A, alpha) Y_params = length 2 tuple, (A, alpha) cnb_params = length 14 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 individual consumption c_{j,s,t} npath = (S, J, T2+S-1) array, time path of distribution of individual labor supply n_{j,s,t} bpath = (S, J, T2+S-1) array, time path of distribution of individual savings b_{j,s,t} n_err_path = (S, J, T2+S-1) array, time path of distribution of individual labor supply Euler errors b_err_path = (S, J, T2+S-1) array, time path of distribution of individual savings Euler errors. First column and first row are identically zero bSp1_err_path = (S, J, T2) array, residual last period savings, should be close to zero in equilibrium. Nonzero elements of matrix should only be in first matrix [:, :, 0] and top plane [0, :, :] Kpath_new = (T2+S-1,) vector, new path of the aggregate capital stock implied by household and firm optimization Kpath_cstr = (T2+S-1,) Boolean vector, =True if K_t<epsilon Lpath_new = (T2+S-1,) vector, new path of the aggregate labor rpath_new = (T2+S-1,) vector, updated time path of interest rate wpath_new = (T2+S-1,) vector, updated time path of the wages 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: Y_t - C_t - K_{t+1} + (1-delta)*K_t KL_path_new = (2*T2,) vector, appended K_path_new and L_path_new from observation 1 to T2 KL_path_init = (2*T2,) vector, appended K_path_init and L_path_init from observation 1 to T2 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 14 dictionary, {cpath, npath, bpath, wpath, rpath, Kpath, Lpath, Ypath, Cpath, bSp1_err_path, n_err_path, b_err_path, RCerrPath, tpi_time} FILES CREATED BY THIS FUNCTION: Kpath.png Lpath.png Ypath.png C_aggr_path.png wpath.png rpath.png cpath.png npath.png bpath.png RETURNS: tpi_output -------------------------------------------------------------------- ''' start_time = time.clock() (J, S, T1, T2, lambdas, emat, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, K_ss, L_ss, C_ss, maxiter, mindist, TPI_tol, xi, diff) = params K1, K1_cstr = aggr.get_K(bmat1, lambdas) # Create time paths for K and L Kpath_init = np.zeros(T2 + S - 1) Kpath_init[:T1] = get_path(K1, K_ss, T1, 'quadratic') Kpath_init[T1:] = K_ss Lpath_init = L_ss * np.ones(T2 + S - 1) iter_TPI = int(0) dist = 10.0 r_params = (A, alpha, delta) w_params = (A, alpha) Y_params = (A, alpha) cnb_params = (J, S, T2, lambdas, emat, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, bmat1, TPI_tol, diff) while (iter_TPI < maxiter) and (dist >= mindist): iter_TPI += 1 rpath = firms.get_r(r_params, Kpath_init, Lpath_init) wpath = firms.get_w(w_params, Kpath_init, Lpath_init) cpath, npath, bpath, n_err_path, b_err_path, bSp1_err_path = \ get_cnbpath(cnb_params, rpath, wpath) 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)) Kpath_new[Kpath_cstr] = 0.01 Lpath_new = np.zeros(T2 + S - 1) Lpath_new[:T2] = aggr.get_L(npath[:, :, :T2], emat, lambdas) Lpath_new[T2:] = L_ss rpath_new = firms.get_r(r_params, Kpath_new, Lpath_new) wpath_new = firms.get_w(w_params, Kpath_new, Lpath_new) Ypath = aggr.get_Y(Y_params, Kpath_new, Lpath_new) Cpath = np.zeros(T2 + S - 1) Cpath[:T2] = aggr.get_C(cpath[:, :, :T2], lambdas) Cpath[T2:] = C_ss RCerrPath = (Ypath[:-1] - Cpath[:-1] - Kpath_new[1:] + (1 - delta) * Kpath_new[:-1]) # Check the distance of Kpath_new1 KL_path_new = np.append(Kpath_new[:T2], Lpath_new[:T2]) KL_path_init = np.append(Kpath_init[:T2], Lpath_init[:T2]) dist = ((KL_path_new - KL_path_init) ** 2).sum() # dist = np.absolute(KL_path_new - KL_path_init).max() print( 'TPI iter: ', iter_TPI, ', dist: ', "%10.4e" % (dist), ', max abs all errs: ', "%10.4e" % (np.hstack(np.absolute(b_err_path).max(), np.absolute(n_err_path).max(), np.absolute(bSp1_err_path).max())).max()) # The resource constraint does not bind across the transition # path until the equilibrium is solved Kpath_init = xi * Kpath_new + (1 - xi) * Kpath_init Lpath_init = xi * Lpath_new + (1 - xi) * Lpath_init if (iter_TPI == maxiter) and (dist > mindist): print('TPI reached maxiter and did not converge.') elif (iter_TPI == maxiter) and (dist <= mindist): print('TPI converged in the last iteration. ' + 'Should probably increase maxiter_TPI.') Kpath = Kpath_new Lpath = Lpath_new rpath = rpath_new wpath = wpath_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, 'bSp1_err_path': bSp1_err_path, '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. labor supply Euler error: ', '%10.4e' % np.absolute(n_err_path[:T2 - 1]).max()) print('Max abs. savings Euler error: ', '%10.4e' % np.absolute(b_err_path[:T2 - 1]).max()) print('Max abs. final per savings: ', '%10.4e' % np.absolute(bSp1_err_path[:T2 - 1]).max()) 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: ''' ---------------------------------------------------------------- cur_path = string, path name of current directory output_fldr = string, folder in current path to save files output_dir = string, total path of images folder output_path = string, path of file name of figure to be saved tvec = (T2+S-1,) vector, time period vector tgridT = (T2,) vector, time period vector from 1 to T2 sgrid = (S,) vector, all ages from 1 to S tmat = (S, T2) matrix, time periods for decisions ages (S) and time periods (T2) smat = (S, T2) matrix, ages for all decisions ages (S) and time periods (T2) ---------------------------------------------------------------- ''' # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = "images" output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot time path of aggregate capital stock tvec = np.linspace(1, T2 + S - 1, T2 + S - 1) minorLocator = MultipleLocator(1) fig, ax = plt.subplots() plt.plot(tvec, Kpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate capital stock K') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate capital $K_{t}$') output_path = os.path.join(output_dir, 'Kpath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of aggregate labor fig, ax = plt.subplots() plt.plot(tvec, Lpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate labor L') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate labor $L_{t}$') output_path = os.path.join(output_dir, 'Lpath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of aggregate output (GDP) fig, ax = plt.subplots() plt.plot(tvec, Ypath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate output (GDP) Y') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate output $Y_{t}$') output_path = os.path.join(output_dir, 'Ypath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of aggregate consumption fig, ax = plt.subplots() plt.plot(tvec, Cpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate consumption C') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate consumption $C_{t}$') output_path = os.path.join(output_dir, 'C_aggr_path') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of real wage fig, ax = plt.subplots() plt.plot(tvec, wpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for real wage w') plt.xlabel(r'Period $t$') plt.ylabel(r'Real wage $w_{t}$') output_path = os.path.join(output_dir, 'wpath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of real interest rate fig, ax = plt.subplots() plt.plot(tvec, rpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for real interest rate r') plt.xlabel(r'Period $t$') plt.ylabel(r'Real interest rate $r_{t}$') output_path = os.path.join(output_dir, 'rpath') plt.savefig(output_path) # plt.show() plt.close() # Come up with nice visualization for time paths of individual # decisions return tpi_output
def get_TPI(b1vec, ss_params, params): # r_guess: guess of interest rate path from period 1 to T1 beta, sigma, S, ltilde, b, upsilon, chi_n_vec, A, alpha, delta, tpi_max_iter, tpi_tol, xi_tpi, T1, T2 = params r_ss, w_ss, c_ss, n_ss, b_ss, K_ss, L_ss = ss_params abs_tpi = 1 tpi_iter = 0 rpath_old = np.zeros(T2 + S - 1) rpath_old[:T1] = get_path(r_ss, r_ss, T1, 'quadratic') rpath_old[T1:] = r_ss while abs_tpi > tpi_tol and tpi_iter < tpi_max_iter: c1_guess = 1.0 tpi_iter += 1 wpath_old = firms.get_w(rpath_old, (A, alpha, delta)) bmat = np.zeros((S, T2 + S - 1)) bmat[:, 0] = b1vec bmat[:, T2:] = np.matlib.repmat(b_ss, S - 1, 1).T nmat = np.zeros((S, T2 + S - 1)) nmat[:, T2:] = np.matlib.repmat(n_ss, S - 1, 1).T cmat = np.zeros((S, T2 + S - 1)) cmat[:, T2:] = np.matlib.repmat(c_ss, S - 1, 1).T # Solve the incomplete remaining lifetime decisions of agents alive # in period t=1 but not born in period t=1 for p in range(S): # p is remaining periods of life c1_args = (rpath_old[:p + 1], wpath_old[:p + 1], beta, sigma, ltilde, b, upsilon, chi_n_vec[S - p - 1:], p + 1, b1vec[S - p - 1]) result_c1 = opt.root(hh.get_b_last, c1_guess, args = (c1_args)) if result_c1.success: c1 = result_c1.x else: raise ValueError("failed to find an appropriate initial consumption") # Calculate aggregate supplies for capital and labor cvec = hh.get_c(c1, rpath_old[:p + 1], beta, sigma, p + 1) nvec = hh.get_n(cvec, sigma, ltilde, b, upsilon, chi_n_vec[S - p - 1: ], wpath_old[:p + 1], p + 1) bvec = hh.get_b(cvec, nvec, rpath_old[:p + 1], wpath_old[:p + 1], p + 1, bs = b1vec[S - p - 1])[1:] # Insert the vector lifetime solutions diagonally (twist donut) DiagMaskbp = np.eye(p) bp_path = DiagMaskbp * bvec bmat[S - p:, 1:p + 1] += bp_path DiagMasknp = np.eye(p + 1) np_path = DiagMasknp * nvec nmat[S - p - 1:, :p + 1] += np_path DiagMaskcp = np.eye(p + 1) cp_path = DiagMaskcp * cvec cmat[S - p - 1:, :p + 1] += cp_path # Solve for complete lifetime decisions of agents born in periods # 1 to T2 and insert the vector lifetime solutions diagonally (twist # donut) into the cpath, bpath, and EulErrPath matrices for t in range(1, T2): c1_args = (rpath_old[t: S + t], wpath_old[t: S + t], beta, sigma, ltilde, b, upsilon, chi_n_vec, S, 0.0) result_c1 = opt.root(hh.get_b_last, c1_guess, args = (c1_args)) if result_c1.success: c1 = result_c1.x else: raise ValueError("failed to find an appropriate initial consumption") # Calculate aggregate supplies for capital and labor cvec = hh.get_c(c1, rpath_old[t : S + t], beta, sigma, S) nvec = hh.get_n(cvec, sigma, ltilde, b, upsilon, chi_n_vec, wpath_old[t: S + t], S) bvec = hh.get_b(cvec, nvec, rpath_old[t: S + t], wpath_old[t: S + t], S) DiagMaskbt = np.eye(S) bt_path = DiagMaskbt * bvec bmat[:, t: t + S] += bt_path DiagMasknt = np.eye(S) nt_path = DiagMasknt * nvec nmat[:, t: t + S] += nt_path DiagMaskct = np.eye(S) ct_path = DiagMaskct * cvec cmat[:, t: t + S] += ct_path bmat[:, T2:] = np.matlib.repmat(b_ss, S - 1, 1).T nmat[:, T2:] = np.matlib.repmat(n_ss, S - 1, 1).T cmat[:, T2:] = np.matlib.repmat(c_ss, S - 1, 1).T K = aggr.get_K(bmat)[0] L = aggr.get_L(nmat)[0] Y = aggr.get_Y(K, L, (A, alpha)) C = aggr.get_C(cmat) rpath_new = firms.get_r(K, L, (A, alpha, delta)) # Calculate the implied capital stock from conjecture and the error abs_tpi = ((rpath_old[:T2] - rpath_new[:T2]) ** 2).sum() # Update guess rpath_old[:T2] = xi_tpi * rpath_new[:T2] + (1 - xi_tpi) * rpath_old[:T2] b_err = np.zeros(T2 + S - 1) n_err = np.zeros(T2 + S - 1) b_last = bmat[S-1, :] for i in range(T2 + S - 1): b_err[i] = abs(hh.get_b_errors(cmat[:, i], rpath_old[i], beta, sigma)).max() n_err[i] = abs(hh.get_n_errors(nmat[:, i], cmat[:, i], sigma, ltilde, b, upsilon, chi_n_vec, wpath_old[i])).max() Rc_err = Y[:-1] - C[:-1] - K[1:] + (1 - delta) * K[:-1] print('iteration:', tpi_iter, ' squared distance: ', abs_tpi) k_first = [k for k in K if abs(k - K_ss) < 0.00001][0] T1 = np.where(K == k_first)[0][0] return cmat, nmat, bmat, rpath_old, wpath_old, K, L, Y, C, b_err, n_err, b_last, Rc_err, T1
def get_SS(rh_ss_guess, rf_ss_guess, q_ss_guess, args, graphs=False): ''' -------------------------------------------------------------------- Solve for the steady-state solution of the S-period-lived agent OG model with exogenous labor supply using one root finder in bvec -------------------------------------------------------------------- INPUTS: rh_ss_guess = scalar > 0, initial guess for rh_ss rf_ss_guess = scalar > 0, initial guess for rf_ss q_ss_guess = scalar > 0, initial guess for q_ss args = length 19 tuple, arguments passed in to get_SS() graphs = boolean, =True if output steady-state graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: outer_loop() firms.get_comp_r() firms.get_KLratio() firms.get_w_KL() hh.get_cbvec() aggr.get_L() aggr.get_Y() firms.get_K_ownown() aggr.get_C() aggr.get_I() aggr.get_NX() utils.print_time() get_ss_graphs() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar > 0, clock time at beginning of program S = integer in [3,80], number of periods an individual lives nhvec = (S,) vector, exogenous Home labor supply n_{h,s,t} nfvec = (S,) vector, exogenous Foreign labor supply n_{h,s,t} beta = scalar in (0,1), discount factor for each model period sigma = scalar > 0, coefficient of relative risk aversion alpha_h = scalar in (0, 1), share parameter in CES production function of Home intermediate goods producer phi_h = scalar >= 1, elasticity of substitution in CES production function of Home intermediate goods producer Z_h = scalar > 0, total factor productivity parameter in Home final goods producer production function gamma_h = scalar in (0, 1), capital share of income in Home Cobb-Douglas production function delta_h = scalar in [0,1], model-period depreciation rate of Home final goods capital alpha_f = scalar in (0, 1), share parameter in CES production function of Foreign intermediate goods producer phi_f = scalar >= 1, elasticity of substitution in CES production function of Foreign intermediate goods producer Z_f = scalar > 0, total factor productivity parameter in Foreign final goods producer production function gamma_f = scalar in (0, 1), capital share of income in Foreign Cobb-Douglas production function delta_f = scalar in [0,1], model-period depreciation rate of Foreign final goods capital tol_outer = scalar > 0, tolerance level for steady-state outer- loop convergence tol_inner = scalar > 0, tolerance level for inner-loop root finder xi = scalar in (0, 1], outer loop updating parameter maxiter = integer >= 1, maximum number of iterations for outer loop fixed point algorithm EulDiff = boolean, =True if use simple differences in Euler errors. Otherwise, use percent deviation form results_ol = length 5 tuple, results from outer_loop() function rh_ss = scalar > 0, steady-state return on Home savings rf_ss = scalar > 0, steady-state return on Foreign savings q_ss = scalar > 0, real exchange rate # Foreign consumption goods per 1 Domestic consumption good ol_dist = scalar > 0, outer loop distance measure ol_success = boolean, =True if outer loop converged r_ss = scalar > -delta_h, steady-state Home composite interest rate rstar_ss = scalar > -delta_f, steady-state Foreign composite interest rate KL_rat_h = scalar > 0, Home final goods capital labor ratio KL_rat_f = scalar > 0, Foreign final goods capital labor ratio wh_ss = scalar > 0, steady-state Home wage wf_ss = scalar > 0, steady-state Foreign wage r_h_path = (S,) vector, steady-state Home composite interest rate over the periods of an agent's life w_h_path = (S,) vector, steady-state Home wage over the periods of an agent's life cbh_args = length 6 tuple, arguments to pass into hh.get_cbvec() ch_ss = (S,) vector, steady-state Home household consumption for each age (c_1, c_2, ...c_S) bh_ss = (S-1,) vector, steady-state Home household savings for each age (b_2, b_3, ...b_S) bhss_errors = (S-1,) vector, steady-state Home household Euler equation errors for savings decision success_h = boolean, =True if root finder for inner loop Home household savings decision converged r_f_path = (S,) vector, steady-state Foreign composite interest rate over the periods of an agent's life w_f_path = (S,) vector, steady-state Foreign wage over the periods of an agent's life cbf_args = length 6 tuple, arguments to pass into hh.get_cbvec() cf_ss = (S,) vector, steady-state Foreign household consumption for each age (c_1, c_2, ...c_S) bf_ss = (S-1,) vector, steady-state Foreign household savings for each age (b_2, b_3, ...b_S) bfss_errors = (S-1,) vector, steady-state Foreign household Euler equation errors for savings decision success_f = boolean, =True if root finder for inner loop Foreign household savings decision converged L_h_ss = scalar > 0, steady-state Home aggregate labor L_f_ss = scalar > 0, steady-state Foreign aggregate labor K_h_ss = scalar > 0, steady-state Home final goods capital stock K_f_ss = scalar > 0, steady-state Foreign final goods capital stock Yh_ss = scalar > 0, steady-state Home aggregate final goods output (GDP) Yf_ss = scalar > 0, steady-state Foreign aggregate final goods output (GDP) K_hh_ss = scalar > 0, steady-state total Home country savings allocated to Home country intermed't goods production K_ff_ss = scalar > 0, steady-state total Foreign country savings allocated to Foreign country int'd't goods production K_fh_ss = scalar > 0, steady-state total Home country savings allocated to Foreign country int'd't goods production K_hf_ss = scalar > 0, steady-state total Foreign country savings allocated to Home country intermed't goods production Ch_ss = scalar > 0, steady-state Home aggregate consumption Cf_ss = scalar > 0, steady-state Foreign aggregate consumption Ih_ss = scalar, steady-state Home aggregate investment If_ss = scalar, steady-state Foreign aggregate investment NXh_ss = scalar, steady-state Home net exports NXf_ss = scalar, steady-state Foreign net exports RC_h_err_ss = scalar, steady-state Home goods market clearing (resource constraint) error RC_f_err_ss = scalar, steady-state Foreign goods market clearing (resource constraint) error ss_time = scalar > 0, time elapsed during SS computation (in seconds) ss_output = length 30 dict, steady-state equilibrium objects {bh_ss, ch_ss, bhss_errors, bf_ss, cf_ss, bfss_errors, wh_ss, rh_ss, r_ss, q_ss, wf_ss, rf_ss, rstar_ss, L_h_ss, K_h_ss, K_hh_ss, K_fh_ss, Yh_ss, Ih_ss, NXh_ss, L_f_ss, K_f_ss, K_ff_ss, K_hf_ss, Yf_ss, If_ss, NXf_ss, RC_h_err_ss, RC_f_err_ss, ss_time} FILES CREATED BY THIS FUNCTION: None RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() (nhvec, nfvec, beta, sigma, alpha_h, phi_h, Z_h, gamma_h, delta_h, alpha_f, phi_f, Z_f, gamma_f, delta_f, tol_outer, tol_inner, xi, maxiter, EulDiff) = args S = nhvec.shape[0] results_ol = outer_loop(rh_ss_guess, rf_ss_guess, q_ss_guess, args) rh_ss, rf_ss, q_ss, ol_dist, ol_success = results_ol # Solve for composite r and rstar r_ss = firms.get_comp_r(rh_ss, rf_ss, q_ss, alpha_h, phi_h, home=True) rstar_ss = firms.get_comp_r(rf_ss, rh_ss, q_ss, alpha_f, phi_f, home=False) # Solve for capital-labor ratios and wages in both countries KL_rat_h = firms.get_KLratio(r_ss, gamma_h, Z_h, delta_h) KL_rat_f = firms.get_KLratio(rstar_ss, gamma_f, Z_f, delta_f) wh_ss = firms.get_w_KL(KL_rat_h, gamma_h, Z_h) wf_ss = firms.get_w_KL(KL_rat_f, gamma_f, Z_f) # Solve for household decisions in Home country r_h_path = rh_ss * np.ones(S) w_h_path = wh_ss * np.ones(S) bhvec_init = 0.02 * np.ones(S - 1) cbh_args = (0.0, nhvec, beta, sigma, EulDiff, tol_inner) bh_ss, ch_ss, bhss_errors, success_h = \ hh.get_cbvec(bhvec_init, r_h_path, w_h_path, cbh_args) # Solve for household decisions in Foreign country r_f_path = rf_ss * np.ones(S) w_f_path = wf_ss * np.ones(S) bfvec_init = 0.02 * np.ones(S - 1) cbf_args = (0.0, nfvec, beta, sigma, EulDiff, tol_inner) bf_ss, cf_ss, bfss_errors, success_f = \ hh.get_cbvec(bfvec_init, r_f_path, w_f_path, cbf_args) # Solve for Home and Foreign aggregate labor supply L_h_ss = aggr.get_L(nhvec) L_f_ss = aggr.get_L(nfvec) # Solve for Home and Foreign aggregate final goods capital stock K_h_ss = KL_rat_h * L_h_ss K_f_ss = KL_rat_f * L_f_ss # Solve for Home and Foreign aggregate final goods output (GDP) Yh_ss = aggr.get_Y(K_h_ss, L_h_ss, gamma_h, Z_h) Yf_ss = aggr.get_Y(K_f_ss, L_f_ss, gamma_f, Z_f) # Solve for Home and Foreign savings invested in own-country # intermediate goods production K_hh_ss = firms.get_K_ownown(K_h_ss, r_ss, rh_ss, alpha_h, phi_h) K_ff_ss = firms.get_K_ownown(K_f_ss, rstar_ss, rf_ss, alpha_f, phi_f) # Solve for Home and Foreign savings invested in other-country # intermediate goods production K_fh_ss = bh_ss.sum() - K_hh_ss K_hf_ss = bf_ss.sum() - K_ff_ss # Solve for Home and Foreign aggregate consumption Ch_ss = aggr.get_C(ch_ss) Cf_ss = aggr.get_C(cf_ss) # Solve for Home and Foreign aggregate investment Ih_ss = aggr.get_I(K_h_ss, K_h_ss, delta_h) If_ss = aggr.get_I(K_f_ss, K_f_ss, delta_f) # Solve for Home and Foreign net exports NXh_ss = aggr.get_NX(K_hh_ss, K_fh_ss, K_hh_ss, K_fh_ss, K_h_ss, K_h_ss, r_ss, rh_ss) NXf_ss = aggr.get_NX(K_ff_ss, K_hf_ss, K_ff_ss, K_hf_ss, K_f_ss, K_f_ss, rstar_ss, rf_ss) # NXh_ss = r_ss * K_h_ss - rh_ss * (K_hh_ss + K_fh_ss) # NXf_ss = rstar_ss * K_f_ss - rf_ss * (K_ff_ss + K_hf_ss) # Solve for Home and Foreign goods market clearing (resource # constraint) errors RC_h_err_ss = Yh_ss - Ch_ss - Ih_ss - NXh_ss RC_f_err_ss = Yf_ss - Cf_ss - If_ss - NXf_ss ss_time = time.clock() - start_time ss_output = \ {'bh_ss': bh_ss, 'ch_ss': ch_ss, 'bhss_errors': bhss_errors, 'bf_ss': bf_ss, 'cf_ss': cf_ss, 'bfss_errors': bfss_errors, 'wh_ss': wh_ss, 'rh_ss': rh_ss, 'r_ss': r_ss, 'q_ss': q_ss, 'wf_ss': wf_ss, 'rf_ss': rf_ss, 'rstar_ss': rstar_ss, 'L_h_ss': L_h_ss, 'K_h_ss': K_h_ss, 'K_hh_ss': K_hh_ss, 'K_fh_ss': K_fh_ss, 'Yh_ss': Yh_ss, 'Ih_ss': Ih_ss, 'NXh_ss': NXh_ss, 'L_f_ss': L_f_ss, 'K_f_ss': K_f_ss, 'K_ff_ss': K_ff_ss, 'K_hf_ss': K_hf_ss, 'Yf_ss': Yf_ss, 'If_ss': If_ss, 'NXf_ss': NXf_ss, 'RC_h_err_ss': RC_h_err_ss, 'RC_f_err_ss': RC_f_err_ss, 'ss_time': ss_time} with np.printoptions(precision=4): print('bh_ss is: ', bh_ss) print('bf_ss is: ', bf_ss) print('K_h_ss=', '%10.4f' % K_h_ss, ', rh_ss=', '%10.4f' % rh_ss, ', r_ss=', '%10.4f' % r_ss, ', wh_ss=', '%10.4f' % wh_ss) print('K_f_ss=', '%10.4f' % K_f_ss, ', rf_ss=', '%10.4f' % rf_ss, ', r*_ss=', '%10.4f' % rstar_ss, ', wf_ss=', '%10.4f' % wf_ss) print('Real exchange rate=', '%10.4f' % q_ss) print('Max. abs. savings Euler error is: ', '%10.4e' % np.absolute(np.append(bhss_errors, bfss_errors)).max()) print('Max. abs. resource constraint error is: ', '%10.4e' % np.absolute(np.append(RC_h_err_ss, RC_f_err_ss)).max()) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: get_ss_graphs(ch_ss, bh_ss, home=True) get_ss_graphs(cf_ss, bf_ss, home=False) return ss_output
def get_SS(args, graph=False): (KL_init, beta, sigma, emat, chi_n_vec, l_tilde, b, upsilon, lambdas, S, J, alpha, A, delta) = args dist = 10 mindist = 1e-08 maxiter = 500 ss_iter = 0 xi = 0.2 r_params = (alpha, A, delta) w_params = (alpha, A) while dist > mindist and ss_iter < maxiter: ss_iter += 1 K, L = KL_init r = firms.get_r(K, L, r_params) w = firms.get_w(K, L, w_params) cmat = np.zeros((S, J)) nmat = np.zeros((S, J)) bmat = np.zeros((S, J)) c1 = 1.0 for j in range(J): c1_guess = c1 c1_args = (r, w, beta, sigma, chi_n_vec, l_tilde, b, upsilon, emat[:, j], S) results_c1 = opt.root(hh.get_bSp1, c1_guess, args=(c1_args)) c1 = results_c1.x cmat[:, j] = hh.get_recurs_c(c1, r, beta, sigma, S) nmat[:, j] = hh.get_n_s(cmat[:, j], w, sigma, chi_n_vec, l_tilde, b, upsilon, emat[:, j]) bmat[:, j] = hh.get_recurs_b(cmat[:, j], nmat[:, j], r, w, emat[:, j]) K_new = aggr.get_K(bmat[:-1, :], lambdas, S) L_new = aggr.get_L(nmat, emat, lambdas, S) KL_new = np.array([K_new, L_new]) dist = ((KL_new - KL_init)**2).sum() KL_init = xi * KL_new + (1 - xi) * KL_init print('iter:', ss_iter, ' dist: ', dist) c_ss = cmat n_ss = nmat b_ss = bmat K_ss = K_new L_ss = L_new r_ss = r w_ss = w Y_params = (alpha, A) Y_ss = aggr.get_Y(K_ss, L_ss, Y_params) C_ss = aggr.get_C(c_ss, lambdas, S) ss_output = { 'c_ss': c_ss, 'n_ss': n_ss, 'b_ss': b_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'r_ss': r_ss, 'w_ss': w_ss, 'Y_ss': Y_ss, 'C_ss': C_ss } if graph: ''' ---------------------------------------------------------------- cur_path = string, path name of current directory output_fldr = string, folder in current path to save files output_dir = string, total path of images folder output_path = string, path of file name of figure to be saved sgrid = (S,) vector, ages from 1 to S lamcumsum = (J,) vector, cumulative sum of lambdas vector jmidgrid = (J,) vector, midpoints of ability percentile bins smat = (J, S) matrix, sgrid copied down J rows jmat = (J, S) matrix, jmidgrid copied across S columns ---------------------------------------------------------------- ''' # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = 'images' output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot 3D steady-state consumption distribution sgrid = np.arange(1, S + 1) lamcumsum = lambdas.cumsum() jmidgrid = 0.5 * lamcumsum + 0.5 * (lamcumsum - lambdas) smat, jmat = np.meshgrid(sgrid, jmidgrid) cmap_c = cm.get_cmap('summer') fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'ability-$j$') ax.set_zlabel(r'indiv. consumption $c_{j,s}$') ax.plot_surface(smat, jmat, c_ss.T, rstride=1, cstride=6, cmap=cmap_c) output_path = os.path.join(output_dir, 'c_ss_3D') plt.savefig(output_path) # plt.show() plt.close() # Plot 2D steady-state consumption distribution minorLocator = MultipleLocator(1) fig, ax = plt.subplots() linestyles = np.array(["-", "--", "-.", ":"]) markers = np.array(["x", "v", "o", "d", ">", "|"]) pct_lb = 0 for j in range(J): this_label = (str(int(np.rint(pct_lb))) + " - " + str(int(np.rint(pct_lb + 100 * lambdas[j]))) + "%") pct_lb += 100 * lambdas[j] if j <= 3: ax.plot(sgrid, c_ss[:, j], label=this_label, linestyle=linestyles[j], color='black') elif j > 3: ax.plot(sgrid, c_ss[:, j], label=this_label, marker=markers[j - 4], color='black') ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'indiv. consumption $c_{j,s}$') output_path = os.path.join(output_dir, 'c_ss_2D') plt.savefig(output_path) # plt.show() plt.close() # Plot 3D steady-state labor supply distribution fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'ability-$j$') ax.set_zlabel(r'labor supply $n_{j,s}$') ax.plot_surface(smat, jmat, n_ss.T, rstride=1, cstride=6, cmap=cmap_c) output_path = os.path.join(output_dir, 'n_ss_3D') plt.savefig(output_path) # plt.show() plt.close() # Plot 2D steady-state labor supply distribution minorLocator = MultipleLocator(1) fig, ax = plt.subplots() linestyles = np.array(["-", "--", "-.", ":"]) markers = np.array(["x", "v", "o", "d", ">", "|"]) pct_lb = 0 for j in range(J): this_label = (str(int(np.rint(pct_lb))) + " - " + str(int(np.rint(pct_lb + 100 * lambdas[j]))) + "%") pct_lb += 100 * lambdas[j] if j <= 3: ax.plot(sgrid, n_ss[:, j], label=this_label, linestyle=linestyles[j], color='black') elif j > 3: ax.plot(sgrid, n_ss[:, j], label=this_label, marker=markers[j - 4], color='black') ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'labor supply $n_{j,s}$') output_path = os.path.join(output_dir, 'n_ss_2D') plt.savefig(output_path) # plt.show() plt.close() # Plot 3D steady-state savings/wealth distribution fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'ability-$j$') ax.set_zlabel(r'indiv. savings $b_{j,s}$') ax.plot_surface(smat, jmat, b_ss.T, rstride=1, cstride=6, cmap=cmap_c) output_path = os.path.join(output_dir, 'b_ss_3D') plt.savefig(output_path) # plt.show() plt.close() # Plot 2D steady-state savings/wealth distribution fig, ax = plt.subplots() linestyles = np.array(["-", "--", "-.", ":"]) markers = np.array(["x", "v", "o", "d", ">", "|"]) pct_lb = 0 for j in range(J): this_label = (str(int(np.rint(pct_lb))) + " - " + str(int(np.rint(pct_lb + 100 * lambdas[j]))) + "%") pct_lb += 100 * lambdas[j] if j <= 3: ax.plot(sgrid, b_ss[:, j], label=this_label, linestyle=linestyles[j], color='black') elif j > 3: ax.plot(sgrid, b_ss[:, j], label=this_label, marker=markers[j - 4], color='black') ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ax.set_xlabel(r'age-$s$') ax.set_ylabel(r'indiv. savings $b_{j,s}$') output_path = os.path.join(output_dir, 'b_ss_2D') plt.savefig(output_path) # plt.show() plt.close() return ss_output
def get_SS(init_vals, args, calibrate_n=False, 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 2 or 3 tuple, (rss_init, c1_init) if calibrate_n=False; (rss_init, c1_init, factor_init) if calibrate_n=True args = length 15 or 16 tuple, (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, Bsct_Tol, Eul_Tol, EulDiff, xi, maxiter) if calibrate_n = False; (S, beta, sigma, l_tilde, b_ellip, upsilon, A, alpha, delta, Bsct_Tol, Factor_tol, Eul_Tol, EulDiff, xi_ss, xi_factor, maxiter) if calibrate_n = True calibrate_n= boolean, =True if calibrate disutility of labor 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() consumption() hrs_by_age() 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 = scalar > 0, initial guess for first period consumpt'n factor_init= scalar > 0, initial guess for factor S = integer in [3, 80], number of periods an individual lives 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 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 cvec_data = (S,) vector, consumption by age from 2016 data w_data = scalar, average yearly wage from 2016 data y_bar_data = scalar, average household income before tax from 2016 data n_data = (S,) vector, (unit-free) labor supply by age from 2016 data chi_n_hat = (S,) vector, data version of chi_n_vec chi_n_vec = (S,) vector, values for chi^n_s A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital Bsct_Tol = scalar > 0, tolderance level for outer-loop bisection method Eul_Tol = scalar > 0, tolerance level for inner-loop root finder EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 xi_SS = scalar in (0, 1], SS updating parameter in outer-loop bisection method xi_factor = scalar in (0, 1], factor updating parameter in outer-loop maxiter = integer >= 1, maximum number of iterations in outer loop bisection method iter_SS = integer >= 0, index of iteration number SS_dist = scalar > 0, distance metric for r in current iteration factor_dist= scalar > 0, distance metric for factor in current iteration c1_options = length 1 dict, options to pass into opt.root(c1_bSp1err,...) rw_params = length 3 tuple, (A, alpha, delta) args to pass into firms.get_r() and firms.get_w() w_init = scalar, initial value for wage inner_args = length 14 tuple, args to pass into inner_loop() K_new = scalar > 0, updated K given r_init, w_init, and bvec L_new = scalar > 0, updated L given r_init, w_init, and nvec cvec = (S,) vector, updated values for lifetime consumption nvec = (S,) vector, updated values for lifetime labor supply bvec = (S,) vector, updated values for lifetime savings (b1, b2,...bS) b_Sp1 = scalar, updated value for savings in last period, should be arbitrarily close to zero r_new = scalar > 0, updated interest rate given bvec and nvec w_new = scalar > 0, updated wage given bvec and nvec y_dar_model= scalar > 0, average household income from model, given r_init and factor_init factor_new = scalar > 0, updated wage given y_bar_data and y_bar_model n_errors = (S,) vector, labor supply Euler errors given r_init and w_init b_errors = (S-1,) vector, savings Euler errors given r_init and w_init all_errors = (2S,) vector, (n_errors, b_errors, b_Sp1) c_ss = (S,) vector, steady-state lifetime consumption n_ss = (S,) vector, steady-state lifetime labor supply b_ss = (S,) vector, steady-state wealth enter period with (b1, b2, ...bS) b_Sp1_ss = scalar, steady-state savings for period after last period of life. b_Sp1_ss approx. 0 in equilibrium n_err_ss = (S,) vector, lifetime labor supply Euler errors b_err_ss = (S-1) vector, 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, (A, alpha) 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 14 dict, steady-state objects {n_ss, b_ss, c_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} FILES CREATED BY THIS FUNCTION: SS_bc.png SS_n.png RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() iter_SS = 0 SS_dist = 10 c1_options = {'maxiter': 500} if calibrate_n: cur_path = os.path.split(os.path.abspath(__file__))[0] dir = os.path.join(cur_path, 'data') (S, beta, sigma, l_tilde, b_ellip, upsilon, A, alpha, delta, Bsct_Tol, Factor_tol, Eul_Tol, EulDiff, xi_ss, xi_factor, maxiter) = args cvec_data = consump.get_consump(S, 15, 15 + S - 1) # average yearly wage and income from data w_data = 46662.59 y_bar_data = 74664 n_data = hrs.hrs_by_age('dec16', 'dec16', dir, 65, l_tilde=45) n_data = np.concatenate((n_data, np.ones(S - 65) * n_data[-1])) r_init, c1_init, factor_init = init_vals rw_params = (A, alpha, delta) chi_n_hat = (w_data * cvec_data) ** (-sigma)/ \ ((b_ellip / l_tilde) * n_data ** (upsilon - 1) * \ (1 - (n_data) ** upsilon) ** ((1 - upsilon) / upsilon)) while (iter_SS < maxiter) and (SS_dist >= Bsct_Tol or factor_dist >= Factor_tol): iter_SS += 1 chi_n_vec = factor_init**(sigma - 1) * chi_n_hat w_init = firms.get_w(r_init, rw_params) inner_args = (c1_init, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, EulDiff, Eul_Tol, c1_options) (K_new, L_new, cvec, nvec, bvec, b_Sp1, r_new, w_new, n_errors, b_errors) = inner_loop(r_init, w_init, inner_args) # Calculate average household income from model y_bar_model = (r_init * bvec + w_init * nvec).mean() factor_new = y_bar_data / y_bar_model all_errors = np.hstack((n_errors, b_errors, b_Sp1)) SS_dist = (np.absolute(r_new - r_init)).sum() factor_dist = np.absolute(factor_new - factor_init) r_init = xi_ss * r_new + (1 - xi_ss) * r_init factor_init = xi_factor * factor_new + (1 - xi_factor) * factor_init print('SS Iter=', iter_SS, ', SS Dist=', '%10.4e' % (SS_dist), ', Factor Dist=', '%10.4e' % (factor_dist), ', Max Abs Err=', '%10.4e' % (np.absolute(all_errors).max())) else: r_init, c1_init = init_vals (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, Bsct_Tol, Eul_Tol, EulDiff, xi, maxiter) = args rw_params = (A, alpha, delta) while (iter_SS < maxiter) and (SS_dist >= Bsct_Tol): iter_SS += 1 w_init = firms.get_w(r_init, rw_params) inner_args = (c1_init, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, EulDiff, Eul_Tol, c1_options) (K_new, L_new, cvec, nvec, bvec, b_Sp1, r_new, w_new, n_errors, b_errors) = inner_loop(r_init, w_init, inner_args) all_errors = np.hstack((n_errors, b_errors, b_Sp1)) SS_dist = (np.absolute(r_new - r_init)).sum() r_init = xi * r_new + (1 - xi) * r_init print('SS Iter=', iter_SS, ', SS Dist=', '%10.4e' % (SS_dist), ', Max Abs Err=', '%10.4e' % (np.absolute(all_errors).max())) c_ss = cvec.copy() n_ss = nvec.copy() b_ss = bvec.copy() b_Sp1_ss = b_Sp1.copy() n_err_ss = n_errors.copy() b_err_ss = b_errors.copy() r_ss = r_new.copy() w_ss = w_new.copy() K_ss = K_new.copy() L_ss = L_new.copy() Y_params = (A, alpha) Y_ss = aggr.get_Y(K_ss, L_ss, Y_params) C_ss = aggr.get_C(c_ss) RCerr_ss = Y_ss - C_ss - delta * K_ss ss_time = time.clock() - start_time ss_output = { 'c_ss': c_ss, 'n_ss': n_ss, 'b_ss': b_ss, 'b_Sp1_ss': b_Sp1_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('n_ss is: ', n_ss) print('b_ss is: ', b_ss) print('K_ss=', K_ss, ', L_ss=', L_ss) print('r_ss=', r_ss, ', w_ss=', w_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('Steady-state residual savings b_Sp1 is: ', b_Sp1_ss) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: create_graphs(c_ss, b_ss, n_ss) return ss_output
def get_TPI(bvec1, args, graphs): ''' -------------------------------------------------------------------- Solves for transition path equilibrium using time path iteration (TPI) -------------------------------------------------------------------- INPUTS: bvec1 = (S,) vector, initial period savings distribution args = length 22 tuple, (S, T1, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, r_ss, K_ss, L_ss, C_ss, b_ss, n_ss, maxiter, Out_Tol, In_Tol, EulDiff, xi) graphs = Boolean, =True if want graphs of TPI objects OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: aggr.get_K() get_path() firms.get_r() firms.get_w() inner_loop() solve_bn_path() aggr.get_L() aggr.get_Y() aggr.get_C() utils.print_time() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar, current processor time in seconds (float) 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 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 A = scalar > 0, total factor productivity parameter in firms' production function alpha = 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 mindist = scalar > 0, convergence criterion for TPI TPI_tol = scalar > 0, tolerance level for TPI root finders xi = scalar in (0,1], TPI path updating parameter diff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 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, (A, alpha, delta) Y_params = length 2 tuple, (A, alpha) cnb_params = length 11 tuple, args to pass into inner_loop() rpath = (T2+S-1,) vector, time path of the interest rates wpath = (T2+S-1,) vector, time path of the wages ind = (S,) vector, integers from 0 to S bn_args = length 14 tuple, arguments to be passed to solve_bn_path() cpath = (S, T2+S-1) matrix, time path of distribution of individual consumption c_{s,t} npath = (S, T2+S-1) matrix, time path of distribution of individual labor supply n_{s,t} bpath = (S, T2+S-1) matrix, time path of distribution of individual savings b_{s,t} n_err_path = (S, T2+S-1) matrix, time path of distribution of individual labor supply Euler errors b_err_path = (S, T2+S-1) matrix, time path of distribution of individual savings Euler errors. First column and first row are identically zero bSp1_err_path = (S, T2) matrix, residual last period savings, which should be close to zero in equilibrium. Nonzero elements of matrix should only be in first column and first row Kpath_new = (T2+S-1,) vector, new path of the aggregate capital stock implied by household and firm optimization Kpath_cnstr = (T2+S-1,) Boolean vector, =True if K_t<=0 Lpath_new = (T2+S-1,) vector, new path of the aggregate labor rpath_new = (T2+S-1,) vector, updated time path of interest rate wpath_new = (T2+S-1,) vector, updated time path of the wages 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: Y_t - C_t - K_{t+1} + (1-delta)*K_t 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 14 dictionary, {cpath, npath, bpath, wpath, rpath, Kpath, Lpath, Ypath, Cpath, bSp1_err_path, n_err_path, b_err_path, RCerrPath, tpi_time} FILES CREATED BY THIS FUNCTION: Kpath.png Lpath.png Ypath.png C_aggr_path.png wpath.png rpath.png cpath.png npath.png bpath.png RETURNS: tpi_output -------------------------------------------------------------------- ''' start_time = time.clock() (S, T1, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, r_ss, K_ss, L_ss, C_ss, b_ss, n_ss, maxiter, Out_Tol, In_Tol, EulDiff, xi) = args K1, K1_cnstr = aggr.get_K(bvec1) # Create time path for r rpath_init = np.zeros(T2 + S - 1) rpath_init[:T1] = get_path(r_ss, r_ss, T1, 'quadratic') rpath_init[T1:] = r_ss iter_TPI = int(0) dist = 10.0 rw_params = (A, alpha, delta) Y_params = (A, alpha) cnb_args = (S, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, bvec1, n_ss, In_Tol, EulDiff) while (iter_TPI < maxiter) and (dist >= Out_Tol): iter_TPI += 1 rpath = rpath_init wpath = firms.get_w(rpath_init, rw_params) cpath, npath, bpath, n_err_path, b_err_path = \ inner_loop(rpath, wpath, cnb_args) Kpath_new = np.zeros(T2 + S - 1) Kpath_new[:T2], Kpath_cstr = aggr.get_K(bpath[:, :T2]) 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]) 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) wpath = firms.get_w(rpath_new, rw_params) Ypath = aggr.get_Y(Kpath_new, Lpath_new, Y_params) Cpath = np.zeros(T2 + S - 1) Cpath[:T2] = aggr.get_C(cpath[:, :T2]) Cpath[T2:] = C_ss RCerrPath = (Ypath[:-1] - Cpath[:-1] - Kpath_new[1:] + (1 - delta) * Kpath_new[:-1]) # Check the distance of rpath_new dist = (np.absolute(rpath_new[:T2] - rpath_init[:T2])).sum() print( 'TPI iter: ', iter_TPI, ', dist: ', "%10.4e" % (dist), ', max abs all errs: ', "%10.4e" % (np.absolute( np.hstack( (b_err_path.max(axis=0), n_err_path.max(axis=0)))).max())) # 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 = (S, T2) create_graphs(tpi_output, graph_args) return tpi_output
def get_SS(args, graph=False): (KL_init, beta, sigma, chi_n_vec, l_tilde, b, upsilon, S, alpha, A, delta) = args dist = 10 mindist = 1e-08 maxiter = 500 ss_iter = 0 xi = 0.2 r_params = (alpha, A, delta) w_params = (alpha, A) while dist > mindist and ss_iter < maxiter: ss_iter += 1 K, L = KL_init r = firms.get_r(K, L, r_params) w = firms.get_w(K, L, w_params) c1_guess = 1.0 c1_args = (r, w, beta, sigma, chi_n_vec, l_tilde, b, upsilon, S) results_c1 = opt.root(hh.get_bSp1, c1_guess, args=(c1_args)) c1 = results_c1.x cvec = hh.get_recurs_c(c1, r, beta, sigma, S) nvec = hh.get_n_s(cvec, w, sigma, chi_n_vec, l_tilde, b, upsilon) bvec = hh.get_recurs_b(cvec, nvec, r, w) K_new = aggr.get_K(bvec[:-1]) L_new = aggr.get_L(nvec) KL_new = np.array([K_new, L_new]) dist = ((KL_new - KL_init)**2).sum() KL_init = xi * KL_new + (1 - xi) * KL_init print('iter:', ss_iter, ' dist: ', dist) c_ss = cvec n_ss = nvec b_ss = bvec K_ss = K_new L_ss = L_new r_ss = r w_ss = w Y_params = (alpha, A) Y_ss = aggr.get_Y(K_ss, L_ss, Y_params) C_ss = aggr.get_C(c_ss) ss_output = { 'c_ss': c_ss, 'n_ss': n_ss, 'b_ss': b_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'r_ss': r_ss, 'w_ss': w_ss, 'Y_ss': Y_ss, 'C_ss': C_ss } if graph: # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = 'images' output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot c_ss, n_ss, b_ss # Plot steady-state consumption and savings distributions age_pers = np.arange(1, S + 1) fig, ax = plt.subplots() plt.plot(age_pers, c_ss, marker='D', label='Consumption') plt.plot(age_pers, np.append(0, b_ss[:-1]), marker='D', label='Savings') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state consumption and savings', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Units of consumption') plt.xlim((0, S + 1)) # plt.ylim((-1.0, 1.15 * (b_ss.max()))) plt.legend(loc='upper left') output_path = os.path.join(output_dir, 'SS_bc') plt.savefig(output_path) # plt.show() plt.close() # Plot steady-state labor supply distributions fig, ax = plt.subplots() plt.plot(age_pers, n_ss, marker='D', label='Labor supply') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state labor supply', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Labor supply') plt.xlim((0, S + 1)) # plt.ylim((-0.1, 1.15 * (n_ss.max()))) plt.legend(loc='upper right') output_path = os.path.join(output_dir, 'SS_n') plt.savefig(output_path) # plt.show() plt.close() return ss_output
def get_TPI(params, bvec1, graphs): ''' -------------------------------------------------------------------- Solves for transition path equilibrium using time path iteration (TPI) -------------------------------------------------------------------- INPUTS: params = length 21 tuple, (S, T1, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, K_ss, L_ss, C_ss, maxiter, mindist, TPI_tol, xi, diff, hh_fsolve) bvec1 = (S,) vector, initial period savings distribution graphs = Boolean, =True if want graphs of TPI objects OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: aggr.get_K() get_path() firms.get_r() firms.get_w() get_cnbpath() solve_bn_path() aggr.get_L() aggr.get_Y() aggr.get_C() utils.print_time() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar, current processor time in seconds (float) 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 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 A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], per-period capital depreciation rt K_ss = scalar > 0, steady-state aggregate capital stock L_ss = scalar > 0, steady-state aggregate labor supply C_ss = scalar > 0, steady-state aggregate consumption maxiter = integer >= 1, Maximum number of iterations for TPI mindist = scalar > 0, convergence criterion for TPI TPI_tol = scalar > 0, tolerance level for TPI root finders xi = scalar in (0,1], TPI path updating parameter diff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 hh_fsolve = boolean, =True if solve inner-loop household problem by choosing c_1 to set final period savings b_{S+1}=0. Otherwise, solve the household problem as multivariate root finder with 2S-1 unknowns and equations K1 = scalar > 0, initial aggregate capital stock K1_cnstr = Boolean, =True if K1 <= 0 Kpath_init = (T2+S-1,) vector, initial guess for the time path of the aggregate capital stock Lpath_init = (T2+S-1,) vector, initial guess for the time path of aggregate labor domain = (T2,) vector, integers from 0 to T2-1 domain2 = (T2,S) array, integers from 0 to T2-1 repeated S times ending_b = (S,) vector, distribution of savings at end of time path initial_b = (S,) vector, distribution of savings in initial period guesses_b = (T2,S) array, initial guess at distribution of savings over the time path ending_b_tail = (S,S) array, distribution of savings for S periods after end of time path guesses_b = (T2+S,S) array, guess at distribution of savings for T2+S periods domain3 = (T2,S) array, integers from 0 to T2-1 repeated S times initial_n = (S,) vector, distribution of labor supply in initial period guesses_n = (T2,S) array, initial guess at distribution of labor supply over the time path ending_n_tail = (S,S) array, distribution of labor supply for S periods after end of time path guesses_n = (T2+S,S) array, guess at distribution of labor supply for T2+S periods guesses = length 2 tuple, initial guesses at distributions of savings and labor supply over the time path iter_TPI = integer >= 0, current iteration of TPI dist = scalar >= 0, distance measure between initial and new paths r_params = length 3 tuple, (A, alpha, delta) w_params = length 2 tuple, (A, alpha) Y_params = length 2 tuple, (A, alpha) cnb_params = length 11 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 ind = (S,) vector, integers from 0 to S bn_args = length 14 tuple, arguments to be passed to solve_bn_path() cpath = (S, T2+S-1) matrix, time path of distribution of individual consumption c_{s,t} npath = (S, T2+S-1) matrix, time path of distribution of individual labor supply n_{s,t} bpath = (S, T2+S-1) matrix, time path of distribution of individual savings b_{s,t} n_err_path = (S, T2+S-1) matrix, time path of distribution of individual labor supply Euler errors b_err_path = (S, T2+S-1) matrix, time path of distribution of individual savings Euler errors. First column and first row are identically zero bSp1_err_path = (S, T2) matrix, residual last period savings, which should be close to zero in equilibrium. Nonzero elements of matrix should only be in first column and first row Kpath_new = (T2+S-1,) vector, new path of the aggregate capital stock implied by household and firm optimization Kpath_cnstr = (T2+S-1,) Boolean vector, =True if K_t<=0 Lpath_new = (T2+S-1,) vector, new path of the aggregate labor rpath_new = (T2+S-1,) vector, updated time path of interest rate wpath_new = (T2+S-1,) vector, updated time path of the wages 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: Y_t - C_t - K_{t+1} + (1-delta)*K_t KL_path_new = (2*T2,) vector, appended K_path_new and L_path_new from observation 1 to T2 KL_path_init = (2*T2,) vector, appended K_path_init and L_path_init from observation 1 to T2 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 14 dictionary, {cpath, npath, bpath, wpath, rpath, Kpath, Lpath, Ypath, Cpath, bSp1_err_path, n_err_path, b_err_path, RCerrPath, tpi_time} FILES CREATED BY THIS FUNCTION: Kpath.png Lpath.png Ypath.png C_aggr_path.png wpath.png rpath.png cpath.png npath.png bpath.png RETURNS: tpi_output -------------------------------------------------------------------- ''' start_time = time.clock() (S, T1, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, K_ss, L_ss, C_ss, b_splus1_ss, n_ss, maxiter, mindist, TPI_tol, xi, diff, hh_fsolve) = params K1, K1_cnstr = aggr.get_K(bvec1) # Create time paths for K and L Kpath_init = np.zeros(T2 + S - 1) Kpath_init[:T1] = get_path(K1, K_ss, T1, 'quadratic') Kpath_init[T1:] = K_ss Lpath_init = L_ss * np.ones(T2 + S - 1) # Make arrays of initial guesses for labor supply and savings domain = np.linspace(0, T2, T2) domain2 = np.tile(domain.reshape(T2, 1), (1, S)) ending_b = b_splus1_ss initial_b = bvec1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, S), (S, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, T2).reshape( T2, 1, ), (1, S)) initial_n = n_ss guesses_n = domain3 * (n_ss - initial_n) + initial_n ending_n_tail = np.tile(n_ss.reshape(1, S), (S, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) guesses = (guesses_b, guesses_n) iter_TPI = int(0) dist = 10.0 r_params = (A, alpha, delta) w_params = (A, alpha) Y_params = (A, alpha) cnb_params = (S, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, bvec1, TPI_tol, diff) while (iter_TPI < maxiter) and (dist >= mindist): iter_TPI += 1 rpath = firms.get_r(r_params, Kpath_init, Lpath_init) wpath = firms.get_w(w_params, Kpath_init, Lpath_init) if hh_fsolve: ind = np.arange(S) bn_args = (rpath, wpath, ind, S, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, bvec1, TPI_tol, diff) npath, b_splus1_path, n_err_path, b_err_path = solve_bn_path( guesses, bn_args) bSp1_err_path = np.zeros((S, T2 + S - 1)) b_s_path = np.zeros((S, T2 + S - 1)) b_s_path[:, 0] = bvec1 b_s_path[1:, 1:] = b_splus1_path[:-1, :-1] cpath = hh.get_cons(rpath, wpath, b_s_path, b_splus1_path, npath) # update guesses for next iteration guesses = (np.transpose(b_splus1_path), np.transpose(npath)) else: cpath, npath, b_s_path, n_err_path, b_err_path, bSp1_err_path = \ get_cnbpath(cnb_params, rpath, wpath) b_splus1_path = np.append(b_s_path[1:, :T2], np.reshape(bSp1_err_path[-1, :], (1, T2)), axis=0) Kpath_new = np.zeros(T2 + S - 1) Kpath_new[:T2], Kpath_cnstr = aggr.get_K(b_s_path[:, :T2]) Kpath_new[T2:] = K_ss Kpath_cnstr = np.append(Kpath_cnstr, np.zeros(S - 1, dtype=bool)) Kpath_new[Kpath_cnstr] = 0.01 Lpath_new = np.zeros(T2 + S - 1) Lpath_new[:T2] = aggr.get_L(npath[:, :T2]) Lpath_new[T2:] = L_ss rpath_new = firms.get_r(r_params, Kpath_new, Lpath_new) wpath_new = firms.get_w(w_params, Kpath_new, Lpath_new) Ypath = aggr.get_Y(Y_params, Kpath_new, Lpath_new) Cpath = np.zeros(T2 + S - 1) Cpath[:T2] = aggr.get_C(cpath[:, :T2]) Cpath[T2:] = C_ss RCerrPath = (Ypath[:-1] - Cpath[:-1] - Kpath_new[1:] + (1 - delta) * Kpath_new[:-1]) # Check the distance of Kpath_new1 KL_path_new = np.append(Kpath_new[:T2], Lpath_new[:T2]) KL_path_init = np.append(Kpath_init[:T2], Lpath_init[:T2]) dist = ((KL_path_new - KL_path_init)**2).sum() # dist = np.absolute(KL_path_new - KL_path_init).max() print( 'TPI iter: ', iter_TPI, ', dist: ', "%10.4e" % (dist), ', max abs all errs: ', "%10.4e" % (np.absolute( np.hstack((b_err_path.max(axis=0), n_err_path.max(axis=0), bSp1_err_path.max(axis=0)))).max())) # The resource constraint does not bind across the transition # path until the equilibrium is solved Kpath_init = xi * Kpath_new + (1 - xi) * Kpath_init Lpath_init = xi * Lpath_new + (1 - xi) * Lpath_init if (iter_TPI == maxiter) and (dist > mindist): print('TPI reached maxiter and did not converge.') elif (iter_TPI == maxiter) and (dist <= mindist): print('TPI converged in the last iteration. ' + 'Should probably increase maxiter_TPI.') Kpath = Kpath_new Lpath = Lpath_new rpath = rpath_new wpath = wpath_new tpi_time = time.clock() - start_time tpi_output = { 'cpath': cpath, 'npath': npath, 'b_s_path': b_s_path, 'b_splus1_path': b_splus1_path, 'wpath': wpath, 'rpath': rpath, 'Kpath': Kpath, 'Lpath': Lpath, 'Ypath': Ypath, 'Cpath': Cpath, 'bSp1_err_path': bSp1_err_path, '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: ''' ---------------------------------------------------------------- cur_path = string, path name of current directory output_fldr = string, folder in current path to save files output_dir = string, total path of images folder output_path = string, path of file name of figure to be saved tvec = (T2+S-1,) vector, time period vector tgridT = (T2,) vector, time period vector from 1 to T2 sgrid = (S,) vector, all ages from 1 to S tmat = (S, T2) matrix, time periods for decisions ages (S) and time periods (T2) smat = (S, T2) matrix, ages for all decisions ages (S) and time periods (T2) ---------------------------------------------------------------- ''' # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = "images" output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot time path of aggregate capital stock tvec = np.linspace(1, T2 + S - 1, T2 + S - 1) minorLocator = MultipleLocator(1) fig, ax = plt.subplots() plt.plot(tvec, Kpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate capital stock K') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate capital $K_{t}$') output_path = os.path.join(output_dir, 'Kpath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of aggregate capital stock fig, ax = plt.subplots() plt.plot(tvec, Lpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate labor L') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate labor $L_{t}$') output_path = os.path.join(output_dir, 'Lpath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of aggregate output (GDP) fig, ax = plt.subplots() plt.plot(tvec, Ypath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate output (GDP) Y') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate output $Y_{t}$') output_path = os.path.join(output_dir, 'Ypath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of aggregate consumption fig, ax = plt.subplots() plt.plot(tvec, Cpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for aggregate consumption C') plt.xlabel(r'Period $t$') plt.ylabel(r'Aggregate consumption $C_{t}$') output_path = os.path.join(output_dir, 'C_aggr_path') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of real wage fig, ax = plt.subplots() plt.plot(tvec, wpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for real wage w') plt.xlabel(r'Period $t$') plt.ylabel(r'Real wage $w_{t}$') output_path = os.path.join(output_dir, 'wpath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of real interest rate fig, ax = plt.subplots() plt.plot(tvec, rpath, marker='D') # for the minor ticks, use no labels; default NullFormatter ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') plt.title('Time path for real interest rate r') plt.xlabel(r'Period $t$') plt.ylabel(r'Real interest rate $r_{t}$') output_path = os.path.join(output_dir, 'rpath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of individual consumption distribution tgridT = np.linspace(1, T2, T2) sgrid = np.linspace(1, S, S) tmat, smat = np.meshgrid(tgridT, sgrid) cmap_c = cm.get_cmap('summer') fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'period-$t$') ax.set_ylabel(r'age-$s$') ax.set_zlabel(r'individual consumption $c_{s,t}$') strideval = max(int(1), int(round(S / 10))) ax.plot_surface(tmat, smat, cpath[:, :T2], rstride=strideval, cstride=strideval, cmap=cmap_c) output_path = os.path.join(output_dir, 'cpath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of individual labor supply distribution cmap_n = cm.get_cmap('summer') fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'period-$t$') ax.set_ylabel(r'age-$s$') ax.set_zlabel(r'individual labor supply $n_{s,t}$') strideval = max(int(1), int(round(S / 10))) ax.plot_surface(tmat, smat, npath[:, :T2], rstride=strideval, cstride=strideval, cmap=cmap_n) output_path = os.path.join(output_dir, 'npath') plt.savefig(output_path) # plt.show() plt.close() # Plot time path of individual savings distribution cmap_b = cm.get_cmap('summer') fig = plt.figure() ax = fig.gca(projection='3d') ax.set_xlabel(r'period-$t$') ax.set_ylabel(r'age-$s$') ax.set_zlabel(r'individual savings $b_{s,t}$') strideval = max(int(1), int(round(S / 10))) ax.plot_surface(tmat, smat, b_splus1_path[:, :T2], rstride=strideval, cstride=strideval, cmap=cmap_b) output_path = os.path.join(output_dir, 'bpath') plt.savefig(output_path) # plt.show() plt.close() return tpi_output
def get_SS(r_init, 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 2 tuple, (rss_init, c1_init) args = length 15 tuple, (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, Bsct_Tol, Eul_Tol, EulDiff, xi, maxiter) 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 = scalar > 0, initial guess for first period consumpt'n S = integer in [3, 80], number of periods an individual lives 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 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 A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital Bsct_Tol = scalar > 0, tolderance level for outer-loop bisection method Eul_Tol = scalar > 0, tolerance level for inner-loop root finder EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 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 iter_SS = integer >= 0, index of iteration number dist = scalar > 0, distance metric for current iteration rw_params = length 3 tuple, (A, alpha, delta) args to pass into firms.get_r() and firms.get_w() w_init = scalar, initial value for wage inner_args = length 14 tuple, args to pass into inner_loop() K_new = scalar > 0, updated K given r_init, w_init, and bvec L_new = scalar > 0, updated L given r_init, w_init, and nvec cvec = (S,) vector, updated values for lifetime consumption nvec = (S,) vector, updated values for lifetime labor supply bvec = (S,) vector, updated values for lifetime savings (b1, b2,...bS) b_Sp1 = scalar, updated value for savings in last period, should be arbitrarily close to zero r_new = scalar > 0, updated interest rate given bvec and nvec w_new = scalar > 0, updated wage given bvec and nvec n_errors = (S,) vector, labor supply Euler errors given r_init and w_init b_errors = (S-1,) vector, savings Euler errors given r_init and w_init all_errors = (2S,) vector, (n_errors, b_errors, b_Sp1) c_ss = (S,) vector, steady-state lifetime consumption n_ss = (S,) vector, steady-state lifetime labor supply b_ss = (S,) vector, steady-state wealth enter period with (b1, b2, ...bS) b_Sp1_ss = scalar, steady-state savings for period after last period of life. b_Sp1_ss approx. 0 in equilibrium n_err_ss = (S,) vector, lifetime labor supply Euler errors b_err_ss = (S-1) vector, 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, (A, alpha) 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 14 dict, steady-state objects {n_ss, b_ss, c_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} FILES CREATED BY THIS FUNCTION: SS_bc.png SS_n.png RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, SS_Tol, Eul_Tol, EulDiff, xi, maxiter) = args ns_guess = 0.4 * l_tilde * np.ones(S) bsp1_guess = 0.1 * np.ones(S - 1) nb_guess = np.append(ns_guess, bsp1_guess) r_args = (nb_guess, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, Eul_Tol, EulDiff) results_r = opt.root(get_r_error, r_init, args=r_args, tol=SS_Tol) if results_r.success: print('SS SUCCESS: Steady-state outer loop for r converged.') r_ss = results_r.x r_err_ss = results_r.fun # Solve for steady-state w as a function of steady-state r w_args = (A, alpha, delta) w_ss = firms.get_w(r_ss, w_args) # Solve for steady-state n_s and b_s given steady-state r and w euler_args = (r_ss, w_ss, beta, sigma, l_tilde, chi_n_vec, b_ellip, upsilon, EulDiff, S) results_nb = opt.root(euler_sys, nb_guess, args=euler_args, method='lm', tol=Eul_Tol) n_ss = results_nb.x[:S] bsp1_ss = results_nb.x[S:] n_err_ss = results_nb.fun[:S] b_err_ss = results_nb.fun[S:] b_ss = np.append(0.0, bsp1_ss) c_ss = hh.get_cons(r_ss, w_ss, b_ss, np.append(bsp1_ss, 0.0), n_ss) K_ss = bsp1_ss.sum() L_ss = n_ss.sum() I_ss = delta * K_ss Y_params = (A, alpha) Y_ss = aggr.get_Y(K_ss, L_ss, Y_params) C_ss = aggr.get_C(c_ss) RCerr_ss = Y_ss - C_ss - I_ss ss_time = time.clock() - start_time ss_output = { 'c_ss': c_ss, 'n_ss': n_ss, 'b_ss': b_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'K_ss': K_ss, 'L_ss': L_ss, 'Y_ss': Y_ss, 'I_ss': I_ss, 'C_ss': C_ss, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'r_err_ss': r_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('n_ss is: ', n_ss) print('b_ss is: ', b_ss) print('K_ss=', K_ss, ', L_ss=', L_ss) print('Y_ss=', Y_ss, ', I_ss=', I_ss, ', C_ss=', C_ss) print('r_ss=', r_ss, ', w_ss=', w_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('Interest rate FOC error is: ', r_err_ss) print('Resource constraint error is: ', RCerr_ss) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: create_graphs(c_ss, b_ss, n_ss) return ss_output