Ejemplo n.º 1
0
def backward_iterate_olg(ucp, a, Pi, coh, r, beta, sigma):
    """One-step backward iteration function."""
    # Implied consumption today consistent with Euler equation (on tomorrow's grid for assets a')
    c_nextgrid = (beta * (1 + r) * (Pi @ ucp))**(-1 / sigma)

    # We have consumption today for each a' tomorrow (a mapping from total cash on hand today c''+a' to a' tomorrow)
    # Interpolate to get mapping of actual cash on hand in each state to assets tomorrow a'
    a_pol = interpolate_y(c_nextgrid + a, coh, a)

    # Derive the consumption policy function using the above mapping from cash-on-hand today to a' tomorrow and the
    # mapping from consumption today to a' (c_nextgrid)
    c_pol = interpolate_y(a, a_pol, c_nextgrid)

    # Replace constrained agents with minimum asset level (bottom of grid)
    cstr_i = a_pol < a[0]  # index of constrained bins
    if np.any(cstr_i):
        a_pol[cstr_i], c_pol[cstr_i] = constrained(coh[cstr_i], a)

    # Replace zeros by 1E-10 to compute marginal utility without dividing by zero
    c_pol[c_pol <= 0] = 1E-10

    # Calculate marginal utility
    uc = c_pol**(-sigma)

    return a_pol, c_pol, uc
Ejemplo n.º 2
0
def household(Va_p,
              Pi_p,
              a_grid,
              e_grid,
              T,
              w,
              r,
              beta,
              eis,
              frisch,
              vphi,
              c_const,
              n_const,
              ssflag=False):
    """Single backward iteration step using endogenous gridpoint method for households with separable CRRA utility.

    Order of returns matters! backward_var, assets, others
    """
    # this one is useful to do internally
    ws = w * e_grid

    # uc(z_t, a_t)
    uc_nextgrid = (beta * Pi_p) @ Va_p

    # c(z_t, a_t) and n(z_t, a_t)
    c_nextgrid, n_nextgrid = cn(uc_nextgrid, ws[:, np.newaxis], eis, frisch,
                                vphi)

    # c(z_t, a_{t-1}) and n(z_t, a_{t-1})
    lhs = c_nextgrid - ws[:, np.newaxis] * n_nextgrid + a_grid[
        np.newaxis, :] - T[:, np.newaxis]
    rhs = (1 + r) * a_grid
    c = utils.interpolate_y(lhs, rhs, c_nextgrid)
    n = utils.interpolate_y(lhs, rhs, n_nextgrid)

    # test constraints, replace if needed
    a = rhs + ws[:, np.newaxis] * n + T[:, np.newaxis] - c
    iconst = np.nonzero(a < a_grid[0])
    a[iconst] = a_grid[0]

    if ssflag:
        # use precomputed values
        c[iconst] = c_const[iconst]
        n[iconst] = n_const[iconst]
    else:
        # have to solve again if in transition
        uc_seed = c_const[iconst]**(-1 / eis)
        c[iconst], n[iconst] = solve_cn(
            ws[iconst[0]], rhs[iconst[1]] + T[iconst[0]] - a_grid[0], eis,
            frisch, vphi, uc_seed)

    # calculate marginal utility to go backward
    Va = (1 + r) * c**(-1 / eis)

    # efficiency units of labor which is what really matters
    ns = e_grid[:, np.newaxis] * n

    return Va, a, c, n, ns
Ejemplo n.º 3
0
def step6(ap_endo, c_endo, z_grid, b_grid, a_grid, ra, rb, chi0, chi1, chi2):
    # b(z, k, a)
    zzz = z_grid[:, np.newaxis, np.newaxis]
    aaa = a_grid[np.newaxis, np.newaxis, :]
    b_endo = (c_endo + ap_endo + b_grid[0] - (1 + ra) * aaa + Psi_fun(ap_endo, aaa, ra, chi0, chi1, chi2) -
              zzz) / (1 + rb)

    # b'(z, b, a), a'(z, b, a)
    # assert np.min(np.diff(b_endo, axis=1)) < 0, 'b(kappa) is not decreasing'
    # assert np.min(np.diff(ap_endo, axis=1)) < 0, 'ap(kappa) is not decreasing'
    ap = utils.interpolate_y(b_endo[:, ::-1, :].swapaxes(1, 2), b_grid, 
                             ap_endo[:, ::-1, :].swapaxes(1, 2)).swapaxes(1, 2)
    return ap
Ejemplo n.º 4
0
def backward_iterate(Va_p, Pi_p, a_grid, e_grid, r, w, beta, eis):
    """Single backward iteration step using endogenous gridpoint method for households with CRRA utility.

    Order of returns matters! backward_var, assets, others

    Parameters
    ----------
    Va_p : np.ndarray
        marginal value of assets tomorrow
    Pi_p : np.ndarray
        Markov transition matrix for skills tomorrow
    a_grid : np.ndarray
        asset grid
    e_grid : np.ndarray
        skill grid
    r : float
        ex-post interest rate
    w : float
        wage
    beta : float
        discount rate today
    eis : float
        elasticity of intertemporal substitution

    Returns
    ----------
    Va : np.ndarray, shape(nS, nA)
        marginal value of assets today
    a : np.ndarray, shape(nS, nA)
        asset policy today
    c : np.ndarray, shape(nS, nA)
        consumption policy today
    """
    uc_nextgrid = (beta * Pi_p) @ Va_p
    c_nextgrid = uc_nextgrid**(-eis)
    coh = (1 + r) * a_grid[np.newaxis, :] + w * e_grid[:, np.newaxis]
    a = utils.interpolate_y(c_nextgrid + a_grid, coh, a_grid)
    utils.setmin(a, a_grid[0])
    c = coh - a
    Va = (1 + r) * c**(-1 / eis)
    return Va, a, c
Ejemplo n.º 5
0
def time_iteration(sigma, theta, alpha, delta, r, lump, beta, Pi_e, d_grid,
                   z_grid, b_grid, k_grid, zzz, lll, bbb, ddd, Ne, Nb, Nd, Nk,
                   rhs, Vb, Vd, P_n_p, P_d_p):

    # output containers
    sol_shape = (Ne, Nb, Nd)
    Wb = np.zeros(sol_shape)
    Wd = np.zeros(sol_shape)

    d_unc = np.zeros(sol_shape)
    b_unc = np.zeros(sol_shape)
    d_con = np.zeros(sol_shape)
    ''' computes one backward EGM step '''

    # a. pre-compute post-decision value functions and LHS offirst-order optimality equation
    # i. post-decision functions
    Wb[:, :, :] = (Vb.T @ (beta * Pi_e.T)).T
    Wd[:, :, :] = (Vd.T @ (beta * Pi_e.T)).T
    # ii. LHS of FOC optimality equation in unconstrained and constrained case
    lhs_unc = Wd / Wb
    lhs_con = lhs_unc[:, 0, :]
    lhs_con = lhs_con[:,
                      np.newaxis, :] / (1 + k_grid[np.newaxis, :, np.newaxis])

    # b. get unconstrained solution to d'(z,b,d), a'(z,b,d), c(z,b,d)
    # i. get d'(z,b',d), b(z,b',d), c(z,b,d) with EGM
    dp_endo_unc, _, b_endo_unc, _ = solve_unconstrained(
        sigma, theta, alpha, delta, r, d_grid, b_grid, z_grid, lump, Ne, Nb,
        Nd, lhs_unc, rhs, Wb, P_d_p, P_n_p)
    # ii. use d'(z,b',d), b(z,b',d) to interpolate to d'(z,b,d), b'(z,b,d)
    i, pi = utils.interpolate_coord(b_endo_unc.swapaxes(
        1, 2), b_grid)  # gives interpolation weights from a' grid to a grid
    d_unc[:, :, :] = utils.apply_coord(i, pi, dp_endo_unc.swapaxes(
        1, 2)).swapaxes(1, 2)  # apply weights to d'(z,a',d)->d'(z,a,d)
    b_unc[:, :, :] = utils.apply_coord(i, pi, b_grid).swapaxes(
        1, 2)  # apply weights to  a'(z,a',d)->a'(z,a,d)

    # c. get constrained solution to d'(z,0,d), b'(z,0,d), c(z,0,d)
    # i. get d'(z,k,d), b(z,k,d), c(z,k,d) with EGM
    dp_endo_con, _, b_endo_con, _ = solve_constrained(sigma, theta, alpha,
                                                      delta, r, d_grid, b_grid,
                                                      k_grid, z_grid, lump, Ne,
                                                      Nk, Nd, lhs_con, rhs, Wb,
                                                      P_n_p, P_d_p)
    # ii. get d'(z,b,d) by interpolating using b'(z,k,d)
    d_con[:] = utils.interpolate_y(b_endo_con[:, ::-1, :].swapaxes(1, 2),
                                   b_grid, dp_endo_con[:, ::-1, :].swapaxes(
                                       1, 2)).swapaxes(1, 2)

    # d. collect policy functions d',b',c by combining unconstrained and constrained solutions
    d, b, c = collect_policy(delta, alpha, r, Ne, Nb, Nd, b_grid, zzz, lll,
                             ddd, bbb, d_unc, b_unc, d_con, P_n_p, P_d_p)
    c_d = d - (1 - delta) * ddd  # durable investment policy fuctions

    # e. update Vb, Vd
    # i. compute marginal utilities
    c[c < 0] = 1e-8  # for numerical stability while converging
    uc = theta * c**(theta - 1) * (ddd)**(1 - theta) * (
        (c**theta * (ddd)**(1 - theta)))**(-sigma)
    ud = (1 - theta) * c**theta * (ddd)**(-theta) * (
        (c**theta * (ddd)**(1 - theta)))**(-sigma)
    # ii. compute Vb, Vd using envelope conditions
    Vb = (1 / P_n_p) * (1 + r) * uc
    Vd = ud + (1 / P_n_p) * uc * (P_d_p * (1 - delta) - 0.5 * alpha *
                                  ((1 - delta)**2 - (d / ddd)**2))

    return Vb, Vd, d, b, c, c_d
Ejemplo n.º 6
0
def EGMhousehold( EVa_p, Pi_p, Pi_ern, a_grid, Pi_seed, rstar, sBorrow, P, hss, kappa, ssN,
                 e_grid,pi_e, pi_ern, w, ra, beta, eis, Eq, N_, destr_L, destrO_L, b, Benefit_type, T_dist, pi_beta, wss,
                 Tss, Ttd, Tuni, ssAvgInc, VAT,  nPoints, cs_avg, ttd_inf, frisch, ssflag=False):
    """Single backward iteration step using endogenous gridpoint method for households with separable CRRA utility."""


     
    x = a_grid >= 0
    x = x.astype(int)
    R = 1 + ra * x + (1- x) * (ra + kappa)    
    
    nBeta = nPoints[0]
    ne = nPoints[1]
    nA = nPoints[2]
    nN = 2
    
    e_grid_alt = e_grid
        
    sol = {'N' : {}, 'S' : {}} # create dict containing vars for each employment state 
    
    # reshape some input
    EVa_p  =                 np.reshape(EVa_p, (nBeta, ne, nN, nA))
    U_inc, _  = Unemp_benefit(Benefit_type, b, e_grid, pi_ern, ne, wss) 
    

    
    T =  transfers(pi_ern, Tss, e_grid, T_dist)

    Ttd_ = transfers_td_e(pi_ern, Ttd, e_grid)
    
    T_agg =  np.broadcast_to(T[np.newaxis, :, np.newaxis] + Ttd_[np.newaxis, :, np.newaxis] + Tuni , (nBeta,ne, nA)) 
    
    # u'c(z_t, a_t) 
    sol['N']['uc_nextgrid']  = np.ones([nBeta, ne, nA]) * np.nan
    sol['S']['uc_nextgrid']  = np.ones([nBeta, ne, nA]) * np.nan
    sol['N']['tInc']         = np.ones([nBeta, ne, nA]) * np.nan
    sol['S']['tInc']         = np.ones([nBeta, ne, nA]) * np.nan


    a_grid_org = a_grid
    dN = N_ / ssN
    dU = (1-N_) / (1-ssN)
    
    for j in range(nBeta):
        sol['N']['uc_nextgrid'][j,:,:]  =  (beta[j] * Pi_ern) @ EVa_p[j,:,0, :] 
        sol['S']['uc_nextgrid'][j,:,:]  =  (beta[j] * Pi_ern) @ EVa_p[j,:,1, :] 
            
    for h in sol:    
        if h == 'N':
            a_grid = a_grid_org 
        if h == 'S':
            a_grid = a_grid_org 
            
        sol[h]['c_nextgrid'] = inv_mu(sol[h]['uc_nextgrid'], eis)
        if h == 'N':
            tax_IN  = avgTaxf(w   * e_grid, ssAvgInc, cs_avg) 
            sol[h]['tInc']  = np.broadcast_to(tax_IN[np.newaxis, :, np.newaxis], (nBeta,ne, nA))
            sol[h]['I']   =   (1 - sol[h]['tInc'])  * w   * e_grid[np.newaxis, :, np.newaxis] * dN + T_agg
        if h == 'S': 
            tax_IS  = avgTaxf(U_inc, ssAvgInc, cs_avg) 
            sol[h]['tInc']  = np.broadcast_to(tax_IS[np.newaxis, :, np.newaxis], (nBeta,ne, nA))
            sol[h]['I']   =   (1 - sol[h]['tInc'])  * U_inc[np.newaxis,:, np.newaxis]  * dU  + T_agg

        # interpolate for each beta 
        sol[h]['c'] =  np.empty([nBeta, ne, nA])  
        

        for j in range(nBeta):
            lhs = sol[h]['c_nextgrid'][j,:,:] * (1+VAT) + a_grid[np.newaxis, :]  - sol[h]['I'][j,:,:]
            rhs = R * a_grid         
            sol[h]['c'][j,:,:]  =     utils.interpolate_y(lhs,  rhs, sol[h]['c_nextgrid'][j,:,:])
      
        sol[h]['a'] = R * a_grid[np.newaxis, np.newaxis, :]   + sol[h]['I'] - sol[h]['c']  * (1+VAT) 
        
        # check borrowing constraint 
        sol[h]['a'], sol[h]['c'] = constr(sol[h]['a'], sol[h]['c'], a_grid[0], 'a', R, a_grid, VAT, sol[h]['I'])
        
   
    # unpack from dict and aggregate   
    cN  =  np.reshape(sol['N']['c'] , (ne*nBeta, nA))  
    cS  =  np.reshape(sol['S']['c'] , (ne*nBeta, nA)) 
    aN  =  np.reshape(sol['N']['a'] , (ne*nBeta, nA))  
    aS  =  np.reshape(sol['S']['a'] , (ne*nBeta, nA)) 

    
    dN = N_ / ssN
    dU = (1-N_) / (1-ssN)
    
    IncN  = np.reshape(sol['N']['I'], (ne*nBeta, nA))        
    IncS  = np.reshape(sol['S']['I'], (ne*nBeta, nA))        
    IncNpretax  = np.reshape(sol['N']['I']    + sol['N']['tInc']  * w * e_grid[np.newaxis, :, np.newaxis] , (ne*nBeta, nA))   
    IncSpretax  = np.reshape(sol['S']['I']    + sol['S']['tInc']  * U_inc[np.newaxis, :, np.newaxis] , (ne*nBeta, nA))   
     
    Ntaxes = sol['N']['tInc']  * w   * e_grid[np.newaxis, :, np.newaxis]
    Ntaxes =  np.reshape(np.broadcast_to(Ntaxes, (nBeta,ne, nA)), (ne*nBeta, nA))     
    Staxes = np.reshape(sol['S']['tInc']  * U_inc[np.newaxis, :, np.newaxis]  , (ne*nBeta, nA))   

    
    mu_N = cN ** (-1 / eis)
    mu_S = cS ** (-1 / eis)
    # EnVa =  R[np.newaxis, :] *  (destr * (1-Eq)     * mu_S   + (1 - destr * (1-Eq)) * mu_N)
    # EuVa =  R[np.newaxis, :] *  ((1-Eq* (1-destrO)) * mu_S   + Eq * (1-destrO)      * mu_N) 
    EnVa =  R[np.newaxis, :] *  (destr_L * (1-Eq)     * mu_S   + (1 - destr_L * (1-Eq)) * mu_N)
    EuVa =  R[np.newaxis, :] *  ((1-Eq* (1-destrO_L)) * mu_S   + Eq * (1-destrO_L)      * mu_N) 
                
    Incagg = N_ * IncN + (1-N_) * IncS

    # Aggregate 
    EVa =   np.reshape( np.stack((EnVa, EuVa), axis=-2), (ne*nBeta*nN, nA)) 
    
    # a =  np.reshape( np.stack((aN * dN, aS * dU), axis=-2), (ne*nBeta*nN, nA)) 
    # c = np.reshape( np.stack((cN* dN, cS* dU), axis=-2), (ne*nBeta*nN, nA)) 
    
    a =  np.reshape( np.stack((aN , aS ), axis=-2), (ne*nBeta*nN, nA)) 
    c = np.reshape( np.stack((cN, cS), axis=-2), (ne*nBeta*nN, nA)) 
    
    UincAgg = np.reshape(np.broadcast_to( U_inc[np.newaxis, :, np.newaxis], (nBeta,ne, nA)), (ne*nBeta, nA)) 
        

    zeromat = np.zeros([ne*nBeta, nA])
    

    tInc = np.reshape( np.stack((Ntaxes * dN, dU * Staxes), axis=-2), (ne*nBeta*nN, nA)) 
    UincAgg =np.reshape( np.stack((zeromat,  UincAgg), axis=-2), (ne*nBeta*nN, nA)) 
    
    Inc = np.reshape( np.stack((IncN * dN, IncS* dU), axis=-2), (ne*nBeta*nN, nA)) 
    IncN = np.reshape( np.stack((IncN , zeromat), axis=-2), (ne*nBeta*nN, nA)) 
    IncS = np.reshape( np.stack((zeromat, IncS), axis=-2), (ne*nBeta*nN, nA)) 
    
    #print(N)
    #print(dU)
    
    # ctd = np.reshape( np.stack((cN* N + cS* (1-N), cN* N + cS* (1-N) ), axis=-2), (ne*nBeta*nN, nA)) 
    # atd = np.reshape( np.stack((aN* N + aS* (1-N) , aN* N + aS* (1-N) ), axis=-2), (ne*nBeta*nN, nA)) 
    ctd = np.reshape( np.stack((cN, cS  ), axis=-2), (ne*nBeta*nN, nA)) 
    atd = np.reshape( np.stack((aN ,  aS), axis=-2), (ne*nBeta*nN, nA)) 
        
    cN = np.reshape( np.stack((cN , zeromat ), axis=-2), (ne*nBeta*nN, nA)) 
    cS = np.reshape( np.stack((zeromat , cS ), axis=-2), (ne*nBeta*nN, nA)) 
    aN = np.reshape( np.stack((aN , zeromat ), axis=-2), (ne*nBeta*nN, nA)) 
    aS = np.reshape( np.stack((zeromat , aS ), axis=-2), (ne*nBeta*nN, nA)) 

    taxN = np.reshape( np.stack((Ntaxes , zeromat ), axis=-2), (ne*nBeta*nN, nA))  
    taxS = np.reshape( np.stack((zeromat , Staxes ), axis=-2), (ne*nBeta*nN, nA)) 

    a_debt = np.reshape(np.broadcast_to( (1-x) * a_grid[np.newaxis, np.newaxis, :], (nBeta,ne, nA)), (ne*nBeta, nA)) 
    
    
    a_debtN = np.reshape( np.stack(( a_debt ,zeromat ), axis=-2), (ne*nBeta*nN, nA)) 
    a_debtS = np.reshape( np.stack((zeromat, a_debt ), axis=-2), (ne*nBeta*nN, nA)) 
    a_debt = np.reshape( np.stack((dN * a_debt ,dU * a_debt ), axis=-2), (ne*nBeta*nN, nA)) 
    
    return EVa, a, c, tInc, UincAgg, Inc, cN, cS, aN, aS, ctd, atd, taxN, taxS, a_debt, a_debtN, a_debtS, IncN, IncS