Dynamic Stochastic General Equilibrium Models for R.
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:
read_dynare()) –
read a Dynare .mod file straight into dsge (macro
directives, calibration, steady state, shocks, measurement errors,
priors, Ramsey/discretionary/OSR policy and OccBin constraints), and
solve or estimate it without Dynare or MATLAB; MATLAB code in the file
and _steadystate.m files are run by a built-in MATLAB
interpreter, and perfect-foresight simulations
(initval/endval, deterministic shocks,
lmmcp constraints) by
simulate_perfect_foresight()obs(), unobs(), state())dsgenl_model(),
solve_dsge(order = 1, 2, 3))bayes_dsge()) with optional parallel chain execution
(n_cores)bayes_particle()) for fully nonlinear Bayesian estimation
without linearizationbayes_factor()) with Kass-Raftery evidence scales and
posterior model probabilitiesvariance_decomposition()) – both unconditional
steady-state shares and forecast-error variance decomposition at
user-supplied horizonsosr()) – finds
the optimal coefficients in a user-specified, restricted policy rule
(e.g. Taylor rule coefficients) given a quadratic welfare lossconditional_forecast()) – forecasts conditional on a
pre-specified path for a subset of observables (Waggoner-Zha 1999
minimum-norm shocks)irf_match())
– estimate structural parameters by matching DSGE impulse responses to a
user-supplied target (e.g. VAR-estimated IRFs),
Christiano-Eichenbaum-Evans stylebayes_dsge_var(),
bayes_dsge_var_mh()) – Bayesian VAR with DSGE-implied prior
(Del Negro & Schorfheide 2004). The MH variant jointly estimates
structural parameters, shock SDs, and the prior weight lambda;
forecast() and conditional_forecast() methods
support fan-chart projections and path-conditioned forecasts –
Dynare-parity workflowperfect_foresight_nonlinear()dsge_model(derived = ...) for encoding models with
Dynare-style # macro substitutions (e.g. Smets-Wouters
2007), with the doubling-algorithm Lyapunov solver handling
highly-persistent state dynamics robustlycalibrated_smoother()) – Kalman smoothing on a model that
has been solved but not estimatedpredetermined() – alias for
state-variable declarations, matching Dynare’s
predetermined_variablesperfect_foresight_expect_err()) – realised vs. subjective
shock paths with revising expectationsextended_path()) – stochastic simulation by solving a
perfect-foresight path per periodendogenous_prior())
– Christiano-Trabandt- Walentin prior on model-implied second
momentsglobal_sensitivity()) – Sobol’ indices and Morris
elementary effectsdiscretionary_policy()) – time-consistent (no-commitment)
feedback rule via the Soederlind / Dennis fixed-point iterationgmm_estimate(), smm_estimate()) –
moment-matching estimators with optional two-step weightingbayes_smc()) – tempered SMC for robust posterior sampling,
especially for multimodal posteriorsmodel_latex()) –
write a model’s equations to compilable LaTeX, with Greek substitution
and time subscriptskalman_filter_skewed()) – exact third-cumulant propagation
for skew-normal structural shocksms_filter()) – regime-switching shock variances via the
Kim (1994) filter, with smoothed regime probabilitiespac_weights(),
pac_target_loading(), pac_simulate()) –
FRB/US-style polynomial adjustment costs with closed-form
forward-looking weightsramsey_policy(),
welfare_loss())perfect_foresight()) and fully nonlinear
via stacked-time Newton
(perfect_foresight_nonlinear())# Install from CRAN
install.packages("dsge")
# Or install the development version from GitHub
# install.packages("devtools")
devtools::install_github("Mustapha-Wasseja/dsge-package")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# 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.
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()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)# ZLB constraint on the interest rate
obc <- simulate_occbin(sol,
constraints = list("r >= 0"),
shocks = list(g = -0.05),
horizon = 40)
plot(obc)# 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)# 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)# 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# 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# 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 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)# 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)# 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)# (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)# 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)# 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_constraintsDynare 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.
# 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 | 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 |
vignette("introduction", package = "dsge")system.file("examples", package = "dsge")MIT