function oo_ = initial_estimation_checks(objective_function,xparam1,dataset_,dataset_info,M_,estim_params_,options_,bayestopt_,BoundsInfo,oo_) % function oo_ = initial_estimation_checks(objective_function,xparam1,dataset_,dataset_info,M_,estim_params_,options_,bayestopt_,BoundsInfo,oo_) % Checks data (complex values, ML evaluation, initial values, BK conditions,..) % % INPUTS % objective_function [function handle] of the objective function % xparam1 [vector] of parameters to be estimated % dataset_ [dseries] object storing the dataset % dataset_info [structure] storing informations about the sample. % M_ [structure] describing the model % estim_params_ [structure] characterizing parameters to be estimated % options_ [structure] describing the options % bayestopt_ [structure] describing the priors % BoundsInfo [structure] containing prior bounds % oo_ [structure] storing the results % % OUTPUTS % oo_ [structure] storing the results % % SPECIAL REQUIREMENTS % none % Copyright © 2003-2023 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 . %get maximum number of simultaneously observed variables for stochastic %singularity check maximum_number_non_missing_observations=max(sum(~isnan(dataset_.data(2:end,:)),2)); init_number_non_missing_observations=sum(~isnan(dataset_.data(1,:)),2); if options_.heteroskedastic_filter if options_.order>1 error('initial_estimation_checks:: heteroskedastic shocks are only supported with the Kalman filter/smoother') end observations_by_period=sum(~isnan(dataset_.data),2); base_shocks = find(diag(M_.Sigma_e)); zero_shocks = ~ismember(1:M_.exo_nbr,base_shocks); non_zero_shocks_by_period=repmat(length(base_shocks),size(observations_by_period)); % check periods for which base shocks are scaled to zero non_zero_shocks_by_period = non_zero_shocks_by_period-sum(M_.heteroskedastic_shocks.Qscale(base_shocks,1:options_.nobs)==0,1)'; % check periods for which base shocks are set to zero non_zero_shocks_by_period = non_zero_shocks_by_period-sum(M_.heteroskedastic_shocks.Qvalue(base_shocks,1:options_.nobs)==0,1)'; % check periods for which other shocks are set to a positive number non_zero_shocks_by_period = non_zero_shocks_by_period+sum(M_.heteroskedastic_shocks.Qvalue(zero_shocks,1:options_.nobs)>0,1)'; end if options_.order>1 if any(any(isnan(dataset_.data))) error('initial_estimation_checks:: particle filtering does not support missing observations') end if options_.prefilter==1 error('initial_estimation_checks:: particle filtering does not support the prefilter option') end if bayestopt_.with_trend error('initial_estimation_checks:: particle filtering does not support trends') end if options_.order>3 && options_.particle.pruning==1 error('initial_estimation_checks:: the particle filter with order>3 does not support pruning') end if options_.particle.pruning~=options_.pruning warning('initial_estimation_checks:: the pruning settings differ between the particle filter and the one used for IRFs/simulations. Make sure this is intended.') end end if options_.occbin.likelihood.status || options_.occbin.smoother.status if options_.prefilter error('initial_estimation_checks:: Occbin is incompatible with the prefilter option due to the sample mean generally not corresponding to the steady state with an occasionally binding constraint.') end if ~options_.occbin.likelihood.inversion_filter && (options_.kalman_algo==2 || options_.kalman_algo==4) error('initial_estimation_checks:: Occbin is incompatible with the selected univariate Kalman filter.') end if options_.fast_kalman_filter error('initial_estimation_checks:: Occbin is incompatible with the fast Kalman filter.') end end if (options_.occbin.likelihood.status && options_.occbin.likelihood.inversion_filter) || (options_.occbin.smoother.status && options_.occbin.smoother.inversion_filter) err_index= find(diag(M_.Sigma_e)~=0); if length(err_index)~=length(options_.varobs) fprintf('initial_estimation_checks:: The IVF requires exactly as many shocks as observables.') end var_index=find(any(isnan(dataset_.data))); if ~isempty(var_index) fprintf('initial_estimation_checks:: The IVF requires exactly as many shocks as observables.\n') fprintf('initial_estimation_checks:: The data series %s contains NaN, I am therefore dropping shock %s for these time points.\n',... options_.varobs{var_index},M_.exo_names{options_.occbin.likelihood.IVF_shock_observable_mapping(var_index)}) end end if options_.order>1 || (options_.order==1 && ~ischar(options_.mode_compute) && options_.mode_compute==11) if options_.order==1 && options_.mode_compute==11 disp_string='mode_compute=11'; else disp_string='particle filtering'; end if M_.H==0 error('initial_estimation_checks:: %s requires measurement error on the observables',disp_string) else if sum(diag(M_.H)>0)M_.exo_nbr+non_zero_ME error(['initial_estimation_checks:: Estimation can''t take place because there are less declared shocks than observed variables!']) end if init_number_non_missing_observations>M_.exo_nbr+non_zero_ME if options_.no_init_estimation_check_first_obs print_init_check_warning=true; else error(['initial_estimation_checks:: Estimation can''t take place because there are less declared shocks than observed variables in first period!']) end end if options_.heteroskedastic_filter if any(observations_by_period>(non_zero_shocks_by_period+non_zero_ME)) error(['initial_estimation_checks:: Estimation can''t take place because too many shocks have been calibrated with a zero variance: Check heteroskedastic block and shocks calibration!']) end else if maximum_number_non_missing_observations>length(find(diag(M_.Sigma_e)))+non_zero_ME error(['initial_estimation_checks:: Estimation can''t take place because too many shocks have been calibrated with a zero variance!']) end end if init_number_non_missing_observations>length(find(diag(M_.Sigma_e)))+non_zero_ME if options_.no_init_estimation_check_first_obs print_init_check_warning=true; else error(['initial_estimation_checks:: Estimation can''t take place because too many shocks have been calibrated with a zero variance in first period!']) end end if print_init_check_warning fprintf('ESTIMATION_CHECKS: You decided to ignore test of stochastic singularity in first_obs.\n'); fprintf('ESTIMATION_CHECKS: If this was not done on purpose (typically when observing a stock variable [capital] in first period, on top of its flow [investment]),\n'); fprintf('ESTIMATION_CHECKS: it may lead to a crash or provide undesired/wrong results later on!\n'); end if (any(bayestopt_.pshape >0 ) && options_.mh_replic) && options_.mh_nblck<1 error(['initial_estimation_checks:: Bayesian estimation cannot be conducted with mh_nblocks=0.']) end % check and display warnings if steady-state solves static model (except if diffuse_filter == 1) and if steady-state changes estimated parameters [oo_.steady_state] = check_steady_state_changes_parameters(M_,estim_params_,oo_,options_, [options_.diffuse_filter==0 options_.diffuse_filter==0] ); % check and display warning if negative values of stderr or corr params are outside unit circle for Bayesian estimation if any(bayestopt_.pshape) check_prior_stderr_corr(estim_params_,bayestopt_); end % display warning if some parameters are still NaN test_for_deep_parameters_calibration(M_); [lnprior,~,~,info]= priordens(xparam1,bayestopt_.pshape,bayestopt_.p6,bayestopt_.p7,bayestopt_.p3,bayestopt_.p4); if any(info) fprintf('The prior density evaluated at the initial values is Inf for the following parameters: %s\n',bayestopt_.name{info,1}) error('The initial value of the prior is -Inf') end if isfield(M_,'filter_initial_state') && ~isempty(M_.filter_initial_state) state_indices=oo_.dr.order_var(oo_.dr.restrict_var_list(bayestopt_.mf0)); for ii=1:size(state_indices,1) if ~isempty(M_.filter_initial_state{state_indices(ii),1}) try evaluate_expression(M_.filter_initial_state{state_indices(ii),2},M_,oo_) catch fprintf('Unable to evaluate the expression\n %s \nfor the filter_initial_state of variable %s\n',M_.filter_initial_state{state_indices(ii),2},M_.endo_names(state_indices(ii),:)) end end end end if ~isreal(dataset_.data) error('initial_estimation_checks: the data contains complex values.') end % Evaluate the likelihood. ana_deriv = options_.analytic_derivation; options_.analytic_derivation=0; if ~isequal(options_.mode_compute,11) || ... (isequal(options_.mode_compute,11) && isequal(options_.order,1)) %shut off potentially automatic switch to diffuse filter for the %purpose of checking stochastic singularity use_univariate_filters_if_singularity_is_detected_old=options_.use_univariate_filters_if_singularity_is_detected; options_.use_univariate_filters_if_singularity_is_detected=0; [fval,info] = feval(objective_function,xparam1,dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,BoundsInfo,oo_.dr,oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state); if info(1)==50 fprintf('\ninitial_estimation_checks:: The forecast error variance in the multivariate Kalman filter became singular.\n') fprintf('initial_estimation_checks:: This is often a sign of stochastic singularity, but can also sometimes happen by chance\n') fprintf('initial_estimation_checks:: for a particular combination of parameters and data realizations.\n') fprintf('initial_estimation_checks:: If you think the latter is the case, you should try with different initial values for the estimated parameters.\n') error('initial_estimation_checks:: The forecast error variance in the multivariate Kalman filter became singular.') end if info(1)==201 || info(1)==202 message=get_error_message(info,options_); error('initial_estimation_checks:: %s.',message) end %reset options options_.use_univariate_filters_if_singularity_is_detected=use_univariate_filters_if_singularity_is_detected_old; else info=0; fval = 0; end if options_.debug oo_.likelihood_at_initial_parameters=fval; end options_.analytic_derivation=ana_deriv; if options_.mode_compute==13 error('Options mode_compute=13 is only compatible with quadratic objective functions') end if isnan(fval) error('The initial value of the likelihood is NaN') elseif imag(fval) error('The initial value of the likelihood is complex') end if info(1) > 0 if options_.order>1 [eigenvalues_] = check(M_,options_, oo_); if any(abs(1-abs(eigenvalues_))1e-9)) || (options_.loglinear && any(abs(log(oo_.steady_state(bayestopt_.mfys)))>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('You should change something in your mod file...') end end if ~isequal(options_.mode_compute,11) disp(['Initial value of the log posterior (or likelihood): ' num2str(-fval)]); end if options_.mh_tune_jscale.status && (options_.mh_tune_jscale.maxiter