README.md

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



Try the dsge package in your browser

Any scripts or data that you put into this service are public.

dsge documentation built on Sept. 25, 2026, 5:08 p.m.