A MATLAB/Dynare toolbox that automates the derivation of welfare-maximizing Ramsey policies and open-loop Nash equilibria for any model you can write in Dynare.
Supports Dynare 6.5 and 7.0 | MATLAB Symbolic Math Toolbox
Published paper
Macroeconomic Policy Games
Martin Bodenstein, Luca Guerrieri & Joe LaBriola — Journal of Monetary Economics, Vol. 101 (2019), pp. 64–81 · doi:10.1016/j.jmoneco.2018.07.015
What it does
When policymakers have distinct objectives, deviating from full cooperation can produce large welfare losses. This toolbox characterizes optimal policies by symbolic differentiation—no tedious manual Lagrangians required.
Computes the joint welfare-maximizing policy under full commitment, using the timeless-perspective approach of Benigno & Woodford (2012).
Solves the open-loop Nash game between two policymakers, each taking the other's complete contingent plan as given.
Reads a standard .mod file and outputs ready-to-run
Dynare files for Ramsey, Nash, or single-agent Ramsey problems.
Prerequisites
sym() and related functions
to derive first-order conditions analytically.
Verified to run on a MacBook with MATLAB 2026a.
setup_toolbox.m once from the toolbox root;
it auto-detects whichever versions are installed and writes
absolute paths into setpathdynare6_5.m and
setpathdynare7_0.m. A warning (not an error)
is issued if only one version is found.
setup_toolbox.m once from the toolbox root.
It embeds correct absolute paths into both
setpathdynare6_5.m and setpathdynare7_0.m.
Either file can be copied into any model subfolder and run at
session start to add the chosen Dynare version and the toolbox
to the MATLAB path.
Package contents
The download is a single zip archive containing the toolbox root and several subfolders. Example subdirectories ship with all generated output files so you can inspect results without re-running the toolbox.
Toolbox root. Contains setup_toolbox.m,
setpathdynare6_5.m, setpathdynare7_0.m,
run_tests.m, and call_cleanup.m.
83 core .m files: convertmodfiles.m,
get_nash.m, get_ramsey.m,
cleanup_dynare_dir.m, templates, and more.
Plotting helpers: makechart.m,
makeirfsecondorder.m, and band-pass filter
routines used by the replication scripts.
Two-country open-economy model (Benigno & Benigno 2006, Corsetti, Dedola & Leduc 2010). Replicates Figures 1–3 of the paper.
Macroprudential regulation model with financial frictions (Gertler & Karadi 2011). Replicates Figures 4–5.
Linear-quadratic implementation of the Corsetti, Dedola & Leduc (2010) model. Used to cross-check the toolbox output.
Test infrastructure. Run run_tests.m from the toolbox
root to verify compatibility; results are saved as timestamped
.mat files in tests/test_results/.
Appendix A.1.1
The toolbox reads a Dynare-formatted .mod file and
generates all first-order conditions automatically. Follow these six
steps to put your model file into the required format. Throughout,
example.mod stands for your model's filename.
var block
Define Util1 and Util2 as endogenous
variables and add their equations to the model block.
These are the period utility functions of the two policymakers.
// Endogenous variables
var Util1, Util2, c1y, c1c, c2y, c2c, ...;
model;
// Utility, agent 1 (e.g., country 1 central bank)
Util1 = (c1c^(1-sigma) - 1) / (1 - sigma) - chi0*c1n^(1+chi);
// Utility, agent 2 (e.g., country 2 central bank)
Util2 = (c2c^(1-sigma) - 1) / (1 - sigma) - chi0*c2n^(1+chi);
...
end;
var block into two blocks
Create one block for endogenous variables (including
Util1, Util2) and a second block for
exogenous shock processes. Precede each block with the comment
markers the toolbox looks for.
// Endogenous variables
var Util1, Util2, c1y, c1c, c2y, c2c, c1pid, c2pid, ...;
// Exogenous variables
var c1z, c2z, c1taupvar, c2taupvar, ...;
varexo c1zerr, c2zerr, c1taupvarerr, c2taupvarerr;
If parameter values are assigned directly inside the
.mod file, remove them and save them as
example_paramfile.m in the same folder.
Dynare will call this script via the steadystate file.
% example_paramfile.m
beta = 0.99;
sigma = 2;
chi = 1;
chi0 = 1;
xi_p = 0.75; % Calvo parameter
nu_p = 0.15; % price markup
omega_c = 0.85; % home bias in consumption
In the model block, insert the comment
// Policy Rule, agent 1 immediately before the
equation that will be replaced by the optimal policy rule for
player 1, and // Policy Rule, agent 2 for player 2.
These can be placeholder Taylor rules or simple definitions.
model;
...
// Policy Rule, agent 1
i1_t = c1pid; // instrument: country-1 producer price inflation
// Policy Rule, agent 2
i2_t = c2pid; // instrument: country-2 producer price inflation
...
end;
initval with a steady-state script
Delete the initval block and save steady-state
values for all endogenous variables as
example_ss_defs.m. Then create
example_steadystate.m using the template below —
Dynare calls this function to initialize the solver.
% example_steadystate.m
function [ys, check] = example_steadystate(junk, ys)
global M_
check = 0;
%% assign parameter values
example_paramfile
%% assign steady-state values
example_ss_defs
%% send parameters and steady states to Dynare
nparams = size(M_.param_names, 1);
for icount = 1:nparams
eval(['M_.params(icount) = ', M_.param_names{icount}, ';'])
end
nvars = M_.endo_nbr;
ys = zeros(nvars, 1);
for i_indx = 1:nvars
eval(['ys(i_indx) = ', M_.endo_names{i_indx}, ';'])
end
end
Collect all equations that describe the paths of exogenous
variables (AR(1) shock processes, etc.) and place them at the
very end of the model block, after all structural
equations.
model;
// ... all structural equations first ...
// Shock processes — place these last
c1z = rho_z * c1z(-1) + sigma_z * c1zerr;
c1taupvar = rho_p * c1taupvar(-1) + sigma_p * c1taupvarerr;
c2z = rho_z * c2z(-1) + sigma_z * c2zerr;
c2taupvar = rho_p * c2taupvar(-1) + sigma_p * c2taupvarerr;
end;
Appendix A.1.2
Once your model file is in the correct format, a single call to
convertmodfiles generates all the Dynare files you need.
convertmodfiles(infilename, policy_problem, instrument1, instrument2, discount_factor_name [, welfare_correction_flag])
| Argument | Type | Description |
|---|---|---|
| infilename | string | Name of your Dynare model file (with or without the
.mod extension). Example: 'BBCDLmodelcomp' |
| policy_problem | 'ramsey' | 'nash' | 'one_agent_ramsey' |
ramsey — joint welfare-maximizing cooperative policy. nash — open-loop Nash game: each player best-responds to the other's full contingent plan. one_agent_ramsey — one player optimizes while the other follows the arbitrary rule in the original file. |
| instrument1 | string | Name of the policy instrument variable for player 1.
Example: 'c1pid' (country-1 producer price inflation). |
| instrument2 | string | Name of the policy instrument variable for player 2, or
'1'/'2' if policy_problem =
'one_agent_ramsey'. |
| discount_factor_name | string | Name of the discount-factor parameter as it appears in
infilename_paramfile.m. Example: 'c1beta'.
The toolbox automatically assigns this value to nbeta
in the generated policy paramfile — no manual editing
required. |
| welfare_correction_flag | 0 | 1 (optional, default 0) | When set to 1, appends a welfare-correction term
that accounts for violations of commitment under the timeless
perspective. |
For a call convertmodfiles('example','nash','instr1','instr2','beta')
the toolbox writes the following files:
| File | Purpose |
|---|---|
| example_nash.mod | Complete Dynare model with the optimal first-order conditions replacing the original policy rules. |
| example_nash_lmss.m | Subset of first-order conditions that are linear in the Lagrange multipliers; used to initialize the steady-state solver. |
| example_nash_steadystate.m | Steadystate function called by Dynare. Calls the paramfile and ss_defs, then solves for the optimal steady state numerically. |
| guess_example_nash_steadystate.m | Uses the original model's steady state as a starting guess for the numerical steady-state solver. |
| example_nash_ss_defs.m | Steady-state values for the structural (non-multiplier) variables. |
| example_nash_paramfile.m | Parameter file; sets omega_welf1 = 0.5,
omega_welf2 = 0.5, and
nbeta = beta (the value of
discount_factor_name passed to
convertmodfiles) automatically. |
Augments any processed Dynare model with cumulative welfare
variables Welf1, Welf2, and
Welf.
Turns shocks on or off across all .mod files in
the current folder. Useful when comparing responses to
different shock groups.
Appendix A.2.1 · Worked example
Figures 1 and 2 of the paper compare impulse responses under
cooperative Ramsey policy and open-loop Nash play in a two-country
sticky-price model following Benigno & Benigno (2006) and
Corsetti, Dedola & Leduc (2010). Figure 1 shows responses to a
technology shock; Figure 2 shows responses to a cost-push shock.
All code lives in BBCDL_model_excl2ndorder/.
Figure 1 — Responses to a one-std-dev technology shock. Blue solid: Ramsey (cooperative). Red dashed: Open-loop Nash.
Figure 2 — Responses to a one-std-dev cost-push (markup) shock. Blue solid: Ramsey (cooperative). Red dashed: Open-loop Nash.
After unzipping, open MATLAB, navigate to the toolbox root
(nash_ramsey_toolbox_051626/), and run
setup_toolbox.m once. This auto-detects Dynare 6.5
and 7.0 and embeds the correct absolute paths into both
setpathdynare6_5.m and setpathdynare7_0.m.
Then navigate to BBCDL_model_excl2ndorder/ and
run the appropriate path script for your Dynare version:
% Step 1 – run once from the toolbox root:
cd 'path/to/nash_ramsey_toolbox_051626'
setup_toolbox % configures both setpathdynare6_5.m and setpathdynare7_0.m
% Step 2 – before each session, from the model folder:
cd 'path/to/nash_ramsey_toolbox_051626/JME_paper_replication_and_examples/BBCDL_model_excl2ndorder'
setpathdynare6_5 % use this for Dynare 6.5
% — or —
setpathdynare7_0 % use this for Dynare 7.0
Run CREATE_RAMSEY_AND_NASH.m. This calls
convertmodfiles once for the cooperative
(Ramsey) problem and once for the Nash problem, both using
producer price inflation (c1pid, c2pid)
as instruments. Pass 'c1beta' as the fifth argument
so the toolbox automatically sets the planner's discount factor
to match the households' — no manual editing of any generated
file is needed.
% CREATE_RAMSEY_AND_NASH.m (run this script)
setpathdynare6_5
% Cooperative Ramsey — 5th arg sets nbeta = c1beta automatically
convertmodfiles('BBCDLmodelcomp', 'ramsey', 'c1pid', 'c2pid', 'c1beta')
% Open-loop Nash — producer price inflation as instruments
convertmodfiles('BBCDLmodelcomp', 'nash', 'c1pid', 'c2pid', 'c1beta')
BBCDLmodelcomp_ramsey_c1pid_c2pid.mod and
BBCDLmodelcomp_nash_c1pid_c2pid.mod, together with
their companion steadystate, paramfile, ss_defs, and lmss files.
The generated paramfiles already contain nbeta = c1beta
and the shock blocks are preserved — the files are ready to run
in Dynare immediately with no further edits.
omega_welf1 = 0.5 and omega_welf2 = 0.5
(equal country weights). Leave these unchanged for Figures 1–2.
BBCDL_figure1and2.m to generate the figures
This script solves both models with Dynare, extracts
impulse responses using makeirfsecondorder
(first-order approximation), and plots Figures 1 and 2 via
makechart.
BBCDL_figure1and2 % run from BBCDL_model_excl2ndorder/
The script loops over two shocks — technology
(c1zerr) and cost-push (c1taupvarerr)
— and plots six panels for each:
All source code, replication scripts, and generated model files are packaged in a single zip archive.
⇓ nash_ramsey_toolbox_051626.zip
Contains: nash_ramsey_toolbox_051626/ · Dynare 6.5 & 7.0 compatible