Linear perturbation around steady state
The main functions of this section are in the Submodule PerturbationSolution
.
The model is linearized with respect to aggregate variables. For this, we write the equilibrium conditions in the form of $F(X,X')=0$, where $X$ and $X'$ are (expected) deviations from steady state in two successive periods. Applying the total differential yields $A*X' = - B*X$, where $A$,$B$ are the first derivatives of $F$ with respect to $X'$,$X$. In the standard setting, we use the generalized Schur decomposition [Klein] to transform this equation into a linearized observation equation $d = gx*k$ and a linearized state transition equation $k' = hx*k$, where $k$ is a vector of the state variables and $d$ is a vector of the control variables, $X = \begin{bmatrix} k & d \end{bmatrix}'$.
In our code, $F$ is implemented as BASEforHANK.PerturbationSolution.Fsys()
, while differentiating and solving for $gx$ and $hx$ is done in BASEforHANK.PerturbationSolution.LinearSolution()
, called by linearize_full_model()
returns the results as a struct
LinearResults
:
linearize_full_model()
BASEforHANK.linearize_full_model
— Functionlinearize_full_model()
Linearize the full model (i.e. including idiosyncratic states and controls) around the steady state, and solves using LinearSolution()
.
Returns
struct
LinearResults
, containing
A::Array{Float64,2}
,B::Array{Float64,2}
: first derivatives ofPerturbationSolution.Fsys()
with respect to argumentsX
[B
] andXPrime
[A
]State2Control::Array{Float64,2}
: observation equationLOMstate::Array{Float64,2}
: state transition equation
BASEforHANK.PerturbationSolution.LinearSolution
— FunctionLinearSolution(sr, m_par, A, B; estim)
Calculate the linearized solution to the non-linear difference equations defined by function Fsys()
, using Schmitt-Grohé & Uribe (JEDC 2004) style linearization (apply the implicit function theorem to obtain linear observation and state transition equations).
The Jacobian is calculated using the package ForwardDiff
Arguments
sr
: steady-state structure (variable values, indexes, numerical parameters, ...)A
,B
: derivative ofFsys()
with respect to argumentsX
[B
] andXPrime
[A
]m_par
: model parameters
Returns
gx
,hx
: observation equations [gx
] and state transition equations [hx
]alarm_LinearSolution
,nk
:alarm_LinearSolution=true
when solving algorithm fails,nk
number of predetermined variablesA
,B
: first derivatives ofFsys()
with respect to argumentsX
[B
] andXPrime
[A
]
The function linearize_full_model()
calls LinearSolution
and stores the results in a LinearResults
struct
.
LinearSolution()
The LinearSolution
function executes the following steps:
generate devices to retrieve distribution and marginal value functions from compressed states/controls (
Γ
andDC
,IDC
)calculate the first derivative of
BASEforHANK.PerturbationSolution.Fsys()
with respect toX
andXPrime
. We use automatic differentiation (implemented in Julia by the packageForwardDiff
). Partial derivatives are calculated using theForwardDiff.jacobian()
function. We exploit that some partial derivatives have known values (contemporaneous marginal value functions and the future marginal distributions) and set them directly instead of calculating them [BL].compute linear observation and state transition equations using the
BASEforHANK.PerturbationSolution.SolveDiffEq()
function
SolveDiffEq()
BASEforHANK.PerturbationSolution.SolveDiffEq
— FunctionSolveDiffEq(A, B, n_par; estim)
Calculate the solution to the linearized difference equations defined as P'BP xt = P'AP x{t+1}, where P
is the (ntotal x r) semi-unitary model reduction matrix n_par.PRightAll
of potentially reduced rank r.
Arguments
A
,B
: matrices with first derivativesn_par::NumericalParameters
:n_par.sol_algo
determines the solution algorithm, options are:litx
: Linear time iteration (implementation follows Reiter)schur
: Klein's algorithm (preferable if number of controls is small)
Returns
gx
,hx
: observation equations [gx
] and state transition equations [hx
]alarm_LinearSolution
,nk
:alarm_LinearSolution=true
when solving algorithm fails,nk
number of predetermined variables
- apply the model reduction by pre- and post-multiplying the reduction matrix $\mathcal{P}$ to the Jacobians
A
andB
that are inputs toBASEforHANK.PerturbationSolution.SolveDiffEq()
. $\mathcal{P}$ is calculated inmodel_reduction()
and stored inn_par.PRightAll
. - compute linear observation and state transition equations. The solution algorithm is set in
n_par.sol_algo
, with the options:schur
(mentioned above) and:litx
[lit]. The results are matrices that map contemporaneous states to controls [gx
], or contemporaneous states to future states [hx
]
Fsys()
BASEforHANK.PerturbationSolution.Fsys
— FunctionFsys(X, XPrime, XSS, m_par, n_par, indexes, Γ, compressionIndexes, DC, IDC, DCD, IDCD)
Equilibrium error function: returns deviations from equilibrium around steady state.
Split computation into Aggregate Part, handled by Fsys_agg()
, and Heterogeneous Agent Part.
Arguments
X
,XPrime
: deviations from steady state in periods t [X
] and t+1 [XPrime
]XSS
: states and controls in steady stateΓ
,DC
,IDC
,DCD
,IDCD
: transformation matrices to retrieve marginal distributions [Γ
], marginal value functions [DC
,IDC
], and the (linear) interpolant of the copula [DCD
,IDCD
] from deviationsindexes
,compressionIndexes
: accessXSS
by variable names (DCT coefficients of compressed $V_m$ and $V_k$ in case ofcompressionIndexes
)
Example
julia> # Solve for steady state, construct Γ,DC,IDC as in LinearSolution()
julia> Fsys(zeros(ntotal),zeros(ntotal),XSS,m_par,n_par,indexes,Γ,compressionIndexes,DC,IDC)
*ntotal*-element Array{Float64,1}:
0.0
0.0
...
0.0
The function BASEforHANK.PerturbationSolution.Fsys()
proceeds in the following way:
- set up vector
F
, that contains the errors to all equilibrium conditions. There are as many conditions as deviations from steady state (length ofX
,XPrime
), and conditions are indexed with respective model variable inIndexStruct
indexes
- generate locally all aggregate variables (for both periods) using
BASEforHANK.Parsing.@generate_equations
- construct the full-grid marginal distributions, marginal value functions, and the copula from the steady-state values and the (compressed) deviations (for the copula, the selection of DCT coefficients that can be perturbed ensures that also the perturbed function is a copula)
- write all equilibrium condition-errors with respect to aggregate variables to
F
, usingBASEforHANK.PerturbationSolution.Fsys_agg()
- compute optimal policies with
BASEforHANK.SteadyState.EGM_policyupdate()
, given future marginal value functions, prices, and individual incomes. Infer present marginal value functions from them (envelope theorem) and set the difference to assumed present marginal value functions (in terms of their compressed deviation from steady state) as equilibrium condition-errors (backward iteration of the value function) - compute future marginal distributions and the copula (on the copula grid) from previous distribution and optimal asset policies. Interpolate when necessary. Set difference to assumed future marginal distributions and copula values on the copula nodes as equilibrium condition-errors (forward iteration of the distribution)
- compute distribution summary statistics with
BASEforHANK.Tools.distrSummaries()
and write equilibrium conditions with their respective (control) variables - return
F
Note that the copula is treated as the sum of two interpolants. An interpolant based on the steady-state distribution using the full steady-state marginals as a grid and a "deviations"-function that is defined on the copula grid generated in prepare_linearization()
. The actual interpolation is carried out with BASEforHANK.Tools.myinterpolate3()
. Default setting is trilinear interpolation, the code also allows for 3d-Akima interpolation.
model_reduction()
BASEforHANK.PerturbationSolution.model_reduction
— Functionmodel_reduction()
Produce Model Reduction based on Variance Covariance Matrix of States and Controls.
Returns/ Updates
struct
SteadyResults
, containing returns of find_steadystate()
The function model_reduction()
derives the approximate factor representation from a first solution of the heterogeneous agent model.[BBL] It then stores the matrices that allow to map the factors to the full set of state and control variables. For deriving the factor representation, the function calculates the long run variance-covariance matrix of all states of the model (given its first-stage reduction).
update_model()
BASEforHANK.PerturbationSolution.update_model
— Functionupdate_model()
Updates the linearized model (around the steady state, after parameter changes in the aggregate model) and solves, using LinearSolution_estim()
. WARNING: The function is not threadsafe in the sense that calling it will alter the input(!) lr.A/B across threads, if lr is not local to the thread.
Returns
struct
LinearResults
, containing
A::Array{Float64,2}
,B::Array{Float64,2}
: first derivatives ofFsys()
with respect to argumentsX
[B
] andXPrime
[A
]State2Control::Array{Float64,2}
: observation equationLOMstate::Array{Float64,2}
: state transition equation
BASEforHANK.PerturbationSolution.Fsys_agg
— FunctionFsys_agg(X, XPrime, XSS, distrSS, m_par, n_par, indexes)
Return deviations from aggregate equilibrium conditions.
indexes
can be both IndexStruct
or IndexStructAggr
; in the latter case (which is how function is called by LinearSolution_estim()
), variable-vectors X
,XPrime
, and XSS
only contain the aggregate variables of the model.
The function update_model()
solves the aggregate model without updating the derivatives of the household/idiosyncratic part. For this purpose the derivatives of BASEforHANK.PerturbationSolution.Fsys_agg()
are calculated instead of Fsys()
. This substantially speeds up the solution after a parameter change that only affects aggregates.[BBL] In particular, if the model is reduced to its approximate factor representation (see above), this generates significant speed gains.
- KleinSee the paper Using the generalized Schur form to solve a multivariate linear rational expectations model by Paul Klein (JEDC 2000)
- BLContemporaneous marginal value functions are irrelevant for optimal decisions, so its effect on other model variables is 0. Due to a rich enough set of prices, the future distribution directly only affects the Fokker-Planck equation. For details, see the paper Solving heterogeneous agent models in discrete time with many idiosyncratic states by perturbation methods, Quantitative Economics, Vol.11(4), November 2020, p. 1253-1288.
- BBLFor details, see the paper Shocks, Frictions, and Inequality in US Business Cycles, American Economic Review, forthcoming.
- litInvoking the Implicit Function Theorem, there exist functions $g$ and $h$ such that $F\left(\begin{pmatrix} k \\ g(k) \end{pmatrix},\begin{pmatrix} h(k) \\ g(h(k)) \end{pmatrix}\right)=0$. Totally differentiating by $k$ yields $B \begin{pmatrix}\mathbb{I}\\ Dg \end{pmatrix}+A \begin{pmatrix}\mathbb{I}\\ Dg \end{pmatrix} Dh = 0$. The
:lit
-algorithm solves this equation for $Dg$ and $Dh$ iteratively.