def test_pct_diff_func(): ''' Test of utils.pct_diff_func(), which returns the absolute value of the percentage difference between to arrays or scalars ''' simul = np.array([110, 23.4, -5.0]) data = np.array([100, 44.4, 6.0]) expected = np.array([0.1, 0.47297297297297297, 1.8333333333333333]) pct_diff = utils.pct_diff_func(simul, data) assert np.allclose(expected, pct_diff)
def run_TPI(p, client=None): ''' Solve for transition path equilibrium of OG-USA. Args: p (OG-USA Specifications object): model parameters client (Dask client object): client Returns: output (dictionary): dictionary with transition path solution results ''' # unpack tuples of parameters initial_values, ss_vars, theta, baseline_values = get_initial_SS_values(p) (B0, b_sinit, b_splus1init, factor, initial_b, initial_n) =\ initial_values (TRbaseline, Gbaseline, D0_baseline) = baseline_values print('Government spending breakpoints are tG1: ', p.tG1, '; and tG2:', p.tG2) # Initialize guesses at time paths # Make array of initial guesses for labor supply and savings guesses_b = utils.get_initial_path(initial_b, ss_vars['bssmat_splus1'], p, 'ratio') guesses_n = utils.get_initial_path(initial_n, ss_vars['nssmat'], p, 'ratio') b_mat = guesses_b n_mat = guesses_n ind = np.arange(p.S) # Get path for aggregate savings and labor supply` L_init = np.ones((p.T + p.S, )) * ss_vars['Lss'] B_init = np.ones((p.T + p.S, )) * ss_vars['Bss'] L_init[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B_init[1:p.T] = aggr.get_B(b_mat[:p.T], p, 'TPI', False)[:p.T - 1] B_init[0] = B0 K_init = B_init * ss_vars['Kss'] / ss_vars['Bss'] K = K_init K_d = K_init * ss_vars['K_d_ss'] / ss_vars['Kss'] K_f = K_init * ss_vars['K_f_ss'] / ss_vars['Kss'] L = L_init B = B_init Y = np.zeros_like(K) Y[:p.T] = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') Y[p.T:] = ss_vars['Yss'] r = np.zeros_like(Y) r[:p.T] = firm.get_r(Y[:p.T], K[:p.T], p, 'TPI') r[p.T:] = ss_vars['rss'] # For case where economy is small open econ r[p.zeta_K == 1] = p.world_int_rate[p.zeta_K == 1] # Compute other interest rates r_gov = fiscal.get_r_gov(r, p) r_hh = aggr.get_r_hh(r, r_gov, K, ss_vars['Dss']) # compute w w = np.zeros_like(r) w[:p.T] = firm.get_w_from_r(r[:p.T], p, 'TPI') w[p.T:] = ss_vars['wss'] # initial guesses at fiscal vars if p.budget_balance: if np.abs(ss_vars['TR_ss']) < 1e-13: TR_ss2 = 0.0 # sometimes SS is very small but not zero, # even if taxes are zero, this get's rid of the # approximation error, which affects the pct changes below else: TR_ss2 = ss_vars['TR_ss'] TR = np.ones(p.T + p.S) * TR_ss2 total_tax_revenue = TR - ss_vars['agg_pension_outlays'] G = np.zeros(p.T + p.S) D = np.zeros(p.T + p.S) D_d = np.zeros(p.T + p.S) D_f = np.zeros(p.T + p.S) else: if p.baseline_spending: TR = TRbaseline G = Gbaseline G[p.T:] = ss_vars['Gss'] else: TR = p.alpha_T * Y G = np.ones(p.T + p.S) * ss_vars['Gss'] D = np.ones(p.T + p.S) * ss_vars['Dss'] D_d = D * ss_vars['D_d_ss'] / ss_vars['Dss'] D_f = D * ss_vars['D_f_ss'] / ss_vars['Dss'] total_tax_revenue = np.ones(p.T + p.S) * ss_vars['total_tax_revenue'] # Initialize bequests BQ0 = aggr.get_BQ(r_hh[0], initial_b, None, p, 'SS', True) if not p.use_zeta: BQ = np.zeros((p.T + p.S, p.J)) for j in range(p.J): BQ[:, j] = (list(np.linspace(BQ0[j], ss_vars['BQss'][j], p.T)) + [ss_vars['BQss'][j]] * p.S) BQ = np.array(BQ) else: BQ = (list(np.linspace(BQ0, ss_vars['BQss'], p.T)) + [ss_vars['BQss']] * p.S) BQ = np.array(BQ) TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((p.T, 2 * p.S, p.J)) TPIdist_vec = np.zeros(p.maxiter) # TPI loop while (TPIiter < p.maxiter) and (TPIdist >= p.mindist_TPI): r_gov[:p.T] = fiscal.get_r_gov(r[:p.T], p) if not p.budget_balance: K[:p.T] = firm.get_K_from_Y(Y[:p.T], r[:p.T], p, 'TPI') r_hh[:p.T] = aggr.get_r_hh(r[:p.T], r_gov[:p.T], K[:p.T], D[:p.T]) outer_loop_vars = (r, w, r_hh, BQ, TR, theta) euler_errors = np.zeros((p.T, 2 * p.S, p.J)) lazy_values = [] for j in range(p.J): guesses = (guesses_b[:, :, j], guesses_n[:, :, j]) lazy_values.append( delayed(inner_loop)(guesses, outer_loop_vars, initial_values, j, ind, p)) if client: futures = client.compute(lazy_values, num_workers=p.num_workers) results = client.gather(futures) else: results = results = compute(*lazy_values, scheduler=dask.multiprocessing.get, num_workers=p.num_workers) for j, result in enumerate(results): euler_errors[:, :, j], b_mat[:, :, j], n_mat[:, :, j] = result bmat_s = np.zeros((p.T, p.S, p.J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:p.T - 1, :-1, :] bmat_splus1 = np.zeros((p.T, p.S, p.J)) bmat_splus1[:, :, :] = b_mat[:p.T, :, :] etr_params_4D = np.tile( p.etr_params.reshape(p.T, p.S, 1, p.etr_params.shape[2]), (1, 1, p.J, 1)) bqmat = household.get_bq(BQ, None, p, 'TPI') trmat = household.get_tr(TR, None, p, 'TPI') tax_mat = tax.net_taxes(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], factor, trmat[:p.T, :, :], theta, 0, None, False, 'TPI', p.e, etr_params_4D, p) r_hh_path = utils.to_timepath_shape(r_hh) wpath = utils.to_timepath_shape(w) c_mat = household.get_cons(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s, bmat_splus1, n_mat[:p.T, :, :], bqmat[:p.T, :, :], tax_mat, p.e, p.tau_c[:p.T, :, :], p) y_before_tax_mat = household.get_y(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], p) (total_tax_rev, iit_payroll_tax_revenue, agg_pension_outlays, bequest_tax_revenue, wealth_tax_revenue, cons_tax_revenue, business_tax_revenue, payroll_tax_revenue, iit_revenue) = aggr.revenue(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], c_mat[:p.T, :, :], Y[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_tax_revenue[:p.T] = total_tax_rev dg_fixed_values = (Y, total_tax_revenue, agg_pension_outlays, TR, Gbaseline, D0_baseline) (Dnew, G[:p.T], D_d[:p.T], D_f[:p.T], new_borrowing, debt_service, new_borrowing_f) =\ fiscal.D_G_path(r_gov, dg_fixed_values, p) L[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B[1:p.T] = aggr.get_B(bmat_splus1[:p.T], p, 'TPI', False)[:p.T - 1] K_demand_open = firm.get_K(L[:p.T], p.world_int_rate[:p.T], p, 'TPI') K[:p.T], K_d[:p.T], K_f[:p.T] = aggr.get_K_splits( B[:p.T], K_demand_open, D_d[:p.T], p.zeta_K[:p.T]) Ynew = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') rnew = r.copy() rnew[:p.T] = firm.get_r(Ynew[:p.T], K[:p.T], p, 'TPI') # For case where economy is small open econ r[p.zeta_K == 1] = p.world_int_rate[p.zeta_K == 1] r_gov_new = fiscal.get_r_gov(rnew, p) r_hh_new = aggr.get_r_hh(rnew[:p.T], r_gov_new[:p.T], K[:p.T], Dnew[:p.T]) # compute w wnew = firm.get_w_from_r(rnew[:p.T], p, 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, p.S, p.J)), b_mat[:p.T - 1, :, :], axis=0) BQnew = aggr.get_BQ(r_hh_new[:p.T], b_mat_shift, None, p, 'TPI', False) bqmat_new = household.get_bq(BQnew, None, p, 'TPI') (total_tax_rev, iit_payroll_tax_revenue, agg_pension_outlays, bequest_tax_revenue, wealth_tax_revenue, cons_tax_revenue, business_tax_revenue, payroll_tax_revenue, iit_revenue) = aggr.revenue(r_hh_new[:p.T], wnew[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat_new[:p.T, :, :], c_mat[:p.T, :, :], Ynew[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_tax_revenue[:p.T] = total_tax_rev TR_new = fiscal.get_TR(Ynew[:p.T], TR[:p.T], G[:p.T], total_tax_revenue[:p.T], agg_pension_outlays[:p.T], p, 'TPI') # update vars for next iteration w[:p.T] = wnew[:p.T] r[:p.T] = utils.convex_combo(rnew[:p.T], r[:p.T], p.nu) BQ[:p.T] = utils.convex_combo(BQnew[:p.T], BQ[:p.T], p.nu) D[:p.T] = Dnew[:p.T] Y[:p.T] = utils.convex_combo(Ynew[:p.T], Y[:p.T], p.nu) if not p.baseline_spending: TR[:p.T] = utils.convex_combo(TR_new[:p.T], TR[:p.T], p.nu) guesses_b = utils.convex_combo(b_mat, guesses_b, p.nu) guesses_n = utils.convex_combo(n_mat, guesses_n, p.nu) print('r diff: ', (rnew[:p.T] - r[:p.T]).max(), (rnew[:p.T] - r[:p.T]).min()) print('BQ diff: ', (BQnew[:p.T] - BQ[:p.T]).max(), (BQnew[:p.T] - BQ[:p.T]).min()) print('TR diff: ', (TR_new[:p.T] - TR[:p.T]).max(), (TR_new[:p.T] - TR[:p.T]).min()) print('Y diff: ', (Ynew[:p.T] - Y[:p.T]).max(), (Ynew[:p.T] - Y[:p.T]).min()) if not p.baseline_spending: if TR.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(TR_new[:p.T], TR[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(np.abs(TR[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(Ynew[:p.T], Y[:p.T]))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print('Iteration:', TPIiter) print('\tDistance:', TPIdist) # Compute effective and marginal tax rates for all agents mtrx_params_4D = np.tile( p.mtrx_params.reshape(p.T, p.S, 1, p.mtrx_params.shape[2]), (1, 1, p.J, 1)) mtry_params_4D = np.tile( p.mtry_params.reshape(p.T, p.S, 1, p.mtry_params.shape[2]), (1, 1, p.J, 1)) e_3D = np.tile(p.e.reshape(1, p.S, p.J), (p.T, 1, 1)) mtry_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, True, e_3D, etr_params_4D, mtry_params_4D, p) mtrx_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, False, e_3D, etr_params_4D, mtrx_params_4D, p) etr_path = tax.ETR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, e_3D, etr_params_4D, p) C = aggr.get_C(c_mat, p, 'TPI') # Note that implicity in this computation is that immigrants' # wealth is all in the form of private capital I_d = aggr.get_I(bmat_splus1[:p.T], K_d[1:p.T + 1], K_d[:p.T], p, 'TPI') I = aggr.get_I(bmat_splus1[:p.T], K[1:p.T + 1], K[:p.T], p, 'TPI') # solve resource constraint # foreign debt service costs debt_service_f = fiscal.get_debt_service_f(r_hh, D_f) RC_error = aggr.resource_constraint(Y[:p.T - 1], C[:p.T - 1], G[:p.T - 1], I_d[:p.T - 1], K_f[:p.T - 1], new_borrowing_f[:p.T - 1], debt_service_f[:p.T - 1], r_hh[:p.T - 1], p) # Compute total investment (not just domestic) I_total = aggr.get_I(None, K[1:p.T + 1], K[:p.T], p, 'total_tpi') # Compute resource constraint error rce_max = np.amax(np.abs(RC_error)) print('Max absolute value resource constraint error:', rce_max) print('Checking time path for violations of constraints.') for t in range(p.T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_mat[t], t, p.ltilde) eul_savings = euler_errors[:, :p.S, :].max(1).max(1) eul_laborleisure = euler_errors[:, p.S:, :].max(1).max(1) print('Max Euler error, savings: ', eul_savings) print('Max Euler error labor supply: ', eul_laborleisure) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y[:p.T], 'B': B, 'K': K, 'K_f': K_f, 'K_d': K_d, 'L': L, 'C': C, 'I': I, 'I_total': I_total, 'I_d': I_d, 'BQ': BQ, 'total_tax_revenue': total_tax_revenue, 'business_tax_revenue': business_tax_revenue, 'iit_payroll_tax_revenue': iit_payroll_tax_revenue, 'iit_revenue': iit_revenue, 'payroll_tax_revenue': payroll_tax_revenue, 'TR': TR, 'agg_pension_outlays': agg_pension_outlays, 'bequest_tax_revenue': bequest_tax_revenue, 'wealth_tax_revenue': wealth_tax_revenue, 'cons_tax_revenue': cons_tax_revenue, 'G': G, 'D': D, 'D_f': D_f, 'D_d': D_d, 'r': r, 'r_gov': r_gov, 'r_hh': r_hh, 'w': w, 'bmat_splus1': bmat_splus1, 'bmat_s': bmat_s[:p.T, :, :], 'n_mat': n_mat[:p.T, :, :], 'c_path': c_mat, 'bq_path': bqmat, 'tr_path': trmat, 'y_before_tax_mat': y_before_tax_mat, 'tax_path': tax_mat, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'resource_constraint_error': RC_error, 'new_borrowing_f': new_borrowing_f, 'debt_service_f': debt_service_f, 'etr_path': etr_path, 'mtrx_path': mtrx_path, 'mtry_path': mtry_path } tpi_dir = os.path.join(p.output_base, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") with open(tpi_vars, "wb") as f: pickle.dump(output, f) if np.any(G) < 0: print('Government spending is negative along transition path' + ' to satisfy budget') if (((TPIiter >= p.maxiter) or (np.absolute(TPIdist) > p.mindist_TPI)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found' + ' (TPIdist)') if ((np.any(np.absolute(RC_error) >= p.mindist_TPI * 10)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(RC_error)') if ((np.any(np.absolute(eul_savings) >= p.mindist_TPI) or (np.any(np.absolute(eul_laborleisure) > p.mindist_TPI))) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(eulers)') return output
def run_TPI(p, client=None): # unpack tuples of parameters initial_values, SS_values, baseline_values = get_initial_SS_values(p) (B0, b_sinit, b_splus1init, factor, initial_b, initial_n, D0) = initial_values (Kss, Bss, Lss, rss, wss, BQss, T_Hss, total_revenue_ss, bssmat_splus1, nssmat, Yss, Gss, theta) = SS_values (T_Hbaseline, Gbaseline) = baseline_values print('Government spending breakpoints are tG1: ', p.tG1, '; and tG2:', p.tG2) # Initialize guesses at time paths # Make array of initial guesses for labor supply and savings domain = np.linspace(0, p.T, p.T) domain2 = np.tile(domain.reshape(p.T, 1, 1), (1, p.S, p.J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, p.T).reshape(p.T, 1, 1), (1, p.S, p.J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) b_mat = guesses_b # np.zeros((p.T + p.S, p.S, p.J)) n_mat = guesses_n # np.zeros((p.T + p.S, p.S, p.J)) ind = np.arange(p.S) L_init = np.ones((p.T + p.S, )) * Lss B_init = np.ones((p.T + p.S, )) * Bss L_init[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B_init[1:p.T] = aggr.get_K(b_mat[:p.T], p, 'TPI', False)[:p.T - 1] B_init[0] = B0 if not p.small_open: if p.budget_balance: K_init = B_init else: K_init = B_init * Kss / Bss else: K_init = firm.get_K(L_init, p.firm_r, p, 'TPI') K = K_init L = L_init B = B_init Y = np.zeros_like(K) Y[:p.T] = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') Y[p.T:] = Yss r = np.zeros_like(Y) if not p.small_open: r[:p.T] = firm.get_r(Y[:p.T], K[:p.T], p, 'TPI') r[p.T:] = rss else: r = p.firm_r # compute w w = np.zeros_like(r) w[:p.T] = firm.get_w_from_r(r[:p.T], p, 'TPI') w[p.T:] = wss r_gov = fiscal.get_r_gov(r, p) if p.budget_balance: r_hh = r else: r_hh = aggr.get_r_hh(r, r_gov, K, p.debt_ratio_ss * Y) if p.small_open: r_hh = p.hh_r BQ0 = aggr.get_BQ(r[0], initial_b, None, p, 'SS', True) if not p.use_zeta: BQ = np.zeros((p.T + p.S, p.J)) for j in range(p.J): BQ[:, j] = (list(np.linspace(BQ0[j], BQss[j], p.T)) + [BQss[j]] * p.S) BQ = np.array(BQ) else: BQ = (list(np.linspace(BQ0, BQss, p.T)) + [BQss] * p.S) BQ = np.array(BQ) if p.budget_balance: if np.abs(T_Hss) < 1e-13: T_Hss2 = 0.0 # sometimes SS is very small but not zero, # even if taxes are zero, this get's rid of the approximation # error, which affects the perc changes below else: T_Hss2 = T_Hss T_H = np.ones(p.T + p.S) * T_Hss2 total_revenue = T_H G = np.zeros(p.T + p.S) elif not p.baseline_spending: T_H = p.alpha_T * Y elif p.baseline_spending: T_H = T_Hbaseline T_H_new = p.T_H # Need to set T_H_new for later reference G = Gbaseline G_0 = Gbaseline[0] # Initialize some starting value if p.budget_balance: D = 0.0 * Y else: D = p.debt_ratio_ss * Y TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((p.T, 2 * p.S, p.J)) TPIdist_vec = np.zeros(p.maxiter) print('analytical mtrs in tpi = ', p.analytical_mtrs) print('tax function type in tpi = ', p.tax_func_type) # TPI loop while (TPIiter < p.maxiter) and (TPIdist >= p.mindist_TPI): r_gov[:p.T] = fiscal.get_r_gov(r[:p.T], p) if p.budget_balance: r_hh[:p.T] = r[:p.T] else: K[:p.T] = firm.get_K_from_Y(Y[:p.T], r[:p.T], p, 'TPI') r_hh[:p.T] = aggr.get_r_hh(r[:p.T], r_gov[:p.T], K[:p.T], D[:p.T]) if p.small_open: r_hh[:p.T] = p.hh_r[:p.T] outer_loop_vars = (r, w, r_hh, BQ, T_H, theta) euler_errors = np.zeros((p.T, 2 * p.S, p.J)) lazy_values = [] for j in range(p.J): guesses = (guesses_b[:, :, j], guesses_n[:, :, j]) lazy_values.append( delayed(inner_loop)(guesses, outer_loop_vars, initial_values, j, ind, p)) results = compute(*lazy_values, scheduler=dask.multiprocessing.get, num_workers=p.num_workers) for j, result in enumerate(results): euler_errors[:, :, j], b_mat[:, :, j], n_mat[:, :, j] = result bmat_s = np.zeros((p.T, p.S, p.J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:p.T - 1, :-1, :] bmat_splus1 = np.zeros((p.T, p.S, p.J)) bmat_splus1[:, :, :] = b_mat[:p.T, :, :] L[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B[1:p.T] = aggr.get_K(bmat_splus1[:p.T], p, 'TPI', False)[:p.T - 1] if np.any(B) < 0: print('B has negative elements. B[0:9]:', B[0:9]) print('B[T-2:T]:', B[p.T - 2, p.T]) etr_params_4D = np.tile( p.etr_params.reshape(p.T, p.S, 1, p.etr_params.shape[2]), (1, 1, p.J, 1)) bqmat = household.get_bq(BQ, None, p, 'TPI') tax_mat = tax.total_taxes(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], factor, T_H[:p.T], theta, 0, None, False, 'TPI', p.e, etr_params_4D, p) r_hh_path = utils.to_timepath_shape(r_hh, p) wpath = utils.to_timepath_shape(w, p) c_mat = household.get_cons(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s, bmat_splus1, n_mat[:p.T, :, :], bqmat[:p.T, :, :], tax_mat, p.e, p.tau_c[:p.T, :, :], p) if not p.small_open: if p.budget_balance: K[:p.T] = B[:p.T] else: if not p.baseline_spending: Y = T_H / p.alpha_T # maybe unecessary (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], c_mat[:p.T, :, :], Y[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue = np.array( list(total_rev) + [total_revenue_ss] * p.S) # set intial debt value if p.baseline: D_0 = p.initial_debt_ratio * Y[0] else: D_0 = D0 if not p.baseline_spending: G_0 = p.alpha_G[0] * Y[0] dg_fixed_values = (Y, total_revenue, T_H, D_0, G_0) Dnew, G = fiscal.D_G_path(r_gov, dg_fixed_values, Gbaseline, p) K[:p.T] = B[:p.T] - Dnew[:p.T] if np.any(K < 0): print('K has negative elements. Setting them ' + 'positive to prevent NAN.') K[:p.T] = np.fmax(K[:p.T], 0.05 * B[:p.T]) else: K[:p.T] = firm.get_K(L[:p.T], p.firm_r[:p.T], p, 'TPI') Ynew = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') if not p.small_open: rnew = firm.get_r(Ynew[:p.T], K[:p.T], p, 'TPI') else: rnew = r.copy() r_gov_new = fiscal.get_r_gov(rnew, p) if p.budget_balance: r_hh_new = rnew[:p.T] else: r_hh_new = aggr.get_r_hh(rnew, r_gov_new, K[:p.T], Dnew[:p.T]) if p.small_open: r_hh_new = p.hh_r[:p.T] # compute w wnew = firm.get_w_from_r(rnew[:p.T], p, 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, p.S, p.J)), b_mat[:p.T - 1, :, :], axis=0) BQnew = aggr.get_BQ(r_hh_new[:p.T], b_mat_shift, None, p, 'TPI', False) bqmat_new = household.get_bq(BQnew, None, p, 'TPI') (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh_new[:p.T], wnew[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat_new[:p.T, :, :], c_mat[:p.T, :, :], Ynew[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue = np.array(list(total_rev) + [total_revenue_ss] * p.S) if p.budget_balance: T_H_new = total_revenue elif not p.baseline_spending: T_H_new = p.alpha_T[:p.T] * Ynew[:p.T] # If baseline_spending==True, no need to update T_H, it's fixed if p.small_open and not p.budget_balance: # Loop through years to calculate debt and gov't spending. # This is done earlier when small_open=False. if p.baseline: D_0 = p.initial_debt_ratio * Y[0] else: D_0 = D0 if not p.baseline_spending: G_0 = p.alpha_G[0] * Ynew[0] dg_fixed_values = (Ynew, total_revenue, T_H, D_0, G_0) Dnew, G = fiscal.D_G_path(r_gov_new, dg_fixed_values, Gbaseline, p) if p.budget_balance: Dnew = D w[:p.T] = wnew[:p.T] r[:p.T] = utils.convex_combo(rnew[:p.T], r[:p.T], p.nu) BQ[:p.T] = utils.convex_combo(BQnew[:p.T], BQ[:p.T], p.nu) D = Dnew Y[:p.T] = utils.convex_combo(Ynew[:p.T], Y[:p.T], p.nu) if not p.baseline_spending: T_H[:p.T] = utils.convex_combo(T_H_new[:p.T], T_H[:p.T], p.nu) guesses_b = utils.convex_combo(b_mat, guesses_b, p.nu) guesses_n = utils.convex_combo(n_mat, guesses_n, p.nu) print('r diff: ', (rnew[:p.T] - r[:p.T]).max(), (rnew[:p.T] - r[:p.T]).min()) print('BQ diff: ', (BQnew[:p.T] - BQ[:p.T]).max(), (BQnew[:p.T] - BQ[:p.T]).min()) print('T_H diff: ', (T_H_new[:p.T] - T_H[:p.T]).max(), (T_H_new[:p.T] - T_H[:p.T]).min()) print('Y diff: ', (Ynew[:p.T] - Y[:p.T]).max(), (Ynew[:p.T] - Y[:p.T]).min()) if not p.baseline_spending: if T_H.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(utils.pct_diff_func(T_H_new[:p.T], T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(np.abs(T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(utils.pct_diff_func(Ynew[:p.T], Y[:p.T]))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print('Iteration:', TPIiter) print('\tDistance:', TPIdist) # Compute effective and marginal tax rates for all agents mtrx_params_4D = np.tile( p.mtrx_params.reshape(p.T, p.S, 1, p.mtrx_params.shape[2]), (1, 1, p.J, 1)) mtry_params_4D = np.tile( p.mtry_params.reshape(p.T, p.S, 1, p.mtry_params.shape[2]), (1, 1, p.J, 1)) e_3D = np.tile(p.e.reshape(1, p.S, p.J), (p.T, 1, 1)) mtry_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, True, e_3D, etr_params_4D, mtry_params_4D, p) mtrx_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, False, e_3D, etr_params_4D, mtrx_params_4D, p) etr_path = tax.ETR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, e_3D, etr_params_4D, p) C = aggr.get_C(c_mat, p, 'TPI') if not p.small_open: I = aggr.get_I(bmat_splus1[:p.T], K[1:p.T + 1], K[:p.T], p, 'TPI') rc_error = Y[:p.T] - C[:p.T] - I[:p.T] - G[:p.T] else: I = ((1 + np.squeeze(np.hstack( (p.g_n[1:p.T], p.g_n_ss)))) * np.exp(p.g_y) * K[1:p.T + 1] - (1.0 - p.delta) * K[:p.T]) BI = aggr.get_I(bmat_splus1[:p.T], B[1:p.T + 1], B[:p.T], p, 'TPI') new_borrowing = (D[1:p.T] * (1 + p.g_n[1:p.T]) * np.exp(p.g_y) - D[:p.T - 1]) rc_error = (Y[:p.T - 1] + new_borrowing - (C[:p.T - 1] + BI[:p.T - 1] + G[:p.T - 1]) + (p.hh_r[:p.T - 1] * B[:p.T - 1] - (p.delta + p.firm_r[:p.T - 1]) * K[:p.T - 1] - p.hh_r[:p.T - 1] * D[:p.T - 1])) # Compute total investment (not just domestic) I_total = ((1 + p.g_n[:p.T]) * np.exp(p.g_y) * K[1:p.T + 1] - (1.0 - p.delta) * K[:p.T]) rce_max = np.amax(np.abs(rc_error)) print('Max absolute value resource constraint error:', rce_max) print('Checking time path for violations of constraints.') for t in range(p.T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_mat[t], t, p.ltilde) eul_savings = euler_errors[:, :p.S, :].max(1).max(1) eul_laborleisure = euler_errors[:, p.S:, :].max(1).max(1) print('Max Euler error, savings: ', eul_savings) print('Max Euler error labor supply: ', eul_laborleisure) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y[:p.T], 'B': B, 'K': K, 'L': L, 'C': C, 'I': I, 'I_total': I_total, 'BQ': BQ, 'total_revenue': total_revenue, 'business_revenue': business_revenue, 'IITpayroll_revenue': T_Ipath, 'T_H': T_H, 'T_P': T_Ppath, 'T_BQ': T_BQpath, 'T_W': T_Wpath, 'T_C': T_Cpath, 'G': G, 'D': D, 'r': r, 'r_gov': r_gov, 'r_hh': r_hh, 'w': w, 'bmat_splus1': bmat_splus1, 'bmat_s': bmat_s[:p.T, :, :], 'n_mat': n_mat[:p.T, :, :], 'c_path': c_mat, 'bq_path': bqmat, 'tax_path': tax_mat, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'resource_constraint_error': rc_error, 'etr_path': etr_path, 'mtrx_path': mtrx_path, 'mtry_path': mtry_path } tpi_dir = os.path.join(p.output_base, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb")) if np.any(G) < 0: print('Government spending is negative along transition path' + ' to satisfy budget') if (((TPIiter >= p.maxiter) or (np.absolute(TPIdist) > p.mindist_TPI)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found' + ' (TPIdist)') if ((np.any(np.absolute(rc_error) >= p.mindist_TPI * 10)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(rc_error)') if ((np.any(np.absolute(eul_savings) >= p.mindist_TPI) or (np.any(np.absolute(eul_laborleisure) > p.mindist_TPI))) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(eulers)') return output
def run_TPI(p, client=None): # unpack tuples of parameters initial_values, SS_values, baseline_values = get_initial_SS_values(p) (B0, b_sinit, b_splus1init, factor, initial_b, initial_n, D0) = initial_values (Kss, Bss, Lss, rss, wss, BQss, T_Hss, total_revenue_ss, bssmat_splus1, nssmat, Yss, Gss, theta) = SS_values (T_Hbaseline, Gbaseline) = baseline_values print('Government spending breakpoints are tG1: ', p.tG1, '; and tG2:', p.tG2) # Initialize guesses at time paths # Make array of initial guesses for labor supply and savings domain = np.linspace(0, p.T, p.T) domain2 = np.tile(domain.reshape(p.T, 1, 1), (1, p.S, p.J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, p.T).reshape(p.T, 1, 1), (1, p.S, p.J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) b_mat = guesses_b # np.zeros((p.T + p.S, p.S, p.J)) n_mat = guesses_n # np.zeros((p.T + p.S, p.S, p.J)) ind = np.arange(p.S) L_init = np.ones((p.T + p.S,)) * Lss B_init = np.ones((p.T + p.S,)) * Bss L_init[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B_init[1:p.T] = aggr.get_K(b_mat[:p.T], p, 'TPI', False)[:p.T - 1] B_init[0] = B0 if not p.small_open: if p.budget_balance: K_init = B_init else: K_init = B_init * Kss / Bss else: K_init = firm.get_K(L_init, p.firm_r, p, 'TPI') K = K_init L = L_init B = B_init Y = np.zeros_like(K) Y[:p.T] = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') Y[p.T:] = Yss r = np.zeros_like(Y) if not p.small_open: r[:p.T] = firm.get_r(Y[:p.T], K[:p.T], p, 'TPI') r[p.T:] = rss else: r = p.firm_r # compute w w = np.zeros_like(r) w[:p.T] = firm.get_w_from_r(r[:p.T], p, 'TPI') w[p.T:] = wss r_gov = fiscal.get_r_gov(r, p) if p.budget_balance: r_hh = r else: r_hh = aggr.get_r_hh(r, r_gov, K, p.debt_ratio_ss * Y) if p.small_open: r_hh = p.hh_r BQ0 = aggr.get_BQ(r[0], initial_b, None, p, 'SS', True) if not p.use_zeta: BQ = np.zeros((p.T + p.S, p.J)) for j in range(p.J): BQ[:, j] = (list(np.linspace(BQ0[j], BQss[j], p.T)) + [BQss[j]] * p.S) BQ = np.array(BQ) else: BQ = (list(np.linspace(BQ0, BQss, p.T)) + [BQss] * p.S) BQ = np.array(BQ) if p.budget_balance: if np.abs(T_Hss) < 1e-13: T_Hss2 = 0.0 # sometimes SS is very small but not zero, # even if taxes are zero, this get's rid of the approximation # error, which affects the perc changes below else: T_Hss2 = T_Hss T_H = np.ones(p.T + p.S) * T_Hss2 total_revenue = T_H G = np.zeros(p.T + p.S) elif not p.baseline_spending: T_H = p.alpha_T * Y elif p.baseline_spending: T_H = T_Hbaseline T_H_new = p.T_H # Need to set T_H_new for later reference G = Gbaseline G_0 = Gbaseline[0] # Initialize some starting value if p.budget_balance: D = 0.0 * Y else: D = p.debt_ratio_ss * Y TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((p.T, 2 * p.S, p.J)) TPIdist_vec = np.zeros(p.maxiter) print('analytical mtrs in tpi = ', p.analytical_mtrs) print('tax function type in tpi = ', p.tax_func_type) # TPI loop while (TPIiter < p.maxiter) and (TPIdist >= p.mindist_TPI): r_gov[:p.T] = fiscal.get_r_gov(r[:p.T], p) if p.budget_balance: r_hh[:p.T] = r[:p.T] else: K[:p.T] = firm.get_K_from_Y(Y[:p.T], r[:p.T], p, 'TPI') r_hh[:p.T] = aggr.get_r_hh(r[:p.T], r_gov[:p.T], K[:p.T], D[:p.T]) if p.small_open: r_hh[:p.T] = p.hh_r[:p.T] outer_loop_vars = (r, w, r_hh, BQ, T_H, theta) euler_errors = np.zeros((p.T, 2 * p.S, p.J)) lazy_values = [] for j in range(p.J): guesses = (guesses_b[:, :, j], guesses_n[:, :, j]) lazy_values.append( delayed(inner_loop)(guesses, outer_loop_vars, initial_values, j, ind, p)) results = compute(*lazy_values, scheduler=dask.multiprocessing.get, num_workers=p.num_workers) for j, result in enumerate(results): euler_errors[:, :, j], b_mat[:, :, j], n_mat[:, :, j] = result bmat_s = np.zeros((p.T, p.S, p.J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:p.T-1, :-1, :] bmat_splus1 = np.zeros((p.T, p.S, p.J)) bmat_splus1[:, :, :] = b_mat[:p.T, :, :] L[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B[1:p.T] = aggr.get_K(bmat_splus1[:p.T], p, 'TPI', False)[:p.T - 1] if np.any(B) < 0: print('B has negative elements. B[0:9]:', B[0:9]) print('B[T-2:T]:', B[p.T - 2, p.T]) etr_params_4D = np.tile( p.etr_params.reshape(p.T, p.S, 1, p.etr_params.shape[2]), (1, 1, p.J, 1)) bqmat = household.get_bq(BQ, None, p, 'TPI') tax_mat = tax.total_taxes(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], factor, T_H[:p.T], theta, 0, None, False, 'TPI', p.e, etr_params_4D, p) r_hh_path = utils.to_timepath_shape(r_hh, p) wpath = utils.to_timepath_shape(w, p) c_mat = household.get_cons(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s, bmat_splus1, n_mat[:p.T, :, :], bqmat[:p.T, :, :], tax_mat, p.e, p.tau_c[:p.T, :, :], p) if not p.small_open: if p.budget_balance: K[:p.T] = B[:p.T] else: if not p.baseline_spending: Y = T_H / p.alpha_T # maybe unecessary (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], c_mat[:p.T, :, :], Y[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue = np.array(list(total_rev) + [total_revenue_ss] * p.S) # set intial debt value if p.baseline: D_0 = p.initial_debt_ratio * Y[0] else: D_0 = D0 if not p.baseline_spending: G_0 = p.alpha_G[0] * Y[0] dg_fixed_values = (Y, total_revenue, T_H, D_0, G_0) Dnew, G = fiscal.D_G_path(r_gov, dg_fixed_values, Gbaseline, p) K[:p.T] = B[:p.T] - Dnew[:p.T] if np.any(K < 0): print('K has negative elements. Setting them ' + 'positive to prevent NAN.') K[:p.T] = np.fmax(K[:p.T], 0.05 * B[:p.T]) else: K[:p.T] = firm.get_K(L[:p.T], p.firm_r[:p.T], p, 'TPI') Ynew = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') if not p.small_open: rnew = firm.get_r(Ynew[:p.T], K[:p.T], p, 'TPI') else: rnew = r.copy() r_gov_new = fiscal.get_r_gov(rnew, p) if p.budget_balance: r_hh_new = rnew[:p.T] else: r_hh_new = aggr.get_r_hh(rnew, r_gov_new, K[:p.T], Dnew[:p.T]) if p.small_open: r_hh_new = p.hh_r[:p.T] # compute w wnew = firm.get_w_from_r(rnew[:p.T], p, 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, p.S, p.J)), b_mat[:p.T - 1, :, :], axis=0) BQnew = aggr.get_BQ(r_hh_new[:p.T], b_mat_shift, None, p, 'TPI', False) bqmat_new = household.get_bq(BQnew, None, p, 'TPI') (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh_new[:p.T], wnew[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat_new[:p.T, :, :], c_mat[:p.T, :, :], Ynew[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue = np.array(list(total_rev) + [total_revenue_ss] * p.S) if p.budget_balance: T_H_new = total_revenue elif not p.baseline_spending: T_H_new = p.alpha_T[:p.T] * Ynew[:p.T] # If baseline_spending==True, no need to update T_H, it's fixed if p.small_open and not p.budget_balance: # Loop through years to calculate debt and gov't spending. # This is done earlier when small_open=False. if p.baseline: D_0 = p.initial_debt_ratio * Y[0] else: D_0 = D0 if not p.baseline_spending: G_0 = p.alpha_G[0] * Ynew[0] dg_fixed_values = (Ynew, total_revenue, T_H, D_0, G_0) Dnew, G = fiscal.D_G_path(r_gov_new, dg_fixed_values, Gbaseline, p) if p.budget_balance: Dnew = D w[:p.T] = wnew[:p.T] r[:p.T] = utils.convex_combo(rnew[:p.T], r[:p.T], p.nu) BQ[:p.T] = utils.convex_combo(BQnew[:p.T], BQ[:p.T], p.nu) D = Dnew Y[:p.T] = utils.convex_combo(Ynew[:p.T], Y[:p.T], p.nu) if not p.baseline_spending: T_H[:p.T] = utils.convex_combo(T_H_new[:p.T], T_H[:p.T], p.nu) guesses_b = utils.convex_combo(b_mat, guesses_b, p.nu) guesses_n = utils.convex_combo(n_mat, guesses_n, p.nu) print('r diff: ', (rnew[:p.T] - r[:p.T]).max(), (rnew[:p.T] - r[:p.T]).min()) print('BQ diff: ', (BQnew[:p.T] - BQ[:p.T]).max(), (BQnew[:p.T] - BQ[:p.T]).min()) print('T_H diff: ', (T_H_new[:p.T]-T_H[:p.T]).max(), (T_H_new[:p.T] - T_H[:p.T]).min()) print('Y diff: ', (Ynew[:p.T]-Y[:p.T]).max(), (Ynew[:p.T] - Y[:p.T]).min()) if not p.baseline_spending: if T_H.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(utils.pct_diff_func(T_H_new[:p.T], T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(np.abs(T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(utils.pct_diff_func(Ynew[:p.T], Y[:p.T]))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print('Iteration:', TPIiter) print('\tDistance:', TPIdist) # Compute effective and marginal tax rates for all agents mtrx_params_4D = np.tile( p.mtrx_params.reshape(p.T, p.S, 1, p.mtrx_params.shape[2]), (1, 1, p.J, 1)) mtry_params_4D = np.tile( p.mtry_params.reshape(p.T, p.S, 1, p.mtry_params.shape[2]), (1, 1, p.J, 1)) e_3D = np.tile(p.e.reshape(1, p.S, p.J), (p.T, 1, 1)) mtry_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, True, e_3D, etr_params_4D, mtry_params_4D, p) mtrx_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, False, e_3D, etr_params_4D, mtrx_params_4D, p) etr_path = tax.ETR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, e_3D, etr_params_4D, p) C = aggr.get_C(c_mat, p, 'TPI') if not p.small_open: I = aggr.get_I(bmat_splus1[:p.T], K[1:p.T + 1], K[:p.T], p, 'TPI') rc_error = Y[:p.T] - C[:p.T] - I[:p.T] - G[:p.T] else: I = ((1 + np.squeeze(np.hstack((p.g_n[1:p.T], p.g_n_ss)))) * np.exp(p.g_y) * K[1:p.T + 1] - (1.0 - p.delta) * K[:p.T]) BI = aggr.get_I(bmat_splus1[:p.T], B[1:p.T + 1], B[:p.T], p, 'TPI') new_borrowing = (D[1:p.T] * (1 + p.g_n[1:p.T]) * np.exp(p.g_y) - D[:p.T - 1]) rc_error = (Y[:p.T - 1] + new_borrowing - ( C[:p.T - 1] + BI[:p.T - 1] + G[:p.T - 1]) + (p.hh_r[:p.T - 1] * B[:p.T - 1] - ( p.delta + p.firm_r[:p.T - 1]) * K[:p.T - 1] - p.hh_r[:p.T - 1] * D[:p.T - 1])) # Compute total investment (not just domestic) I_total = ((1 + p.g_n[:p.T]) * np.exp(p.g_y) * K[1:p.T + 1] - (1.0 - p.delta) * K[:p.T]) rce_max = np.amax(np.abs(rc_error)) print('Max absolute value resource constraint error:', rce_max) print('Checking time path for violations of constraints.') for t in range(p.T): household.constraint_checker_TPI( b_mat[t], n_mat[t], c_mat[t], t, p.ltilde) eul_savings = euler_errors[:, :p.S, :].max(1).max(1) eul_laborleisure = euler_errors[:, p.S:, :].max(1).max(1) print('Max Euler error, savings: ', eul_savings) print('Max Euler error labor supply: ', eul_laborleisure) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = {'Y': Y[:p.T], 'B': B, 'K': K, 'L': L, 'C': C, 'I': I, 'I_total': I_total, 'BQ': BQ, 'total_revenue': total_revenue, 'business_revenue': business_revenue, 'IITpayroll_revenue': T_Ipath, 'T_H': T_H, 'T_P': T_Ppath, 'T_BQ': T_BQpath, 'T_W': T_Wpath, 'T_C': T_Cpath, 'G': G, 'D': D, 'r': r, 'r_gov': r_gov, 'r_hh': r_hh, 'w': w, 'bmat_splus1': bmat_splus1, 'bmat_s': bmat_s[:p.T, :, :], 'n_mat': n_mat[:p.T, :, :], 'c_path': c_mat, 'bq_path': bqmat, 'tax_path': tax_mat, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'resource_constraint_error': rc_error, 'etr_path': etr_path, 'mtrx_path': mtrx_path, 'mtry_path': mtry_path} tpi_dir = os.path.join(p.output_base, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb")) if np.any(G) < 0: print('Government spending is negative along transition path' + ' to satisfy budget') if (((TPIiter >= p.maxiter) or (np.absolute(TPIdist) > p.mindist_TPI)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found' + ' (TPIdist)') if ((np.any(np.absolute(rc_error) >= p.mindist_TPI * 10)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(rc_error)') if ((np.any(np.absolute(eul_savings) >= p.mindist_TPI) or (np.any(np.absolute(eul_laborleisure) > p.mindist_TPI))) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(eulers)') return output
def SS_solver(bmat, nmat, r, BQ, T_H, factor, Y, p, client, fsolve_flag=False): ''' -------------------------------------------------------------------- Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using a bisection method similar to TPI. -------------------------------------------------------------------- INPUTS: b_guess_init = [S,J] array, initial guesses for savings n_guess_init = [S,J] array, initial guesses for labor supply wguess = scalar, initial guess for SS real wage rate rguess = scalar, initial guess for SS real interest rate T_Hguess = scalar, initial guess for lump sum transfer factorguess = scalar, initial guess for scaling factor to dollars chi_b = [J,] vector, chi^b_j, the utility weight on bequests chi_n = [S,] vector, chi^n_s utility weight on labor supply params = length X tuple, list of parameters iterative_params = length X tuple, list of parameters that determine the convergence of the while loop tau_bq = [J,] vector, bequest tax rate rho = [S,] vector, mortality rates by age lambdas = [J,] vector, fraction of population with each ability type omega = [S,] vector, stationary population weights e = [S,J] array, effective labor units by age and ability type OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: euler_equation_solver() aggr.get_K() aggr.get_L() firm.get_Y() firm.get_r() firm.get_w() aggr.get_BQ() tax.replacement_rate_vals() aggr.revenue() utils.convex_combo() utils.pct_diff_func() OBJECTS CREATED WITHIN FUNCTION: b_guess = [S,] vector, initial guess at household savings n_guess = [S,] vector, initial guess at household labor supply b_s = [S,] vector, wealth enter period with b_splus1 = [S,] vector, household savings b_splus2 = [S,] vector, household savings one period ahead BQ = scalar, aggregate bequests to lifetime income group theta = scalar, replacement rate for social security benenfits error1 = [S,] vector, errors from FOC for savings error2 = [S,] vector, errors from FOC for labor supply tax1 = [S,] vector, total income taxes paid cons = [S,] vector, household consumption OBJECTS CREATED WITHIN FUNCTION - SMALL OPEN ONLY Bss = scalar, aggregate household wealth in the steady state BIss = scalar, aggregate household net investment in the steady state RETURNS: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 array) OUTPUT: None -------------------------------------------------------------------- ''' # Rename the inputs if not p.budget_balance: if not p.baseline_spending: Y = T_H / p.alpha_T[-1] if p.small_open: r = p.hh_r[-1] dist = 10 iteration = 0 dist_vec = np.zeros(p.maxiter) maxiter_ss = p.maxiter nu_ss = p.nu if fsolve_flag: maxiter_ss = 1 while (dist > p.mindist_SS) and (iteration < maxiter_ss): # Solve for the steady state levels of b and n, given w, r, # Y and factor if p.budget_balance: outer_loop_vars = (bmat, nmat, r, BQ, T_H, factor) else: outer_loop_vars = (bmat, nmat, r, BQ, Y, T_H, factor) (euler_errors, new_bmat, new_nmat, new_r, new_r_gov, new_r_hh, new_w, new_T_H, new_Y, new_factor, new_BQ, average_income_model) =\ inner_loop(outer_loop_vars, p, client) r = utils.convex_combo(new_r, r, nu_ss) factor = utils.convex_combo(new_factor, factor, nu_ss) BQ = utils.convex_combo(new_BQ, BQ, nu_ss) # bmat = utils.convex_combo(new_bmat, bmat, nu_ss) # nmat = utils.convex_combo(new_nmat, nmat, nu_ss) if not p.baseline_spending: T_H = utils.convex_combo(new_T_H, T_H, nu_ss) dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [utils.pct_diff_func(new_T_H, T_H)] + [utils.pct_diff_func(new_factor, factor)]).max() else: Y = utils.convex_combo(new_Y, Y, nu_ss) if Y != 0: dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [utils.pct_diff_func(new_Y, Y)] + [utils.pct_diff_func(new_factor, factor)]).max() else: # If Y is zero (if there is no output), a percent difference # will throw NaN's, so we use an absolute difference dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [abs(new_Y - Y)] + [utils.pct_diff_func(new_factor, factor)]).max() dist_vec[iteration] = dist # Similar to TPI: if the distance between iterations increases, then # decrease the value of nu to prevent cycling if iteration > 10: if dist_vec[iteration] - dist_vec[iteration - 1] > 0: nu_ss /= 2.0 print('New value of nu:', nu_ss) iteration += 1 print('Iteration: %02d' % iteration, ' Distance: ', dist) ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' bssmat_s = np.append(np.zeros((1, p.J)), bmat[:-1, :], axis=0) bssmat_splus1 = bmat nssmat = nmat rss = r r_gov_ss = fiscal.get_r_gov(rss, p) if p.budget_balance: r_hh_ss = rss Dss = 0.0 else: Dss = p.debt_ratio_ss * Y Lss = aggr.get_L(nssmat, p, 'SS') Bss = aggr.get_K(bssmat_splus1, p, 'SS', False) K_demand_open_ss = firm.get_K(Lss, p.firm_r[-1], p, 'SS') D_f_ss = p.zeta_D[-1] * Dss D_d_ss = Dss - D_f_ss K_d_ss = Bss - D_d_ss if not p.small_open: K_f_ss = p.zeta_K[-1] * (K_demand_open_ss - Bss + D_d_ss) Kss = K_f_ss + K_d_ss # Note that implicity in this computation is that immigrants' # wealth is all in the form of private capital I_d_ss = aggr.get_I(bssmat_splus1, K_d_ss, K_d_ss, p, 'SS') Iss = aggr.get_I(bssmat_splus1, Kss, Kss, p, 'SS') else: K_d_ss = Bss - D_d_ss K_f_ss = K_demand_open_ss - Bss + D_d_ss Kss = K_f_ss + K_d_ss InvestmentPlaceholder = np.zeros(bssmat_splus1.shape) Iss = aggr.get_I(InvestmentPlaceholder, Kss, Kss, p, 'SS') BIss = aggr.get_I(bssmat_splus1, Bss, Bss, p, 'BI_SS') I_d_ss = aggr.get_I(bssmat_splus1, K_d_ss, K_d_ss, p, 'SS') r_hh_ss = aggr.get_r_hh(rss, r_gov_ss, Kss, Dss) wss = new_w BQss = new_BQ factor_ss = factor T_Hss = T_H bqssmat = household.get_bq(BQss, None, p, 'SS') Yss = firm.get_Y(Kss, Lss, p, 'SS') theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, None, p) # Compute effective and marginal tax rates for all agents etr_params_3D = np.tile(np.reshape( p.etr_params[-1, :, :], (p.S, 1, p.etr_params.shape[2])), (1, p.J, 1)) mtrx_params_3D = np.tile(np.reshape( p.mtrx_params[-1, :, :], (p.S, 1, p.mtrx_params.shape[2])), (1, p.J, 1)) mtry_params_3D = np.tile(np.reshape( p.mtry_params[-1, :, :], (p.S, 1, p.mtry_params.shape[2])), (1, p.J, 1)) mtry_ss = tax.MTR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, True, p.e, etr_params_3D, mtry_params_3D, p) mtrx_ss = tax.MTR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, False, p.e, etr_params_3D, mtrx_params_3D, p) etr_ss = tax.ETR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, p.e, etr_params_3D, p) taxss = tax.total_taxes(r_hh_ss, wss, bssmat_s, nssmat, bqssmat, factor_ss, T_Hss, theta, None, None, False, 'SS', p.e, etr_params_3D, p) cssmat = household.get_cons(r_hh_ss, wss, bssmat_s, bssmat_splus1, nssmat, bqssmat, taxss, p.e, p.tau_c[-1, :, :], p) yss_before_tax_mat = r_hh_ss * bssmat_s + wss * p.e * nssmat Css = aggr.get_C(cssmat, p, 'SS') (total_revenue_ss, T_Iss, T_Pss, T_BQss, T_Wss, T_Css, business_revenue) =\ aggr.revenue(r_hh_ss, wss, bssmat_s, nssmat, bqssmat, cssmat, Yss, Lss, Kss, factor, theta, etr_params_3D, p, 'SS') debt_service_ss = r_gov_ss * Dss new_borrowing = Dss * ((1 + p.g_n_ss) * np.exp(p.g_y) - 1) # government spends such that it expands its debt at the same rate as GDP if p.budget_balance: Gss = 0.0 else: Gss = total_revenue_ss + new_borrowing - (T_Hss + debt_service_ss) print('G components = ', new_borrowing, T_Hss, debt_service_ss) # Compute total investment (not just domestic) Iss_total = ((1 + p.g_n_ss) * np.exp(p.g_y) - 1 + p.delta) * Kss # solve resource constraint # net foreign borrowing print('Foreign debt holdings = ', D_f_ss) print('Foreign capital holdings = ', K_f_ss) new_borrowing_f = D_f_ss * (np.exp(p.g_y) * (1 + p.g_n_ss) - 1) debt_service_f = D_f_ss * r_hh_ss RC = aggr.resource_constraint(Yss, Css, Gss, I_d_ss, K_f_ss, new_borrowing_f, debt_service_f, r_hh_ss, p) print('resource constraint: ', RC) if Gss < 0: print('Steady state government spending is negative to satisfy' + ' budget') if ENFORCE_SOLUTION_CHECKS and (np.absolute(RC) > p.mindist_SS): print('Resource Constraint Difference:', RC) err = 'Steady state aggregate resource constraint not satisfied' raise RuntimeError(err) # check constraints household.constraint_checker_SS(bssmat_splus1, nssmat, cssmat, p.ltilde) euler_savings = euler_errors[:p.S, :] euler_labor_leisure = euler_errors[p.S:, :] print('Maximum error in labor FOC = ', np.absolute(euler_labor_leisure).max()) print('Maximum error in savings FOC = ', np.absolute(euler_savings).max()) ''' ------------------------------------------------------------------------ Return dictionary of SS results ------------------------------------------------------------------------ ''' output = {'Kss': Kss, 'K_f_ss': K_f_ss, 'K_d_ss': K_d_ss, 'Bss': Bss, 'Lss': Lss, 'Css': Css, 'Iss': Iss, 'Iss_total': Iss_total, 'I_d_ss': I_d_ss, 'nssmat': nssmat, 'Yss': Yss, 'Dss': Dss, 'D_f_ss': D_f_ss, 'D_d_ss': D_d_ss, 'wss': wss, 'rss': rss, 'r_gov_ss': r_gov_ss, 'r_hh_ss': r_hh_ss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'yss_before_tax_mat': yss_before_tax_mat, 'bqssmat': bqssmat, 'T_Hss': T_Hss, 'Gss': Gss, 'total_revenue_ss': total_revenue_ss, 'business_revenue': business_revenue, 'IITpayroll_revenue': T_Iss, 'T_Pss': T_Pss, 'T_BQss': T_BQss, 'T_Wss': T_Wss, 'T_Css': T_Css, 'euler_savings': euler_savings, 'debt_service_f': debt_service_f, 'new_borrowing_f': new_borrowing_f, 'debt_service_ss': debt_service_ss, 'new_borrowing': new_borrowing, 'euler_labor_leisure': euler_labor_leisure, 'resource_constraint_error': RC, 'etr_ss': etr_ss, 'mtrx_ss': mtrx_ss, 'mtry_ss': mtry_ss} return output
def run_TPI(p, client=None): # unpack tuples of parameters initial_values, ss_vars, theta, baseline_values = get_initial_SS_values(p) (B0, b_sinit, b_splus1init, factor, initial_b, initial_n, D0) = initial_values (T_Hbaseline, Gbaseline) = baseline_values print('Government spending breakpoints are tG1: ', p.tG1, '; and tG2:', p.tG2) # Initialize guesses at time paths # Make array of initial guesses for labor supply and savings domain = np.linspace(0, p.T, p.T) domain2 = np.tile(domain.reshape(p.T, 1, 1), (1, p.S, p.J)) ending_b = ss_vars['bssmat_splus1'] guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, p.T).reshape(p.T, 1, 1), (1, p.S, p.J)) guesses_n = domain3 * (ss_vars['nssmat'] - initial_n) + initial_n ending_n_tail = np.tile(ss_vars['nssmat'].reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) b_mat = guesses_b n_mat = guesses_n ind = np.arange(p.S) L_init = np.ones((p.T + p.S, )) * ss_vars['Lss'] B_init = np.ones((p.T + p.S, )) * ss_vars['Bss'] L_init[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B_init[1:p.T] = aggr.get_K(b_mat[:p.T], p, 'TPI', False)[:p.T - 1] B_init[0] = B0 if not p.small_open: if p.budget_balance: K_init = B_init else: K_init = B_init * ss_vars['Kss'] / ss_vars['Bss'] else: K_init = firm.get_K(L_init, p.firm_r, p, 'TPI') K = K_init K_d = K_init * ss_vars['K_d_ss'] / ss_vars['Kss'] K_f = K_init * ss_vars['K_f_ss'] / ss_vars['Kss'] L = L_init B = B_init Y = np.zeros_like(K) Y[:p.T] = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') Y[p.T:] = ss_vars['Yss'] r = np.zeros_like(Y) if not p.small_open: r[:p.T] = firm.get_r(Y[:p.T], K[:p.T], p, 'TPI') r[p.T:] = ss_vars['rss'] else: r = p.firm_r # compute w w = np.zeros_like(r) w[:p.T] = firm.get_w_from_r(r[:p.T], p, 'TPI') w[p.T:] = ss_vars['wss'] r_gov = fiscal.get_r_gov(r, p) if p.budget_balance: r_hh = r else: r_hh = aggr.get_r_hh(r, r_gov, K, ss_vars['Dss']) if p.small_open: r_hh = p.hh_r BQ0 = aggr.get_BQ(r[0], initial_b, None, p, 'SS', True) if not p.use_zeta: BQ = np.zeros((p.T + p.S, p.J)) for j in range(p.J): BQ[:, j] = (list(np.linspace(BQ0[j], ss_vars['BQss'][j], p.T)) + [ss_vars['BQss'][j]] * p.S) BQ = np.array(BQ) else: BQ = (list(np.linspace(BQ0, ss_vars['BQss'], p.T)) + [ss_vars['BQss']] * p.S) BQ = np.array(BQ) if p.budget_balance: if np.abs(ss_vars['T_Hss']) < 1e-13: T_Hss2 = 0.0 # sometimes SS is very small but not zero, # even if taxes are zero, this get's rid of the approximation # error, which affects the perc changes below else: T_Hss2 = ss_vars['T_Hss'] T_H = np.ones(p.T + p.S) * T_Hss2 total_revenue = T_H G = np.zeros(p.T + p.S) elif not p.baseline_spending: T_H = p.alpha_T * Y G = np.ones(p.T + p.S) * ss_vars['Gss'] elif p.baseline_spending: T_H = T_Hbaseline T_H_new = p.T_H # Need to set T_H_new for later reference G = Gbaseline G_0 = Gbaseline[0] # Initialize some starting values if p.budget_balance: D = np.zeros(p.T + p.S) else: D = np.ones(p.T + p.S) * ss_vars['Dss'] if ss_vars['Dss'] == 0: D_d = np.zeros(p.T + p.S) D_f = np.zeros(p.T + p.S) else: D_d = D * ss_vars['D_d_ss'] / ss_vars['Dss'] D_f = D * ss_vars['D_f_ss'] / ss_vars['Dss'] total_revenue = np.ones(p.T + p.S) * ss_vars['total_revenue_ss'] TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((p.T, 2 * p.S, p.J)) TPIdist_vec = np.zeros(p.maxiter) # TPI loop while (TPIiter < p.maxiter) and (TPIdist >= p.mindist_TPI): r_gov[:p.T] = fiscal.get_r_gov(r[:p.T], p) if p.budget_balance: r_hh[:p.T] = r[:p.T] else: K[:p.T] = firm.get_K_from_Y(Y[:p.T], r[:p.T], p, 'TPI') r_hh[:p.T] = aggr.get_r_hh(r[:p.T], r_gov[:p.T], K[:p.T], D[:p.T]) if p.small_open: r_hh[:p.T] = p.hh_r[:p.T] outer_loop_vars = (r, w, r_hh, BQ, T_H, theta) euler_errors = np.zeros((p.T, 2 * p.S, p.J)) lazy_values = [] for j in range(p.J): guesses = (guesses_b[:, :, j], guesses_n[:, :, j]) lazy_values.append( delayed(inner_loop)(guesses, outer_loop_vars, initial_values, j, ind, p)) results = compute(*lazy_values, scheduler=dask.multiprocessing.get, num_workers=p.num_workers) for j, result in enumerate(results): euler_errors[:, :, j], b_mat[:, :, j], n_mat[:, :, j] = result bmat_s = np.zeros((p.T, p.S, p.J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:p.T - 1, :-1, :] bmat_splus1 = np.zeros((p.T, p.S, p.J)) bmat_splus1[:, :, :] = b_mat[:p.T, :, :] etr_params_4D = np.tile( p.etr_params.reshape(p.T, p.S, 1, p.etr_params.shape[2]), (1, 1, p.J, 1)) bqmat = household.get_bq(BQ, None, p, 'TPI') tax_mat = tax.total_taxes(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], factor, T_H[:p.T], theta, 0, None, False, 'TPI', p.e, etr_params_4D, p) r_hh_path = utils.to_timepath_shape(r_hh, p) wpath = utils.to_timepath_shape(w, p) c_mat = household.get_cons(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s, bmat_splus1, n_mat[:p.T, :, :], bqmat[:p.T, :, :], tax_mat, p.e, p.tau_c[:p.T, :, :], p) y_before_tax_mat = (r_hh_path[:p.T, :, :] * bmat_s[:p.T, :, :] + wpath[:p.T, :, :] * p.e * n_mat[:p.T, :, :]) if not p.baseline_spending and not p.budget_balance: Y[:p.T] = T_H[:p.T] / p.alpha_T[:p.T] # maybe unecessary (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], c_mat[:p.T, :, :], Y[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue[:p.T] = total_rev # set intial debt value if p.baseline: D0 = p.initial_debt_ratio * Y[0] if not p.baseline_spending: G_0 = p.alpha_G[0] * Y[0] dg_fixed_values = (Y, total_revenue, T_H, D0, G_0) Dnew, G[:p.T] = fiscal.D_G_path(r_gov, dg_fixed_values, Gbaseline, p) # Fix initial amount of foreign debt holding D_f[0] = p.initial_foreign_debt_ratio * Dnew[0] for t in range(1, p.T): D_f[t + 1] = (D_f[t] / (np.exp(p.g_y) * (1 + p.g_n[t + 1])) + p.zeta_D[t] * (Dnew[t + 1] - (Dnew[t] / (np.exp(p.g_y) * (1 + p.g_n[t + 1]))))) D_d[:p.T] = Dnew[:p.T] - D_f[:p.T] else: # if budget balance Dnew = np.zeros(p.T + 1) G[:p.T] = np.zeros(p.T) D_f[:p.T] = np.zeros(p.T) D_d[:p.T] = np.zeros(p.T) L[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B[1:p.T] = aggr.get_K(bmat_splus1[:p.T], p, 'TPI', False)[:p.T - 1] K_demand_open = firm.get_K(L[:p.T], p.firm_r[:p.T], p, 'TPI') K_d[:p.T] = B[:p.T] - D_d[:p.T] if np.any(K_d < 0): print('K_d has negative elements. Setting them ' + 'positive to prevent NAN.') K_d[:p.T] = np.fmax(K_d[:p.T], 0.05 * B[:p.T]) K_f[:p.T] = p.zeta_K[:p.T] * (K_demand_open - B[:p.T] + D_d[:p.T]) K = K_f + K_d if np.any(B) < 0: print('B has negative elements. B[0:9]:', B[0:9]) print('B[T-2:T]:', B[p.T - 2, p.T]) if p.small_open: K[:p.T] = K_demand_open Ynew = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') rnew = r.copy() if not p.small_open: rnew[:p.T] = firm.get_r(Ynew[:p.T], K[:p.T], p, 'TPI') else: rnew[:p.T] = r[:p.T].copy() r_gov_new = fiscal.get_r_gov(rnew, p) if p.budget_balance: r_hh_new = rnew[:p.T] else: r_hh_new = aggr.get_r_hh(rnew[:p.T], r_gov_new[:p.T], K[:p.T], Dnew[:p.T]) if p.small_open: r_hh_new = p.hh_r[:p.T] # compute w wnew = firm.get_w_from_r(rnew[:p.T], p, 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, p.S, p.J)), b_mat[:p.T - 1, :, :], axis=0) BQnew = aggr.get_BQ(r_hh_new[:p.T], b_mat_shift, None, p, 'TPI', False) bqmat_new = household.get_bq(BQnew, None, p, 'TPI') (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh_new[:p.T], wnew[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat_new[:p.T, :, :], c_mat[:p.T, :, :], Ynew[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue[:p.T] = total_rev if p.budget_balance: T_H_new = total_revenue elif not p.baseline_spending: T_H_new = p.alpha_T[:p.T] * Ynew[:p.T] # If baseline_spending==True, no need to update T_H, it's fixed # update vars for next iteration w[:p.T] = wnew[:p.T] r[:p.T] = utils.convex_combo(rnew[:p.T], r[:p.T], p.nu) BQ[:p.T] = utils.convex_combo(BQnew[:p.T], BQ[:p.T], p.nu) D[:p.T] = Dnew[:p.T] Y[:p.T] = utils.convex_combo(Ynew[:p.T], Y[:p.T], p.nu) if not p.baseline_spending: T_H[:p.T] = utils.convex_combo(T_H_new[:p.T], T_H[:p.T], p.nu) guesses_b = utils.convex_combo(b_mat, guesses_b, p.nu) guesses_n = utils.convex_combo(n_mat, guesses_n, p.nu) print('r diff: ', (rnew[:p.T] - r[:p.T]).max(), (rnew[:p.T] - r[:p.T]).min()) print('BQ diff: ', (BQnew[:p.T] - BQ[:p.T]).max(), (BQnew[:p.T] - BQ[:p.T]).min()) print('T_H diff: ', (T_H_new[:p.T] - T_H[:p.T]).max(), (T_H_new[:p.T] - T_H[:p.T]).min()) print('Y diff: ', (Ynew[:p.T] - Y[:p.T]).max(), (Ynew[:p.T] - Y[:p.T]).min()) if not p.baseline_spending: if T_H.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(T_H_new[:p.T], T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(np.abs(T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(Ynew[:p.T], Y[:p.T]))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print('Iteration:', TPIiter) print('\tDistance:', TPIdist) # Compute effective and marginal tax rates for all agents mtrx_params_4D = np.tile( p.mtrx_params.reshape(p.T, p.S, 1, p.mtrx_params.shape[2]), (1, 1, p.J, 1)) mtry_params_4D = np.tile( p.mtry_params.reshape(p.T, p.S, 1, p.mtry_params.shape[2]), (1, 1, p.J, 1)) e_3D = np.tile(p.e.reshape(1, p.S, p.J), (p.T, 1, 1)) mtry_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, True, e_3D, etr_params_4D, mtry_params_4D, p) mtrx_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, False, e_3D, etr_params_4D, mtrx_params_4D, p) etr_path = tax.ETR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, e_3D, etr_params_4D, p) C = aggr.get_C(c_mat, p, 'TPI') # Note that implicity in this computation is that immigrants' # wealth is all in the form of private capital I_d = aggr.get_I(bmat_splus1[:p.T], K_d[1:p.T + 1], K_d[:p.T], p, 'TPI') I = aggr.get_I(bmat_splus1[:p.T], K[1:p.T + 1], K[:p.T], p, 'TPI') # solve resource constraint # net foreign borrowing new_borrowing_f = (D_f[1:p.T + 1] * np.exp(p.g_y) * (1 + p.g_n[1:p.T + 1]) - D_f[:p.T]) debt_service_f = D_f * r_hh RC_error = aggr.resource_constraint(Y[:p.T - 1], C[:p.T - 1], G[:p.T - 1], I_d[:p.T - 1], K_f[:p.T - 1], new_borrowing_f[:p.T - 1], debt_service_f[:p.T - 1], r_hh[:p.T - 1], p) # Compute total investment (not just domestic) I_total = ((1 + p.g_n[:p.T]) * np.exp(p.g_y) * K[1:p.T + 1] - (1.0 - p.delta) * K[:p.T]) rce_max = np.amax(np.abs(RC_error)) print('Max absolute value resource constraint error:', rce_max) print('Checking time path for violations of constraints.') for t in range(p.T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_mat[t], t, p.ltilde) eul_savings = euler_errors[:, :p.S, :].max(1).max(1) eul_laborleisure = euler_errors[:, p.S:, :].max(1).max(1) print('Max Euler error, savings: ', eul_savings) print('Max Euler error labor supply: ', eul_laborleisure) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y[:p.T], 'B': B, 'K': K, 'K_f': K_f, 'K_d': K_d, 'L': L, 'C': C, 'I': I, 'I_total': I_total, 'I_d': I_d, 'BQ': BQ, 'total_revenue': total_revenue, 'business_revenue': business_revenue, 'IITpayroll_revenue': T_Ipath, 'T_H': T_H, 'T_P': T_Ppath, 'T_BQ': T_BQpath, 'T_W': T_Wpath, 'T_C': T_Cpath, 'G': G, 'D': D, 'D_f': D_f, 'D_d': D_d, 'r': r, 'r_gov': r_gov, 'r_hh': r_hh, 'w': w, 'bmat_splus1': bmat_splus1, 'bmat_s': bmat_s[:p.T, :, :], 'n_mat': n_mat[:p.T, :, :], 'c_path': c_mat, 'bq_path': bqmat, 'y_before_tax_mat': y_before_tax_mat, 'tax_path': tax_mat, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'resource_constraint_error': RC_error, 'new_borrowing_f': new_borrowing_f, 'debt_service_f': debt_service_f, 'etr_path': etr_path, 'mtrx_path': mtrx_path, 'mtry_path': mtry_path } tpi_dir = os.path.join(p.output_base, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb")) if np.any(G) < 0: print('Government spending is negative along transition path' + ' to satisfy budget') if (((TPIiter >= p.maxiter) or (np.absolute(TPIdist) > p.mindist_TPI)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found' + ' (TPIdist)') if ((np.any(np.absolute(RC_error) >= p.mindist_TPI * 10)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(RC_error)') if ((np.any(np.absolute(eul_savings) >= p.mindist_TPI) or (np.any(np.absolute(eul_laborleisure) > p.mindist_TPI))) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(eulers)') return output
def SS_solver(bmat, nmat, r, BQ, TR, factor, Y, p, client, fsolve_flag=False): ''' Solves for the steady state distribution of capital, labor, as well as w, r, TR and the scaling factor, using functional iteration. Args: bmat (Numpy array): initial guess at savings, size = SxJ nmat (Numpy array): initial guess at labor supply, size = SxJ r (scalar): real interest rate BQ (array_like): aggregate bequest amount(s) TR (scalar): lump sum transfer amount factor (scalar): scaling factor converting model units to dollars Y (scalar): real GDP p (OG-USA Specifications object): model parameters client (Dask client object): client Returns: output (dictionary): dictionary with steady state solution results ''' # Rename the inputs if not p.budget_balance: if not p.baseline_spending: Y = TR / p.alpha_T[-1] if p.small_open: r = p.hh_r[-1] dist = 10 iteration = 0 dist_vec = np.zeros(p.maxiter) maxiter_ss = p.maxiter nu_ss = p.nu if fsolve_flag: maxiter_ss = 1 while (dist > p.mindist_SS) and (iteration < maxiter_ss): # Solve for the steady state levels of b and n, given w, r, # Y and factor if p.budget_balance: outer_loop_vars = (bmat, nmat, r, BQ, TR, factor) else: outer_loop_vars = (bmat, nmat, r, BQ, Y, TR, factor) (euler_errors, new_bmat, new_nmat, new_r, new_r_gov, new_r_hh, new_w, new_TR, new_Y, new_factor, new_BQ, average_income_model) =\ inner_loop(outer_loop_vars, p, client) r = utils.convex_combo(new_r, r, nu_ss) factor = utils.convex_combo(new_factor, factor, nu_ss) BQ = utils.convex_combo(new_BQ, BQ, nu_ss) # bmat = utils.convex_combo(new_bmat, bmat, nu_ss) # nmat = utils.convex_combo(new_nmat, nmat, nu_ss) if not p.baseline_spending: TR = utils.convex_combo(new_TR, TR, nu_ss) dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [utils.pct_diff_func(new_TR, TR)] + [utils.pct_diff_func(new_factor, factor)]).max() else: Y = utils.convex_combo(new_Y, Y, nu_ss) if Y != 0: dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [utils.pct_diff_func(new_Y, Y)] + [utils.pct_diff_func(new_factor, factor)]).max() else: # If Y is zero (if there is no output), a percent difference # will throw NaN's, so we use an absolute difference dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [abs(new_Y - Y)] + [utils.pct_diff_func(new_factor, factor)]).max() dist_vec[iteration] = dist # Similar to TPI: if the distance between iterations increases, then # decrease the value of nu to prevent cycling if iteration > 10: if dist_vec[iteration] - dist_vec[iteration - 1] > 0: nu_ss /= 2.0 print('New value of nu:', nu_ss) iteration += 1 print('Iteration: %02d' % iteration, ' Distance: ', dist) # Generate the SS values of variables, including euler errors bssmat_s = np.append(np.zeros((1, p.J)), bmat[:-1, :], axis=0) bssmat_splus1 = bmat nssmat = nmat rss = r r_gov_ss = fiscal.get_r_gov(rss, p) if p.budget_balance: r_hh_ss = rss Dss = 0.0 else: Dss = p.debt_ratio_ss * Y Lss = aggr.get_L(nssmat, p, 'SS') Bss = aggr.get_B(bssmat_splus1, p, 'SS', False) K_demand_open_ss = firm.get_K(Lss, p.firm_r[-1], p, 'SS') D_f_ss = p.zeta_D[-1] * Dss D_d_ss = Dss - D_f_ss K_d_ss = Bss - D_d_ss if not p.small_open: K_f_ss = p.zeta_K[-1] * (K_demand_open_ss - Bss + D_d_ss) Kss = K_f_ss + K_d_ss # Note that implicity in this computation is that immigrants' # wealth is all in the form of private capital I_d_ss = aggr.get_I(bssmat_splus1, K_d_ss, K_d_ss, p, 'SS') Iss = aggr.get_I(bssmat_splus1, Kss, Kss, p, 'SS') else: K_d_ss = Bss - D_d_ss K_f_ss = K_demand_open_ss - Bss + D_d_ss Kss = K_f_ss + K_d_ss InvestmentPlaceholder = np.zeros(bssmat_splus1.shape) Iss = aggr.get_I(InvestmentPlaceholder, Kss, Kss, p, 'SS') I_d_ss = aggr.get_I(bssmat_splus1, K_d_ss, K_d_ss, p, 'SS') r_hh_ss = aggr.get_r_hh(rss, r_gov_ss, Kss, Dss) wss = new_w BQss = new_BQ factor_ss = factor TR_ss = TR bqssmat = household.get_bq(BQss, None, p, 'SS') trssmat = household.get_tr(TR_ss, None, p, 'SS') Yss = firm.get_Y(Kss, Lss, p, 'SS') theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, None, p) # Compute effective and marginal tax rates for all agents etr_params_3D = np.tile(np.reshape( p.etr_params[-1, :, :], (p.S, 1, p.etr_params.shape[2])), (1, p.J, 1)) mtrx_params_3D = np.tile(np.reshape( p.mtrx_params[-1, :, :], (p.S, 1, p.mtrx_params.shape[2])), (1, p.J, 1)) mtry_params_3D = np.tile(np.reshape( p.mtry_params[-1, :, :], (p.S, 1, p.mtry_params.shape[2])), (1, p.J, 1)) mtry_ss = tax.MTR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, True, p.e, etr_params_3D, mtry_params_3D, p) mtrx_ss = tax.MTR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, False, p.e, etr_params_3D, mtrx_params_3D, p) etr_ss = tax.ETR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, p.e, etr_params_3D, p) taxss = tax.total_taxes(r_hh_ss, wss, bssmat_s, nssmat, bqssmat, factor_ss, trssmat, theta, None, None, False, 'SS', p.e, etr_params_3D, p) cssmat = household.get_cons(r_hh_ss, wss, bssmat_s, bssmat_splus1, nssmat, bqssmat, taxss, p.e, p.tau_c[-1, :, :], p) yss_before_tax_mat = r_hh_ss * bssmat_s + wss * p.e * nssmat Css = aggr.get_C(cssmat, p, 'SS') (total_revenue_ss, T_Iss, T_Pss, T_BQss, T_Wss, T_Css, business_revenue) =\ aggr.revenue(r_hh_ss, wss, bssmat_s, nssmat, bqssmat, cssmat, Yss, Lss, Kss, factor, theta, etr_params_3D, p, 'SS') debt_service_ss = r_gov_ss * Dss new_borrowing = Dss * ((1 + p.g_n_ss) * np.exp(p.g_y) - 1) # government spends such that it expands its debt at the same rate as GDP if p.budget_balance: Gss = 0.0 else: Gss = total_revenue_ss + new_borrowing - (TR_ss + debt_service_ss) print('G components = ', new_borrowing, TR_ss, debt_service_ss) # Compute total investment (not just domestic) Iss_total = ((1 + p.g_n_ss) * np.exp(p.g_y) - 1 + p.delta) * Kss # solve resource constraint # net foreign borrowing print('Foreign debt holdings = ', D_f_ss) print('Foreign capital holdings = ', K_f_ss) new_borrowing_f = D_f_ss * (np.exp(p.g_y) * (1 + p.g_n_ss) - 1) debt_service_f = D_f_ss * r_hh_ss RC = aggr.resource_constraint(Yss, Css, Gss, I_d_ss, K_f_ss, new_borrowing_f, debt_service_f, r_hh_ss, p) print('resource constraint: ', RC) if Gss < 0: print('Steady state government spending is negative to satisfy' + ' budget') if ENFORCE_SOLUTION_CHECKS and (np.absolute(RC) > p.mindist_SS): print('Resource Constraint Difference:', RC) err = 'Steady state aggregate resource constraint not satisfied' raise RuntimeError(err) # check constraints household.constraint_checker_SS(bssmat_splus1, nssmat, cssmat, p.ltilde) euler_savings = euler_errors[:p.S, :] euler_labor_leisure = euler_errors[p.S:, :] print('Maximum error in labor FOC = ', np.absolute(euler_labor_leisure).max()) print('Maximum error in savings FOC = ', np.absolute(euler_savings).max()) # Return dictionary of SS results output = {'Kss': Kss, 'K_f_ss': K_f_ss, 'K_d_ss': K_d_ss, 'Bss': Bss, 'Lss': Lss, 'Css': Css, 'Iss': Iss, 'Iss_total': Iss_total, 'I_d_ss': I_d_ss, 'nssmat': nssmat, 'Yss': Yss, 'Dss': Dss, 'D_f_ss': D_f_ss, 'D_d_ss': D_d_ss, 'wss': wss, 'rss': rss, 'r_gov_ss': r_gov_ss, 'r_hh_ss': r_hh_ss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'yss_before_tax_mat': yss_before_tax_mat, 'bqssmat': bqssmat, 'TR_ss': TR_ss, 'trssmat': trssmat, 'Gss': Gss, 'total_revenue_ss': total_revenue_ss, 'business_revenue': business_revenue, 'IITpayroll_revenue': T_Iss, 'T_Pss': T_Pss, 'T_BQss': T_BQss, 'T_Wss': T_Wss, 'T_Css': T_Css, 'euler_savings': euler_savings, 'debt_service_f': debt_service_f, 'new_borrowing_f': new_borrowing_f, 'debt_service_ss': debt_service_ss, 'new_borrowing': new_borrowing, 'euler_labor_leisure': euler_labor_leisure, 'resource_constraint_error': RC, 'etr_ss': etr_ss, 'mtrx_ss': mtrx_ss, 'mtry_ss': mtry_ss} return output
def SS_solver(bmat, nmat, r, BQ, T_H, factor, Y, p, client, fsolve_flag=False): ''' -------------------------------------------------------------------- Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using a bisection method similar to TPI. -------------------------------------------------------------------- INPUTS: b_guess_init = [S,J] array, initial guesses for savings n_guess_init = [S,J] array, initial guesses for labor supply wguess = scalar, initial guess for SS real wage rate rguess = scalar, initial guess for SS real interest rate T_Hguess = scalar, initial guess for lump sum transfer factorguess = scalar, initial guess for scaling factor to dollars chi_b = [J,] vector, chi^b_j, the utility weight on bequests chi_n = [S,] vector, chi^n_s utility weight on labor supply params = length X tuple, list of parameters iterative_params = length X tuple, list of parameters that determine the convergence of the while loop tau_bq = [J,] vector, bequest tax rate rho = [S,] vector, mortality rates by age lambdas = [J,] vector, fraction of population with each ability type omega = [S,] vector, stationary population weights e = [S,J] array, effective labor units by age and ability type OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: euler_equation_solver() aggr.get_K() aggr.get_L() firm.get_Y() firm.get_r() firm.get_w() aggr.get_BQ() tax.replacement_rate_vals() aggr.revenue() utils.convex_combo() utils.pct_diff_func() OBJECTS CREATED WITHIN FUNCTION: b_guess = [S,] vector, initial guess at household savings n_guess = [S,] vector, initial guess at household labor supply b_s = [S,] vector, wealth enter period with b_splus1 = [S,] vector, household savings b_splus2 = [S,] vector, household savings one period ahead BQ = scalar, aggregate bequests to lifetime income group theta = scalar, replacement rate for social security benenfits error1 = [S,] vector, errors from FOC for savings error2 = [S,] vector, errors from FOC for labor supply tax1 = [S,] vector, total income taxes paid cons = [S,] vector, household consumption OBJECTS CREATED WITHIN FUNCTION - SMALL OPEN ONLY Bss = scalar, aggregate household wealth in the steady state BIss = scalar, aggregate household net investment in the steady state RETURNS: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 array) OUTPUT: None -------------------------------------------------------------------- ''' # Rename the inputs if not p.budget_balance: if not p.baseline_spending: Y = T_H / p.alpha_T[-1] if p.small_open: r = p.hh_r[-1] dist = 10 iteration = 0 dist_vec = np.zeros(p.maxiter) maxiter_ss = p.maxiter nu_ss = p.nu if fsolve_flag: maxiter_ss = 1 while (dist > p.mindist_SS) and (iteration < maxiter_ss): # Solve for the steady state levels of b and n, given w, r, # Y and factor if p.budget_balance: outer_loop_vars = (bmat, nmat, r, BQ, T_H, factor) else: outer_loop_vars = (bmat, nmat, r, BQ, Y, T_H, factor) (euler_errors, new_bmat, new_nmat, new_r, new_r_gov, new_r_hh, new_w, new_T_H, new_Y, new_factor, new_BQ, average_income_model) =\ inner_loop(outer_loop_vars, p, client) r = utils.convex_combo(new_r, r, nu_ss) factor = utils.convex_combo(new_factor, factor, nu_ss) BQ = utils.convex_combo(new_BQ, BQ, nu_ss) # bmat = utils.convex_combo(new_bmat, bmat, nu_ss) # nmat = utils.convex_combo(new_nmat, nmat, nu_ss) if p.budget_balance: T_H = utils.convex_combo(new_T_H, T_H, nu_ss) dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [utils.pct_diff_func(new_T_H, T_H)] + [utils.pct_diff_func(new_factor, factor)]).max() else: Y = utils.convex_combo(new_Y, Y, nu_ss) if Y != 0: dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [utils.pct_diff_func(new_Y, Y)] + [utils.pct_diff_func(new_factor, factor)]).max() else: # If Y is zero (if there is no output), a percent difference # will throw NaN's, so we use an absoluate difference dist = np.array([utils.pct_diff_func(new_r, r)] + list(utils.pct_diff_func(new_BQ, BQ)) + [abs(new_Y - Y)] + [utils.pct_diff_func(new_factor, factor)]).max() dist_vec[iteration] = dist # Similar to TPI: if the distance between iterations increases, then # decrease the value of nu to prevent cycling if iteration > 10: if dist_vec[iteration] - dist_vec[iteration - 1] > 0: nu_ss /= 2.0 print('New value of nu:', nu_ss) iteration += 1 print('Iteration: %02d' % iteration, ' Distance: ', dist) ''' ------------------------------------------------------------------------ Generate the SS values of variables, including euler errors ------------------------------------------------------------------------ ''' bssmat_s = np.append(np.zeros((1, p.J)), bmat[:-1, :], axis=0) bssmat_splus1 = bmat nssmat = nmat rss = r r_gov_ss = fiscal.get_r_gov(rss, p) if p.budget_balance: r_hh_ss = rss debt_ss = 0.0 else: debt_ss = p.debt_ratio_ss * Y Lss = aggr.get_L(nssmat, p, 'SS') if not p.small_open: Bss = aggr.get_K(bssmat_splus1, p, 'SS', False) Kss = Bss - debt_ss Iss = aggr.get_I(bssmat_splus1, Kss, Kss, p, 'SS') else: # Compute capital (K) and wealth (B) separately Kss = firm.get_K(Lss, p.firm_r[-1], p, 'SS') InvestmentPlaceholder = np.zeros(bssmat_splus1.shape) Iss = aggr.get_I(InvestmentPlaceholder, Kss, Kss, p, 'SS') Bss = aggr.get_K(bssmat_splus1, p, 'SS', False) BIss = aggr.get_I(bssmat_splus1, Bss, Bss, p, 'BI_SS') if p.budget_balance: r_hh_ss = rss else: r_hh_ss = aggr.get_r_hh(rss, r_gov_ss, Kss, debt_ss) if p.small_open: r_hh_ss = p.hh_r[-1] wss = new_w BQss = new_BQ factor_ss = factor T_Hss = T_H bqssmat = household.get_bq(BQss, None, p, 'SS') Yss = firm.get_Y(Kss, Lss, p, 'SS') theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, None, p) # Compute effective and marginal tax rates for all agents etr_params_3D = np.tile(np.reshape( p.etr_params[-1, :, :], (p.S, 1, p.etr_params.shape[2])), (1, p.J, 1)) mtrx_params_3D = np.tile(np.reshape( p.mtrx_params[-1, :, :], (p.S, 1, p.mtrx_params.shape[2])), (1, p.J, 1)) mtry_params_3D = np.tile(np.reshape( p.mtry_params[-1, :, :], (p.S, 1, p.mtry_params.shape[2])), (1, p.J, 1)) mtry_ss = tax.MTR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, True, p.e, etr_params_3D, mtry_params_3D, p) mtrx_ss = tax.MTR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, False, p.e, etr_params_3D, mtrx_params_3D, p) etr_ss = tax.ETR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, p.e, etr_params_3D, p) taxss = tax.total_taxes(r_hh_ss, wss, bssmat_s, nssmat, bqssmat, factor_ss, T_Hss, theta, None, None, False, 'SS', p.e, etr_params_3D, p) cssmat = household.get_cons(r_hh_ss, wss, bssmat_s, bssmat_splus1, nssmat, bqssmat, taxss, p.e, p.tau_c[-1, :, :], p) Css = aggr.get_C(cssmat, p, 'SS') (total_revenue_ss, T_Iss, T_Pss, T_BQss, T_Wss, T_Css, business_revenue) =\ aggr.revenue(r_hh_ss, wss, bssmat_s, nssmat, bqssmat, cssmat, Yss, Lss, Kss, factor, theta, etr_params_3D, p, 'SS') debt_service_ss = r_gov_ss * p.debt_ratio_ss * Yss new_borrowing = p.debt_ratio_ss * Yss * ((1 + p.g_n_ss) * np.exp(p.g_y) - 1) # government spends such that it expands its debt at the same rate as GDP if p.budget_balance: Gss = 0.0 else: Gss = total_revenue_ss + new_borrowing - (T_Hss + debt_service_ss) print('G components = ', new_borrowing, T_Hss, debt_service_ss) # Compute total investment (not just domestic) Iss_total = p.delta * Kss # solve resource constraint if p.small_open: # include term for current account resource_constraint = (Yss + new_borrowing - (Css + BIss + Gss) + (p.hh_r[-1] * Bss - (p.delta + p.firm_r[-1]) * Kss - debt_service_ss)) print('Yss= ', Yss, '\n', 'Css= ', Css, '\n', 'Bss = ', Bss, '\n', 'BIss = ', BIss, '\n', 'Kss = ', Kss, '\n', 'Iss = ', Iss, '\n', 'Lss = ', Lss, '\n', 'T_H = ', T_H, '\n', 'Gss= ', Gss) print('D/Y:', debt_ss / Yss, 'T/Y:', T_Hss / Yss, 'G/Y:', Gss / Yss, 'Rev/Y:', total_revenue_ss / Yss, 'Int payments to GDP:', (r_gov_ss * debt_ss) / Yss) print('resource constraint: ', resource_constraint) else: resource_constraint = Yss - (Css + Iss + Gss) print('Yss= ', Yss, '\n', 'Gss= ', Gss, '\n', 'Css= ', Css, '\n', 'Kss = ', Kss, '\n', 'Iss = ', Iss, '\n', 'Lss = ', Lss, '\n', 'Debt service = ', debt_service_ss) print('D/Y:', debt_ss / Yss, 'T/Y:', T_Hss / Yss, 'G/Y:', Gss / Yss, 'Rev/Y:', total_revenue_ss / Yss, 'business rev/Y: ', business_revenue / Yss, 'Int payments to GDP:', (r_gov_ss * debt_ss) / Yss) print('Check SS budget: ', Gss - (np.exp(p.g_y) * (1 + p.g_n_ss) - 1 - r_gov_ss) * debt_ss - total_revenue_ss + T_Hss) print('resource constraint: ', resource_constraint) if Gss < 0: print('Steady state government spending is negative to satisfy' + ' budget') if ENFORCE_SOLUTION_CHECKS and (np.absolute(resource_constraint) > p.mindist_SS): print('Resource Constraint Difference:', resource_constraint) err = 'Steady state aggregate resource constraint not satisfied' raise RuntimeError(err) # check constraints household.constraint_checker_SS(bssmat_splus1, nssmat, cssmat, p.ltilde) euler_savings = euler_errors[:p.S, :] euler_labor_leisure = euler_errors[p.S:, :] print('Maximum error in labor FOC = ', np.absolute(euler_labor_leisure).max()) print('Maximum error in savings FOC = ', np.absolute(euler_savings).max()) ''' ------------------------------------------------------------------------ Return dictionary of SS results ------------------------------------------------------------------------ ''' output = {'Kss': Kss, 'Bss': Bss, 'Lss': Lss, 'Css': Css, 'Iss': Iss, 'Iss_total': Iss_total, 'nssmat': nssmat, 'Yss': Yss, 'Dss': debt_ss, 'wss': wss, 'rss': rss, 'r_gov_ss': r_gov_ss, 'r_hh_ss': r_hh_ss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1, 'bqssmat': bqssmat, 'T_Hss': T_Hss, 'Gss': Gss, 'total_revenue_ss': total_revenue_ss, 'business_revenue': business_revenue, 'IITpayroll_revenue': T_Iss, 'T_Pss': T_Pss, 'T_BQss': T_BQss, 'T_Wss': T_Wss, 'T_Css': T_Css, 'euler_savings': euler_savings, 'euler_labor_leisure': euler_labor_leisure, 'resource_constraint_error': resource_constraint, 'etr_ss': etr_ss, 'mtrx_ss': mtrx_ss, 'mtry_ss': mtry_ss} return output