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_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_TP(p, ss_output, graphs): ''' -------------------------------------------------------------------- Solves for transition path equilibrium using time path iteration (TPI) -------------------------------------------------------------------- INPUTS: p = parameters class object ss_output = length 18 dictionary, steady-state output graphs = boolean, =True if generate transition path equilibrium graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: get_path() firms.get_wt() hh.get_cnb_paths() aggr.get_Lt() aggr.get_Kt() firms.get_rt() aggr.get_BQt() utils.print_time() firms.get_Yt() aggr.get_Ct() aggr.get_It() aggr.get_NXt() creat_graphs() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar, current processor time in seconds (float) r_ss = scalar > -delta, steady-state interest rate BQ_ss = scalar > 0, steady-state total bequests r_path_init = (T2+S,) vector, initial guess of interest rate time path BQ_path_init = (T2+S,) vector, initial guess of total bequests time path r_0 = scalar > -delta, initial period interest rate guess BQ_0 = scalar > 0, initial period total bequests guess rBQpath_init = (2, T2+S) matrix, initial guess for time paths of interest rate and total bequests iter_TPI = integer >= 0, iteration number index for TPI dist = scalar > 0, distance measure of (rBQpath_new - rBQpath_init) cnb_args = length 2 tuple, (ss_output, p) arguments passed to hh.get_cnb_paths() w_path = (T2+S,) vector, time path of wages cs_path = (S, T2+S) matrix, time path of household consumption by age ns_path = (S, T2+S) matrix, time path of household labor supply by age bs_path = (S+1, T2+S+1) matrix, time path of household savings and wealth by age ns_err_path = (S, T2+S) matrix, time path of Euler errors by age from household optimal labor supply decisions bs_err_path = (S+1, T2+S+1) matrix, time path of Euler errors by age from household optimal savings decisions L_path = (T2+1,) vector, time path of aggregate labor K_path = (T2+1,) vector, time path of aggregate capital stock r_path_new = (T2+S,) vector, time path of interest rates implied by household and firm optimization BQ_Path_new = (T2+S,) vector, time path of total bequests implied by household and firm optimization rBQpath_new = (2, T2+S) matrix, time path of interest rates and total bequests implied by household and firm optimization tpi_time = scalar, elapsed time for TPI computation r_path = (T2+S,) vector, equilibrium interest rate time path BQ_path = (T2+S,) vector, equilibrium total bequests time path Y_path = (T2+1,) vector, equilibrium aggregate output time path C_path = (T2+1,) vector, equilibrium aggregate consumption time path I_path = (T2+1,) vector, equilibrium aggregate investment time path NX_path = (T2+1,) vector, equilibrium net exports time path tpi_output = length 17 dictionary, tpi output objects {cs_path, ns_path, bs_path, ns_err_path, bs_err_path, r_path, w_path, BQ_path, K_path, L_path, Y_path, C_path, I_path, NX_path, dist, iter_TPI, tpi_time} FILES CREATED BY THIS FUNCTION: None RETURNS: tpi_output -------------------------------------------------------------------- ''' start_time = time.clock() # Unpack steady-state objects to be used in this algorithm r_ss = ss_output['r_ss'] BQ_ss = ss_output['BQ_ss'] # Create initial time paths for r, w r_path_init = np.zeros(p.T2 + p.S) BQ_path_init = np.zeros(p.T2 + p.S) # pct_r = 1 + p.xi_TP * ((Km_ss.sum() - p.b_s0_vec.sum()) / # p.b_s0_vec.sum()) r_0 = r_ss # pct_r * r_ss BQ_0 = BQ_ss # (2 - pct_r) * w_ss r_path_init[:p.T2 + 1] = get_path(r_0, r_ss, p.T2 + 1, 'quadratic') r_path_init[p.T2 + 1:] = r_ss BQ_path_init[:p.T2 + 1] = get_path(BQ_0, BQ_ss, p.T2 + 1, 'quadratic') BQ_path_init[p.T2 + 1:] = BQ_ss # print('rpath_init=', rpath_init) # print('BQpath_init=', BQpath_init) rBQpath_init = np.zeros((2, p.T2 + p.S)) rBQpath_init[0, :] = r_path_init rBQpath_init[1, :] = BQ_path_init # raise ValueError('Pause program') iter_TPI = int(0) dist = 10.0 cnb_args = (ss_output, p) while (iter_TPI < p.maxiter_TP) and (dist > p.TP_OutTol): iter_TPI += 1 r_path_init = rBQpath_init[0, :] BQ_path_init = rBQpath_init[1, :] # Solve for time path of w_t given r_t w_path = firms.get_wt(r_path_init, p) # Solve for time path of household optimal decisions n_{s,t} # and b_{s+1,t+1} given prices r_t and w_t and total bequests # BQ_t (cs_path, ns_path, bs_path, ns_err_path, bs_err_path) = \ hh.get_cnb_paths(r_path_init, w_path, BQ_path_init, cnb_args) # Solve for time paths of aggregate capital K_t and aggregate # labor L_t L_path = aggr.get_Lt(ns_path[:, :p.T2 + 1], p) K_path = aggr.get_Kt(bs_path[1:, :p.T2 + 1], p) # Solve for new time paths of r_t^{i+1} and total bequests # BQ_t^{i+1} r_path_new = np.zeros(p.T2 + p.S) r_path_new[:p.T2 + 1] = firms.get_rt(K_path, L_path, p) r_path_new[p.T2 + 1:] = r_path_init[p.T2 + 1:] BQ_path_new = np.zeros(p.T2 + p.S) BQ_path_new[:p.T2 + 1] = aggr.get_BQt(bs_path[1:, :p.T2 + 1], r_path_init[:p.T2 + 1], p) BQ_path_new[p.T2 + 1:] = BQ_path_init[p.T2 + 1:] # Calculate distance measure between (r^{i+1},BQ^{i+1}) and # (r^i,BQ^i) rBQpath_new = np.vstack((r_path_new.reshape((1, p.T2 + p.S)), BQ_path_new.reshape((1, p.T2 + p.S)))) dist = np.absolute(rBQpath_new - rBQpath_init).max() print( 'TPI iter: ', iter_TPI, ', dist: ', "%10.4e" % (dist), ', max abs all errs: ', "%10.4e" % (np.absolute(np.hstack((bs_err_path.max(axis=0), ns_err_path.max(axis=0)))).max())) if dist > p.TP_OutTol: rBQpath_init = (p.xi_TP * rBQpath_new + (1 - p.xi_TP) * rBQpath_init) tpi_time = time.clock() - start_time # Print TPI computation time utils.print_time(tpi_time, 'TPI') if (iter_TPI == p.maxiter_TP) and (dist > p.TP_OutTol): print('TPI reached maxiter and did not converge.') elif (iter_TPI == p.maxiter_TP) and (dist <= p.TP_OutTol): print('TPI converged in the last iteration. ' + 'Should probably increase maxiter_TP.') elif (iter_TPI < p.maxiter_TP) and (dist <= p.TP_OutTol): print('TPI SUCCESS: Converged on iteration', iter_TPI, '.') r_path = r_path_init BQ_path = BQ_path_init # Solve for equilibrium time paths of aggregate output, consumption, # investment, and net exports Y_path = firms.get_Yt(K_path, L_path, p) C_path = aggr.get_Ct(cs_path[:, :p.T2 + 1], p) I_path = aggr.get_It(K_path, p) NX_path = aggr.get_NXt(bs_path[1:, :p.T2 + 1], p) # Create TPI output dictionary tpi_output = { 'cs_path': cs_path, 'ns_path': ns_path, 'bs_path': bs_path, 'ns_err_path': ns_err_path, 'bs_err_path': bs_err_path, 'r_path': r_path, 'w_path': w_path, 'BQ_path': BQ_path, 'K_path': K_path, 'L_path': L_path, 'Y_path': Y_path, 'C_path': C_path, 'I_path': I_path, 'NX_path': NX_path, 'dist': dist, 'iter_TPI': iter_TPI, 'tpi_time': tpi_time} if graphs: create_graphs(tpi_output, p) return tpi_output
def get_SS(rBQ_init, p, graphs=False): ''' -------------------------------------------------------------------- Solve for the steady-state solution of the S-period-lived agent OG model with endogenous labor supply and multiple industries using the root finder method in r and w for the outer loop -------------------------------------------------------------------- INPUTS: rBQ_init = (2,) vector, initial guesses for (rss_init, BQss_init) p = parameters class object graphs = boolean, =True if output steady-state graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: rBQ_errors() firms.get_wt() hh.get_cnb_vecs() aggr.get_Lt() aggr.get_Kt() firms.get_Yt() C_ss = aggr.get_Ct() I_ss = aggr.get_It() NX_ss = aggr.get_NXt() utils.print_time() ss_graphs() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar > 0, clock time at beginning of program nvec_guess = (S,) vector, initial guess for optimal household labor supply n_s bvec_guess = (S,) vector, initial guess for optimal household savings b_sp1 nb_guess = (2S,) vector, initial guesses for optimal household labor supply and savings (n_s, b_sp1) rBQ_args = length 2 tuple, (nb_guess, p) results_rBQ = root results object err_msg = string, error message text string r_ss = scalar > -delta, steady-state interest rate BQ_ss = scalar > 0, steady-state total bequests r_err_ss = scalar, error in steady-state optimal solution firm first order condition for r_ss BQ_err_ss = scalar, error in steady-state optimal solution bequests law of motion for BQ_ss w_ss = scalar > 0, steady-state wage b_init = scalar = 0, initial wealth of initial age individuals r_path = (S,) vector, constant interest rate time path over lifetime of individual w_path = (S,) vector, constant wage time path over lifetime of individual BQ_path = (S,) vector, constant total bequests time path over lifetime of individual c_ss = (S,) vector, steady-state consumption by age n_ss = (S,) vector, steady-state labor supply by age b_ss = (S+1,) vector, steady-state wealth or savings by age n_err_ss = (S,) vector, errors associated with optimal labor supply solution b_err_ss = (S,) vector, errors associated with optimal savings solution L_ss = scalar > 0, steady-state aggregate labor K_ss = scalar > 0, steady-state aggregate capital stock Y_ss = scalar > 0, steady-state aggregate output C_ss = scalar > 0, steady-state aggregate consumption I_ss = scalar, steady-state aggregate investment NX_ss = scalar, steady-state net exports RCerr_ss = scalar, steady-state resource constraint (goods market clearing) error ss_time = scalar, seconds elapsed for steady-state computation ss_output = length 18 dictionary, steady-state output {c_ss, n_ss, b_ss, n_err_ss, b_err_ss, r_ss, w_ss, BQ_ss, r_err_ss, BQ_err_ss, L_ss, K_ss, Y_ss, C_ss, I_ss, NX_ss, RCerr_ss, ss_time} FILES CREATED BY THIS FUNCTION: None RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() nvec_guess = 0.4 * p.l_tilde * np.ones(p.S) bvec_guess = 0.1 * np.ones(p.S) nb_guess = np.append(nvec_guess, bvec_guess) rBQ_args = (nb_guess, p) results_rBQ = opt.root(rBQ_errors, rBQ_init, args=rBQ_args, tol=p.SS_OutTol) if not results_rBQ.success: err_msg = ('SS Error: Steady-state root finder did not ' + 'solve. results_rBQ.success=False') raise ValueError(err_msg) else: print('SS SUCESSS: steady-state solution converged.') # print(results_rw) r_ss, BQ_ss = results_rBQ.x r_err_ss, BQ_err_ss = results_rBQ.fun # Solve for steady-state wage w_ss implied by r_ss w_ss = firms.get_wt(r_ss, p) # Solve for household steady-state decisions c_s, n_s, b_{s+1} given # r, w, and BQ b_init = 0.0 r_path = r_ss * np.ones(p.S) w_path = w_ss * np.ones(p.S) BQ_path = BQ_ss * np.ones(p.S) c_ss, n_ss, b_ss, n_err_ss, b_err_ss = \ hh.get_cnb_vecs(nb_guess, b_init, r_path, w_path, BQ_path, p.rho_ss, p.SS_EulDif, p, p.SS_EulTol) # Solve for steady-state aggregate labor and aggregate capital L_ss = aggr.get_Lt(n_ss, p) K_ss = aggr.get_Kt(b_ss[1:], p) # Solve for steady-state aggregate output Y, consumption C, # investment I, and net exports Y_ss = firms.get_Yt(K_ss, L_ss, p) C_ss = aggr.get_Ct(c_ss, p) I_ss = aggr.get_It(K_ss, p) NX_ss = aggr.get_NXt(b_ss[1:], p) # Solve for steady-state resource constraint error 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, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'r_ss': r_ss, 'w_ss': w_ss, 'BQ_ss': BQ_ss, 'r_err_ss': r_err_ss, 'BQ_err_ss': BQ_err_ss, 'L_ss': L_ss, 'K_ss': K_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'I_ss': I_ss, 'NX_ss': NX_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('n_ss=', n_ss) print('b_ss=', b_ss) print('K_ss=', K_ss) print('L_ss=', L_ss) print('r_ss=', r_ss, ', w_ss=', w_ss, ', BQ_ss=', BQ_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('RC error is: ', RCerr_ss) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: ss_graphs(c_ss, n_ss, b_ss, p) return ss_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(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(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_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: 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() (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 = ch_ss.sum() Cf_ss = cf_ss.sum() # Solve for Home and Foreign goods market clearing (resource # constraint) errors # RC_h_err_ss = Yh_ss - Ch_ss - delta_h * K_h_ss # RC_f_err_ss = Yf_ss - Cf_ss - delta_f * K_f_ss RC_h_err_ss = (Yh_ss - Ch_ss - (r_ss + delta_h) * K_h_ss + rh_ss * (K_hh_ss + K_fh_ss)) RC_f_err_ss = (Yf_ss - Cf_ss - (rstar_ss + delta_f) * K_f_ss + rf_ss * (K_ff_ss + K_hf_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, '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, 'RC_h_err_ss': RC_h_err_ss, 'RC_f_err_ss': RC_f_err_ss, 'ss_time': ss_time} print('bh_ss is: ', bh_ss) print('bf_ss is: ', bf_ss) print('K_h_ss=', K_h_ss, ', rh_ss=', rh_ss, ', r_ss=', r_ss, ', wh_ss=', wh_ss) print('K_f_ss=', K_f_ss, ', rf_ss=', rf_ss, ', rstar_ss=', rstar_ss, ', wf_ss=', wf_ss) print('Max. abs. savings Euler error is: ', np.absolute(np.append(bhss_errors, bfss_errors)).max()) print('Max. abs. resource constraint error is: ', 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(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_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(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
SS_tol_inner, xi_SS, SS_maxiter, mean_ydata, init_calc) print('BEGIN EQUILIBRIUM STEADY-STATE COMPUTATION WITH CALIBRATION') print('Solving SS outer loop using bisection method on r, BQ, ' + 'and factor.') ss_output = ss.get_SS(ss_init_vals, ss_args, SS_graphs) # Update ss_args with new chi_n_vec chi_n_vec = ss_output['chi_n_vec'] ss_args = (J, E, S, lambdas, emat, mort_rates, imm_rates_adj, omega_SS, g_n_SS, zeta_mat, chi_n_vec, chi_b_vec, beta, sigma, l_tilde, b_ellip, upsilon, g_y, Z, gamma, delta, SS_tol_outer, SS_tol_inner, xi_SS, SS_maxiter, mean_ydata, init_calc) tot_ss_time = time.clock() - tot_ss_strt_time utils.print_time(tot_ss_time, 'Total steady-state') # Save ss_output as pickle pickle.dump(ss_output, open(ss_outputfile, 'wb')) pickle.dump(ss_args, open(ss_paramsfile, 'wb')) # Don't compute steady-state, get it from pickle else: # Make sure that the SS output files exist ss_vars_exst = os.path.exists(ss_outputfile) ss_args_exst = os.path.exists(ss_paramsfile) if (not ss_vars_exst) or (not ss_args_exst): # If the files don't exist, stop the program and run the steady- # state solution first err_msg = ('ERROR: The SS output files do not exist and ' + 'SS_solve=False. Must set SS_solve=True and ' +
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_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_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 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