Exemple #1
0
def test_get_D_ss(budget_balance, expected_tuple):
    '''
    Test of the fiscla.get_D_ss() function.
    '''
    r_gov = 0.03
    Y = 1.176255339
    p = Specifications()
    p.debt_ratio_ss = 1.2
    p.budget_balance = budget_balance
    p.g_n_ss = 0.02
    test_tuple = fiscal.get_D_ss(r_gov, Y, p)

    for i, v in enumerate(test_tuple):
        assert np.allclose(v, expected_tuple[i])
Exemple #2
0
def inner_loop(outer_loop_vars, p, client):
    '''
    This function solves for the inner loop of the SS.  That is, given
    the guesses of the outer loop variables (r, w, TR, factor) this
    function solves the households' problems in the SS.

    Args:
        outer_loop_vars (tuple): tuple of outer loop variables,
            (bssmat, nssmat, r, BQ, TR, factor) or
            (bssmat, nssmat, r, BQ, Y, TR, factor)
        bssmat (Numpy array): initial guess at savings, size = SxJ
        nssmat (Numpy array): initial guess at labor supply, size = SxJ
        BQ (array_like): aggregate bequest amount(s)
        Y (scalar): real GDP
        TR (scalar): lump sum transfer amount
        factor (scalar): scaling factor converting model units to dollars
        w (scalar): real wage rate
        p (OG-USA Specifications object): model parameters
        client (Dask client object): client

    Returns:
        (tuple): results from household solution:

            * euler_errors (Numpy array): errors terms from FOCs,
                size = 2SxJ
            * bssmat (Numpy array): savings, size = SxJ
            * nssmat (Numpy array): labor supply, size = SxJ
            * new_r (scalar): real interest rate on firm capital
            * new_r_gov (scalar): real interest rate on government debt
            * new_r_hh (scalar): real interest rate on household
                portfolio
            * new_w (scalar): real wage rate
            * new_TR (scalar): lump sum transfer amount
            * new_Y (scalar): real GDP
            * new_factor (scalar): scaling factor converting model
                units to dollars
            * new_BQ (array_like): aggregate bequest amount(s)
            * average_income_model (scalar): average income in model
                units

    '''
    # unpack variables to pass to function
    if p.budget_balance:
        bssmat, nssmat, r, BQ, TR, factor = outer_loop_vars
        r_hh = r
        Y = 1.0  # placeholder
        K = 1.0  # placeholder
    else:
        bssmat, nssmat, r, BQ, Y, TR, factor = outer_loop_vars
        K = firm.get_K_from_Y(Y, r, p, 'SS')
    # initialize array for euler errors
    euler_errors = np.zeros((2 * p.S, p.J))

    w = firm.get_w_from_r(r, p, 'SS')
    r_gov = fiscal.get_r_gov(r, p)
    D, D_d, D_f, new_borrowing, debt_service, new_borrowing_f =\
        fiscal.get_D_ss(r_gov, Y, p)
    r_hh = aggr.get_r_hh(r, r_gov, K, D)
    bq = household.get_bq(BQ, None, p, 'SS')
    tr = household.get_tr(TR, None, p, 'SS')

    lazy_values = []
    for j in range(p.J):
        guesses = np.append(bssmat[:, j], nssmat[:, j])
        euler_params = (r_hh, w, bq[:, j], tr[:, j], factor, j, p)
        lazy_values.append(delayed(opt.fsolve)(euler_equation_solver,
                                               guesses * .9,
                                               args=euler_params,
                                               xtol=MINIMIZER_TOL,
                                               full_output=True))
    if client:
        futures = client.compute(lazy_values, num_workers=p.num_workers)
        results = client.gather(futures)
    else:
        results = results = compute(
            *lazy_values, scheduler=dask.multiprocessing.get,
            num_workers=p.num_workers)

    # for j, result in results.items():
    for j, result in enumerate(results):
        [solutions, infodict, ier, message] = result
        euler_errors[:, j] = infodict['fvec']
        bssmat[:, j] = solutions[:p.S]
        nssmat[:, j] = solutions[p.S:]

    L = aggr.get_L(nssmat, p, 'SS')
    B = aggr.get_B(bssmat, p, 'SS', False)
    K_demand_open = firm.get_K(L, p.world_int_rate[-1], p, 'SS')
    K, K_d, K_f = aggr.get_K_splits(B, K_demand_open, D_d, p.zeta_K[-1])
    Y = firm.get_Y(K, L, p, 'SS')
    if p.zeta_K[-1] == 1.0:
        new_r = p.world_int_rate[-1]
    else:
        new_r = firm.get_r(Y, K, p, 'SS')
    new_w = firm.get_w_from_r(new_r, p, 'SS')

    b_s = np.array(list(np.zeros(p.J).reshape(1, p.J)) +
                   list(bssmat[:-1, :]))
    new_r_gov = fiscal.get_r_gov(new_r, p)
    new_r_hh = aggr.get_r_hh(new_r, new_r_gov, K, D)
    average_income_model = ((new_r_hh * b_s + new_w * p.e * nssmat) *
                            p.omega_SS.reshape(p.S, 1) *
                            p.lambdas.reshape(1, p.J)).sum()
    if p.baseline:
        new_factor = p.mean_income_data / average_income_model
    else:
        new_factor = factor
    new_BQ = aggr.get_BQ(new_r_hh, bssmat, None, p, 'SS', False)
    new_bq = household.get_bq(new_BQ, None, p, 'SS')
    tr = household.get_tr(TR, None, p, 'SS')
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, None, p)
    etr_params_3D = np.tile(
        np.reshape(p.etr_params[-1, :, :],
                   (p.S, 1, p.etr_params.shape[2])), (1, p.J, 1))
    taxss = tax.net_taxes(
        new_r_hh, new_w, b_s, nssmat, new_bq, factor, tr, theta, None,
        None, False, 'SS', p.e, etr_params_3D, p)
    cssmat = household.get_cons(
        new_r_hh, new_w, b_s, bssmat, nssmat, new_bq, taxss, p.e,
        p.tau_c[-1, :, :], p)
    total_tax_revenue, _, agg_pension_outlays, _, _, _, _, _, _ =\
        aggr.revenue(new_r_hh, new_w, b_s, nssmat, new_bq, cssmat, Y, L,
                     K, factor, theta, etr_params_3D, p, 'SS')
    G = fiscal.get_G_ss(Y, total_tax_revenue, agg_pension_outlays, TR,
                        new_borrowing, debt_service, p)
    new_TR = fiscal.get_TR(Y, TR, G, total_tax_revenue,
                           agg_pension_outlays, p, 'SS')

    return euler_errors, bssmat, nssmat, new_r, new_r_gov, new_r_hh, \
        new_w, new_TR, Y, new_factor, new_BQ, average_income_model
Exemple #3
0
def SS_solver(bmat, nmat, r, BQ, TR, factor, Y, p, client,
              fsolve_flag=False):
    '''
    Solves for the steady state distribution of capital, labor, as well
    as w, r, TR and the scaling factor, using functional iteration.

    Args:
        bmat (Numpy array): initial guess at savings, size = SxJ
        nmat (Numpy array): initial guess at labor supply, size = SxJ
        r (scalar): real interest rate
        BQ (array_like): aggregate bequest amount(s)
        TR (scalar): lump sum transfer amount
        factor (scalar): scaling factor converting model units to dollars
        Y (scalar): real GDP
        p (OG-USA Specifications object): model parameters
        client (Dask client object): client

    Returns:
        output (dictionary): dictionary with steady state solution
            results

    '''
    dist = 10
    iteration = 0
    dist_vec = np.zeros(p.maxiter)
    maxiter_ss = p.maxiter
    nu_ss = p.nu
    if fsolve_flag:  # case where already solved via SS_fsolve
        maxiter_ss = 1
    while (dist > p.mindist_SS) and (iteration < maxiter_ss):
        # Solve for the steady state levels of b and n, given w, r,
        # Y and factor
        if p.budget_balance:
            outer_loop_vars = (bmat, nmat, r, BQ, TR, factor)
        else:
            outer_loop_vars = (bmat, nmat, r, BQ, Y, TR, factor)

        (euler_errors, new_bmat, new_nmat, new_r, new_r_gov, new_r_hh,
         new_w, new_TR, new_Y, new_factor, new_BQ,
         average_income_model) =\
            inner_loop(outer_loop_vars, p, client)

        r = utils.convex_combo(new_r, r, nu_ss)
        factor = utils.convex_combo(new_factor, factor, nu_ss)
        BQ = utils.convex_combo(new_BQ, BQ, nu_ss)
        if p.baseline_spending:
            Y = utils.convex_combo(new_Y, Y, nu_ss)
            if Y != 0:
                dist = np.array([utils.pct_diff_func(new_r, r)] +
                                list(utils.pct_diff_func(new_BQ, BQ)) +
                                [utils.pct_diff_func(new_Y, Y)] +
                                [utils.pct_diff_func(new_factor,
                                                     factor)]).max()
            else:
                # If Y is zero (if there is no output), a percent difference
                # will throw NaN's, so we use an absolute difference
                dist = np.array([utils.pct_diff_func(new_r, r)] +
                                list(utils.pct_diff_func(new_BQ, BQ)) +
                                [abs(new_Y - Y)] +
                                [utils.pct_diff_func(new_factor,
                                                     factor)]).max()
        else:
            TR = utils.convex_combo(new_TR, TR, nu_ss)
            dist = np.array([utils.pct_diff_func(new_r, r)] +
                            list(utils.pct_diff_func(new_BQ, BQ)) +
                            [utils.pct_diff_func(new_TR, TR)] +
                            [utils.pct_diff_func(new_factor, factor)]).max()
        dist_vec[iteration] = dist
        # Similar to TPI: if the distance between iterations increases, then
        # decrease the value of nu to prevent cycling
        if iteration > 10:
            if dist_vec[iteration] - dist_vec[iteration - 1] > 0:
                nu_ss /= 2.0
                print('New value of nu:', nu_ss)
        iteration += 1
        print('Iteration: %02d' % iteration, ' Distance: ', dist)

    # Generate the SS values of variables, including euler errors
    bssmat_s = np.append(np.zeros((1, p.J)), bmat[:-1, :], axis=0)
    bssmat_splus1 = bmat
    nssmat = nmat

    rss = r
    r_gov_ss = fiscal.get_r_gov(rss, p)
    TR_ss = TR
    Lss = aggr.get_L(nssmat, p, 'SS')
    Bss = aggr.get_B(bssmat_splus1, p, 'SS', False)
    (Dss, D_d_ss, D_f_ss, new_borrowing, debt_service,
     new_borrowing_f) = fiscal.get_D_ss(r_gov_ss, Y, p)
    K_demand_open_ss = firm.get_K(Lss, p.world_int_rate[-1], p, 'SS')
    Kss, K_d_ss, K_f_ss = aggr.get_K_splits(
        Bss, K_demand_open_ss, D_d_ss, p.zeta_K[-1])
    Yss = firm.get_Y(Kss, Lss, p, 'SS')
    r_hh_ss = aggr.get_r_hh(rss, r_gov_ss, Kss, Dss)
    # Note that implicity in this computation is that immigrants'
    # wealth is all in the form of private capital
    I_d_ss = aggr.get_I(bssmat_splus1, K_d_ss, K_d_ss, p, 'SS')
    Iss = aggr.get_I(bssmat_splus1, Kss, Kss, p, 'SS')
    wss = new_w
    BQss = new_BQ
    factor_ss = factor
    bqssmat = household.get_bq(BQss, None, p, 'SS')
    trssmat = household.get_tr(TR_ss, None, p, 'SS')
    theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, None, p)

    # Compute effective and marginal tax rates for all agents
    etr_params_3D = np.tile(np.reshape(
        p.etr_params[-1, :, :], (p.S, 1, p.etr_params.shape[2])), (1, p.J, 1))
    mtrx_params_3D = np.tile(np.reshape(
        p.mtrx_params[-1, :, :], (p.S, 1, p.mtrx_params.shape[2])),
                             (1, p.J, 1))
    mtry_params_3D = np.tile(np.reshape(
        p.mtry_params[-1, :, :], (p.S, 1, p.mtry_params.shape[2])),
                             (1, p.J, 1))
    mtry_ss = tax.MTR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, True,
                             p.e, etr_params_3D, mtry_params_3D, p)
    mtrx_ss = tax.MTR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, False,
                             p.e, etr_params_3D, mtrx_params_3D, p)
    etr_ss = tax.ETR_income(r_hh_ss, wss, bssmat_s, nssmat, factor, p.e,
                            etr_params_3D, p)

    taxss = tax.net_taxes(r_hh_ss, wss, bssmat_s, nssmat, bqssmat,
                          factor_ss, trssmat, theta, None, None, False,
                          'SS', p.e, etr_params_3D, p)
    cssmat = household.get_cons(r_hh_ss, wss, bssmat_s, bssmat_splus1,
                                nssmat, bqssmat, taxss,
                                p.e, p.tau_c[-1, :, :], p)
    yss_before_tax_mat = household.get_y(
        r_hh_ss, wss, bssmat_s, nssmat, p)
    Css = aggr.get_C(cssmat, p, 'SS')

    (total_tax_revenue, iit_payroll_tax_revenue, agg_pension_outlays,
     bequest_tax_revenue, wealth_tax_revenue, cons_tax_revenue,
     business_tax_revenue, payroll_tax_revenue, iit_revenue
     ) = aggr.revenue(
         r_hh_ss, wss, bssmat_s, nssmat, bqssmat, cssmat, Yss, Lss, Kss,
         factor, theta, etr_params_3D, p, 'SS')
    Gss = fiscal.get_G_ss(
        Yss, total_tax_revenue, agg_pension_outlays, TR_ss,
        new_borrowing, debt_service, p)

    # Compute total investment (not just domestic)
    Iss_total = aggr.get_I(None, Kss, Kss, p, 'total_ss')

    # solve resource constraint
    # net foreign borrowing
    print('Foreign debt holdings = ', D_f_ss)
    print('Foreign capital holdings = ', K_f_ss)
    debt_service_f = fiscal.get_debt_service_f(r_hh_ss, D_f_ss)
    RC = aggr.resource_constraint(
        Yss, Css, Gss, I_d_ss, K_f_ss, new_borrowing_f, debt_service_f,
        r_hh_ss, p)
    print('resource constraint: ', RC)

    if Gss < 0:
        print('Steady state government spending is negative to satisfy'
              + ' budget')

    if ENFORCE_SOLUTION_CHECKS and (np.absolute(RC) >
                                    p.mindist_SS):
        print('Resource Constraint Difference:', RC)
        err = 'Steady state aggregate resource constraint not satisfied'
        raise RuntimeError(err)

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

    euler_savings = euler_errors[:p.S, :]
    euler_labor_leisure = euler_errors[p.S:, :]
    print('Maximum error in labor FOC = ',
          np.absolute(euler_labor_leisure).max())
    print('Maximum error in savings FOC = ',
          np.absolute(euler_savings).max())

    # Return dictionary of SS results
    output = {'Kss': Kss, 'K_f_ss': K_f_ss, 'K_d_ss': K_d_ss,
              'Bss': Bss, 'Lss': Lss, 'Css': Css, 'Iss': Iss,
              'Iss_total': Iss_total, 'I_d_ss': I_d_ss, 'nssmat': nssmat,
              'Yss': Yss, 'Dss': Dss, 'D_f_ss': D_f_ss,
              'D_d_ss': D_d_ss, 'wss': wss, 'rss': rss,
              'r_gov_ss': r_gov_ss, 'r_hh_ss': r_hh_ss, 'theta': theta,
              'BQss': BQss, 'factor_ss': factor_ss, 'bssmat_s': bssmat_s,
              'cssmat': cssmat, 'bssmat_splus1': bssmat_splus1,
              'yss_before_tax_mat': yss_before_tax_mat,
              'bqssmat': bqssmat, 'TR_ss': TR_ss, 'trssmat': trssmat,
              'Gss': Gss, 'total_tax_revenue': total_tax_revenue,
              'business_tax_revenue': business_tax_revenue,
              'iit_payroll_tax_revenue': iit_payroll_tax_revenue,
              'iit_revenue': iit_revenue,
              'payroll_tax_revenue': payroll_tax_revenue,
              'agg_pension_outlays': agg_pension_outlays,
              'bequest_tax_revenue': bequest_tax_revenue,
              'wealth_tax_revenue': wealth_tax_revenue,
              'cons_tax_revenue': cons_tax_revenue,
              'euler_savings': euler_savings,
              'debt_service_f': debt_service_f,
              'new_borrowing_f': new_borrowing_f,
              'debt_service': debt_service,
              'new_borrowing': new_borrowing,
              'euler_labor_leisure': euler_labor_leisure,
              'resource_constraint_error': RC,
              'etr_ss': etr_ss, 'mtrx_ss': mtrx_ss, 'mtry_ss': mtry_ss}

    return output