def inner_loop(r, w, Y, x, params): ''' -------------------------------------------------------------------- Given values for r and w, solve for equilibrium errors from the two first order conditions of the firm -------------------------------------------------------------------- INPUTS: r = scalar > 0, guess at steady-state interest rate w = scalar > 0, guess at steady-state wage Y = scalar > 0, guess steady-state output x = scalar > 0, guess as steady-state transfers per household params = length 16 tuple, (c1_init, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, tax_params, fiscal_params, diff, hh_fsolve, SS_tol) OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: hh.bn_solve() hh.c1_bSp1err() hh.get_cnb_vecs() aggr.get_K() aggr.get_L() firms.get_r() firms.get_w() OBJECTS CREATED WITHIN FUNCTION: c1_init = scalar > 0, initial guess for c1 S = integer >= 3, number of periods in individual lifetime beta = scalar in (0,1), discount factor sigma = scalar >= 1, coefficient of relative risk aversion l_tilde = scalar > 0, per-period time endowment for every agent 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) diff = boolean, =True if simple difference Euler errors, otherwise percent deviation Euler errors 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 SS_tol = scalar > 0, tolerance level for steady-state fsolve 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 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() b_init = (S-1,) vector, initial guess at distribution of savings n_init = (S,) vector, initial guess at distribution of labor supply guesses = (2S-1,) vector, initial guesses at b and n bn_params = length 12 tuple, parameters to pass to solve_bn_path() (r, w, x, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, tax_params, diff) euler_errors = (2S-1,) vector, Euler errors for FOCs for b and n b_splus1_vec = (S,) vector, optimal savings choice nvec = (S,) vector, optimal labor supply choice b_Sp1 = scalar, last period savings b_s_vec = (S,) vector, wealth enter period with cvec = (S,) vector, optimal consumption 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() c1_options = length 1 dict, options for c1_bSp1err() results_c1 = results object, results from c1_bSp1err() c1 = scalar > 0, optimal initial period consumption given r and w cnb_args = length 8 tuple, args to pass into get_cnb_vecs() cvec = (S,) vector, lifetime consumption (c1, c2, ...cS) nvec = (S,) vector, lifetime labor supply (n1, n2, ...nS) bvec = (S,) vector, lifetime savings (b1, b2, ...bS) with b1=0 b_Sp1 = scalar, final period savings, should be close to zero B = scalar > 0, aggregate savings B_cnstr = boolean, =True if B < 0 L = scalar > 0, aggregate labor debt = scalar, total government debt K = scalar > 0, aggregate capital stock K_cnstr = boolean, =True if K < 0 r_new = scalar > 0, implied steady-state interest rate w_new = scalar > 0, implied steady-state wage Y_new = scalar >0, implied steady-state output x_new = scalar >=0, implied transfers per household FILES CREATED BY THIS FUNCTION: None RETURNS: B, K, L, Y_new, debt, cvec, nvec, b_s_vec, b_splus1_vec, b_Sp1, x_new, r_new, w_new -------------------------------------------------------------------- ''' c1_init, S, beta, sigma, l_tilde, b_ellip, upsilon,\ chi_n_vec, A, alpha, delta, tax_params, fiscal_params,\ diff, hh_fsolve, SS_tol = params tau_l, tau_k, tau_c = tax_params tG1, tG2, alpha_X, alpha_G, rho_G, alpha_D, alpha_D0 = fiscal_params r_params = (A, alpha, delta, tau_c) w_params = (A, alpha) Y_params = (A, alpha) 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, w, x, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, tax_params, diff) [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_vec = np.append(solutions[:S - 1], 0.0) nvec = solutions[S - 1:] b_Sp1 = 0.0 b_s_vec = np.append(0.0, b_splus1_vec[:-1]) cvec = hh.get_cons(r, w, b_s_vec, b_splus1_vec, nvec, x, tax_params) else: rpath = r * np.ones(S) wpath = w * np.ones(S) xpath = x * np.ones(S) c1_options = {'maxiter': 500} c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, tax_params, xpath, rpath, wpath, diff) results_c1 = \ opt.root(hh.c1_bSp1err, c1_init, args=(c1_args), method='lm', tol=SS_tol, options=(c1_options)) c1_new = results_c1.x cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, tax_params, diff) cvec, nvec, b_s_vec, b_Sp1 = \ hh.get_cnb_vecs(c1_new, rpath, wpath, xpath, cnb_args) b_splus1_vec = np.append(b_s_vec[1:], b_Sp1) B, B_cnstr = aggr.get_K(b_s_vec) L = aggr.get_L(nvec) L = np.maximum(0.0001, L) debt = alpha_D * Y K = B - debt K_cnstr = K < 0 if K_cnstr: print('Aggregate capital constraint is violated K<=0 for ' + 'in the steady state.') r_new = firms.get_r(r_params, K, L) w_new = firms.get_w(w_params, K, L) Y_new = aggr.get_Y(Y_params, K, L) x_new = (alpha_X * Y_new) / S return B, K, L, Y_new, debt, cvec, nvec, b_s_vec, b_splus1_vec, \ b_Sp1, x_new, r_new, w_new
def get_cnbpath(params, rpath, wpath): ''' -------------------------------------------------------------------- Given time paths for interest rates and wages, this function generates matrices for the time path of the distribution of individual consumption, labor supply, savings, the corresponding Euler errors for the labor supply decision and the savings decision, and the residual error of end-of-life savings associated with solving each lifetime decision. -------------------------------------------------------------------- INPUTS: params = length 11 tuple, (S, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, bvec1, TPI_tol, diff) rpath = (T2+S-1,) vector, equilibrium time path of interest rate wpath = (T2+S-1,) vector, equilibrium time path of the real wage OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: hh.c1_bSp1err() hh.get_cnb_vecs() hh.get_n_errors() hh.get_b_errors() OBJECTS CREATED WITHIN FUNCTION: S = integer in [3,80], number of periods an individual lives T2 = integer > S, number of periods until steady state beta = scalar in (0,1), discount factor 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 bvec1 = (S,) vector, initial period savings distribution TPI_tol = scalar > 0, tolerance level for fsolve's in TPI 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 cpath = (S, T2+S-1) matrix, time path of the distribution of consumption npath = (S, T2+S-1) matrix, time path of the distribution of labor supply bpath = (S, T2+S-1) matrix, time path of the distribution of savings n_err_path = (S, T2+S-1) matrix, time path of distribution of labor supply Euler errors b_err_path = (S, T2+S-1) matrix, time path of distribution of savings Euler errors 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 c1_options = length 1 dict, options for opt.root(hh.c1_bSp1err,...) b_err_params = length 2 tuple, args to pass into hh.get_b_errors() p = integer in [1, S-1], index representing number of periods remaining in a lifetime, used to solve incomplete lifetimes c1_init = scalar > 0, guess for initial period consumption c1_args = length 10 tuple, args to pass into opt.root(hh.c1_bSp1err,...) results_c1 = results object, solution from opt.root(hh.c1_bSp1err,...) c1 = scalar > 0, optimal initial consumption cnb_args = length 8 tuple, args to pass into hh.get_cnb_vecs() cvec = (p,) vector, individual lifetime consumption decisions nvec = (p,) vector, individual lifetime labor supply decisions bvec = (p,) vector, individual lifetime savings decisions b_Sp1 = scalar, savings in last period for next period. Should be zero in equilibrium DiagMaskc = (p, p) boolean identity matrix DiagMaskb = (p-1, p-1) boolean identity matrix n_err_params = length 5 tuple, args to pass into hh.get_n_errors() n_err_vec = (p,) vector, individual lifetime labor supply Euler errors b_err_vec = (p-1,) vector, individual lifetime savings Euler errors t = integer in [0,T2-1], index of time period (minus 1) FILES CREATED BY THIS FUNCTION: None RETURNS: cpath, npath, bpath, n_err_path, b_err_path, bSp1_err_path -------------------------------------------------------------------- ''' (S, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, bvec1, TPI_tol, diff) = params cpath = np.zeros((S, T2 + S - 1)) npath = np.zeros((S, T2 + S - 1)) bpath = np.append(bvec1.reshape((S, 1)), np.zeros((S, T2 + S - 2)), axis=1) n_err_path = np.zeros((S, T2 + S - 1)) b_err_path = np.zeros((S, T2 + S - 1)) bSp1_err_path = np.zeros((S, T2)) # Solve the incomplete remaining lifetime decisions of agents alive # in period t=1 but not born in period t=1 c1_options = {'maxiter': 500} b_err_params = (beta, sigma) for p in range(1, S): c1_init = 0.1 c1_args = (bvec1[-p], beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec[-p:], rpath[:p], wpath[:p], diff) results_c1 = \ opt.root(hh.c1_bSp1err, c1_init, args=(c1_args), method='lm', tol=TPI_tol, options=(c1_options)) c_1 = results_c1.x cnb_args = (bvec1[-p], beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec[-p:], diff) cvec, nvec, bvec, b_Sp1 = \ hh.get_cnb_vecs(c_1, rpath[:p], wpath[:p], cnb_args) DiagMaskc = np.eye(p, dtype=bool) DiagMaskb = np.eye(p - 1, dtype=bool) cpath[-p:, :p] = DiagMaskc * cvec + cpath[-p:, :p] npath[-p:, :p] = DiagMaskc * nvec + npath[-p:, :p] n_err_args = (wpath[:p], cvec, sigma, l_tilde, chi_n_vec[-p:], b_ellip, upsilon, diff) n_err_vec = hh.get_n_errors(nvec, n_err_args) n_err_path[-p:, :p] = (DiagMaskc * n_err_vec + n_err_path[-p:, :p]) bSp1_err_path[-p, 0] = b_Sp1 if p > 1: bpath[S - p + 1:, 1:p] = (DiagMaskb * bvec[1:] + bpath[S - p + 1:, 1:p]) b_err_vec = hh.get_b_errors(b_err_params, rpath[1:p], cvec, diff) b_err_path[S - p + 1:, 1:p] = (DiagMaskb * b_err_vec + b_err_path[S - p + 1:, 1:p]) # print('p=', p, ', max. abs. all errs: ', # np.hstack((n_err_vec, b_err_vec, b_Sp1)).max()) # Solve the remaining lifetime decisions of agents born between # period t=1 and t=T (complete lifetimes) DiagMaskc = np.eye(S, dtype=bool) DiagMaskb = np.eye(S - 1, dtype=bool) for t in range(T2): # Go from periods 1 to T (columns 0 to T-1) if t == 0: c1_init = 0.1 else: c1_init = cpath[0, t - 1] c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, rpath[t:t + S], wpath[t:t + S], diff) results_c1 = \ opt.root(hh.c1_bSp1err, c1_init, args=(c1_args), method='lm', tol=TPI_tol, options=(c1_options)) c_1 = results_c1.x cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, diff) cvec, nvec, bvec, b_Sp1 = \ hh.get_cnb_vecs(c_1, rpath[t:t + S], wpath[t:t + S], cnb_args) cpath[:, t:t + S] = DiagMaskc * cvec + cpath[:, t:t + S] npath[:, t:t + S] = DiagMaskc * nvec + npath[:, t:t + S] n_err_args = (wpath[t:t + S], cvec, sigma, l_tilde, chi_n_vec, b_ellip, upsilon, diff) n_err_vec = hh.get_n_errors(nvec, n_err_args) n_err_path[:, t:t + S] = (DiagMaskc * n_err_vec + n_err_path[:, t:t + S]) bpath[:, t:t + S] = DiagMaskc * bvec + bpath[:, t:t + S] b_err_vec = hh.get_b_errors(b_err_params, rpath[t + 1:t + S], cvec, diff) b_err_path[1:, t + 1:t + S] = (DiagMaskb * b_err_vec + b_err_path[1:, t + 1:t + S]) bSp1_err_path[0, t] = b_Sp1 # print('t=', t, ', max. abs. all errs: ', # np.absolute(np.hstack((n_err_vec, b_err_vec, # b_Sp1))).max()) return cpath, npath, bpath, n_err_path, b_err_path, bSp1_err_path
def rBQ_errors(rBQ_vals, *args): ''' -------------------------------------------------------------------- Generate interest rate and wage errors from labor market clearing and capital market clearing conditions -------------------------------------------------------------------- INPUTS: rBQ_vals = (2,) vector, steady-state r value and BQ value args = length 2 tuple, (nb_guess, p) OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: firms.get_wt() hh.get_cnb_vecs() aggr.get_Lt() aggr.get_Kt() firms.get_rt() aggr.get_BQt() OBJECTS CREATED WITHIN FUNCTION: nb_buess = (2S,) vector, initial guesses for n_s and b_sp1 p = parameters class object r_init = scalar, initial guess for steady-state interest rate BQ_init = scalar, initial guess for steady-state total bequests w = scalar, steady-state wage implied by r_init 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_s = (S,) vector, steady-state consumption by age n_s = (S,) vector, steady-state labor supply by age b_s = (S+1,) vector, steady-state wealth or savings by age n_errors = (S,) vector, errors associated with optimal labor supply solution b_errors = (S,) vector, errors associated with optimal savings solution L = scalar, aggregate labor implied by household and firm optimization K = scalar, aggregate capital implied by household and firm optimization r_new = scalar, new value of r implied by household and firm optimization BQ_new = scalar, new value of BQ implied by household and firm optimization r_error = scalar, difference between r_new and r_init BQ_error = scalar, difference between BQ_new and BQ_init rBQ_errors = (2,) vector, r_error and BQ_error FILES CREATED BY THIS FUNCTION: None RETURNS: rBQ_errors -------------------------------------------------------------------- ''' (nb_guess, p) = args r_init, BQ_init = rBQ_vals # Solve for steady-state wage w implied by r w = firms.get_wt(r_init, 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_init * np.ones(p.S) w_path = w * np.ones(p.S) BQ_path = BQ_init * np.ones(p.S) c_s, n_s, b_s, n_errors, b_errors = \ 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 aggregate labor and aggregate capital L = aggr.get_Lt(n_s, p) K = aggr.get_Kt(b_s[1:], p) # Solve for updated values of the interest rate r and total bequests # BQ r_new = firms.get_rt(K, L, p) BQ_new = aggr.get_BQt(b_s[1:], r_init, p) # solve for errors in interest rate and total bequests guesses r_error = r_new - r_init BQ_error = BQ_new - BQ_init rBQ_errors = np.array([r_error, BQ_error]) return rBQ_errors
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 inner_loop(r, w, args): ''' -------------------------------------------------------------------- Given values for r and w, solve for equilibrium errors from the two first order conditions of the firm -------------------------------------------------------------------- INPUTS: r = scalar > 0, guess at steady-state interest rate w = scalar > 0, guess at steady-state wage args = length 14 tuple, (c1_init, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, EulDiff, Eul_Tol, c1_options) OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: hh.c1_bSp1err() hh.get_cnb_vecs() aggr.get_K() aggr.get_L() firms.get_r() firms.get_w() OBJECTS CREATED WITHIN FUNCTION: c1_init = scalar > 0, initial guess for c1 S = integer >= 3, number of periods in individual lifetime beta = scalar in (0,1), discount factor sigma = scalar >= 1, coefficient of relative risk aversion l_tilde = scalar > 0, per-period time endowment for every agent 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 EulDiff = boolean, =True if simple difference Euler errors, otherwise percent deviation Euler errors SS_tol = scalar > 0, tolerance level for steady-state fsolve c1_options = length 1 dict, options for c1_bSp1err() rpath = (S,) vector, lifetime path of interest rates wpath = (S,) vector, lifetime path of wages c1_args = length 10 tuple, args to pass into hh.c1_bSp1err() results_c1 = results object, results from c1_bSp1err() c1 = scalar > 0, optimal initial period consumption given r and w cnb_args = length 8 tuple, args to pass into get_cnb_vecs() cvec = (S,) vector, lifetime consumption (c1, c2, ...cS) nvec = (S,) vector, lifetime labor supply (n1, n2, ...nS) bvec = (S,) vector, lifetime savings (b1, b2, ...bS) with b1=0 b_Sp1 = scalar, final period savings, should be close to zero n_errors = (S,) vector, labor supply Euler errors b_errors = (S-1,) vector, savings Euler errors K = scalar > 0, aggregate capital stock K_cstr = boolean, =True if K < epsilon L = scalar > 0, aggregate labor L_cstr = boolean, =True if L < epsilon r_params = length 3 tuple, (A, alpha, delta) w_params = length 2 tuple, (A, alpha) r_new = scalar > 0, guess at steady-state interest rate w_new = scalar > 0, guess at steady-state wage FILES CREATED BY THIS FUNCTION: None RETURNS: K, L, cvec, nvec, bvec, b_Sp1, r_new, w_new, n_errors, b_errors -------------------------------------------------------------------- ''' (c1_init, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, EulDiff, SS_tol, c1_options) = args rpath = r * np.ones(S) wpath = w * np.ones(S) c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, rpath, wpath, EulDiff) results_c1 = \ opt.root(hh.c1_bSp1err, c1_init, args=(c1_args), method='lm', tol=SS_tol, options=(c1_options)) c1 = results_c1.x cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, EulDiff) cvec, nvec, bvec, b_Sp1, n_errors, b_errors = \ hh.get_cnb_vecs(c1, rpath, wpath, cnb_args) K, K_cstr = aggr.get_K(bvec) L, L_cstr = aggr.get_L(nvec) r_params = (A, alpha, delta) r_new = firms.get_r(K, L, r_params) w_params = (A, alpha, delta) w_new = firms.get_w(r_new, w_params) return (K, L, cvec, nvec, bvec, b_Sp1, r_new, w_new, n_errors, b_errors)
def get_SS(init_vals, args, graphs=False): ''' -------------------------------------------------------------------- Solve for the steady-state solution of the S-period-lived agent OG model with endogenous labor supply and a small open economy. -------------------------------------------------------------------- INPUTS: init_vals = length 5 tuple, (Kss_init, Lss_init, rss_init, wss_init,c1_init) args = length 14 tuple, (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, SS_tol, EulDiff, hh_fsolve, KL_outer) graphs = boolean, =True if output steady-state graphs OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: firms.get_r() firms.get_w() hh.bn_solve() hh.c1_bSp1err() hh.get_cnb_vecs() aggr.get_K() aggr.get_L() aggr.get_Y() aggr.get_C() hh.get_cons() hh.get_n_errors() hh.get_b_errors() utils.print_time() OBJECTS CREATED WITHIN FUNCTION: start_time = scalar > 0, clock time at beginning of program Kss_init = scalar > 0, initial guess for steady-state aggregate capital stock supplied Lss_init = scalar > 0, initial guess for steady-state aggregate labor rss_init = scalar > 0, initial guess for steady-state interest rate wss_init = scalar > 0, initial guess for steady-state wage c1_init = scalar > 0, initial guess for first period consumpt'n S = integer in [3, 80], number of periods an individual lives beta = scalar in (0,1), discount factor for each model per sigma = scalar > 0, coefficient of relative risk aversion l_tilde = scalar > 0, time endowment for each agent each period b_ellip = scalar > 0, fitted value of b for elliptical disutility of labor upsilon = scalar > 1, fitted value of upsilon for elliptical disutility of labor chi_n_vec = (S,) vector, values for chi^n_s A = scalar > 0, total factor productivity parameter in firms' production function alpha = scalar in (0,1), capital share of income delta = scalar in [0,1], model-period depreciation rate of capital SS_tol = scalar > 0, tolerance level for steady-state fsolve EulDiff = Boolean, =True if want difference version of Euler errors beta*(1+r)*u'(c2) - u'(c1), =False if want ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1 maxiter_SS = integer >= 1, maximum number of iterations in outer loop bisection method iter_SS = integer >= 0, index of iteration number mindist_SS = scalar > 0, minimum distance tolerance for convergence dist_SS = scalar > 0, distance metric for current iteration xi_SS = scalar in (0,1], updating parameter KL_init = (2,) vector, (K_init, L_init) c1_options = length 1 dict, options to pass into opt.root(c1_bSp1err,...) cnb_args = length 8 tuple, args to pass into get_cnb_vecs() #r_params = length 3 tuple, args to pass into get_r() w_params = length 2 tuple, args to pass into get_w() K_init = scalar, initial value of aggregate capital stock supplied L_init = scalar, initial value of aggregate labor r_init = scalar, initial value for interest rate w_init = scalar, initial value for wage K_d = scalar, capital demand rpath = (S,) vector, lifetime path of interest rates wpath = (S,) vector, lifetime path of wages c1_args = length 10 tuple, args to pass into c1_bSp1err() results_c1 = results object, root finder results from opt.root(c1_bSp1err,...) c1_new = scalar, updated value of optimal c1 given r_init and w_init cvec_new = (S,) vector, updated values for lifetime consumption nvec_new = (S,) vector, updated values for lifetime labor supply b_s_new = (S,) vector, updated values for lifetime wealth b_splus1_new = (S,) vector, updated values for lifetime savings (b1, b2,...bS) b_Sp1_new = scalar, updated value for savings in last period, should be arbitrarily close to zero K_new = scalar, updated K given bvec_new K_cnstr = boolean, =True if K_new <= 0 L_new = scalar, updated L given nvec_new KL_new = (2,) vector, updated K and L given bvec_new, nvec_new K_ss = scalar > 0, steady-state aggregate capital stock supplied K_d_ss = scalar > 0, steady-state aggregate capital stock demanded L_ss = scalar > 0, steady-state aggregate labor r_ss = scalar > 0, steady-state interest rate w_ss = scalar > 0, steady-state wage c1_ss = scalar > 0, steady-state consumption in first period c_ss = (S,) vector, steady-state lifetime consumption n_ss = (S,) vector, steady-state lifetime labor supply b_s_ss = (S,) vector, steady-state wealth enter period with b_splus1_ss = (S,) vector, steady-state lifetime savings (b1_ss, b2_ss, ...bS_ss) where b1_ss=0 b_Sp1_ss = scalar, steady-state savings for period after last period of life. b_Sp1_ss approx. 0 in equilibrium Y_params = length 2 tuple, (A, alpha) Y_ss = scalar > 0, steady-state aggregate output (GDP) C_ss = scalar > 0, steady-state aggregate consumption n_err_params = length 5 tuple, args to pass into get_n_errors() n_err_ss = (S,) vector, lifetime labor supply Euler errors b_err_params = length 2 tuple, args to pass into get_b_errors() b_err_ss = (S-1) vector, lifetime savings Euler errors RCerr_ss = scalar, resource constraint error ss_time = scalar, seconds elapsed to run steady-state comput'n ss_output = length 14 dict, steady-state objects {n_ss, b_ss, c_ss, b_Sp1_ss, w_ss, r_ss, K_ss, L_ss, Y_ss, C_ss, n_err_ss, b_err_ss, RCerr_ss, ss_time} FILES CREATED BY THIS FUNCTION: SS_bc.png SS_n.png RETURNS: ss_output -------------------------------------------------------------------- ''' start_time = time.clock() c1_init = init_vals (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta, r_star, SS_tol, EulDiff, hh_fsolve) = args c1_options = {'maxiter': 500} cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, EulDiff) w_params = (A, alpha, delta) K_params = (A, alpha, delta) r_ss = r_star w_ss = firms.get_w(r_ss, w_params) if hh_fsolve: b_init = np.ones((S - 1, 1)) * 0.05 n_init = np.ones((S, 1)) * 0.4 guesses = np.append(b_init, n_init) bn_params = (r_ss, w_ss, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, EulDiff) [solutions, infodict, ier, message] = \ opt.fsolve(hh.bn_solve, guesses, args=bn_params, xtol=SS_tol, full_output=True) euler_errors = infodict['fvec'] print('Max Euler errors: ', np.absolute(euler_errors).max()) b_splus1_ss = np.append(solutions[:S - 1], 0.0) n_ss = solutions[S - 1:] b_Sp1_ss = 0.0 b_s_ss = np.append(0.0, b_splus1_ss[:-1]) c_ss = hh.get_cons(r_ss, w_ss, b_s_ss, b_splus1_ss, n_ss) else: rpath = r_ss * np.ones(S) wpath = w_ss * np.ones(S) c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, rpath, wpath, EulDiff) c1_options = {'maxiter': 500} results_c1 = \ opt.root(hh.c1_bSp1err, c1_new, args=(c1_args), method='lm', tol=SS_tol, options=(c1_options)) c1_ss = results_c1.x cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, EulDiff) c_ss, n_ss, b_s_ss, b_Sp1_ss = hh.get_cnb_vecs(c1_ss, rpath, wpath, cnb_args) b_splus1_ss = np.append(b_s_ss[1:], b_Sp1_ss) L_ss = aggr.get_L_s(n_ss) K_s_ss, K_cnstr = aggr.get_K_s(b_s_ss) K_d_ss = firms.get_K_d(r_ss, L_ss, K_params) Y_params = (A, alpha) Y_ss = aggr.get_Y(Y_params, K_d_ss, L_ss) C_ss = aggr.get_C(c_ss) n_err_args = (w_ss, c_ss, sigma, l_tilde, chi_n_vec, b_ellip, upsilon, EulDiff) n_err_ss = hh.get_n_errors(n_ss, n_err_args) b_err_params = (beta, sigma) b_err_ss = hh.get_b_errors(b_err_params, r_ss, c_ss, EulDiff) NX_ss = Y_ss - C_ss - delta * K_s_ss RCerr_ss = Y_ss - C_ss - delta * K_s_ss - NX_ss ss_time = time.clock() - start_time ss_output = { 'n_ss': n_ss, 'b_s_ss': b_s_ss, 'b_splus1_ss': b_splus1_ss, 'c_ss': c_ss, 'b_Sp1_ss': b_Sp1_ss, 'w_ss': w_ss, 'r_ss': r_ss, 'K_s_ss': K_s_ss, 'K_d_ss': K_d_ss, 'L_ss': L_ss, 'Y_ss': Y_ss, 'C_ss': C_ss, 'n_err_ss': n_err_ss, 'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time } print('n_ss is: ', n_ss) print('b_splus1_ss is: ', b_splus1_ss) print('K_s_ss=', K_s_ss, 'K_d_ss=', K_d_ss, ', L_ss=', L_ss) print('r_ss=', r_ss, ', w_ss=', w_ss) print('Maximum abs. labor supply Euler error is: ', np.absolute(n_err_ss).max()) print('Maximum abs. savings Euler error is: ', np.absolute(b_err_ss).max()) print('Resource constraint error is: ', RCerr_ss) print('Net Exports = ', NX_ss) print('Output and consumption: ', Y_ss, C_ss) print('Steady-state residual savings b_Sp1 is: ', b_Sp1_ss) # Print SS computation time utils.print_time(ss_time, 'SS') if graphs: ''' ---------------------------------------------------------------- cur_path = string, path name of current directory output_fldr = string, folder in current path to save files output_dir = string, total path of images folder output_path = string, path of file name of figure to be saved age_pers = (S,) vector, ages from 1 to S ---------------------------------------------------------------- ''' # Create directory if images directory does not already exist cur_path = os.path.split(os.path.abspath(__file__))[0] output_fldr = 'images' output_dir = os.path.join(cur_path, output_fldr) if not os.access(output_dir, os.F_OK): os.makedirs(output_dir) # Plot steady-state consumption and savings distributions age_pers = np.arange(1, S + 1) fig, ax = plt.subplots() plt.plot(age_pers, c_ss, marker='D', label='Consumption') plt.plot(age_pers, b_splus1_ss, marker='D', label='Savings') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state consumption and savings', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Units of consumption') plt.xlim((0, S + 1)) # plt.ylim((-1.0, 1.15 * (b_ss.max()))) plt.legend(loc='upper left') output_path = os.path.join(output_dir, 'SS_bc') plt.savefig(output_path) # plt.show() plt.close() # Plot steady-state labor supply distributions fig, ax = plt.subplots() plt.plot(age_pers, n_ss, marker='D', label='Labor supply') # for the minor ticks, use no labels; default NullFormatter minorLocator = MultipleLocator(1) ax.xaxis.set_minor_locator(minorLocator) plt.grid(b=True, which='major', color='0.65', linestyle='-') # plt.title('Steady-state labor supply', fontsize=20) plt.xlabel(r'Age $s$') plt.ylabel(r'Labor supply') plt.xlim((0, S + 1)) # plt.ylim((-0.1, 1.15 * (n_ss.max()))) plt.legend(loc='upper right') output_path = os.path.join(output_dir, 'SS_n') plt.savefig(output_path) # plt.show() plt.close() return ss_output
def get_SS_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 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 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() Kss_init, Lss_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 KL_init = np.array([Kss_init, Lss_init]) c1_options = {'maxiter': 500} r_params = (A, alpha, delta) w_params = (A, alpha) 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) rpath = r_init * np.ones(S) wpath = w_init * np.ones(S) cmat = np.zeros((S, J)) nmat = np.zeros((S, J)) bmat = np.zeros((S, J)) b_Sp1_vec = np.zeros(J) for j in range(J): c1_args = (0.0, emat[:, j], beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, rpath, wpath, EulDiff) results_c1 = \ opt.root(hh.c1_bSp1err, c1_init, args=(c1_args), method='lm', tol=SS_tol, options=(c1_options)) c1 = results_c1.x cnb_args = (0.0, emat[:, j], beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, EulDiff) cmat[:, j], nmat[:, j], bmat[:, j], b_Sp1_vec[j] = \ hh.get_cnb_vecs(c1, rpath, wpath, cnb_args) K_new, K_cnstr = aggr.get_K(bmat, lambdas) L_new = aggr.get_L(nmat, emat, lambdas) 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 print('SS Iteration=', iter_SS, ', SS Distance=', '%10.4e' % (dist_SS), ',K:', '%10.4e' % (K_new), 'L:', '%10.4e' % (L_new)) K_ss, L_ss = KL_init r_ss = firms.get_r(r_params, K_ss, L_ss) w_ss = firms.get_w(w_params, K_ss, L_ss) c_ss = cmat n_ss = nmat b_ss = bmat b_Sp1_ss = b_Sp1_vec Y_params = (A, alpha) Y_ss = aggr.get_Y(Y_params, K_ss, L_ss) C_ss = aggr.get_C(c_ss, lambdas) n_err_ss = np.zeros((S, J)) b_err_ss = np.zeros((S - 1, J)) for j in range(J): n_err_params = (emat[:, j], sigma, l_tilde, chi_n_vec, b_ellip, upsilon) n_err_ss[:, j] = hh.get_n_errors(n_err_params, w_ss, c_ss[:, j], n_ss[:, j], EulDiff) b_err_params = (beta, sigma) b_err_ss[:, j] = hh.get_b_errors(b_err_params, r_ss, c_ss[:, j], EulDiff) 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