def test_FOC_savings(model_vars, params, expected): # Test FOC condition for household's choice of savings (r, w, b, b_splus1, n, BQ, factor, tr, theta, tau_c, etr_params, mtry_params, t, j, method) = model_vars if j is not None: test_value = household.FOC_savings(r, w, b, b_splus1, n, BQ, factor, tr, theta, params.e[:, j], params.rho, tau_c, etr_params, mtry_params, t, j, params, method) else: test_value = household.FOC_savings(r, w, b, b_splus1, n, BQ, factor, tr, theta, np.squeeze(params.e), params.rho, tau_c, etr_params, mtry_params, t, j, params, method) assert np.allclose(test_value, expected)
def euler_equation_solver(guesses, *args): ''' Finds the euler errors for certain b and n, one ability type at a time. Args: guesses (Numpy array): initial guesses for b and n, lenth 2S args (tuple): tuple of arguments (r, w, bq, TR, factor, j, p) w (scalar): real wage rate bq (Numpy array): bequest amounts by age, length S tr (scalar): government transfer amount by age, length S factor (scalar): scaling factor converting model units to dollars p (OG-USA Specifications object): model parameters Returns: errros (Numpy array): errors from FOCs, length 2S ''' (r, w, bq, tr, factor, j, p) = args b_guess = np.array(guesses[:p.S]) n_guess = np.array(guesses[p.S:]) b_s = np.array([0] + list(b_guess[:-1])) b_splus1 = b_guess theta = tax.replacement_rate_vals(n_guess, w, factor, j, p) error1 = household.FOC_savings(r, w, b_s, b_splus1, n_guess, bq, factor, tr, theta, p.e[:, j], p.rho, p.tau_c[-1, :, j], p.etr_params[-1, :, :], p.mtry_params[-1, :, :], None, j, p, 'SS') error2 = household.FOC_labor(r, w, b_s, b_splus1, n_guess, bq, factor, tr, theta, p.chi_n, p.e[:, j], p.tau_c[-1, :, j], p.etr_params[-1, :, :], p.mtrx_params[-1, :, :], None, j, p, 'SS') # Put in constraints for consumption and savings. # According to the euler equations, they can be negative. When # Chi_b is large, they will be. This prevents that from happening. # I'm not sure if the constraints are needed for labor. # But we might as well put them in for now. mask1 = n_guess < 0 mask2 = n_guess > p.ltilde mask3 = b_guess <= 0 mask4 = np.isnan(n_guess) mask5 = np.isnan(b_guess) error2[mask1] = 1e14 error2[mask2] = 1e14 error1[mask3] = 1e14 error1[mask5] = 1e14 error2[mask4] = 1e14 taxes = tax.total_taxes(r, w, b_s, n_guess, bq, factor, tr, theta, None, j, False, 'SS', p.e[:, j], p.etr_params[-1, :, :], p) cons = household.get_cons(r, w, b_s, b_splus1, n_guess, bq, taxes, p.e[:, j], p.tau_c[-1, :, j], p) mask6 = cons < 0 error1[mask6] = 1e14 errors = np.hstack((error1, error2)) return errors
def test_FOC_savings(model_vars, params, expected): # Test FOC condition for household's choice of savings r, w, b, b_splus1, b_splus2, n, BQ, factor, T_H = model_vars test_value = household.FOC_savings(r, w, b, b_splus1, b_splus2, n, BQ, factor, T_H, params) assert np.allclose(test_value, expected)
def firstdoughnutring(guesses, r, w, bq, tr, theta, factor, j, initial_b, p): ''' Solves the first entries of the upper triangle of the twist doughnut. This is separate from the main TPI function because the values of b and n are scalars, so it is easier to just have a separate function for these cases. Args: guesses (Numpy array): initial guesses for b and n, length 2 r (scalar): real interest rate w (scalar): real wage rate bq (scalar): bequest amounts by age tr (scalar): government transfer amount theta (Numpy array): retirement replacement rates, length J factor (scalar): scaling factor converting model units to dollars j (int): index of ability type initial_b (Numpy array): savings of agents alive at T=0, size = SxJ p (OG-USA Specifications object): model parameters Returns: euler errors (Numpy array): errors from first order conditions, length 2 ''' b_splus1 = float(guesses[0]) n = float(guesses[1]) b_s = float(initial_b[-2, j]) # Find errors from FOC for savings and FOC for labor supply error1 = household.FOC_savings(np.array([r]), np.array([w]), b_s, np.array([b_splus1]), np.array([n]), np.array([bq]), factor, np.array([tr]), theta[j], p.e[-1, j], p.rho[-1], np.array([p.tau_c[0, -1, j]]), p.etr_params[0, -1, :], p.mtry_params[0, -1, :], None, j, p, 'TPI_scalar') error2 = household.FOC_labor(np.array([r]), np.array([w]), b_s, b_splus1, np.array([n]), np.array([bq]), factor, np.array([tr]), theta[j], p.chi_n[-1], p.e[-1, j], np.array([p.tau_c[0, -1, j]]), p.etr_params[0, -1, :], p.mtrx_params[0, -1, :], None, j, p, 'TPI_scalar') if n <= 0 or n >= 1: error2 += 1e12 if b_splus1 <= 0: error1 += 1e12 return [np.squeeze(error1)] + [np.squeeze(error2)]
def firstdoughnutring(guesses, r, w, bq, T_H, theta, factor, j, initial_b, p): ''' Solves the first entries of the upper triangle of the twist doughnut. This is separate from the main TPI function because the values of b and n are scalars, so it is easier to just have a separate function for these cases. Inputs: guesses = guess for b and n (2x1 list) winit = initial wage rate (scalar) rinit = initial rental rate (scalar) BQinit = initial aggregate bequest (scalar) T_H_init = initial lump sum tax (scalar) initial_b = initial distribution of capital (SxJ array) factor = steady state scaling factor (scalar) j = which ability type is being solved for (integer) parameters = tuple of parameters (tuple) theta = replacement rates (Jx1 array) tau_bq = bequest tax rates (Jx1 array) Output: euler errors (2x1 list) ''' b_splus1 = float(guesses[0]) n = float(guesses[1]) b_s = float(initial_b[-2, j]) # Find errors from FOC for savings and FOC for labor supply error1 = household.FOC_savings(np.array([r]), np.array([w]), b_s, np.array([b_splus1]), np.array([n]), np.array([bq]), factor, np.array([T_H]), theta[j], p.e[-1, j], p.rho[-1], np.array([p.tau_c[0, -1, j]]), p.etr_params[0, -1, :], p.mtry_params[0, -1, :], None, j, p, 'TPI_scalar') error2 = household.FOC_labor(np.array([r]), np.array([w]), b_s, b_splus1, np.array([n]), np.array([bq]), factor, np.array([T_H]), theta[j], p.chi_n[-1], p.e[-1, j], np.array([p.tau_c[0, -1, j]]), p.etr_params[0, -1, :], p.mtrx_params[0, -1, :], None, j, p, 'TPI_scalar') if n <= 0 or n >= 1: error2 += 1e12 if b_splus1 <= 0: error1 += 1e12 return [np.squeeze(error1)] + [np.squeeze(error2)]
def twist_doughnut(guesses, r, w, bq, T_H, theta, factor, j, s, t, tau_c, etr_params, mtrx_params, mtry_params, initial_b, p): ''' Parameters: guesses = distribution of capital and labor (various length list) w = wage rate ((T+S)x1 array) r = rental rate ((T+S)x1 array) BQ = aggregate bequests ((T+S)x1 array) T_H = lump sum tax over time ((T+S)x1 array) factor = scaling factor (scalar) j = which ability type is being solved for (scalar) s = which upper triangle loop is being solved for (scalar) t = which diagonal is being solved for (scalar) params = list of parameters (list) theta = replacement rates (Jx1 array) tau_bq = bequest tax rate (Jx1 array) rho = mortalit rate (Sx1 array) lambdas = ability weights (Jx1 array) e = ability type (SxJ array) initial_b = capital stock distribution in period 0 (SxJ array) chi_b = chi^b_j (Jx1 array) chi_n = chi^n_s (Sx1 array) Output: Value of Euler error (various length list) ''' length = int(len(guesses) / 2) b_guess = np.array(guesses[:length]) n_guess = np.array(guesses[length:]) if length == p.S: b_s = np.array([0] + list(b_guess[:-1])) else: b_s = np.array([(initial_b[-(s + 3), j])] + list(b_guess[:-1])) b_splus1 = b_guess w_s = w[t:t + length] r_s = r[t:t + length] n_s = n_guess chi_n_s = p.chi_n[-length:] e_s = p.e[-length:, j] rho_s = p.rho[-length:] T_H_s = T_H[t:t + length] error1 = household.FOC_savings(r_s, w_s, b_s, b_splus1, n_s, bq, factor, T_H_s, theta, e_s, rho_s, tau_c, etr_params, mtry_params, t, j, p, 'TPI') error2 = household.FOC_labor(r_s, w_s, b_s, b_splus1, n_s, bq, factor, T_H_s, theta, chi_n_s, e_s, tau_c, etr_params, mtrx_params, t, j, p, 'TPI') # Check and punish constraint violations mask1 = n_guess < 0 error2[mask1] += 1e12 mask2 = n_guess > p.ltilde error2[mask2] += 1e12 mask4 = b_guess <= 0 error2[mask4] += 1e12 mask5 = b_splus1 < 0 error2[mask5] += 1e12 return list(error1.flatten()) + list(error2.flatten())
def twist_doughnut(guesses, r, w, bq, tr, theta, factor, j, s, t, tau_c, etr_params, mtrx_params, mtry_params, initial_b, p): ''' Solves the upper triangle of time path iterations. These are the agents who are alive at time T=0 so that we do not solve for their full lifetime (so of their life was before the model begins). Args: guesses (Numpy array): initial guesses for b and n, length 2s r (scalar): real interest rate w (scalar): real wage rate bq (Numpy array): bequest amounts by age, length s tr (scalar): government transfer amount theta (Numpy array): retirement replacement rates, length J factor (scalar): scaling factor converting model units to dollars j (int): index of ability type s (int): years of life remaining t (int): model period tau_c (Numpy array): consumption tax rates, size = sxJ etr_params (Numpy array): ETR function parameters, size = sxsxnum_params mtrx_params (Numpy array): labor income MTR function parameters, size = sxsxnum_params mtry_params (Numpy array): capital income MTR function parameters, size = sxsxnum_params initial_b (Numpy array): savings of agents alive at T=0, size = SxJ p (OG-USA Specifications object): model parameters Returns: euler errors (Numpy array): errors from first order conditions, length 2s ''' length = int(len(guesses) / 2) b_guess = np.array(guesses[:length]) n_guess = np.array(guesses[length:]) if length == p.S: b_s = np.array([0] + list(b_guess[:-1])) else: b_s = np.array([(initial_b[-(s + 3), j])] + list(b_guess[:-1])) b_splus1 = b_guess w_s = w[t:t + length] r_s = r[t:t + length] n_s = n_guess chi_n_s = p.chi_n[-length:] e_s = p.e[-length:, j] rho_s = p.rho[-length:] error1 = household.FOC_savings(r_s, w_s, b_s, b_splus1, n_s, bq, factor, tr, theta, e_s, rho_s, tau_c, etr_params, mtry_params, t, j, p, 'TPI') error2 = household.FOC_labor(r_s, w_s, b_s, b_splus1, n_s, bq, factor, tr, theta, chi_n_s, e_s, tau_c, etr_params, mtrx_params, t, j, p, 'TPI') # Check and punish constraint violations mask1 = n_guess < 0 error2[mask1] += 1e12 mask2 = n_guess > p.ltilde error2[mask2] += 1e12 mask4 = b_guess <= 0 error2[mask4] += 1e12 mask5 = b_splus1 < 0 error2[mask5] += 1e12 return list(error1.flatten()) + list(error2.flatten())
def euler_equation_solver(guesses, *args): ''' -------------------------------------------------------------------- Finds the euler errors for certain b and n, one ability type at a time. -------------------------------------------------------------------- INPUTS: guesses = [2S,] vector, initial guesses for b and n r = scalar, real interest rate w = scalar, real wage rate T_H = scalar, lump sum transfer factor = scalar, scaling factor converting model units to dollars j = integer, ability group params = length 21 tuple, list of parameters chi_b = [J,] vector, chi^b_j, the utility weight on bequests chi_n = [S,] vector, chi^n_s utility weight on labor supply tau_bq = scalar, bequest tax rate rho = [S,] vector, mortality rates by age lambdas = [J,] vector, fraction of population with each ability type omega_SS = [S,] vector, stationary population weights e = [S,J] array, effective labor units by age and ability type tax_params = length 5 tuple, (tax_func_type, analytical_mtrs, etr_params, mtrx_params, mtry_params) tax_func_type = string, type of tax function used analytical_mtrs = boolean, =True if use analytical_mtrs, =False if use estimated MTRs etr_params = [S,BW,#tax params] array, parameters for effective tax rate function mtrx_params = [S,BW,#tax params] array, parameters for marginal tax rate on labor income function mtry_params = [S,BW,#tax params] array, parameters for marginal tax rate on capital income function OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION: aggr.get_BQ() tax.replacement_rate_vals() household.FOC_savings() household.FOC_labor() tax.total_taxes() household.get_cons() 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 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 RETURNS: 2Sx1 list of euler errors OUTPUT: None -------------------------------------------------------------------- ''' (r, w, bq, T_H, factor, j, p) = args b_guess = np.array(guesses[:p.S]) n_guess = np.array(guesses[p.S:]) b_s = np.array([0] + list(b_guess[:-1])) b_splus1 = b_guess theta = tax.replacement_rate_vals(n_guess, w, factor, j, p) error1 = household.FOC_savings(r, w, b_s, b_splus1, n_guess, bq, factor, T_H, theta, p.e[:, j], p.rho, p.tau_c[-1, :, j], p.etr_params[-1, :, :], p.mtry_params[-1, :, :], None, j, p, 'SS') error2 = household.FOC_labor(r, w, b_s, b_splus1, n_guess, bq, factor, T_H, theta, p.chi_n, p.e[:, j], p.tau_c[-1, :, j], p.etr_params[-1, :, :], p.mtrx_params[-1, :, :], None, j, p, 'SS') # Put in constraints for consumption and savings. # According to the euler equations, they can be negative. When # Chi_b is large, they will be. This prevents that from happening. # I'm not sure if the constraints are needed for labor. # But we might as well put them in for now. mask1 = n_guess < 0 mask2 = n_guess > p.ltilde mask3 = b_guess <= 0 mask4 = np.isnan(n_guess) mask5 = np.isnan(b_guess) error2[mask1] = 1e14 error2[mask2] = 1e14 error1[mask3] = 1e14 error1[mask5] = 1e14 error2[mask4] = 1e14 taxes = tax.total_taxes(r, w, b_s, n_guess, bq, factor, T_H, theta, None, j, False, 'SS', p.e[:, j], p.etr_params[-1, :, :], p) cons = household.get_cons(r, w, b_s, b_splus1, n_guess, bq, taxes, p.e[:, j], p.tau_c[-1, :, j], p) mask6 = cons < 0 error1[mask6] = 1e14 return np.hstack((error1, error2))
n = pd.DataFrame(np.array(n)) w = np.array(w) error_sum = b_s[b_s < 0].sum().sum() +\ n[n < 0].sum().sum() + w[w < 0].sum().sum() return [np.array(1e9 * error_sum)] * 2 ======= or np.isnan(r).any() or np.isnan(w).any(): return [np.array(1e10)] * 2 >>>>>>> e45bda2b32d217b3ef4ed14b3dd87cf484ab68d3 # Find errors from FOC for savings and FOC for labor supply error1 = household.FOC_savings(np.array([r]), np.array([w]), b_s, np.array([b_splus1]), np.array([n]), np.array([bq]), factor, np.array([T_H]), theta[j], p.e[-1, j], p.rho[-1], np.array([p.tau_c[0, -1, j]]), p.etr_params[0, -1, :], p.mtry_params[0, -1, :], None, j, p, 'TPI_scalar') error2 = household.FOC_labor( np.array([r]), np.array([w]), b_s, b_splus1, np.array([n]), np.array([bq]), factor, np.array([T_H]), theta[j], p.chi_n[-1], p.e[-1, j], np.array([p.tau_c[0, -1, j]]), p.etr_params[0, -1, :], p.mtrx_params[0, -1, :], None, j, p, 'TPI_scalar') if n <= 0 or n >= 1: error2 += 1e12 if b_splus1 <= 0: error1 += 1e12