# Solving the Model

## The `gensys`

routine

The DSGE model is written down in its canonical representation:

where $\Gamma_0$, $\Gamma_1$, $C$, $\Psi$, and $\Pi$ are matrices of coefficients for $s_t$ (states at time $t$), $s_{t-1}$ (lagged states), $\epsilon_t$ (exogenous shocks) and $\eta_t$ (expectational shocks).

DSGE.jl solves the model to obtain its state-space form:

using the `gensys`

routine of Chris Sims, introduced in this paper. This algorithm can be easily extended to (exogenous) regime switching. For each regime $i$, define the canonical matrices $\Gamma_{0, i}$, $\Gamma_{1, i}$, $C_i$, $\Psi_i$, and $\Pi_i$. Calling `gensys`

on each regime and constructing the relevant easurement matrix yields the matrices $T_i$, $R_i$, $C_i$, $Q_i$, $Z_i$, $D_i$, and $E_i$, which define the state-space form of a DSGE with multiple regimes.

We provide a standalone native Julia implementation of the routine (`gensys`

) as well as a wrapper for `AbstractDSGEModel`

subtypes (`solve`

). When the Gensys.jl package becomes ready for use, we intend to deprecate our `gensys`

code and substitute the `gensysdt`

method for our code.

## Regime-Switching

We allow solving the model with regime-switching in two cases.

- Exogenous and unanticipated regimes
- Alternative policies (permanent and temporary)

The first is straightforward to implement because the regimes are exogenous and unanticipated. We simply need to specify the equilibrium conditions in each regime, run `gensys`

for each regime, and return multiple transition equations. The required steps to solve a model with exogenous and unanticipated regime-switching are

- Write
`eqcond`

to accept a second argument specifying the regime, e.g.`eqcond(m::MyDSGEModel, reg::Int)`

.

To allow no regime-switching, we recommend also writing the wrapper `eqcond(m) = eqcond(m, 1)`

or whatever default regime is desired.

- Add additional keyword arguments to
`measurement`

so that it is defined as

```
function measurement(m::MyDSGEModel, TTT::AbstractMatrix{T}, RRR::AbstractMatrix{T}, CCC::AbstractVector{T};
reg::Int = 1, TTTs::Vector{<: AbstractMatrix{T}} = Matrix{T}[],
CCCs::Vector{<: AbstractVector{T}} = Vector{T}[],
information_set::UnitRange = reg:reg) where {T <: Real}
```

The type assertions for the arrays and keywords are not strictly necessary but are advised.

- Add the settings and indices required to ensure regime-switching is properly handled.

See Regime-Switching Forecasts for guidance on how to do this.

For 1 and 2, we recommend conferring with the implementation of regime-switching for Model 1002. See the equilibrium conditions here and the measurement equation here.

Temporary alternative policies are slightly more complicated. They leverage the same machinery as exogenous and unanticipated regime-switching, so steps 1 and 2 above are required still. But in addition, we need to specify in which regimes policies should be different than those specified by `eqcond`

, which assumes all policies are permanent ones. Once we have specified these policies, we use the algorithm from Calgiarini and Kulish to calculate the rational expectations solution to a model with ``predicted structural changes'', which allows us to specify temporary alternative policies like a temporary ZLB or a temporary switch to average inflation targeting. The function implementing this algorithm is`

gensys2`.

Missing docstring for `DSGE.gensys2`

. Check Documenter's build log for details.

See Alternative Policies and the regime-switching example script for guidance on how to use temporary alternative policies.

`DSGE.solve`

— Function`solve(m::AbstractDSGEModel; apply_altpolicy = false)`

Driver to compute the model solution and augment transition matrices.

**Inputs**

`m`

: the model object

**Keyword Arguments**

`apply_altpolicy::Bool`

: whether or not to solve the model under the alternative policy. This should be`true`

when we solve the model to forecast, but`false`

when computing smoothed historical states (since the past was estimated under the baseline rule).`regime_switching::Bool`

: true if the state space system features regime switching`regimes::Union{Int, Vector{Int}, UnitRange{Int}}`

: specifies the specific regime to solve for.

**Outputs**

- TTT, RRR, and CCC matrices of the state transition equation:

`S_t = TTT*S_{t-1} + RRR*ϵ_t + CCC`

solve(m::PoolModel) ```

Driver to compute the model solution when using the PoolModel type

**Inputs**

`m`

: the PoolModel object

**Outputs**

- Φ: transition function
- F_ϵ: distribution of structural shock
- F
*λ: prior on the initial λ*0

`solvect(m::AbstractCTModel; reduction_settings_check::Bool = false)`

Driver to compute the model solution and augment transition matrices.

**Inputs**

`m`

: the model object

**Outputs**

- TTT, RRR, and CCC matrices of the state transition equation:
`S_t = TTT*S_{t-1} + RRR*ϵ_t + CCC`

## The `System`

Type

The `solve`

function only returns the $TTT$, $RRR$, and $CCC$ matrices. To obtain the other matrices in the state-space representation of the DSGE, we provide a wrapper function `compute_system`

, which returns an object of type `System`

, whose fields are also special types we have implemented to faciltiate use of the state-space form.

`DSGE.System`

— Type`System{T <: Real}`

A mutable struct containing the transition and measurement equations for a state-space model. The matrices may be directly indexed: `sys[:TTT]`

returns `sys.transition.TTT`

, `sys[:ZZ]`

returns `sys.measurement.ZZ`

, etc.

`DSGE.Transition`

— Type`Transition{T<:Real}`

The transition equation of the state-space model takes the form

``s_t = TTT*s_{t-1} + RRR*ϵ_t + CCC``

The `Transition`

type stores the coefficient `Matrix{T}`

s (`TTT`

, `RRR`

) and constant `Vector{T} CCC`

.

`DSGE.Measurement`

— Type`Measurement{T<:Real}`

The measurement equation of the state-space model takes the form

`y_t = ZZ*s_t + DD + u_t`

where the error `u_t`

is the measurement error, which is uncorrelated with the shocks in the transition equation `ϵ_t`

.

**Fields**

If `Ns`

is the number of states `s_t`

, `Ny`

is the number of observables `y_t`

, and `Ne`

is the number of shocks `ϵ_t`

:

`ZZ`

: the`Ny`

x`Ns`

measurement matrix`DD`

: the`Ny`

x 1 constant vector`QQ`

: the`Ne`

x`Ne`

covariance matrix for the shocks`ϵ_t`

`EE`

: the`Ny`

x`Ny`

covariance matrix for the measurement error`η_t`

`DSGE.PseudoMeasurement`

— Type`PseudoMeasurement{T<:Real}`

The pseudo-measurement equation of the state-space model takes the form

`x_t = ZZ_pseudo*s_t + DD_pseudo`

**Fields**

Let `Ns`

be the number of states `s_t`

and `Nx`

be the number of pseudo-observables `x_t`

:

`ZZ_pseudo`

: the`Nx`

x`Ns`

pseudo-measurement matrix`DD_pseudo`

: the`Nx`

x 1 constant vector

`DSGE.compute_system`

— Function```
compute_system(m; tvis::Bool = false, verbose = :high)
compute_system_helper(m; tvis::Bool = false, verbose = :high)
```

Given the current model parameters, compute the state-space system corresponding to model `m`

. Returns a `System`

or `RegimeSwitchingSystem`

object. The keyword `apply_altpolicy`

indicates whether the state-space system should reflect an alternative policy, and the keyword `tvis`

indicates whether the state-space system involves time-varying information sets. To use `tvis = true`

, at least the setting `:tvis_information_set`

must exist. See `?DSGE.compute_tvis_system`

for more information about computing state-space systems with time-varying information sets.

compute*system just runs compute*system_helper (which actually computes the system) and then in the case of imperfect but positive credibility, adjusts the anticipated observables and pseudo-observables' measurement equations.

```
compute_system(m; apply_altpolicy = false,
check_system = false, get_system = false,
get_population_moments = false, use_intercept = false,
tvis::Bool = false, verbose = :high)
compute_system(m, data; apply_altpolicy = false,
check_system = false, get_system = false,
get_population_moments = false,
tvis::Bool = false, verbose = :high)
```

Given the current model parameters, compute the DSGE-VAR or DSGE-VECM system corresponding to model `m`

. If a matrix `data`

is also passed, then the VAR is estimated on `data`

using the DSGE `m`

as a prior with weight λ.

**Keyword Arguments**

`check_system::Bool`

: see`?compute_system`

that takes the input`m::AbstractDSGEModel`

and`system::System`

.`get_system::Bool`

: see Outputs`get_population_moments::Bool`

: see Outputs`use_intercept::Bool`

: use an intercept term when computing the OLS estimate of the VAR system.`tvis::Bool`

indicates whether the state-space system involves time-varying information sets.

**Outputs**

- If
`get_system = true`

: Returns the updated`system`

whose measurement matrices`ZZ`

,`DD`

, and`QQ`

correspond to the VAR or VECM specified by`m`

. If`m`

is an`AbstractDSGEVECMModel`

, then the`system`

and the vector implied by additional cointegrating relationships are returned as a 2-element tuple. - If
`get_population_moments = true`

: Returns the limit cross product matrices that describe the DSGE implied population moments between the observables and their lags. If`data`

is also passed as an input, then the sample population moments are also returned. - Otherwise:

Returns `β`

and `Σ`

, the coefficients and observables covariance matrix of the VAR or VECM. If `data`

is passed in, then `β`

and `Σ`

are estimated from the data using `m`

as a prior with weight λ. Otherwise, `β`

and `Σ`

comprise the VECM approximation of the DSGE `m`

.

`compute_system(m::PoolModel{T})`

Given the current model parameters, compute the state-space system corresponding to the PoolModel model `m`

.

Outputs

``` Φ: state transition function Ψ: likelihood function, given weights on underlying models (the states) and predictive densities F*ϵ: structural shock distribution F*u: likelihood function measurement error distribution F_λ: initial distribution of λ for state transition function

```
compute_system(m::AbstractDSGEModel, system::System;
observables::Vector{Symbol} = collect(keys(m.observables)),
pseudo_observables::Vector{Symbol} = collect(keys(m.pseudo_observables)),
states::Vector{Symbol} = vcat(collect(keys(m.endogenou_states)),
collect(keys(m.endogenous_states_augmented)))
shocks::Vector{Symbol} = collect(keys(m.exogenous_shocks)),
zero_DD = false, zero_DD_pseudo = false)
compute_system(m::AbstractDSGEVECMModel, system::System;
observables::Vector{Symbol} = collect(keys(m.observables)),
pseudo_observables::Vector{Symbol} = collect(keys(m.pseudo_observables)),
cointegrating::Vector{Symbol} = collect(keys(m.cointegrating)),
states::Vector{Symbol} = vcat(collect(keys(m.endogenou_states)),
collect(keys(m.endogenous_states_augmented)))
shocks::Vector{Symbol} = collect(keys(m.exogenous_shocks)),
zero_DD = false, zero_DD_pseudo = false)
```

computes the corresponding transition and measurement equations specified by the keywords (e.g. `states`

, `pseudo_observables`

) using the existing `ZZ`

, `ZZ_pseudo`

, and `TTT`

matrices in `system`

.

Note that this function does not update the EE matrix, which is set to all zeros. To incorporate measurement errors, the user must specify the EE matrix after applying compute_system.

**Keywords**

`observables`

: variables that should be

entered into the new `ZZ`

and `DD`

matrices. The `observables`

can be both Observables and PseudoObservables, but they must be an element of the system already.

`pseudo_observables`

: variables that should be

entered into the new `ZZ_pseudo`

and `DD_pseudo`

matrices. The `observables`

can be both Observables and PseudoObservables, but they must be an element of the system already.

`cointegrating`

: variables that should be

entered into the new `ZZ`

and `DD`

matrices as cointegrating relationships. The `observables`

can be both Observables and PseudoObservables, but they must be an element of the system already.

`states`

: variables that should be

entered into the new `TTT`

and `RRR`

matrices as states. They must be existing states.

`shocks`

: variables that should be

entered into the new `RRR`

and `QQ`

matrices as shocks. They must be existing exogenous shocks.

## The `RegimeSwitchingSystem`

Type

When there are multiple (exogenous) regimes in the state-space representation of the DSGE, it is useful to treat the system as one type rather than a vector of individual `System`

objects. The `RegimeSwitchingSystem`

type implements this idea, and via multiple dispatch, most commands that work on a `System`

object also work on a `RegimeSwitchingSystem`

object.

`DSGE.RegimeSwitchingSystem`

— Type`RegimeSwitchingSystem{T <: Real}`

A mutable struct containing the transition and measurement equations for a state-space model with regime-switching. The matrices may be directly indexed: `sys[1, :TTT]`

returns `sys.regime[1].transition.TTT`

, etc.

To get the number of regimes, one can call `n_regimes(regime_switch_system)`

or `regime_switch_system[:regimes]`

. Like a `System`

object, the fields of a `RegimeSwitchingSystem`

can be accessed by

```
regime_switch_system[:transitions]
regime_switch_system[:measurements]
regime_switch_system[:pseudo_measurements]
```

A `System`

can be formed from a specific regime by calling

`sys_reg2 = regime_switch_system[2]`

and specific matrices/types in a given regime can be accessed by

```
regime_switch_system[2, :TTT]
regime_switch_system[2, :transition]
regime_switch_system[2, :measurement]
regime_switch_system[2, :pseudo_measurement]
```

## The `TimeVaryingInformationSetSystem`

Type

This type implements a state space system with time-varying information sets. We alter two parts of the `RegimeSwitchingSystem`

.

First, the `transitions`

field is now a `Vector{Vector{Transition}}`

` because we may need to calculate the transition equations under different information sets. For example, the time-varying transition equations implied by expecting a temporary ZLB to 2023:Q4 in 2020:Q4 will be different than those implied by expecting a temporary ZLB to 2024:Q4. Thus, if the Federal Reserve announced a ZLB to 2023:Q4 in 2020:Q4, and then in 2021:Q1, they announced an extension of the ZLB to 2024:Q4, then the measurement equation needs to calculate two sets of time-varying transition equations.

Second, we add two new fields, `information_set`

and `select`

. The first specifies which regimes are part of the information set in a given regime. The second specifies which transition equation to use in each regime. Continuing the example of the change in the ZLB length, the regime in the `select`

field for 2020:Q4 would point to the set of transition equations associated with a temporary ZLB to 20203:Q4, while the regime in `select`

for 2021:Q1 would point to the set of transition equations associated with a temporary ZLB to 20204:Q4.

For more guidance, see Time-Varying Information Sets and the example tvis_system.jl, which shows how to work with this type.