dsge

Dynamic Stochastic General Equilibrium Models for R.

CRAN status

Overview

The dsge package provides a comprehensive framework for specifying, solving, and estimating DSGE models entirely in R. No external software (Dynare, MATLAB, Octave) is required.

Key capabilities:

Installation

# Install from CRAN
install.packages("dsge")

# Or install the development version from GitHub
# install.packages("devtools")
devtools::install_github("Mustapha-Wasseja/dsge-package")

Quick Start: Maximum Likelihood

library(dsge)

# Define a simple New Keynesian model
nk <- dsge_model(
  obs(p   ~ beta * lead(p) + kappa * x),       # Phillips curve
  unobs(x ~ lead(x) - (r - lead(p) - g)),      # IS curve
  obs(r   ~ psi * p + u),                       # Taylor rule
  state(u ~ rhou * u),                          # Monetary shock
  state(g ~ rhog * g),                          # Demand shock
  fixed = list(beta = 0.99),
  start = list(kappa = 0.1, psi = 1.5, rhou = 0.7, rhog = 0.9)
)

# Estimate by maximum likelihood
fit <- estimate(nk, data = your_data)
summary(fit)

# Postestimation
irf(fit, periods = 20) |> plot()               # Impulse responses
forecast(fit, horizon = 12) |> plot()           # Forecasts
smooth_states(fit) |> plot()                    # Kalman-smoothed states
shock_decomposition(fit) |> plot()              # Historical decomposition
check_identification(fit)                       # Identification diagnostics
robust_vcov(fit)                                # Sandwich standard errors
model_covariance(fit)                           # Model-implied moments

Bayesian Estimation

# Specify priors
my_priors <- list(
  kappa = prior("beta", shape1 = 30, shape2 = 70),
  psi   = prior("gamma", shape = 184, rate = 122.7),
  rhou  = prior("beta", shape1 = 70, shape2 = 20),
  rhog  = prior("beta", shape1 = 70, shape2 = 20)
)

# Run MCMC
fit_bayes <- bayes_dsge(nk, data = your_data, priors = my_priors,
                        chains = 2, iter = 10000, warmup = 5000)

# Diagnostics and results
summary(fit_bayes)
plot(fit_bayes, type = "trace")
plot(fit_bayes, type = "prior_posterior")
plot(fit_bayes, type = "irf", periods = 20)

Supported priors: normal, beta, gamma, uniform, inv_gamma.

Nonlinear DSGE Models

rbc <- dsgenl_model(
  "1/C = beta / C(+1) * (alpha * exp(Z) * K^(alpha-1) + 1 - delta)",
  "K(+1) = exp(Z) * K^alpha - C + (1 - delta) * K",
  "Z(+1) = rho * Z",
  observed = "C",
  endo_state = "K",
  exo_state = "Z",
  fixed = list(alpha = 0.33, beta = 0.99, delta = 0.025),
  start = list(rho = 0.9),
  ss_guess = c(C = 2, K = 30, Z = 0)
)

sol <- solve_dsge(rbc, params = c(alpha = 0.33, beta = 0.99,
                                   delta = 0.025, rho = 0.9),
                  shock_sd = c(Z = 0.01))
irf(sol, periods = 40) |> plot()

Advanced Features

Second- and Third-Order Perturbation

sol2 <- solve_dsge(rbc, params = params, shock_sd = sd, order = 2)
simulate_2nd_order(sol2, periods = 200)
irf_2nd_order(sol2, periods = 40)

sol3 <- solve_dsge(rbc, params = params, shock_sd = sd, order = 3)
simulate_3rd_order(sol3, periods = 200)

Occasionally Binding Constraints

# ZLB constraint on the interest rate
obc <- simulate_occbin(sol,
  constraints = list("r >= 0"),
  shocks = list(g = -0.05),
  horizon = 40)
plot(obc)

Perfect Foresight Paths

# Linearized perfect foresight (fast, small shocks)
pf <- perfect_foresight(sol,
  shocks = list(Z = c(-0.05, -0.03, -0.01)),
  horizon = 60)
plot(pf)

# Fully nonlinear perfect foresight via stacked-time Newton
# (recommended for large shocks where nonlinearities matter)
pf_nl <- perfect_foresight_nonlinear(rbc,
  params   = c(rho = 0.9),
  shock_sd = c(Z = 0.01),
  shocks   = list(Z = 0.10),
  horizon  = 40)
plot(pf_nl)

Particle Filter and PMMH

# Bootstrap particle filter likelihood for nonlinear models
ll <- particle_filter_loglik(sol2, data = your_data, n_particles = 1000)

# Particle Marginal Metropolis-Hastings -- fully nonlinear Bayesian
fit_pmmh <- bayes_particle(rbc, data = your_data, priors = my_priors,
                           n_particles = 500, chains = 2, iter = 5000)

Ramsey Optimal Policy

# Quadratic welfare loss on inflation and output gap
rp <- ramsey_policy(sol,
  Q_xx = diag(c(p = 1, x = 0.5)),
  Q_yy = diag(c(r = 0.1)))
welfare_loss(sol, rp$F)   # evaluate welfare under the optimal rule

Bayes Factor Model Comparison

# Compare two Bayesian fits
bf <- bayes_factor(fit_bayes_A, fit_bayes_B,
                   prior_odds = c(0.5, 0.5))
print(bf)   # log Bayes factor + Kass-Raftery evidence label

Variance Decomposition

# Unconditional decomposition (long-run shares)
vd <- variance_decomposition(sol)
print(vd)
plot(vd)

# Forecast-error variance decomposition at multiple horizons
fevd <- variance_decomposition(sol, horizon = c(1, 4, 8, 20))
plot(fevd)

Optimal Simple Rules

# Optimal Taylor-rule coefficient
res <- osr(nk,
  params      = c(kappa = 0.1, psi = 1.5, rhou = 0.7, rhog = 0.9),
  shock_sd    = c(e.u = 1.0, e.g = 0.5),
  osr_params  = c(psi = 1.5),
  welfare_weights = list(Q_yy = c(p = 1, x = 0.5, r = 0.1)),
  lower = 1.01, upper = 5.0)
print(res)

Conditional Forecasts

# Hold the policy rate at 0.5 for the next 4 periods
cf <- conditional_forecast(fit, horizon = 12,
  condition = list(r = c(0.5, 0.5, 0.5, 0.5, rep(NA, 8))))
plot(cf)

IRF Matching Estimation

# Match the DSGE IRF to an externally estimated target
est <- irf_match(nk,
  params_start   = c(kappa = 0.15, psi = 2.0, rhou = 0.6, rhog = 0.8),
  shock_sd_start = c(e.u = 0.8, e.g = 0.7),
  target         = target_irf_dataframe)

DSGE-VAR

# (a) Conditional-on-(theta,lambda) Bayesian VAR with DSGE prior
fit_dv <- bayes_dsge_var(sol, data = your_data,
                         p = 4, lambda = 1.0, n_draws = 1000)
print(fit_dv)
# Compare different lambdas by marginal likelihood
sapply(c(0.5, 1, 2, 5),
       function(l) bayes_dsge_var(sol, your_data, p=4, lambda=l,
                                  n_draws=200)$log_marg_lik)

# (b) Joint MH estimation of (theta_DSGE, sigma, lambda) -- Dynare-parity
priors <- list(kappa = prior("beta",  shape1 = 2, shape2 = 8),
               psi   = prior("normal", mean = 1.5, sd = 0.25),
               rhou  = prior("beta",  shape1 = 2, shape2 = 2),
               rhog  = prior("beta",  shape1 = 8, shape2 = 2))
fit_mh <- bayes_dsge_var_mh(nk, data = your_data, priors = priors,
                            p = 4, chains = 2, iter = 2000)
print(fit_mh)

# Unconditional + conditional forecasts from the DSGE-VAR posterior
fc_unc  <- forecast(fit_mh, horizon = 12)
fc_cond <- conditional_forecast(fit_mh, horizon = 12,
            condition = list(r = c(0.5, 0.5, 0.5, 0.5, rep(NA, 8))))
plot(fc_unc); plot(fc_cond)

Anticipated / News Shocks (Perfect Foresight)

# Nonlinear PF correctly anticipates a future TFP shock
pf_news <- perfect_foresight_nonlinear(rbc,
  params   = c(rho = 0.9),
  shock_sd = c(Z = 0.01),
  shocks   = list(Z = c(0, 0, 0.05)),  # announced at t=1, arrives at t=3
  horizon  = 40)
plot(pf_news)

Importing Dynare Models

# Read a Dynare .mod file: model, calibration, steady state, shocks, priors
rbc <- read_dynare(system.file("examples", "rbc.mod", package = "dsge"))
rbc                        # summary, auxiliary variables and any notes

sol <- solve_dsge(rbc)     # solves at the file's calibration
plot(irf(sol, periods = 40))

# Files with estimated_params / varobs estimate directly, using the
# translated priors (data columns named as in Dynare)
# fit <- bayes_dsge(read_dynare("model.mod"), data = my_data)

# Optimal policy and occasionally binding constraints declared in the file
# ram <- solve_dsge(read_dynare("ramsey.mod"))       # ramsey_model
# opt <- osr(read_dynare("osr.mod"))                  # osr_params, optim_weights
# zlb <- simulate_occbin(read_dynare("zlb.mod"))      # occbin_constraints

Dynare timing is handled automatically (lags become auxiliary state variables, so k(-1) capital timing needs no rewriting), and macro directives (@#define, @#for, @#if, …) are expanded in R. MATLAB statements in the file (calibrations, verbatim blocks) and MATLAB steady-state files (<model>_steadystate.m, with fsolve and helper functions) are run by a built-in MATLAB interpreter. Results have been checked against Dynare 6.0 (see dev/dynare-validation/): the first-order impulse responses of every model in Johannes Pfeifer’s DSGE_mod collection that Dynare runs in Octave, second- and third-order decision rules of 21 nonlinear models, the Smets-Wouters (2007) likelihood (with lik_init = 1 and 2), and a full Bayesian estimation.

Parallel MCMC Chains

# Run chains in parallel across cores (PSOCK on Windows, fork on POSIX)
fit_bayes <- bayes_dsge(nk, data = your_data, priors = my_priors,
                        chains = 4, iter = 10000, warmup = 5000,
                        n_cores = 4)

Feature Comparison

Feature dsge (R) DynareR (R) Dynare (MATLAB)
Native R implementation Yes No (wrapper) No
External software required None Dynare + Octave MATLAB/Octave
CRAN package Yes Yes N/A
Linear DSGE Yes Via Dynare Yes
Nonlinear DSGE Yes Via Dynare Yes
ML estimation Yes Via Dynare Yes
Bayesian estimation (RWMH) Yes Via Dynare Yes
Particle filter / PMMH Yes Via Dynare Yes
Parallel MCMC chains Yes Via Dynare Yes
2nd-order perturbation Yes Via Dynare Yes
3rd-order perturbation Yes Via Dynare Yes
OccBin / ZLB Yes Via Dynare Yes
Linear perfect foresight Yes Via Dynare Yes
Nonlinear perfect foresight (LBJ) Yes Via Dynare Yes
Ramsey optimal policy Yes Via Dynare Yes
Bayes factor model comparison Yes No Partial
Variance decomposition (unconditional + FEVD) Yes Via Dynare Yes
Optimal simple rules Yes Via Dynare Yes
Discretionary optimal policy Yes Via Dynare Yes
Conditional forecasts Yes Via Dynare Yes
IRF matching estimation Yes Via Dynare Yes
GMM / SMM estimation Yes Via Dynare Yes
DSGE-VAR (joint MH + forecasting) Yes Via Dynare Yes
Sequential Monte Carlo sampler Yes Via Dynare Yes
Endogenous priors Yes Via Dynare Yes
Derived (model-local) parameters Yes Via Dynare Yes
Calibrated-model smoother Yes Via Dynare Yes
Extended path simulation Yes Via Dynare Yes
Perfect foresight with expectation errors Yes Via Dynare Yes
Global sensitivity analysis Yes Via Dynare Yes
Skew-normal Kalman filter Yes Via Dynare Yes
Markov-switching volatility Yes Via Dynare Yes
PAC equations Yes Via Dynare Yes
LaTeX model export Yes Via Dynare Yes
R model interface (coef, vcov, plot) Yes No No
Formula-based specification Yes No No
Reads Dynare .mod files Yes (translated to R) Yes (runs Dynare) Yes

Documentation

References

License

MIT