def measurement(model, G1, impact, C):
    """
    Compute measurement equation
    Written based on NYFED-DSGE's Julia-language implementation.
    """
    
    endo = model.endog_states
    exo  = model.exog_shocks
    obs  = model.observables

    n_obs         = len(util.flatten_indices(obs))
    n_shocks_exo  = len(util.flatten_indices(exo))
    n_states      = len(util.flatten_indices(endo))

    ZZ = np.zeros([n_obs, n_states])
    DD = np.zeros(n_obs)
    EE = np.zeros([n_obs, n_obs])
    QQ = np.zeros([n_shocks_exo, n_shocks_exo])

    ## Output growth
    ZZ[obs['obs_gdp'], endo['y_t']]  = 1.0
    ZZ[obs['obs_gdp'], endo['y_t1']] = -1.0
    ZZ[obs['obs_gdp'], endo['z_t']]  = 1.0
    DD[obs['obs_gdp']]               = model.params['gam_Q'].value

    ## Inflation
    ZZ[obs['obs_inflation'], endo['pi_t']] = 4.0
    DD[obs['obs_inflation']]               = model.params['pi'].value

    ## FF rate
    ZZ[obs['obs_nominalrate'], endo['R_t']] = 4.0
    DD[obs['obs_nominalrate']]             = model.params['pi'].value + model.params['rA'].value \
                                             + 4.0 * model.params['gam_Q'].value

    ## Measurement error
    EE[obs['obs_gdp'], endo['y_t']]         = model.params['e_y'].value ** 2
    EE[obs['obs_inflation'], endo['pi_t']]  = model.params['e_pi'].value ** 2
    EE[obs['obs_nominalrate'], endo['R_t']] = model.params['e_R'].value ** 2

    ## Variance of innovations
    QQ[exo['z_sh'], exo['z_sh']]   = model.params['sig_z'].value ** 2
    QQ[exo['g_sh'], exo['g_sh']]   = model.params['sig_g'].value ** 2
    QQ[exo['rm_sh'], exo['rm_sh']] = model.params['sig_R'].value ** 2

    return ZZ, DD, QQ, EE
Exemple #2
0
def measurement(model, G1, impact, C, inverse_basis):
    """
    Compute measurement equation
    Written based on NYFED-DSGE's Julia-language implementation.
    """

    endo = model.endog_states
    exo = model.exog_shocks
    obs = model.observables

    n_obs = len(util.flatten_indices(obs))
    n_states = len(util.flatten_indices(endo))

    track_lag = model.settings['track_lag'].value
    freq = model.settings['state_simulation_freq'].value

    ZZ = np.zeros([n_obs, n_states])
    DD = np.zeros(n_obs)
    #EE = np.zeros([n_obs, n_obs])
    EE = np.diag([0.20 * 0.579923, 0.20 * 1.470832, 0.20 * 2.237937])
    QQ = np.eye(freq) * 1 / freq
    #QQ = np.eye(freq*exo) * 1/freq

    ZZ[obs['obs_gdp'], endo['output']] = 1.0
    ZZ[obs['obs_inflation'], endo['inflation']] = 4.0
    ZZ[obs['obs_nominalrate'], endo['monetary_policy']] = 4.0

    if track_lag:
        augmented_inverse_basis = np.zeros(
            [n_states, (freq + 1) * G1.shape[0]])
        augmented_inverse_basis[:, -1 - inverse_basis.shape[1] +
                                1:] = inverse_basis.toarray()
        ZZ = ZZ @ augmented_inverse_basis
    else:
        augmented_inverse_basis = np.zeros([n_states, freq * G1.shape[0]])
        augmented_inverse_basis[:, -1 - inverse_basis.shape[1] +
                                1:] = inverse_basis.toarray()

        ZZ = ZZ @ augmented_inverse_basis

    return ZZ, DD, QQ, EE
Exemple #3
0
def krylov_reduction(model, GAM0, GAM1, PSI, PI, C):

    if not 'F' in model.settings.keys():
        model.settings.update({
            'F':
            type(
                'setting', (object, ), {
                    'value': lambda x: x,
                    'description': 'Function applied during Krylov reduction'
                })
        })
    F = model.settings['F'].value

    # Grab Dimensions
    n_state_vars_unreduce = int(model.settings['n_state_vars_unreduce'].value)
    n_state_vars = int(model.settings['n_state_vars'].value)
    n_jump_vars = int(model.settings['n_jump_vars'].value)
    krylov_dim = int(model.settings['krylov_dim'].value)
    n_total = n_jump_vars + n_state_vars
    n_vars = len(util.flatten_indices(model.endog_states))
    n_state_vars -= n_state_vars_unreduce

    GAM1_full = GAM1.toarray()

    B_pv = solve(-GAM1_full[n_total:n_vars, n_total:n_vars],
                 GAM1_full[n_total:n_vars, :n_jump_vars])

    B_pg = solve(
        -GAM1_full[n_total:n_vars, n_total:n_vars],
        GAM1_full[n_total:n_vars, n_jump_vars:n_jump_vars + n_state_vars])
    B_pZ = solve(
        -GAM1_full[n_total:n_vars, n_total:n_vars],
        GAM1_full[n_total:n_vars, n_jump_vars + n_state_vars:n_jump_vars +
                  n_state_vars + n_state_vars_unreduce])
    B_gg = GAM1_full[n_jump_vars:n_jump_vars + n_state_vars,
                     n_jump_vars:n_jump_vars + n_state_vars]
    B_gv = GAM1_full[n_jump_vars:n_jump_vars + n_state_vars, :n_jump_vars]
    B_gp = GAM1_full[n_jump_vars:n_jump_vars + n_state_vars, n_total:n_vars]

    # Drop redundant equations
    obs = B_pg
    _, d0, V_g = svd(obs, full_matrices=False)
    aux = d0 / d0[0]
    n_Bpg = int(sum(aux > 10 * np.finfo(float).eps))
    V_g = V_g.conj().T
    V_g = V_g[:, :n_Bpg] * aux[:n_Bpg]

    # Compute Krylov subspace
    A = lambda x: 0 + B_gg.conj().T @ x + B_pg.conj().T @ (B_gp.conj().T @ x)
    V_g, _, _ = deflated_block_arnoldi(A, V_g, krylov_dim)
    n_state_vars_red = V_g.shape[1]

    # Build state space reduction transform
    reduced_basis = lil_matrix(
        np.zeros((n_jump_vars + n_state_vars_red, n_vars)))
    reduced_basis[:n_jump_vars, :n_jump_vars] = speye(n_jump_vars,
                                                      dtype=float,
                                                      format='csc')
    reduced_basis[n_jump_vars: n_jump_vars+n_state_vars_red, \
                  n_jump_vars: n_jump_vars+n_state_vars    ] = V_g.conj().T
    reduced_basis[n_jump_vars + n_state_vars_red:n_jump_vars + n_state_vars_red + n_state_vars_unreduce,\
                  n_jump_vars + n_state_vars    :n_jump_vars + n_state_vars     + n_state_vars_unreduce] \
            = np.eye(n_state_vars_unreduce)

    # Build inverse transform
    inv_reduced_basis = lil_matrix(
        np.zeros((n_vars, n_jump_vars + n_state_vars_red)))
    inv_reduced_basis[:n_jump_vars, :n_jump_vars] = speye(n_jump_vars,
                                                          dtype=float,
                                                          format='csc')
    inv_reduced_basis[n_jump_vars:n_jump_vars+n_state_vars,\
                      n_jump_vars:n_state_vars_red+n_jump_vars] = V_g
    inv_reduced_basis[n_total:n_vars, :n_jump_vars] = B_pv

    inv_reduced_basis[n_total:n_vars,
                      n_jump_vars:n_jump_vars + n_state_vars_red] = B_pg @ V_g
    inv_reduced_basis[n_total:n_vars,
                      n_jump_vars + n_state_vars_red:n_jump_vars +
                      n_state_vars_red + n_state_vars_unreduce] = B_pZ

    inv_reduced_basis[n_jump_vars+n_state_vars:n_total,\
                      n_jump_vars+n_state_vars_red:n_jump_vars+n_state_vars_red+n_state_vars_unreduce] \
        = speye(n_state_vars_unreduce, dtype=float, format='csc')

    model.settings.update({
        'n_state_vars_red':
        type(
            'setting', (object, ), {
                'value': n_state_vars_red + n_state_vars_unreduce,
                'description': 'Number of state variables after reduction'
            })
    })

    # Change basis
    GAM0_kry, GAM1_kry, PSI_kry, PI_kry, C_kry = \
        change_basis(reduced_basis, inv_reduced_basis, GAM0, GAM1, PSI, PI, C, ignore_GAM0 = True)

    return GAM0_kry, GAM1_kry, PSI_kry, PI_kry, C_kry, reduced_basis, inv_reduced_basis
Exemple #4
0
def eqcond(model):
    """
    Compute equilibirum of HANK model
    Written based on NYFED-DSGE's Julia-language implementation.
    """
    nstates = len(util.flatten_indices(model.endog_states))  # 406
    n_s_exp = len(util.flatten_indices(model.expected_shocks))  # 201
    n_s_exo = len(util.flatten_indices(model.exog_shocks))  # 1

    x = np.zeros(2 * nstates + n_s_exp + n_s_exo)

    # Read in parameters, settings
    niter_hours = model.settings['niter_hours'].value
    n_v = model.settings['n_jump_vars'].value
    n_g = model.settings['n_state_vars'].value
    ymarkov_combined = model.settings['ymarkov_combined'].value
    zz = model.settings['zz'].value
    a = model.settings['a'].value
    I, J = zz.shape
    amax = model.settings['amax'].value
    amin = model.settings['amin'].value
    aa = np.repeat(a.reshape(-1, 1), J, axis=1)
    A_switch = spkron(ymarkov_combined, speye(I, dtype=float, format='csc'))
    daf, dab, azdelta = aux.initialize_diff_grids(a, I, J)

    # Set up steady state parameters
    V_ss = model.steady_state['V_ss'].value
    g_ss = model.steady_state['g_ss'].value
    G_ss = model.steady_state['G_ss'].value
    w_ss = model.steady_state['w_ss'].value
    N_ss = model.steady_state['N_ss'].value
    C_ss = model.steady_state['C_ss'].value
    Y_ss = model.steady_state['Y_ss'].value
    B_ss = model.steady_state['B_ss'].value
    r_ss = model.steady_state['r_ss'].value
    rho_ss = model.steady_state['rho_ss'].value
    sig_MP = model.params['sig_MP'].value
    theta_MP = model.params['theta_MP'].value
    # sig_FP   = model.params['sig_FP'].value
    # theta_FP = model.params['theta_FP'].value
    # sig_PS   = model.params['sig_PS'].value
    # theta_PS = model.params['theta_PS'].value

    h_ss = model.steady_state['h_ss'].value.reshape(I, J, order='F')
    ceselast = model.params['ceselast'].value
    inflation_ss = model.steady_state['inflation_ss'].value
    maxhours = model.params['maxhours'].value
    govbcrule_fixnomB = model.params['govbcrule_fixnomB'].value
    priceadjust = model.params['priceadjust'].value
    taylor_inflation = model.params['taylor_inflation'].value
    taylor_outputgap = model.params['taylor_outputgap'].value
    meanlabeff = model.params['meanlabeff'].value

    # Necessary for construction of household problem functions
    labtax = model.params['labtax'].value
    coefrra = model.params['coefrra'].value
    frisch = model.params['frisch'].value
    labdisutil = model.params['labdisutil'].value

    TFP = 1.0

    def _get_residuals(x):
        #x = x.toarray().flatten()
        # Prepare steady state deviations
        V = (x[:n_v - 1] + V_ss).reshape(I, J, order='F')
        inflation = x[n_v - 1] + inflation_ss
        gg = x[n_v:n_v + n_g - 1] + g_ss[:-1]
        MP = x[n_v + n_g - 1]
        w = x[n_v + n_g] + w_ss
        hours = x[n_v + n_g + 1] + N_ss
        consumption = x[n_v + n_g + 2] + C_ss
        output = x[n_v + n_g + 3] + Y_ss
        assets = x[n_v + n_g + 4] + B_ss
        #government  = x[n_v + n_g + 5]       + G_ss

        V_dot = x[nstates:nstates + n_v - 1]
        inflation_dot = x[nstates + n_v - 1]
        g_dot = x[nstates + n_v:nstates + n_v + n_g - 1]
        mp_dot = x[nstates + n_g + n_v - 1]
        #fp_dot          = x[nstates + n_g + n_v + 5]
        #ps_dot          = x[nstates + n_g + n_v + 3]
        VEErrors = x[2 * nstates:2 * nstates + n_v - 1]
        inflation_error = x[2 * nstates + n_v - 1]
        mp_shock = x[2 * nstates + n_v]
        #fp_shock        = x[2*nstates + n_v + 1]
        #ps_shock        = x[2*nstates + n_v + 2]

        g_end = (1 - gg @ azdelta[:-1]) / azdelta[-1]
        g = np.append(gg, g_end)
        g[g < 1e-19] = 0.0

        #-----------------------------------------------------------------
        # Get equilibrium values, given steady state values
        normalized_wage = w / TFP
        profshare = (zz / meanlabeff) * ((1.0 - normalized_wage) * output)
        r_nominal = r_ss + taylor_inflation * inflation \
                    + taylor_outputgap * (np.log(output)-np.log(Y_ss)) + MP
        r = r_nominal - inflation
        lumptransfer    = labtax * w * hours - G_ss - \
                            (r_nominal - (1-govbcrule_fixnomB) * inflation) * assets

        #-----------------------------------------------------------------
        # Compute one iteration of the HJB
        ## Get flow utility, income, and labor hour functions
        util, income, labor = \
            aux.construct_household_problem_functions(V, w, coefrra, frisch, labtax, labdisutil)

        ## Initialize other variables, using V to ensure everything is a dual number
        Vaf = np.copy(V)
        Vab = np.copy(V)
        #h0 = np.array([h_ss[i, j] for i in range(I) for j in range(J)]).reshape(I, J)
        h0 = np.copy(h_ss)

        #-----------------------------------------------------------------
        # Construct Initial Difference Matrices
        #         hf = np.empty_like(V)
        #         hb = np.empty_like(V)

        Vaf[-1, :] = income(h_ss[-1, :], zz[-1, :], profshare[-1, :],
                            lumptransfer, r, amax)**(-coefrra)
        Vab[-1, :] = (V[-1, :] - V[-2, :]) / dab[-1]

        Vaf[0, :] = (V[1, :] - V[0, :]) / daf[0]
        Vab[0, :] = income(h_ss[0, :], zz[0, :], profshare[0, :], lumptransfer,
                           r, amin)**(-coefrra)

        Vaf[1:-1] = (V[2:, :] - V[1:-1, :]) / daf[0]
        Vab[1:-1] = (V[1:-1, :] - V[:-2, :]) / dab[0]

        # idx = ((i,j) for i in range(I) for j in range(J))
        # for t in idx:
        #     hf[t] = min(abs(labor(zz[t], Vaf[t])), maxhours)
        #     hb[t] = min(abs(labor(zz[t], Vab[t])), maxhours)

        hf = np.minimum(abs(labor(zz, Vaf)), maxhours)
        hb = np.minimum(abs(labor(zz, Vab)), maxhours)

        cf = Vaf**(-1 / coefrra)
        cb = Vab**(-1 / coefrra)

        #-----------------------------------------------------------------
        # Hours Iteration
        idx = ((i, j) for i in range(I) for j in range(J))
        for ih in range(niter_hours):
            for t in idx:
                if t[0] == I - 1:
                    cf[t] = income(hf[t], zz[t], profshare[t], lumptransfer, r,
                                   aa[t])
                    hf[t] = labor(zz[t], cf[t]**(-coefrra))
                    hf[t] = min(abs(hf[t]), maxhours)
                    if ih == niter_hours - 1:
                        Vaf[t] = cf[t]**(-coefrra)

                elif t[0] == 0:
                    cb[t] = income(hb[t], zz[t], profshare[t], lumptransfer, r,
                                   aa[t])
                    hb[t] = labor(zz[t], cb[t]**(-coefrra))
                    hb[t] = min(abs(hb[t]), maxhours)
                    if ih == niter_hours:
                        Vab[t] = cb[t]**(-coefrra)

            c0 = income(h0, zz, profshare, lumptransfer, r, aa)
            h0 = labor(zz, c0**(-coefrra))
            h0 = np.minimum(abs(h0.flatten()), maxhours).reshape(I, J)

        c0 = income(h0, zz, profshare, lumptransfer, r, aa)
        sf = income(hf, zz, profshare, lumptransfer, r, aa) - cf
        sb = income(hb, zz, profshare, lumptransfer, r, aa) - cb

        #-----------------------------------------------------------------
        # Upwind
        #T = sb[0,0].dtype

        Vf = (cf > 0) * (util(cf, hf) + sf * Vaf) + (cf <= 0) * (-1e12)
        Vb = (cb > 0) * (util(cb, hb) + sb * Vab) + (cb <= 0) * (-1e12)
        V0 = (c0 > 0) * util(c0, h0) + (c0 <= 0) * (-1e12)

        Iunique = (sb < 0) * (1 - (sf > 0)) + (1 - (sb < 0)) * (sf > 0)
        Iboth = (sb < 0) * (sf > 0)
        Ib = Iunique * (sb < 0) * (Vb > V0) + Iboth * (Vb == np.maximum(
            np.maximum(Vb, Vf), V0))
        If = Iunique * (sf > 0) * (Vf > V0) + Iboth * (Vf == np.maximum(
            np.maximum(Vb, Vf), V0))
        I0 = 1 - Ib - If

        h = hf * If + hb * Ib + h0 * I0
        c = cf * If + cb * Ib + c0 * I0
        s = sf * If + sb * Ib
        u = util(c, h)

        X = -Ib * sb / np.array([dab, dab]).reshape(I, J)
        Z = If * sf / np.array([daf, daf]).reshape(I, J)
        Y = -Z - X

        X[0, :] = 0.
        Z[I - 1, :] = 0.

        A = spdiag([
            X.reshape(I * J, order='F')[1:],
            Y.reshape(I * J, order='F'),
            Z.reshape(I * J, order='F')[:I * J - 1]
        ],
                   offsets=[-1, 0, 1],
                   shape=(I * J, I * J),
                   format='csc') + A_switch

        #-----------------------------------------------------------------
        # Collect/calculate Residuals
        hjb_residual = u.flatten(order='F') + A * V.flatten(order='F') \
                        + V_dot + VEErrors  - rho_ss * V.flatten(order='F')

        pc_residual  = -((r - 0) * inflation - (ceselast / priceadjust * \
                                                (w / TFP - (ceselast-1) / ceselast) + \
                                                inflation_dot - inflation_error))

        g_azdelta = g.flatten() * azdelta.flatten()
        g_intermediate = spdiag(1 / azdelta) * A.T @ g_azdelta
        g_residual = g_dot - g_intermediate[:-1]

        mp_residual = mp_dot - (-theta_MP * MP + sig_MP * mp_shock)

        realsav = sum(
            aa.flatten(order='F') * g.flatten(order='F') *
            azdelta.flatten(order='F'))
        realsav_dot = sum(
            s.flatten(order='F') * g.flatten(order='F') *
            azdelta.flatten(order='F'))
        bondmarket_residual = realsav_dot / realsav + govbcrule_fixnomB * inflation

        labmarket_residual = sum(zz.flatten(order='F') * h.flatten(order='F') \
                                 * g.flatten(order='F') * azdelta.flatten(order='F')) - hours

        consumption_residual = sum(c.flatten(order='F') * g.flatten(order='F') \
                                   * azdelta.flatten(order='F')) - consumption

        output_residual = TFP * hours - output
        #output_residual = TFP * hours - (-theta_PS * output + sig_PS * ps_shock)

        assets_residual = assets - realsav

        #government_residual = fp_dot - (-theta_FP * government + sig_FP * fp_shock)

        # Return equilibrium conditions
        return np.hstack(
            (hjb_residual, pc_residual, g_residual, mp_residual,
             bondmarket_residual, labmarket_residual, consumption_residual,
             output_residual, assets_residual))
        # return np.hstack((hjb_residual, pc_residual, g_residual,
        #                  mp_residual,
        #                  bondmarket_residual, labmarket_residual, consumption_residual,
        #                  output_residual, assets_residual, government_residual))

    derivs = jacob_mat(_get_residuals, x, nstates, h=1e-10)

    GAM1 = -derivs[:, :nstates]
    GAM0 = derivs[:, nstates:2 * nstates]
    PI = -derivs[:, 2 * nstates:2 * nstates + n_s_exp]
    PSI = -derivs[:, 2 * nstates + n_s_exp:2 * nstates + n_s_exp + n_s_exo]
    C = np.zeros(nstates)

    return GAM0, GAM1, PSI, PI, C
def eqcond(model):
    """
    Compute equilibirum of RANK model
    Written based on NYFED-DSGE's Julia-language implementation.
    """

    endo = model.endog_states
    exo  = model.exog_shocks
    ex   = model.expected_shocks
    eq   = model.equilibrium_conditions

    n_states      = len(util.flatten_indices(model.endog_states))
    n_shocks_exog = len(util.flatten_indices(model.exog_shocks))
    n_shocks_exp  = len(util.flatten_indices(model.expected_shocks))

    GAM0 = np.zeros([n_states, n_states])
    GAM1 = np.zeros([n_states, n_states])
    C    = np.zeros(n_states)
    PSI  = np.zeros([n_states, n_shocks_exog])
    PI   = np.zeros([n_states, n_shocks_exp])

    #--- Endogenous States ---------------------------------------------------
    # 1. Consumption Euler Equation
    GAM0[eq['eq_euler'], endo['y_t']]    = 1.0
    GAM0[eq['eq_euler'], endo['R_t']]    = 1/model.params['tau'].value
    GAM0[eq['eq_euler'], endo['g_t']]    = -(1-model.params['rho_g'].value)
    GAM0[eq['eq_euler'], endo['z_t']]    = -model.params['rho_z'].value/model.params['tau'].value
    GAM0[eq['eq_euler'], endo['Ey_t1']]  = -1.0
    GAM0[eq['eq_euler'], endo['Epi_t1']] = -1/model.params['tau'].value

    # 2. NK Phillips Curve
    GAM0[eq['eq_phillips'], endo['y_t']]    = -model.params['kappa'].value
    GAM0[eq['eq_phillips'], endo['pi_t']]   = 1.0
    GAM0[eq['eq_phillips'], endo['g_t']]    = model.params['kappa'].value
    GAM0[eq['eq_phillips'], endo['Epi_t1']] = -1/(1+model.params['rA'].value/400)

    # 3. Monetary Policy Rule
    GAM0[eq['eq_mp'], endo['y_t']]   = -(1-model.params['rho_R'].value) * model.params['psi_2'].value
    GAM0[eq['eq_mp'], endo['pi_t']]  = -(1-model.params['rho_R'].value) * model.params['psi_1'].value
    GAM0[eq['eq_mp'], endo['R_t']]   = 1.0
    GAM0[eq['eq_mp'], endo['g_t']]   =  (1-model.params['rho_R'].value) * model.params['psi_2'].value
    GAM1[eq['eq_mp'], endo['R_t']]   = model.params['rho_R'].value
    PSI[eq['eq_mp'],  exo['rm_sh']]  = 1.0

    # 4. Output lag
    GAM0[eq['eq_y_t1'], endo['y_t1']] = 1.0
    GAM1[eq['eq_y_t1'], endo['y_t']]  = 1.0

    # 5. Government spending
    GAM0[eq['eq_g'], endo['g_t']] = 1.0
    GAM1[eq['eq_g'], endo['g_t']] = model.params['rho_g'].value
    PSI[eq['eq_g'], exo['g_sh']]  = 1.0

    # 6. Technology
    GAM0[eq['eq_z'], endo['z_t']] = 1.0
    GAM1[eq['eq_z'], endo['z_t']] = model.params['rho_z'].value
    PSI[eq['eq_z'], exo['z_sh']]  = 1.0

    # 7. Expected output
    GAM0[eq['eq_Ey'], endo['y_t']]   = 1.0
    GAM1[eq['eq_Ey'], endo['Ey_t1']] = 1.0
    PI[eq['eq_Ey'], ex['Ey_sh']]     = 1.0

    # 8. Expected inflation
    GAM0[eq['eq_Epi'], endo['pi_t']]   = 1.0
    GAM1[eq['eq_Epi'], endo['Epi_t1']] = 1.0
    PI[eq['eq_Epi'], ex['Epi_sh']]     = 1.0

    return GAM0, GAM1, C, PSI, PI