Example #1
0
def run_time_path_iteration(Kss,
                            Lss,
                            Yss,
                            BQss,
                            theta,
                            parameters,
                            g_n_vector,
                            omega_stationary,
                            K0,
                            b_sinit,
                            b_splus1init,
                            L0,
                            Y0,
                            r0,
                            BQ0,
                            T_H_0,
                            tax0,
                            c0,
                            initial_b,
                            initial_n,
                            factor_ss,
                            tau_bq,
                            chi_b,
                            chi_n,
                            get_baseline=False,
                            output_dir="./OUTPUT",
                            **kwargs):

    TPI_FIG_DIR = output_dir
    # Initialize Time paths
    domain = np.linspace(0, T, T)
    Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss
    Kinit[-1] = Kss
    Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss))
    Linit = np.ones(T + S) * Lss
    Yinit = firm.get_Y(Kinit, Linit, parameters)
    winit = firm.get_w(Yinit, Linit, parameters)
    rinit = firm.get_r(Yinit, Kinit, parameters)
    BQinit = np.zeros((T + S, J))
    for j in xrange(J):
        BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQinit = np.array(BQinit)
    T_H_init = np.ones(T + S) * T_Hss

    # Make array of initial guesses
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)

    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    b_mat = np.zeros((T + S, S, J))
    n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)

    TPIiter = 0
    TPIdist = 10

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss)
        Lpath_TPI = list(Linit) + list(np.ones(10) * Lss)
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            plt.figure()
            plt.axhline(y=Kss,
                        color='black',
                        linewidth=2,
                        label=r"Steady State $\hat{K}$",
                        ls='--')
            plt.plot(np.arange(T + 10),
                     Kpath_TPI[:T + 10],
                     'b',
                     linewidth=2,
                     label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))
        # Uncomment the following print statements to make sure all euler equations are converging.
        # If they don't, then you'll have negative consumption or consumption spikes.  If they don't,
        # it is the initial guesses.  You might need to scale them differently.  It is rather delicate for the first
        # few periods and high ability groups.
        for j in xrange(J):
            b_mat[1, -1, j], n_mat[0, -1, j] = np.array(
                opt.fsolve(SS_TPI_firstdoughnutring,
                           [guesses_b[1, -1, j], guesses_n[0, -1, j]],
                           args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1],
                                 initial_b, factor_ss, j, parameters, theta,
                                 tau_bq),
                           xtol=1e-13))
            # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6:
            # print 'minidoughnut:',
            # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1,
            # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b,
            # factor_ss, j, parameters, theta, tau_bq)).max()
            for s in xrange(S - 2):  # Upper triangle
                ind2 = np.arange(s + 2)
                b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j],
                                           S - (s + 2))
                n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2))
                solutions = opt.fsolve(
                    Steady_state_TPI_solver,
                    list(b_guesses_to_use) + list(n_guesses_to_use),
                    args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j,
                          s, 0, parameters, theta, tau_bq, rho, lambdas, e,
                          initial_b, chi_b, chi_n),
                    xtol=1e-13)
                b_vec = solutions[:len(solutions) / 2]
                b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec
                n_vec = solutions[len(solutions) / 2:]
                n_mat[ind2, S - (s + 2) + ind2, j] = n_vec
                # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6:
                # print 's-loop:',
                # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit,
                # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters,
                # theta, tau_bq, rho, lambdas, e, initial_b, chi_b,
                # chi_n))).max()
            for t in xrange(0, T):
                b_guesses_to_use = .75 * \
                    np.diag(guesses_b[t + 1:t + S + 1, :, j])
                n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j])
                solutions = opt.fsolve(
                    Steady_state_TPI_solver,
                    list(b_guesses_to_use) + list(n_guesses_to_use),
                    args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j,
                          None, t, parameters, theta, tau_bq, rho, lambdas, e,
                          None, chi_b, chi_n),
                    xtol=1e-13)
                b_vec = solutions[:S]
                b_mat[t + 1 + ind, ind, j] = b_vec
                n_vec = solutions[S:]
                n_mat[t + ind, ind, j] = n_vec
                inputs = list(solutions)
                euler_errors[t, :, j] = np.abs(
                    Steady_state_TPI_solver(inputs, winit, rinit, BQinit[:, j],
                                            T_H_init, factor_ss, j, None, t,
                                            parameters, theta, tau_bq, rho,
                                            lambdas, e, None, chi_b, chi_n))
        # if euler_errors.max() > 1e-6:
        #     print 't-loop:', euler_errors.max()
        # Force the initial distribution of capital to be as given above.
        b_mat[0, :, :] = initial_b
        Kinit = household.get_K(b_mat[:T],
                                omega_stationary[:T].reshape(T, S, 1),
                                lambdas.reshape(1, 1,
                                                J), g_n_vector[:T], 'TPI')
        Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T],
                           omega_stationary[:T, :].reshape(T, S, 1),
                           lambdas.reshape(1, 1, J), 'TPI')
        Ynew = firm.get_Y(Kinit, Linit, parameters)
        wnew = firm.get_w(Ynew, Linit, parameters)
        rnew = firm.get_r(Ynew, Kinit, parameters)
        # the following needs a g_n term
        BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T],
                                 omega_stationary[:T].reshape(T, S, 1),
                                 lambdas.reshape(1, 1,
                                                 J), rho.reshape(1, S, 1),
                                 g_n_vector[:T].reshape(T, 1), 'TPI')
        bmat_s = np.zeros((T, S, J))
        bmat_s[:, 1:, :] = b_mat[:T, :-1, :]
        T_H_new = np.array(
            list(
                tax.get_lump_sum(
                    rnew.reshape(T, 1, 1), bmat_s, wnew.reshape(T, 1, 1),
                    e.reshape(1, S, J), n_mat[:T], BQnew.reshape(T, 1, J),
                    lambdas.reshape(1, 1, J), factor_ss, omega_stationary[:T].
                    reshape(T, S, 1), 'TPI', parameters, theta, tau_bq)) +
            [T_Hss] * S)

        winit[:T] = utils.convex_combo(wnew, winit[:T], parameters)
        rinit[:T] = utils.convex_combo(rnew, rinit[:T], parameters)
        BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], parameters)
        T_H_init[:T] = utils.convex_combo(T_H_new[:T], T_H_init[:T],
                                          parameters)
        guesses_b = utils.convex_combo(b_mat, guesses_b, parameters)
        guesses_n = utils.convex_combo(n_mat, guesses_n, parameters)
        if T_H_init.all() != 0:
            TPIdist = np.array(
                list(utils.perc_dif_func(rnew, rinit[:T])) +
                list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) +
                list(utils.perc_dif_func(wnew, winit[:T])) +
                list(utils.perc_dif_func(T_H_new, T_H_init))).max()
        else:
            TPIdist = np.array(
                list(utils.perc_dif_func(rnew, rinit[:T])) +
                list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) +
                list(utils.perc_dif_func(wnew, winit[:T])) +
                list(np.abs(T_H_new, T_H_init))).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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    print 'Computing final solutions'

    # As in SS, you need the final distributions of b and n to match the final
    # w, r, BQ, etc.  Otherwise the euler errors are large.  You need one more
    # fsolve.
    for j in xrange(J):
        b_mat[1, -1, j], n_mat[0, -1, j] = np.array(
            opt.fsolve(SS_TPI_firstdoughnutring,
                       [guesses_b[1, -1, j], guesses_n[0, -1, j]],
                       args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1],
                             initial_b, factor_ss, j, parameters, theta,
                             tau_bq),
                       xtol=1e-13))
        for s in xrange(S - 2):  # Upper triangle
            ind2 = np.arange(s + 2)
            b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2))
            n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2))
            solutions = opt.fsolve(
                Steady_state_TPI_solver,
                list(b_guesses_to_use) + list(n_guesses_to_use),
                args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0,
                      parameters, theta, tau_bq, rho, lambdas, e, initial_b,
                      chi_b, chi_n),
                xtol=1e-13)
            b_vec = solutions[:len(solutions) / 2]
            b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec
            n_vec = solutions[len(solutions) / 2:]
            n_mat[ind2, S - (s + 2) + ind2, j] = n_vec
        for t in xrange(0, T):
            b_guesses_to_use = .75 * np.diag(guesses_b[t + 1:t + S + 1, :, j])
            n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j])
            solutions = opt.fsolve(
                Steady_state_TPI_solver,
                list(b_guesses_to_use) + list(n_guesses_to_use),
                args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None,
                      t, parameters, theta, tau_bq, rho, lambdas, e, None,
                      chi_b, chi_n),
                xtol=1e-13)
            b_vec = solutions[:S]
            b_mat[t + 1 + ind, ind, j] = b_vec
            n_vec = solutions[S:]
            n_mat[t + ind, ind, j] = n_vec
            inputs = list(solutions)
            euler_errors[t, :, j] = np.abs(
                Steady_state_TPI_solver(inputs, winit, rinit, BQinit[:, j],
                                        T_H_init, factor_ss, j, None, t,
                                        parameters, theta, tau_bq, rho,
                                        lambdas, e, None, chi_b, chi_n))

    b_mat[0, :, :] = initial_b
    '''
    ------------------------------------------------------------------------
    Generate variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    Kpath_TPI = np.array(list(Kinit) + list(np.ones(10) * Kss))
    Lpath_TPI = np.array(list(Linit) + list(np.ones(10) * Lss))
    BQpath_TPI = np.array(list(BQinit) + list(np.ones((10, J)) * BQss))

    b_s = np.zeros((T, S, J))
    b_s[:, 1:, :] = b_mat[:T, :-1, :]
    b_splus1 = np.zeros((T, S, J))
    b_splus1[:, :, :] = b_mat[1:T + 1, :, :]

    tax_path = tax.total_taxes(rinit[:T].reshape(T, 1, 1),
                               b_s, winit[:T].reshape(T, 1, 1),
                               e.reshape(1, S, J), n_mat[:T],
                               BQinit[:T, :].reshape(T, 1, J), lambdas,
                               factor_ss, T_H_init[:T].reshape(T, 1, 1), None,
                               'TPI', False, parameters, theta, tau_bq)
    c_path = household.get_cons(rinit[:T].reshape(T, 1, 1),
                                b_s, winit[:T].reshape(T, 1, 1),
                                e.reshape(1, S, J), n_mat[:T],
                                BQinit[:T].reshape(T, 1, J),
                                lambdas.reshape(1, 1, J), b_splus1, parameters,
                                tax_path)

    Y_path = firm.get_Y(Kpath_TPI[:T], Lpath_TPI[:T], parameters)
    C_path = household.get_C(c_path, omega_stationary[:T].reshape(T, S, 1),
                             lambdas, 'TPI')
    I_path = firm.get_I(Kpath_TPI[1:T + 1], Kpath_TPI[:T], delta, g_y,
                        g_n_vector[:T])
    print 'Resource Constraint Difference:', Y_path - C_path - I_path

    print 'Checking time path for violations of constaints.'
    for t in xrange(T):
        household.constraint_checker_TPI(b_mat[t], n_mat[t], c_path[t], t,
                                         parameters)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)
    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {
        'Kpath_TPI': Kpath_TPI,
        'b_mat': b_mat,
        'c_path': c_path,
        'eul_savings': eul_savings,
        'eul_laborleisure': eul_laborleisure,
        'Lpath_TPI': Lpath_TPI,
        'BQpath_TPI': BQpath_TPI,
        'n_mat': n_mat,
        'rinit': rinit,
        'Yinit': Yinit,
        'T_H_init': T_H_init,
        'tax_path': tax_path,
        'winit': winit
    }

    if get_baseline:
        tpi_init_dir = os.path.join(output_dir, "TPIinit")
        utils.mkdirs(tpi_init_dir)
        tpi_init_vars = os.path.join(tpi_init_dir, "TPIinit_vars.pkl")
        pickle.dump(output, open(tpi_init_vars, "wb"))
    else:
        tpi_dir = os.path.join(output_dir, "TPI")
        utils.mkdirs(tpi_dir)
        tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl")
        pickle.dump(output, open(tpi_vars, "wb"))
Example #2
0
def run_time_path_iteration(Kss, Lss, Yss, BQss, theta, parameters, g_n_vector, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, chi_n, get_baseline=False, output_dir="./OUTPUT", **kwargs):

    TPI_FIG_DIR = output_dir
    # Initialize Time paths
    domain = np.linspace(0, T, T)
    Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss
    Kinit[-1] = Kss
    Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss))
    Linit = np.ones(T + S) * Lss
    Yinit = firm.get_Y(Kinit, Linit, parameters)
    winit = firm.get_w(Yinit, Linit, parameters)
    rinit = firm.get_r(Yinit, Kinit, parameters)
    BQinit = np.zeros((T + S, J))
    for j in xrange(J):
        BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQinit = np.array(BQinit)
    T_H_init = np.ones(T + S) * T_Hss

    # Make array of initial guesses
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)

    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    b_mat = np.zeros((T + S, S, J))
    n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)

    TPIiter = 0
    TPIdist = 10

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss)
        Lpath_TPI = list(Linit) + list(np.ones(10) * Lss)
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            plt.figure()
            plt.axhline(
                y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
            plt.plot(np.arange(
                T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))
        # Uncomment the following print statements to make sure all euler equations are converging.
        # If they don't, then you'll have negative consumption or consumption spikes.  If they don't,
        # it is the initial guesses.  You might need to scale them differently.  It is rather delicate for the first
        # few periods and high ability groups.
        for j in xrange(J):
            b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]],
                                                                   args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13))
            # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6:
            # print 'minidoughnut:',
            # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1,
            # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b,
            # factor_ss, j, parameters, theta, tau_bq)).max()
            for s in xrange(S - 2):  # Upper triangle
                ind2 = np.arange(s + 2)
                b_guesses_to_use = np.diag(
                    guesses_b[1:S + 1, :, j], S - (s + 2))
                n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2))
                solutions = opt.fsolve(Steady_state_TPI_solver, list(
                    b_guesses_to_use) + list(n_guesses_to_use), args=(
                    winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13)
                b_vec = solutions[:len(solutions) / 2]
                b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec
                n_vec = solutions[len(solutions) / 2:]
                n_mat[ind2, S - (s + 2) + ind2, j] = n_vec
                # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6:
                # print 's-loop:',
                # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit,
                # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters,
                # theta, tau_bq, rho, lambdas, e, initial_b, chi_b,
                # chi_n))).max()
            for t in xrange(0, T):
                b_guesses_to_use = .75 * \
                    np.diag(guesses_b[t + 1:t + S + 1, :, j])
                n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j])
                solutions = opt.fsolve(Steady_state_TPI_solver, list(
                    b_guesses_to_use) + list(n_guesses_to_use), args=(
                    winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13)
                b_vec = solutions[:S]
                b_mat[t + 1 + ind, ind, j] = b_vec
                n_vec = solutions[S:]
                n_mat[t + ind, ind, j] = n_vec
                inputs = list(solutions)
                euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver(
                    inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n))
        # if euler_errors.max() > 1e-6:
        #     print 't-loop:', euler_errors.max()
        # Force the initial distribution of capital to be as given above.
        b_mat[0, :, :] = initial_b
        Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape(
            T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI')
        Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[
                           :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
        Ynew = firm.get_Y(Kinit, Linit, parameters)
        wnew = firm.get_w(Ynew, Linit, parameters)
        rnew = firm.get_r(Ynew, Kinit, parameters)
        # the following needs a g_n term
        BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape(
            T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
        bmat_s = np.zeros((T, S, J))
        bmat_s[:, 1:, :] = b_mat[:T, :-1, :]
        T_H_new = np.array(list(tax.get_lump_sum(rnew.reshape(T, 1, 1), bmat_s, wnew.reshape(
            T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQnew.reshape(T, 1, J), lambdas.reshape(
            1, 1, J), factor_ss, omega_stationary[:T].reshape(T, S, 1), 'TPI', parameters, theta, tau_bq)) + [T_Hss] * S)

        winit[:T] = utils.convex_combo(wnew, winit[:T], parameters)
        rinit[:T] = utils.convex_combo(rnew, rinit[:T], parameters)
        BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], parameters)
        T_H_init[:T] = utils.convex_combo(
            T_H_new[:T], T_H_init[:T], parameters)
        guesses_b = utils.convex_combo(b_mat, guesses_b, parameters)
        guesses_n = utils.convex_combo(n_mat, guesses_n, parameters)
        if T_H_init.all() != 0:
            TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list(
                utils.perc_dif_func(wnew, winit[:T])) + list(utils.perc_dif_func(T_H_new, T_H_init))).max()
        else:
            TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list(
                utils.perc_dif_func(wnew, winit[:T])) + list(np.abs(T_H_new, T_H_init))).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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    print 'Computing final solutions'

    # As in SS, you need the final distributions of b and n to match the final
    # w, r, BQ, etc.  Otherwise the euler errors are large.  You need one more
    # fsolve.
    for j in xrange(J):
        b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]],
                                                               args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13))
        for s in xrange(S - 2):  # Upper triangle
            ind2 = np.arange(s + 2)
            b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2))
            n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2))
            solutions = opt.fsolve(Steady_state_TPI_solver, list(
                b_guesses_to_use) + list(n_guesses_to_use), args=(
                winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13)
            b_vec = solutions[:len(solutions) / 2]
            b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec
            n_vec = solutions[len(solutions) / 2:]
            n_mat[ind2, S - (s + 2) + ind2, j] = n_vec
        for t in xrange(0, T):
            b_guesses_to_use = .75 * np.diag(guesses_b[t + 1:t + S + 1, :, j])
            n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j])
            solutions = opt.fsolve(Steady_state_TPI_solver, list(
                b_guesses_to_use) + list(n_guesses_to_use), args=(
                winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13)
            b_vec = solutions[:S]
            b_mat[t + 1 + ind, ind, j] = b_vec
            n_vec = solutions[S:]
            n_mat[t + ind, ind, j] = n_vec
            inputs = list(solutions)
            euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver(
                inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n))

    b_mat[0, :, :] = initial_b

    '''
    ------------------------------------------------------------------------
    Generate variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    Kpath_TPI = np.array(list(Kinit) + list(np.ones(10) * Kss))
    Lpath_TPI = np.array(list(Linit) + list(np.ones(10) * Lss))
    BQpath_TPI = np.array(list(BQinit) + list(np.ones((10, J)) * BQss))

    b_s = np.zeros((T, S, J))
    b_s[:, 1:, :] = b_mat[:T, :-1, :]
    b_splus1 = np.zeros((T, S, J))
    b_splus1[:, :, :] = b_mat[1:T + 1, :, :]

    tax_path = tax.total_taxes(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape(
        1, S, J), n_mat[:T], BQinit[:T, :].reshape(T, 1, J), lambdas, factor_ss, T_H_init[:T].reshape(T, 1, 1), None, 'TPI', False, parameters, theta, tau_bq)
    c_path = household.get_cons(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape(
        1, S, J), n_mat[:T], BQinit[:T].reshape(T, 1, J), lambdas.reshape(1, 1, J), b_splus1, parameters, tax_path)

    Y_path = firm.get_Y(Kpath_TPI[:T], Lpath_TPI[:T], parameters)
    C_path = household.get_C(c_path, omega_stationary[
                             :T].reshape(T, S, 1), lambdas, 'TPI')
    I_path = firm.get_I(Kpath_TPI[1:T + 1],
                        Kpath_TPI[:T], delta, g_y, g_n_vector[:T])
    print 'Resource Constraint Difference:', Y_path - C_path - I_path

    print'Checking time path for violations of constaints.'
    for t in xrange(T):
        household.constraint_checker_TPI(
            b_mat[t], n_mat[t], c_path[t], t, parameters)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {'Kpath_TPI': Kpath_TPI, 'b_mat': b_mat, 'c_path': c_path,
              'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure,
              'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI, 'n_mat': n_mat,
              'rinit': rinit, 'Yinit': Yinit, 'T_H_init': T_H_init,
              'tax_path': tax_path, 'winit': winit}

    if get_baseline:
        tpi_init_dir = os.path.join(output_dir, "TPIinit")
        utils.mkdirs(tpi_init_dir)
        tpi_init_vars = os.path.join(tpi_init_dir, "TPIinit_vars.pkl")
        pickle.dump(output, open(tpi_init_vars, "wb"))
    else:
        tpi_dir = os.path.join(output_dir, "TPI")
        utils.mkdirs(tpi_dir)
        tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl")
        pickle.dump(output, open(tpi_vars, "wb"))
Example #3
0
def run_TPI(income_tax_params,
            tpi_params,
            iterative_params,
            initial_values,
            SS_values,
            output_dir="./OUTPUT"):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params
    K0, b_sinit, b_splus1init, L0, Y0,\
            w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n = initial_values
    Kss, Lss, rss, wss, BQss, T_Hss, bssmat_splus1, nssmat = SS_values

    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    domain = np.linspace(0, T, T)
    K_init = (-1 / (domain + 1)) * (Kss - K0) + Kss
    K_init[-1] = Kss
    K_init = np.array(list(K_init) + list(np.ones(S) * Kss))
    L_init = np.ones(T + S) * Lss

    K = K_init
    L = L_init
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    w = firm.get_w(Y, L, alpha)
    r_params = (alpha, delta)
    r = firm.get_r(Y, K, r_params)
    BQ = np.zeros((T + S, J))
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    if T_Hss < 1e-13 and T_Hss > 0.0:
        T_Hss2 = 0.0  # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below
    else:
        T_Hss2 = T_Hss
    T_H = np.ones(T + S) * T_Hss2

    # Make array of initial guesses for labor supply and savings
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)

    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    b_mat = np.zeros((T + S, S, J))
    n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)

    TPIiter = 0
    TPIdist = 10
    PLOT_TPI = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            K_plot = list(K) + list(np.ones(10) * Kss)
            L_plot = list(L) + list(np.ones(10) * Lss)
            plt.figure()
            plt.axhline(y=Kss,
                        color='black',
                        linewidth=2,
                        label=r"Steady State $\hat{K}$",
                        ls='--')
            plt.plot(np.arange(T + 10),
                     Kpath_plot[:T + 10],
                     'b',
                     linewidth=2,
                     label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))
        # Uncomment the following print statements to make sure all euler equations are converging.
        # If they don't, then you'll have negative consumption or consumption spikes.  If they don't,
        # it is the initial guesses.  You might need to scale them differently.  It is rather delicate for the first
        # few periods and high ability groups.

        # theta_params = (e[-1, j], 1, omega[0].reshape(S, 1), lambdas[j])
        # theta = tax.replacement_rate_vals(n, w, factor, theta_params)
        theta = np.zeros((J, ))

        guesses = (guesses_b, guesses_n)
        outer_loop_vars = (r, w, K, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values,
                             theta, ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars,
                                                inner_loop_params)

        # if euler_errors.max() > 1e-6:
        #     print 't-loop:', euler_errors.max()
        # Force the initial distribution of capital to be as given above.
        b_mat[0, :, :] = initial_b
        K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J),
                    g_n_vector[:T], 'TPI')
        K[:T] = household.get_K(b_mat[:T], K_params)
        L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                    lambdas.reshape(1, 1, J), 'TPI')
        L[:T] = firm.get_L(n_mat[:T], L_params)

        Y_params = (alpha, Z)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        wnew = firm.get_w(Ynew[:T], L[:T], alpha)
        r_params = (alpha, delta)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)

        BQ_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J),
                     rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat[:T, :, :],
                                 BQ_params)
        bmat_s = np.zeros((T, S, J))
        bmat_s[:, 1:, :] = b_mat[:T, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[1:T + 1, :, :]

        TH_tax_params = np.zeros((T, S, J, etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            TH_tax_params[:, :, :, i] = np.tile(
                np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
                (1, 1, J))

        T_H_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)),
                      lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1),
                      'TPI', TH_tax_params, theta, tau_bq, tau_payroll,
                      h_wealth, p_wealth, m_wealth, retire, T, S, J)
        T_H_new = np.array(
            list(
                tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), (
                    1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), (
                        1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape(
                            T, 1, J), factor, T_H_params)) + [T_Hss] * S)

        w[:T] = utils.convex_combo(wnew[:T], w[:T], nu)
        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu)
        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)
        if T_H.all() != 0:
            TPIdist = np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T])) +
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                list(utils.pct_diff_func(wnew[:T], w[:T])) +
                list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
        else:
            TPIdist = np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T])) +
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                list(utils.pct_diff_func(wnew[:T], w[:T])) +
                list(np.abs(T_H_new[:T], T_H[: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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    if ((TPIiter >= maxiter) or
        (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS:
        raise RuntimeError("Transition path equlibrium not found")

    Y[:T] = Ynew

    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, K, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, theta,
                         ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars,
                                            inner_loop_params)
    b_mat[0, :, :] = initial_b

    K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J),
                g_n_vector[:T], 'TPI')
    K[:T] = household.get_K(
        b_mat[:T],
        K_params)  # this is what old code does, but it's strange - why use
    # b_mat -- what is going on with initial period, etc.

    etr_params_path = np.zeros((T, S, J, etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:, :, :, i] = np.tile(
            np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
            (1, 1, J))
    tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas, 'TPI',
                       retire, etr_params_path, h_wealth, p_wealth, m_wealth,
                       tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)),
                               np.tile(w[:T].reshape(T, 1, 1),
                                       (1, S, J)), bmat_s, n_mat[:T, :, :],
                               BQ[:T, :].reshape(T, 1, J), factor,
                               T_H[:T].reshape(T, 1, 1), None, False,
                               tax_path_params)

    cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1),
                                bmat_s, bmat_splus1, n_mat[:T, :, :],
                                BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)
    I_params = (delta, g_y, g_n_vector[:T])
    I = firm.get_I(K[1:T + 1], K[:T], I_params)
    print 'Resource Constraint Difference:', Y[:T] - C[:T] - I[:T]

    print 'Checking time path for violations of constaints.'
    for t in xrange(T):
        household.constraint_checker_TPI(b_mat[t], n_mat[t], c_path[t], t,
                                         ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    print 'Max Euler error, savings: ', eul_savings
    print 'Max Euler error labor supply: ', eul_laborleisure

    if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
         (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
            and ENFORCE_SOLUTION_CHECKS):
        raise RuntimeError("Transition path equlibrium not found")
    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {
        'Y': Y,
        'K': K,
        'L': L,
        'C': C,
        'I': I,
        'BQ': BQ,
        'T_H': T_H,
        'r': r,
        'w': w,
        'b_mat': b_mat,
        'n_mat': n_mat,
        'c_path': c_path,
        'tax_path': tax_path,
        'eul_savings': eul_savings,
        'eul_laborleisure': eul_laborleisure
    }

    tpi_dir = os.path.join(output_dir, "TPI")
    utils.mkdirs(tpi_dir)
    tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl")
    pickle.dump(output, open(tpi_vars, "wb"))

    macro_output = {
        'Y': Y,
        'K': K,
        'L': L,
        'C': C,
        'I': I,
        'BQ': BQ,
        'T_H': T_H,
        'r': r,
        'w': w,
        'tax_path': tax_path
    }

    # Non-stationary output
    # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path,
    #           'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path,
    #           'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path,
    #           'w_ns_path': w_ns_path}

    return output, macro_output
Example #4
0
def create_tpi_params(analytical_mtrs, etr_params, mtrx_params, mtry_params,
                      b_ellipse, upsilon, J, S, T, BW, beta, sigma, alpha, Z,
                      delta, ltilde, nu, g_y, tau_payroll, retire,
                      mean_income_data, run_params,
                      input_dir="./OUTPUT", baseline_dir="./OUTPUT", **kwargs):

    globals().update(run_params)

    ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl")
    variables = pickle.load(open(ss_init, "rb"))
    for key in variables:
        globals()[key] = variables[key]

    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(baseline_dir, "SSinit/ss_init_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas
    initial_b= ss_baseline_vars['bssmat_splus1'] 


    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    # Put income tax parameters in a tuple 
    # Assumption here is that tax parameters of last year of budget
    # window continue forever and so will be SS values
    etr_params_TP = np.zeros((S,T+S,etr_params.shape[2]))
    etr_params_TP[:,:BW,:] = etr_params
    etr_params_TP[:,BW:,:] = np.reshape(etr_params[:,BW-1,:],(S,1,etr_params.shape[2]))

    mtrx_params_TP = np.zeros((S,T+S,mtrx_params.shape[2]))
    mtrx_params_TP[:,:BW,:] = mtrx_params
    mtrx_params_TP[:,BW:,:] = np.reshape(mtrx_params[:,BW-1,:],(S,1,mtrx_params.shape[2]))

    mtry_params_TP = np.zeros((S,T+S,mtry_params.shape[2]))
    mtry_params_TP[:,:BW,:] = mtry_params
    mtry_params_TP[:,BW:,:] = np.reshape(mtry_params[:,BW-1,:],(S,1,mtry_params.shape[2]))

    income_tax_params = (analytical_mtrs, etr_params_TP, mtrx_params_TP, mtry_params_TP)


    wealth_tax_params = [h_wealth, p_wealth, m_wealth]
    ellipse_params = [b_ellipse, upsilon]
    parameters = [J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire,
                  mean_income_data]  + wealth_tax_params + ellipse_params

    N_tilde = omega.sum(1)
    omega_stationary = omega / N_tilde.reshape(T + S, 1)

    initial_n = nssmat

    # Get an initial distribution of capital with the initial population
    # distribution
    K0 = household.get_K(initial_b, omega_stationary[
                         0].reshape(S, 1), lambdas, g_n_vector[0], 'SS')


    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0 = firm.get_L(e, initial_n, omega_stationary[
                    0].reshape(S, 1), lambdas, 'SS')
    Y0 = firm.get_Y(K0, L0, parameters)
    w0 = firm.get_w(Y0, L0, parameters)
    r0 = firm.get_r(Y0, K0, parameters)
    BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape(
        S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')

    T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[
                             0].reshape(S, 1), 'SS', etr_params_TP[:,0,:], parameters, theta, tau_bq)

    tax0_params = (J, S, retire, np.tile(np.reshape(etr_params_TP[:,0,:],(S,1,etr_params_TP.shape[2])),(1,J,1)), 
                    h_wealth, p_wealth, m_wealth, tau_payroll)
    tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas,
                           factor_ss, T_H_0, None, 'SS', False, tax0_params, theta, tau_bq)
    c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(
        1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0)

    return (income_tax_params, wealth_tax_params, ellipse_params, parameters,
            N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0,
            w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n)
Example #5
0
def inner_loop(outer_loop_vars, params, baseline, baseline_spending=False):
    '''
    This function solves for the inner loop of
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, Y, factor)
    this function solves the households'
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate
        w          = [T,] vector, wage rate
        b          = [T,S,J] array, wealth holdings
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        Y        = [T,] vector, lump sum transfer amount(s)


    Functions called:
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.revenue()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ

    '''

    # unpack variables and parameters pass to function
    ss_params, income_tax_params, chi_params, small_open_params = params
    J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, budget_balance, \
                  alpha_T, debt_ratio_ss, tau_b, delta_tau,\
                  lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params

    small_open, ss_firm_r, ss_hh_r = small_open_params
    if budget_balance:
        bssmat, nssmat, r, w, T_H, factor = outer_loop_vars
    else:
        bssmat, nssmat, r, w, Y, T_H, factor = outer_loop_vars

    euler_errors = np.zeros((2*S,J))



    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            guesses = np.append(bssmat[:, j], nssmat[:, j])
        else:
            guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])
        euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9,
                                   args=euler_params, xtol=MINIMIZER_TOL, full_output=True)

        euler_errors[:,j] = infodict['fvec']
      #  print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max()

        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]

    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    if small_open == False:
        K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS')
        B = household.get_K(bssmat, K_params)
        if budget_balance:
            K = B
        else:
            K = B - debt_ratio_ss*Y
    else:
        K_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        K = firm.get_K(L, ss_firm_r, K_params)
    # Y_params = (alpha, Z)
    Y_params = (Z, gamma, epsilon)
    new_Y = firm.get_Y(K, L, Y_params)
    #print 'inner K, L, Y: ', K, L, new_Y
    if budget_balance:
        Y = new_Y
    if small_open == False:
        r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        new_r = firm.get_r(Y, K, r_params)
    else:
        new_r = ss_hh_r
    w_params = (Z, gamma, epsilon)
    new_w = firm.get_w(Y, L, w_params)
    print 'inner factor prices: ', new_r, new_w

    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    if baseline:
        new_factor = mean_income_data / average_income_model
    else:
        new_factor = factor

    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, S, retire)
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    if budget_balance:
        T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                          tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)
        new_T_H = tax.revenue(new_r, new_w, b_s, nssmat, new_BQ, new_Y, L, K, factor, T_H_params)
    elif baseline_spending:
        new_T_H = T_H
    else:
        new_T_H = alpha_T*new_Y

    return euler_errors, bssmat, nssmat, new_r, new_w, \
         new_T_H, new_Y, new_factor, new_BQ, average_income_model
Example #6
0
def inner_loop(outer_loop_vars, params, baseline):
    '''
    This function solves for the inner loop of
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, T_H, factor)
    this function solves the households'
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate
        w          = [T,] vector, wage rate
        b          = [T,S,J] array, wealth holdings
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        T_H        = [T,] vector, lump sum transfer amount(s)


    Functions called:
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.get_lump_sum()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ

    '''

    # unpack variables and parameters pass to function
    bssmat, nssmat, r, w, T_H, BQ, theta, factor = outer_loop_vars
    ss_params, income_tax_params, chi_params = params

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params

    # bssmat = START_VALUES['bssmat_splus1']
    # nssmat = START_VALUES['nssmat']
    cssmat = np.zeros((S,J))
    euler_errors = np.zeros((2*S,J))

    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            b_Sp1_guess = bssmat[-1, j]
        else:
            b_Sp1_guess = bssmat[-1, j-1]*10

        euler_params = [r, w, T_H, BQ, theta, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solution, infodict, ier, message] = opt.fsolve(lc_error, b_Sp1_guess,
                                     args=euler_params, xtol=MINIMIZER_TOL, full_output=True)
        # [x0, r_out] = opt.bisect(lc_error, -1.0, 10.0, args=euler_params, xtol=MINIMIZER_TOL, full_output=True, disp=False)
        print 'j = ', j
        print 'b[0] error = ', infodict['fvec']
        print 'message: ', message
        # print 'b[S]= ', x0
        # print 'converged= ', r_out.converged

        b_out, nssmat[:, j], cssmat[:, j] = lifecycle_solver(solution,euler_params)
        bssmat[:, j] = b_out[1:]
        # print solutions
        # quit()
        #
        # euler_errors[:,j] = infodict['fvec']
        # print 'j = ', j
        # print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max()
    # print 'bssmat: ', bssmat
    # print 'nssmat: ', nssmat
    # print 'cssmat: ', cssmat
    quit()
    K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS')
    K = household.get_K(bssmat, K_params)
    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    new_r = firm.get_r(Y, K, r_params)
    new_w = firm.get_w(Y, L, alpha)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    if baseline:
        new_factor = mean_income_data / average_income_model
    else:
        new_factor = factor

    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, S, J, omega_SS.reshape(S, 1), lambdas,retire)
    new_theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                      tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params)

    print 'Inner Loop Max Euler Error: ', (np.absolute(euler_errors)).max()
    # print 'K: ', K
    # print 'L: ', L
    #print 'bssmat: ', bssmat
    return euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_BQ, new_theta, new_factor, average_income_model
Example #7
0
def TPI_fsolve(guesses, Kss, Lss, Yss, BQss, theta, income_tax_params, wealth_tax_params, ellipse_params, parameters, g_n_vector, 
                           omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, 
                           T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, 
                           chi_n, output_dir="./OUTPUT", **kwargs):

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \
        h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = parameters

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params

    # create full time paths with guesses and SS values
    rinit = np.zeros(T+S)
    winit = np.zeros(T+S)
    T_H_init = np.zeros(T+S)
    BQinit = np.zeros((T+S,J))
    rinit[:T] = guesses[0:T].reshape(T)
    winit[:T] = guesses[T:2*T].reshape(T)
    rinit[T:] = rss
    winit[T:] = wss
    T_H_init[:T] = guesses[2*T:3*T].reshape(T)
    BQinit[:T,:] = guesses[3*T:].reshape(T,J)
    T_H_init[T:] = T_Hss
    BQinit[T:,:] = BQss

    

    # Make array of initial guesses for distribution of 
    # savings and labor supply
    domain = np.linspace(0, T, T)
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)

    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    b_mat = np.zeros((T + S, S, J))
    n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)

    euler_errors = np.zeros((T, 2 * S, J))

    # Solve hh problem over time path:
    # Uncomment the following print statements to make sure all euler equations are converging.
    # If they don't, then you'll have negative consumption or consumption spikes.  If they don't,
    # it is the initial guesses.  You might need to scale them differently.  It is rather delicate for the first
    # few periods and high ability groups.
    for j in xrange(J):
        b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]],
                                                               args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, 
                                                               j, income_tax_params, parameters, theta, tau_bq), xtol=1e-13))
        # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6:
        # print 'minidoughnut:',
        # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1,
        # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b,
        # factor_ss, j, parameters, theta, tau_bq)).max()
        for s in xrange(S - 2):  # Upper triangle
            ind2 = np.arange(s + 2)
            b_guesses_to_use = np.diag(
                guesses_b[1:S + 1, :, j], S - (s + 2))
            n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2))

            # initialize array of diagonal elements
            length_diag = (np.diag(np.transpose(etr_params[:S,:,0]),S-(s+2))).shape[0]
            etr_params_to_use = np.zeros((length_diag,etr_params.shape[2]))
            mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2]))
            mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2]))
            for i in range(etr_params.shape[2]):
                etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:S,:,i]),S-(s+2))
                mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:S,:,i]),S-(s+2))
                mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:S,:,i]),S-(s+2))

            inc_tax_params_upper = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use)

            solutions = opt.fsolve(Steady_state_TPI_solver, list(
                b_guesses_to_use) + list(n_guesses_to_use), args=(
                winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, inc_tax_params_upper, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13)
            b_vec = solutions[:len(solutions) / 2]
            b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec
            n_vec = solutions[len(solutions) / 2:]
            n_mat[ind2, S - (s + 2) + ind2, j] = n_vec
            # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6:
            # print 's-loop:',
            # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit,
            # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters,
            # theta, tau_bq, rho, lambdas, e, initial_b, chi_b,
            # chi_n))).max()
        for t in xrange(0, T):
            b_guesses_to_use = .75 * \
                np.diag(guesses_b[t + 1:t + S + 1, :, j])
            n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j])

            # initialize array of diagonal elements
            length_diag = (np.diag(np.transpose(etr_params[:,t:t+S,i]))).shape[0]
            etr_params_to_use = np.zeros((length_diag,etr_params.shape[2]))
            mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2]))
            mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2]))
            for i in range(etr_params.shape[2]):
                etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:,t:t+S,i]))
                mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:,t:t+S,i]))
                mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:,t:t+S,i]))

            inc_tax_params_TP = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use)

            solutions = opt.fsolve(Steady_state_TPI_solver, list(
                b_guesses_to_use) + list(n_guesses_to_use), args=(
                winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13)
            b_vec = solutions[:S]
            b_mat[t + 1 + ind, ind, j] = b_vec
            n_vec = solutions[S:]
            n_mat[t + ind, ind, j] = n_vec
            inputs = list(solutions)
            euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver(
                inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n))
    # if euler_errors.max() > 1e-6:
    #     print 't-loop:', euler_errors.max()
    # Force the initial distribution of capital to be as given above.
    b_mat[0, :, :] = initial_b
    Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape(
        T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI')
    Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[
                       :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')

    # Plotting of Kpath and Lpath to check convergence
    # make vectors of Kpath and Lpath to plot
    Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss)
    Lpath_TPI = list(Linit) + list(np.ones(10) * Lss)
    # Plot TPI for K for each iteration, so we can see if there is a
    # problem
    TPI_FIG_DIR = output_dir
    if PLOT_TPI is True:
        plt.figure()
        plt.axhline(
            y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
        plt.plot(np.arange(
            T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$")
        plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))


    Ynew = firm.get_Y(Kinit, Linit, parameters)
    wnew = firm.get_w(Ynew, Linit, parameters)
    rnew = firm.get_r(Ynew, Kinit, parameters)
    # the following needs a g_n term
    BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape(
        T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')

    bmat_s = np.zeros((T, S, J))
    bmat_s[:, 1:, :] = b_mat[:T, :-1, :]
    # initialize array 
    TH_tax_params = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        TH_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) 

    T_H_new = np.array(list(tax.get_lump_sum(np.tile(rnew.reshape(T, 1, 1),(1,S,J)), bmat_s, np.tile(wnew.reshape(
        T, 1, 1),(1,S,J)), np.tile(e.reshape(1, S, J),(T,1,1)), n_mat[:T,:,:], BQnew.reshape(T, 1, J), lambdas.reshape(
        1, 1, J), factor_ss, omega_stationary[:T].reshape(T, S, 1), 'TPI', TH_tax_params, parameters, theta, tau_bq)) + [T_Hss] * S)

    error1 = rinit[:T]-rnew[:T] 
    error2 = winit[:T]-wnew[:T] 
    error3 = T_H_init[:T]-T_H_new[:T]
    error4 = BQinit[:T] - BQnew[:T]

    # Check and punish constraing violations
    mask1 = rinit[:T] <= 0
    mask2 = winit[:T] <= 0
    mask3 = np.isnan(rinit[:T])
    mask4 = np.isnan(winit[:T])
    error1[mask1] = 1e14
    error2[mask2] = 1e14
    error1[mask3] = 1e14
    error2[mask4] = 1e14
    mask5 = T_H_init[:T] < 0
    mask6 = np.isnan(T_H_init[:T])
    mask7 = BQinit[:T] < 0
    mask8 = np.isnan(BQinit[:T])
    error3[mask5] = 1e14
    error3[mask6] = 1e14
    error4[mask7] = 1e14
    error4[mask8] = 1e14

    errors = np.array(list(error1) +list(error2) + list(error3) + list(error4.flatten()))

    print '\t\tDistance:', np.absolute(errors).max()

    return errors 
Example #8
0
def inner_loop(outer_loop_vars, params, baseline, baseline_spending=False):
    '''
    This function solves for the inner loop of
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, Y, factor)
    this function solves the households'
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate
        w          = [T,] vector, wage rate
        b          = [T,S,J] array, wealth holdings
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        Y        = [T,] vector, lump sum transfer amount(s)


    Functions called:
        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()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ

    '''

    # unpack variables and parameters pass to function
    ss_params, income_tax_params, chi_params, small_open_params = params
    J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, budget_balance, \
                  alpha_T, debt_ratio_ss, tau_b, delta_tau,\
                  lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params

    small_open, ss_firm_r, ss_hh_r = small_open_params
    if budget_balance:
        bssmat, nssmat, r, w, T_H, factor = outer_loop_vars
    else:
        bssmat, nssmat, r, w, Y, T_H, factor = outer_loop_vars

    euler_errors = np.zeros((2 * S, J))

    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            guesses = np.append(bssmat[:, j], nssmat[:, j])
        else:
            guesses = np.append(bssmat[:, j - 1], nssmat[:, j - 1])
        euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver,
                                                         guesses * .9,
                                                         args=euler_params,
                                                         xtol=MINIMIZER_TOL,
                                                         full_output=True)

        euler_errors[:, j] = infodict['fvec']
        #  print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max()

        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]

    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = aggr.get_L(nssmat, L_params)
    if small_open == False:
        K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates,
                    g_n_ss, 'SS')
        B = aggr.get_K(bssmat, K_params)
        if budget_balance:
            K = B
        else:
            K = B - debt_ratio_ss * Y
    else:
        K_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        K = firm.get_K(L, ss_firm_r, K_params)
    # Y_params = (alpha, Z)
    Y_params = (Z, gamma, epsilon)
    new_Y = firm.get_Y(K, L, Y_params)
    #print 'inner K, L, Y: ', K, L, new_Y
    if budget_balance:
        Y = new_Y
    if small_open == False:
        r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        new_r = firm.get_r(Y, K, r_params)
    else:
        new_r = ss_hh_r
    w_params = (Z, gamma, epsilon)
    new_w = firm.get_w(Y, L, w_params)
    print 'inner factor prices: ', new_r, new_w

    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    if baseline:
        new_factor = mean_income_data / average_income_model
    else:
        new_factor = factor

    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J),
                 rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = aggr.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, S, retire)
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    if budget_balance:
        T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS',
                      etr_params, theta, tau_bq, tau_payroll, h_wealth,
                      p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)
        new_T_H = aggr.revenue(new_r, new_w, b_s, nssmat, new_BQ, new_Y, L, K,
                               factor, T_H_params)
    elif baseline_spending:
        new_T_H = T_H
    else:
        new_T_H = alpha_T * new_Y

    return euler_errors, bssmat, nssmat, new_r, new_w, \
         new_T_H, new_Y, new_factor, new_BQ, average_income_model
Example #9
0
def SS_solver(b_guess_init,
              n_guess_init,
              rss,
              wss,
              T_Hss,
              factor_ss,
              Yss,
              params,
              baseline,
              fsolve_flag=False,
              baseline_spending=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
    --------------------------------------------------------------------
    '''

    bssmat, nssmat, chi_params, ss_params, income_tax_params, iterative_params, small_open_params = params
    J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, budget_balance, \
                  alpha_T, debt_ratio_ss, tau_b, delta_tau,\
                  lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params

    chi_b, chi_n = chi_params

    maxiter, mindist_SS = iterative_params

    small_open, ss_firm_r, ss_hh_r = small_open_params

    # Rename the inputs
    r = rss
    w = wss
    T_H = T_Hss
    factor = factor_ss
    if budget_balance == False:
        if baseline_spending == True:
            Y = Yss
        else:
            Y = T_H / alpha_T
    if small_open == True:
        r = ss_hh_r

    dist = 10
    iteration = 0
    dist_vec = np.zeros(maxiter)

    if fsolve_flag == True:
        maxiter = 1

    while (dist > mindist_SS) and (iteration < maxiter):
        # Solve for the steady state levels of b and n, given w, r, Y and
        # factor
        if budget_balance:
            outer_loop_vars = (bssmat, nssmat, r, w, T_H, factor)
        else:
            outer_loop_vars = (bssmat, nssmat, r, w, Y, T_H, factor)
        inner_loop_params = (ss_params, income_tax_params, chi_params,
                             small_open_params)

        euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_Y, new_factor, new_BQ, average_income_model = inner_loop(outer_loop_vars, inner_loop_params, baseline, baseline_spending)

        r = utils.convex_combo(new_r, r, nu)
        w = utils.convex_combo(new_w, w, nu)
        factor = utils.convex_combo(new_factor, factor, nu)
        if budget_balance:
            T_H = utils.convex_combo(new_T_H, T_H, nu)
            dist = np.array([utils.pct_diff_func(new_r, r)] +
                            [utils.pct_diff_func(new_w, w)] +
                            [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)
            if Y != 0:
                dist = np.array(
                    [utils.pct_diff_func(new_r, r)] +
                    [utils.pct_diff_func(new_w, w)] +
                    [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)] +
                    [utils.pct_diff_func(new_w, w)] + [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 /= 2.0
                print 'New value of nu:', nu
        iteration += 1
        print "Iteration: %02d" % iteration, " Distance: ", dist
    '''
    ------------------------------------------------------------------------
        Generate the SS values of variables, including euler errors
    ------------------------------------------------------------------------
    '''
    bssmat_s = np.append(np.zeros((1, J)), bssmat[:-1, :], axis=0)
    bssmat_splus1 = bssmat

    rss = r
    wss = w
    factor_ss = factor
    T_Hss = T_H

    Lss_params = (e, omega_SS.reshape(S, 1), lambdas, 'SS')
    Lss = aggr.get_L(nssmat, Lss_params)
    if small_open == False:
        Kss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS')
        Bss = aggr.get_K(bssmat_splus1, Kss_params)
        if budget_balance:
            debt_ss = 0.0
        else:
            debt_ss = debt_ratio_ss * Y
        Kss = Bss - debt_ss
        Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS')
        Iss = aggr.get_I(bssmat_splus1, Kss, Kss, Iss_params)
    else:
        # Compute capital (K) and wealth (B) separately
        Kss_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        Kss = firm.get_K(Lss, ss_firm_r, Kss_params)
        Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS')
        InvestmentPlaceholder = np.zeros(bssmat_splus1.shape)
        Iss = aggr.get_I(InvestmentPlaceholder, Kss, Kss, Iss_params)
        Bss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS')
        Bss = aggr.get_K(bssmat_splus1, Bss_params)
        BIss_params = (0.0, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS')
        BIss = aggr.get_I(bssmat_splus1, Bss, Bss, BIss_params)
        if budget_balance:
            debt_ss = 0.0
        else:
            debt_ss = debt_ratio_ss * Y

    # Yss_params = (alpha, Z)
    Yss_params = (Z, gamma, epsilon)
    Yss = firm.get_Y(Kss, Lss, Yss_params)

    # Verify that T_Hss = alpha_T*Yss
    #    transfer_error = T_Hss - alpha_T*Yss
    #    if np.absolute(transfer_error) > mindist_SS:
    #        print 'Transfers exceed alpha_T percent of GDP by:', transfer_error
    #        err = "Transfers do not match correct share of GDP in SS_solver"
    #        raise RuntimeError(err)

    BQss = new_BQ
    theta_params = (e, S, retire)
    theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, theta_params)

    # Next 5 lines pulled out of inner_loop where they are used to calculate tax revenue. Now calculating G to balance gov't budget.
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    lump_sum_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS',
                       etr_params, theta, tau_bq, tau_payroll, h_wealth,
                       p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)
    revenue_ss = aggr.revenue(new_r, new_w, b_s, nssmat, new_BQ, Yss, Lss, Kss,
                              factor, lump_sum_params)
    r_gov_ss = rss
    debt_service_ss = r_gov_ss * debt_ratio_ss * Yss
    new_borrowing = debt_ratio_ss * Yss * ((1 + g_n_ss) * np.exp(g_y) - 1)
    # government spends such that it expands its debt at the same rate as GDP
    if budget_balance:
        Gss = 0.0
    else:
        Gss = revenue_ss + new_borrowing - (T_Hss + debt_service_ss)

    # solve resource constraint
    etr_params_3D = np.tile(
        np.reshape(etr_params, (S, 1, etr_params.shape[1])), (1, J, 1))
    mtrx_params_3D = np.tile(
        np.reshape(mtrx_params, (S, 1, mtrx_params.shape[1])), (1, J, 1))
    '''
    ------------------------------------------------------------------------
        The code below is to calulate and save model MTRs
                - only exists to help debug
    ------------------------------------------------------------------------
    '''
    # etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:]
    # etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1))
    # mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:]
    # mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1))
    # e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J)))
    # nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J)))
    # mtry_ss_params = (e_extended[1:,:], etr_params_extended_3D, mtry_params_extended_3D, analytical_mtrs)
    # mtry_ss = tax.MTR_capital(rss, wss, bssmat_splus1, nss_extended[1:,:], factor_ss, mtry_ss_params)
    # mtrx_ss_params = (e, etr_params_3D, mtrx_params_3D, analytical_mtrs)
    # mtrx_ss = tax.MTR_labor(rss, wss, bssmat_s, nssmat, factor_ss, mtrx_ss_params)

    # np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",")
    # np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",")

    # solve resource constraint
    taxss_params = (e, lambdas, 'SS', retire, etr_params_3D, h_wealth,
                    p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    taxss = tax.total_taxes(rss, wss, bssmat_s, nssmat, BQss, factor_ss, T_Hss,
                            None, False, taxss_params)
    css_params = (e, lambdas.reshape(1, J), g_y)
    cssmat = household.get_cons(rss, wss, bssmat_s, bssmat_splus1, nssmat,
                                BQss.reshape(1, J), taxss, css_params)

    biz_params = (tau_b, delta_tau)
    business_revenue = tax.get_biz_tax(wss, Yss, Lss, Kss, biz_params)

    Css_params = (omega_SS.reshape(S, 1), lambdas, 'SS')
    Css = aggr.get_C(cssmat, Css_params)

    if small_open == False:
        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:', revenue_ss / Yss, 'business rev/Y: ', business_revenue / Yss, 'Int payments to GDP:', (
            rss * debt_ss) / Yss
        print 'Check SS budget: ', Gss - (np.exp(g_y) * (1 + g_n_ss) - 1 -
                                          rss) * debt_ss - revenue_ss + T_Hss
        print 'resource constraint: ', resource_constraint
    else:
        # include term for current account
        resource_constraint = Yss + new_borrowing - (Css + BIss + Gss) + (
            ss_hh_r * Bss - (delta + ss_firm_r) * 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:', revenue_ss / Yss, 'Int payments to GDP:', (
            rss * debt_ss) / Yss
        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) > 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, nssmat, cssmat, ltilde)

    euler_savings = euler_errors[:S, :]
    euler_labor_leisure = euler_errors[S:, :]
    '''
    ------------------------------------------------------------------------
        Return dictionary of SS results
    ------------------------------------------------------------------------
    '''
    output = {
        'Kss': Kss,
        'bssmat': bssmat,
        'Bss': Bss,
        'Lss': Lss,
        'Css': Css,
        'Iss': Iss,
        'nssmat': nssmat,
        'Yss': Yss,
        'wss': wss,
        'rss': rss,
        'theta': theta,
        'BQss': BQss,
        'factor_ss': factor_ss,
        'bssmat_s': bssmat_s,
        'cssmat': cssmat,
        'bssmat_splus1': bssmat_splus1,
        'T_Hss': T_Hss,
        'Gss': Gss,
        'revenue_ss': revenue_ss,
        'euler_savings': euler_savings,
        'euler_labor_leisure': euler_labor_leisure,
        'chi_n': chi_n,
        'chi_b': chi_b
    }

    return output
Example #10
0
def run_steady_state(ss_parameters,
                     iterative_params,
                     get_baseline=False,
                     calibrate_model=False,
                     output_dir="./OUTPUT"):
    '''
    ------------------------------------------------------------------------
        Run SS
    ------------------------------------------------------------------------
    '''

    if get_baseline:
        # Generate initial guesses for chi^b_j and chi^n_s
        chi_params = np.zeros(S + J)
        chi_params[:J] = chi_b_guess
        chi_params[J:] = chi_n_guess
        # First run SS simulation with guesses at initial values for b, n, w, r, etc
        # For inital guesses of b and n, we choose very small b, and medium n
        b_guess = np.ones((S, J)).flatten() * .01
        n_guess = np.ones((S, J)).flatten() * .5 * ltilde
        # For initial guesses of w, r, T_H, and factor, we use values that are close
        # to some steady state values.
        wguess = 1.2
        rguess = .06
        T_Hguess = 0
        factorguess = 100000
        solutions = SS_solver(b_guess.reshape(S,
                                              J), n_guess.reshape(S,
                                                                  J), wguess,
                              rguess, T_Hguess, factorguess, chi_params[J:],
                              chi_params[:J], ss_parameters, iterative_params,
                              tau_bq, rho, lambdas, omega_SS, e)

        if calibrate_model:
            outputs = {'solutions': solutions, 'chi_params': chi_params}
            ss_init_path = os.path.join(output_dir,
                                        "Saved_moments/SS_init_solutions.pkl")
            pickle.dump(outputs, open(ss_init_path, "wb"))
            function_to_minimize_X = lambda x: function_to_minimize(
                x, chi_params, ss_parameters, iterative_params, omega_SS, rho,
                lambdas, tau_bq, e, output_dir)
            bnds = tuple([(1e-6, None)] * (S + J))
            # In order to scale all the parameters to estimate in the minimizer, we have the minimizer fit a vector of ones that
            # will be multiplied by the chi initial guesses inside the function.  Otherwise, if chi^b_j=1e5 for some j, and the
            # minimizer peturbs that value by 1e-8, the % difference will be extremely small, outside of the tolerance of the
            # minimizer, and it will not change that parameter.
            chi_params_scalars = np.ones(S + J)
            chi_params_scalars = opt.minimize(function_to_minimize_X,
                                              chi_params_scalars,
                                              method='TNC',
                                              tol=MINIMIZER_TOL,
                                              bounds=bnds,
                                              options=MINIMIZER_OPTIONS).x
            chi_params *= chi_params_scalars
            print 'The final scaling params', chi_params_scalars
            print 'The final bequest parameter values:', chi_params

            solutions_dict = pickle.load(open(ss_init_path, "rb"))
            solutions = solutions_dict['solutions']
            b_guess = solutions[:S * J]
            n_guess = solutions[S * J:2 * S * J]
            wguess, rguess, factorguess, T_Hguess = solutions[2 * S * J:]
            solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J),
                                  wguess, rguess, T_Hguess, factorguess,
                                  chi_params[J:], chi_params[:J],
                                  ss_parameters, iterative_params, tau_bq, rho,
                                  lambdas, omega_SS, e)
    else:
        variables = pickle.load(open(ss_init_path, "rb"))
        solutions = solutions_dict['solutions']
        chi_params = solutions_dict['chi_params']
        b_guess = solutions[:S * J]
        n_guess = solutions[S * J:2 * S * J]
        wguess, rguess, factorguess, T_Hguess = solutions[2 * S * J:]
        solutions = SS_solver(b_guess.reshape(S,
                                              J), n_guess.reshape(S,
                                                                  J), wguess,
                              rguess, T_Hguess, factorguess, chi_params[J:],
                              chi_params[:J], ss_parameters, iterative_params,
                              tau_bq, rho, lambdas, omega_SS, e)
    '''
    ------------------------------------------------------------------------
        Generate the SS values of variables, including euler errors
    ------------------------------------------------------------------------
    '''

    if get_baseline:
        outputs = {'solutions': solutions, 'chi_params': chi_params}
        ss_init_dir = os.path.join(output_dir,
                                   "Saved_moments/SS_init_solutions.pkl")
        pickle.dump(outputs, open(ss_init_dir, "wb"))
    else:
        outputs = {'solutions': solutions, 'chi_params': chi_params}
        ss_exp_dir = os.path.join(output_dir,
                                  "Saved_moments/SS_experiment_solutions.pkl")
        pickle.dump(outputs, open(ss_exp_dir, "wb"))

    bssmat = solutions[0:(S - 1) * J].reshape(S - 1, J)
    bq = solutions[(S - 1) * J:S * J]
    bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat))
    bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J)))
    nssmat = solutions[S * J:2 * S * J].reshape(S, J)
    wss, rss, factor_ss, T_Hss = solutions[2 * S * J:]

    Kss = household.get_K(bssmat_splus1, omega_SS.reshape(S, 1), lambdas,
                          g_n_ss, 'SS')
    Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas, 'SS')
    Yss = firm.get_Y(Kss, Lss, ss_parameters)

    Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss)

    theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, e, J,
                                      omega_SS.reshape(S, 1), lambdas)
    BQss = household.get_BQ(rss, bssmat_splus1, omega_SS.reshape(S, 1),
                            lambdas, rho.reshape(S, 1), g_n_ss, 'SS')
    b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat))
    taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas, factor_ss,
                            T_Hss, None, 'SS', False, ss_parameters, theta,
                            tau_bq)
    cssmat = household.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape(1, J),
                                lambdas.reshape(1, J), bssmat_splus1,
                                ss_parameters, taxss)

    Css = household.get_C(cssmat, omega_SS.reshape(S, 1), lambdas, 'SS')

    resource_constraint = Yss - (Css + Iss)

    print 'Resource Constraint Difference:', resource_constraint

    household.constraint_checker_SS(bssmat, nssmat, cssmat, ss_parameters)

    b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat))
    b_splus1 = bssmat_splus1
    b_splus2 = np.array(
        list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J))))

    chi_b = np.tile(chi_params[:J].reshape(1, J), (S, 1))
    chi_n = np.array(chi_params[J:])
    euler_savings = np.zeros((S, J))
    euler_labor_leisure = np.zeros((S, J))
    for j in xrange(J):
        euler_savings[:, j] = household.euler_savings_func(
            wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j],
            b_splus2[:, j], BQss[j], factor_ss, T_Hss, chi_b[:, j],
            ss_parameters, theta[j], tau_bq[j], rho, lambdas[j])
        euler_labor_leisure[:, j] = household.euler_labor_leisure_func(
            wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j],
            BQss[j], factor_ss, T_Hss, chi_n, ss_parameters, theta[j],
            tau_bq[j], lambdas[j])
    '''
    ------------------------------------------------------------------------
        Save the values in various ways, depending on the stage of
            the simulation, to be used in TPI or graphing functions
    ------------------------------------------------------------------------
    '''

    # Pickle variables
    output = {
        'Kss': Kss,
        'bssmat': bssmat,
        'Lss': Lss,
        'nssmat': nssmat,
        'Yss': Yss,
        'wss': wss,
        'rss': rss,
        'theta': theta,
        'BQss': BQss,
        'factor_ss': factor_ss,
        'bssmat_s': bssmat_s,
        'cssmat': cssmat,
        'bssmat_splus1': bssmat_splus1,
        'T_Hss': T_Hss,
        'euler_savings': euler_savings,
        'euler_labor_leisure': euler_labor_leisure,
        'chi_n': chi_n,
        'chi_b': chi_b
    }
    if get_baseline:
        utils.mkdirs(os.path.join(output_dir, "SSinit"))
        ss_init_dir = os.path.join(output_dir, "SSinit/ss_init_vars.pkl")
        pickle.dump(output, open(ss_init_dir, "wb"))
        bssmat_init = bssmat_splus1
        nssmat_init = nssmat
        # Pickle variables for TPI initial values
        output2 = {'bssmat_init': bssmat_init, 'nssmat_init': nssmat_init}
        ss_init_tpi = os.path.join(output_dir, "SSinit/ss_init_tpi_vars.pkl")
        pickle.dump(output2, open(ss_init_tpi, "wb"))
    else:
        utils.mkdirs(os.path.join(output_dir, "SS"))
        ss_vars = os.path.join(output_dir, "SS/ss_vars.pkl")
        pickle.dump(output, open(ss_vars, "wb"))
    return output
Example #11
0
def run_TPI(income_tax_params, tpi_params, iterative_params,
            initial_values, SS_values, fix_transfers=False,
            output_dir="./OUTPUT"):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params
    K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP = initial_values
    Kss, Lss, rss, wss, BQss, T_Hss, Gss, bssmat_splus1, nssmat = SS_values


    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    domain = np.linspace(0, T, T)
    r = np.ones(T + S) * rss
    BQ = np.zeros((T + S, J))
    BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r[0], initial_b, BQ0_params)
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    # print "BQ values = ", BQ[0, :], BQ[100, :], BQ[-1, :], BQss
    # print "K0 vs Kss = ", K0-Kss

    if fix_transfers:
        T_H = T_H_baseline
    else:
        if np.abs(T_Hss) < 1e-13 :
            T_Hss2 = 0.0 # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below
        else:
            T_Hss2 = T_Hss
        T_H = np.ones(T + S) * T_Hss2 * (r/rss)
    G = np.ones(T + S) * Gss
    # # print "T_H values = ", T_H[0], T_H[100], T_H[-1], T_Hss
    # # print "omega diffs = ", (omega_S_preTP-omega[-1]).max(), (omega[10]-omega[-1]).max()
    #
    # Make array of initial guesses for labor supply and savings
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)
    # print 'diff btwn start and end b: ', (guesses_b[0]-guesses_b[-1]).max()
    #
    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    # b_mat = np.zeros((T + S, S, J))
    # n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)
    # # print 'diff btwn start and end n: ', (guesses_n[0]-guesses_n[-1]).max()
    #
    # # find economic aggregates
    K = np.zeros(T+S)
    L = np.zeros(T+S)
    K[0] = K0
    K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI')
    K[1:T] = household.get_K(guesses_b[:T-1], K_params)
    K[T:] = Kss
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
    L[:T] = firm.get_L(guesses_n[:T], L_params)
    L[T:] = Lss
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    r[:T] = firm.get_r(Y[:T], K[:T], r_params)

    # uncomment lines below if want to use starting values from prior run
    r = TPI_START_VALUES['r']
    K = TPI_START_VALUES['K']
    L = TPI_START_VALUES['L']
    Y = TPI_START_VALUES['Y']
    T_H = TPI_START_VALUES['T_H']
    BQ = TPI_START_VALUES['BQ']
    G = TPI_START_VALUES['G']

    guesses_b = TPI_START_VALUES['b_mat']
    guesses_n = TPI_START_VALUES['n_mat']


    TPIiter = 0
    TPIdist = 10
    PLOT_TPI = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    # print 'analytical mtrs in tpi = ', analytical_mtrs

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            K_plot = list(K) + list(np.ones(10) * Kss)
            L_plot = list(L) + list(np.ones(10) * Lss)
            plt.figure()
            plt.axhline(
                y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
            plt.plot(np.arange(
                T + 10), Kpath_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))


        guesses = (guesses_b, guesses_n)
        w_params = (Z, alpha, delta)
        w = firm.get_w_from_r(r, w_params)
        # print 'r and rss diff = ', r-rss
        # print 'w and wss diff = ', w-wss
        # print 'BQ and BQss diff = ', BQ-BQss
        # print 'T_H and T_Hss diff = ', T_H - T_Hss
        # print 'guess b and bss = ', (bssmat_splus1 - guesses_b).max()
        # print 'guess n and nss = ', (nssmat - guesses_n).max()
        outer_loop_vars = (r, w, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)

        # print 'guess b and bss = ', (b_mat - guesses_b).max()
        # print 'guess n and nss over time = ', (n_mat - guesses_n).max(axis=2).max(axis=1)
        # print 'guess n and nss over age = ', (n_mat - guesses_n).max(axis=0).max(axis=1)
        # print 'guess n and nss over ability = ', (n_mat - guesses_n).max(axis=0).max(axis=0)
        # quit()

        print 'Max Euler error: ', (np.abs(euler_errors)).max()

        bmat_s = np.zeros((T, S, J))
        bmat_s[0, 1:, :] = initial_b[:-1, :]
        bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[:T, :, :]

        K[0] = K0
        K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J),
                    imm_rates[:T-1].reshape(T-1, S, 1), g_n_vector[1:T], 'TPI')
        K[1:T] = household.get_K(bmat_splus1[:T-1], K_params)
        L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                    lambdas.reshape(1, 1, J), 'TPI')
        L[:T] = firm.get_L(n_mat[:T], L_params)
        # print 'K diffs = ', K-K0
        # print 'L diffs = ', L-L[0]

        Y_params = (alpha, Z)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        r_params = (alpha, delta)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)
        wnew = firm.get_w_from_r(rnew, w_params)

        omega_shift = np.append(omega_S_preTP.reshape(1, S),
                                omega[:T-1, :], axis=0)
        BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J),
                     rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
        # b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)),
        #                         b_mat[:T-1, :, :], axis=0)
        b_mat_shift = bmat_splus1[:T, :, :]
        # print 'b diffs = ', (bmat_splus1[100, :, :] - initial_b).max(), (bmat_splus1[0, :, :] - initial_b).max(), (bmat_splus1[1, :, :] - initial_b).max()
        # print 'r diffs = ', rnew[1]-r[1], rnew[100]-r[100], rnew[-1]-r[-1]
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift,
                                 BQ_params)
        BQss2 = np.empty(J)
        for j in range(J):
            BQss_params = (omega[1, :], lambdas[j], rho, g_n_vector[1], 'SS')
            BQss2[j] = household.get_BQ(rnew[1], bmat_splus1[1, :, j],
                                        BQss_params)
        # print 'BQ test = ', BQss2-BQss, BQss-BQnew[1], BQss-BQnew[100], BQss-BQnew[-1]

        total_tax_params = np.zeros((T, S, J, etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            total_tax_params[:, :, :, i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

        tax_receipt_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
                total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
        net_tax_receipts = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
               bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S)

        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        if fix_transfers:
            T_H_new = T_H
            G[:T] = net_tax_receipts[:T] - T_H[:T]
        else:
            T_H_new = net_tax_receipts
            T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu)
            G[:T] = 0.0

        etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            etr_params_path[:,:,:,i] = np.tile(
                np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
        tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)),
                           lambdas, 'TPI', retire, etr_params_path, h_wealth,
                           p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
        b_to_use = np.zeros((T, S, J))
        b_to_use[0, 1:, :] = initial_b[:-1, :]
        b_to_use[1:, 1:, :] = b_mat[:T-1, :-1, :]
        tax_path = tax.total_taxes(
            np.tile(r[:T].reshape(T, 1, 1),(1,S,J)),
            np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), b_to_use,
            n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor,
            T_H[:T].reshape(T, 1, 1), None, False, tax_path_params)

        y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * b_to_use[:T, :, :] +
                  np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) *
                  np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :])
        cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
        c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), b_to_use[:T,:,:], b_mat[:T,:,:], n_mat[:T,:,:],
                       BQ[:T].reshape(T, 1, J), tax_path, cons_params)


        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)
        if T_H.all() != 0:
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) +
                               list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                               list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            print 'r dist = ', np.array(list(utils.pct_diff_func(rnew[:T], r[:T]))).max()
            print 'BQ dist = ', np.array(list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten())).max()
            print 'T_H dist = ', np.array(list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            print 'T_H path = ', T_H[:20]
            # print 'r old = ', r[:T]
            # print 'r new = ', rnew[:T]
            # print 'K old = ', K[:T]
            # print 'L old = ', L[:T]
            # print 'income = ', y_path[:, :, -1]
            # print 'taxes = ', tax_path[:, :, -1]
            # print 'labor supply = ', n_mat[:, :, -1]
            # print 'max and min labor = ', n_mat.max(), n_mat.min()
            # print 'max and min labor = ', np.argmax(n_mat), np.argmin(n_mat)
            # print 'max and min labor, j = 7 = ', n_mat[:,:,-1].max(), n_mat[:,:,-1].min()
            # print 'max and min labor, j = 6 = ', n_mat[:,:,-2].max(), n_mat[:,:,-2].min()
            # print 'max and min labor, j = 5 = ', n_mat[:,:,4].max(), n_mat[:,:,4].min()
            # print 'max and min labor, j = 4 = ', n_mat[:,:,3].max(), n_mat[:,:,3].min()
            # print 'max and min labor, j = 3 = ', n_mat[:,:,2].max(), n_mat[:,:,2].min()
            # print 'max and min labor, j = 2 = ', n_mat[:,:,1].max(), n_mat[:,:,1].min()
            # print 'max and min labor, j = 1 = ', n_mat[:,:,0].max(), n_mat[:,:,0].min()
            # print 'max and min labor, S = 80 = ', n_mat[:,-1,-1].max(), n_mat[:,-1,-1].min()
            # print "number  > 1 = ", (n_mat > 1).sum()
            # print "number  < 0, = ", (n_mat < 0).sum()
            # print "number  > 1, j=7 = ", (n_mat[:T,:,-1] > 1).sum()
            # print "number  < 0, j=7 = ", (n_mat[:T,:,-1] < 0).sum()
            # print "number  > 1, s=80, j=7 = ", (n_mat[:T,-1,-1] > 1).sum()
            # print "number  < 0, s=80, j=7 = ", (n_mat[:T,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 80= ", (n_mat[:T,-1,-1] > 1).sum()
            # print "number  < 0, j = 7, age 80= ", (n_mat[:T,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] > 1).sum()
            # print "number  < 0, j = 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80,-1] > 1).sum()
            # print "number  < 0, j = 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80   ,-1] < 0).sum()
            # diag_dict = {'n_mat': n_mat, 'b_mat': b_mat, 'y_path': y_path, 'c_path': c_path}
            # pickle.dump(diag_dict, open('tpi_iter1.pkl', 'wb'))

        else:
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) +
                               list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                               list(np.abs(T_H_new[:T]-T_H[: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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    Y[:T] = Ynew


    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)

    bmat_s = np.zeros((T, S, J))
    bmat_s[0, 1:, :] = initial_b[:-1, :]
    bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :]
    bmat_splus1 = np.zeros((T, S, J))
    bmat_splus1[:, :, :] = b_mat[:T, :, :]

    K[0] = K0
    K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI')
    K[1:T] = household.get_K(bmat_splus1[:T-1], K_params)
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
    L[:T]  = firm.get_L(n_mat[:T], L_params)

    Y_params = (alpha, Z)
    Ynew = firm.get_Y(K[:T], L[:T], Y_params)
    r_params = (alpha, delta)
    rnew = firm.get_r(Ynew[:T], K[:T], r_params)
    wnew = firm.get_w_from_r(rnew, w_params)

    omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0)
    BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1),
                 g_n_vector[:T].reshape(T, 1), 'TPI')
    b_mat_shift = np.append(np.reshape(initial_b,(1,S,J)),b_mat[:T-1,:,:],axis=0)
    BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params)

    total_tax_params = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        total_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

    tax_receipt_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
            total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    net_tax_receipts = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
           bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S)

    if fix_transfers:
        G[:T] = net_tax_receipts[:T] - T_H[:T]
    else:
        T_H[:T] = net_tax_receipts[:T]
        G[:T] = 0.0

    etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
    tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas, 'TPI', retire, etr_params_path, h_wealth,
                       p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), bmat_s,
                               n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params)

    cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T,:,:],
                   BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)
    I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI')
    I = firm.get_I(bmat_splus1[:T], K[1:T+1], K[:T], I_params)
    rc_error = Y[:T] - C[:T] - I[:T] - G[:T]
    print 'Resource Constraint Difference:', rc_error

    # compute utility
    u_params = (sigma, np.tile(chi_n.reshape(1, S, 1), (T, 1, J)),
                b_ellipse, ltilde, upsilon,
                np.tile(rho.reshape(1, S, 1), (T, 1, J)),
                np.tile(chi_b.reshape(1, 1, J), (T, S, 1)))
    utility_path = household.get_u(c_path[:T, :, :], n_mat[:T, :, :],
                                   bmat_splus1[:T, :, :], u_params)

    # compute before and after-tax income
    y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * bmat_s[:T, :, :] +
              np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) *
              np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :])
    inctax_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), etr_params_path)
    y_aftertax_path = (y_path -
                       tax.tau_income(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)),
                                      np.tile(w[:T].reshape(T, 1, 1), (1, S, J)),
                                      bmat_s[:T,:,:], n_mat[:T,:,:], factor, inctax_params))

    # compute after-tax wealth
    wtax_params = (h_wealth, p_wealth, m_wealth)
    b_aftertax_path = bmat_s[:T,:,:] - tax.tau_wealth(bmat_s[:T,:,:], wtax_params)

    print'Checking time path for violations of constaints.'
    for t in xrange(T):
        household.constraint_checker_TPI(
            b_mat[t], n_mat[t], c_path[t], t, ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    print 'Max Euler error, savings: ', eul_savings
    print 'Max Euler error labor supply: ', eul_laborleisure



    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G,
              'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat,
              'c_path': c_path, 'tax_path': tax_path, 'bmat_s': bmat_s,
              'utility_path': utility_path, 'b_aftertax_path': b_aftertax_path,
              'y_aftertax_path': y_aftertax_path, 'y_path': y_path,
              'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure}

    macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I,
                    'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w,
                    'tax_path': tax_path}


    # if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS :
    #     raise RuntimeError("Transition path equlibrium not found")
    #
    # if ((np.any(np.absolute(rc_error) >= 1e-6))
    #     and ENFORCE_SOLUTION_CHECKS):
    #     raise RuntimeError("Transition path equlibrium not found")
    #
    # if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
    #     (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
    #     and ENFORCE_SOLUTION_CHECKS):
    #     raise RuntimeError("Transition path equlibrium not found")

    return output, macro_output
Example #12
0
def inner_loop(outer_loop_vars, params):
    '''
    This function solves for the inner loop of 
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, T_H, factor) 
    this function solves the households' 
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate 
        w          = [T,] vector, wage rate 
        b          = [T,S,J] array, wealth holdings 
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        T_H        = [T,] vector, lump sum transfer amount(s) 


    Functions called: 
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.get_lump_sum()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ
    
    '''

    # unpack variables and parameters pass to function
    bssmat, nssmat, r, w, T_H, factor = outer_loop_vars
    ss_params, income_tax_params, chi_params = params 

    J, S, T, BQ_dist, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params
    etr_params = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1))
    mtrx_params = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1))
    mtry_params = np.tile(np.reshape(mtry_params,(S,1,mtry_params.shape[1])),(1,J,1))


    euler_errors = np.zeros((2*S,J))

    
    guesses = np.hstack((bssmat, nssmat))
    euler_params = [r, w, T_H, factor, J, S, BQ_dist, beta, sigma, ltilde, g_y,\
              g_n_ss, tau_payroll, retire, mean_income_data,\
              h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
              chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
              analytical_mtrs, etr_params, mtrx_params,\
              mtry_params]

    [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9,
                               args=euler_params, xtol=MINIMIZER_TOL, full_output=True)

    euler_errors = infodict['fvec']
    print 'Max Euler errors: ', np.absolute(euler_errors).max()
    euler_errors = euler_errors.reshape(S, 2 *J)
    solutions = solutions.reshape(S, 2*J)
    
    bssmat = solutions[:, :J]
    nssmat = solutions[:, J:]

    K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS')
    K = household.get_K(bssmat, K_params)
    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    new_r = firm.get_r(Y, K, r_params)
    new_w = firm.get_w(Y, L, alpha)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    new_factor = mean_income_data / average_income_model
    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, J, omega_SS.reshape(S, 1), lambdas)
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    T_H_params = (e, BQ_dist, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                      tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params)

    return euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_factor, new_BQ, average_income_model
Example #13
0
def SS_solver(b_guess_init, n_guess_init, wss, rss, T_Hss, factor_ss, params, 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 = lenght 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()
    household.get_K()
    firm.get_L()
    firm.get_Y()
    firm.get_r()
    firm.get_w()
    household.get_BQ()
    tax.replacement_rate_vals()
    tax.get_lump_sum()
    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

    RETURNS: solutions = steady state values of b, n, w, r, factor,
                    T_H ((2*S*J+4)x1 array)
    
    OUTPUT: None
    --------------------------------------------------------------------
    '''
    
    bssmat, nssmat, chi_params, ss_params, income_tax_params, iterative_params = params 

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params

    chi_b, chi_n = chi_params

    maxiter, mindist_SS = iterative_params

    # Rename the inputs
    w = wss
    r = rss
    T_H = T_Hss
    factor = factor_ss
 
    dist = 10
    iteration = 0
    dist_vec = np.zeros(maxiter)

    if fsolve_flag == True:
        maxiter = 1 

    while (dist > mindist_SS) and (iteration < maxiter):
        # Solve for the steady state levels of b and n, given w, r, T_H and
        # factor

        outer_loop_vars = (bssmat, nssmat, r, w, T_H, factor)
        inner_loop_params = (ss_params, income_tax_params, chi_params)

        euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_factor, new_BQ, average_income_model = inner_loop(outer_loop_vars, inner_loop_params)

        r = utils.convex_combo(new_r, r, nu)
        w = utils.convex_combo(new_w, w, nu)
        factor = utils.convex_combo(new_factor, factor, nu)
        T_H = utils.convex_combo(new_T_H, T_H, nu)
        if T_H != 0:
            dist = np.array([utils.pct_diff_func(new_r, r)] +
                            [utils.pct_diff_func(new_w, w)] +
                            [utils.pct_diff_func(new_T_H, T_H)] +
                            [utils.pct_diff_func(new_factor, factor)]).max()
        else:
            # If T_H is zero (if there are no taxes), a percent difference
            # will throw NaN's, so we use an absoluate difference
            dist = np.array([utils.pct_diff_func(new_r, r)] +
                            [utils.pct_diff_func(new_w, w)] +
                            [abs(new_T_H - T_H)] +
                            [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 /= 2.0
                print 'New value of nu:', nu
        iteration += 1
        print "Iteration: %02d" % iteration, " Distance: ", dist

    '''
    ------------------------------------------------------------------------
        Generate the SS values of variables, including euler errors
    ------------------------------------------------------------------------
    '''
    bssmat_s = np.append(np.zeros((1,J)),bssmat[:-1,:],axis=0)
    bssmat_splus1 = bssmat

    wss = w
    rss = r
    factor_ss = factor
    T_Hss = T_H

    Kss_params = (omega_SS.reshape(S, 1), lambdas, g_n_ss, 'SS')
    Kss = household.get_K(bssmat_splus1, Kss_params)
    Lss_params = (e, omega_SS.reshape(S, 1), lambdas, 'SS')
    Lss = firm.get_L(nssmat, Lss_params)
    Yss_params = (alpha, Z)
    Yss = firm.get_Y(Kss, Lss, Yss_params)
    Iss_params = (delta, g_y, g_n_ss)
    Iss = firm.get_I(Kss, Kss, Iss_params)

    BQss = new_BQ 
    theta = np.zeros(J) # zero out payroll taxes since included in tax functions
    # # theta_params = (e, J, omega_SS.reshape(S, 1), lambdas)
    # # tax.replacement_rate_vals(nssmat, wss, factor_ss, theta_params)
    
    # solve resource constraint
    etr_params_3D = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1))
    mtrx_params_3D = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1))
    
    '''
    ------------------------------------------------------------------------
        The code below is to calulate and save model MTRs 
                - only exists help debug
    ------------------------------------------------------------------------
    '''
    # etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:]
    # etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1))
    # mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:]
    # mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1))
    # e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J))) 
    # nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J))) 
    # mtry_ss_params = (e_extended[1:,:], etr_params_extended_3D, mtry_params_extended_3D, analytical_mtrs)
    # mtry_ss = tax.MTR_capital(rss, wss, bssmat_splus1, nss_extended[1:,:], factor_ss, mtry_ss_params)
    # mtrx_ss_params = (e, etr_params_3D, mtrx_params_3D, analytical_mtrs)
    # mtrx_ss = tax.MTR_labor(rss, wss, bssmat_s, nssmat, factor_ss, mtrx_ss_params)

    # np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",")
    # np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",")

    # solve resource constraint
    taxss_params = (e, lambdas, 'SS', retire, etr_params_3D, 
                    h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    taxss = tax.total_taxes(rss, wss, bssmat_s, nssmat, BQss, factor_ss, T_Hss, None, False, taxss_params)
    css_params = (e, lambdas.reshape(1, J), g_y)
    cssmat = household.get_cons(rss, wss, bssmat_s, bssmat_splus1, nssmat, BQss.reshape(
        1, J), taxss, css_params)

    Css_params = (omega_SS.reshape(S, 1), lambdas, 'SS') 
    Css = household.get_C(cssmat, Css_params)

    resource_constraint = Yss - (Css + Iss)

    print 'Resource Constraint Difference:', resource_constraint

    if ENFORCE_SOLUTION_CHECKS and np.absolute(resource_constraint) > 1e-8:
        err = "Steady state aggregate resource constraint not satisfied"
        raise RuntimeError(err)

    # check constraints
    household.constraint_checker_SS(bssmat, nssmat, cssmat, ltilde)


    euler_savings = euler_errors[:S,:]
    euler_labor_leisure = euler_errors[S:,:]

    '''
    ------------------------------------------------------------------------
        Return dictionary of SS results
    ------------------------------------------------------------------------
    '''

    output = {'Kss': Kss, 'bssmat': bssmat, 'Lss': Lss, 'Css':Css, 'nssmat': nssmat, 'Yss': Yss,
              'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss,
              'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1,
              'T_Hss': T_Hss, 'euler_savings': euler_savings,
              'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n,
              'chi_b': chi_b}

    return output 
Example #14
0
def inner_loop(outer_loop_vars, params):
    '''
    This function solves for the inner loop of 
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, T_H, factor) 
    this function solves the households' 
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate 
        w          = [T,] vector, wage rate 
        b          = [T,S,J] array, wealth holdings 
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        T_H        = [T,] vector, lump sum transfer amount(s) 


    Functions called: 
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.get_lump_sum()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ
    
    '''

    # unpack variables and parameters pass to function
    bssmat, nssmat, r, w, T_H, factor = outer_loop_vars
    ss_params, income_tax_params, chi_params = params 

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params


    euler_errors = np.zeros((2*S,J))

    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            guesses = np.append(bssmat[:, j], nssmat[:, j])
        else:
            guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])
        euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9,
                                   args=euler_params, xtol=MINIMIZER_TOL, full_output=True)

        euler_errors[:,j] = infodict['fvec']
        print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max()
        
        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]

    K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS')
    K = household.get_K(bssmat, K_params)
    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    new_r = firm.get_r(Y, K, r_params)
    new_w = firm.get_w(Y, L, alpha)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    new_factor = mean_income_data / average_income_model
    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, J, omega_SS.reshape(S, 1), lambdas)
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                      tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params)

    return euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_factor, new_BQ, average_income_model
Example #15
0
def run_TPI(income_tax_params, tpi_params, iterative_params, initial_values, SS_values, output_dir="./OUTPUT"):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BQ_dist, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params
    K0, b_sinit, b_splus1init, L0, Y0,\
            w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n = initial_values
    Kss, Lss, rss, wss, BQss, T_Hss, bssmat_splus1, nssmat = SS_values


    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    domain = np.linspace(0, T, T)
    K_init = (-1 / (domain + 1)) * (Kss - K0) + Kss
    K_init[-1] = Kss
    K_init = np.array(list(K_init) + list(np.ones(S) * Kss))
    L_init = np.ones(T + S) * Lss

    K = K_init
    L = L_init
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    w = firm.get_w(Y, L, alpha)
    r_params = (alpha, delta)
    r = firm.get_r(Y, K, r_params)
    BQ = np.zeros((T + S, J))
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    if T_Hss < 1e-13 and T_Hss > 0.0 :
        T_Hss2 = 0.0 # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below
    else:
        T_Hss2 = T_Hss   
    T_H = np.ones(T + S) * T_Hss2

    # Make array of initial guesses for labor supply and savings
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)

    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    b_mat = np.zeros((T + S, S, J))
    n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)

    TPIiter = 0
    TPIdist = 10
    PLOT_TPI = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)


    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            K_plot = list(K) + list(np.ones(10) * Kss)
            L_plot = list(L) + list(np.ones(10) * Lss)
            plt.figure()
            plt.axhline(
                y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
            plt.plot(np.arange(
                T + 10), Kpath_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))
        # Uncomment the following print statements to make sure all euler equations are converging.
        # If they don't, then you'll have negative consumption or consumption spikes.  If they don't,
        # it is the initial guesses.  You might need to scale them differently.  It is rather delicate for the first
        # few periods and high ability groups.

        # theta_params = (e[-1, j], 1, omega[0].reshape(S, 1), lambdas[j])
        # theta = tax.replacement_rate_vals(n, w, factor, theta_params)
        theta = np.zeros((J,)) 

        guesses = (guesses_b, guesses_n)
        outer_loop_vars = (r, w, K, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values, theta, ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)


        # if euler_errors.max() > 1e-6:
        #     print 't-loop:', euler_errors.max()
        # Force the initial distribution of capital to be as given above.
        b_mat[0, :, :] = initial_b
        K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI')
        K[:T] = household.get_K(b_mat[:T], K_params)
        L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
        L[:T]  = firm.get_L(n_mat[:T], L_params)

        Y_params = (alpha, Z)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        wnew = firm.get_w(Ynew[:T], L[:T], alpha)
        r_params = (alpha, delta)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)

        BQ_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), 
                    g_n_vector[:T].reshape(T, 1), 'TPI')
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat[:T,:,:], BQ_params)
        bmat_s = np.zeros((T, S, J))
        bmat_s[:, 1:, :] = b_mat[:T, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[1:T + 1, :, :]

        TH_tax_params = np.zeros((T,S,J,etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            TH_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

        T_H_params = (np.tile(e.reshape(1, S, J),(T,1,1)), BQ_dist, lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', 
                TH_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
        T_H_new = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
               bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, T_H_params)) + [T_Hss] * S)

        w[:T] = utils.convex_combo(wnew[:T], w[:T], nu)
        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu)
        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)
        if T_H.all() != 0:
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                utils.pct_diff_func(wnew[:T], w[:T])) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
        else:
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                utils.pct_diff_func(wnew[:T], w[:T])) + list(np.abs(T_H_new[:T], T_H[: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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS :
        raise RuntimeError("Transition path equlibrium not found")


    Y[:T] = Ynew


    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, K, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, theta, ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)
    b_mat[0, :, :] = initial_b

    K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI')
    K[:T] = household.get_K(b_mat[:T], K_params) # this is what old code does, but it's strange - why use 
    # b_mat -- what is going on with initial period, etc.

    etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
    tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), BQ_dist, lambdas, 'TPI', retire, etr_params_path, h_wealth, 
                       p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), bmat_s, 
                               n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) 

    cons_params = (e.reshape(1, S, J), BQ_dist, lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(omega[:T].reshape(T,S,1), r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T,:,:], 
                   BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)
    I_params = (delta, g_y, g_n_vector[:T])
    I = firm.get_I(K[1:T+1], K[:T], I_params)
    print 'Resource Constraint Difference:', Y[:T] - C[:T] - I[:T]


    print'Checking time path for violations of constaints.'
    for t in xrange(T):
        household.constraint_checker_TPI(
            b_mat[t], n_mat[t], c_path[t], t, ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    print 'Max Euler error, savings: ', eul_savings
    print 'Max Euler error labor supply: ', eul_laborleisure

    if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
        (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
        and ENFORCE_SOLUTION_CHECKS):
        raise RuntimeError("Transition path equlibrium not found")

    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 
              'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 
              'c_path': c_path, 'tax_path': tax_path,
              'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure}

    tpi_dir = os.path.join(output_dir, "TPI")
    utils.mkdirs(tpi_dir)
    tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl")
    pickle.dump(output, open(tpi_vars, "wb"))
    
    macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I,
                    'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w, 
                    'tax_path': tax_path}

    # Non-stationary output
    # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path,
    #           'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path,
    #           'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path,
    #           'w_ns_path': w_ns_path}


    return output, macro_output
Example #16
0
def SS_solver(b_guess_init,
              n_guess_init,
              wguess,
              rguess,
              T_Hguess,
              factorguess,
              chi_n,
              chi_b,
              tax_params,
              params,
              iterative_params,
              tau_bq,
              rho,
              lambdas,
              weights,
              e,
              fsolve_flag=False):
    '''
    Solves for the steady state distribution of capital, labor, as well as
    w, r, T_H and the scaling factor, using an iterative method similar to TPI.
    Inputs:
        b_guess_init = guesses for b (SxJ array)
        n_guess_init = guesses for n (SxJ array)
        wguess = guess for wage rate (scalar)
        rguess = guess for rental rate (scalar)
        T_Hguess = guess for lump sum tax (scalar)
        factorguess = guess for scaling factor to dollars (scalar)
        chi_n = chi^n_s (Sx1 array)
        chi_b = chi^b_j (Jx1 array)
        params = list of parameters (list)
        iterative_params = list of parameters that determine the convergence
                           of the while loop (list)
        tau_bq = bequest tax rate (Jx1 array)
        rho = mortality rates (Sx1 array)
        lambdas = ability weights (Jx1 array)
        weights = population weights (Sx1 array)
        e = ability levels (SxJ array)
    Outputs:
        solutions = steady state values of b, n, w, r, factor,
                    T_H ((2*S*J+4)x1 array)
    '''

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_params

    maxiter, mindist_SS = iterative_params
    # Rename the inputs
    w = wguess
    r = rguess
    T_H = T_Hguess
    factor = factorguess
    bssmat = b_guess_init
    nssmat = n_guess_init

    dist = 10
    iteration = 0
    dist_vec = np.zeros(maxiter)

    if fsolve_flag == True:
        maxiter = 1

    while (dist > mindist_SS) and (iteration < maxiter):
        # Solve for the steady state levels of b and n, given w, r, T_H and
        # factor
        for j in xrange(J):
            # Solve the euler equations
            if j == 0:
                guesses = np.append(bssmat[:, j], nssmat[:, j])
            else:
                guesses = np.append(bssmat[:, j - 1], nssmat[:, j - 1])

            args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n,
                     tau_bq, rho, lambdas, weights, e)
            [solutions, infodict, ier,
             message] = opt.fsolve(Euler_equation_solver,
                                   guesses * .9,
                                   args=args_,
                                   xtol=1e-13,
                                   full_output=True)

            print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()

            bssmat[:, j] = solutions[:S]
            nssmat[:, j] = solutions[S:]
            # print np.array(Euler_equation_solver(np.append(bssmat[:, j],
            # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n,
            # theta, tau_bq, rho, lambdas, e)).max()

        K = household.get_K(bssmat, weights.reshape(S, 1),
                            lambdas.reshape(1, J), g_n_ss, 'SS')
        L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J),
                       'SS')
        Y = firm.get_Y(K, L, params)
        new_r = firm.get_r(Y, K, params)
        new_w = firm.get_w(Y, L, params)
        b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
        average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                                weights.reshape(S, 1) *
                                lambdas.reshape(1, J)).sum()
        new_factor = mean_income_data / average_income_model
        new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1),
                                  lambdas.reshape(1, J), rho.reshape(S, 1),
                                  g_n_ss, 'SS')
        theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J,
                                          weights.reshape(S, 1), lambdas)
        # lump_sum_tax_params = (a_etr_income, b_etr_income, c_etr_income, d_etr_income,
        #                    e_etr_income, f_etr_income, min_x_etr_income, max_x_etr_income,
        #                    min_y_etr_income, max_y_etr_income)
        new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ,
                                   lambdas.reshape(1, J), factor,
                                   weights.reshape(S, 1), 'SS', etr_params,
                                   params, theta, tau_bq)

        r = utils.convex_combo(new_r, r, nu)
        w = utils.convex_combo(new_w, w, nu)
        factor = utils.convex_combo(new_factor, factor, nu)
        T_H = utils.convex_combo(new_T_H, T_H, nu)
        if T_H != 0:
            dist = np.array([utils.perc_dif_func(new_r, r)] +
                            [utils.perc_dif_func(new_w, w)] +
                            [utils.perc_dif_func(new_T_H, T_H)] +
                            [utils.perc_dif_func(new_factor, factor)]).max()
        else:
            # If T_H is zero (if there are no taxes), a percent difference
            # will throw NaN's, so we use an absoluate difference
            dist = np.array([utils.perc_dif_func(new_r, r)] +
                            [utils.perc_dif_func(new_w, w)] +
                            [abs(new_T_H - T_H)] +
                            [utils.perc_dif_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 /= 2.0
                print 'New value of nu:', nu
        iteration += 1
        print "Iteration: %02d" % iteration, " Distance: ", dist

    eul_errors = np.ones(J)
    b_mat = np.zeros((S, J))
    n_mat = np.zeros((S, J))
    # Given the final w, r, T_H and factor, solve for the SS b and n (if you
    # don't do a final fsolve, there will be a slight mismatch,
    # with high euler errors)
    for j in xrange(J):
        guesses = np.append(bssmat[:, j], nssmat[:, j])
        args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n,
                 tau_bq, rho, lambdas, weights, e)
        [solutions1, infodict, ier,
         message] = opt.fsolve(Euler_equation_solver,
                               guesses * .9,
                               args=args_,
                               xtol=1e-13,
                               full_output=True)
        eul_errors[j] = np.array(infodict['fvec']).max()
        print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()
        b_mat[:, j] = solutions1[:S]
        n_mat[:, j] = solutions1[S:]
    print 'SS fsolve euler error:', eul_errors.max()
    solutions = np.append(b_mat.flatten(), n_mat.flatten())
    other_vars = np.array([w, r, factor, T_H])
    solutions = np.append(solutions, other_vars)
    return solutions
Example #17
0
def inner_loop(outer_loop_vars, params, baseline):
    '''
    This function solves for the inner loop of
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, T_H, factor)
    this function solves the households'
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate
        w          = [T,] vector, wage rate
        b          = [T,S,J] array, wealth holdings
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        T_H        = [T,] vector, lump sum transfer amount(s)


    Functions called:
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.get_lump_sum()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ

    '''

    # unpack variables and parameters pass to function
    bssmat, nssmat, r, w, T_H, BQ, theta, factor = outer_loop_vars
    ss_params, income_tax_params, chi_params = params

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params

    # bssmat = START_VALUES['bssmat_splus1']
    # nssmat = START_VALUES['nssmat']
    cssmat = np.zeros((S, J))
    euler_errors = np.zeros((2 * S, J))

    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            b_Sp1_guess = bssmat[-1, j]
        else:
            b_Sp1_guess = bssmat[-1, j - 1] * 10

        euler_params = [r, w, T_H, BQ, theta, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solution, infodict, ier, message] = opt.fsolve(lc_error,
                                                        b_Sp1_guess,
                                                        args=euler_params,
                                                        xtol=MINIMIZER_TOL,
                                                        full_output=True)
        # [x0, r_out] = opt.bisect(lc_error, -1.0, 10.0, args=euler_params, xtol=MINIMIZER_TOL, full_output=True, disp=False)
        print 'j = ', j
        print 'b[0] error = ', infodict['fvec']
        print 'message: ', message
        # print 'b[S]= ', x0
        # print 'converged= ', r_out.converged

        b_out, nssmat[:,
                      j], cssmat[:,
                                 j] = lifecycle_solver(solution, euler_params)
        bssmat[:, j] = b_out[1:]
        # print solutions
        # quit()
        #
        # euler_errors[:,j] = infodict['fvec']
        # print 'j = ', j
        # print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max()
    # print 'bssmat: ', bssmat
    # print 'nssmat: ', nssmat
    # print 'cssmat: ', cssmat
    quit()
    K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates,
                g_n_ss, 'SS')
    K = household.get_K(bssmat, K_params)
    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    new_r = firm.get_r(Y, K, r_params)
    new_w = firm.get_w(Y, L, alpha)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    if baseline:
        new_factor = mean_income_data / average_income_model
    else:
        new_factor = factor

    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J),
                 rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, S, J, omega_SS.reshape(S, 1), lambdas, retire)
    new_theta = tax.replacement_rate_vals(nssmat, new_w, new_factor,
                                          theta_params)

    T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS',
                  etr_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth,
                  m_wealth, retire, T, S, J)
    new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor,
                               T_H_params)

    print 'Inner Loop Max Euler Error: ', (np.absolute(euler_errors)).max()
    # print 'K: ', K
    # print 'L: ', L
    #print 'bssmat: ', bssmat
    return euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_BQ, new_theta, new_factor, average_income_model
Example #18
0
def SS_fsolve(guesses, b_guess_init, n_guess_init, chi_n, chi_b, tax_params,
              params, iterative_params, tau_bq, rho, lambdas, weights, e):
    '''
    Solves for the steady state distribution of capital, labor, as well as
    w, r, T_H and the scaling factor, using an iterative method similar to TPI.
    Inputs:
        b_guess_init = guesses for b (SxJ array)
        n_guess_init = guesses for n (SxJ array)
        wguess = guess for wage rate (scalar)
        rguess = guess for rental rate (scalar)
        T_Hguess = guess for lump sum tax (scalar)
        factorguess = guess for scaling factor to dollars (scalar)
        chi_n = chi^n_s (Sx1 array)
        chi_b = chi^b_j (Jx1 array)
        params = list of parameters (list)
        iterative_params = list of parameters that determine the convergence
                           of the while loop (list)
        tau_bq = bequest tax rate (Jx1 array)
        rho = mortality rates (Sx1 array)
        lambdas = ability weights (Jx1 array)
        weights = population weights (Sx1 array)
        e = ability levels (SxJ array)
    Outputs:
        solutions = steady state values of b, n, w, r, factor,
                    T_H ((2*S*J+4)x1 array)
    '''

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_params

    maxiter, mindist_SS = iterative_params
    # Rename the inputs
    w = guesses[0]
    r = guesses[1]
    T_H = guesses[2]
    factor = guesses[3]
    bssmat = b_guess_init
    nssmat = n_guess_init

    # Solve for the steady state levels of b and n, given w, r, T_H and
    # factor
    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            guesses = np.append(bssmat[:, j], nssmat[:, j])
        else:
            guesses = np.append(bssmat[:, j - 1], nssmat[:, j - 1])
        args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n,
                 tau_bq, rho, lambdas, weights, e)
        [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver,
                                                         guesses * .9,
                                                         args=args_,
                                                         xtol=1e-13,
                                                         full_output=True)

        print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()

        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]
        # print np.array(Euler_equation_solver(np.append(bssmat[:, j],
        # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n,
        # theta, tau_bq, rho, lambdas, e)).max()

    K = household.get_K(bssmat, weights.reshape(S, 1), lambdas.reshape(1, J),
                        g_n_ss, 'SS')
    L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J),
                   'SS')
    Y = firm.get_Y(K, L, params)
    new_r = firm.get_r(Y, K, params)
    new_w = firm.get_w(Y, L, params)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            weights.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    new_factor = mean_income_data / average_income_model
    new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1),
                              lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss,
                              'SS')
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J,
                                      weights.reshape(S, 1), lambdas)

    new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ,
                               lambdas.reshape(1, J), factor,
                               weights.reshape(S, 1), 'SS', etr_params, params,
                               theta, tau_bq)

    error1 = new_w - w
    error2 = new_r - r
    error3 = new_T_H - T_H
    error4 = new_factor - factor
    print 'errors: ', error1, error2, error3, error4
    print 'T_H: ', new_T_H
    print 'factor: ', new_factor

    # Check and punish violations
    if r <= 0:
        error1 += 1e9
    #if r > 1:
    #    error1 += 1e9
    if w <= 0:
        error2 += 1e9

    return [error1, error2, error3, error4]
Example #19
0
def SS_solver(b_guess_init, n_guess_init, wss, rss, T_Hss, BQss, factor_ss, params, baseline, 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 = lenght 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()
    household.get_K()
    firm.get_L()
    firm.get_Y()
    firm.get_r()
    firm.get_w()
    household.get_BQ()
    tax.replacement_rate_vals()
    tax.get_lump_sum()
    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

    RETURNS: solutions = steady state values of b, n, w, r, factor,
                    T_H ((2*S*J+4)x1 array)

    OUTPUT: None
    --------------------------------------------------------------------
    '''

    bssmat, nssmat, chi_params, ss_params, income_tax_params, iterative_params = params

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params

    chi_b, chi_n = chi_params

    maxiter, mindist_SS = iterative_params

    # Rename the inputs
    w = wss
    r = rss
    T_H = T_Hss
    BQ = BQss
    factor = factor_ss

    dist = 10
    iteration = 0
    dist_vec = np.zeros(maxiter)

    if fsolve_flag == True:
        maxiter = 1

    while (dist > mindist_SS) and (iteration < maxiter):
        # Solve for the steady state levels of b and n, given w, r, T_H and
        # factor

        outer_loop_vars = (bssmat, nssmat, r, w, T_H, factor)
        inner_loop_params = (ss_params, income_tax_params, chi_params)

        euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_BQ, new_theta, new_factor, average_income_model = inner_loop(outer_loop_vars, inner_loop_params, baseline)

        # print 'T_H: ', T_H, new_T_H
        # print 'factor: ', factor, new_factor
        # print 'interest rate: ', r, new_r
        # print 'wage rate: ', w, new_w

        r = utils.convex_combo(new_r, r, nu)
        w = utils.convex_combo(new_w, w, nu)
        factor = utils.convex_combo(new_factor, factor, nu)
        T_H = utils.convex_combo(new_T_H, T_H, nu)
        BQ = utils.convex_combo(new_BQ, BQ, nu)
        theta = utils.convex_combo(new_theta, theta, nu)
        if T_H != 0:
            dist = np.array([utils.pct_diff_func(new_r, r)] +
                            [utils.pct_diff_func(new_w, w)] +
                            [utils.pct_diff_func(new_T_H, T_H)] +
                            [utils.pct_diff_func(new_BQ, BQ)] +
                            [utils.pct_diff_func(new_theta, theta)] +
                            [utils.pct_diff_func(new_factor, factor)]).max()
        else:
            # If T_H is zero (if there are no taxes), a percent difference
            # will throw NaN's, so we use an absoluate difference
            dist = np.array([utils.pct_diff_func(new_r, r)] +
                            [utils.pct_diff_func(new_w, w)] +
                            [abs(new_T_H - T_H)] +
                            [utils.pct_diff_func(new_BQ, BQ)] +
                            [utils.pct_diff_func(new_theta, theta)] +
                            [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 /= 2.0
                #print 'New value of nu:', nu
        iteration += 1
        #print "Iteration: %02d" % iteration, " Distance: ", dist

    '''
    ------------------------------------------------------------------------
        Generate the SS values of variables, including euler errors
    ------------------------------------------------------------------------
    '''
    bssmat_s = np.append(np.zeros((1,J)),bssmat[:-1,:],axis=0)
    bssmat_splus1 = bssmat

    wss = w
    rss = r
    factor_ss = factor
    T_Hss = T_H

    Kss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS')
    Kss = household.get_K(bssmat_splus1, Kss_params)
    Lss_params = (e, omega_SS.reshape(S, 1), lambdas, 'SS')
    Lss = firm.get_L(nssmat, Lss_params)
    Yss_params = (alpha, Z)
    Yss = firm.get_Y(Kss, Lss, Yss_params)
    Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS')
    Iss = firm.get_I(bssmat_splus1, Kss, Kss, Iss_params)

    BQss = new_BQ
    # theta_params = (e, S, J, omega_SS.reshape(S, 1), lambdas,retire)
    # theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, theta_params)

    # solve resource constraint
    etr_params_3D = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1))
    mtrx_params_3D = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1))
    taxss_params = (e, lambdas, 'SS', retire, etr_params_3D,
                    h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    taxss = tax.total_taxes(rss, wss, bssmat_s, nssmat, BQss, factor_ss, T_Hss, None, False, taxss_params)
    css_params = (e, lambdas.reshape(1, J), g_y)
    cssmat = household.get_cons(rss, wss, bssmat_s, bssmat_splus1, nssmat, BQss.reshape(
        1, J), taxss, css_params)

    Css_params = (omega_SS.reshape(S, 1), lambdas, 'SS')
    Css = household.get_C(cssmat, Css_params)

    resource_constraint = Yss - (Css + Iss)



    '''
    ------------------------------------------------------------------------
        The code below is to calulate and save model MTRs
                - only exists to help debug
    ------------------------------------------------------------------------
    '''
    # etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:]
    # etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1))
    # mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:]
    # mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1))
    # e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J)))
    # nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J)))
    # mtry_ss_params = (e_extended[1:,:], etr_params_extended_3D, mtry_params_extended_3D, analytical_mtrs)
    # mtry_ss = tax.MTR_capital(rss, wss, bssmat_splus1, nss_extended[1:,:], factor_ss, mtry_ss_params)
    # mtrx_ss_params = (e, etr_params_3D, mtrx_params_3D, analytical_mtrs)
    # mtrx_ss = tax.MTR_labor(rss, wss, bssmat_s, nssmat, factor_ss, mtrx_ss_params)
    #
    # etr_ss_params = (e, etr_params_3D)
    # etr_ss = tax.tau_income(rss, wss, bssmat_s, nssmat, factor_ss, etr_ss_params)
    #
    # np.savetxt("etr_ss.csv", etr_ss, delimiter=",")
    # np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",")
    # np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",")


    print 'interest rate: ', rss
    print 'wage rate: ', wss
    print 'factor: ', factor_ss
    print 'T_H', T_Hss
    print 'Resource Constraint Difference:', resource_constraint
    print 'Max Euler Error: ', (np.absolute(euler_errors)).max()

    if ENFORCE_SOLUTION_CHECKS and np.absolute(resource_constraint) > 1e-8:
        err = "Steady state aggregate resource constraint not satisfied"
        raise RuntimeError(err)

    # check constraints
    household.constraint_checker_SS(bssmat, nssmat, cssmat, ltilde)

    if np.absolute(resource_constraint) > 1e-8 or (np.absolute(euler_errors)).max() > 1e-8:
        ss_flag = 1
    else:
        ss_flag = 0


    euler_savings = euler_errors[:S,:]
    euler_labor_leisure = euler_errors[S:,:]

    '''
    ------------------------------------------------------------------------
        Return dictionary of SS results
    ------------------------------------------------------------------------
    '''

    output = {'Kss': Kss, 'bssmat': bssmat, 'Lss': Lss, 'Css':Css, 'Iss':Iss,
              'nssmat': nssmat, 'Yss': Yss,'wss': wss, 'rss': rss, 'theta': theta,
              'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s,
              'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1,
              'T_Hss': T_Hss, 'euler_savings': euler_savings,
              'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n,
              'chi_b': chi_b, 'ss_flag':ss_flag}

    return output
Example #20
0
def run_steady_state(income_tax_parameters,
                     ss_parameters,
                     iterative_params,
                     get_baseline=False,
                     calibrate_model=False,
                     output_dir="./OUTPUT"):
    '''
    ------------------------------------------------------------------------
        Run SS
    ------------------------------------------------------------------------
    '''

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_parameters

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_parameters

    # Generate initial guesses for chi^b_j and chi^n_s
    chi_params = np.zeros(S + J)
    chi_params[:J] = chi_b_guess
    chi_params[J:] = chi_n_guess
    # First run SS simulation with guesses at initial values for b, n, w, r, etc
    # For inital guesses of b and n, we choose very small b, and medium n
    b_guess = np.ones((S, J)).flatten() * .05
    n_guess = np.ones((S, J)).flatten() * .4 * ltilde
    # For initial guesses of w, r, T_H, and factor, we use values that are close
    # to some steady state values.
    wguess = 1.2
    rguess = .06
    T_Hguess = 0.12
    factorguess = 70000.0

    guesses = [wguess, rguess, T_Hguess, factorguess]
    args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params[J:],
             chi_params[:J], income_tax_parameters, ss_parameters,
             iterative_params, tau_bq, rho, lambdas, omega_SS, e)
    [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve,
                                                     guesses,
                                                     args=args_,
                                                     xtol=mindist_SS,
                                                     full_output=True)
    [wguess, rguess, T_Hguess, factorguess] = solutions
    fsolve_flag = True
    solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess,
                          rguess, T_Hguess, factorguess, chi_params[J:],
                          chi_params[:J], income_tax_parameters, ss_parameters,
                          iterative_params, tau_bq, rho, lambdas, omega_SS, e,
                          fsolve_flag)

    if calibrate_model:
        global Nfeval, value_all, chi_params_all
        Nfeval = 1
        value_all = np.zeros((10000))
        chi_params_all = np.zeros((S + J, 10000))
        outputs = {'solutions': solutions, 'chi_params': chi_params}
        ss_init_path = os.path.join(output_dir,
                                    "Saved_moments/SS_init_solutions.pkl")
        pickle.dump(outputs, open(ss_init_path, "wb"))
        function_to_minimize_X = lambda x: function_to_minimize(
            x, chi_params, income_tax_parameters, ss_parameters,
            iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir)
        bnds = tuple([(1e-6, None)] * (S + J))
        # In order to scale all the parameters to estimate in the minimizer, we have the minimizer fit a vector of ones that
        # will be multiplied by the chi initial guesses inside the function.  Otherwise, if chi^b_j=1e5 for some j, and the
        # minimizer peturbs that value by 1e-8, the % difference will be extremely small, outside of the tolerance of the
        # minimizer, and it will not change that parameter.
        chi_params_scalars = np.ones(S + J)
        #chi_params_scalars = opt.minimize(function_to_minimize_X, chi_params_scalars,
        #                                  method='TNC', tol=MINIMIZER_TOL, bounds=bnds, callback=callbackF(chi_params_scalars), options=MINIMIZER_OPTIONS).x
        # chi_params_scalars = opt.minimize(function_to_minimize, chi_params_scalars,
        #                                   args=(chi_params, income_tax_parameters, ss_parameters, iterative_params,
        #                                     omega_SS, rho, lambdas, tau_bq, e, output_dir),
        #                                   method='TNC', tol=MINIMIZER_TOL, bounds=bnds,
        #                                   callback=callbackF(chi_params_scalars,chi_params, income_tax_parameters,
        #                                     ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir),
        #                                   options=MINIMIZER_OPTIONS).x
        chi_params_scalars = opt.minimize(
            function_to_minimize,
            chi_params_scalars,
            args=(chi_params, income_tax_parameters, ss_parameters,
                  iterative_params, omega_SS, rho, lambdas, tau_bq, e,
                  output_dir),
            method='TNC',
            tol=MINIMIZER_TOL,
            bounds=bnds,
            options=MINIMIZER_OPTIONS).x
        chi_params *= chi_params_scalars
        print 'The final scaling params', chi_params_scalars
        print 'The final bequest parameter values:', chi_params

        solutions_dict = pickle.load(open(ss_init_path, "rb"))
        solutions = solutions_dict['solutions']
        b_guess = solutions[:S * J]
        n_guess = solutions[S * J:2 * S * J]
        wguess, rguess, factorguess, T_Hguess = solutions[2 * S * J:]
        guesses = [wguess, rguess, T_Hguess, factorguess]
        args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params[J:],
                 chi_params[:J], income_tax_parameters, ss_parameters,
                 iterative_params, tau_bq, rho, lambdas, omega_SS, e)
        [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve,
                                                         guesses,
                                                         args=args_,
                                                         xtol=mindist_SS,
                                                         full_output=True)
        [wguess, rguess, T_Hguess, factorguess] = solutions
        fsolve_flag = True
        solutions = SS_solver(b_guess.reshape(S,
                                              J), n_guess.reshape(S,
                                                                  J), wguess,
                              rguess, T_Hguess, factorguess, chi_params[J:],
                              chi_params[:J], income_tax_parameters,
                              ss_parameters, iterative_params, tau_bq, rho,
                              lambdas, omega_SS, e, fsolve_flag)
    '''
    ------------------------------------------------------------------------
        Generate the SS values of variables, including euler errors
    ------------------------------------------------------------------------
    '''

    if get_baseline:
        outputs = {'solutions': solutions, 'chi_params': chi_params}
        ss_init_dir = os.path.join(output_dir,
                                   "Saved_moments/SS_baseline_solutions.pkl")
        pickle.dump(outputs, open(ss_init_dir, "wb"))
    else:
        outputs = {'solutions': solutions, 'chi_params': chi_params}
        ss_exp_dir = os.path.join(output_dir,
                                  "Saved_moments/SS_reform_solutions.pkl")
        pickle.dump(outputs, open(ss_exp_dir, "wb"))

    bssmat = solutions[0:(S - 1) * J].reshape(S - 1, J)
    bq = solutions[
        (S - 1) * J:S *
        J]  # technically, this is just the intentional bequests - wealth of those with max age
    bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat))
    bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J)))
    nssmat = solutions[S * J:2 * S * J].reshape(S, J)
    wss, rss, factor_ss, T_Hss = solutions[2 * S * J:]

    Kss = household.get_K(bssmat_splus1, omega_SS.reshape(S, 1), lambdas,
                          g_n_ss, 'SS')
    Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas, 'SS')
    Yss = firm.get_Y(Kss, Lss, ss_parameters)

    Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss)

    theta = np.zeros(J)  #tax.replacement_rate_vals(
    #nssmat, wss, factor_ss, e, J, omega_SS.reshape(S, 1), lambdas)
    BQss = household.get_BQ(rss, bssmat_splus1, omega_SS.reshape(S, 1),
                            lambdas, rho.reshape(S, 1), g_n_ss, 'SS')
    b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat))

    etr_params_3D = np.tile(
        np.reshape(etr_params, (S, 1, etr_params.shape[1])), (1, J, 1))
    mtrx_params_3D = np.tile(
        np.reshape(mtrx_params, (S, 1, mtrx_params.shape[1])), (1, J, 1))
    etr_params_extended = np.append(etr_params,
                                    np.reshape(etr_params[-1, :],
                                               (1, etr_params.shape[1])),
                                    axis=0)[1:, :]
    etr_params_extended_3D = np.tile(
        np.reshape(etr_params_extended, (S, 1, etr_params_extended.shape[1])),
        (1, J, 1))
    mtry_params_extended = np.append(mtry_params,
                                     np.reshape(mtry_params[-1, :],
                                                (1, mtry_params.shape[1])),
                                     axis=0)[1:, :]
    mtry_params_extended_3D = np.tile(
        np.reshape(mtry_params_extended,
                   (S, 1, mtry_params_extended.shape[1])), (1, J, 1))
    e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J)))
    nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J)))
    mtry_ss = tax.MTR_capital(rss, bssmat_splus1, wss, e_extended[1:, :],
                              nss_extended[1:, :], factor_ss, analytical_mtrs,
                              etr_params_extended_3D, mtry_params_extended_3D)

    mtrx_ss = tax.MTR_labor(rss, bssmat_s, wss, e, nssmat, factor_ss,
                            analytical_mtrs, etr_params_3D, mtrx_params_3D)

    np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",")
    np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",")

    taxss_params = (J, S, retire,
                    np.tile(
                        np.reshape(etr_params, (S, 1, etr_params.shape[1])),
                        (1, J, 1)), h_wealth, p_wealth, m_wealth, tau_payroll)

    taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas, factor_ss,
                            T_Hss, None, 'SS', False, taxss_params, theta,
                            tau_bq)
    cssmat = household.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape(1, J),
                                lambdas.reshape(1, J), bssmat_splus1,
                                ss_parameters, taxss)

    Css = household.get_C(cssmat, omega_SS.reshape(S, 1), lambdas, 'SS')

    resource_constraint = Yss - (Css + Iss)

    print 'Resource Constraint Difference:', resource_constraint

    constraint_params = ltilde
    household.constraint_checker_SS(bssmat, nssmat, cssmat, constraint_params)

    b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat))
    b_splus1 = bssmat_splus1
    b_splus2 = np.array(
        list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J))))

    chi_b = np.tile(chi_params[:J].reshape(1, J), (S, 1))
    chi_n = np.array(chi_params[J:])
    euler_savings = np.zeros((S, J))
    euler_labor_leisure = np.zeros((S, J))
    for j in xrange(J):
        euler_savings[:, j] = household.euler_savings_func(
            wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j],
            b_splus2[:, j], BQss[j], factor_ss, T_Hss, chi_b[:, j],
            income_tax_parameters, ss_parameters, theta[j], tau_bq[j], rho,
            lambdas[j])
        euler_labor_leisure[:, j] = household.euler_labor_leisure_func(
            wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j],
            BQss[j], factor_ss, T_Hss, chi_n, income_tax_parameters,
            ss_parameters, theta[j], tau_bq[j], lambdas[j])
    '''
    ------------------------------------------------------------------------
        Save the values in various ways, depending on the stage of
            the simulation, to be used in TPI or graphing functions
    ------------------------------------------------------------------------
    '''

    # Pickle variables
    output = {
        'Kss': Kss,
        'bssmat': bssmat,
        'Lss': Lss,
        'Css': Css,
        'nssmat': nssmat,
        'Yss': Yss,
        'wss': wss,
        'rss': rss,
        'theta': theta,
        'BQss': BQss,
        'factor_ss': factor_ss,
        'bssmat_s': bssmat_s,
        'cssmat': cssmat,
        'bssmat_splus1': bssmat_splus1,
        'T_Hss': T_Hss,
        'euler_savings': euler_savings,
        'euler_labor_leisure': euler_labor_leisure,
        'chi_n': chi_n,
        'chi_b': chi_b
    }

    utils.mkdirs(os.path.join(output_dir, "SSinit"))
    ss_init_dir = os.path.join(output_dir, "SSinit/ss_init_vars.pkl")
    pickle.dump(output, open(ss_init_dir, "wb"))
    bssmat_init = bssmat_splus1
    nssmat_init = nssmat
    # Pickle variables for TPI initial values
    output2 = {'bssmat_init': bssmat_init, 'nssmat_init': nssmat_init}
    ss_init_tpi = os.path.join(output_dir, "SSinit/ss_init_tpi_vars.pkl")
    pickle.dump(output2, open(ss_init_tpi, "wb"))

    return output
Example #21
0
def run_time_path_iteration(Kss, Lss, Yss, BQss, theta, income_tax_params, wealth_tax_params, ellipse_params, parameters, g_n_vector, 
                           omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, 
                           T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, 
                           chi_n, output_dir="./OUTPUT", **kwargs):

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \
        h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = parameters

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params

    TPI_FIG_DIR = output_dir
    # Initialize Time paths
    domain = np.linspace(0, T, T)
    Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss
    Kinit[-1] = Kss
    Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss))
    Linit = np.ones(T + S) * Lss
    Yinit = firm.get_Y(Kinit, Linit, parameters)
    winit = firm.get_w(Yinit, Linit, parameters)
    rinit = firm.get_r(Yinit, Kinit, parameters)
    BQinit = np.zeros((T + S, J))
    for j in xrange(J):
        BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQinit = np.array(BQinit)
    if T_Hss < 1e-13 and T_Hss > 0.0 :
        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_init = np.ones(T + S) * T_Hss2

    # Make array of initial guesses
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)

    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    b_mat = np.zeros((T + S, S, J))
    n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)

    TPIiter = 0
    TPIdist = 10

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss)
        Lpath_TPI = list(Linit) + list(np.ones(10) * Lss)
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            plt.figure()
            plt.axhline(
                y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
            plt.plot(np.arange(
                T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))
        # Uncomment the following print statements to make sure all euler equations are converging.
        # If they don't, then you'll have negative consumption or consumption spikes.  If they don't,
        # it is the initial guesses.  You might need to scale them differently.  It is rather delicate for the first
        # few periods and high ability groups.
        for j in xrange(J):
            b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]],
                                                                   args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, 
                                                                   j, income_tax_params, parameters, theta, tau_bq), xtol=1e-13))
            # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6:
            # print 'minidoughnut:',
            # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1,
            # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b,
            # factor_ss, j, parameters, theta, tau_bq)).max()
            for s in xrange(S - 2):  # Upper triangle
                ind2 = np.arange(s + 2)
                b_guesses_to_use = np.diag(
                    guesses_b[1:S + 1, :, j], S - (s + 2))
                n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2))

                # initialize array of diagonal elements
                length_diag = (np.diag(np.transpose(etr_params[:S,:,0]),S-(s+2))).shape[0]
                etr_params_to_use = np.zeros((length_diag,etr_params.shape[2]))
                mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2]))
                mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2]))
                for i in range(etr_params.shape[2]):
                    etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:S,:,i]),S-(s+2))
                    mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:S,:,i]),S-(s+2))
                    mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:S,:,i]),S-(s+2))

                inc_tax_params_upper = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use)

                solutions = opt.fsolve(Steady_state_TPI_solver, list(
                    b_guesses_to_use) + list(n_guesses_to_use), args=(
                    winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, inc_tax_params_upper, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13)
                b_vec = solutions[:len(solutions) / 2]
                b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec
                n_vec = solutions[len(solutions) / 2:]
                n_mat[ind2, S - (s + 2) + ind2, j] = n_vec
                # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6:
                # print 's-loop:',
                # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit,
                # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters,
                # theta, tau_bq, rho, lambdas, e, initial_b, chi_b,
                # chi_n))).max()
            for t in xrange(0, T):
                b_guesses_to_use = .75 * \
                    np.diag(guesses_b[t + 1:t + S + 1, :, j])
                n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j])

                # initialize array of diagonal elements
                length_diag = (np.diag(np.transpose(etr_params[:,t:t+S,i]))).shape[0]
                etr_params_to_use = np.zeros((length_diag,etr_params.shape[2]))
                mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2]))
                mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2]))
                for i in range(etr_params.shape[2]):
                    etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:,t:t+S,i]))
                    mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:,t:t+S,i]))
                    mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:,t:t+S,i]))

                inc_tax_params_TP = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use)

                solutions = opt.fsolve(Steady_state_TPI_solver, list(
                    b_guesses_to_use) + list(n_guesses_to_use), args=(
                    winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13)
                b_vec = solutions[:S]
                b_mat[t + 1 + ind, ind, j] = b_vec
                n_vec = solutions[S:]
                n_mat[t + ind, ind, j] = n_vec
                inputs = list(solutions)
                euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver(
                    inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n))

        # if euler_errors.max() > 1e-6:
        #     print 't-loop:', euler_errors.max()
        # Force the initial distribution of capital to be as given above.
        b_mat[0, :, :] = initial_b
        Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape(
            T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI')
        Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[
                           :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
        Ynew = firm.get_Y(Kinit, Linit, parameters)
        wnew = firm.get_w(Ynew, Linit, parameters)
        rnew = firm.get_r(Ynew, Kinit, parameters)
        # the following needs a g_n term
        BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape(
            T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
        bmat_s = np.zeros((T, S, J))
        bmat_s[:, 1:, :] = b_mat[:T, :-1, :]

        # initialize array 
        TH_tax_params = np.zeros((T,S,J,etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            TH_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

        T_H_new = np.array(list(tax.get_lump_sum(np.tile(rnew.reshape(T, 1, 1),(1,S,J)), bmat_s, np.tile(wnew.reshape(
            T, 1, 1),(1,S,J)), np.tile(e.reshape(1, S, J),(T,1,1)), n_mat[:T,:,:], BQnew.reshape(T, 1, J), lambdas.reshape(
            1, 1, J), factor_ss, omega_stationary[:T].reshape(T, S, 1), 'TPI', TH_tax_params, parameters, theta, tau_bq)) + [T_Hss] * S)

        winit[:T] = utils.convex_combo(wnew, winit[:T], nu)
        rinit[:T] = utils.convex_combo(rnew, rinit[:T], nu)
        BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], nu)
        T_H_init[:T] = utils.convex_combo(T_H_new[:T], T_H_init[:T], nu)
        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)
        if T_H_init.all() != 0:
            TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list(
                utils.perc_dif_func(wnew, winit[:T])) + list(utils.perc_dif_func(T_H_new, T_H_init))).max()
        else:
            TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list(
                utils.perc_dif_func(wnew, winit[:T])) + list(np.abs(T_H_new, T_H_init))).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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist


    return winit[:T], rinit[:T], T_H_init[:T], BQinit[:T], Yinit
Example #22
0
def run_steady_state(ss_parameters, iterative_params, get_baseline=False, calibrate_model=False):
    '''
    ------------------------------------------------------------------------
        Run SS
    ------------------------------------------------------------------------
    '''

    if get_baseline:
        # Generate initial guesses for chi^b_j and chi^n_s
        chi_params = np.zeros(S+J)
        chi_params[:J] = chi_b_guess
        chi_params[J:] = chi_n_guess
        # First run SS simulation with guesses at initial values for b, n, w, r, etc
        # For inital guesses of b and n, we choose very small b, and medium n
        b_guess = np.ones((S, J)).flatten() * .01
        n_guess = np.ones((S, J)).flatten() * .5 * ltilde
        # For initial guesses of w, r, T_H, and factor, we use values that are close
        # to some steady state values.
        wguess = 1.2
        rguess = .06
        T_Hguess = 0
        factorguess = 100000
        solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e)

        if calibrate_model:
            outputs = {'solutions':solutions, 'chi_params':chi_params}
            pickle.dump(outputs, open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "wb"))
            function_to_minimize_X = lambda x: function_to_minimize(x, chi_params, ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e)
            bnds = tuple([(1e-6, None)] * (S + J))
            # In order to scale all the parameters to estimate in the minimizer, we have the minimizer fit a vector of ones that
            # will be multiplied by the chi initial guesses inside the function.  Otherwise, if chi^b_j=1e5 for some j, and the
            # minimizer peturbs that value by 1e-8, the % difference will be extremely small, outside of the tolerance of the
            # minimizer, and it will not change that parameter.
            chi_params_scalars = np.ones(S+J)
            chi_params_scalars = opt.minimize(function_to_minimize_X, chi_params_scalars, method='TNC', tol=MINIMIZER_TOL, bounds=bnds, options=MINIMIZER_OPTIONS).x
            chi_params *= chi_params_scalars
            print 'The final scaling params', chi_params_scalars
            print 'The final bequest parameter values:', chi_params

            solutions_dict = pickle.load(open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "rb"))
            solutions = solutions_dict['solutions']
            b_guess = solutions[:S*J]
            n_guess = solutions[S*J:2*S*J]
            wguess, rguess, factorguess, T_Hguess = solutions[2*S*J:]
            solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e)
    else:
        variables = pickle.load(open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "rb"))
        solutions = solutions_dict['solutions']
        chi_params = solutions_dict['chi_params']
        b_guess = solutions[:S*J]
        n_guess = solutions[S*J:2*S*J]
        wguess, rguess, factorguess, T_Hguess = solutions[2*S*J:]
        solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[J:], chi_params[:J], ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e)


    '''
    ------------------------------------------------------------------------
        Generate the SS values of variables, including euler errors
    ------------------------------------------------------------------------
    '''


    if get_baseline:
        outputs = {'solutions':solutions, 'chi_params':chi_params}
        pickle.dump(outputs, open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "wb"))
    else:
        outputs = {'solutions':solutions, 'chi_params':chi_params}
        pickle.dump(outputs, open("OUTPUT/Saved_moments/SS_experiment_solutions.pkl", "wb"))

    bssmat = solutions[0:(S-1) * J].reshape(S-1, J)
    bq = solutions[(S-1)*J:S*J]
    bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat))
    bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J)))
    nssmat = solutions[S * J:2*S*J].reshape(S, J)
    wss, rss, factor_ss, T_Hss = solutions[2*S*J:]

    Kss = household.get_K(bssmat_splus1, omega_SS.reshape(S, 1), lambdas, g_n_ss, 'SS')
    Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas, 'SS')
    Yss = firm.get_Y(Kss, Lss, ss_parameters)

    Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss)

    theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, e, J, omega_SS.reshape(S, 1), lambdas)
    BQss = household.get_BQ(rss, bssmat_splus1, omega_SS.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_ss, 'SS')
    b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat))
    taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas, factor_ss, T_Hss, None, 'SS', False, ss_parameters, theta, tau_bq)
    cssmat = household.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape(1, J), lambdas.reshape(1, J), bssmat_splus1, ss_parameters, taxss)

    Css = household.get_C(cssmat, omega_SS.reshape(S, 1), lambdas, 'SS')

    resource_constraint = Yss - (Css + Iss)

    print 'Resource Constraint Difference:', resource_constraint

    household.constraint_checker_SS(bssmat, nssmat, cssmat, ss_parameters)

    b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat))
    b_splus1 = bssmat_splus1
    b_splus2 = np.array(list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J))))

    chi_b = np.tile(chi_params[:J].reshape(1, J), (S, 1))
    chi_n = np.array(chi_params[J:])
    euler_savings = np.zeros((S, J))
    euler_labor_leisure = np.zeros((S, J))
    for j in xrange(J):
        euler_savings[:, j] = household.euler_savings_func(wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], b_splus2[:, j], BQss[j], factor_ss, T_Hss, chi_b[:, j], ss_parameters, theta[j], tau_bq[j], rho, lambdas[j])
        euler_labor_leisure[:, j] = household.euler_labor_leisure_func(wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], BQss[j], factor_ss, T_Hss, chi_n, ss_parameters, theta[j], tau_bq[j], lambdas[j])
    '''
    ------------------------------------------------------------------------
        Save the values in various ways, depending on the stage of
            the simulation, to be used in TPI or graphing functions
    ------------------------------------------------------------------------
    '''

    # Pickle variables
    output = {'Kss':Kss, 'bssmat':bssmat, 'Lss':Lss, 'nssmat':nssmat, 'Yss':Yss,
              'wss':wss, 'rss':rss, 'theta':theta, 'BQss':BQss, 'factor_ss':factor_ss,
              'bssmat_s':bssmat_s, 'cssmat':cssmat, 'bssmat_splus1':bssmat_splus1,
              'T_Hss':T_Hss, 'euler_savings':euler_savings,
              'euler_labor_leisure': euler_labor_leisure, 'chi_n':chi_n,
              'chi_b':chi_b}
    if get_baseline:
        pickle.dump(output, open("OUTPUT/SSinit/ss_init_vars.pkl", "wb"))
        bssmat_init = bssmat_splus1
        nssmat_init = nssmat
        # Pickle variables for TPI initial values
        output2 = {'bssmat_init':bssmat_init, 'nssmat_init':nssmat_init}
        pickle.dump(output2, open("OUTPUT/SSinit/ss_init_tpi_vars.pkl", "wb"))
    else:
        pickle.dump(output, open("OUTPUT/SS/ss_vars.pkl", "wb"))
    return output
Example #23
0
def TP_solutions(winit, rinit, T_H_init, BQinit2, Kss, Lss, Yss, BQss, theta, income_tax_params, wealth_tax_params, ellipse_params, parameters, g_n_vector, 
                           omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, 
                           T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, 
                           chi_n, output_dir="./OUTPUT", **kwargs):


    '''
    This function returns the solutions for all variables along the time path.

    
    '''

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \
        h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = parameters

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params

    print 'Computing final solutions'

    # Extend time paths past T
    winit = np.array(list(winit) + list(np.ones(S) * wss))
    rinit = np.array(list(rinit) + list(np.ones(S) * rss))
    T_H_init = np.array(list(T_H_init) + list(np.ones(S) * T_Hss))
    BQinit = np.zeros((T + S, J))
    for j in xrange(J):
        BQinit[:, j] = list(BQinit2[:,j]) + [BQss[j]] * S
    BQinit = np.array(BQinit)

    # Make array of initial guesses
    domain = np.linspace(0, T, T)
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)

    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    b_mat = np.zeros((T + S, S, J))
    n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)


    # initialize array of Euler errors
    euler_errors = np.zeros((T, 2 * S, J))

    # As in SS, you need the final distributions of b and n to match the final
    # w, r, BQ, etc.  Otherwise the euler errors are large.  You need one more
    # fsolve.
    for j in xrange(J):
        b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]],
                                                                   args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, 
                                                                   j, income_tax_params, parameters, theta, tau_bq), xtol=1e-13))
        for s in xrange(S - 2):  # Upper triangle
            ind2 = np.arange(s + 2)
            b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2))
            n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2))

            # initialize array of diagonal elements
            length_diag = (np.diag(np.transpose(etr_params[:S,:,0]),S-(s+2))).shape[0]
            etr_params_to_use = np.zeros((length_diag,etr_params.shape[2]))
            mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2]))
            mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2]))
            for i in range(etr_params.shape[2]):
                etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:S,:,i]),S-(s+2))
                mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:S,:,i]),S-(s+2))
                mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:S,:,i]),S-(s+2))

            inc_tax_params_upper = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use)

            solutions = opt.fsolve(Steady_state_TPI_solver, list(
                b_guesses_to_use) + list(n_guesses_to_use), args=(
                winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, inc_tax_params_upper, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13)
            b_vec = solutions[:len(solutions) / 2]
            b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec
            n_vec = solutions[len(solutions) / 2:]
            n_mat[ind2, S - (s + 2) + ind2, j] = n_vec
        for t in xrange(0, T):
            b_guesses_to_use = .75 * np.diag(guesses_b[t + 1:t + S + 1, :, j])
            n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j])

            # initialize array of diagonal elements
            length_diag = (np.diag(np.transpose(etr_params[:,t:t+S,i]))).shape[0]
            etr_params_to_use = np.zeros((length_diag,etr_params.shape[2]))
            mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2]))
            mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2]))
            for i in range(etr_params.shape[2]):
                etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:,t:t+S,i]))
                mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:,t:t+S,i]))
                mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:,t:t+S,i]))

            inc_tax_params_TP = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use)

            solutions = opt.fsolve(Steady_state_TPI_solver, list(
                b_guesses_to_use) + list(n_guesses_to_use), args=(
                winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13)
            b_vec = solutions[:S]
            b_mat[t + 1 + ind, ind, j] = b_vec
            n_vec = solutions[S:]
            n_mat[t + ind, ind, j] = n_vec
            inputs = list(solutions)
            euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver(
                inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n))

    b_mat[0, :, :] = initial_b

    '''
    ------------------------------------------------------------------------
    Generate variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''
    Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape(
            T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI')
    Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[
                           :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')

    Kpath_TPI = np.array(list(Kinit) + list(np.ones(10) * Kss))
    Lpath_TPI = np.array(list(Linit) + list(np.ones(10) * Lss))
    BQpath_TPI = np.array(list(BQinit) + list(np.ones((10, J)) * BQss))

    b_s = np.zeros((T, S, J))
    b_s[:, 1:, :] = b_mat[:T, :-1, :]
    b_splus1 = np.zeros((T, S, J))
    b_splus1[:, :, :] = b_mat[1:T + 1, :, :]

    # initialize array 
    etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

    tax_path_params = J, S, retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll
    tax_path = tax.total_taxes(np.tile(rinit[:T].reshape(T, 1, 1),(1,S,J)), b_s, np.tile(winit[:T].reshape(T, 1, 1),(1,S,J)), 
                               np.tile(e.reshape(1, S, J),(T,1,1)), n_mat[:T,:,:], BQinit[:T, :].reshape(T, 1, J), lambdas, 
                               factor_ss, T_H_init[:T].reshape(T, 1, 1), None, 'TPI', False, tax_path_params, theta, tau_bq)

    c_path = household.get_cons(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape(
        1, S, J), n_mat[:T], BQinit[:T].reshape(T, 1, J), lambdas.reshape(1, 1, J), b_splus1, parameters, tax_path)

    Y_path = firm.get_Y(Kpath_TPI[:T], Lpath_TPI[:T], parameters)
    C_path = household.get_C(c_path, omega_stationary[
                             :T].reshape(T, S, 1), lambdas, 'TPI')
    I_path = firm.get_I(Kpath_TPI[1:T + 1],
                        Kpath_TPI[:T], delta, g_y, g_n_vector[:T])
    print 'Resource Constraint Difference:', Y_path - C_path - I_path

    print'Checking time path for violations of constaints.'
    hh_constraint_params = ltilde
    for t in xrange(T):
        household.constraint_checker_TPI(
            b_mat[t], n_mat[t], c_path[t], t, hh_constraint_params)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    print 'Max Euler error, savings: ', eul_savings
    print 'Max Euler error labor supply: ', eul_laborleisure

    '''
    ------------------------------------------------------------------------
    Create the unstationarized versions of the paths of macro aggregates
    ------------------------------------------------------------------------
    '''
    # tvec = np.linspace(0, len(C_path), len(C_path))
    # growth_path = np.exp(g_y*tvec)
    # pop_path = np.zeros(len(C_path))
    # for i in range(0,len(C_path)):
    #     pop_path[i] = np.exp(g_n_vector[:i].sum())   # note that this normalizes the pop in the initial period to one

    # growth_pop_path = growth_path*pop_path 

    # C_ns_path = C_path * growth_pop_path
    # K_ns_path = Kinit * growth_pop_path
    # BQ_ns_path = growth_pop_path * BQinit[:T]
    # L_ns_path = Linit * pop_path 
    # T_H_ns_path = T_H_init[:T] * growth_pop_path
    # w_ns_path = winit*growth_path
    # I_ns_path = I_path * growth_pop_path
    # Y_ns_path = Y_path * growth_pop_path 
    


    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {'Kpath_TPI': Kpath_TPI, 'b_mat': b_mat, 'c_path': c_path,
              'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure,
              'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI, 'n_mat': n_mat,
              'rinit': rinit, 'Y_path': Y_path, 'T_H_init': T_H_init,
              'tax_path': tax_path, 'winit': winit}
    
    macro_output = {'Kpath_TPI': Kpath_TPI, 'C_path': C_path, 'I_path': I_path,
              'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI,
              'rinit': rinit, 'Y_path': Y_path, 'T_H_init': T_H_init,
              'winit': winit, 'tax_path': tax_path}

    # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path,
    #           'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path,
    #           'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path,
    #           'w_ns_path': w_ns_path}


    tpi_dir = os.path.join(output_dir, "TPI")
    utils.mkdirs(tpi_dir)
    tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl")
    pickle.dump(output, open(tpi_vars, "wb"))

    tpi_dir = os.path.join(output_dir, "TPI")
    utils.mkdirs(tpi_dir)
    tpi_vars = os.path.join(tpi_dir, "TPI_macro_vars.pkl")
    pickle.dump(macro_output, open(tpi_vars, "wb"))
Example #24
0
def run_TPI(income_tax_params, tpi_params, iterative_params, small_open_params, initial_values, SS_values, fiscal_params, biz_tax_params, output_dir="./OUTPUT", baseline_spending=False):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params
    # K0, b_sinit, b_splus1init, L0, Y0,\
    #         w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n, omega_S_preTP = initial_values
    small_open, tpi_firm_r, tpi_hh_r = small_open_params
    B0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP, initial_debt = initial_values
    Kss, Bss, Lss, rss, wss, BQss, T_Hss, revenue_ss, bssmat_splus1, nssmat, Yss, Gss = SS_values
    tau_b, delta_tau = biz_tax_params
    if baseline_spending==False:
        budget_balance, ALPHA_T, ALPHA_G, tG1, tG2, rho_G, debt_ratio_ss = fiscal_params
    else:
        budget_balance, ALPHA_T, ALPHA_G, tG1, tG2, rho_G, debt_ratio_ss, T_Hbaseline, Gbaseline = fiscal_params

    print 'Government spending breakpoints are tG1: ', tG1, '; and tG2:', tG2

    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    # Make array of initial guesses for labor supply and savings
    domain = np.linspace(0, T, T)
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)

    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    b_mat = guesses_b#np.zeros((T + S, S, J))
    n_mat = guesses_n#np.zeros((T + S, S, J))
    ind = np.arange(S)

    L_init = np.ones((T+S,))*Lss
    B_init = np.ones((T+S,))*Bss
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
    L_init[:T]  = firm.get_L(n_mat[:T], L_params)
    B_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI')
    B_init[1:T] = household.get_K(b_mat[:T-1], B_params)
    B_init[0] = B0

    if small_open == False:
        if budget_balance:
            K_init = B_init
        else:
            K_init = B_init * Kss/Bss
    else:
        K_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        K_init = firm.get_K(L_init, tpi_firm_r, K_params)

    K = K_init
#    if np.any(K < 0):
#        print 'K_init has negative elements. Setting them positive to prevent NAN.'
#        K[:T] = np.fmax(K[:T], 0.05*B[:T])

    L = L_init
    B = B_init
    Y_params = (Z, gamma, epsilon)
    Y = firm.get_Y(K, L, Y_params)
    w_params = (Z, gamma, epsilon)
    w = firm.get_w(Y, L, w_params)
    if small_open == False:
        r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        r = firm.get_r(Y, K, r_params)
    else:
        r = tpi_hh_r

    BQ = np.zeros((T + S, J))
    BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r[0], initial_b, BQ0_params)
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    if budget_balance:
        if np.abs(T_Hss) < 1e-13 :
            T_Hss2 = 0.0 # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below
        else:
            T_Hss2 = T_Hss
        T_H = np.ones(T + S) * T_Hss2
        REVENUE = T_H
        G = np.zeros(T + S)
    elif baseline_spending==False:
        T_H = ALPHA_T * Y
    elif baseline_spending==True:
        T_H = T_Hbaseline
        T_H_new = T_H   # Need to set T_H_new for later reference
        G   = Gbaseline
        G_0 = Gbaseline[0]

    # Initialize some inputs
    # D = np.zeros(T + S)
    D = debt_ratio_ss*Y
    omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0)
    BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1),
                     g_n_vector[:T].reshape(T, 1), 'TPI')
    tax_params = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
    REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
                      tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)


    # print 'D/Y:', D[:T]/Y[:T]
    # print 'T/Y:', T_H[:T]/Y[:T]
    # print 'G/Y:', G[:T]/Y[:T]
    # print 'Int payments to GDP:', (r[:T]*D[:T])/Y[:T]
    # quit()


    TPIiter = 0
    TPIdist = 10
    PLOT_TPI = False
    report_tG1 = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    print 'analytical mtrs in tpi = ', analytical_mtrs


    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):

        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            #K_plot = list(K) + list(np.ones(10) * Kss)
            D_plot = list(D) + list(np.ones(10) * Yss * debt_ratio_ss)
            plt.figure()
            plt.axhline(
                y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
            plt.plot(np.arange(
                T + 10), D_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_D"))

        if report_tG1 is True:
            print '\tAt time tG1-1:'
            print '\t\tG = ', G[tG1-1]
            print '\t\tK = ', K[tG1-1]
            print '\t\tr = ', r[tG1-1]
            print '\t\tD = ', D[tG1-1]


        guesses = (guesses_b, guesses_n)
        outer_loop_vars = (r, w, K, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)

        bmat_s = np.zeros((T, S, J))
        bmat_s[0, 1:, :] = initial_b[:-1, :]
        bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[:T, :, :]

        #L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') # defined above
        L[:T]  = firm.get_L(n_mat[:T], L_params)
        #B_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI') # defined above
        B[1:T] = household.get_K(bmat_splus1[:T-1], B_params)
        if np.any(B) < 0:
            print 'B has negative elements. B[0:9]:', B[0:9]
            print 'B[T-2:T]:', B[T-2,T]

        if small_open == False:
            if budget_balance:
                K[:T] = B[:T]
            else:
                if baseline_spending == False:
                    Y = T_H/ALPHA_T  #SBF 3/3: This seems totally unnecessary as both these variables are defined above.

#                tax_params = np.zeros((T,S,J,etr_params.shape[2]))
#                for i in range(etr_params.shape[2]):
#                    tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

#                REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
#                        tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) # define above
                REVENUE = np.array(list(tax.revenue(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)),
                       bmat_s, n_mat[:T,:,:], BQ[:T].reshape(T, 1, J), Y[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S)

                D_0    = initial_debt * Y[0]
                other_dg_params = (T, r, g_n_vector, g_y)
                if baseline_spending==False:
                    G_0    = ALPHA_G[0] * Y[0]
                dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0)
                Dnew, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending)
                K[:T] = B[:T] - Dnew[:T]
                if np.any(K < 0):
                    print 'K has negative elements. Setting them positive to prevent NAN.'
                    K[:T] = np.fmax(K[:T], 0.05*B[:T])
        else:
            # K_params previously set to =  (Z, gamma, epsilon, delta, tau_b, delta_tau)
            K[:T] = firm.get_K(L[:T], tpi_firm_r[:T], K_params)
        Y_params = (Z, gamma, epsilon)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        Y = Ynew
        w_params = (Z, gamma, epsilon)
        wnew = firm.get_w(Ynew[:T], L[:T], w_params)
        if small_open == False:
            r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
            rnew = firm.get_r(Ynew[:T], K[:T], r_params)
        else:
            rnew = r.copy()

        print 'Y and T_H: ', Y[3], T_H[3]
#        omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0)  # defined above
#        BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1),
#                     g_n_vector[:T].reshape(T, 1), 'TPI')  # defined above
        b_mat_shift = np.append(np.reshape(initial_b,(1,S,J)),b_mat[:T-1,:,:],axis=0)
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params)

#        tax_params = np.zeros((T,S,J,etr_params.shape[2]))
#        for i in range(etr_params.shape[2]):
#            tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

#        REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
#                tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) # defined above
        REVENUE = np.array(list(tax.revenue(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
               bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), Y[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S)

        if budget_balance:
            T_H_new = REVENUE
        elif baseline_spending==False:
            T_H_new = ALPHA_T[:T] * Y[:T]
        # If baseline_spending==True, no need to update T_H, which remains fixed.

        if small_open==True and budget_balance==False:
            # Loop through years to calculate debt and gov't spending. This is done earlier when small_open=False.
            D_0    = initial_debt * Y[0]
            other_dg_params = (T, r, g_n_vector, g_y)
            if baseline_spending==False:
                G_0    = ALPHA_G[0] * Y[0]
            dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0)
            Dnew, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending)

        w[:T] = utils.convex_combo(wnew[:T], w[:T], nu)
        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        # D[:T] = utils.convex_combo(Dnew[:T], D[:T], nu)
        D = Dnew
        Y[:T] = utils.convex_combo(Ynew[:T], Y[:T], nu)
        if baseline_spending==False:
            T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu)
        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)

        print 'r diff: ', (rnew[:T]-r[:T]).max(), (rnew[:T]-r[:T]).min()
        print 'w diff: ', (wnew[:T]-w[:T]).max(), (wnew[:T]-w[:T]).min()
        print 'BQ diff: ', (BQnew[:T]-BQ[:T]).max(), (BQnew[:T]-BQ[:T]).min()
        print 'T_H diff: ', (T_H_new[:T]-T_H[:T]).max(), (T_H_new[:T]-T_H[:T]).min()

        if baseline_spending==False:
            if T_H.all() != 0:
                TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                    utils.pct_diff_func(wnew[:T], w[:T])) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            else:
                TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                    utils.pct_diff_func(wnew[:T], w[:T])) + list(np.abs(T_H[:T]))).max()
        else:
            # TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
            #     utils.pct_diff_func(wnew[:T], w[:T])) + list(utils.pct_diff_func(Dnew[:T], D[:T]))).max()
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                utils.pct_diff_func(wnew[:T], w[:T])) + list(utils.pct_diff_func(Ynew[:T], Y[:T]))).max()

        TPIdist_vec[TPIiter] = TPIdist
        # After T=10, if cycling occurs, drop the value of nu
        # wait til after T=10 or so, because sometimes there is a jump up
        # in the first couple iterations
        # if TPIiter > 10:
        #     if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0:
        #         nu /= 2
        #         print 'New Value of nu:', nu
        TPIiter += 1
        print 'Iteration:', TPIiter
        print '\tDistance:', TPIdist

        # print 'D/Y:', (D[:T]/Ynew[:T]).max(), (D[:T]/Ynew[:T]).min(), np.median(D[:T]/Ynew[:T])
        # print 'T/Y:', (T_H_new[:T]/Ynew[:T]).max(), (T_H_new[:T]/Ynew[:T]).min(), np.median(T_H_new[:T]/Ynew[:T])
        # print 'G/Y:', (G[:T]/Ynew[:T]).max(), (G[:T]/Ynew[:T]).min(), np.median(G[:T]/Ynew[:T])
        # print 'Int payments to GDP:', ((r[:T]*D[:T])/Ynew[:T]).max(), ((r[:T]*D[:T])/Ynew[:T]).min(), np.median((r[:T]*D[:T])/Ynew[:T])
        #
        # print 'D/Y:', (D[:T]/Ynew[:T])
        # print 'T/Y:', (T_H_new[:T]/Ynew[:T])
        # print 'G/Y:', (G[:T]/Ynew[:T])
        #
        # print 'deficit: ', REVENUE[:T] - T_H_new[:T] - G[:T]

    # Loop through years to calculate debt and gov't spending. The re-assignment of G0 & D0 is necessary because Y0 may change in the TPI loop.
    if budget_balance == False:
        D_0    = initial_debt * Y[0]
        other_dg_params = (T, r, g_n_vector, g_y)
        if baseline_spending==False:
            G_0    = ALPHA_G[0] * Y[0]
        dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0)
        D, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending)

    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, K, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)

    bmat_s = np.zeros((T, S, J))
    bmat_s[0, 1:, :] = initial_b[:-1, :]
    bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :]
    bmat_splus1 = np.zeros((T, S, J))
    bmat_splus1[:, :, :] = b_mat[:T, :, :]

    #L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') # defined above
    L[:T]  = firm.get_L(n_mat[:T], L_params)
    #B_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI') # defined above
    B[1:T] = household.get_K(bmat_splus1[:T-1], B_params)

    if small_open == False:
        K[:T] = B[:T] - D[:T]
    else:
        # K_params previously set to = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        K[:T] = firm.get_K(L[:T], tpi_firm_r[:T], K_params)
    # Y_params previously set to = (Z, gamma, epsilon)
    Ynew = firm.get_Y(K[:T], L[:T], Y_params)

    # testing for change in Y
    ydiff = Ynew[:T] - Y[:T]
    ydiff_max = np.amax(np.abs(ydiff))
    print 'ydiff_max = ', ydiff_max

    w_params = (Z, gamma, epsilon)
    wnew = firm.get_w(Ynew[:T], L[:T], w_params)
    if small_open == False:
        # r_params previously set to = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)
    else:
        rnew = r

    # Note: previously, Y was not reassigned to equal Ynew at this point.
    Y = Ynew[:]

#    omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0)
#    BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1),
#                 g_n_vector[:T].reshape(T, 1), 'TPI')
    b_mat_shift = np.append(np.reshape(initial_b,(1,S,J)),b_mat[:T-1,:,:],axis=0)
    BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params)

#    tax_params = np.zeros((T,S,J,etr_params.shape[2]))
#    for i in range(etr_params.shape[2]):
#        tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

#    REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
#            tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)
    REVENUE = np.array(list(tax.revenue(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
           bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), Ynew[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S)

    etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
    tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas, 'TPI', retire, etr_params_path, h_wealth,
                       p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), bmat_s,
                               n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params)

    cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T,:,:],
                   BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)

    if budget_balance==False:
        D_0    = initial_debt * Y[0]
        other_dg_params = (T, r, g_n_vector, g_y)
        if baseline_spending==False:
            G_0    = ALPHA_G[0] * Y[0]
        dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0)
        D, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending)


    if small_open == False:
        I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI')
        I = firm.get_I(bmat_splus1[:T], K[1:T+1], K[:T], I_params)
        rc_error = Y[:T] - C[:T] - I[:T] - G[:T]
    else:
        #InvestmentPlaceholder = np.zeros(bmat_splus1[:T].shape)
        #I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI')
        I = (1+g_n_vector[:T])*np.exp(g_y)*K[1:T+1] - (1.0 - delta) * K[:T] #firm.get_I(InvestmentPlaceholder, K[1:T+1], K[:T], I_params)
        BI_params = (0.0, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI')
        BI = firm.get_I(bmat_splus1[:T], B[1:T+1], B[:T], BI_params)
        new_borrowing = D[1:T]*(1+g_n_vector[1:T])*np.exp(g_y) - D[:T-1]
        rc_error = Y[:T-1] + new_borrowing - (C[:T-1] + BI[:T-1] + G[:T-1] ) + (tpi_hh_r[:T-1] * B[:T-1] - (delta + tpi_firm_r[:T-1])*K[:T-1] - tpi_hh_r[:T-1]*D[:T-1])
        #print 'Y(T-1):', Y[T-1], '\n','C(T-1):', C[T-1], '\n','K(T-1):', K[T-1], '\n','B(T-1):', B[T-1], '\n','BI(T-1):', BI[T-1], '\n','I(T-1):', I[T-1]

    rce_max = np.amax(np.abs(rc_error))
    print 'Max absolute value resource constraint error:', rce_max

    print'Checking time path for violations of constraints.'
    for t in xrange(T):
        household.constraint_checker_TPI(
            b_mat[t], n_mat[t], c_path[t], t, ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

   # print 'Max Euler error, savings: ', eul_savings
   # print 'Max Euler error labor supply: ', eul_laborleisure



    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ,
              'REVENUE': REVENUE, 'T_H': T_H, 'G': G, 'D': D,
              'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat,
              'c_path': c_path, 'tax_path': tax_path,
              'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure}

    tpi_dir = os.path.join(output_dir, "TPI")
    utils.mkdirs(tpi_dir)
    tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl")
    pickle.dump(output, open(tpi_vars, "wb"))

    macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I,
                    'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w,
                    'tax_path': tax_path}

    growth = (1+g_n_vector)*np.exp(g_y)
    with open('TPI_output.csv', 'wb') as csvfile:
        tpiwriter = csv.writer(csvfile)
        tpiwriter.writerow(Y)
        tpiwriter.writerow(D)
        tpiwriter.writerow(REVENUE)
        tpiwriter.writerow(G)
        tpiwriter.writerow(T_H)
        tpiwriter.writerow(C)
        tpiwriter.writerow(K)
        tpiwriter.writerow(I)
        tpiwriter.writerow(r)
        if small_open == True:
            tpiwriter.writerow(B)
            tpiwriter.writerow(BI)
            tpiwriter.writerow(new_borrowing)
        tpiwriter.writerow(growth)
        tpiwriter.writerow(rc_error)
        tpiwriter.writerow(ydiff)


    if np.any(G) < 0:
        print 'Government spending is negative along transition path to satisfy budget'

    if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS :
        raise RuntimeError("Transition path equlibrium not found (TPIdist)")

    if ((np.any(np.absolute(rc_error) >= mindist_TPI))
        and ENFORCE_SOLUTION_CHECKS):
        raise RuntimeError("Transition path equlibrium not found (rc_error)")

    if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
        (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
        and ENFORCE_SOLUTION_CHECKS):
        raise RuntimeError("Transition path equlibrium not found (eulers)")

    # Non-stationary output
    # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path,
    #           'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path,
    #           'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path,
    #           'w_ns_path': w_ns_path}


    return output, macro_output
Example #25
0
def SS_solver(b_guess_init, n_guess_init, rss, wss, T_Hss, factor_ss, Yss, params, baseline, fsolve_flag=False, baseline_spending=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()
    household.get_K()
    firm.get_L()
    firm.get_Y()
    firm.get_r()
    firm.get_w()
    household.get_BQ()
    tax.replacement_rate_vals()
    tax.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
    --------------------------------------------------------------------
    '''

    bssmat, nssmat, chi_params, ss_params, income_tax_params, iterative_params, small_open_params = params
    J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, budget_balance, \
                  alpha_T, debt_ratio_ss, tau_b, delta_tau,\
                  lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params

    chi_b, chi_n = chi_params

    maxiter, mindist_SS = iterative_params

    small_open, ss_firm_r, ss_hh_r = small_open_params

    # Rename the inputs
    r = rss
    w = wss
    T_H = T_Hss
    factor = factor_ss
    if budget_balance == False:
        if baseline_spending == True:
            Y = Yss
        else:
            Y = T_H / alpha_T
    if small_open == True:
        r = ss_hh_r

    dist = 10
    iteration = 0
    dist_vec = np.zeros(maxiter)

    if fsolve_flag == True:
        maxiter = 1

    while (dist > mindist_SS) and (iteration < maxiter):
        # Solve for the steady state levels of b and n, given w, r, Y and
        # factor
        if budget_balance:
            outer_loop_vars = (bssmat, nssmat, r, w, T_H, factor)
        else:
            outer_loop_vars = (bssmat, nssmat, r, w, Y, T_H, factor)
        inner_loop_params = (ss_params, income_tax_params, chi_params, small_open_params)

        euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_Y, new_factor, new_BQ, average_income_model = inner_loop(outer_loop_vars, inner_loop_params, baseline, baseline_spending)

        r = utils.convex_combo(new_r, r, nu)
        w = utils.convex_combo(new_w, w, nu)
        factor = utils.convex_combo(new_factor, factor, nu)
        if budget_balance:
            T_H = utils.convex_combo(new_T_H, T_H, nu)
            dist = np.array([utils.pct_diff_func(new_r, r)] +
                            [utils.pct_diff_func(new_w, w)] +
                            [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)
            if Y != 0:
                dist = np.array([utils.pct_diff_func(new_r, r)] +
                                [utils.pct_diff_func(new_w, w)] +
                                [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)] +
                                [utils.pct_diff_func(new_w, w)] +
                                [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 /= 2.0
                print 'New value of nu:', nu
        iteration += 1
        print "Iteration: %02d" % iteration, " Distance: ", dist

    '''
    ------------------------------------------------------------------------
        Generate the SS values of variables, including euler errors
    ------------------------------------------------------------------------
    '''
    bssmat_s = np.append(np.zeros((1,J)),bssmat[:-1,:],axis=0)
    bssmat_splus1 = bssmat

    rss = r
    wss = w
    factor_ss = factor
    T_Hss = T_H

    Lss_params = (e, omega_SS.reshape(S, 1), lambdas, 'SS')
    Lss = firm.get_L(nssmat, Lss_params)
    if small_open == False:
        Kss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS')
        Bss = household.get_K(bssmat_splus1, Kss_params)
        if budget_balance:
            debt_ss = 0.0
        else:
            debt_ss = debt_ratio_ss*Y
        Kss = Bss - debt_ss
        Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS')
        Iss = firm.get_I(bssmat_splus1, Kss, Kss, Iss_params)
    else:
        # Compute capital (K) and wealth (B) separately
        Kss_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        Kss = firm.get_K(Lss, ss_firm_r, Kss_params)
        Iss_params = (delta, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS')
        InvestmentPlaceholder = np.zeros(bssmat_splus1.shape)
        Iss = firm.get_I(InvestmentPlaceholder, Kss, Kss, Iss_params)
        Bss_params = (omega_SS.reshape(S, 1), lambdas, imm_rates, g_n_ss, 'SS')
        Bss = household.get_K(bssmat_splus1, Bss_params)
        BIss_params = (0.0, g_y, omega_SS, lambdas, imm_rates, g_n_ss, 'SS')
        BIss = firm.get_I(bssmat_splus1, Bss, Bss, BIss_params)
        if budget_balance:
            debt_ss = 0.0
        else:
            debt_ss = debt_ratio_ss*Y


    # Yss_params = (alpha, Z)
    Yss_params = (Z, gamma, epsilon)
    Yss = firm.get_Y(Kss, Lss, Yss_params)

    # Verify that T_Hss = alpha_T*Yss
#    transfer_error = T_Hss - alpha_T*Yss
#    if np.absolute(transfer_error) > mindist_SS:
#        print 'Transfers exceed alpha_T percent of GDP by:', transfer_error
#        err = "Transfers do not match correct share of GDP in SS_solver"
#        raise RuntimeError(err)

    BQss = new_BQ
    theta_params = (e, S, retire)
    theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, theta_params)

    # Next 5 lines pulled out of inner_loop where they are used to calculate tax revenue. Now calculating G to balance gov't budget.
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    lump_sum_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                      tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)
    revenue_ss = tax.revenue(new_r, new_w, b_s, nssmat, new_BQ, Yss, Lss, Kss, factor, lump_sum_params)
    r_gov_ss = rss
    debt_service_ss = r_gov_ss*debt_ratio_ss*Yss
    new_borrowing = debt_ratio_ss*Yss*((1+g_n_ss)*np.exp(g_y)-1)
    # government spends such that it expands its debt at the same rate as GDP
    if budget_balance:
        Gss = 0.0
    else:
        Gss = revenue_ss + new_borrowing - (T_Hss + debt_service_ss)

    # solve resource constraint
    etr_params_3D = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1))
    mtrx_params_3D = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1))

    '''
    ------------------------------------------------------------------------
        The code below is to calulate and save model MTRs
                - only exists to help debug
    ------------------------------------------------------------------------
    '''
    # etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:]
    # etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1))
    # mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:]
    # mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1))
    # e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J)))
    # nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J)))
    # mtry_ss_params = (e_extended[1:,:], etr_params_extended_3D, mtry_params_extended_3D, analytical_mtrs)
    # mtry_ss = tax.MTR_capital(rss, wss, bssmat_splus1, nss_extended[1:,:], factor_ss, mtry_ss_params)
    # mtrx_ss_params = (e, etr_params_3D, mtrx_params_3D, analytical_mtrs)
    # mtrx_ss = tax.MTR_labor(rss, wss, bssmat_s, nssmat, factor_ss, mtrx_ss_params)

    # np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",")
    # np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",")

    # solve resource constraint
    taxss_params = (e, lambdas, 'SS', retire, etr_params_3D,
                    h_wealth, p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    taxss = tax.total_taxes(rss, wss, bssmat_s, nssmat, BQss, factor_ss, T_Hss, None, False, taxss_params)
    css_params = (e, lambdas.reshape(1, J), g_y)
    cssmat = household.get_cons(rss, wss, bssmat_s, bssmat_splus1, nssmat, BQss.reshape(
        1, J), taxss, css_params)

    biz_params = (tau_b, delta_tau)
    business_revenue = tax.get_biz_tax(wss, Yss, Lss, Kss, biz_params)

    Css_params = (omega_SS.reshape(S, 1), lambdas, 'SS')
    Css = household.get_C(cssmat, Css_params)

    if small_open == False:
        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:', revenue_ss/Yss, 'business rev/Y: ', business_revenue/Yss, 'Int payments to GDP:', (rss*debt_ss)/Yss
        print 'Check SS budget: ', Gss - (np.exp(g_y)*(1+g_n_ss)-1-rss)*debt_ss - revenue_ss + T_Hss
        print 'resource constraint: ', resource_constraint
    else:
        # include term for current account
        resource_constraint = Yss + new_borrowing  - (Css + BIss + Gss) + (ss_hh_r * Bss - (delta + ss_firm_r) * 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:', revenue_ss/Yss, 'Int payments to GDP:', (rss*debt_ss)/Yss
        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) > 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, nssmat, cssmat, ltilde)

    euler_savings = euler_errors[:S,:]
    euler_labor_leisure = euler_errors[S:,:]

    '''
    ------------------------------------------------------------------------
        Return dictionary of SS results
    ------------------------------------------------------------------------
    '''
    output = {'Kss': Kss, 'bssmat': bssmat, 'Bss': Bss, 'Lss': Lss, 'Css':Css, 'Iss':Iss, 'nssmat': nssmat, 'Yss': Yss,
              'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss,
              'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1,
              'T_Hss': T_Hss, 'Gss': Gss, 'revenue_ss': revenue_ss, 'euler_savings': euler_savings,
              'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n,
              'chi_b': chi_b}

    return output
Example #26
0
def run_TPI(income_tax_params,
            tpi_params,
            iterative_params,
            initial_values,
            SS_values,
            fix_transfers=False,
            output_dir="./OUTPUT"):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params
    K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP = initial_values
    Kss, Lss, rss, wss, BQss, T_Hss, Gss, bssmat_splus1, nssmat = SS_values

    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    domain = np.linspace(0, T, T)
    r = np.ones(T + S) * rss
    BQ = np.zeros((T + S, J))
    BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1),
                  g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r[0], initial_b, BQ0_params)
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    # print "BQ values = ", BQ[0, :], BQ[100, :], BQ[-1, :], BQss
    # print "K0 vs Kss = ", K0-Kss

    if fix_transfers:
        T_H = T_H_baseline
    else:
        if np.abs(T_Hss) < 1e-13:
            T_Hss2 = 0.0  # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below
        else:
            T_Hss2 = T_Hss
        T_H = np.ones(T + S) * T_Hss2 * (r / rss)
    G = np.ones(T + S) * Gss
    # # print "T_H values = ", T_H[0], T_H[100], T_H[-1], T_Hss
    # # print "omega diffs = ", (omega_S_preTP-omega[-1]).max(), (omega[10]-omega[-1]).max()
    #
    # Make array of initial guesses for labor supply and savings
    domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J))
    ending_b = bssmat_splus1
    guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b
    ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1))
    guesses_b = np.append(guesses_b, ending_b_tail, axis=0)
    # print 'diff btwn start and end b: ', (guesses_b[0]-guesses_b[-1]).max()
    #
    domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J))
    guesses_n = domain3 * (nssmat - initial_n) + initial_n
    ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1))
    guesses_n = np.append(guesses_n, ending_n_tail, axis=0)
    # b_mat = np.zeros((T + S, S, J))
    # n_mat = np.zeros((T + S, S, J))
    ind = np.arange(S)
    # # print 'diff btwn start and end n: ', (guesses_n[0]-guesses_n[-1]).max()
    #
    # # find economic aggregates
    K = np.zeros(T + S)
    L = np.zeros(T + S)
    K[0] = K0
    K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J),
                imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI')
    K[1:T] = household.get_K(guesses_b[:T - 1], K_params)
    K[T:] = Kss
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                lambdas.reshape(1, 1, J), 'TPI')
    L[:T] = firm.get_L(guesses_n[:T], L_params)
    L[T:] = Lss
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    r[:T] = firm.get_r(Y[:T], K[:T], r_params)

    # uncomment lines below if want to use starting values from prior run
    r = TPI_START_VALUES['r']
    K = TPI_START_VALUES['K']
    L = TPI_START_VALUES['L']
    Y = TPI_START_VALUES['Y']
    T_H = TPI_START_VALUES['T_H']
    BQ = TPI_START_VALUES['BQ']
    G = TPI_START_VALUES['G']

    guesses_b = TPI_START_VALUES['b_mat']
    guesses_n = TPI_START_VALUES['n_mat']

    TPIiter = 0
    TPIdist = 10
    PLOT_TPI = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    # print 'analytical mtrs in tpi = ', analytical_mtrs

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            K_plot = list(K) + list(np.ones(10) * Kss)
            L_plot = list(L) + list(np.ones(10) * Lss)
            plt.figure()
            plt.axhline(y=Kss,
                        color='black',
                        linewidth=2,
                        label=r"Steady State $\hat{K}$",
                        ls='--')
            plt.plot(np.arange(T + 10),
                     Kpath_plot[:T + 10],
                     'b',
                     linewidth=2,
                     label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))

        guesses = (guesses_b, guesses_n)
        w_params = (Z, alpha, delta)
        w = firm.get_w_from_r(r, w_params)
        # print 'r and rss diff = ', r-rss
        # print 'w and wss diff = ', w-wss
        # print 'BQ and BQss diff = ', BQ-BQss
        # print 'T_H and T_Hss diff = ', T_H - T_Hss
        # print 'guess b and bss = ', (bssmat_splus1 - guesses_b).max()
        # print 'guess n and nss = ', (nssmat - guesses_n).max()
        outer_loop_vars = (r, w, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values,
                             ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars,
                                                inner_loop_params)

        # print 'guess b and bss = ', (b_mat - guesses_b).max()
        # print 'guess n and nss over time = ', (n_mat - guesses_n).max(axis=2).max(axis=1)
        # print 'guess n and nss over age = ', (n_mat - guesses_n).max(axis=0).max(axis=1)
        # print 'guess n and nss over ability = ', (n_mat - guesses_n).max(axis=0).max(axis=0)
        # quit()

        print 'Max Euler error: ', (np.abs(euler_errors)).max()

        bmat_s = np.zeros((T, S, J))
        bmat_s[0, 1:, :] = initial_b[:-1, :]
        bmat_s[1:, 1:, :] = b_mat[:T - 1, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[:T, :, :]

        K[0] = K0
        K_params = (omega[:T - 1].reshape(T - 1, S,
                                          1), lambdas.reshape(1, 1, J),
                    imm_rates[:T - 1].reshape(T - 1, S,
                                              1), g_n_vector[1:T], 'TPI')
        K[1:T] = household.get_K(bmat_splus1[:T - 1], K_params)
        L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                    lambdas.reshape(1, 1, J), 'TPI')
        L[:T] = firm.get_L(n_mat[:T], L_params)
        # print 'K diffs = ', K-K0
        # print 'L diffs = ', L-L[0]

        Y_params = (alpha, Z)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        r_params = (alpha, delta)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)
        wnew = firm.get_w_from_r(rnew, w_params)

        omega_shift = np.append(omega_S_preTP.reshape(1, S),
                                omega[:T - 1, :],
                                axis=0)
        BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J),
                     rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
        # b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)),
        #                         b_mat[:T-1, :, :], axis=0)
        b_mat_shift = bmat_splus1[:T, :, :]
        # print 'b diffs = ', (bmat_splus1[100, :, :] - initial_b).max(), (bmat_splus1[0, :, :] - initial_b).max(), (bmat_splus1[1, :, :] - initial_b).max()
        # print 'r diffs = ', rnew[1]-r[1], rnew[100]-r[100], rnew[-1]-r[-1]
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift,
                                 BQ_params)
        BQss2 = np.empty(J)
        for j in range(J):
            BQss_params = (omega[1, :], lambdas[j], rho, g_n_vector[1], 'SS')
            BQss2[j] = household.get_BQ(rnew[1], bmat_splus1[1, :, j],
                                        BQss_params)
        # print 'BQ test = ', BQss2-BQss, BQss-BQnew[1], BQss-BQnew[100], BQss-BQnew[-1]

        total_tax_params = np.zeros((T, S, J, etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            total_tax_params[:, :, :, i] = np.tile(
                np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
                (1, 1, J))

        tax_receipt_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)),
                              lambdas.reshape(1, 1,
                                              J), omega[:T].reshape(T, S,
                                                                    1), 'TPI',
                              total_tax_params, theta, tau_bq, tau_payroll,
                              h_wealth, p_wealth, m_wealth, retire, T, S, J)
        net_tax_receipts = np.array(
            list(
                tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), (
                    1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), (
                        1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape(
                            T, 1, J), factor, tax_receipt_params)) +
            [T_Hss] * S)

        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        if fix_transfers:
            T_H_new = T_H
            G[:T] = net_tax_receipts[:T] - T_H[:T]
        else:
            T_H_new = net_tax_receipts
            T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu)
            G[:T] = 0.0

        etr_params_path = np.zeros((T, S, J, etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            etr_params_path[:, :, :, i] = np.tile(
                np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
                (1, 1, J))
        tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas,
                           'TPI', retire, etr_params_path, h_wealth, p_wealth,
                           m_wealth, tau_payroll, theta, tau_bq, J, S)
        b_to_use = np.zeros((T, S, J))
        b_to_use[0, 1:, :] = initial_b[:-1, :]
        b_to_use[1:, 1:, :] = b_mat[:T - 1, :-1, :]
        tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)),
                                   np.tile(w[:T].reshape(T, 1, 1),
                                           (1, S, J)), b_to_use,
                                   n_mat[:T, :, :], BQ[:T, :].reshape(T, 1, J),
                                   factor, T_H[:T].reshape(T, 1, 1), None,
                                   False, tax_path_params)

        y_path = (np.tile(r[:T].reshape(T, 1, 1),
                          (1, S, J)) * b_to_use[:T, :, :] +
                  np.tile(w[:T].reshape(T, 1, 1),
                          (1, S, J)) * np.tile(e.reshape(1, S, J),
                                               (T, 1, 1)) * n_mat[:T, :, :])
        cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
        c_path = household.get_cons(r[:T].reshape(T, 1,
                                                  1), w[:T].reshape(T, 1, 1),
                                    b_to_use[:T, :, :], b_mat[:T, :, :],
                                    n_mat[:T, :, :], BQ[:T].reshape(T, 1, J),
                                    tax_path, cons_params)

        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)
        if T_H.all() != 0:
            TPIdist = np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T])) +
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            print 'r dist = ', np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T]))).max()
            print 'BQ dist = ', np.array(
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten())).max()
            print 'T_H dist = ', np.array(
                list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            print 'T_H path = ', T_H[:20]
            # print 'r old = ', r[:T]
            # print 'r new = ', rnew[:T]
            # print 'K old = ', K[:T]
            # print 'L old = ', L[:T]
            # print 'income = ', y_path[:, :, -1]
            # print 'taxes = ', tax_path[:, :, -1]
            # print 'labor supply = ', n_mat[:, :, -1]
            # print 'max and min labor = ', n_mat.max(), n_mat.min()
            # print 'max and min labor = ', np.argmax(n_mat), np.argmin(n_mat)
            # print 'max and min labor, j = 7 = ', n_mat[:,:,-1].max(), n_mat[:,:,-1].min()
            # print 'max and min labor, j = 6 = ', n_mat[:,:,-2].max(), n_mat[:,:,-2].min()
            # print 'max and min labor, j = 5 = ', n_mat[:,:,4].max(), n_mat[:,:,4].min()
            # print 'max and min labor, j = 4 = ', n_mat[:,:,3].max(), n_mat[:,:,3].min()
            # print 'max and min labor, j = 3 = ', n_mat[:,:,2].max(), n_mat[:,:,2].min()
            # print 'max and min labor, j = 2 = ', n_mat[:,:,1].max(), n_mat[:,:,1].min()
            # print 'max and min labor, j = 1 = ', n_mat[:,:,0].max(), n_mat[:,:,0].min()
            # print 'max and min labor, S = 80 = ', n_mat[:,-1,-1].max(), n_mat[:,-1,-1].min()
            # print "number  > 1 = ", (n_mat > 1).sum()
            # print "number  < 0, = ", (n_mat < 0).sum()
            # print "number  > 1, j=7 = ", (n_mat[:T,:,-1] > 1).sum()
            # print "number  < 0, j=7 = ", (n_mat[:T,:,-1] < 0).sum()
            # print "number  > 1, s=80, j=7 = ", (n_mat[:T,-1,-1] > 1).sum()
            # print "number  < 0, s=80, j=7 = ", (n_mat[:T,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 80= ", (n_mat[:T,-1,-1] > 1).sum()
            # print "number  < 0, j = 7, age 80= ", (n_mat[:T,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] > 1).sum()
            # print "number  < 0, j = 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80,-1] > 1).sum()
            # print "number  < 0, j = 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80   ,-1] < 0).sum()
            # diag_dict = {'n_mat': n_mat, 'b_mat': b_mat, 'y_path': y_path, 'c_path': c_path}
            # pickle.dump(diag_dict, open('tpi_iter1.pkl', 'wb'))

        else:
            TPIdist = np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T])) +
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                list(np.abs(T_H_new[:T] - T_H[: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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    Y[:T] = Ynew

    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars,
                                            inner_loop_params)

    bmat_s = np.zeros((T, S, J))
    bmat_s[0, 1:, :] = initial_b[:-1, :]
    bmat_s[1:, 1:, :] = b_mat[:T - 1, :-1, :]
    bmat_splus1 = np.zeros((T, S, J))
    bmat_splus1[:, :, :] = b_mat[:T, :, :]

    K[0] = K0
    K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J),
                imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI')
    K[1:T] = household.get_K(bmat_splus1[:T - 1], K_params)
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                lambdas.reshape(1, 1, J), 'TPI')
    L[:T] = firm.get_L(n_mat[:T], L_params)

    Y_params = (alpha, Z)
    Ynew = firm.get_Y(K[:T], L[:T], Y_params)
    r_params = (alpha, delta)
    rnew = firm.get_r(Ynew[:T], K[:T], r_params)
    wnew = firm.get_w_from_r(rnew, w_params)

    omega_shift = np.append(omega_S_preTP.reshape(1, S),
                            omega[:T - 1, :],
                            axis=0)
    BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J),
                 rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
    b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)),
                            b_mat[:T - 1, :, :],
                            axis=0)
    BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params)

    total_tax_params = np.zeros((T, S, J, etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        total_tax_params[:, :, :, i] = np.tile(
            np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
            (1, 1, J))

    tax_receipt_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)),
                          lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1),
                          'TPI', total_tax_params, theta, tau_bq, tau_payroll,
                          h_wealth, p_wealth, m_wealth, retire, T, S, J)
    net_tax_receipts = np.array(
        list(
            tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), (
                1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), (
                    1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape(
                        T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S)

    if fix_transfers:
        G[:T] = net_tax_receipts[:T] - T_H[:T]
    else:
        T_H[:T] = net_tax_receipts[:T]
        G[:T] = 0.0

    etr_params_path = np.zeros((T, S, J, etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:, :, :, i] = np.tile(
            np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
            (1, 1, J))
    tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas, 'TPI',
                       retire, etr_params_path, h_wealth, p_wealth, m_wealth,
                       tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)),
                               np.tile(w[:T].reshape(T, 1, 1),
                                       (1, S, J)), bmat_s, n_mat[:T, :, :],
                               BQ[:T, :].reshape(T, 1, J), factor,
                               T_H[:T].reshape(T, 1, 1), None, False,
                               tax_path_params)

    cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1),
                                bmat_s, bmat_splus1, n_mat[:T, :, :],
                                BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)
    I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas,
                imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T + 1], 'TPI')
    I = firm.get_I(bmat_splus1[:T], K[1:T + 1], K[:T], I_params)
    rc_error = Y[:T] - C[:T] - I[:T] - G[:T]
    print 'Resource Constraint Difference:', rc_error

    # compute utility
    u_params = (sigma, np.tile(chi_n.reshape(1, S, 1),
                               (T, 1, J)), b_ellipse, ltilde, upsilon,
                np.tile(rho.reshape(1, S, 1),
                        (T, 1, J)), np.tile(chi_b.reshape(1, 1, J), (T, S, 1)))
    utility_path = household.get_u(c_path[:T, :, :], n_mat[:T, :, :],
                                   bmat_splus1[:T, :, :], u_params)

    # compute before and after-tax income
    y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * bmat_s[:T, :, :] +
              np.tile(w[:T].reshape(T, 1, 1),
                      (1, S, J)) * np.tile(e.reshape(1, S, J),
                                           (T, 1, 1)) * n_mat[:T, :, :])
    inctax_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), etr_params_path)
    y_aftertax_path = (y_path - tax.tau_income(
        np.tile(r[:T].reshape(T, 1, 1),
                (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)),
        bmat_s[:T, :, :], n_mat[:T, :, :], factor, inctax_params))

    # compute after-tax wealth
    wtax_params = (h_wealth, p_wealth, m_wealth)
    b_aftertax_path = bmat_s[:T, :, :] - tax.tau_wealth(
        bmat_s[:T, :, :], wtax_params)

    print 'Checking time path for violations of constaints.'
    for t in xrange(T):
        household.constraint_checker_TPI(b_mat[t], n_mat[t], c_path[t], t,
                                         ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    print 'Max Euler error, savings: ', eul_savings
    print 'Max Euler error labor supply: ', eul_laborleisure
    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {
        'Y': Y,
        'K': K,
        'L': L,
        'C': C,
        'I': I,
        'BQ': BQ,
        'G': G,
        'T_H': T_H,
        'r': r,
        'w': w,
        'b_mat': b_mat,
        'n_mat': n_mat,
        'c_path': c_path,
        'tax_path': tax_path,
        'bmat_s': bmat_s,
        'utility_path': utility_path,
        'b_aftertax_path': b_aftertax_path,
        'y_aftertax_path': y_aftertax_path,
        'y_path': y_path,
        'eul_savings': eul_savings,
        'eul_laborleisure': eul_laborleisure
    }

    macro_output = {
        'Y': Y,
        'K': K,
        'L': L,
        'C': C,
        'I': I,
        'BQ': BQ,
        'G': G,
        'T_H': T_H,
        'r': r,
        'w': w,
        'tax_path': tax_path
    }

    # if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS :
    #     raise RuntimeError("Transition path equlibrium not found")
    #
    # if ((np.any(np.absolute(rc_error) >= 1e-6))
    #     and ENFORCE_SOLUTION_CHECKS):
    #     raise RuntimeError("Transition path equlibrium not found")
    #
    # if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
    #     (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
    #     and ENFORCE_SOLUTION_CHECKS):
    #     raise RuntimeError("Transition path equlibrium not found")

    return output, macro_output
Example #27
0
def create_tpi_params(a_tax_income, b_tax_income, c_tax_income,
                      d_tax_income,
                      b_ellipse, upsilon, J, S, T, beta, sigma, alpha, Z,
                      delta, ltilde, nu, g_y, tau_payroll, retire,
                      mean_income_data, get_baseline=True, input_dir="./OUTPUT", **kwargs):

    if get_baseline:
        ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl")
        variables = pickle.load(open(ss_init, "rb"))
        for key in variables:
            globals()[key] = variables[key]
    else:
        params_path = os.path.join(
            input_dir, "Saved_moments/params_changed.pkl")
        variables = pickle.load(open(params_path, "rb"))
        for key in variables:
            globals()[key] = variables[key]
        var_path = os.path.join(input_dir, "SS/ss_vars.pkl")
        variables = pickle.load(open(var_path, "rb"))
        for key in variables:
            globals()[key] = variables[key]
        init_tpi_vars = os.path.join(input_dir, "SSinit/ss_init_tpi_vars.pkl")
        variables = pickle.load(open(init_tpi_vars, "rb"))
        for key in variables:
            globals()[key] = variables[key]

    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    income_tax_params = [a_tax_income,
                         b_tax_income, c_tax_income, d_tax_income]
    wealth_tax_params = [h_wealth, p_wealth, m_wealth]
    ellipse_params = [b_ellipse, upsilon]
    parameters = [J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire,
                  mean_income_data] + income_tax_params + wealth_tax_params + ellipse_params

    N_tilde = omega.sum(1)
    omega_stationary = omega / N_tilde.reshape(T + S, 1)

    if get_baseline:
        initial_b = bssmat_splus1
        initial_n = nssmat
    else:
        initial_b = bssmat_init
        initial_n = nssmat_init
    # Get an initial distribution of capital with the initial population
    # distribution
    K0 = household.get_K(initial_b, omega_stationary[
                         0].reshape(S, 1), lambdas, g_n_vector[0], 'SS')
    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0 = firm.get_L(e, initial_n, omega_stationary[
                    0].reshape(S, 1), lambdas, 'SS')
    Y0 = firm.get_Y(K0, L0, parameters)
    w0 = firm.get_w(Y0, L0, parameters)
    r0 = firm.get_r(Y0, K0, parameters)
    BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape(
        S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[
                             0].reshape(S, 1), 'SS', parameters, theta, tau_bq)
    tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas,
                           factor_ss, T_H_0, None, 'SS', False, parameters, theta, tau_bq)
    c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(
        1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0)

    return (income_tax_params, wealth_tax_params, ellipse_params, parameters,
            N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0,
            w0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n)
Example #28
0
def SS_solver(b_guess_init, n_guess_init, wguess, rguess, T_Hguess,
              factorguess, chi_n, chi_b, tax_params, params, iterative_params, tau_bq,
              rho, lambdas, weights, e, fsolve_flag=False):
    '''
    Solves for the steady state distribution of capital, labor, as well as
    w, r, T_H and the scaling factor, using an iterative method similar to TPI.
    Inputs:
        b_guess_init = guesses for b (SxJ array)
        n_guess_init = guesses for n (SxJ array)
        wguess = guess for wage rate (scalar)
        rguess = guess for rental rate (scalar)
        T_Hguess = guess for lump sum tax (scalar)
        factorguess = guess for scaling factor to dollars (scalar)
        chi_n = chi^n_s (Sx1 array)
        chi_b = chi^b_j (Jx1 array)
        params = list of parameters (list)
        iterative_params = list of parameters that determine the convergence
                           of the while loop (list)
        tau_bq = bequest tax rate (Jx1 array)
        rho = mortality rates (Sx1 array)
        lambdas = ability weights (Jx1 array)
        weights = population weights (Sx1 array)
        e = ability levels (SxJ array)
    Outputs:
        solutions = steady state values of b, n, w, r, factor,
                    T_H ((2*S*J+4)x1 array)
    '''
    
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_params

    maxiter, mindist_SS = iterative_params
    # Rename the inputs
    w = wguess
    r = rguess
    T_H = T_Hguess
    factor = factorguess
    bssmat = b_guess_init
    nssmat = n_guess_init

    dist = 10
    iteration = 0
    dist_vec = np.zeros(maxiter)

    if fsolve_flag == True:
        maxiter = 1 


    while (dist > mindist_SS) and (iteration < maxiter):
        # Solve for the steady state levels of b and n, given w, r, T_H and
        # factor
        for j in xrange(J):
            # Solve the euler equations
            if j == 0:
                guesses = np.append(bssmat[:, j], nssmat[:, j])
            else:
                guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])

            args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho,
                     lambdas, weights, e)
            [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9,
                                   args=args_, xtol=1e-13, full_output=True)

            print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()

            bssmat[:, j] = solutions[:S]
            nssmat[:, j] = solutions[S:]
            # print np.array(Euler_equation_solver(np.append(bssmat[:, j],
            # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n,
            # theta, tau_bq, rho, lambdas, e)).max()

        K = household.get_K(bssmat, weights.reshape(S, 1),
                            lambdas.reshape(1, J), g_n_ss, 'SS')
        L = firm.get_L(e, nssmat, weights.reshape(S, 1),
                       lambdas.reshape(1, J), 'SS')
        Y = firm.get_Y(K, L, params)
        new_r = firm.get_r(Y, K, params)
        new_w = firm.get_w(Y, L, params)
        b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
        average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                                weights.reshape(S, 1) *
                                lambdas.reshape(1, J)).sum()
        new_factor = mean_income_data / average_income_model
        new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1),
                                  lambdas.reshape(1, J), rho.reshape(S, 1),
                                  g_n_ss, 'SS')
        theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J,
                                          weights.reshape(S, 1), lambdas)
        # lump_sum_tax_params = (a_etr_income, b_etr_income, c_etr_income, d_etr_income, 
        #                    e_etr_income, f_etr_income, min_x_etr_income, max_x_etr_income, 
        #                    min_y_etr_income, max_y_etr_income)
        new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ,
                                   lambdas.reshape(1, J), factor,
                                   weights.reshape(S, 1), 'SS', etr_params, params, theta,
                                   tau_bq)

        r = utils.convex_combo(new_r, r, nu)
        w = utils.convex_combo(new_w, w, nu)
        factor = utils.convex_combo(new_factor, factor, nu)
        T_H = utils.convex_combo(new_T_H, T_H, nu)
        if T_H != 0:
            dist = np.array([utils.perc_dif_func(new_r, r)] +
                            [utils.perc_dif_func(new_w, w)] +
                            [utils.perc_dif_func(new_T_H, T_H)] +
                            [utils.perc_dif_func(new_factor, factor)]).max()
        else:
            # If T_H is zero (if there are no taxes), a percent difference
            # will throw NaN's, so we use an absoluate difference
            dist = np.array([utils.perc_dif_func(new_r, r)] +
                            [utils.perc_dif_func(new_w, w)] +
                            [abs(new_T_H - T_H)] +
                            [utils.perc_dif_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 /= 2.0
                print 'New value of nu:', nu
        iteration += 1
        print "Iteration: %02d" % iteration, " Distance: ", dist

    eul_errors = np.ones(J)
    b_mat = np.zeros((S, J))
    n_mat = np.zeros((S, J))
    # Given the final w, r, T_H and factor, solve for the SS b and n (if you
    # don't do a final fsolve, there will be a slight mismatch,
    # with high euler errors)
    for j in xrange(J):
        guesses = np.append(bssmat[:, j], nssmat[:, j])
        args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho,
                 lambdas, weights, e)
        [solutions1, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9,
                                   args=args_, xtol=1e-13, full_output=True)
        eul_errors[j] = np.array(infodict['fvec']).max()
        print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()
        b_mat[:, j] = solutions1[:S]
        n_mat[:, j] = solutions1[S:]
    print 'SS fsolve euler error:', eul_errors.max()
    solutions = np.append(b_mat.flatten(), n_mat.flatten())
    other_vars = np.array([w, r, factor, T_H])
    solutions = np.append(solutions, other_vars)
    return solutions
Example #29
0
def create_tpi_params(**sim_params):
    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas
    initial_b = ss_baseline_vars['bssmat_splus1']
    initial_n = ss_baseline_vars['nssmat']

    SS_values = (ss_baseline_vars['Kss'], ss_baseline_vars['Lss'],
                 ss_baseline_vars['rss'], ss_baseline_vars['wss'],
                 ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'],
                 ss_baseline_vars['bssmat_splus1'], ss_baseline_vars['nssmat'])

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    wealth_tax_params = [
        sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth']
    ]
    ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']]
    chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']]

    N_tilde = sim_params['omega'].sum(
        1
    )  #this should just be one in each year given how we've constructed omega
    sim_params['omega'] = sim_params['omega'] / N_tilde.reshape(
        sim_params['T'] + sim_params['S'], 1)

    tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BW'],
                  sim_params['beta'], sim_params['sigma'], sim_params['alpha'],
                  sim_params['Z'], sim_params['delta'], sim_params['ltilde'],
                  sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'],
                  sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde,
                  sim_params['lambdas'], sim_params['e'], sim_params['retire'], sim_params['mean_income_data'], factor] + \
                  wealth_tax_params + ellipse_params + chi_params
    iterative_params = [
        sim_params['maxiter'], sim_params['mindist_SS'],
        sim_params['mindist_TPI']
    ]


    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params

    ## Assumption for tax functions is that policy in last year of BW is
    # extended permanently
    etr_params_TP = np.zeros((S, T + S, sim_params['etr_params'].shape[2]))
    etr_params_TP[:, :BW, :] = sim_params['etr_params']
    etr_params_TP[:, BW:, :] = np.reshape(
        sim_params['etr_params'][:, BW - 1, :],
        (S, 1, sim_params['etr_params'].shape[2]))

    mtrx_params_TP = np.zeros((S, T + S, sim_params['mtrx_params'].shape[2]))
    mtrx_params_TP[:, :BW, :] = sim_params['mtrx_params']
    mtrx_params_TP[:, BW:, :] = np.reshape(
        sim_params['mtrx_params'][:, BW - 1, :],
        (S, 1, sim_params['mtrx_params'].shape[2]))

    mtry_params_TP = np.zeros((S, T + S, sim_params['mtry_params'].shape[2]))
    mtry_params_TP[:, :BW, :] = sim_params['mtry_params']
    mtry_params_TP[:, BW:, :] = np.reshape(
        sim_params['mtry_params'][:, BW - 1, :],
        (S, 1, sim_params['mtry_params'].shape[2]))

    income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP,
                         mtrx_params_TP, mtry_params_TP)
    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''
    # Get an initial distribution of capital with the initial population
    # distribution
    K0_params = (omega[0].reshape(S, 1), lambdas, g_n_vector[0], 'SS')
    K0 = household.get_K(initial_b, K0_params)

    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0_params = (e, omega[0].reshape(S, 1), lambdas, 'SS')
    L0 = firm.get_L(initial_n, L0_params)
    Y0_params = (alpha, Z)
    Y0 = firm.get_Y(K0, L0, Y0_params)
    w0 = firm.get_w(Y0, L0, alpha)
    r0_params = (alpha, delta)
    r0 = firm.get_r(Y0, K0, r0_params)

    BQ0_params = (omega[0].reshape(S, 1), lambdas, rho.reshape(S, 1),
                  g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r0, initial_b, BQ0_params)

    theta_params = (e, J, omega[0].reshape(S, 1), lambdas)
    theta = tax.replacement_rate_vals(initial_n, w0, factor, theta_params)

    T_H_params = (e, lambdas, omega[0].reshape(S, 1), 'SS',
                  etr_params_TP[:, 0, :], theta, tau_bq, tau_payroll, h_wealth,
                  p_wealth, m_wealth, retire, T, S, J)
    T_H_0 = tax.get_lump_sum(r0, w0, b_sinit, initial_n, BQ0, factor,
                             T_H_params)

    etr_params_3D = np.tile(
        np.reshape(etr_params_TP[:, 0, :], (S, 1, etr_params_TP.shape[2])),
        (1, J, 1))
    tax0_params = (e, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth,
                   m_wealth, tau_payroll, theta, tau_bq, J, S)
    tax0 = tax.total_taxes(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_0,
                           None, False, tax0_params)

    c0_params = (e, lambdas.reshape(1, J), g_y)
    c0 = household.get_cons(r0, w0, b_sinit, b_splus1init, initial_n,
                            BQ0.reshape(1, J), tax0, c0_params)

    initial_values = (K0, b_sinit, b_splus1init, L0, Y0, w0, r0, BQ0, T_H_0,
                      factor, tax0, c0, initial_b, initial_n)

    return (income_tax_params, tpi_params, iterative_params, initial_values,
            SS_values)
Example #30
0
def SS_fsolve(guesses, b_guess_init, n_guess_init, chi_n, chi_b, tax_params, params, iterative_params, tau_bq,
              rho, lambdas, weights, e):
    '''
    Solves for the steady state distribution of capital, labor, as well as
    w, r, T_H and the scaling factor, using an iterative method similar to TPI.
    Inputs:
        b_guess_init = guesses for b (SxJ array)
        n_guess_init = guesses for n (SxJ array)
        wguess = guess for wage rate (scalar)
        rguess = guess for rental rate (scalar)
        T_Hguess = guess for lump sum tax (scalar)
        factorguess = guess for scaling factor to dollars (scalar)
        chi_n = chi^n_s (Sx1 array)
        chi_b = chi^b_j (Jx1 array)
        params = list of parameters (list)
        iterative_params = list of parameters that determine the convergence
                           of the while loop (list)
        tau_bq = bequest tax rate (Jx1 array)
        rho = mortality rates (Sx1 array)
        lambdas = ability weights (Jx1 array)
        weights = population weights (Sx1 array)
        e = ability levels (SxJ array)
    Outputs:
        solutions = steady state values of b, n, w, r, factor,
                    T_H ((2*S*J+4)x1 array)
    '''
    
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_params

    maxiter, mindist_SS = iterative_params
    # Rename the inputs
    w = guesses[0]
    r = guesses[1]
    T_H = guesses[2]
    factor = guesses[3]
    bssmat = b_guess_init
    nssmat = n_guess_init

    # Solve for the steady state levels of b and n, given w, r, T_H and
    # factor
    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            guesses = np.append(bssmat[:, j], nssmat[:, j])
        else:
            guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])
        args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho,
                 lambdas, weights, e)
        [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9,
                                   args=args_, xtol=1e-13, full_output=True)

        print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()
        
        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]
        # print np.array(Euler_equation_solver(np.append(bssmat[:, j],
        # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n,
        # theta, tau_bq, rho, lambdas, e)).max()

    K = household.get_K(bssmat, weights.reshape(S, 1),
                        lambdas.reshape(1, J), g_n_ss, 'SS')
    L = firm.get_L(e, nssmat, weights.reshape(S, 1),
                   lambdas.reshape(1, J), 'SS')
    Y = firm.get_Y(K, L, params)
    new_r = firm.get_r(Y, K, params)
    new_w = firm.get_w(Y, L, params)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            weights.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    new_factor = mean_income_data / average_income_model
    new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1),
                              lambdas.reshape(1, J), rho.reshape(S, 1),
                              g_n_ss, 'SS')
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J,
                                      weights.reshape(S, 1), lambdas)

    new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ,
                               lambdas.reshape(1, J), factor,
                               weights.reshape(S, 1), 'SS', etr_params, params, theta,
                               tau_bq)


    error1 = new_w - w
    error2 = new_r - r
    error3 = new_T_H - T_H
    error4 = new_factor - factor
    print 'errors: ', error1, error2, error3, error4
    print 'T_H: ', new_T_H
    print 'factor: ', new_factor

    # Check and punish violations
    if r <= 0:
        error1 += 1e9
    #if r > 1:
    #    error1 += 1e9
    if w <= 0:
        error2 += 1e9

    return [error1, error2, error3, error4]
Example #31
0
def create_tpi_params(a_tax_income,
                      b_tax_income,
                      c_tax_income,
                      d_tax_income,
                      b_ellipse,
                      upsilon,
                      J,
                      S,
                      T,
                      beta,
                      sigma,
                      alpha,
                      Z,
                      delta,
                      ltilde,
                      nu,
                      g_y,
                      tau_payroll,
                      retire,
                      mean_income_data,
                      get_baseline=True,
                      input_dir="./OUTPUT",
                      **kwargs):

    if get_baseline:
        ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl")
        variables = pickle.load(open(ss_init, "rb"))
        for key in variables:
            globals()[key] = variables[key]
    else:
        params_path = os.path.join(input_dir,
                                   "Saved_moments/params_changed.pkl")
        variables = pickle.load(open(params_path, "rb"))
        for key in variables:
            globals()[key] = variables[key]
        var_path = os.path.join(input_dir, "SS/ss_vars.pkl")
        variables = pickle.load(open(var_path, "rb"))
        for key in variables:
            globals()[key] = variables[key]
        init_tpi_vars = os.path.join(input_dir, "SSinit/ss_init_tpi_vars.pkl")
        variables = pickle.load(open(init_tpi_vars, "rb"))
        for key in variables:
            globals()[key] = variables[key]
    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    income_tax_params = [
        a_tax_income, b_tax_income, c_tax_income, d_tax_income
    ]
    wealth_tax_params = [h_wealth, p_wealth, m_wealth]
    ellipse_params = [b_ellipse, upsilon]
    parameters = [
        J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss,
        tau_payroll, retire, mean_income_data
    ] + income_tax_params + wealth_tax_params + ellipse_params

    N_tilde = omega.sum(1)
    omega_stationary = omega / N_tilde.reshape(T + S, 1)

    if get_baseline:
        initial_b = bssmat_splus1
        initial_n = nssmat
    else:
        initial_b = bssmat_init
        initial_n = nssmat_init
    # Get an initial distribution of capital with the initial population
    # distribution
    K0 = household.get_K(initial_b, omega_stationary[0].reshape(S, 1), lambdas,
                         g_n_vector[0], 'SS')
    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0 = firm.get_L(e, initial_n, omega_stationary[0].reshape(S, 1), lambdas,
                    'SS')
    Y0 = firm.get_Y(K0, L0, parameters)
    w0 = firm.get_w(Y0, L0, parameters)
    r0 = firm.get_r(Y0, K0, parameters)
    BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape(S, 1),
                           lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas,
                             factor_ss, omega_stationary[0].reshape(S, 1),
                             'SS', parameters, theta, tau_bq)
    tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas,
                           factor_ss, T_H_0, None, 'SS', False, parameters,
                           theta, tau_bq)
    c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(1, J),
                            lambdas.reshape(1, J), b_splus1init, parameters,
                            tax0)

    return (income_tax_params, wealth_tax_params, ellipse_params, parameters,
            N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, w0,
            r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n)
Example #32
0
def run_steady_state(income_tax_parameters, ss_parameters, iterative_params, get_baseline=False, calibrate_model=False, output_dir="./OUTPUT"):
    '''
    ------------------------------------------------------------------------
        Run SS
    ------------------------------------------------------------------------
    '''

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_parameters

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_parameters

    # Generate initial guesses for chi^b_j and chi^n_s
    chi_params = np.zeros(S + J)
    chi_params[:J] = chi_b_guess
    chi_params[J:] = chi_n_guess
    # First run SS simulation with guesses at initial values for b, n, w, r, etc
    # For inital guesses of b and n, we choose very small b, and medium n
    b_guess = np.ones((S, J)).flatten() * 0.05
    n_guess = np.ones((S, J)).flatten() * .4 * ltilde
    # For initial guesses of w, r, T_H, and factor, we use values that are close
    # to some steady state values.
    wguess = 1.2
    rguess = .06
    T_Hguess = 0.12 
    factorguess = 70000.0

    guesses = [wguess, rguess, T_Hguess, factorguess]
    args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params[J:], chi_params[:J], 
             income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e)
    [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve, guesses, args=args_, xtol=mindist_SS, full_output=True)
    [wguess, rguess, T_Hguess, factorguess] = solutions
    fsolve_flag = True
    solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[
                          J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e, fsolve_flag)


    if calibrate_model:
        global Nfeval, value_all, chi_params_all
        Nfeval = 1
        value_all = np.zeros((10000))
        chi_params_all = np.zeros((S+J,10000))
        outputs = {'solutions': solutions, 'chi_params': chi_params}
        ss_init_path = os.path.join(
            output_dir, "Saved_moments/SS_init_solutions.pkl")
        pickle.dump(outputs, open(ss_init_path, "wb"))
        function_to_minimize_X = lambda x: function_to_minimize(
            x, chi_params, income_tax_parameters, ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir)
        bnds = tuple([(1e-6, None)] * (S + J))
        # In order to scale all the parameters to estimate in the minimizer, we have the minimizer fit a vector of ones that
        # will be multiplied by the chi initial guesses inside the function.  Otherwise, if chi^b_j=1e5 for some j, and the
        # minimizer peturbs that value by 1e-8, the % difference will be extremely small, outside of the tolerance of the
        # minimizer, and it will not change that parameter.
        chi_params_scalars = np.ones(S + J)
        #chi_params_scalars = opt.minimize(function_to_minimize_X, chi_params_scalars,
        #                                  method='TNC', tol=MINIMIZER_TOL, bounds=bnds, callback=callbackF(chi_params_scalars), options=MINIMIZER_OPTIONS).x
        # chi_params_scalars = opt.minimize(function_to_minimize, chi_params_scalars, 
        #                                   args=(chi_params, income_tax_parameters, ss_parameters, iterative_params, 
        #                                     omega_SS, rho, lambdas, tau_bq, e, output_dir),
        #                                   method='TNC', tol=MINIMIZER_TOL, bounds=bnds, 
        #                                   callback=callbackF(chi_params_scalars,chi_params, income_tax_parameters, 
        #                                     ss_parameters, iterative_params, omega_SS, rho, lambdas, tau_bq, e, output_dir), 
        #                                   options=MINIMIZER_OPTIONS).x
        chi_params_scalars = opt.minimize(function_to_minimize, chi_params_scalars, 
                                          args=(chi_params, income_tax_parameters, ss_parameters, iterative_params, 
                                            omega_SS, rho, lambdas, tau_bq, e, output_dir),
                                          method='TNC', tol=MINIMIZER_TOL, bounds=bnds, 
                                          options=MINIMIZER_OPTIONS).x
        chi_params *= chi_params_scalars
        print 'The final scaling params', chi_params_scalars
        print 'The final bequest parameter values:', chi_params

        solutions_dict = pickle.load(open(ss_init_path, "rb"))
        solutions = solutions_dict['solutions']
        b_guess = solutions[:S * J]
        n_guess = solutions[S * J:2 * S * J]
        wguess, rguess, factorguess, T_Hguess = solutions[2 * S * J:]
        guesses = [wguess, rguess, T_Hguess, factorguess]
        args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params[J:], chi_params[:J], 
             income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e)
        [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve, guesses, args=args_, xtol=mindist_SS, full_output=True)
        [wguess, rguess, T_Hguess, factorguess] = solutions
        fsolve_flag = True
        solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params[
                          J:], chi_params[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e, fsolve_flag)


    '''
    ------------------------------------------------------------------------
        Generate the SS values of variables, including euler errors
    ------------------------------------------------------------------------
    '''

    if get_baseline:
        outputs = {'solutions': solutions, 'chi_params': chi_params}
        ss_init_dir = os.path.join(
            output_dir, "Saved_moments/SS_baseline_solutions.pkl")
        pickle.dump(outputs, open(ss_init_dir, "wb"))
    else:
        outputs = {'solutions': solutions, 'chi_params': chi_params}
        ss_exp_dir = os.path.join(
            output_dir, "Saved_moments/SS_reform_solutions.pkl")
        pickle.dump(outputs, open(ss_exp_dir, "wb"))

    bssmat = solutions[0:(S - 1) * J].reshape(S - 1, J)
    bq = solutions[(S - 1) * J:S * J] # technically, this is just the intentional bequests - wealth of those with max age
    bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat))
    bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J)))
    nssmat = solutions[S * J:2 * S * J].reshape(S, J)
    wss, rss, factor_ss, T_Hss = solutions[2 * S * J:]

    Kss = household.get_K(bssmat_splus1, omega_SS.reshape(
        S, 1), lambdas, g_n_ss, 'SS')
    Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas, 'SS')
    Yss = firm.get_Y(Kss, Lss, ss_parameters)

    Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss)

    theta = np.zeros(J) #tax.replacement_rate_vals(
        #nssmat, wss, factor_ss, e, J, omega_SS.reshape(S, 1), lambdas)
    BQss = household.get_BQ(rss, bssmat_splus1, omega_SS.reshape(
        S, 1), lambdas, rho.reshape(S, 1), g_n_ss, 'SS')
    b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat))
    
    etr_params_3D = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1))
    mtrx_params_3D = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1))
    etr_params_extended = np.append(etr_params,np.reshape(etr_params[-1,:],(1,etr_params.shape[1])),axis=0)[1:,:]
    etr_params_extended_3D = np.tile(np.reshape(etr_params_extended,(S,1,etr_params_extended.shape[1])),(1,J,1))
    mtry_params_extended = np.append(mtry_params,np.reshape(mtry_params[-1,:],(1,mtry_params.shape[1])),axis=0)[1:,:]
    mtry_params_extended_3D = np.tile(np.reshape(mtry_params_extended,(S,1,mtry_params_extended.shape[1])),(1,J,1))
    e_extended = np.array(list(e) + list(np.zeros(J).reshape(1, J))) 
    nss_extended = np.array(list(nssmat) + list(np.zeros(J).reshape(1, J))) 
    mtry_ss = tax.MTR_capital(rss, bssmat_splus1, wss, e_extended[1:,:], nss_extended[1:,:], factor_ss, 
                              analytical_mtrs, etr_params_extended_3D, mtry_params_extended_3D)

    mtrx_ss = tax.MTR_labor(rss, bssmat_s, wss, e, nssmat, factor_ss, analytical_mtrs, etr_params_3D, mtrx_params_3D)

    #np.savetxt("mtr_ss_capital.csv", mtry_ss, delimiter=",")
    #np.savetxt("mtr_ss_labor.csv", mtrx_ss, delimiter=",")

    taxss_params = (J,S, retire, np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1)),
                    h_wealth, p_wealth, m_wealth, tau_payroll)

    taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas,
                            factor_ss, T_Hss, None, 'SS', False, taxss_params, theta, tau_bq)
    cssmat = household.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape(
        1, J), lambdas.reshape(1, J), bssmat_splus1, ss_parameters, taxss)

    Css = household.get_C(cssmat, omega_SS.reshape(S, 1), lambdas, 'SS')

    resource_constraint = Yss - (Css + Iss)

    print 'Resource Constraint Difference:', resource_constraint

    constraint_params = ltilde
    household.constraint_checker_SS(bssmat, nssmat, cssmat, constraint_params)

    b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat))
    b_splus1 = bssmat_splus1
    b_splus2 = np.array(list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J))))

    chi_b = np.tile(chi_params[:J].reshape(1, J), (S, 1))
    chi_n = np.array(chi_params[J:])
    euler_savings = np.zeros((S, J))
    euler_labor_leisure = np.zeros((S, J))
    for j in xrange(J):
        euler_savings[:, j] = household.euler_savings_func(wss, rss, e[:, j], nssmat[:, j], b_s[:, j], b_splus1[:, j], 
                                 b_splus2[:, j], BQss[j], factor_ss, T_Hss, chi_b[:, j], income_tax_parameters, ss_parameters, 
                                 theta[j], tau_bq[j], rho, lambdas[j])
        euler_labor_leisure[:, j] = household.euler_labor_leisure_func(wss, rss, e[:, j], nssmat[:, j], b_s[:, j], 
                                     b_splus1[:, j], BQss[j], factor_ss, T_Hss, chi_n, income_tax_parameters, 
                                     ss_parameters, theta[j], tau_bq[j], lambdas[j])
    '''
    ------------------------------------------------------------------------
        Save the values in various ways, depending on the stage of
            the simulation, to be used in TPI or graphing functions
    ------------------------------------------------------------------------
    '''

    # Pickle variables
    output = {'Kss': Kss, 'bssmat': bssmat, 'Lss': Lss, 'Css':Css, 'nssmat': nssmat, 'Yss': Yss,
              'wss': wss, 'rss': rss, 'theta': theta, 'BQss': BQss, 'factor_ss': factor_ss,
              'bssmat_s': bssmat_s, 'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1,
              'T_Hss': T_Hss, 'euler_savings': euler_savings,
              'euler_labor_leisure': euler_labor_leisure, 'chi_n': chi_n,
              'chi_b': chi_b}

    utils.mkdirs(os.path.join(output_dir, "SSinit"))
    ss_init_dir = os.path.join(output_dir, "SSinit/ss_init_vars.pkl")
    pickle.dump(output, open(ss_init_dir, "wb"))
    bssmat_init = bssmat_splus1
    nssmat_init = nssmat
    # Pickle variables for TPI initial values
    output2 = {'bssmat_init': bssmat_init, 'nssmat_init': nssmat_init}
    ss_init_tpi = os.path.join(output_dir, "SSinit/ss_init_tpi_vars.pkl")
    pickle.dump(output2, open(ss_init_tpi, "wb"))

    return output
Example #33
0
def create_tpi_params(**sim_params):

    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas
    initial_b = ss_baseline_vars['bssmat_splus1']
    initial_n = ss_baseline_vars['nssmat']

    SS_values = (ss_baseline_vars['Kss'],ss_baseline_vars['Lss'], ss_baseline_vars['rss'], 
                 ss_baseline_vars['wss'], ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'],
                 ss_baseline_vars['bssmat_splus1'], ss_baseline_vars['nssmat'])

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    wealth_tax_params = [sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth']]
    ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']]
    chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']]

    N_tilde = sim_params['omega'].sum(1) #this should just be one in each year given how we've constructed omega
    sim_params['omega'] = sim_params['omega'] / N_tilde.reshape(sim_params['T'] + sim_params['S'], 1)

    tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BQ_dist'], sim_params['BW'], 
                  sim_params['beta'], sim_params['sigma'], sim_params['alpha'], 
                  sim_params['Z'], sim_params['delta'], sim_params['ltilde'], 
                  sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'], 
                  sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde,
                  sim_params['lambdas'], sim_params['e'], sim_params['retire'], sim_params['mean_income_data'], factor] + \
                  wealth_tax_params + ellipse_params + chi_params
    iterative_params = [sim_params['maxiter'], sim_params['mindist_SS'], sim_params['mindist_TPI']]
    

    J, S, T, BQ_dist, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params

    ## Assumption for tax functions is that policy in last year of BW is 
    # extended permanently
    etr_params_TP = np.zeros((S,T+S,sim_params['etr_params'].shape[2]))
    etr_params_TP[:,:BW,:] = sim_params['etr_params']
    etr_params_TP[:,BW:,:] = np.reshape(sim_params['etr_params'][:,BW-1,:],(S,1,sim_params['etr_params'].shape[2]))

    mtrx_params_TP = np.zeros((S,T+S,sim_params['mtrx_params'].shape[2]))
    mtrx_params_TP[:,:BW,:] = sim_params['mtrx_params']
    mtrx_params_TP[:,BW:,:] = np.reshape(sim_params['mtrx_params'][:,BW-1,:],(S,1,sim_params['mtrx_params'].shape[2]))

    mtry_params_TP = np.zeros((S,T+S,sim_params['mtry_params'].shape[2]))
    mtry_params_TP[:,:BW,:] = sim_params['mtry_params']
    mtry_params_TP[:,BW:,:] = np.reshape(sim_params['mtry_params'][:,BW-1,:],(S,1,sim_params['mtry_params'].shape[2]))

    income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP, mtrx_params_TP, mtry_params_TP)

    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''
    # Get an initial distribution of capital with the initial population
    # distribution
    K0_params = (omega[0].reshape(S, 1), lambdas, g_n_vector[0], 'SS')
    K0 = household.get_K(initial_b, K0_params)

    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0_params = (e, omega[0].reshape(S, 1), lambdas, 'SS')
    L0 = firm.get_L(initial_n, L0_params)
    Y0_params = (alpha, Z)
    Y0 = firm.get_Y(K0, L0, Y0_params)
    w0 = firm.get_w(Y0, L0, alpha)
    r0_params = (alpha, delta)
    r0 = firm.get_r(Y0, K0, r0_params)

    BQ0_params = (omega[0].reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r0, initial_b, BQ0_params)

    theta_params = (e, J, omega[0].reshape(S, 1), lambdas)
    theta = tax.replacement_rate_vals(initial_n, w0, factor, theta_params)

    T_H_params = (e, BQ_dist, lambdas, omega[0].reshape(S, 1), 'SS', etr_params_TP[:,0,:], 
                    theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    T_H_0 = tax.get_lump_sum(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_params)

    etr_params_3D = np.tile(np.reshape(etr_params_TP[:,0,:],(S,1,etr_params_TP.shape[2])),(1,J,1))
    tax0_params = (e, BQ_dist, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth, m_wealth, 
                    tau_payroll, theta, tau_bq, J, S)
    tax0 = tax.total_taxes(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_0, None, False, tax0_params)

    c0_params = (e, BQ_dist, lambdas.reshape(1, J), g_y)
    c0 = household.get_cons(omega[0].reshape(S, 1), r0, w0, b_sinit, b_splus1init, initial_n, BQ0.reshape(
        1, J), tax0, c0_params)

    initial_values = (K0, b_sinit, b_splus1init, L0, Y0,
            w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n)

    return (income_tax_params, tpi_params, iterative_params, initial_values, SS_values)
Example #34
0
def inner_loop(outer_loop_vars, params, baseline):
    '''
    This function solves for the inner loop of
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, T_H, factor)
    this function solves the households'
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate
        w          = [T,] vector, wage rate
        b          = [T,S,J] array, wealth holdings
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        T_H        = [T,] vector, lump sum transfer amount(s)


    Functions called:
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.get_lump_sum()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ

    '''

    # unpack variables and parameters pass to function
    bssmat, nssmat, r, w, T_H, factor = outer_loop_vars
    ss_params, income_tax_params, chi_params = params

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params

    # bssmat = START_VALUES['bssmat_splus1']
    # nssmat = START_VALUES['nssmat']
    euler_errors = np.zeros((2*S,J))

    for j in xrange(J):
        # Solve the euler equations
        # if j == 0:
        #     guesses = np.append(bssmat[:, j], nssmat[:, j])
        # elif j == J - 1:
        #     guesses = np.append(bssmat[:, j-1]*2.0, nssmat[:, j-1])
        # else:
        #     guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])

        guesses = np.append(bssmat[:, j], nssmat[:, j])

        euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9,
                                    args=euler_params, xtol=MINIMIZER_TOL, full_output=True)

        euler_errors[:,j] = infodict['fvec']
        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]
    K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS')
    K = household.get_K(bssmat, K_params)
    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    new_r = firm.get_r(Y, K, r_params)
    new_w = firm.get_w(Y, L, alpha)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    if baseline:
        new_factor = mean_income_data / average_income_model
    else:
        new_factor = factor

    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, S, retire)
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                      tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    net_tax_receipts = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params)

    print 'Inner Loop Max Euler Error: ', (np.absolute(euler_errors)).max()

    return euler_errors, bssmat, nssmat, new_r, new_w, \
             net_tax_receipts, new_factor, new_BQ, average_income_model