# Computation of the steady state and dimensionality reduction

Most of the code of this section is in the folder `4_HetAgentsFcns`

, except for `prepare_linearization()`

which is in `5_LinearizationFunctions`

.

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, bonds $m$ and illiquid 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 `HANKEstim.find_steadystate()`

and `HANKEstim.prepare_linearization()`

:

## Overview of `find_steadystate`

`HANKEstim.find_steadystate`

— Function`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`

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:

- instantiate the parameter
`struct`

`NumericalParameters`

as`n_par`

(see Parameters). Within the struct, we set the number of income states [`ny`

] and use the`HANKEstim.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. - find equilibrium capital stock (by finding a root of
`HANKEstim.Kdiff()`

), where the supply of capital by households is calculated in`HANKEstim.Ksupply()`

, which uses the Endogenous Grid Method (see`HANKEstim.EGM_policyupdate`

) to iteratively obtain optimal policies and marginal value functions

## Overview of `prepare_linearization`

`HANKEstim.prepare_linearization`

— Function`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`

:`struct`

s 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`HANKEstim.myinterpolate3()`

`n_par::NumericalParameters`

,`m_par::ModelParameters`

`CDF_SS`

,`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()`

We first calculate other equilibrium quantities and produce distributional summary statistics (`HANKEstim.distrSummaries()`

). Next, we reduce the dimensionality:

- compute coefficients of the Chebyshev polynomials that serve as basis functions for $V_m$ and $V_k$, using the Discrete Cosine Transformation (Julia-package
`FFTW`

), and retain those that explain the most of its variance, up to`100*(1-n_par.reduc)`

percent. Save their indices in`compressionIndexes`

- 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 `@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 `HANKEstim.jl`

).

While the steady state marginal value functions have full dimensionality, in the vectors that collect *deviations* from steady state (in `HANKEstim.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 `@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 `HANKEstim.SGU_estim()`

).

Be sure that you edit `prepare_linearization()`

and not `prepare_linearization_generated()`

which will be overwritten by the model parser based on `prepare_linearization()`

.

## 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.

`HANKEstim.ModelParameters`

— TypeModelParameters()

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))
```

The numerical parameters contain the grid (and the meshes) on which the stationary equilibrium is solved, discretization results of `HANKEstim.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`

.

`HANKEstim.NumericalParameters`

— TypeNumericalParameters()

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)`

## Find stationary equilibrium: functions

`HANKEstim.Tauchen`

— Function`Tauchen(rho,N,sigma,mue)`

Generate a discrete approximation to an AR(1) process, following Tauchen (1987).

Uses importance sampling: each bin has probability 1/N to realize

**Arguments**

`rho`

: autocorrelation coefficient`N`

: number of gridpoints`sigma`

: long-run variance`mue`

: mean of the AR(1) process

**Returns**

`grid_vec`

: state vector grid`P`

: transition matrix`bounds`

: bin bounds

`HANKEstim.Kdiff`

— Function`Kdiff(K_guess,n_par,m_par)`

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 `employment(K,A,m_par)`

, `interest(K,A,N,m_par)`

, `wage(K,A,N,m_par)`

, `output(K,TFP,N,m_par)`

, and `Ksupply()`

.

**Arguments**

`K_guess::Float64`

: capital stock guess`n_par::NumericalParameters`

,`m_par::ModelParameters`

`HANKEstim.Ksupply`

— Function`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

`HANKEstim.EGM_policyupdate`

— Function`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

`HANKEstim.distrSummaries`

— Function`distrSummaries(distr,c_a_star,c_n_star,n_par,inc,incgross,m_par)`

Compute distributional summary statistics, e.g. Gini indexes, top-10% income and wealth shares, and 10%, 50%, and 90%-consumption quantiles.

**Arguments**

`distr`

: joint distribution over bonds, capital and income $(m \times k \times y)$`c_a_star`

,`c_n_star`

: optimal consumption policies with [`a`

] or without [`n`

] capital adjustment`n_par::NumericalParameters`

,`m_par::ModelParameters`

`inc`

: vector of (on grid-)incomes, consisting of labor income (scaled by $\frac{\gamma-\tau^P}{1+\gamma}$, plus labor union-profits), rental income, liquid asset income, capital liquidation income, labor income (scaled by $\frac{1-\tau^P}{1+\gamma}$, without labor union-profits), and labor income (without scaling or labor union-profits)`incgross`

: vector of (on grid-)*pre-tax*incomes, consisting of labor income (without scaling, plus labor union-profits), rental income, liquid asset income, capital liquidation income, labor income (without scaling or labor union-profits)

## Collect variables: macros

`HANKEstim.@writeXSS`

— Macro`@writeXSS()`

Write all single steady state variables into vectors XSS / XSSaggr.

**Requires**

(module) globals `state_names`

, `control_names`

, `aggr_names`

`HANKEstim.@make_fn`

— Macro`@make_fn(fn_name)`

Create function `fn_name`

that returns an instance of `struct`

`IndexStruct`

(created by `@make_struct`

), mapping states and controls to indexes inferred from numerical parameters and compression indexes.

**Requires**

(module) global `state_names`

, `control_names`

`HANKEstim.@make_fnaggr`

— Macro`@make_fnaggr(fn_name)`

Create function `fn_name`

that returns an instance of `struct`

`IndexStructAggr`

(created by `@make_struct_aggr`

), mapping aggregate states and controls to values `1`

to `length(aggr_names)`

(both steady state and deviation from it).

**Requires**

(module) global `aggr_names`

`HANKEstim.@make_struct`

— Macro`@make_struct(struct_name)`

Make `struct`

`struct_name`

with two fields for every variable name in `s_names`

(state variables) and `c_names`

(control variables), together with fields for distribution-states and marginal value function-controls.

**Requires**

(module) globals `state_names`

, `control_names`

`HANKEstim.@make_struct_aggr`

— Macro`@make_struct_aggr(struct_name)`

Make `struct`

`struct_name`

with two fields for every variable name in `aggr_names`

(for steady state value and for deviation from it).

**Requires**

(module) global `aggr_names`

- BBLFor details, see the paper Shocks, Frictions, and Inequality in US Business Cycles
- BLFor details, see the paper Solving heterogeneous agent models in discrete time with many idiosyncratic states by perturbation methods