dynare/matlab/+mom/run.m

1033 lines
59 KiB
Matlab
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

function [oo_, options_mom_, M_] = run(bayestopt_, options_, oo_, estim_params_, M_, options_mom_)
%function [oo_, options_mom_, M_] = run(bayestopt_, options_, oo_, estim_params_, M_, 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 options_mom_ structure
% - Carry over options from the preprocessor
% - Initialize other options
% - Get variable orderings and state space representation
% Step 2: Checks and transformations for matched moments structure
% 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: Iterated method of moments estimation
% Step 8: J-Test
% Step 9: 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 bayestopt_: [structure] information about priors
% o options_: [structure] information about global options
% o oo_: [structure] storage for results
% o estim_params_: [structure] information about estimated parameters
% o M_: [structure] information about model with
% o matched_moments: [cell] information about selected moments to match in estimation
% vars: matched_moments{:,1});
% lead/lags: matched_moments{:,2};
% powers: matched_moments{:,3};
% o options_mom_: [structure] information about settings specified by the user
% -------------------------------------------------------------------------
% OUTPUTS
% o oo_: [structure] storage for results (oo_)
% o options_mom_: [structure] information about all (user-specified and updated) 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_objective.m
% o evaluate_steady_state
% o get_all_parameters.m
% o get_matrix_entries_for_psd_check.m
% o makedataset.m
% o mom.check_plot.m
% o mom.data_moments.m
% o mom.objective_function.m
% o mom.optimal_weighting_matrix
% o mom-standard_errors
% 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.m
% o test_for_deep_parameters_calibration.m
% =========================================================================
% Copyright © 2020-2021 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 <https://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
% Author(s):
% o Willi Mutschler (willi@mutschler.eu)
% o Johannes Pfeifer (jpfeifer@uni-koeln.de)
% =========================================================================
%% TO DO LIST
% - [ ] add IRF matching
% - [ ] speed up pruned_state_space_system (by using doubling with old initial values, hardcoding zeros, other "tricks" used in e.g. nlma)
% - [ ] add option to use autocorrelations (we have useautocorr in identification toolbox already)
% - [ ] SMM with extended path
% - [ ] deal with measurement errors (once @wmutschl has implemented this in identification toolbox)
% - [ ] dirname option to save output to different directory not yet implemented
% - [ ] display scaled moments
% The TeX option crashes MATLAB R2014a run with "-nodisplay" option
% (as is done from the testsuite).
% Since we cant directly test whether "-nodisplay" has been passed,
% we test for the "TOP_TEST_DIR" environment variable, which is set
% by the testsuite.
% Note that it was not tested whether the crash happens with more
% recent MATLAB versions, so when OLD_MATLAB_VERSION is increased,
% one should make a test before removing this workaround.
if options_.TeX && ~isoctave && matlab_ver_less_than('8.4') && ~isempty(getenv('TOP_TEST_DIR'))
warning('Disabling TeX option due to a bug in MATLAB R2014a with -nodisplay')
options_.TeX = false;
end
if isfield(options_mom_, 'TeX') && options_mom_.TeX && ~isoctave && matlab_ver_less_than('8.4') && ~isempty(getenv('TOP_TEST_DIR'))
warning('Disabling TeX option due to a bug in MATLAB R2014a with -nodisplay')
options_mom_.TeX = false;
end
% -------------------------------------------------------------------------
% Step 0: Check if required structures and options exist
% -------------------------------------------------------------------------
if isempty(estim_params_) % structure storing the info about estimated parameters in the estimated_params block
if ~(isfield(estim_params_,'nvx') && (size(estim_params_.var_exo,1)+size(estim_params_.var_endo,1)+size(estim_params_.corrx,1)+size(estim_params_.corrn,1)+size(estim_params_.param_vals,1))==0)
error('method_of_moments: You need to provide an ''estimated_params'' block')
else
error('method_of_moments: The ''estimated_params'' block must not be empty')
end
end
if ~isfield(M_,'matched_moments') || isempty(M_.matched_moments) % 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(bayestopt_) && any(bayestopt_.pshape==0) && any(bayestopt_.pshape~=0)
error('method_of_moments: Estimation must be either fully classical or fully Bayesian. Maybe you forgot to specify a prior distribution.')
end
if options_.logged_steady_state || options_.loglinear
error('method_of_moments: The loglinear option is not supported. Please append the required logged variables as auxiliary equations.\n')
else
options_mom_.logged_steady_state = 0;
options_mom_.loglinear = false;
end
fprintf('\n==== Method of Moments Estimation (%s) ====\n\n',options_mom_.mom.mom_method)
% -------------------------------------------------------------------------
% Step 1a: Prepare options_mom_ structure
% -------------------------------------------------------------------------
% options_mom_ 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(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM')
options_mom_.mom = set_default_option(options_mom_.mom,'bartlett_kernel_lag',20); % bandwith in optimal weighting matrix
options_mom_.mom = set_default_option(options_mom_.mom,'penalized_estimator',false); % include deviation from prior mean as additional moment restriction and use prior precision as weight
options_mom_.mom = set_default_option(options_mom_.mom,'verbose',false); % display and store intermediate estimation results
options_mom_.mom = set_default_option(options_mom_.mom,'weighting_matrix',{'DIAGONAL'; 'OPTIMAL'}); % weighting matrix in moments distance objective function at each iteration of estimation;
% possible values are 'OPTIMAL', 'IDENTITY_MATRIX' ,'DIAGONAL' or a filename. Size of cell determines stages in iterated estimation.
options_mom_.mom = set_default_option(options_mom_.mom,'weighting_matrix_scaling_factor',1); % scaling of weighting matrix in objective function
options_mom_.mom = set_default_option(options_mom_.mom,'se_tolx',1e-5); % step size for numerical computation of standard errors
options_mom_ = set_default_option(options_mom_,'order',1); % order of Taylor approximation in perturbation
options_mom_ = set_default_option(options_mom_,'pruning',false); % use pruned state space system at higher-order
% Checks for perturbation order
if options_mom_.order < 1
error('method_of_moments: The order of the Taylor approximation cannot be 0!')
end
end
if strcmp(options_mom_.mom.mom_method,'SMM')
options_mom_.mom = set_default_option(options_mom_.mom,'burnin',500); % number of periods dropped at beginning of simulation
options_mom_.mom = set_default_option(options_mom_.mom,'bounded_shock_support',false); % trim shocks in simulation to +- 2 stdev
options_mom_.mom = set_default_option(options_mom_.mom,'seed',24051986); % seed used in simulations
options_mom_.mom = set_default_option(options_mom_.mom,'simulation_multiple',7); % multiple of the data length used for simulation
if options_mom_.mom.simulation_multiple < 1
fprintf('The simulation horizon is shorter than the data. Dynare resets the simulation_multiple to 5.\n')
options_mom_.mom.simulation_multiple = 7;
end
end
if strcmp(options_mom_.mom.mom_method,'GMM')
% Check for pruning with GMM at higher order
if options_mom_.order > 1 && ~options_mom_.pruning
fprintf('GMM at higher order only works with pruning, so we set pruning option to 1.\n');
options_mom_.pruning = true;
end
if options_mom_.order > 3
error('method_of_moments: perturbation orders higher than 3 are not implemented for GMM estimation, try using SMM.\n');
end
end
options_mom_.mom = set_default_option(options_mom_.mom,'analytic_standard_errors',false); % compute standard errors numerically (0) or analytically (1). Analytical derivatives are only available for GMM.
options_mom_.mom = set_default_option(options_mom_.mom,'analytic_jacobian',false); % use analytic Jacobian in optimization, only available for GMM and gradient-based optimizers
% initialize flag to compute derivs in objective function (needed for GMM with either analytic_standard_errors or analytic_jacobian )
options_mom_.mom.compute_derivs = false;
% General options that can be set by the user in the mod file, otherwise default values are provided
options_mom_ = set_default_option(options_mom_,'dirname',M_.dname); % specify directory in which to store estimation output [not yet working]
options_mom_ = set_default_option(options_mom_,'graph_format','eps'); % specify the file format(s) for graphs saved to disk
options_mom_ = set_default_option(options_mom_,'nodisplay',false); % do not display the graphs, but still save them to disk
options_mom_ = set_default_option(options_mom_,'nograph',false); % do not create graphs (which implies that they are not saved to the disk nor displayed)
options_mom_ = set_default_option(options_mom_,'noprint',false); % do not print output to console
options_mom_ = set_default_option(options_mom_,'plot_priors',true); % control plotting of priors
options_mom_ = set_default_option(options_mom_,'prior_trunc',1e-10); % probability of extreme values of the prior density that is ignored when computing bounds for the parameters
options_mom_ = set_default_option(options_mom_,'TeX',false); % print TeX tables and graphics
options_mom_ = set_default_option(options_mom_,'verbosity',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
options_mom_ = set_default_option(options_mom_,'first_obs',1); % number of first observation
options_mom_ = set_default_option(options_mom_,'logdata',false); % if data is already in logs
options_mom_ = set_default_option(options_mom_,'nobs',NaN); % number of observations
options_mom_ = set_default_option(options_mom_,'prefilter',false); % demean each data series by its empirical mean and use centered moments
options_mom_ = set_default_option(options_mom_,'xls_sheet',1); % name of sheet with data in Excel
options_mom_ = set_default_option(options_mom_,'xls_range',''); % range of data in Excel sheet
% temporary workaround for https://git.dynare.org/Dynare/dseries/-/issues/51
if options_mom_.xls_sheet~=1
evalin('base','options_.xls_sheet=options_mom_.xls_sheet');
end
if ~isempty(options_mom_.xls_range)
evalin('base','options_.xls_range=options_mom_.xls_range');
end
% Recursive estimation and forecast are not supported
if numel(options_mom_.nobs)>1
error('method_of_moments: Recursive estimation and forecast for samples is not supported. Please set an integer as ''nobs''.');
end
if numel(options_mom_.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
options_mom_ = set_default_option(options_mom_,'huge_number',1e7); % value for replacing the infinite bounds on parameters by finite numbers. Used by some optimizers for numerical reasons
if (isoctave && user_has_octave_forge_package('optim')) || (~isoctave && user_has_matlab_license('optimization_toolbox'))
options_mom_ = set_default_option(options_mom_,'mode_compute',13); % specifies lsqnonlin as default optimizer for minimization of moments distance
else
options_mom_ = set_default_option(options_mom_,'mode_compute',4); % specifies csminwel as fallback default option for minimization of moments distance
end
options_mom_ = set_default_option(options_mom_,'additional_optimizer_steps',[]); % vector of additional mode-finders run after mode_compute
options_mom_ = set_default_option(options_mom_,'optim_opt',[]); % a list of NAME and VALUE pairs to set options for the optimization routines. Available options depend on mode_compute
options_mom_ = set_default_option(options_mom_,'silent_optimizer',false); % run minimization of moments distance silently without displaying results or saving files in between
% Check plot options that can be set by the user in the mod file, otherwise default values are provided
options_mom_.mode_check.nolik = false; % we don't do likelihood (also this initializes mode_check substructure)
options_mom_.mode_check = set_default_option(options_mom_.mode_check,'status',false); % plot the target function for values around the computed minimum for each estimated parameter in turn. This is helpful to diagnose problems with the optimizer.
options_mom_.mode_check = set_default_option(options_mom_.mode_check,'neighbourhood_size',.5); % width of the window around the computed minimum to be displayed on the diagnostic plots. This width is expressed in percentage deviation. The Inf value is allowed, and will trigger a plot over the entire domain
options_mom_.mode_check = set_default_option(options_mom_.mode_check,'symmetric_plots',true); % ensure that the check plots are symmetric around the minimum. A value of 0 allows to have asymmetric plots, which can be useful if the minimum is close to a domain boundary, or in conjunction with neighbourhood_size = Inf when the domain is not the entire real line
options_mom_.mode_check = set_default_option(options_mom_.mode_check,'number_of_points',20); % number of points around the minimum where the target function is evaluated (for each parameter)
% Numerical algorithms options that can be set by the user in the mod file, otherwise default values are provided
options_mom_ = set_default_option(options_mom_,'aim_solver',false); % use AIM algorithm to compute perturbation approximation instead of mjdgges
options_mom_ = set_default_option(options_mom_,'k_order_solver',false); % use k_order_perturbation instead of mjdgges
options_mom_ = set_default_option(options_mom_,'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
options_mom_ = set_default_option(options_mom_,'dr_cycle_reduction_tol',1e-7); % convergence criterion used in the cycle reduction algorithm
options_mom_ = set_default_option(options_mom_,'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
options_mom_ = set_default_option(options_mom_,'dr_logarithmic_reduction_maxiter',100); % maximum number of iterations used in the logarithmic reduction algorithm
options_mom_ = set_default_option(options_mom_,'dr_logarithmic_reduction_tol',1e-12); % convergence criterion used in the cycle reduction algorithm
options_mom_ = set_default_option(options_mom_,'lyapunov_db',false); % doubling algorithm (disclyap_fast) to solve Lyapunov equation to compute variance-covariance matrix of state variables
options_mom_ = set_default_option(options_mom_,'lyapunov_fp',false); % fixed-point algorithm to solve Lyapunov equation to compute variance-covariance matrix of state variables
options_mom_ = set_default_option(options_mom_,'lyapunov_srs',false); % square-root-solver (dlyapchol) algorithm to solve Lyapunov equation to compute variance-covariance matrix of state variables
options_mom_ = set_default_option(options_mom_,'lyapunov_complex_threshold',1e-15); % complex block threshold for the upper triangular matrix in symmetric Lyapunov equation solver
options_mom_ = set_default_option(options_mom_,'lyapunov_fixed_point_tol',1e-10); % convergence criterion used in the fixed point Lyapunov solver
options_mom_ = set_default_option(options_mom_,'lyapunov_doubling_tol',1e-16); % convergence criterion used in the doubling algorithm
options_mom_ = set_default_option(options_mom_,'sylvester_fp',false); % determines whether to use fixed point algorihtm to solve Sylvester equation (gensylv_fp), faster for large scale models
options_mom_ = set_default_option(options_mom_,'sylvester_fixed_point_tol',1e-12); % convergence criterion used in the fixed point Sylvester solver
options_mom_ = set_default_option(options_mom_,'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
% if there are no unit roots one can use 1.0 (or slightly below) which we set as default; if they are possible, you may have have multiple unit roots and the accuracy decreases when computing the eigenvalues in lyapunov_symm
% Note that unit roots are only possible at first-order, at higher order we set it to 1 in pruned_state_space_system and focus only on stationary observables.
options_mom_ = set_default_option(options_mom_,'qz_zero_threshold',1e-6); % value used to test if a generalized eigenvalue is 0/0 in the generalized Schur decomposition
options_mom_ = set_default_option(options_mom_,'schur_vec_tol',1e-11); % tolerance level used to find nonstationary variables in Schur decomposition of the transition matrix.
options_mom_ = set_default_option(options_mom_,'trust_region_initial_step_bound_factor',1); % used in dynare_solve for trust_region
if options_mom_.order > 2
fprintf('Dynare will use ''k_order_solver'' as the order>2\n');
options_mom_.k_order_solver = true;
end
% -------------------------------------------------------------------------
% Step 1b: Options that are set by the preprocessor and need to be carried over
% -------------------------------------------------------------------------
% options related to VAROBS
if ~isfield(options_,'varobs')
error('method_of_moments: VAROBS statement is missing!')
else
options_mom_.varobs = options_.varobs; % observable variables in declaration order
options_mom_.obs_nbr = length(options_mom_.varobs); % number of observed variables
% Check that each declared observed variable is also an endogenous variable
for i = 1:options_mom_.obs_nbr
if ~any(strcmp(options_mom_.varobs{i},M_.endo_names))
error(['method_of_moments: Unknown variable (' options_mom_.varobs{i} ')!'])
end
end
% Check that a variable is not declared as observed more than once
if length(unique(options_mom_.varobs))<length(options_mom_.varobs)
for i = 1:options_mom_.obs_nbr
if sum(strcmp(options_mom_.varobs{i},options_mom_.varobs))>1
error(['method_of_moments: A variable cannot be declared as observed more than once (' options_mom_.varobs{i} ')!'])
end
end
end
end
% options related to variable declarations
if isfield(options_,'trend_coeffs')
error('method_of_moments: %s does not allow for trend in data',options_mom_.mom.mom_method)
end
% options related to estimated_params and estimated_params_init
options_mom_.use_calibration_initialization = options_.use_calibration_initialization;
% options related to model block
options_mom_.linear = options_.linear;
options_mom_.use_dll = options_.use_dll;
options_mom_.block = options_.block;
options_mom_.bytecode = options_.bytecode;
% options related to steady command
options_mom_.homotopy_force_continue = options_.homotopy_force_continue;
options_mom_.homotopy_mode = options_.homotopy_mode;
options_mom_.homotopy_steps = options_.homotopy_steps;
options_mom_.markowitz = options_.markowitz;
options_mom_.solve_algo = options_.solve_algo;
options_mom_.solve_tolf = options_.solve_tolf;
options_mom_.solve_tolx = options_.solve_tolx;
options_mom_.steady = options_.steady;
options_mom_.steadystate = options_.steadystate;
options_mom_.steadystate_flag = options_.steadystate_flag;
% options related to dataset
options_mom_.dataset = options_.dataset;
options_mom_.initial_period = options_.initial_period;
% options related to endogenous prior restrictions are not supported
options_mom_.endogenous_prior_restrictions.irf = {};
options_mom_.endogenous_prior_restrictions.moment = {};
if ~isempty(options_.endogenous_prior_restrictions.irf) && ~isempty(options_.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 = 1, 3, 7, 11, 102, 11, 13
% nothing to be done
% mode_compute = 2
options_mom_.saopt = options_.saopt;
% mode_compute = 4
options_mom_.csminwel = options_.csminwel;
% mode_compute = 5
options_mom_.newrat = options_.newrat;
options_mom_.gstep = options_.gstep;
% mode_compute = 6
options_mom_.gmhmaxlik = options_.gmhmaxlik;
options_mom_.mh_jscale = options_.mh_jscale;
% mode_compute = 8
options_mom_.simplex = options_.simplex;
% mode_compute = 9
options_mom_.cmaes = options_.cmaes;
% mode_compute = 10
options_mom_.simpsa = options_.simpsa;
% mode_compute = 12
options_mom_.particleswarm = options_.particleswarm;
% mode_compute = 101
options_mom_.solveopt = options_.solveopt;
options_mom_.gradient_method = options_.gradient_method;
options_mom_.gradient_epsilon = options_.gradient_epsilon;
options_mom_.analytic_derivation = 0;
options_mom_.analytic_derivation_mode = 0; % needed by get_perturbation_params_derivs.m, ie use efficient sylvester equation method to compute analytical derivatives as in Ratto & Iskrev (2012)
options_mom_.vector_output= false; % specifies whether the objective function returns a vector
optimizer_vec=[options_mom_.mode_compute;num2cell(options_mom_.additional_optimizer_steps)]; % at each stage one can possibly use different optimizers sequentially
analytic_jacobian_optimizers = [1, 3, 4, 13, 101]; %these are currently supported, see to-do list
% -------------------------------------------------------------------------
% Step 1d: Other options that need to be initialized
% -------------------------------------------------------------------------
options_mom_.initialize_estimated_parameters_with_the_prior_mode = 0; % needed by set_prior.m
options_mom_.figures.textwidth = 0.8; %needed by plot_priors.m
options_mom_.ramsey_policy = 0; % needed by evaluate_steady_state
options_mom_ = set_default_option(options_mom_,'debug',false); %neeeded by e.g. check_plot
options_mom_.risky_steadystate = false; %needed by resol
options_mom_.threads = options_.threads; %needed by resol
options_mom_.jacobian_flag = true;
options_mom_.gstep = options_.gstep;
% 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;
%options_mom_ = set_default_option(options_mom_,'endo_vars_for_moment_computations_in_estimation',[]);
% -------------------------------------------------------------------------
% Step 1e: Get variable orderings and state space representation
% -------------------------------------------------------------------------
oo_.dr = set_state_space(oo_.dr,M_,options_mom_);
% Get index of observed variables in DR order
oo_.dr.obs_var = [];
for i=1:options_mom_.obs_nbr
oo_.dr.obs_var = [oo_.dr.obs_var; find(strcmp(options_mom_.varobs{i}, M_.endo_names(oo_.dr.order_var)))];
end
% -------------------------------------------------------------------------
% Step 2: Checks and transformations for matched_moments structure
% -------------------------------------------------------------------------
M_.matched_moments_orig = M_.matched_moments; %save original structure
% higher-order product moments not supported yet for GMM
if strcmp(options_mom_.mom.mom_method, 'GMM') && any(cellfun(@sum,M_.matched_moments(:,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 for duplicate moment conditions
for jm=1:size(M_.matched_moments,1)
% expand powers to vector of ones
if any(M_.matched_moments{jm,3}>1)
tmp1=[]; tmp2=[]; tmp3=[];
for jjm=1:length(M_.matched_moments{jm,3})
tmp1 = [tmp1 repmat(M_.matched_moments{jm,1}(jjm),[1 M_.matched_moments{jm,3}(jjm)]) ];
tmp2 = [tmp2 repmat(M_.matched_moments{jm,2}(jjm),[1 M_.matched_moments{jm,3}(jjm)]) ];
tmp3 = [tmp3 repmat(1,[1 M_.matched_moments{jm,3}(jjm)]) ];
end
M_.matched_moments{jm,1} = tmp1;
M_.matched_moments{jm,2} = tmp2;
M_.matched_moments{jm,3} = tmp3;
end
% shift time structure to focus only on lags
M_.matched_moments{jm,2} = M_.matched_moments{jm,2} - max(M_.matched_moments{jm,2});
% sort such that t=0 variable comes first
[M_.matched_moments{jm,2},idx_sort] = sort(M_.matched_moments{jm,2},'descend');
M_.matched_moments{jm,1} = M_.matched_moments{jm,1}(idx_sort);
M_.matched_moments{jm,3} = M_.matched_moments{jm,3}(idx_sort);
end
% find duplicate rows in cell array by making groups according to powers as we can then use cell2mat for the unique function
powers = cellfun(@sum,M_.matched_moments(:,3))';
UniqueMomIdx = [];
for jpow = unique(powers)
idx1 = find(powers==jpow);
[~,idx2] = unique(cell2mat(M_.matched_moments(idx1,:)),'rows');
UniqueMomIdx = [UniqueMomIdx idx1(idx2)];
end
% remove duplicate elements
DuplicateMoms = setdiff(1:size(M_.matched_moments_orig,1),UniqueMomIdx);
if ~isempty(DuplicateMoms)
fprintf('Found and removed duplicate declared moments in ''matched_moments'' block in rows:\n %s.\n',num2str(DuplicateMoms))
fprintf('Dynare will continue with remaining moment conditions\n');
end
if strcmp(options_mom_.mom.mom_method, 'SMM')
% for SMM we can keep the original structure but get rid of duplicate moments
M_.matched_moments = M_.matched_moments_orig(sort(UniqueMomIdx),:);
elseif strcmp(options_mom_.mom.mom_method, 'GMM')
% for GMM we use the transformed matched_moments structure
M_.matched_moments = M_.matched_moments(sort(UniqueMomIdx),:);
end
% Check if both prefilter and first moments were specified
first_moment_indicator = find(cellfun(@(x) sum(abs(x))==1,M_.matched_moments(:,3)))';
if options_mom_.prefilter && ~isempty(first_moment_indicator)
fprintf('Centered moments requested (prefilter option is set); therefore, ignore declared first moments in ''matched_moments'' block.\n');
M_.matched_moments(first_moment_indicator,:)=[]; %remove first moments entries
end
options_mom_.mom.mom_nbr = size(M_.matched_moments,1);
% Get maximum lag number for autocovariances/autocorrelations
options_mom_.ar = max(cellfun(@max,M_.matched_moments(:,2))) - min(cellfun(@min,M_.matched_moments(:,2)));
%check that only observed variables are involved in moments
not_observed_variables=setdiff(oo_.dr.inv_order_var([M_.matched_moments{:,1}]),oo_.dr.obs_var);
if ~isempty(not_observed_variables)
error('\nmethod_of_moments: You specified moments involving %s, but it is not a varobs.',M_.endo_names{oo_.dr.order_var(not_observed_variables)})
end
% -------------------------------------------------------------------------
% Step 3: Checks and transformations for estimated parameters, priors, and bounds
% -------------------------------------------------------------------------
% Set priors and bounds over the estimated parameters
[xparam0, estim_params_, bayestopt_, lb, ub, M_] = set_prior(estim_params_, M_, options_mom_);
% Check measurement errors
if (estim_params_.nvn || estim_params_.ncn) && strcmp(options_mom_.mom.mom_method, 'GMM')
error('method_of_moments: GMM estimation does not support measurement error(s) yet. Please specifiy them as a structural shock.')
end
% Check if enough moments for estimation
if options_mom_.mom.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')
% Check if a _prior_restrictions.m file exists
if exist([M_.fname '_prior_restrictions.m'],'file')
options_mom_.prior_restrictions.status = 1;
options_mom_.prior_restrictions.routine = str2func([M_.fname '_prior_restrictions']);
end
bayestopt_laplace=bayestopt_;
% Check on specified priors and penalized estimation
if any(bayestopt_laplace.pshape > 0) % prior specified
if ~options_mom_.mom.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',options_mom_.mom.mom_method)
options_mom_.mom.penalized_estimator=1;
end
if any(setdiff([0;bayestopt_laplace.pshape],[0,3]))
fprintf('\nNon-normal priors specified. %s with penalty uses a Laplace type of approximation.\n',options_mom_.mom.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')
non_normal_priors=bayestopt_laplace.pshape~=3;
bayestopt_laplace.pshape(non_normal_priors) = 3;
bayestopt_laplace.p3(non_normal_priors) = -Inf*ones(sum(non_normal_priors),1);
bayestopt_laplace.p4(non_normal_priors) = Inf*ones(sum(non_normal_priors),1);
bayestopt_laplace.p6(non_normal_priors) = bayestopt_laplace.p1(non_normal_priors);
bayestopt_laplace.p7(non_normal_priors) = bayestopt_laplace.p2(non_normal_priors);
bayestopt_laplace.p5(non_normal_priors) = bayestopt_laplace.p1(non_normal_priors);
end
if any(isinf(bayestopt_laplace.p2)) %find infinite variance priors
inf_var_pars=bayestopt_laplace.name(isinf(bayestopt_laplace.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')
if isoctave
warning('off','Octave:singular-matrix');
else
warning('off','MATLAB:singularMatrix');
end
end
end
% Check for calibrated covariances before updating parameters
estim_params_ = check_for_calibrated_covariances(xparam0,estim_params_,M_);
% Checks on parameter calibration and initialization
xparam1_calib = get_all_parameters(estim_params_,M_); %get calibrated parameters
if ~any(isnan(xparam1_calib)) %all estimated parameters are calibrated
estim_params_.full_calibration_detected=1;
else
estim_params_.full_calibration_detected=0;
end
if options_mom_.use_calibration_initialization %set calibration as starting values
if ~isempty(bayestopt_laplace) && all(bayestopt_laplace.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 explicitly initialized.',options_mom_.mom.mom_method)
else
[xparam0,estim_params_]=do_parameter_initialization(estim_params_,xparam1_calib,xparam0); %get explicitly initialized parameters that have precedence over calibrated values
end
end
% Check initialization
if ~isempty(bayestopt_laplace) && all(bayestopt_laplace.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 ',options_mom_.mom.mom_method)
end
% Set and check parameter bounds
if ~isempty(bayestopt_laplace) && any(bayestopt_laplace.pshape > 0)
% Plot prior densities
if ~options_mom_.nograph && options_mom_.plot_priors
plot_priors(bayestopt_,M_,estim_params_,options_mom_)
plot_priors(bayestopt_laplace,M_,estim_params_,options_mom_,'Laplace approximated priors')
end
% Set prior bounds
Bounds = prior_bounds(bayestopt_laplace, options_mom_.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;
if options_mom_.mom.penalized_estimator
fprintf('Penalized estimation turned off as you did not declare priors\n')
options_mom_.mom.penalized_estimator = 0;
end
end
% Set correct bounds for standard deviations and corrrelations
param_of_interest=(1:length(xparam0))'<=estim_params_.nvx+estim_params_.nvn;
LB_below_0=(Bounds.lb<0 & param_of_interest);
Bounds.lb(LB_below_0)=0;
param_of_interest=(1:length(xparam0))'> estim_params_.nvx+estim_params_.nvn & (1:length(xparam0))'<estim_params_.nvx+estim_params_.nvn +estim_params_.ncx + estim_params_.ncn;
LB_below_minus_1=(Bounds.lb<-1 & param_of_interest);
UB_above_1=(Bounds.ub>1 & param_of_interest);
Bounds.lb(LB_below_minus_1)=-1;
Bounds.ub(UB_above_1)=1;
clear('bayestopt_','LB_below_0','LB_below_minus_1','UB_above_1','param_of_interest');%make sure stale structure cannot be used
% Test if initial values of the estimated parameters are all between the prior lower and upper bounds
if options_mom_.use_calibration_initialization
try
check_prior_bounds(xparam0,Bounds,M_,estim_params_,options_mom_,bayestopt_laplace)
catch last_error
fprintf('Cannot use parameter values from calibration as they violate the prior bounds.')
rethrow(last_error);
end
else
check_prior_bounds(xparam0,Bounds,M_,estim_params_,options_mom_,bayestopt_laplace)
end
estim_params_= get_matrix_entries_for_psd_check(M_,estim_params_);
% Set sigma_e_is_diagonal flag (needed if the shocks block is not declared in the mod file).
M_.sigma_e_is_diagonal = true;
if estim_params_.ncx || any(nnz(tril(M_.Correlation_matrix,-1))) || isfield(estim_params_,'calibrated_covariances')
M_.sigma_e_is_diagonal = false;
end
% storing prior parameters in MoM info structure for penalized minimization
oo_.prior.mean = bayestopt_laplace.p1;
oo_.prior.variance = diag(bayestopt_laplace.p2.^2);
% Set all parameters
M_ = set_all_parameters(xparam0,estim_params_,M_);
%provide warning if there is NaN in parameters
test_for_deep_parameters_calibration(M_);
% -------------------------------------------------------------------------
% Step 4: Checks and transformations for data
% -------------------------------------------------------------------------
% Check if datafile has same name as mod file
[~,name,~] = fileparts(options_mom_.datafile);
if strcmp(name,M_.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
% Build dataset
dataset_ = makedataset(options_mom_);
% set options for old interface from the ones for new interface
if ~isempty(dataset_)
options_mom_.nobs = dataset_.nobs;
end
% Check length of data for estimation of second moments
if options_mom_.ar > options_mom_.nobs+1
error('method_of_moments: Data set is too short to compute second moments');
end
% Provide info on data moments handling
fprintf('Computing data moments. Note that NaN values in the moments (due to leads and lags or missing data) are replaced by the mean of the corresponding moment\n');
% Get data moments for the method of moments
[oo_.mom.data_moments, oo_.mom.m_data] = mom.data_moments(dataset_.data, oo_, M_.matched_moments, options_mom_);
% Get shock series for SMM and set variance correction factor
if strcmp(options_mom_.mom.mom_method,'SMM')
options_mom_.mom.long = round(options_mom_.mom.simulation_multiple*options_mom_.nobs);
options_mom_.mom.variance_correction_factor = (1+1/options_mom_.mom.simulation_multiple);
% draw shocks for SMM
if ~isoctave
smmstream = RandStream('mt19937ar','Seed',options_mom_.mom.seed);
temp_shocks = randn(smmstream,options_mom_.mom.long+options_mom_.mom.burnin,M_.exo_nbr);
temp_shocks_ME = randn(smmstream,options_mom_.mom.long,length(M_.H));
else
[state_u,state_n] = get_dynare_random_generator_state; %get state for later resetting
set_dynare_random_generator_state(options_mom_.mom.seed,options_mom_.mom.seed);
temp_shocks = randn(options_mom_.mom.long+options_mom_.mom.burnin,M_.exo_nbr);
temp_shocks_ME = randn(options_mom_.mom.long,length(M_.H));
set_dynare_random_generator_state(state_u,state_n); %reset state for later resetting
end
if options_mom_.mom.bounded_shock_support == 1
temp_shocks(temp_shocks>2) = 2;
temp_shocks(temp_shocks<-2) = -2;
temp_shocks_ME(temp_shocks_ME<-2) = -2;
temp_shocks_ME(temp_shocks_ME<-2) = -2;
end
options_mom_.mom.shock_series = temp_shocks;
options_mom_.mom.ME_shock_series = temp_shocks_ME;
if options_mom_.k_order_solver && ~options_mom_.pruning % dynare++ routines will be called in simult_.m, store some additional stuff
options_mom_.DynareRandomStreams.seed = options_mom_.mom.seed;
end
end
% -------------------------------------------------------------------------
% Step 5: checks for steady state at initial parameters
% -------------------------------------------------------------------------
% setting steadystate_check_flag option
if options_mom_.steadystate.nocheck
steadystate_check_flag = 0;
else
steadystate_check_flag = 1;
end
old_steady_params=M_.params; %save initial parameters for check if steady state changes param values
% Check steady state at initial model parameter values
[oo_.steady_state, new_steady_params, info] = evaluate_steady_state(oo_.steady_state,M_,options_mom_,oo_,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, options_mom_);
end
% check whether steady state file changes estimated parameters
if isfield(estim_params_,'param_vals') && ~isempty(estim_params_.param_vals)
Model_par_varied=M_; %store M_ structure
Model_par_varied.params(estim_params_.param_vals(:,1))=Model_par_varied.params(estim_params_.param_vals(:,1))*1.01; %vary parameters
[~, new_steady_params_2] = evaluate_steady_state(oo_.steady_state,Model_par_varied,options_mom_,oo_,1);
changed_par_indices=find((old_steady_params(estim_params_.param_vals(:,1))-new_steady_params(estim_params_.param_vals(:,1))) ...
| (Model_par_varied.params(estim_params_.param_vals(:,1))-new_steady_params_2(estim_params_.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(M_.param_names(estim_params_.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.')
if strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_standard_errors
fprintf('For analytical standard errors, the parameter-Jacobians of the dynamic model and of the steady-state will be computed numerically\n'),
fprintf('(re-set options_mom_.analytic_derivation_mode= -2)'),
options_mom_.analytic_derivation_mode= -2;
end
end
end
% display warning if some parameters are still NaN
test_for_deep_parameters_calibration(M_);
% If steady state of observed variables is non zero, set noconstant equal 0
if all(abs(oo_.steady_state(oo_.dr.order_var(oo_.dr.obs_var)))<1e-9)
options_mom_.noconstant = 0; %identifying the constant based on just the initial parameter value is not feasible
else
options_mom_.noconstant = 0;
end
% -------------------------------------------------------------------------
% Step 6: checks for objective function at initial parameters
% -------------------------------------------------------------------------
objective_function = str2func('mom.objective_function');
try
% Check for NaN or complex values of moment-distance-funtion evaluated
% at initial parameters and identity weighting matrix
oo_.mom.Sw = eye(options_mom_.mom.mom_nbr);
tic_id = tic;
[fval, info, ~, ~, ~, oo_, M_] = feval(objective_function, xparam0, Bounds, oo_, estim_params_, M_, options_mom_);
elapsed_time = toc(tic_id);
if isnan(fval)
error('method_of_moments: The initial value of the objective function is NaN')
elseif imag(fval)
error('method_of_moments: The initial value of the objective function is complex')
end
if info(1) > 0
disp('method_of_moments: Error in computing the objective function for initial parameter values')
print_info(info, options_mom_.noprint, options_mom_)
end
fprintf('Initial value of the moment objective function with %4.1f times identity weighting matrix: %6.4f \n\n', options_mom_.mom.weighting_matrix_scaling_factor, fval);
fprintf('Time required to compute objective function once: %5.4f seconds \n', elapsed_time);
catch last_error% if check fails, provide info on using calibration if present
if estim_params_.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(last_error);
end
% -------------------------------------------------------------------------
% Step 7a: Method of moments estimation: print some info
% -------------------------------------------------------------------------
fprintf('\n---------------------------------------------------\n')
if strcmp(options_mom_.mom.mom_method,'SMM')
fprintf('Simulated method of moments with');
elseif strcmp(options_mom_.mom.mom_method,'GMM')
fprintf('General method of moments with');
end
if options_mom_.prefilter
fprintf('\n - centered moments (prefilter=1)');
else
fprintf('\n - uncentered moments (prefilter=0)');
end
if options_mom_.mom.penalized_estimator
fprintf('\n - penalized estimation using deviation from prior mean and weighted with prior precision');
end
for i = 1:length(optimizer_vec)
if i == 1
str = '- optimizer (mode_compute';
else
str = ' (additional_optimizer_steps';
end
switch optimizer_vec{i}
case 0
fprintf('\n %s=0): no minimization',str);
case 1
fprintf('\n %s=1): fmincon',str);
case 2
fprintf('\n %s=2): continuous simulated annealing',str);
case 3
fprintf('\n %s=3): fminunc',str);
case 4
fprintf('\n %s=4): csminwel',str);
case 5
fprintf('\n %s=5): newrat',str);
case 6
fprintf('\n %s=6): gmhmaxlik',str);
case 7
fprintf('\n %s=7): fminsearch',str);
case 8
fprintf('\n %s=8): Dynare Nelder-Mead simplex',str);
case 9
fprintf('\n %s=9): CMA-ES',str);
case 10
fprintf('\n %s=10): simpsa',str);
case 11
error('\nmethod_of_moments: online_auxiliary_filter (mode_compute=11) is only supported with likelihood-based estimation techniques');
case 12
fprintf('\n %s=12): particleswarm',str);
case 101
fprintf('\n %s=101): SolveOpt',str);
case 102
fprintf('\n %s=102): simulannealbnd',str);
case 13
fprintf('\n %s=13): lsqnonlin',str);
otherwise
if ischar(optimizer_vec{i})
fprintf('\n %s=%s): user-defined',str,optimizer_vec{i});
else
error('method_of_moments: Unknown optimizer, please contact the developers ')
end
end
if options_mom_.silent_optimizer
fprintf(' (silent)');
end
if strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_jacobian && ismember(optimizer_vec{i},analytic_jacobian_optimizers)
fprintf(' (using analytical Jacobian)');
end
end
fprintf('\n - perturbation order: %d', options_mom_.order)
if options_mom_.order > 1 && options_mom_.pruning
fprintf(' (with pruning)')
end
if strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_standard_errors
fprintf('\n - standard errors: analytic derivatives');
else
fprintf('\n - standard errors: numerical derivatives');
end
fprintf('\n - number of matched moments: %d', options_mom_.mom.mom_nbr);
fprintf('\n - number of parameters: %d', length(xparam0));
fprintf('\n\n');
% -------------------------------------------------------------------------
% Step 7b: Iterated method of moments estimation
% -------------------------------------------------------------------------
if size(options_mom_.mom.weighting_matrix,1)>1 && ~(any(strcmpi('diagonal',options_mom_.mom.weighting_matrix)) || any(strcmpi('optimal',options_mom_.mom.weighting_matrix)))
fprintf('\nYou did not specify the use of an optimal or diagonal weighting matrix. There is no point in running an iterated method of moments.\n')
end
for stage_iter=1:size(options_mom_.mom.weighting_matrix,1)
fprintf('Estimation stage %u\n',stage_iter);
Woptflag = false;
switch lower(options_mom_.mom.weighting_matrix{stage_iter})
case 'identity_matrix'
fprintf(' - identity weighting matrix\n');
weighting_matrix = eye(options_mom_.mom.mom_nbr);
case 'diagonal'
fprintf(' - diagonal of optimal weighting matrix (Bartlett kernel with %d lags)\n', options_mom_.mom.bartlett_kernel_lag);
if stage_iter == 1
fprintf(' and using data-moments as initial estimate of model-moments\n');
weighting_matrix = diag(diag( mom.optimal_weighting_matrix(oo_.mom.m_data, oo_.mom.data_moments, options_mom_.mom.bartlett_kernel_lag) ));
else
fprintf(' and using previous stage estimate of model-moments\n');
weighting_matrix = diag(diag( mom.optimal_weighting_matrix(oo_.mom.m_data, oo_.mom.model_moments, options_mom_.mom.bartlett_kernel_lag) ));
end
case 'optimal'
fprintf(' - optimal weighting matrix (Bartlett kernel with %d lags)\n', options_mom_.mom.bartlett_kernel_lag);
if stage_iter == 1
fprintf(' and using data-moments as initial estimate of model-moments\n');
weighting_matrix = mom.optimal_weighting_matrix(oo_.mom.m_data, oo_.mom.data_moments, options_mom_.mom.bartlett_kernel_lag);
else
fprintf(' and using previous stage estimate of model-moments\n');
weighting_matrix = mom.optimal_weighting_matrix(oo_.mom.m_data, oo_.mom.model_moments, options_mom_.mom.bartlett_kernel_lag);
Woptflag = true;
end
otherwise %user specified matrix in file
fprintf(' - user-specified weighting matrix\n');
try
load(options_mom_.mom.weighting_matrix{stage_iter},'weighting_matrix')
catch
error(['method_of_moments: No matrix named ''weighting_matrix'' could be found in ',options_mom_.mom.weighting_matrix{stage_iter},'.mat'])
end
[nrow, ncol] = size(weighting_matrix);
if ~isequal(nrow,ncol) || ~isequal(nrow,length(oo_.mom.data_moments)) %check if square and right size
error(['method_of_moments: weighting_matrix must be square and have ',num2str(length(oo_.mom.data_moments)),' rows and columns'])
end
end
try %check for positive definiteness of weighting_matrix
oo_.mom.Sw = chol(weighting_matrix);
catch
error('method_of_moments: Specified weighting_matrix is not positive definite. Check whether your model implies stochastic singularity.')
end
for optim_iter= 1:length(optimizer_vec)
options_mom_.current_optimizer = optimizer_vec{optim_iter};
if optimizer_vec{optim_iter}==0
xparam1=xparam0; %no minimization, evaluate objective at current values
fval = feval(objective_function, xparam1, Bounds, oo_, estim_params_, M_, options_mom_);
else
if optimizer_vec{optim_iter}==13
options_mom_.vector_output = true;
else
options_mom_.vector_output = false;
end
if strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_jacobian && ismember(optimizer_vec{optim_iter},analytic_jacobian_optimizers) %do this only for gradient-based optimizers
options_mom_.mom.compute_derivs = true;
else
options_mom_.mom.compute_derivs = false;
end
[xparam1, fval, exitflag] = dynare_minimize_objective(objective_function, xparam0, optimizer_vec{optim_iter}, options_mom_, [Bounds.lb Bounds.ub], bayestopt_laplace.name, bayestopt_laplace, [],...
Bounds, oo_, estim_params_, M_, options_mom_);
if options_mom_.vector_output
fval = fval'*fval;
end
end
fprintf('\nStage %d Iteration %d: value of minimized moment distance objective function: %12.10f.\n',stage_iter,optim_iter,fval)
if options_mom_.mom.verbose
oo_.mom=display_estimation_results_table(xparam1,NaN(size(xparam1)),M_,options_mom_,estim_params_,bayestopt_laplace,oo_.mom,prior_dist_names,sprintf('%s (STAGE %d ITERATION %d) VERBOSE',options_mom_.mom.mom_method,stage_iter,optim_iter),sprintf('verbose_%s_stage_%d_iter_%d',lower(options_mom_.mom.mom_method),stage_iter,optim_iter));
end
xparam0=xparam1;
end
options_mom_.vector_output = false;
% Update M_ and DynareResults (in particular to get oo_.mom.model_moments)
M_ = set_all_parameters(xparam1,estim_params_,M_);
if strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_standard_errors
options_mom_.mom.compute_derivs = true; % for GMM we compute derivatives analytically in the objective function with this flag
end
[fval, ~, ~,~,~, oo_] = feval(objective_function, xparam1, Bounds, oo_, estim_params_, M_, options_mom_);
options_mom_.mom.compute_derivs = false; % reset to not compute derivatives in objective function during optimization
SE = mom.standard_errors(xparam1, objective_function, Bounds, oo_, estim_params_, M_, options_mom_, Woptflag);
% Store results in output structure
oo_.mom = display_estimation_results_table(xparam1,SE,M_,options_mom_,estim_params_,bayestopt_laplace,oo_.mom,prior_dist_names,sprintf('%s (STAGE %u)',options_mom_.mom.mom_method,stage_iter),sprintf('%s_stage_%u',lower(options_mom_.mom.mom_method),stage_iter));
end
% -------------------------------------------------------------------------
% Step 8: J test
% -------------------------------------------------------------------------
if options_mom_.mom.mom_nbr > length(xparam1)
%get optimal weighting matrix for J test, if necessary
if ~Woptflag
W_opt = mom.optimal_weighting_matrix(oo_.mom.m_data, oo_.mom.model_moments, options_mom_.mom.bartlett_kernel_lag);
oo_j=oo_;
oo_j.mom.Sw = chol(W_opt);
[fval] = feval(objective_function, xparam1, Bounds, oo_j, estim_params_, M_, options_mom_);
end
% Compute J statistic
if strcmp(options_mom_.mom.mom_method,'SMM')
Variance_correction_factor = options_mom_.mom.variance_correction_factor;
elseif strcmp(options_mom_.mom.mom_method,'GMM')
Variance_correction_factor=1;
end
oo_.mom.J_test.j_stat = dataset_.nobs*Variance_correction_factor*fval/options_mom_.mom.weighting_matrix_scaling_factor;
oo_.mom.J_test.degrees_freedom = length(oo_.mom.model_moments)-length(xparam1);
oo_.mom.J_test.p_val = 1-chi2cdf(oo_.mom.J_test.j_stat, oo_.mom.J_test.degrees_freedom);
fprintf('\nvalue of J-test statistic: %f\n',oo_.mom.J_test.j_stat)
fprintf('p-value of J-test statistic: %f\n',oo_.mom.J_test.p_val)
end
% -------------------------------------------------------------------------
% Step 9: Display estimation results
% -------------------------------------------------------------------------
title = ['Comparison of data moments and model moments (',options_mom_.mom.mom_method,')'];
headers = {'Moment','Data','Model'};
for jm = 1:size(M_.matched_moments,1)
lables_tmp = 'E[';
lables_tmp_tex = 'E \left[ ';
for jvar = 1:length(M_.matched_moments{jm,1})
lables_tmp = [lables_tmp M_.endo_names{M_.matched_moments{jm,1}(jvar)}];
lables_tmp_tex = [lables_tmp_tex, '{', M_.endo_names_tex{M_.matched_moments{jm,1}(jvar)}, '}'];
if M_.matched_moments{jm,2}(jvar) ~= 0
lables_tmp = [lables_tmp, '(', num2str(M_.matched_moments{jm,2}(jvar)), ')'];
lables_tmp_tex = [lables_tmp_tex, '_{t', num2str(M_.matched_moments{jm,2}(jvar)), '}'];
else
lables_tmp_tex = [lables_tmp_tex, '_{t}'];
end
if M_.matched_moments{jm,3}(jvar) > 1
lables_tmp = [lables_tmp, '^', num2str(M_.matched_moments{jm,3}(jvar))];
lables_tmp_tex = [lables_tmp_tex, '^{', num2str(M_.matched_moments{jm,3}(jvar)) '}'];
end
if jvar == length(M_.matched_moments{jm,1})
lables_tmp = [lables_tmp, ']'];
lables_tmp_tex = [lables_tmp_tex, ' \right]'];
else
lables_tmp = [lables_tmp, '*'];
lables_tmp_tex = [lables_tmp_tex, ' \times '];
end
end
labels{jm,1} = lables_tmp;
labels_TeX{jm,1} = lables_tmp_tex;
end
data_mat=[oo_.mom.data_moments oo_.mom.model_moments ];
dyntable(options_mom_, title, headers, labels, data_mat, cellofchararraymaxlength(labels)+2, 10, 7);
if options_mom_.TeX
dyn_latex_table(M_, options_mom_, title, ['comparison_moments_', options_mom_.mom.mom_method], headers, labels_TeX, data_mat, cellofchararraymaxlength(labels)+2, 10, 7);
end
if options_mom_.mode_check.status
mom.check_plot(objective_function,xparam1,SE,options_mom_,M_,estim_params_,Bounds,bayestopt_laplace,...
Bounds, oo_, estim_params_, M_, options_mom_)
end
fprintf('\n==== Method of Moments Estimation (%s) Completed ====\n\n',options_mom_.mom.mom_method)
% -------------------------------------------------------------------------
% Step 9: Clean up
% -------------------------------------------------------------------------
%reset warning state
if isoctave
warning('on')
else
warning on
end
if isoctave && isfield(options_, 'prior_restrictions') && ...
isfield(options_.prior_restrictions, 'routine')
% Octave crashes if it tries to save function handles (to the _results.mat file)
% See https://savannah.gnu.org/bugs/?43215
options_.prior_restrictions.routine = [];
end