Computation of the steady state and dimensionality reduction

Note

Most of the code of this section is in the submodule SteadyState, except for prepare_linearization() which is generated by the preprocessor and can be found in Preprocessor/generated_fcns/. The preprocessor uses a template stored in Preprocessor/template_fcns/.

The model features uninsured income shocks $y$ (by assumption, all workers supply the same efficiency units of labor [BBL], so idiosyncratic productivity shocks translate to income shocks) and two assets, liquid assets (bonds) $m$ and illiquid assets (capital) $k$. Entrepreneurs (last income-state) receive no labor income, but firm profits, while workers additionally receive labor union profits.

The steady state equilibrium contains marginal value functions $V_m$ and $V_k$ on a three-dimensional grid $(m \times k \times y)$ and the ergodic joint distribution over these idiosyncratic states. We do dimensionality reduction [BL] by applying the Discrete Cosine Transformation to the marginal value functions and approximating the joint distribution with a copula and state-dependent marginals.

The main functions are call_find_steadystate() and call_prepare_linearization():

compute_steadystate

Combines steady state computation and preparation of linearization in one function call. It has the same returns as call_prepare_linearization.

call_find_steadystate

BASEforHANK.SteadyState.find_steadystateFunction
find_steadystate(m_par)

Find the stationary equilibrium capital stock.

Returns

  • KSS: steady-state capital stock
  • VmSS, VkSS: marginal value functions
  • distrSS::Array{Float64,3}: steady-state distribution of idiosyncratic states, computed by Ksupply()
  • n_par::NumericalParameters,m_par::ModelParameters
source

The function takes the parameter struct ModelParameters as input m_par (see Parameters).

To find the stationary equilibrium, we proceed in roughly the following steps:

  1. instantiate the parameter struct NumericalParameters as n_par (see Parameters). Within the struct, we set the number of income states [ny] and use the BASEforHANK.Tools.Tauchen() method to obtain a grid and a transition matrix of income, given the autocorrelation of the income process [m_par.ρ_h]. Then, include entrepreneurial state.
  2. find equilibrium capital stock (by finding a root of BASEforHANK.SteadyState.Kdiff()), where the supply of capital by households is calculated in BASEforHANK.SteadyState.Ksupply(), which uses the Endogenous Grid Method (see BASEforHANK.SteadyState.EGM_policyupdate()) to iteratively obtain optimal policies and marginal value functions. Root finding is performed using Brent's method where the customized algorithm generates initial guesses for value functions and distributions based on previous iterations in the root finding. The supply of capital by households is computed based on the eigenvector associated with the unit eigenvalue of the transition matrix that comes out of the households' policies.

call_prepare_linearization

BASEforHANK.PerturbationSolution.prepare_linearizationFunction
prepare_linearization(KSS, VmSS, VkSS, distrSS, n_par, m_par)

Compute a number of equilibrium objects needed for linearization.

Arguments

  • KSS: steady-state capital stock
  • VmSS, VkSS: marginal value functions
  • distrSS::Array{Float64,3}: steady-state distribution of idiosyncratic states, computed by Ksupply()
  • n_par::NumericalParameters,m_par::ModelParameters

Returns

  • XSS::Array{Float64,1}, XSSaggr::Array{Float64,1}: steady state vectors produced by @writeXSS()
  • indexes, indexes_aggr: structs for accessing XSS,XSSaggr by variable names, produced by @make_fn(), @make_fnaggr()
  • compressionIndexes::Array{Array{Int,1},1}: indexes for compressed marginal value functions ($V_m$ and $V_k$)
  • Copula(x,y,z): function that maps marginals x,y,z to approximated joint distribution, produced by myinterpolate3()
  • n_par::NumericalParameters,m_par::ModelParameters
  • CDFSS, CDF_m, CDF_k, CDF_y: cumulative distribution functions (joint and marginals)
  • distrSS::Array{Float64,3}: steady state distribution of idiosyncratic states, computed by Ksupply()
source

We first calculate other equilibrium quantities and produce distributional summary statistics (BASEforHANK.Tools.distrSummaries()). Next, we reduce the dimensionality:

  1. Find the sparse representation of fluctuations of $V_m$ and $V_k$ around the steady state. For this purpose, calculate the derivatives of $V_m$ and $V_k$ with respect to all prices that enter the household problem. Then transform these derivatives using the Discrete Cosine Transformation (Julia-package FFTW) into polynomial coefficients. Calculate the average absolute value of those coefficients and retain those that explain a large share of the variance of coefficients (up to 100*(1-n_par.reduc_marginal_value) percent). Add, in the same way, polynomial coefficients that explain $V_m$ and $V_k$ themselves. The quality of the latter approximation is controlled by n_par.reduc_value. The corresponding indices are saved in compressionIndexes. This whole step is being done in first_stage_reduction().
  2. Prepare a node mesh on which the time-varying linear interpolant of the copula is defined. The grid in each $m$, $k$, and $y$ dimension is selected such that each resulting bin holds approximately the same share of the respective aggregate variable.

Lastly, we collect the steady-state values of all model variables in the vector XSS (see BASEforHANK.Parsing.@writeXSS). The state variables consist of the marginal distributions over $m$, $k$ and $y$ and the aggregate state variables (collected in state_names). The control variables consist of the steady state marginal value functions (over the full grid) and the aggregate control variables (collected in control_names; these vectors are defined in the main script BASEforHANK.jl).

While the steady-state marginal value functions have full dimensionality, in the vectors that collect deviations from steady state (in BASEforHANK.PerturbationSolution.Fsys(), those are X and XPrime) only the coefficients of the most important Chebyshev polynomials are saved. Additionally, the deviations of the marginal distributions are saved with one entry short of the grid size, since the marginals are restricted to sum up to 1. We manage this by creating the struct indexes (using BASEforHANK.Parsing.@make_fn), that has two fields for each variable: steady state value and deviation.

We also construct the vector XSSaggr and the struct indexes_aggr, which are similar to the above but only store (and manage) aggregate variables. This is useful for differentiating only with respect to aggregate variables in the estimation part (see BASEforHANK.PerturbationSolution.LinearSolution_estim()).

Warning

If you change the household decision model and hence need to customize the steady state solution, you will need to adjust the template Preprocessor/template_fcns/prepare_linearization.jl and not Preprocessor/generated_fcns/prepare_linearization_generated.jl which will be overwritten by the model parser based on Preprocessor/template_fcns/prepare_linearization.jl. Note that the "definition" of the function (right click in VSCode) in the module is the generated one.

Parameters

The model parameters for the steady state have to be calibrated. We set them in the struct ModelParameters. It also contains all other parameters that are estimated, including the stochastic process-parameters for the aggregate shocks.

BASEforHANK.Parsing.ModelParametersType

ModelParameters()

Collect all model parameters with calibrated values / priors for estimation in a struct.

Uses packages Parameters, FieldMetadata, Flatten. Boolean value denotes whether parameter is estimated.

Example

julia> m_par = ModelParameters();
julia> # Obtain vector of prior distributions of parameters that are estimated.
julia> priors = collect(metaflatten(m_par, prior))
source

The numerical parameters contain the grid (and the meshes) on which the stationary equilibrium is solved, discretization results of call_find_steadystate() like the transition matrix of income and the joint distribution, and other parameters that determine the numerical approximation or solution technique, like reduc or sol_algo.

BASEforHANK.Parsing.NumericalParametersType

NumericalParameters()

Collect parameters for the numerical solution of the model in a struct.

Use package Parameters to provide initial values.

Example

julia> n_par = NumericalParameters(mmin = -6.6, mmax = 1000)
source

In particular, ny, nk, and nm control the resolution for the income, illiquid asset, and liquid asset grid. The resolution of the copula used in the linearization does not need to coincide with that grid and is controled by ny_copula, nk_copula, and nm_copula, respectively. Note, however, that the copula resolution should not exceed the actual grid size.

Find stationary equilibrium: functions

BASEforHANK.SteadyState.KdiffFunction
Kdiff(K_guess, 
n_par, 
m_par, 
initial = true, 
Vm_guess = zeros(1, 1, 1), 
Vk_guess = zeros(1, 1, 1), 
distr_guess = zeros(1, 1, 1))

Calculate the difference between the capital stock that is assumed and the capital stock that prevails under that guessed capital stock's implied prices when households face idiosyncratic income risk (Aiyagari model).

Requires global functions from the IncomesETC module incomes() and Ksupply().

Arguments

  • K_guess::Float64: capital stock guess
  • n_par::NumericalParameters,
  • m_par::ModelParameters
  • 5 optional arguments:
    • initial::Bool = true: whether to use initial guess for marginal values
    • Vm_guess::AbstractArray = zeros(1, 1, 1): initial guess for marginal value of liquid assets
    • Vk_guess::AbstractArray = zeros(1, 1, 1): initial guess for marginal value of illiquid assets
    • distr_guess::AbstractArray = zeros(1, 1, 1): initial guess for stationary distribution
source
BASEforHANK.SteadyState.KsupplyFunction
Ksupply(RB_guess,R_guess,w_guess,profit_guess,n_par,m_par)

Calculate the aggregate savings when households face idiosyncratic income risk.

Idiosyncratic state is tuple $(m,k,y)$, where $m$: liquid assets, $k$: illiquid assets, $y$: labor income

Arguments

  • R_guess: real interest rate illiquid assets
  • RB_guess: nominal rate on liquid assets
  • w_guess: wages
  • profit_guess: profits
  • n_par::NumericalParameters
  • m_par::ModelParameters

Returns

  • K,B: aggregate saving in illiquid (K) and liquid (B) assets
  • TransitionMat,TransitionMat_a,TransitionMat_n: sparse transition matrices (average, with [a] or without [n] adjustment of illiquid asset)
  • distr: ergodic steady state of TransitionMat
  • c_a_star,m_a_star,k_a_star,c_n_star,m_n_star: optimal policies for consumption [c], liquid [m] and illiquid [k] asset, with [a] or without [n] adjustment of illiquid asset
  • V_m,V_k: marginal value functions
source
BASEforHANK.SteadyState.EGM_policyupdateFunction
EGM_policyupdate(EVm,EVk,Qminus,πminus,RBminus,Tshock,inc,n_par,m_par,warnme)

Find optimal policies, given marginal continuation values EVm, EVk, today's prices [Qminus, πminus,RBminus], and income [inc], using the Endogenous Grid Method.

Optimal policies are defined on the fixed grid, but optimal asset choices (m and k) are off-grid values.

Returns

  • c_a_star,m_a_star,k_a_star,c_n_star,m_n_star: optimal (on-grid) policies for consumption [c], liquid [m] and illiquid [k] asset, with [a] or without [n] adjustment of illiquid asset
source