First draft of method of moments toolbox with GMM and SMM

time-shift
Willi Mutschler 2020-06-11 13:21:31 +02:00 committed by Johannes Pfeifer
parent 77dbeab98a
commit 3615962a61
11 changed files with 2265 additions and 1 deletions

994
matlab/method_of_moments.m Normal file
View File

@ -0,0 +1,994 @@
function [DynareResults, OptionsMoM] = method_of_moments(BayesInfo, DynareOptions, DynareResults, EstimatedParameters, Model, MatchedMoments, OptionsMoM)
%function [oo_, options_mom] = method_of_moments(M, options, oo, bayestopt, estim_params, matched_moments, options_mom)
% -------------------------------------------------------------------------
% This function performs a method of moments estimation with the following steps:
% Step 0: Check if required structures and options exist
% Step 1: - Prepare OptionsMoM structure
% - Carry over Options from the preprocessor
% - Other options that need to be initialized
% - Get variable orderings and state space representation
% Step 2: Checks and transformations for matched moments structure (preliminary)
% Step 3: Checks and transformations for estimated parameters, priors, and bounds
% Step 4: Checks and transformations for data
% Step 5: checks for steady state at initial parameters
% Step 6: checks for objective function at initial parameters
% Step 7: Method of moments estimation: print some info, first-stage, and second-stage
% Step 8: Clean up
% -------------------------------------------------------------------------
% This function is inspired by replication codes accompanied to the following papers:
% o Andreasen, Fernández-Villaverde, Rubio-Ramírez (2018): "The Pruned State-Space System for Non-Linear DSGE Models: Theory and Empirical Applications", Review of Economic Studies, 85(1):1-49.
% o Born, Pfeifer (2014): "Risk Matters: Comment", American Economic Review, 104(12):4231-4239.
% o Mutschler (2018): "Higher-order statistics for DSGE models", Econometrics and Statistics, 6:44-56.
% =========================================================================
% INPUTS
% o BayesInfo: [structure] information about priors (bayestopt_)
% o DynareOptions: [structure] information about global options (options_)
% o DynareResults: [structure] storage for results (oo_)
% o EstimatedParameters: [structure] information about estimated parameters (estim_params_)
% o Model: [structure] information about model (M_)
% o MatchedMoments: [structure] information about selected moments to match in estimation (matched_moments_)
% o OptionsMoM: [structure] information about settings specified by the user (options_mom_)
% -------------------------------------------------------------------------
% OUTPUTS
% o DynareResults: [structure] storage for results (oo_)
% o OptionsMoM: [structure] information about all used settings used in estimation (options_mom_)
% -------------------------------------------------------------------------
% This function is called by
% o driver.m
% -------------------------------------------------------------------------
% This function calls
% o check_for_calibrated_covariances.m
% o check_prior_bounds.m
% o do_parameter_initialization.m
% o dynare_minimize.m
% o evaluate_steady_state
% o get_all_parameters.m
% o makedataset.m
% o method_of_moments_datamoments.m
% o plot_priors.m
% o print_info.m
% o prior_bounds.m
% o set_default_option.m
% o set_prior.m
% o set_state_space.m
% o set_all_parameters
% o list_of_parameters_calibrated_as_Inf
% o list_of_parameters_calibrated_as_NaN
% =========================================================================
% Copyright (C) 2020 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
% Author(s):
% o Willi Mutschler (willi@mutschler.eu)
% o Johannes Pfeifer (jpfeifer@uni-koeln.de)
% =========================================================================
%% TO DO LIST
% - [ ] penalized estimation: how does penalized_estimator work? What is
% penalized_estimator? Not all optimizer make use of this...what is special
% about mode_compute=1 in objective functions. Do we need global objective_function_penalty_base in objective function
% - [ ] make csminwel work
% - [ ] why does lsqnonlin take less time in Andreasen toolbox?
% - [ ] recheck different optimizers if they are useful
% - [ ] test prefilter option (i.e. centered moments)
% - [ ] how to deal with logged_steady_state
% - [ ] mode_check plots?
% - [ ] test prior restrictions file
% - [ ] test user-specified weightning matrix
% - [ ] test non-symetric Sigma_e
% - [ ] which qz_criterium value?
% - [ ] are missing observations a problem? in method_of_moments_datamoments.m nan are replaced by mean of moment
% - [ ] check negative priors on std errors and above 1 for correlations
% - [ ] add measurement errors
% - [ ] add IRF matching
% - [ ] what are trend_coeffs and how to deal with them?
% - [ ] once interface is established: provide code to remove duplicate declared moments in matched moments block
% - [ ] test estimated_params_init(use calibration)
% - [ ] test estimated_params_bounds block
% - [ ] test what happens if all parameters will be estimated but some/all are not calibrated
% - [ ] speed up lyapunov equation by using doubling with old initial values
% - [ ] check what happens if parameters are set to INF or NAN
% - [ ] provide a table with dataMoments and final modelMoments
% - [ ] check smm at order > 3 without pruning
% - [ ] provide option to use analytical derivatives to compute std errors (similar to what we already do in identification)
% - [ ] add Bayesian GMM/SMM estimation
% - [ ] useautocorr
% - [ ] instead of mom_steps, iterate over optimizers using additional_optimizer_steps
% -------------------------------------------------------------------------
% Step 0: Check if required structures and options exist
% -------------------------------------------------------------------------
if isempty(EstimatedParameters) % structure storing the info about estimated parameters in the estimated_params block
error('method_of_moments: You need to provide an ''estimated_params'' block')
end
if isempty(MatchedMoments) % structure storing the moments used for the method of moments estimation
error('method_of_moments: You need to provide a ''matched_moments'' block')
end
if ~isempty(BayesInfo) && any(BayesInfo.pshape==0) && any(BayesInfo.pshape~=0)
error('method_of_moments: Estimation must be either fully classical or fully Bayesian. Maybe you forgot to specify a prior distribution.')
end
fprintf('\n==== Method of Moments Estimation ====\n\n')
% -------------------------------------------------------------------------
% Step 1a: Prepare OptionsMoM structure
% -------------------------------------------------------------------------
% OptionsMoM is local and contains default and user-specified values for
% all settings needed for the method of moments estimation. Some options,
% though, are set by the preprocessor into options_ and we copy these over.
% The idea is to be independent of options_ and have full control of the
% estimation instead of possibly having to deal with options chosen somewhere
% else in the mod file.
% Method of Moments estimation options that can be set by the user in the mod file, otherwise default values are provided
if strcmp(OptionsMoM.mom_method,'GMM') || strcmp(OptionsMoM.mom_method,'SMM')
OptionsMoM = set_default_option(OptionsMoM,'bartlett_kernel_lag',20); % bandwith in optimal weighting matrix
OptionsMoM = set_default_option(OptionsMoM,'order',1); % order of Taylor approximation in perturbation
OptionsMoM = set_default_option(OptionsMoM,'penalized_estimator',false); % @wmutschl: provide description
OptionsMoM = set_default_option(OptionsMoM,'pruning',true); % use pruned state space system at higher-order
OptionsMoM = set_default_option(OptionsMoM,'verbose',false); % display and store intermediate estimation results
OptionsMoM = set_default_option(OptionsMoM,'weighting_matrix','identity_matrix'); % weighting matrix in moments distance objective function; possible values: OPTIMAL|IDENTITY_MATRIX|DIAGONAL|filename
OptionsMoM = set_default_option(OptionsMoM,'additional_optimizer_steps',[]); % Number of iterations in the steps of the 2-step feasible method of moments
% Checks for perturbation order
if OptionsMoM.order < 1
error('method_of_moments:: The order of the Taylor approximation cannot be 0!')
elseif OptionsMoM.order > 2 && (~isfield(OptionsMoM,'k_order_solver') || ~OptionsMoM.k_order_solver)
fprintf('method_of_moments: For perturbation order k>2, we add the k_order_solver option.\n');
OptionsMoM.k_order_solver = 1;
end
end
if strcmp(OptionsMoM.mom_method,'SMM')
objective_function = str2func('method_of_moments_SMM');
OptionsMoM = set_default_option(OptionsMoM,'bounded_shock_support',false); % trim shocks in simulation to +- 2 stdev
OptionsMoM = set_default_option(OptionsMoM,'drop',500); % number of periods dropped at beginning of simulation
OptionsMoM = set_default_option(OptionsMoM,'seed',24051986); % seed used in simulations
OptionsMoM = set_default_option(OptionsMoM,'simulation_multiple',5); % multiple of the data length used for simulation
if OptionsMoM.simulation_multiple < 1
fprintf('The simulation horizon is shorter than the data. Dynare resets the simulation_multiple to 2.\n')
OptionsMoM.smm.simulation_multiple = 2;
end
end
if strcmp(OptionsMoM.mom_method,'GMM')
objective_function = str2func('method_of_moments_GMM');
% Check for pruning with GMM at higher order
if OptionsMoM.order > 1 && ~OptionsMoM.pruning
fprintf('GMM at higher order only works with pruning, so we set pruning option to 1.\n');
OptionsMoM.pruning = true;
end
end
% General options that can be set by the user in the mod file, otherwise default values are provided
OptionsMoM = set_default_option(OptionsMoM,'dirname',Model.fname); % directory in which to store estimation output
OptionsMoM = set_default_option(OptionsMoM,'graph_format','eps'); % specify the file format(s) for graphs saved to disk
OptionsMoM = set_default_option(OptionsMoM,'nodisplay',false); % do not display the graphs, but still save them to disk
OptionsMoM = set_default_option(OptionsMoM,'nograph',false); % do not create graphs (which implies that they are not saved to the disk nor displayed)
OptionsMoM = set_default_option(OptionsMoM,'noprint',false); % do not print output to console
OptionsMoM = set_default_option(OptionsMoM,'plot_priors',true); % control plotting of priors
OptionsMoM = set_default_option(OptionsMoM,'prior_trunc',1e-10); % probability of extreme values of the prior density that is ignored when computing bounds for the parameters
OptionsMoM = set_default_option(OptionsMoM,'TeX',false); % print TeX tables and graphics
% Data and model options that can be set by the user in the mod file, otherwise default values are provided
OptionsMoM = set_default_option(OptionsMoM,'first_obs',1); % number of first observation
OptionsMoM = set_default_option(OptionsMoM,'logdata',false); % if loglinear is set, this option is necessary if the user provides data already in logs, otherwise the log transformation will be applied twice (this may result in complex data)
OptionsMoM = set_default_option(OptionsMoM,'loglinear',false); % computes a log-linear approximation of the model instead of a linear approximation
OptionsMoM = set_default_option(OptionsMoM,'nobs',NaN); % number of observations
OptionsMoM = set_default_option(OptionsMoM,'prefilter',false); % demean each data series by its empirical mean and use centered moments
OptionsMoM = set_default_option(OptionsMoM,'xls_sheet',1); % name of sheet with data in Excel
OptionsMoM = set_default_option(OptionsMoM,'xls_range',''); % range of data in Excel sheet
% Recursive estimation and forecast are not supported
if numel(OptionsMoM.nobs)>1
error('method_of_moments: Recursive estimation and forecast for samples is not supported. Please set an integer as ''nobs''.');
end
if numel(OptionsMoM.first_obs)>1
error('method_of_moments: Recursive estimation and forecast for samples is not supported. Please set an integer as ''first_obs''.');
end
% Optimization options that can be set by the user in the mod file, otherwise default values are provided
if strcmp(OptionsMoM.mom_method, 'GMM')
OptionsMoM = set_default_option(OptionsMoM,'analytic_derivation',0); % use analytic derivatives to compute standard errors for GMM
elseif isfield(OptionsMoM,'analytic_derivation')
fprintf('Only GMM supports analytic derivation to compute standard errors, we reset ''analytic_derivation'' to 0.\n')
OptionsMoM.analytic_derivation = 0;
else
OptionsMoM.analytic_derivation = 0;
end
OptionsMoM = set_default_option(OptionsMoM,'huge_number',1e7); % value for replacing the infinite bounds on parameters by finite numbers. Used by some optimizers for numerical reasons
OptionsMoM = set_default_option(OptionsMoM,'mode_compute',13); % specifies the optimizer for minimization of moments distance
OptionsMoM = set_default_option(OptionsMoM,'optim_opt',[]); % a list of NAME and VALUE pairs to set options for the optimization routines. Available options depend on mode_compute
OptionsMoM = set_default_option(OptionsMoM,'silent_optimizer',false); % run minimization of moments distance silently without displaying results or saving files in between
if ~isfield(OptionsMoM,'dynatol')
OptionsMoM.dynatol = {};
end
OptionsMoM.dynatol = set_default_option(OptionsMoM.dynatol,'f', 1e-5);% convergence criterion on function value for numerical differentiation
OptionsMoM.dynatol = set_default_option(OptionsMoM.dynatol,'x', 1e-5);% convergence criterion on funciton input for numerical differentiation
% Numerical algorithms options that can be set by the user in the mod file, otherwise default values are provided
OptionsMoM = set_default_option(OptionsMoM,'aim_solver',false); % Use AIM algorithm to compute perturbation approximation
OptionsMoM = set_default_option(OptionsMoM,'dr_cycle_reduction',false); % use cycle reduction algorithm to solve the polynomial equation for retrieving the coefficients associated to the endogenous variables in the decision rule
OptionsMoM = set_default_option(OptionsMoM,'dr_cycle_reduction_tol',1e-7); % convergence criterion used in the cycle reduction algorithm
OptionsMoM = set_default_option(OptionsMoM,'dr_logarithmic_reduction',false); % use logarithmic reduction algorithm to solve the polynomial equation for retrieving the coefficients associated to the endogenous variables in the decision rule
OptionsMoM = set_default_option(OptionsMoM,'dr_logarithmic_reduction_maxiter',100); % maximum number of iterations used in the logarithmic reduction algorithm
OptionsMoM = set_default_option(OptionsMoM,'dr_logarithmic_reduction_tol',1e-12); % convergence criterion used in the cycle reduction algorithm
OptionsMoM = set_default_option(OptionsMoM,'lyapunov_db',false); % doubling algorithm (disclyap_fast) to solve Lyapunov equation to compute variance-covariance matrix of state variables
OptionsMoM = set_default_option(OptionsMoM,'lyapunov_fp',false); % fixed-point algorithm to solve Lyapunov equation to compute variance-covariance matrix of state variables
OptionsMoM = set_default_option(OptionsMoM,'lyapunov_srs',false); % square-root-solver (dlyapchol) algorithm to solve Lyapunov equation to compute variance-covariance matrix of state variables
OptionsMoM = set_default_option(OptionsMoM,'lyapunov_complex_threshold',1e-15); % complex block threshold for the upper triangular matrix in symmetric Lyapunov equation solver
OptionsMoM = set_default_option(OptionsMoM,'lyapunov_fixed_point_tol',1e-10); % convergence criterion used in the fixed point Lyapunov solver
OptionsMoM = set_default_option(OptionsMoM,'lyapunov_doubling_tol',1e-16); % convergence criterion used in the doubling algorithm
OptionsMoM = set_default_option(OptionsMoM,'sylvester_fp',false); % determines whether to use fixed point algorihtm to solve Sylvester equation (gensylv_fp), faster for large scale models
OptionsMoM = set_default_option(OptionsMoM,'sylvester_fixed_point_tol',1e-12); % convergence criterion used in the fixed point Sylvester solver
OptionsMoM = set_default_option(OptionsMoM,'qz_criterium',1-1e-6); % value used to split stable from unstable eigenvalues in reordering the Generalized Schur decomposition used for solving first order problems [IS THIS CORRET @wmutschl]
OptionsMoM = set_default_option(OptionsMoM,'qz_zero_threshold',1e-6); % value used to test if a generalized eigenvalue is 0/0 in the generalized Schur decomposition
% -------------------------------------------------------------------------
% Step 1b: Options that are set by the preprocessor and (probably) need to be carried over
% -------------------------------------------------------------------------
% options related to VAROBS
if ~isfield(DynareOptions,'varobs')
error('method_of_moments: VAROBS statement is missing!')
else
OptionsMoM.varobs = DynareOptions.varobs; % observable variables in declaration order
OptionsMoM.obs_nbr = length(OptionsMoM.varobs);% number of observed variables
% Check that each declared observed variable is also an endogenous variable
for i = 1:OptionsMoM.obs_nbr
if ~any(strcmp(OptionsMoM.varobs{i},Model.endo_names))
error(['method_of_moments: Unknown variable (' OptionsMoM.varobs{i} ')!'])
end
end
% Check that a variable is not declared as observed more than once.
if length(unique(OptionsMoM.varobs))<length(OptionsMoM.varobs)
for i = 1:OptionsMoM.obs_nbr
if sum(strcmp(OptionsMoM.varobs{i},OptionsMoM.varobs))>1
error(['method_of_moments: A variable cannot be declared as observed more than once (' OptionsMoM.varobs{i} ')!'])
end
end
end
end
% options related to variable declarations
if ~isfield(DynareOptions,'trend_coeffs')
%BayesInfo.with_trend = 0;
else
error('method_of_moments: %s does not allow for trend in data',OptionsMoM.mom_method)
end
% options related to estimated_params and estimated_params_init
OptionsMoM.use_calibration_initialization = DynareOptions.use_calibration_initialization;
% options related to model; block
OptionsMoM.linear = DynareOptions.linear;
OptionsMoM.use_dll = DynareOptions.use_dll;
OptionsMoM.block = DynareOptions.block;
OptionsMoM.bytecode = DynareOptions.bytecode;
% options related to steady; command
OptionsMoM.homotopy_force_continue = DynareOptions.homotopy_force_continue;
OptionsMoM.homotopy_mode = DynareOptions.homotopy_mode;
OptionsMoM.homotopy_steps = DynareOptions.homotopy_steps;
OptionsMoM.logged_steady_state = DynareOptions.logged_steady_state; % @wmutschl: when and how does this get set?
OptionsMoM.markowitz = DynareOptions.markowitz;
OptionsMoM.solve_algo = DynareOptions.solve_algo;
OptionsMoM.solve_tolf = DynareOptions.solve_tolf;
OptionsMoM.steady = DynareOptions.steady;
OptionsMoM.steadystate = DynareOptions.steadystate;
OptionsMoM.steadystate_flag = DynareOptions.steadystate_flag;
% options related to dataset
OptionsMoM.dataset = DynareOptions.dataset;
OptionsMoM.initial_period = DynareOptions.initial_period;
% options related to endogenous prior restrictions
OptionsMoM.endogenous_prior_restrictions.irf = {};
OptionsMoM.endogenous_prior_restrictions.moment = {};
if ~isempty(DynareOptions.endogenous_prior_restrictions.irf) && ~isempty(DynareOptions.endogenous_prior_restrictions.moment)
fprintf('Endogenous prior restrictions are not supported yet and will be skipped.\n')
end
% -------------------------------------------------------------------------
% Step 1c: Options related to optimizers
% -------------------------------------------------------------------------
% mode_compute = 2
OptionsMoM.saopt = DynareOptions.saopt;
% mode_compute = 4
OptionsMoM.csminwel = DynareOptions.csminwel;
if OptionsMoM.mode_compute == 4
error('method_of_moments:optimizer','method_of_moments: csminwel optimizer (mode_compute=4) is not yet supported (due to penalized_objective handling).\n Choose a different optimizer, e.g. lsqnonlin (mode_compute=13), fminsearch (mode_compute=7), SolveOpt (mode_compute=101).')
end
% mode_compute = 5 (not yet)
if OptionsMoM.mode_compute == 5
error('method_of_moments:optimizer','method_of_moments: newrat optimizer (mode_compute=5) is not yet supported.\n Choose a different optimizer, e.g. lsqnonlin (mode_compute=13), fminsearch (mode_compute=7), SolveOpt (mode_compute=101).')
end
% mode_compute = 6
if OptionsMoM.mode_compute == 6
error('method_of_moments:optimizer','method_of_moments: mode_compute=6 is not compatible with a method of moments estimation.\n Choose a different optimizer, e.g. lsqnonlin (mode_compute=13), fminsearch (mode_compute=7), SolveOpt (mode_compute=101).')
end
% mode_compute = 8
OptionsMoM.simplex = DynareOptions.simplex;
% mode_compute = 9
OptionsMoM.cmaes = DynareOptions.cmaes;
% mode_compute = 10
OptionsMoM.simpsa = DynareOptions.simpsa;
% mode_compute = 11
if OptionsMoM.mode_compute == 11
error('method_of_moments:optimizer','method_of_moments: mode_compute=11 is not compatible with a method of moments estimation.\n Choose a different optimizer, e.g. lsqnonlin (mode_compute=13), fminsearch (mode_compute=7), SolveOpt (mode_compute=101).')
end
% mode_compute = 12
OptionsMoM.particleswarm = DynareOptions.particleswarm;
if OptionsMoM.mode_compute == 12
error('method_of_moments:optimizer','method_of_moments: mode_compute=12 is not yet supported (due to penalized_objective handling).\n Choose a different optimizer, e.g. lsqnonlin (mode_compute=13), fminsearch (mode_compute=7), SolveOpt (mode_compute=101).')
end
% mode_compute = 101
OptionsMoM.solveopt = DynareOptions.solveopt;
OptionsMoM.gradient_method = DynareOptions.gradient_method;
OptionsMoM.gradient_epsilon = DynareOptions.gradient_epsilon;
% -------------------------------------------------------------------------
% Step 1d: Other options that need to be initialized
% -------------------------------------------------------------------------
OptionsMoM.initialize_estimated_parameters_with_the_prior_mode = 0; % needed by set_prior.m
OptionsMoM.figures.textwidth = 0.8; %needed by plot_priors.m
OptionsMoM.ramsey_policy = 0; % needed by evaluate_steady_state
OptionsMoM.debug = false; %needed by resol.m
OptionsMoM.risky_steadystate = false; %needed by resol
OptionsMoM.threads = DynareOptions.threads; %needed by resol
OptionsMoM.jacobian_flag = true;
OptionsMoM.gstep = DynareOptions.gstep;
OptionsMoM.solve_tolf = DynareOptions.solve_tolf;
OptionsMoM.solve_tolx = DynareOptions.solve_tolx;
% options_mom.dsge_var = false; %needed by check_list_of_variables
% options_mom.bayesian_irf = false; %needed by check_list_of_variables
% options_mom.moments_varendo = false; %needed by check_list_of_variables
% options_mom.smoother = false; %needed by check_list_of_variables
% options_mom.filter_step_ahead = []; %needed by check_list_of_variables
% options_mom.forecast = 0;
%OptionsMoM = set_default_option(OptionsMoM,'endo_vars_for_moment_computations_in_estimation',[]);
% -------------------------------------------------------------------------
% Step 1e: Get variable orderings and state space representation
% -------------------------------------------------------------------------
DynareResults.dr = set_state_space(DynareResults.dr,Model,OptionsMoM);
% Get index of observed variables in DR order
DynareResults.dr.obs_var = [];
for i=1:OptionsMoM.obs_nbr
DynareResults.dr.obs_var = [DynareResults.dr.obs_var; find(strcmp(OptionsMoM.varobs{i}, Model.endo_names(DynareResults.dr.order_var)))];
end
% -------------------------------------------------------------------------
% Step 2: Checks and transformations for matched moments structure (preliminary)
% -------------------------------------------------------------------------
% Note that we do not have a preprocessor interface yet for this, so this
% will need much improvement later on. @wmutschl
if strcmp(OptionsMoM.mom_method, 'GMM')
% Initialize indices
OptionsMoM.index.E_y = false(OptionsMoM.obs_nbr,1); %unconditional first order product moments
OptionsMoM.index.E_yy = false(OptionsMoM.obs_nbr,OptionsMoM.obs_nbr); %unconditional second order product moments
OptionsMoM.index.E_yyt = false(OptionsMoM.obs_nbr,OptionsMoM.obs_nbr,0); %unconditional temporal second order product moments
OptionsMoM.index.E_y_pos = zeros(OptionsMoM.obs_nbr,1); %position in matched moments block
OptionsMoM.index.E_yy_pos = zeros(OptionsMoM.obs_nbr,OptionsMoM.obs_nbr); %position in matched moments block
OptionsMoM.index.E_yyt_pos = zeros(OptionsMoM.obs_nbr,OptionsMoM.obs_nbr,0); %position in matched moments block
end
for jm=1:size(MatchedMoments,1)
% higher-order product moments not supported yet for GMM
if strcmp(OptionsMoM.mom_method, 'GMM') && sum(MatchedMoments{jm,3}) > 2
error('method_of_moments: GMM does not yet support product moments higher than 2. Change row %d in ''matched_moments'' block.',jm);
end
% Check if declared variables are also observed (needed as otherwise the dataset variables won't coincide)
if any(~ismember(DynareResults.dr.inv_order_var(MatchedMoments{jm,1})', DynareResults.dr.obs_var))
error('method_of_moments: Variables in row %d in ''matched_moments'' block need to be declared as VAROBS.', jm)
end
if strcmp(OptionsMoM.mom_method, 'GMM')
% Check (for now) that only lags are declared
if any(MatchedMoments{jm,2}>0)
error('method_of_moments: Leads in row %d in the ''matched_moments'' block are not supported for GMM, shift the moments and declare only lags.', jm)
end
% Check (for now) that first declared variable has zero lag
if MatchedMoments{jm,2}(1)~=0
error('method_of_moments: The first variable declared in row %d in the ''matched_moments'' block is not allowed to have a lead or lag for GMM;\n reorder the variables in the row such that the first variable has zero lag!',jm)
end
vars = DynareResults.dr.inv_order_var(MatchedMoments{jm,1})';
if sum(MatchedMoments{jm,3}) == 1
% First-order product moment
vpos = (DynareResults.dr.obs_var == vars);
OptionsMoM.index.E_y(vpos,1) = true;
OptionsMoM.index.E_y_pos(vpos,1) = jm;
elseif sum(MatchedMoments{jm,3}) == 2
% Second-order product moment
idx1 = (DynareResults.dr.obs_var == vars(1));
idx2 = (DynareResults.dr.obs_var == vars(2));
lag1 = MatchedMoments{jm,2}(1);
lag2 = MatchedMoments{jm,2}(2);
if lag1==0 && lag2==0 % contemporenous covariance matrix
OptionsMoM.index.E_yy(idx1,idx2) = true;
OptionsMoM.index.E_yy(idx2,idx1) = true;
OptionsMoM.index.E_yy_pos(idx1,idx2) = jm;
OptionsMoM.index.E_yy_pos(idx2,idx1) = jm;
elseif lag1==0 && lag2 < 0
OptionsMoM.index.E_yyt(idx1,idx2,-lag2) = true;
OptionsMoM.index.E_yyt_pos(idx1,idx2,-lag2) = jm;
end
end
end
end
% @wmutschl: add check for duplicate moments by using the cellfun and unique functions
if strcmp(OptionsMoM.mom_method,'GMM')
%Remove duplicate elements
UniqueMomIdx = [nonzeros(OptionsMoM.index.E_y_pos); nonzeros(triu(OptionsMoM.index.E_yy_pos)); nonzeros(OptionsMoM.index.E_yyt_pos)];
DuplicateMoms = setdiff(1:size(MatchedMoments,1),UniqueMomIdx);
if ~isempty(DuplicateMoms)
fprintf('Found and removed duplicate declared moments in ''matched_moments'' block in rows: %s.\n',num2str(DuplicateMoms))
end
%reorder MatchedMoments to be compatible with OptionsMoM.index
MatchedMoments = MatchedMoments(UniqueMomIdx,:);
else
fprintf('For SMM we do not check yet for duplicate moment declarations in ''matched_moments'' block. You need to check this manually.\n\n')
end
% Check if both prefilter and first moments were specified
OptionsMoM.first_moment_indicator = find(cellfun(@(x) sum(abs(x))==1,MatchedMoments(:,3)))';
if OptionsMoM.prefilter && ~isempty(OptionsMoM.first_moment_indicator)
fprintf('Centered moments requested (prefilter option is set); therefore, ignore declared first moments in ''matched_moments'' block in rows: %s.\n',num2str(OptionsMoM.index.E_y_pos'));
MatchedMoments = MatchedMoments(OptionsMoM.first_moment_indicator,:); %remove first moments entries
OptionsMoM.first_moment_indicator = [];
end
OptionsMoM.mom_nbr = size(MatchedMoments,1);
% Get maximum lag number for autocovariances/autocorrelations
OptionsMoM.ar = max(cellfun(@max,MatchedMoments(:,2))) - min(cellfun(@min,MatchedMoments(:,2)));
% -------------------------------------------------------------------------
% Step 3: Checks and transformations for estimated parameters, priors, and bounds
% -------------------------------------------------------------------------
% Set priors over the estimated parameters
if ~isempty(EstimatedParameters) && ~(isfield(EstimatedParameters,'nvx') && (size(EstimatedParameters.var_exo,1)+size(EstimatedParameters.var_endo,1)+size(EstimatedParameters.corrx,1)+size(EstimatedParameters.corrn,1)+size(EstimatedParameters.param_vals,1))==0)
[xparam0, EstimatedParameters, BayesInfo, lb, ub, Model] = set_prior(EstimatedParameters, Model, OptionsMoM);
end
% Check measurement errors
if EstimatedParameters.nvn || EstimatedParameters.ncn
error('method_of_moments: moment estimation does not support measurement error(s) yet. Please specifiy them as a structural shock.')
end
% Check if a _prior_restrictions.m file exists
if exist([Model.fname '_prior_restrictions.m'])
OptionsMoM.prior_restrictions.status = 1;
OptionsMoM.prior_restrictions.routine = str2func([Model.fname '_prior_restrictions']);
end
% Check on specified priors and penalized estimation
if ~isempty(EstimatedParameters) && ~(isfield(EstimatedParameters,'nvx') && (size(EstimatedParameters.var_exo,1)+size(EstimatedParameters.var_endo,1)+size(EstimatedParameters.corrx,1)+size(EstimatedParameters.corrn,1)+size(EstimatedParameters.param_vals,1))==0)
if any(BayesInfo.pshape > 0) % prior specified
if any(setdiff([0;BayesInfo.pshape],[0,3]))
if ~OptionsMoM.penalized_estimator
fprintf('\nPriors were specified, but the penalized_estimator-option was not set.\n')
fprintf('Dynare sets penalized_estimator to 1. Conducting %s with penalty.\n',OptionsMoM.mom_method)
OptionsMoM.penalized_estimator=1;
end
fprintf('\nNon-normal priors specified. %s with penalty uses a Laplace type of approximation.\n',OptionsMoM.mom_method)
fprintf('Only the prior mean and standard deviation are relevant, all other shape information, except for the parameter bounds, is ignored.\n\n')
end
if any(isinf(BayesInfo.p2))
inf_var_pars=BayesInfo.name(isinf(BayesInfo.p2));
disp_string=[inf_var_pars{1,:}];
for ii=2:size(inf_var_pars,1)
disp_string=[disp_string,', ',inf_var_pars{ii,:}];
end
fprintf('The parameter(s) %s have infinite prior variance. This implies a flat prior\n',disp_string)
fprintf('Dynare disables the matrix singularity warning\n')
warning('off','MATLAB:singularMatrix');
end
end
end
if OptionsMoM.penalized_estimator && OptionsMoM.mode_compute==13
error('method_of_moments: Penalized estimator option is not compatible with mode_compute=13. Deactivate penalized_estimator, don''t use priors, or choose a different optimizer.')
end
% Check for calibrated covariances before updating parameters
if ~isempty(EstimatedParameters) && ~(isfield(EstimatedParameters,'nvx') && sum(EstimatedParameters.nvx+EstimatedParameters.nvn+EstimatedParameters.ncx+EstimatedParameters.ncn+EstimatedParameters.np)==0)
EstimatedParameters = check_for_calibrated_covariances(xparam0,EstimatedParameters,Model);
end
% Checks on parameter calibration and initialization
xparam1_calib = get_all_parameters(EstimatedParameters,Model); %get calibrated parameters
if ~any(isnan(xparam1_calib)) %all estimated parameters are calibrated
EstimatedParameters.full_calibration_detected=1;
else
EstimatedParameters.full_calibration_detected=0;
end
if OptionsMoM.use_calibration_initialization %set calibration as starting values
if ~isempty(BayesInfo) && all(BayesInfo.pshape==0) && any(all(isnan([xparam1_calib xparam0]),2))
error('method_of_moments: When using the use_calibration option with %s without prior, the parameters must be properly initialized.',OptionsMoM.mom_method)
else
[xparam0,EstimatedParameters]=do_parameter_initialization(EstimatedParameters,xparam1_calib,xparam0); %get explicitly initialized parameters that have precedence to calibrated values
end
end
% Check on initialization @wmutschl: why without penalty?
if ~isempty(BayesInfo) && all(BayesInfo.pshape==0) && any(isnan(xparam0))
error('method_of_moments: %s without penalty requires all estimated parameters to be initialized, either in an estimated_params or estimated_params_init-block ',OptionsMoM.mom_method)
end
% Set and check parameter bounds
if ~isempty(EstimatedParameters) && ~(all(strcmp(fieldnames(EstimatedParameters),'full_calibration_detected')) || (isfield(EstimatedParameters,'nvx') && sum(EstimatedParameters.nvx+EstimatedParameters.nvn+EstimatedParameters.ncx+EstimatedParameters.ncn+EstimatedParameters.np)==0))
if ~isempty(BayesInfo) && any(BayesInfo.pshape > 0)
% Plot prior densities
if ~OptionsMoM.nograph && OptionsMoM.plot_priors
plot_priors(BayesInfo,Model,EstimatedParameters,OptionsMoM)
end
% Set prior bounds
Bounds = prior_bounds(BayesInfo, OptionsMoM.prior_trunc);
Bounds.lb = max(Bounds.lb,lb);
Bounds.ub = min(Bounds.ub,ub);
else % estimated parameters but no declared priors
% No priors are declared so Dynare will estimate the parameters
% with inequality constraints for the parameters.
Bounds.lb = lb;
Bounds.ub = ub;
end
% Test if initial values of the estimated parameters are all between the prior lower and upper bounds
if OptionsMoM.use_calibration_initialization
try
check_prior_bounds(xparam0,Bounds,Model,EstimatedParameters,OptionsMoM,BayesInfo)
catch
e = lasterror();
fprintf('Cannot use parameter values from calibration as they violate the prior bounds.')
rethrow(e);
end
else
check_prior_bounds(xparam0,Bounds,Model,EstimatedParameters,OptionsMoM,BayesInfo)
end
end
% Check symmetric Sigma_e
Sigma_e_non_zero_rows = find(~all(Model.Sigma_e==0,1));
Sigma_e_non_zero_columns = find(~all(Model.Sigma_e==0,2));
if ~isequal(Sigma_e_non_zero_rows,Sigma_e_non_zero_columns')
error('method_of_moments: Structual error matrix not symmetric')
end
if isfield(EstimatedParameters,'var_exo') && ~isempty(EstimatedParameters.var_exo)
EstimatedParameters.Sigma_e_entries_to_check_for_positive_definiteness = union(Sigma_e_non_zero_rows,EstimatedParameters.var_exo(:,1));
else
EstimatedParameters.Sigma_e_entries_to_check_for_positive_definiteness = Sigma_e_non_zero_rows;
end
% Set sigma_e_is_diagonal flag (needed if the shocks block is not declared in the mod file).
Model.sigma_e_is_diagonal = true;
if EstimatedParameters.ncx || any(nnz(tril(Model.Correlation_matrix,-1))) || isfield(EstimatedParameters,'calibrated_covariances')
Model.sigma_e_is_diagonal = false;
end
% Provide some warnings on standard errors and correlations of shocks
if any(BayesInfo.pshape)
if EstimatedParameters.nvx && any(BayesInfo.p3(1:EstimatedParameters.nvx)<0)
warning('Your prior allows for negative standard deviations for structural shocks. It is recommended to change your prior.')
end
offset=EstimatedParameters.nvx;
if EstimatedParameters.nvn && any(BayesInfo.p3(1+offset:offset+EstimatedParameters.nvn)<0)
warning('Your prior allows for negative standard deviations for measurement error. It is recommended to change your prior.')
end
offset = EstimatedParameters.nvx+EstimatedParameters.nvn;
if EstimatedParameters.ncx && (any(BayesInfo.p3(1+offset:offset+EstimatedParameters.ncx)<-1) || any(BayesInfo.p4(1+offset:offset+EstimatedParameters.ncx)>1))
warning('Your prior allows for correlations between structural shocks larger than +-1 and will not integrate to 1 due to truncation. Please change your prior')
end
offset = EstimatedParameters.nvx+EstimatedParameters.nvn+EstimatedParameters.ncx;
if EstimatedParameters.ncn && (any(BayesInfo.p3(1+offset:offset+EstimatedParameters.ncn)<-1) || any(BayesInfo.p4(1+offset:offset+EstimatedParameters.ncn)>1))
warning('Your prior allows for correlations between measurement errors larger than +-1 and will not integrate to 1 due to truncation. Please change your prior')
end
end
% storing prior parameters in MoM info structure for penalized minimization
DynareResults.prior.pnames = {''; 'beta'; 'gamm'; 'norm'; 'invg'; 'unif'; 'invg2'; ''; 'weibl'};
DynareResults.prior.p1 = BayesInfo.p1;
DynareResults.prior.p2 = BayesInfo.p2;
% DynareResults.prior.mode = BayesInfo.p5;
% DynareResults.prior.variance = diag(BayesInfo.p2.^2);
% DynareResults.prior.hyperparameters.first = BayesInfo.p6;
% DynareResults.prior.hyperparameters.second = BayesInfo.p7;
% Set all parameters
Model = set_all_parameters(xparam0,EstimatedParameters,Model);
% -------------------------------------------------------------------------
% Step 4: Checks and transformations for data
% -------------------------------------------------------------------------
% Check if datafile has same name as mod file
if ~isempty(OptionsMoM.datafile)
[~,name,~] = fileparts(OptionsMoM.datafile);
if strcmp(name,Model.fname)
error('method_of_moments: Data-file and mod-file are not allowed to have the same name. Please change the name of the data file.')
end
end
% Build dataset
[DynareDataset, ~, ~] = makedataset(OptionsMoM);
% set options for old interface from the ones for new interface
if ~isempty(DynareDataset)
OptionsMoM.nobs = DynareDataset.nobs;
end
% missing observations are not supported yet
if any(any(isnan(DynareDataset.data)))
error('method_of_moments: missing observations are not supported')
end
% Check length of data for estimation of second moments
if OptionsMoM.ar > OptionsMoM.nobs+1
error('method_of_moments: Data set is too short to compute second moments');
end
% Get data moments for the method of moments
[DynareResults.mom.dataMoments, DynareResults.mom.m_data] = method_of_moments_datamoments(DynareDataset.data, DynareResults, MatchedMoments, OptionsMoM);
if OptionsMoM.prefilter
if sum(abs(DynareDataset.mean))/DynareDataset.nobs >1e-9
fprintf('The mean of the data is:\n')
disp(DynareDataset.mean);
error('method_of_moments: You are trying to perform a method of moments estimation with centered moments (prefilter=1) using uncentered data.')
end
elseif ~isempty(OptionsMoM.first_moment_indicator)
if sum(abs(DynareResults.mom.dataMoments(OptionsMoM.first_moment_indicator)))/sum(OptionsMoM.first_moment_indicator) <1e-2
fprintf('The mean of the data for which Dynare tries to match first moments is:\n')
disp(DynareResults.mom.dataMoments(OptionsMoM.first_moment_indicator)');
warning('method_of_moments:data_mean_zero','method_of_moments: You are trying to perform a method of moments estimation with uncentered moments (prefilter=0),\n but the data are (almost) mean 0. Check if this is desired.')
end
end
% Get shock series for SMM and set variance correction factor
if strcmp(OptionsMoM.mom_method,'SMM')
OptionsMoM.long = round(OptionsMoM.simulation_multiple*OptionsMoM.nobs);
OptionsMoM.variance_correction_factor = (1+1/OptionsMoM.simulation_multiple);
% draw shocks for SMM
smmstream = RandStream('mt19937ar','Seed',OptionsMoM.seed);
temp_shocks = randn(smmstream,OptionsMoM.long+OptionsMoM.drop,Model.exo_nbr);
if OptionsMoM.bounded_shock_support == 1
temp_shocks(temp_shocks>2) = 2;
temp_shocks(temp_shocks<-2) = -2;
end
OptionsMoM.shock_series = temp_shocks;
end
% -------------------------------------------------------------------------
% Step 5: checks for steady state at initial parameters
% -------------------------------------------------------------------------
% Check for logged steady state ...is this necessary @wmutschl
if OptionsMoM.logged_steady_state
DynareResults.dr.ys=exp(DynareResults.dr.ys);
DynareResults.steady_state=exp(DynareResults.steady_state);
OptionsMoM.logged_steady_state=0;
end
% setting steadystate_check_flag option
if OptionsMoM.steadystate.nocheck
steadystate_check_flag = 0;
else
steadystate_check_flag = 1;
end
% Check steady state at initial model parameter values
[DynareResults.steady_state, params, info] = evaluate_steady_state(DynareResults.steady_state,Model,OptionsMoM,DynareResults,steadystate_check_flag);
if info(1)
fprintf('\nmethod_of_moments: The steady state at the initial parameters cannot be computed.\n')
print_info(info, 0, OptionsMoM);
end
try
% check if steady state solves static model
[DynareResults.steady_state, new_steady_params] = evaluate_steady_state(DynareResults.steady_state,Model,OptionsMoM,DynareResults,1);
% check whether steady state file changes estimated parameters
if isfield(EstimatedParameters,'param_vals') && ~isempty(EstimatedParameters.param_vals)
Model0=Model; %store Model structure
old_steady_params=Model.params; %save initial parameters for check if steady state changes param values
Model0.params(EstimatedParameters.param_vals(:,1))=Model0.params(EstimatedParameters.param_vals(:,1))*1.01; %vary parameters
[~, new_steady_params_2] = evaluate_steady_state(DynareResults.steady_state,Model0,OptionsMoM,DynareResults,1);
changed_par_indices=find((old_steady_params(EstimatedParameters.param_vals(:,1))-new_steady_params(EstimatedParameters.param_vals(:,1))) ...
| (Model0.params(EstimatedParameters.param_vals(:,1))-new_steady_params_2(EstimatedParameters.param_vals(:,1))));
if ~isempty(changed_par_indices)
fprintf('\nThe steady state file internally changed the values of the following estimated parameters:\n')
disp(char(Model.param_names(EstimatedParameters.param_vals(changed_par_indices,1))))
fprintf('This will override parameter values and may lead to wrong results.\n')
fprintf('Check whether this is really intended.\n')
warning('The steady state file internally changes the values of the estimated parameters.')
end
end
% display warning if some parameters are still NaN
test_for_deep_parameters_calibration(Model);
catch % if check fails, provide info on using calibration if present
e = lasterror();
if EstimatedParameters.full_calibration_detected %calibrated model present and no explicit starting values
skipline(1);
fprintf('There was an error in computing the moments for initial parameter values.\n')
fprintf('If this is not a problem with the setting of options (check the error message below),\n')
fprintf('you should try using the calibrated version of the model as starting values. To do\n')
fprintf('this, add an empty estimated_params_init-block with use_calibration option immediately before the estimation\n')
fprintf('command (and after the estimated_params-block so that it does not get overwritten):\n');
skipline(2);
end
rethrow(e);
end
% If steady state of observed variables is non zero, set noconstant equal 0
if (~OptionsMoM.loglinear && all(abs(DynareResults.steady_state(DynareResults.dr.order_var(DynareResults.dr.obs_var)))<1e-9)) || (OptionsMoM.loglinear && all(abs(log(DynareResults.steady_state(DynareResults.dr.order_var(DynareResults.dr.obs_var))))<1e-9))
OptionsMoM.noconstant = 1;
else
OptionsMoM.noconstant = 0;
% If the data are prefiltered then there must not be constants in the
% measurement equation of the DSGE model
if OptionsMoM.prefilter
skipline()
disp('You have specified the option "prefilter" to demean your data but the')
disp('steady state of of the observed variables is non zero.')
disp('Either change the measurement equations, by centering the observed')
disp('variables in the model block, or drop the prefiltering.')
error('method_of_moments: The option ''prefilter'' is inconsistent with the non-zero mean measurement equations in the model.')
end
end
% -------------------------------------------------------------------------
% Step 6: checks for objective function at initial parameters
% -------------------------------------------------------------------------
try
% Check for NaN or complex values of moment-distance-funtion evaluated
% at initial parameters and identity weighting matrix
DynareResults.mom.Sw = eye(OptionsMoM.mom_nbr);
tic_id = tic;
[fval, info, exit_flag, DynareResults, Model, OptionsMoM] = feval(objective_function, xparam0, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM);
if OptionsMoM.mode_compute == 13
fval = fval'*fval;
end
elapsed_time = toc(tic_id);
if isnan(fval)
error('method_of_moments: The initial value of the target function is NaN')
elseif imag(fval)
error('method_of_moments: The initial value of the target function is complex')
end
if info(1) > 0
disp('method_of_moments: Error in computing the target function for initial parameter values')
print_info(info, OptionsMoM.noprint, OptionsMoM)
end
if OptionsMoM.prefilter==1
if (~OptionsMoM.loglinear && any(abs(DynareResults.steady_state(DynareResults.dr.order_var(DynareResults.dr.obs_var)))>1e-9)) || (OptionsMoM.loglinear && any(abs(log(DynareResults.steady_state(DynareResults.dr.order_var(DynareResults.dr.obs_var))))>1e-9))
disp(['You are trying to estimate a model with a non zero steady state for the observed endogenous'])
disp(['variables using demeaned data!'])
error('method_of_moments: You should change something in your mod file...')
end
end
fprintf('Initial value of the moment objective function with identity weighting matrix: %6.4f \n\n', fval);
fprintf('Time required to compute target function once: %5.4f seconds \n', elapsed_time);
catch % if check fails, provide info on using calibration if present
e = lasterror();
if EstimatedParameters.full_calibration_detected %calibrated model present and no explicit starting values
skipline(1);
fprintf('There was an error in computing the moments for initial parameter values.\n')
fprintf('If this is not a problem with the setting of options (check the error message below),\n')
fprintf('you should try using the calibrated version of the model as starting values. To do\n')
fprintf('this, add an empty estimated_params_init-block with use_calibration option immediately before the estimation\n')
fprintf('command (and after the estimated_params-block so that it does not get overwritten):\n');
skipline(2);
end
rethrow(e);
end
if OptionsMoM.mode_compute == 0 %We only report value of moments distance at initial value of the parameters
fprintf('no minimization of moments distance due to ''mode_compute=0''\n')
return
end
% -------------------------------------------------------------------------
% Step 7a: Method of moments estimation: print some info
% -------------------------------------------------------------------------
fprintf('\n---------------------------------------------------\n')
if strcmp(OptionsMoM.mom_method,'SMM')
fprintf('Simulated method of moments with');
elseif strcmp(OptionsMoM.mom_method,'GMM')
fprintf('General method of moments with');
end
if OptionsMoM.prefilter
fprintf('\n - centered moments (prefilter=1)');
else
fprintf('\n - uncentered moments (prefilter=0)');
end
if OptionsMoM.penalized_estimator
fprintf('\n - penalized estimation using priors');
end
if OptionsMoM.mode_compute == 1; fprintf('\n - optimizer (mode_compute=1): fmincon');
elseif OptionsMoM.mode_compute == 2; fprintf('\n - optimizer (mode_compute=2): continuous simulated annealing');
elseif OptionsMoM.mode_compute == 3; fprintf('\n - optimizer (mode_compute=3): fminunc');
elseif OptionsMoM.mode_compute == 4; fprintf('\n - optimizer (mode_compute=4): csminwel');
elseif OptionsMoM.mode_compute == 7; fprintf('\n - optimizer (mode_compute=7): fminsearch');
elseif OptionsMoM.mode_compute == 8; fprintf('\n - optimizer (mode_compute=8): Dynare Nelder-Mead simplex');
elseif OptionsMoM.mode_compute == 9; fprintf('\n - optimizer (mode_compute=9): CMA-ES');
elseif OptionsMoM.mode_compute == 10; fprintf('\n - optimizer (mode_compute=10): simpsa');
elseif OptionsMoM.mode_compute == 12; fprintf('\n - optimizer (mode_compute=12): particleswarm');
elseif OptionsMoM.mode_compute == 101; fprintf('\n - optimizer (mode_compute=101): SolveOpt');
elseif OptionsMoM.mode_compute == 102; fprintf('\n - optimizer (mode_compute=102): simulannealbnd');
elseif OptionsMoM.mode_compute == 13; fprintf('\n - optimizer (mode_compute=13): lsqnonlin');
end
if OptionsMoM.silent_optimizer
fprintf(' (silent)');
end
fprintf('\n - perturbation order: %d', OptionsMoM.order)
if OptionsMoM.order > 1 && OptionsMoM.pruning
fprintf(' (with pruning)')
end
fprintf('\n - number of matched moments: %d', OptionsMoM.mom_nbr);
fprintf('\n - number of parameters: %d', length(xparam0));
% Check if enough moments for estimation
if OptionsMoM.mom_nbr < length(xparam0)
fprintf('\n');
error('method_of_moments: We must have at least as many moments as parameters for a method of moments estimation.')
end
fprintf('\n\n')
% -------------------------------------------------------------------------
% Step 7b: Method of moments estimation: First-stage
% -------------------------------------------------------------------------
fprintf('First-stage estimation\n');
switch lower(OptionsMoM.weighting_matrix)
case 'identity_matrix'
fprintf(' - identity weighting matrix\n');
DynareResults.mom.Sw = eye(length(DynareResults.mom.dataMoments));
case 'diagonal'
%@wmutschl: better description in fprintf
fprintf(' - diagonal weighting matrix: diagonal of Newey-West estimator with lag order %d\n', OptionsMoM.bartlett_kernel_lag);
fprintf(' and data moments as estimate of unconditional moments\n');
Wopt = method_of_moments_optimal_weighting_matrix(DynareResults.mom.m_data, DynareResults.mom.dataMoments, OptionsMoM.bartlett_kernel_lag);
DynareResults.mom.Sw = chol(diag(diag(Wopt)));
case 'optimal'
%@wmutschl: better description in fprintf
fprintf(' - weighting matrix: optimal. At first-stage we use diagonal of Newey-West estimator with lag order %d\n', OptionsMoM.bartlett_kernel_lag);
fprintf(' and the data moments as initial estimate of unconditional moments\n');
Wopt = method_of_moments_optimal_weighting_matrix(DynareResults.mom.m_data, DynareResults.mom.dataMoments, OptionsMoM.bartlett_kernel_lag);
DynareResults.mom.Sw = chol(diag(diag(Wopt)));
otherwise %user specified matrix in file
fprintf(' - weighting matrix: user-specified\n');
try
load(OptionsMoM.weighting_matrix,'weighting_matrix')
catch
error(['method_of_moments: No matrix named ''weighting_matrix'' could be found in ',OptionsMoM.weighting_matrix,'.mat'])
end
[nrow, ncol] = size(weighting_matrix);
if ~isequal(nrow,ncol) && ~isequal(nrow,length(DynareResults.mom.dataMoments)) %check if square and right size
error(['method_of_moments: weighting_matrix must be square and have ',num2str(length(DynareResults.mom.dataMoments)),' rows and columns'])
end
try %check for positive definiteness
DynareResults.Sw = chol(weighting_matrix);
hsd = sqrt(diag(weighting_matrix));
inv(weighting_matrix./(hsd*hsd'))./(hsd*hsd');
catch
error('method_of_moments: Specified weighting_matrix is not positive definite')
end
end
Woptflag = 0;
xparam1 = xparam0;
for istep1 = 1:2
[xparam1, fval, exitflag, hessian_mat, OptionsMoM] = dynare_minimize_objective(objective_function, xparam1, OptionsMoM.mode_compute, OptionsMoM, [Bounds.lb Bounds.ub], BayesInfo.name, BayesInfo, [],...
Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM);
if OptionsMoM.mode_compute == 13
fval = fval'*fval;
end
fprintf('\nIteration %d value of minimized moment''s distance target function: %f.\n',istep1,fval)
if OptionsMoM.verbose
DynareResults.mom=display_estimation_results_table(xparam1,NaN(size(xparam1)),Model,OptionsMoM,EstimatedParameters,BayesInfo,DynareResults.mom,DynareResults.prior.pnames,sprintf('%s (FIRST-STAGE ITERATION %d) verbose',OptionsMoM.mom_method,istep1),sprintf('verbose_%s_1st_stage_iter_%d',lower(OptionsMoM.mom_method),istep1));
end
end
% Update Model and DynareResults (in particular DynareResults.mom.modelMoments)
Model = set_all_parameters(xparam1,EstimatedParameters,Model);
[fval, ~, ~, DynareResults, ~, ~] = feval(objective_function, xparam1, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM);
if OptionsMoM.mode_compute == 13
fval = fval'*fval;
end
% Compute Standard errors
SE_1 = method_of_moments_standard_errors(xparam1, objective_function, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM, Woptflag);
% Store first-stage results in output structure
DynareResults.mom = display_estimation_results_table(xparam1,SE_1,Model,OptionsMoM,EstimatedParameters,BayesInfo,DynareResults.mom,DynareResults.prior.pnames,sprintf('%s (FIRST-STAGE)',OptionsMoM.mom_method),sprintf('%s_1st_stage',lower(OptionsMoM.mom_method)));
% -------------------------------------------------------------------------
% Step 7c: Method of moments estimation: Second-stage
% -------------------------------------------------------------------------
fprintf('Second-stage estimation\n');
switch lower(OptionsMoM.weighting_matrix)
case 'identity_matrix'
fprintf(' - weighting matrix: identity\n');
DynareResults.mom.Sw = eye(length(DynareResults.mom.dataMoments));
case 'diagonal'
fprintf(' - weighting matrix: diagonal of Newey-West estimator with lag order %d\n', OptionsMoM.bartlett_kernel_lag);
fprintf(' and based on first-stage estimate of unconditional model moments\n');
Wopt = method_of_moments_optimal_weighting_matrix(DynareResults.mom.m_data, DynareResults.mom.modelMoments, OptionsMoM.bartlett_kernel_lag);
DynareResults.mom.Sw = chol(diag(diag(Wopt)));
case 'optimal'
fprintf(' - weighting matrix: Newey-West estimator with lag order %d\n', OptionsMoM.bartlett_kernel_lag);
fprintf(' and based on first-stage estimate of unconditional model moments\n');
Wopt = method_of_moments_optimal_weighting_matrix(DynareResults.mom.m_data, DynareResults.mom.modelMoments, OptionsMoM.bartlett_kernel_lag);
DynareResults.mom.Sw = chol(Wopt);
Woptflag = 1;
fprintf(' rank of optimal weighting matrix: %d\n',rank(Wopt));
otherwise %keep user specified matrix in file
fprintf(' - weighting matrix: user-specified\n');
end
xparam2 = xparam1;
for istep2 = 1:2
[xparam2, fval, exitflag, hessian_mat, OptionsMoM] = dynare_minimize_objective(objective_function, xparam2, OptionsMoM.mode_compute, OptionsMoM, [Bounds.lb Bounds.ub], BayesInfo.name, BayesInfo, [],...
Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM);
if OptionsMoM.mode_compute == 13
fval = fval'*fval;
end
fprintf('\n - iteration %d value of minimized moment''s distance target function: %f.\n',istep2,fval)
if OptionsMoM.verbose
DynareResults.mom=display_estimation_results_table(xparam2,NaN(size(xparam2)),Model,OptionsMoM,EstimatedParameters,BayesInfo,DynareResults.mom,DynareResults.prior.pnames,sprintf('%s (SECOND-STAGE ITERATION %d) verbose',OptionsMoM.mom_method,istep2),sprintf('verbose_%s_2nd_stage_iter_%d',lower(OptionsMoM.mom_method),istep2));
end
end
% Update Model and DynareResults (in particular DynareResults.mom.modelMoments)
Model = set_all_parameters(xparam2,EstimatedParameters,Model);
[fval, ~, ~, DynareResults, ~, ~] = feval(objective_function, xparam2, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM);
if OptionsMoM.mode_compute == 13
fval = fval'*fval;
end
% Compute Standard errors
SE_2 = method_of_moments_standard_errors(xparam2, objective_function, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM, Woptflag);
% Store second-stage results in output structure
DynareResults.mom = display_estimation_results_table(xparam2,SE_2,Model,OptionsMoM,EstimatedParameters,BayesInfo,DynareResults.mom,DynareResults.prior.pnames,sprintf('%s (SECOND-STAGE)',OptionsMoM.mom_method),sprintf('%s_2nd_stage',lower(OptionsMoM.mom_method)));
% Compute J statistic
if strcmp(OptionsMoM.mom_method,'SMM')
Variance_correction_factor = OptionsMoM.variance_correction_factor;
elseif strcmp(OptionsMoM.mom_method,'GMM')
Variance_correction_factor=1;
end
DynareResults.mom.J_test.j_stat = DynareDataset.nobs*Variance_correction_factor*fval;
DynareResults.mom.J_test.degrees_freedom = length(DynareResults.mom.modelMoments)-length(xparam2);
DynareResults.mom.J_test.p_val = 1-chi2cdf(DynareResults.mom.J_test.j_stat, DynareResults.mom.J_test.degrees_freedom);
fprintf('\n p-value of J-test: %f\n',DynareResults.mom.J_test.p_val)
fprintf('\n==== Method of Moments Estimation Completed ====\n\n')
% -------------------------------------------------------------------------
% Step 8: Clean up
% -------------------------------------------------------------------------
% restore warnings
warning('on','MATLAB:singularMatrix');

View File

@ -0,0 +1,224 @@
function [fval, info, exit_flag, DynareResults, Model, OptionsMoM] = method_of_moments_GMM(xparam1, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM)
% [fval, info, exit_flag, DynareResults, Model, OptionsMoM] = method_of_moments_GMM(xparam1, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM)
% -------------------------------------------------------------------------
% This function evaluates the objective function for GMM estimation
% =========================================================================
% INPUTS
% o xparam1: current value of estimated parameters as returned by set_prior()
% o Bounds: structure containing parameter bounds
% o DynareResults: structure for results (oo_)
% o EstimatedParameters: structure describing the estimated_parameters (estim_params_)
% o MatchedMoments: structure containing information about selected moments to match in estimation (matched_moments_)
% o Model structure describing the Model
% o OptionsMoM: structure information about all settings (specified by the user, preprocessor, and taken from global options_)
% -------------------------------------------------------------------------
% OUTPUTS
% o fval: value of the quadratic form of the moment difference (except for lsqnonlin, where this is done implicitly)
% o info: vector storing error code and penalty
% o exit_flag: 0 if no error, 1 of error
% o DynareResults: structure containing the results with the following updated fields:
% - mom.modelMoments [numMom x 1] vector with model moments
% - mom.Q value of the quadratic form of the moment difference
% o Model: Matlab's structure describing the Model
% -------------------------------------------------------------------------
% This function is called by
% o driver.m
% -------------------------------------------------------------------------
% This function calls
% o ispd
% o pruned_state_space_system
% o resol
% o set_all_parameters
% =========================================================================
% Copyright (C) 2020 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
% Author(s):
% o Willi Mutschler (willi@mutschler.eu)
% o Johannes Pfeifer (jpfeifer@uni-koeln.de)
% =========================================================================
% To Do: check penalized estimation for different optimizers, what is special about mode_compute=1 [@wmutschl]
%--------------------------------------------------------------------------
% 0. Initialization of the returned variables and others...
%--------------------------------------------------------------------------
exit_flag = 1;
info = zeros(4,1);
xparam1 = xparam1(:); % Ensure that xparam1 is a column vector
%--------------------------------------------------------------------------
% 1. Get the structural parameters & define penalties
%--------------------------------------------------------------------------
% Return, with endogenous penalty, if some parameters are smaller than the lower bound of the parameters.
if any(xparam1<Bounds.lb)
if ~isequal(OptionsMoM.mode_compute,1)
k = find(xparam1<Bounds.lb);
fval = Inf;
exit_flag = 0;
info(1) = 41;
info(4)= sum((Bounds.lb(k)-xparam1(k)).^2);
return
elseif OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
return
end
end
% Return, with endogenous penalty, if some parameters are greater than the upper bound of the parameters.
if any(xparam1>Bounds.ub)
if ~isequal(OptionsMoM.mode_compute,1)
k = find(xparam1>Bounds.ub);
fval = Inf;
exit_flag = 0;
info(1) = 42;
info(4)= sum((xparam1(k)-Bounds.ub(k)).^2);
return
elseif OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
return
end
end
% Set all parameters
Model = set_all_parameters(xparam1,EstimatedParameters,Model);
% Test if Q is positive definite.
if ~issquare(Model.Sigma_e) || EstimatedParameters.ncx || isfield(EstimatedParameters,'calibrated_covariances')
[Q_is_positive_definite, penalty] = ispd(Model.Sigma_e(EstimatedParameters.Sigma_e_entries_to_check_for_positive_definiteness,EstimatedParameters.Sigma_e_entries_to_check_for_positive_definiteness));
if ~Q_is_positive_definite
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
else
fval = Inf;
exit_flag = 0;
info(1) = 43;
info(4) = penalty;
end
return
end
if isfield(EstimatedParameters,'calibrated_covariances')
correct_flag=check_consistency_covariances(Model.Sigma_e);
if ~correct_flag
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
else
penalty = sum(Model.Sigma_e(EstimatedParameters.calibrated_covariances.position).^2);
fval = Inf;
exit_flag = 0;
info(1) = 71;
info(4) = penalty;
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
end
end
return
end
end
end
%--------------------------------------------------------------------------
% 2. call resol to compute steady state and model solution
%--------------------------------------------------------------------------
% Compute linear approximation around the deterministic steady state
[dr, info, Model, OptionsMoM, DynareResults] = resol(0, Model, OptionsMoM, DynareResults);
% Return, with endogenous penalty when possible, if resol issues an error code
if info(1)
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
return
else
if info(1) == 3 || info(1) == 4 || info(1) == 5 || info(1)==6 ||info(1) == 19 ||...
info(1) == 20 || info(1) == 21 || info(1) == 23 || info(1) == 26 || ...
info(1) == 81 || info(1) == 84 || info(1) == 85 || info(1) == 86
%meaningful second entry of output that can be used
fval = Inf;
info(4) = info(2);
exit_flag = 0;
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
end
return
else
fval = Inf;
info(4) = 0.1;
exit_flag = 0;
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
end
return
end
end
end
%--------------------------------------------------------------------------
% 3. Set up pruned state-space system and compute model moments
%--------------------------------------------------------------------------
pruned_state_space = pruned_state_space_system(Model, OptionsMoM, dr, DynareResults.dr.obs_var, OptionsMoM.ar, 0, 0);
DynareResults.mom.modelMoments = nan(OptionsMoM.mom_nbr,1);
offset = 0;
% First moments
if isfield(OptionsMoM.index,'E_y') && nnz(OptionsMoM.index.E_y) > 0 && ~OptionsMoM.prefilter
E_y = pruned_state_space.E_y;
E_y_nbr = nnz(OptionsMoM.index.E_y);
DynareResults.mom.modelMoments(offset+1:E_y_nbr,1) = E_y(OptionsMoM.index.E_y);
offset = offset + E_y_nbr;
end
% Second moments
if isfield(OptionsMoM.index,'E_yy') && nnz(OptionsMoM.index.E_yy) > 0
if OptionsMoM.prefilter
E_yy = pruned_state_space.Var_y;
else
E_yy = pruned_state_space.Var_y + pruned_state_space.E_y*pruned_state_space.E_y';
end
E_yy_nbr = nnz(triu(OptionsMoM.index.E_yy));
DynareResults.mom.modelMoments(offset+(1:E_yy_nbr),1) = E_yy(triu(OptionsMoM.index.E_yy));
offset = offset + E_yy_nbr;
end
if isfield(OptionsMoM.index,'E_yyt') && nnz(OptionsMoM.index.E_yyt) > 0
if OptionsMoM.prefilter
E_yyt = pruned_state_space.Var_yi;
else
E_yyt = pruned_state_space.Var_yi + repmat(pruned_state_space.E_y*pruned_state_space.E_y',[1 1 size(pruned_state_space.Var_yi,3)]);
end
E_yyt_nbr = nnz(OptionsMoM.index.E_yyt);
DynareResults.mom.modelMoments(offset+(1:E_yyt_nbr),1) = E_yyt(OptionsMoM.index.E_yyt);
end
%--------------------------------------------------------------------------
% 4. Compute quadratic target function
%--------------------------------------------------------------------------
moments_difference = DynareResults.mom.dataMoments - DynareResults.mom.modelMoments;
residuals = DynareResults.mom.Sw*moments_difference;
DynareResults.mom.Q = residuals'*residuals;
if OptionsMoM.mode_compute == 13 % lsqnonlin
fval = residuals;
else
fval = DynareResults.mom.Q;
if OptionsMoM.penalized_estimator
fval=fval+(xparam1-DynareResults.prior.p1)'/diag(DynareResults.prior.p2)*(xparam1-DynareResults.prior.p1);
end
end
end%main function end

View File

@ -0,0 +1,223 @@
function [fval, info, exit_flag, DynareResults, Model, OptionsMoM] = method_of_moments_SMM(xparam1, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM)
% [fval, info, exit_flag, DynareResults, Model, OptionsMoM] = method_of_moments_SMM(xparam1, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM)
% -------------------------------------------------------------------------
% This function evaluates the objective function for SMM estimation
% =========================================================================
% INPUTS
% o xparam1: current value of estimated parameters as returned by set_prior()
% o Bounds: structure containing parameter bounds
% o DynareResults: structure for results (oo_)
% o EstimatedParameters: structure describing the estimated_parameters (estim_params_)
% o MatchedMoments: structure containing information about selected moments to match in estimation (matched_moments_)
% o Model structure describing the Model
% o OptionsMoM: structure information about all settings (specified by the user, preprocessor, and taken from global options_)
% -------------------------------------------------------------------------
% OUTPUTS
% o fval: value of the quadratic form of the moment difference (except for lsqnonlin, where this is done implicitly)
% o info: vector storing error code and penalty
% o exit_flag: 0 if no error, 1 of error
% o DynareResults: structure containing the results with the following updated fields:
% - mom.modelMoments [numMom x 1] vector with model moments
% - mom.Q value of the quadratic form of the moment difference
% o Model: Matlab's structure describing the Model
% -------------------------------------------------------------------------
% This function is called by
% o driver.m
% -------------------------------------------------------------------------
% This function calls
% o bsxfun
% o ispd
% o method_of_moments_datamoments
% o resol
% o set_all_parameters
% o simult_
% =========================================================================
% Copyright (C) 2020 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
% Author(s):
% o Willi Mutschler (willi@mutschler.eu)
% o Johannes Pfeifer (jpfeifer@uni-koeln.de)
% =========================================================================
% To Do: check penalized estimation for different optimizers, what is special about mode_compute=1 [@wmutschl]
%------------------------------------------------------------------------------
% 0. Initialization of the returned variables and others...
%------------------------------------------------------------------------------
exit_flag = 1;
info = zeros(4,1);
xparam1 = xparam1(:); % Ensure that xparam1 is a column vector
%------------------------------------------------------------------------------
% 1. Get the structural parameters & define penalties
%------------------------------------------------------------------------------
% Return, with endogenous penalty, if some parameters are smaller than the lower bound of the parameters.
if any(xparam1<Bounds.lb)
if ~isequal(OptionsMoM.mode_compute,1)
k = find(xparam1<Bounds.lb);
fval = Inf;
exit_flag = 0;
info(1) = 41;
info(4)= sum((Bounds.lb(k)-xparam1(k)).^2);
return
elseif OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
return
end
end
% Return, with endogenous penalty, if some parameters are greater than the upper bound of the parameters.
if any(xparam1>Bounds.ub)
if ~isequal(OptionsMoM.mode_compute,1)
k = find(xparam1>Bounds.ub);
fval = Inf;
exit_flag = 0;
info(1) = 42;
info(4)= sum((xparam1(k)-Bounds.ub(k)).^2);
return
elseif OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
return
end
end
% Set all parameters
Model = set_all_parameters(xparam1,EstimatedParameters,Model);
% Test if Q is positive definite.
if ~issquare(Model.Sigma_e) || EstimatedParameters.ncx || isfield(EstimatedParameters,'calibrated_covariances')
[Q_is_positive_definite, penalty] = ispd(Model.Sigma_e(EstimatedParameters.Sigma_e_entries_to_check_for_positive_definiteness,EstimatedParameters.Sigma_e_entries_to_check_for_positive_definiteness));
if ~Q_is_positive_definite
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
else
fval = Inf;
exit_flag = 0;
info(1) = 43;
info(4) = penalty;
end
return
end
if isfield(EstimatedParameters,'calibrated_covariances')
correct_flag=check_consistency_covariances(Model.Sigma_e);
if ~correct_flag
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
else
penalty = sum(Model.Sigma_e(EstimatedParameters.calibrated_covariances.position).^2);
fval = Inf;
exit_flag = 0;
info(1) = 71;
info(4) = penalty;
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
end
end
return
end
end
end
%------------------------------------------------------------------------------
% 2. call resol to compute steady state and model solution
%------------------------------------------------------------------------------
% Compute linear approximation around the deterministic steady state
[dr, info, Model, OptionsMoM, DynareResults] = resol(0, Model, OptionsMoM, DynareResults);
% Return, with endogenous penalty when possible, if dynare_resolve issues an error code (defined in resol).
if info(1)
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
return
else
if info(1) == 3 || info(1) == 4 || info(1) == 5 || info(1)==6 ||info(1) == 19 ||...
info(1) == 20 || info(1) == 21 || info(1) == 23 || info(1) == 26 || ...
info(1) == 81 || info(1) == 84 || info(1) == 85 || info(1) == 86
%meaningful second entry of output that can be used
fval = Inf;
info(4) = info(2);
exit_flag = 0;
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
end
return
else
fval = Inf;
info(4) = 0.1;
exit_flag = 0;
if OptionsMoM.mode_compute == 13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
end
return
end
end
end
%------------------------------------------------------------------------------
% 3. Compute Moments of the model solution for normal innovations
%------------------------------------------------------------------------------
% create shock series with correct covariance matrix from iid standard normal shocks
i_exo_var = setdiff(1:Model.exo_nbr, find(diag(Model.Sigma_e) == 0 )); %find singular entries in covariance
chol_S = chol(Model.Sigma_e(i_exo_var,i_exo_var));
scaled_shock_series = zeros(size(OptionsMoM.shock_series)); %initialize
scaled_shock_series(:,i_exo_var) = OptionsMoM.shock_series(:,i_exo_var)*chol_S; %set non-zero entries
% simulate series
y_sim = simult_(Model, OptionsMoM, dr.ys, dr, scaled_shock_series, OptionsMoM.order);
% provide meaningful penalty if data is nan or inf
if any(any(isnan(y_sim))) || any(any(isinf(y_sim)))
if OptionsMoM.mode_compute==13
fval = ones(size(DynareResults.mom.dataMoments,1),1)*OptionsMoM.huge_number;
else
fval = Inf;
end
info(1)=180;
info(4) = 0.1;
exit_flag = 0;
return
end
% Remove burning and focus on observables (note that y_sim is in declaration order)
y_sim = y_sim(DynareResults.dr.order_var(DynareResults.dr.obs_var) , end-OptionsMoM.long:end)';
% Remove mean if centered moments
if OptionsMoM.prefilter
y_sim = bsxfun(@minus, y_sim, mean(y_sim,1));
end
DynareResults.mom.modelMoments = method_of_moments_datamoments(y_sim, DynareResults, MatchedMoments, OptionsMoM);
%------------------------------------------------------------------------------
% 4. Compute quadratic target function
%------------------------------------------------------------------------------
moments_difference = DynareResults.mom.dataMoments - DynareResults.mom.modelMoments;
residuals = DynareResults.mom.Sw*moments_difference;
DynareResults.mom.Q = residuals'*residuals;
if OptionsMoM.mode_compute == 13 % lsqnonlin
fval = residuals;
else
fval = DynareResults.mom.Q;
if OptionsMoM.penalized_estimator
fval=fval+(xparam1-DynareResults.prior.p1)'/diag(DynareResults.mom.p2)*(xparam1-DynareResults.mom.p1);
end
end
end %main function end

View File

@ -0,0 +1,73 @@
function [dataMoments, m_data] = method_of_moments_datamoments(data, DynareResults, MatchedMoments, OptionsMoM)
% [dataMoments, m_data] = method_of_moments_datamoments(data, DynareResults, MatchedMoments, OptionsMoM)
% This function computes the user-selected empirical moments from data
% =========================================================================
% INPUTS
% o data [T x varobs_nbr] data set
% o DynareResults: [structure] storage for results (oo_)
% o MatchedMoments: [structure] information about selected moments to match in estimation (matched_moments_)
% o OptionsMoM: [structure] information about all settings (specified by the user, preprocessor, and taken from global options_)
% -------------------------------------------------------------------------
% OUTPUTS
% o dataMoments [numMom x 1] mean of selected empirical moments
% o m_data [T x numMom] selected empirical moments at each point in time
% -------------------------------------------------------------------------
% This function is called by
% o method_of_moments.m
% o method_of_moments_SMM.m
% =========================================================================
% Copyright (C) 2020 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
% Author(s):
% o Willi Mutschler (willi@mutschler.eu)
% o Johannes Pfeifer (jpfeifer@uni-koeln.de)
% =========================================================================
% Initialization
T = size(data,1); % Number of observations (T) and number of observables (ny)
mom_nbr = OptionsMoM.mom_nbr;
dataMoments = nan(mom_nbr,1);
m_data = nan(T,mom_nbr);
% Product moment for each time period, i.e. each row t contains yt1(l1)^p1*yt2(l2)^p2*...
% note that here we already are able to treat leads and lags and any power product moments
for jm = 1:mom_nbr
vars = DynareResults.dr.inv_order_var(MatchedMoments{jm,1})';
leadlags = MatchedMoments{jm,2}; % note that lags are negative numbers and leads are positive numbers
powers = MatchedMoments{jm,3};
for jv = 1:length(vars)
jvar = DynareResults.dr.obs_var == vars(jv);
y = nan(T,1);
y( (1-min(leadlags(jv),0)) : (T-max(leadlags(jv),0)) , 1) = data( (1+max(leadlags(jv),0)) : (T+min(leadlags(jv),0)) , jvar).^powers(jv);
if jv==1
m_data_tmp = y;
else
m_data_tmp = m_data_tmp.*y;
end
end
dataMoments(jm,1) = sum(m_data_tmp,'omitnan')/(T-sum(abs(leadlags)));
% We replace nan (due to leads and lags) with the corresponding mean
% @wmutschl: this should also work for missing values, right?
m_data_tmp(isnan(m_data_tmp)) = dataMoments(jm,1);
m_data(:,jm) = m_data_tmp;
end
end %function end

View File

@ -0,0 +1,86 @@
function Wopt = method_of_moments_optimal_weighting_matrix(m_data, moments, qLag)
% Wopt = method_of_moments_optimal_weighting_matrix(m_data, moments, qLag)
% -------------------------------------------------------------------------
% This function computes the optimal weigthing matrix by a Bartlett kernel with maximum lag qlag
% Adapted from replication codes of
% o Andreasen, Fernández-Villaverde, Rubio-Ramírez (2018): "The Pruned State-Space System for Non-Linear DSGE Models: Theory and Empirical Applications", Review of Economic Studies, 85(1):1-49.
% =========================================================================
% INPUTS
% o m_data [T x numMom] selected empirical or theoretical moments at each point in time
% o moments [numMom x 1] mean of selected empirical or theoretical moments
% o qlag [integer] Bartlett kernel maximum lag order
% -------------------------------------------------------------------------
% OUTPUTS
% o Wopt [numMom x numMom] optimal weighting matrix
% -------------------------------------------------------------------------
% This function is called by
% o method_of_moments.m
% -------------------------------------------------------------------------
% This function calls:
% o CorrMatrix (embedded)
% =========================================================================
% Copyright (C) 2020 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
% Author(s):
% o Willi Mutschler (willi@mutschler.eu)
% o Johannes Pfeifer (jpfeifer@uni-koeln.de)
% =========================================================================
% Initialize
[T,numMom] = size(m_data); %note that in m_data nan values (due to leads or lags in matchedmoments) are removed so T is the effective sample size
% center around moments (could be either datamoments or modelmoments)
hFunc = m_data - repmat(moments',T,1);
% The required correlation matrices
GAMA_array = zeros(numMom,numMom,qLag);
GAMA0 = CorrMatrix(hFunc,T,numMom,0);
if qLag > 0
for ii=1:qLag
GAMA_array(:,:,ii) = CorrMatrix(hFunc,T,numMom,ii);
end
end
% The estimate of S
S = GAMA0;
if qLag > 0
for ii=1:qLag
S = S + (1-ii/(qLag+1))*(GAMA_array(:,:,ii) + GAMA_array(:,:,ii)');
end
end
% The estimate of W
Wopt = S\eye(size(S,1));
% Check positive definite W
try
chol(Wopt);
catch err
error('method_of_moments: The optimal weighting matrix is not positive definite. Check whether your model implies stochastic singularity\n')
end
end
% The correlation matrix
function GAMAcorr = CorrMatrix(hFunc,T,numMom,v)
GAMAcorr = zeros(numMom,numMom);
for t = 1+v:T
GAMAcorr = GAMAcorr + hFunc(t-v,:)'*hFunc(t,:);
end
GAMAcorr = GAMAcorr/T;
end

View File

@ -0,0 +1,105 @@
function [SEvalues, AVar] = method_of_moments_standard_errors(xparam, objective_function, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM, Wopt_flag)
% [SEvalues, AVar] = method_of_moments_standard_errors(xparam, objective_function, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM, Wopt_flag)
% -------------------------------------------------------------------------
% This function computes standard errors to the method of moments estimates
% Adapted from replication codes of
% o Andreasen, Fernández-Villaverde, Rubio-Ramírez (2018): "The Pruned State-Space System for Non-Linear DSGE Models: Theory and Empirical Applications", Review of Economic Studies, 85(1):1-49.
% =========================================================================
% INPUTS
% o xparam: value of estimated parameters as returned by set_prior()
% o objective_function string of objective function, either method_of_moments_GMM.m or method_of_moments_SMM.m
% o Bounds: structure containing parameter bounds
% o DynareResults: structure for results (oo_)
% o EstimatedParameters: structure describing the estimated_parameters (estim_params_)
% o MatchedMoments: structure containing information about selected moments to match in estimation (matched_moments_)
% o Model structure describing the Model
% o OptionsMoM: structure information about all settings (specified by the user, preprocessor, and taken from global options_)
% o Wopt_flag: indicator whether the optimal weighting is actually used
% -------------------------------------------------------------------------
% OUTPUTS
% o SEvalues [nparam x 1] vector of standard errors
% o AVar [nparam x nparam] asymptotic covariance matrix
% -------------------------------------------------------------------------
% This function is called by
% o method_of_moments.m
% -------------------------------------------------------------------------
% This function calls:
% o get_the_name
% o get_error_message
% o method_of_moments_GMM.m (objective function)
% o method_of_moments_SMM.m (objective function)
% o method_of_moments_optimal_weighting_matrix
% =========================================================================
% Copyright (C) 2020 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
% Author(s):
% o Willi Mutschler (willi@mutschler.eu)
% o Johannes Pfeifer (jpfeifer@uni-koeln.de)
% =========================================================================
% Some dimensions
numMom = size(DynareResults.mom.modelMoments,1);
dimParams = size(xparam,1);
D = zeros(numMom,dimParams);
epsValue = OptionsMoM.dynatol.x;
for i=1:dimParams
%Positive step
xparam_eps_p = xparam;
xparam_eps_p(i,1) = xparam_eps_p(i) + epsValue;
[~, info_p, exit_flag_p, DynareResults_p, ~, ~] = feval(objective_function, xparam_eps_p, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM);
% Negative step
xparam_eps_m = xparam;
xparam_eps_m(i,1) = xparam_eps_m(i) - epsValue;
[~, info_m, exit_flag_m, DynareResults_m, ~, ~] = feval(objective_function, xparam_eps_m, Bounds, DynareResults, EstimatedParameters, MatchedMoments, Model, OptionsMoM);
% The Jacobian:
if nnz(info_p)==0 && nnz(info_m)==0
D(:,i) = (DynareResults_p.mom.modelMoments - DynareResults_m.mom.modelMoments)/(2*epsValue);
else
problpar = get_the_name(i,OptionsMoM.TeX, Model, EstimatedParameters, OptionsMoM);
message_p = get_error_message(info_p, OptionsMoM);
message_m = get_error_message(info_m, OptionsMoM);
warning('method_of_moments:info','Cannot compute the Jacobian for parameter %s - no standard errors available\n %s %s\nCheck your bounds and/or priors, or use a different optimizer.\n',problpar, message_p, message_m)
AVar = NaN(length(xparam),length(xparam));
SEvalues = NaN(length(xparam),1);
return
end
end
T = OptionsMoM.nobs; %Number of observations
if isfield(OptionsMoM,'variance_correction_factor')
T = T*OptionsMoM.variance_correction_factor;
end
if Wopt_flag
% We have the optimal weighting matrix
WW = DynareResults.mom.Sw'*DynareResults.mom.Sw;
AVar = 1/T*((D'*WW*D)\eye(dimParams));
else
% We do not have the optimal weighting matrix yet
WWused = DynareResults.mom.Sw'*DynareResults.mom.Sw;
WWopt = method_of_moments_optimal_weighting_matrix(DynareResults.mom.m_data, DynareResults.mom.modelMoments, OptionsMoM.bartlett_kernel_lag);
S = WWopt\eye(size(WWopt,1));
AA = (D'*WWused*D)\eye(dimParams);
AVar = 1/T*AA*D'*WWused*S*WWused*D*AA;
end
SEvalues = sqrt(diag(AVar));

View File

@ -428,7 +428,7 @@ switch minimizer_algorithm
case 12
if isoctave
error('Option mode_compute=12 is not available under Octave')
elseif ~user_has_matlab_license('global_optimization_toolbox')
elseif ~user_has_matlab_license('GADS_Toolbox')
error('Option mode_compute=12 requires the Global Optimization Toolbox')
end
[LB, UB] = set_bounds_to_finite_values(bounds, options_.huge_number);
@ -523,6 +523,21 @@ switch minimizer_algorithm
end
func = @(x)objective_function(x,varargin{:});
[opt_par_values,fval,exitflag,output] = simulannealbnd(func,start_par_value,bounds(:,1),bounds(:,2),optim_options);
case 13
% Matlab's lsqnonlin (Optimization toolbox needed).
if isoctave && ~user_has_octave_forge_package('optim')
error('Option mode_compute=13 requires the optim package')
elseif ~isoctave && ~user_has_matlab_license('optimization_toolbox')
error('Option mode_compute=13 requires the Optimization Toolbox')
end
optim_options = optimset('display','iter','MaxFunEvals',5000,'MaxIter',5000,'TolFun',1e-6,'TolX',1e-6);
if ~isempty(options_.optim_opt)
eval(['optim_options = optimset(optim_options,' options_.optim_opt ');']);
end
if options_.silent_optimizer
optim_options = optimset(optim_options,'display','off');
end
[opt_par_values,Resnorm,fval,exitflag,OUTPUT,LAMBDA,JACOB] = lsqnonlin(objective_function,start_par_value,bounds(:,1),bounds(:,2),optim_options,varargin{:});
otherwise
if ischar(minimizer_algorithm)
if exist(minimizer_algorithm)

View File

@ -47,6 +47,8 @@ MODFILES = \
estimation/MH_recover/fs2000_recover_3.mod \
estimation/t_proposal/fs2000_student.mod \
estimation/tune_mh_jscale/fs2000.mod \
estimation/method_of_moments/AnScho_MoM.mod \
estimation/method_of_moments/RBCmodel_MoM.mod \
moments/example1_var_decomp.mod \
moments/example1_bp_test.mod \
moments/test_AR1_spectral_density.mod \

View File

@ -0,0 +1,253 @@
% DSGE model used in replication files of
% An, Sungbae and Schorfheide, Frank, (2007), Bayesian Analysis of DSGE Models, Econometric Reviews, 26, issue 2-4, p. 113-172.
% Adapted by Willi Mutschler (@wmutschl, willi@mutschler.eu)
% =========================================================================
% Copyright (C) 2020 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% =========================================================================
% Define testscenario
@#define orderApp = 2
@#define estimParams = 1
% Note that we set the numerical optimization tolerance levels very large to speed up the testsuite
@#define optimizer = 1
var c p R g y z INFL INT YGR;
varexo e_r e_g e_z;
parameters tau nu kap cyst psi1 psi2 rhor rhog rhoz rrst pist gamst;
varobs INT YGR INFL;
tau = 2;
nu = 0.1;
kap = 0.33;
cyst = 0.85;
psi1 = 1.5;
psi2 = 0.125;
rhor = 0.75;
rhog = 0.95;
rhoz = 0.9;
rrst = 1;
pist = 3.2;
gamst = 0.55;
model;
#pist2 = exp(pist/400);
#rrst2 = exp(rrst/400);
#bet = 1/rrst2;
#phi = tau*(1-nu)/nu/kap/pist2^2;
#gst = 1/cyst;
#cst = (1-nu)^(1/tau);
#yst = cst*gst;
#dy = y-y(-1);
1 = exp(-tau*c(+1)+tau*c+R-z(+1)-p(+1));
(1-nu)/nu/phi/(pist2^2)*(exp(tau*c)-1) = (exp(p)-1)*((1-1/2/nu)*exp(p)+1/2/nu) - bet*(exp(p(+1))-1)*exp(-tau*c(+1)+tau*c+y(+1)-y+p(+1));
exp(c-y) = exp(-g) - phi*pist2^2*gst/2*(exp(p)-1)^2;
R = rhor*R(-1) + (1-rhor)*psi1*p + (1-rhor)*psi2*(dy+z) + e_r/100;
g = rhog*g(-1) + e_g/100;
z = rhoz*z(-1) + e_z/100;
YGR = gamst+100*(dy+z);
INFL = pist+400*p;
INT = pist+rrst+4*gamst+400*R;
end;
steady_state_model;
z = 0; p = 0; g = 0; r = 0; c = 0; y = 0;
YGR = gamst; INFL = pist; INT = pist + rrst + 4*gamst;
end;
shocks;
var e_r = 0.20^2;
var e_g = 0.80^2;
var e_z = 0.45^2;
corr e_r,e_g = 0.2;
end;
@#if estimParams == 0
% Define only initial values without bounds
estimated_params;
%tau, 1.50;
%kap, 0.15;
psi1, 1.20;
psi2, 0.50;
rhor, 0.50;
%rhog, 0.50;
%rhoz, 0.50;
%rrst, 1.20;
%pist, 3.00;
gamst, 0.75;
stderr e_r, 0.30;
stderr e_g, 0.30;
stderr e_z, 0.30;
corr e_r,e_g, 0.10;
end;
@#endif
@#if estimParams == 1
% Define initial values and bounds
estimated_params;
%tau, 1.50, 1e-5, 10;
%kap, 0.15, 1e-5, 10;
psi1, 1.20, 1e-5, 10;
psi2, 0.50, 1e-5, 10;
rhor, 0.50, 1e-5, 0.99999;
%rhog, 0.50, 1e-5, 0.99999;
%rhoz, 0.50, 1e-5, 0.99999;
%rrst, 1.20, 1e-5, 10;
%pist, 3.00, 1e-5, 20;
gamst, 0.75, -5, 5;
stderr e_r, 0.30, 1e-8, 5;
stderr e_g, 0.30, 1e-8, 5;
stderr e_z, 0.30, 1e-8, 5;
corr e_r,e_g, 0.10, -1, 1;
end;
@#endif
@#if estimParams == 2
% Define prior distribution
estimated_params;
%tau, 1.50, 1e-5, 10, gamma_pdf, 2.00, 0.50;
%kap, 0.15, 1e-5, 10, gamma_pdf, 0.33, 0.10;
psi1, 1.20, 1e-5, 10, gamma_pdf, 1.50, 0.25;
psi2, 0.50, 1e-5, 10, gamma_pdf, 0.125, 0.25;
rhor, 0.50, 1e-5, 0.99999, beta_pdf, 0.50, 0.20;
%rhog, 0.50, 1e-5, 0.99999, beta_pdf, 0.80, 0.10;
%rhoz, 0.50, 1e-5, 0.99999, beta_pdf, 0.66, 0.15;
%rrst, 1.20, 1e-5, 10, gamma_pdf, 0.50, 0.50;
%pist, 3.00, 1e-5, 20, gamma_pdf, 7.00, 2.00;
gamst, 0.75, -5, 5, normal_pdf, 0.40, 0.20;
stderr e_r, 0.30, 1e-8, 5, inv_gamma_pdf, 0.50, 0.26;
stderr e_g, 0.30, 1e-8, 5, inv_gamma_pdf, 1.25, 0.65;
stderr e_z, 0.30, 1e-8, 5, inv_gamma_pdf, 0.63, 0.33;
corr e_r,e_g, 0.10, -1, 1, uniform_pdf, , , -1, 1;
end;
@#endif
% Simulate data
stoch_simul(order=@{orderApp},pruning,nodisplay,nomoments,periods=750,drop=500);
save('AnScho_MoM_data_@{orderApp}.mat', options_.varobs{:} );
pause(1);
%--------------------------------------------------------------------------
% Method of Moments Estimation
%--------------------------------------------------------------------------
% matched_moments blocks : We don't have an interface yet
% get indices in declaration order
iYGR = strmatch('YGR', M_.endo_names,'exact');
iINFL = strmatch('INFL', M_.endo_names,'exact');
iINT = strmatch('INT', M_.endo_names,'exact');
% first entry: number of variable in declaration order
% second entry: lag
% third entry: power
matched_moments_ = {
%first-order product moments
[iYGR ] [0 ], [1 ];
[iINFL ] [0 ], [1 ];
[iINT ] [0 ], [1 ];
%second-order contemporenous product moments
[iYGR iYGR ] [0 0], [1 1];
[iYGR iINFL] [0 0], [1 1];
[iYGR iINT ] [0 0], [1 1];
[iINFL iINFL] [0 0], [1 1];
[iINFL iINT ] [0 0], [1 1];
[iINT iINT ] [0 0], [1 1];
%second-order temporal product moments
[iYGR iYGR ] [0 -1], [1 1];
%[iINT iYGR ] [0 -1], [1 1];
%[iINFL iYGR ] [0 -1], [1 1];
%[iYGR iINT ] [0 -1], [1 1];
[iINT iINT ] [0 -1], [1 1];
%[iINFL iINT ] [0 -1], [1 1];
%[iYGR iINFL] [0 -1], [1 1];
%[iINT iINFL] [0 -1], [1 1];
[iINFL iINFL] [0 -1], [1 1];
};
@#for mommethod in ["GMM", "SMM"]
method_of_moments(
% Necessery options
mom_method = @{mommethod} % method of moments method; possible values: GMM|SMM
, datafile = 'AnScho_MoM_data_@{orderApp}.mat' % name of filename with data
% Options for both GMM and SMM
% , bartlett_kernel_lag = 20 % bandwith in optimal weighting matrix
, order = @{orderApp} % order of Taylor approximation in perturbation
% , penalized_estimator % use penalized optimization
, pruning % use pruned state space system at higher-order
% , verbose % display and store intermediate estimation results
, weighting_matrix = OPTIMAL % weighting matrix in moments distance objective function; possible values: OPTIMAL|IDENTITY_MATRIX|DIAGONAL|filename
, mom_steps = [2 2] % vector of numbers for the iterations in the 2-step feasible method of moments
% , prefilter=0 % demean each data series by its empirical mean and use centered moments
%
% Options for SMM
% , bounded_shock_support % trim shocks in simulation to +- 2 stdev
% , drop = 500 % number of periods dropped at beginning of simulation
% , seed = 24051986 % seed used in simulations
% , simulation_multiple = 5 % multiple of the data length used for simulation
%
% General options
%, dirname = 'MM' % directory in which to store estimation output
% , graph_format = EPS % specify the file format(s) for graphs saved to disk
% , nodisplay % do not display the graphs, but still save them to disk
% , nograph % do not create graphs (which implies that they are not saved to the disk nor displayed)
% , noprint % do not print stuff to console
% , plot_priors = 1 % control plotting of priors
% , prior_trunc = 1e-10 % probability of extreme values of the prior density that is ignored when computing bounds for the parameters
% , TeX % print TeX tables and graphics
%
% Data and model options
%, first_obs = 501 % number of first observation
% , logdata % if loglinear is set, this option is necessary if the user provides data already in logs, otherwise the log transformation will be applied twice (this may result in complex data)
% , loglinear % computes a log-linear approximation of the model instead of a linear approximation
, nobs = 250 % number of observations
% , xls_sheet = willi % name of sheet with data in Excel
% , xls_range = B2:D200 % range of data in Excel sheet
%
% Optimization options that can be set by the user in the mod file, otherwise default values are provided
% , analytic_derivation % uses analytic derivatives to compute standard errors for GMM
%, huge_number=1D10 % value for replacing the infinite bounds on parameters by finite numbers. Used by some optimizers for numerical reasons
, mode_compute = @{optimizer} % specifies the optimizer for minimization of moments distance, note that by default there is a new optimizer
%, optim = ('TolFun', 1e-5
% ,'TolX', 1e-6
% ) % a list of NAME and VALUE pairs to set options for the optimization routines. Available options depend on mode_compute
%, silent_optimizer % run minimization of moments distance silently without displaying results or saving files in between
% , tolf = 1e-5 % convergence criterion on function value for numerical differentiation
% , tolx = 1e-6 % convergence criterion on funciton input for numerical differentiation
%
% % Numerical algorithms options
% , aim_solver % Use AIM algorithm to compute perturbation approximation
% , dr=default % method used to compute the decision rule; possible values are DEFAULT, CYCLE_REDUCTION, LOGARITHMIC_REDUCTION
% , dr_cycle_reduction_tol = 1e-7 % convergence criterion used in the cycle reduction algorithm
% , dr_logarithmic_reduction_maxiter = 100 % maximum number of iterations used in the logarithmic reduction algorithm
% , dr_logarithmic_reduction_tol = 1e-12 % convergence criterion used in the cycle reduction algorithm
% , k_order_solver % use k_order_solver in higher order perturbation approximations
% , lyapunov = DEFAULT % algorithm used to solve lyapunov equations; possible values are DEFAULT, FIXED_POINT, DOUBLING, SQUARE_ROOT_SOLVER
% , lyapunov_complex_threshold = 1e-15 % complex block threshold for the upper triangular matrix in symmetric Lyapunov equation solver
% , lyapunov_fixed_point_tol = 1e-10 % convergence criterion used in the fixed point Lyapunov solver
% , lyapunov_doubling_tol = 1e-16 % convergence criterion used in the doubling algorithm
% , sylvester = default % algorithm to solve Sylvester equation; possible values are DEFAULT, FIXED_POINT
% , sylvester_fixed_point_tol = 1e-12 % convergence criterion used in the fixed point Sylvester solver
% , qz_criterium = 0.999999 % value used to split stable from unstable eigenvalues in reordering the Generalized Schur decomposition used for solving first order problems [IS THIS CORRET @wmutschl]
% , qz_zero_threshold = 1e-6 % value used to test if a generalized eigenvalue is 0/0 in the generalized Schur decomposition
);
@#endfor

View File

@ -0,0 +1,215 @@
% RBC model used in replication files of
% Andreasen, Fernández-Villaverde, Rubio-Ramírez (2018): "The Pruned State-Space System for Non-Linear DSGE Models: Theory and Empirical Applications", Review of Economic Studies, 85(1):1-49.
% Adapted by Willi Mutschler (@wmutschl, willi@mutschler.eu)
% =========================================================================
% Copyright (C) 2020 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% =========================================================================
% Define testscenario
@#define orderApp = 3
@#define estimParams = 1
% Note that we will set the numerical optimization tolerance levels very large to speed up the testsuite
@#define optimizer = 13
var k c a iv y la n rk w;
predetermined_variables k;
varexo u_a;
varobs n c iv;
parameters DELTA BETTA B ETAl ETAc THETA ALFA RHOA STDA;
DELTA = 0.025;
BETTA = 0.984;
B = 0.5;
ETAl = 1;
ETAc = 2;
THETA = 3.48;
ALFA = 0.667;
RHOA = 0.979;
STDA = 0.0072;
model;
0 = -exp(la) +(exp(c)-B*exp(c(-1)))^(-ETAc) - BETTA*B*(exp(c(+1))-B*exp(c))^(-ETAc);
0 = -THETA*(1-exp(n))^-ETAl + exp(la)*exp(w);
0 = -exp(la) + BETTA*exp(la(+1))*(exp(rk(+1)) + (1-DELTA));
0 = -exp(a)*(1-ALFA)*exp(k)^(-ALFA)*exp(n)^(ALFA) + exp(rk);
0 = -exp(a)*ALFA*exp(k)^(1-ALFA)*exp(n)^(ALFA-1) + exp(w);
0 = -exp(c) - exp(iv) + exp(y);
0 = -exp(y) + exp(a)*exp(k)^(1-ALFA)*exp(n)^(ALFA);
0 = -exp(k(+1)) + (1-DELTA)*exp(k) + exp(iv);
0 = -log(exp(a)) + RHOA*log(exp(a(-1))) + STDA*u_a;
end;
shocks;
var u_a = 1;
end;
@#if estimParams == 0
estimated_params;
DELTA, 0.02;
BETTA, 0.9;
B, 0.4;
%ETAl, 1;
ETAc, 1.5;
ALFA, 0.6;
RHOA, 0.9;
STDA, 0.01;
%THETA, 3.48;
end;
@#endif
@#if estimParams == 1
estimated_params;
DELTA, 0.02, 0, 1;
BETTA, 0.90, 0, 1;
B, 0.40, 0, 1;
%ETAl, 1, 0, 10;
ETAc, 1.80, 0, 10;
ALFA, 0.60, 0, 1;
RHOA, 0.90, 0, 1;
STDA, 0.01, 0, 1;
%THETA, 3.48, 0, 10;
end;
@#endif
@#if estimParams == 2
estimated_params;
DELTA, 0.02, 0, 1, normal_pdf, 0.02, 0.1;
BETTA, 0.90, 0, 1, normal_pdf, 0.90, 0.1;
B, 0.40, 0, 1, normal_pdf, 0.40, 0.1;
%ETAl, 1, 0, 10, normal_pdf, 0.25, 0.0.1;
ETAc, 1.80, 0, 10, normal_pdf, 1.80, 0.1;
ALFA, 0.60, 0, 1, normal_pdf, 0.60, 0.1;
RHOA, 0.90, 0, 1, normal_pdf, 0.90, 0.1;
STDA, 0.01, 0, 1, normal_pdf, 0.01, 0.1;
%THETA, 3.48, 0, 10, normal_pdf, 0.25, 0.0.1;
end;
@#endif
% Simulate data
stoch_simul(order=@{orderApp},pruning,nodisplay,nomoments,periods=750,drop=500);
save('RBC_MoM_data_@{orderApp}.mat', options_.varobs{:} );
pause(1);
%--------------------------------------------------------------------------
% Method of Moments Estimation
%--------------------------------------------------------------------------
% matched_moments blocks : We don't have an interface yet
% get indices in declaration order
ic = strmatch('c', M_.endo_names,'exact');
iiv = strmatch('iv', M_.endo_names,'exact');
in = strmatch('n', M_.endo_names,'exact');
% first entry: number of variable in declaration order
% second entry: lag
% third entry: power
matched_moments_ = {
[ic ] [0 ], [1 ];
[in ] [0 ], [1 ];
[iiv ] [0 ], [1 ];
[ic ic ] [0 0], [1 1];
[ic iiv] [0 0], [1 1];
[ic in ] [0 0], [1 1];
% [iiv ic ] [0 0], [1 1];
[iiv iiv] [0 0], [1 1];
[iiv in ] [0 0], [1 1];
% [in ic ] [0 0], [1 1];
% [in iiv] [0 0], [1 1];
[in in ] [0 0], [1 1];
[ic ic ] [0 -1], [1 1];
[in in ] [0 -1], [1 1];
[iiv iiv] [0 -1], [1 1];
% [iiv iiv] [0 -1], [1 1];
};
@#for mommethod in ["GMM", "SMM"]
method_of_moments(
% Necessery options
mom_method = @{mommethod} % method of moments method; possible values: GMM|SMM
, datafile = 'RBC_MoM_data_@{orderApp}.mat' % name of filename with data
% Options for both GMM and SMM
% , bartlett_kernel_lag = 20 % bandwith in optimal weighting matrix
, order = @{orderApp} % order of Taylor approximation in perturbation
% , penalized_estimator % use penalized optimization
, pruning % use pruned state space system at higher-order
% , verbose % display and store intermediate estimation results
, weighting_matrix = OPTIMAL % weighting matrix in moments distance objective function; possible values: OPTIMAL|IDENTITY_MATRIX|DIAGONAL|filename
, mom_steps = [2 2] % vector of numbers for the iterations in the 2-step feasible method of moments
% , prefilter=0 % demean each data series by its empirical mean and use centered moments
%
% Options for SMM
% , bounded_shock_support % trim shocks in simulation to +- 2 stdev
% , drop = 500 % number of periods dropped at beginning of simulation
% , seed = 24051986 % seed used in simulations
% , simulation_multiple = 5 % multiple of the data length used for simulation
%
% General options
%, dirname = 'MM' % directory in which to store estimation output
% , graph_format = EPS % specify the file format(s) for graphs saved to disk
% , nodisplay % do not display the graphs, but still save them to disk
% , nograph % do not create graphs (which implies that they are not saved to the disk nor displayed)
% , noprint % do not print stuff to console
% , plot_priors = 1 % control plotting of priors
% , prior_trunc = 1e-10 % probability of extreme values of the prior density that is ignored when computing bounds for the parameters
% , TeX % print TeX tables and graphics
%
% Data and model options
%, first_obs = 501 % number of first observation
% , logdata % if loglinear is set, this option is necessary if the user provides data already in logs, otherwise the log transformation will be applied twice (this may result in complex data)
% , loglinear % computes a log-linear approximation of the model instead of a linear approximation
%, nobs = 500 % number of observations
% , xls_sheet = willi % name of sheet with data in Excel
% , xls_range = B2:D200 % range of data in Excel sheet
%
% Optimization options that can be set by the user in the mod file, otherwise default values are provided
% , analytic_derivation % uses analytic derivatives to compute standard errors for GMM
%, huge_number=1D10 % value for replacing the infinite bounds on parameters by finite numbers. Used by some optimizers for numerical reasons
, mode_compute = @{optimizer} % specifies the optimizer for minimization of moments distance, note that by default there is a new optimizer
%, optim = ('TolFun', 1e-3
% ,'TolX', 1e-5
% ) % a list of NAME and VALUE pairs to set options for the optimization routines. Available options depend on mode_compute
, silent_optimizer % run minimization of moments distance silently without displaying results or saving files in between
% , tolf = 1e-5 % convergence criterion on function value for numerical differentiation
% , tolx = 1e-6 % convergence criterion on funciton input for numerical differentiation
%
% % Numerical algorithms options
% , aim_solver % Use AIM algorithm to compute perturbation approximation
% , dr=default % method used to compute the decision rule; possible values are DEFAULT, CYCLE_REDUCTION, LOGARITHMIC_REDUCTION
% , dr_cycle_reduction_tol = 1e-7 % convergence criterion used in the cycle reduction algorithm
% , dr_logarithmic_reduction_maxiter = 100 % maximum number of iterations used in the logarithmic reduction algorithm
% , dr_logarithmic_reduction_tol = 1e-12 % convergence criterion used in the cycle reduction algorithm
% , k_order_solver % use k_order_solver in higher order perturbation approximations
% , lyapunov = DEFAULT % algorithm used to solve lyapunov equations; possible values are DEFAULT, FIXED_POINT, DOUBLING, SQUARE_ROOT_SOLVER
% , lyapunov_complex_threshold = 1e-15 % complex block threshold for the upper triangular matrix in symmetric Lyapunov equation solver
% , lyapunov_fixed_point_tol = 1e-10 % convergence criterion used in the fixed point Lyapunov solver
% , lyapunov_doubling_tol = 1e-16 % convergence criterion used in the doubling algorithm
% , sylvester = default % algorithm to solve Sylvester equation; possible values are DEFAULT, FIXED_POINT
% , sylvester_fixed_point_tol = 1e-12 % convergence criterion used in the fixed point Sylvester solver
% , qz_criterium = 0.999999 % value used to split stable from unstable eigenvalues in reordering the Generalized Schur decomposition used for solving first order problems [IS THIS CORRET @wmutschl]
% , qz_zero_threshold = 1e-6 % value used to test if a generalized eigenvalue is 0/0 in the generalized Schur decomposition
);
@#endfor

View File

@ -0,0 +1,74 @@
% By Willi Mutschler, September 26, 2016. Email: willi@mutschler.eu
function [ys,params,check] = RBCmodel_steadystate(ys,exo,M_,options_)
%% Step 0: initialize indicator and set options for numerical solver
check = 0;
options = optimset('Display','off','TolX',1e-12,'TolFun',1e-12);
params = M_.params;
%% Step 1: read out parameters to access them with their name
for ii = 1:M_.param_nbr
eval([ M_.param_names{ii} ' = M_.params(' int2str(ii) ');']);
end
%% Step 2: Check parameter restrictions
if ETAc*ETAl<1 % parameter violates restriction (here it is artifical)
check=1; %set failure indicator
return; %return without updating steady states
end
%% Step 3: Enter model equations here
A = 1;
RK = 1/BETTA - (1-DELTA);
K_O_N = (RK/(A*(1-ALFA)))^(-1/ALFA);
if K_O_N <= 0
check = 1; % set failure indicator
return; % return without updating steady states
end
W = A*ALFA*(K_O_N)^(1-ALFA);
IV_O_N = DELTA*K_O_N;
Y_O_N = A*K_O_N^(1-ALFA);
C_O_N = Y_O_N - IV_O_N;
if C_O_N <= 0
check = 1; % set failure indicator
return; % return without updating steady states
end
% The labor level
if ETAc == 1 && ETAl == 1
N = (1-BETTA*B)*(C_O_N*(1-B))^-1*W/THETA/(1+(1-BETTA*B)*(C_O_N*(1-B))^-1*W/THETA);
else
% No closed-form solution use a fixed-point algorithm
N0 = 1/3;
[N,~,exitflag] = fsolve(@(N) THETA*(1-N)^(-ETAl)*N^ETAc - (1-BETTA*B)*(C_O_N*(1-B))^(-ETAc)*W, N0,options);
if exitflag <= 0
check = 1; % set failure indicator
return % return without updating steady states
end
end
C=C_O_N*N;
Y=Y_O_N*N;
IV=IV_O_N*N;
K=K_O_N*N;
LA = (C-B*C)^(-ETAc)-BETTA*B*(C-B*C)^(-ETAc);
k=log(K);
c=log(C);
a=log(A);
iv=log(IV);
y=log(Y);
la=log(LA);
n=log(N);
rk=log(RK);
w=log(W);
%% Step 4: Update parameters and variables
params=NaN(M_.param_nbr,1);
for iter = 1:M_.param_nbr %update parameters set in the file
eval([ 'params(' num2str(iter) ') = ' M_.param_names{iter} ';' ])
end
for ii = 1:M_.orig_endo_nbr %auxiliary variables are set automatically
eval(['ys(' int2str(ii) ') = ' M_.endo_names{ii} ';']);
end
end