A general purpose DSGE interface which presents a lightweight approach to solving macroeconomic models. The purpose of creating this module was to rapidly estimate models in liu of (Childers, 2022).
As a departure to DifferentiableStateSpaceModels.jl, this module is entirely self contained and builds off of existing tools like GeneralisedFilters.jl for marginalized likelihood estimation.
Upon cloning this repository, we have to properly set up the environment to support the local execution of this interface; furthermore, we also rely on a development branch of GeneralisedFilters.jl for functional automatic differentiation.
To set this up, instantiate the environment described in Project.toml, by running Using Pkg; Pkg.activate("."); Pkg.instantiate() if not activated automatically.
First load in the module as well as some helpful packages.
using DynamicMacroeconomics
using GeneralisedFilters
using RandomWe begin by defining the model equations, where each of the function arguments are state variables (including shocks). The desired syntax subscribes to the DAG paradigm ala SSJ, which implies variable substitution across blocks without a symbolic backend.
@simple function market_clearing(C, Y, I, r, β, γ)
euler = (C^-γ) - (β * (1 + lead(r)) * (lead(C)^-γ))
goods_mkt = Y - C - I
return euler, goods_mkt
end
@simple function firms(Z, K, α, δ)
r = α * Z * lag(K)^(α - 1) - δ
Y = Z * lag(K)^α
return r, Y
end
@simple function households(K, δ)
I = K - (1 - δ) * lag(K)
return I
end
@simple function shocks(Z, ρ, ε)
shock_res = log(Z) - ρ * log(lag(Z)) - ε
return shock_res
endSteady states are calculated internally, using NonlinearSolve.jl as a backend for optimization.
rbc_model = model(market_clearing, firms, households, shocks; name="rbc")
ss = solve_steady_state(
rbc_model,
(γ=1.00, α=0.30, δ=0.25, β=(1 / 1.05), ρ=0.80, ε=0.00),
(C=1.00, K=0.40, Z=0.40),
(euler=0.00, goods_mkt=0.00, shock_res=0.00),
)Now that the model is sufficiently defined, we can obtain the policy function by solving the first order perturbation either by state space or sequence space methods.
unknowns = (:K, :C, :Z)
shocks = (:ε,)
targets = (:euler, :goods_mkt, :shock_res)
solve(rbc_model, ss, unknowns, shocks, targets; order=1, algo=QuadraticIteration())
solve(rbc_model, ss, unknowns, shocks, targets; order=1, algo=QZ())
solve(rbc_model, ss, unknowns, shocks, targets; order=1, algo=SequenceJacobian(150))We encourage the user to experiment with SSMProblems.jl to create a potentially nonlinear measurement, but we include a constructor for linear Gaussian state space models. To demonstrate we can create a state space observing consumption with a measurement noise of 1.0, and simulate 100 time periods.
A, B = solve(rbc_model, ss, unknowns, shocks, targets; order=1, algo=QZ())
ssm = StateSpaceModel(..., LinearGaussianControllableDynamics(A, B), ...)
x, y = sample(rng, ssm, 100)Using GeneralizedFilters.jl, we can extract the loglikelihood with the Kalman filter. This is used in models/rbc.jl for estimation. More details can be provided in that script (lol sike not really, although this will be soon reestablished).
- Models support general offsets, but first order perturbation does not handle it just yet.
- I plan on removing the
ComponentArrays.jldependency since it may have some odd type conversions. - Yes, I know the docs are broken and it will get fixed as soon as I can solve models consistently.
Just ask me for questions on the implementation, and if you see anything questionable feel free to raise an issue or a PR.