1function DynareResults = initial_estimation_checks(objective_function,xparam1,DynareDataset,DatasetInfo,Model,EstimatedParameters,DynareOptions,BayesInfo,BoundsInfo,DynareResults)
2% function DynareResults = initial_estimation_checks(objective_function,xparam1,DynareDataset,DatasetInfo,Model,EstimatedParameters,DynareOptions,BayesInfo,BoundsInfo,DynareResults)
3% Checks data (complex values, ML evaluation, initial values, BK conditions,..)
4%
5% INPUTS
6%   objective_function  [function handle] of the objective function
7%   xparam1:            [vector] of parameters to be estimated
8%   DynareDataset:      [dseries] object storing the dataset
9%   DataSetInfo:        [structure] storing informations about the sample.
10%   Model:              [structure] decribing the model
11%   EstimatedParameters [structure] characterizing parameters to be estimated
12%   DynareOptions       [structure] describing the options
13%   BayesInfo           [structure] describing the priors
14%   BoundsInfo          [structure] containing prior bounds
15%   DynareResults       [structure] storing the results
16%
17% OUTPUTS
18%    DynareResults     structure of temporary results
19%
20% SPECIAL REQUIREMENTS
21%    none
22
23% Copyright (C) 2003-2018 Dynare Team
24%
25% This file is part of Dynare.
26%
27% Dynare is free software: you can redistribute it and/or modify
28% it under the terms of the GNU General Public License as published by
29% the Free Software Foundation, either version 3 of the License, or
30% (at your option) any later version.
31%
32% Dynare is distributed in the hope that it will be useful,
33% but WITHOUT ANY WARRANTY; without even the implied warranty of
34% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35% GNU General Public License for more details.
36%
37% You should have received a copy of the GNU General Public License
38% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
39
40%get maximum number of simultaneously observed variables for stochastic
41%singularity check
42maximum_number_non_missing_observations=max(sum(~isnan(DynareDataset.data),2));
43
44if DynareOptions.order>1
45    if any(any(isnan(DynareDataset.data)))
46        error('initial_estimation_checks:: particle filtering does not support missing observations')
47    end
48    if DynareOptions.prefilter==1
49        error('initial_estimation_checks:: particle filtering does not support the prefilter option')
50    end
51    if BayesInfo.with_trend
52        error('initial_estimation_checks:: particle filtering does not support trends')
53    end
54    if DynareOptions.order>2 && DynareOptions.particle.pruning==1
55        error('initial_estimation_checks:: the particle filter with order>2 does not support pruning')
56    end
57    if DynareOptions.particle.pruning~=DynareOptions.pruning
58        fprintf('initial_estimation_checks:: the pruning settings differ between the particle filter and the one used for IRFs/simulations. Make sure this is intended.\n')
59    end
60end
61
62non_zero_ME=length(EstimatedParameters.H_entries_to_check_for_positive_definiteness);
63
64if maximum_number_non_missing_observations>Model.exo_nbr+non_zero_ME
65    error(['initial_estimation_checks:: Estimation can''t take place because there are less declared shocks than observed variables!'])
66end
67
68if maximum_number_non_missing_observations>length(find(diag(Model.Sigma_e)))+non_zero_ME
69    error(['initial_estimation_checks:: Estimation can''t take place because too many shocks have been calibrated with a zero variance!'])
70end
71
72if (any(BayesInfo.pshape  >0 ) && DynareOptions.mh_replic) && DynareOptions.mh_nblck<1
73    error(['initial_estimation_checks:: Bayesian estimation cannot be conducted with mh_nblocks=0.'])
74end
75
76old_steady_params=Model.params; %save initial parameters for check if steady state changes param values
77
78% % check if steady state solves static model (except if diffuse_filter == 1)
79[DynareResults.steady_state, new_steady_params] = evaluate_steady_state(DynareResults.steady_state,Model,DynareOptions,DynareResults,DynareOptions.diffuse_filter==0);
80
81if isfield(EstimatedParameters,'param_vals') && ~isempty(EstimatedParameters.param_vals)
82    %check whether steady state file changes estimated parameters
83    Model_par_varied=Model; %store Model structure
84    Model_par_varied.params(EstimatedParameters.param_vals(:,1))=Model_par_varied.params(EstimatedParameters.param_vals(:,1))*1.01; %vary parameters
85    [~, new_steady_params_2] = evaluate_steady_state(DynareResults.steady_state,Model_par_varied,DynareOptions,DynareResults,DynareOptions.diffuse_filter==0);
86
87    changed_par_indices=find((old_steady_params(EstimatedParameters.param_vals(:,1))-new_steady_params(EstimatedParameters.param_vals(:,1))) ...
88                             | (Model_par_varied.params(EstimatedParameters.param_vals(:,1))-new_steady_params_2(EstimatedParameters.param_vals(:,1))));
89
90    if ~isempty(changed_par_indices)
91        fprintf('\nThe steady state file internally changed the values of the following estimated parameters:\n')
92        disp(char(Model.param_names(EstimatedParameters.param_vals(changed_par_indices,1))))
93        fprintf('This will override the parameter values drawn from the proposal density and may lead to wrong results.\n')
94        fprintf('Check whether this is really intended.\n')
95        warning('The steady state file internally changes the values of the estimated parameters.')
96    end
97end
98
99if any(BayesInfo.pshape) % if Bayesian estimation
100    nvx=EstimatedParameters.nvx;
101    if nvx && any(BayesInfo.p3(1:nvx)<0)
102        warning('Your prior allows for negative standard deviations for structural shocks. Due to working with variances, Dynare will be able to continue, but it is recommended to change your prior.')
103    end
104    offset=nvx;
105    nvn=EstimatedParameters.nvn;
106    if nvn && any(BayesInfo.p3(1+offset:offset+nvn)<0)
107        warning('Your prior allows for negative standard deviations for measurement error. Due to working with variances, Dynare will be able to continue, but it is recommended to change your prior.')
108    end
109    offset = nvx+nvn;
110    ncx=EstimatedParameters.ncx;
111    if ncx && (any(BayesInfo.p3(1+offset:offset+ncx)<-1) || any(BayesInfo.p4(1+offset:offset+ncx)>1))
112        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')
113    end
114    offset = nvx+nvn+ncx;
115    ncn=EstimatedParameters.ncn;
116    if ncn && (any(BayesInfo.p3(1+offset:offset+ncn)<-1) || any(BayesInfo.p4(1+offset:offset+ncn)>1))
117        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')
118    end
119end
120
121% display warning if some parameters are still NaN
122test_for_deep_parameters_calibration(Model);
123
124[lnprior,~,~,info]= priordens(xparam1,BayesInfo.pshape,BayesInfo.p6,BayesInfo.p7,BayesInfo.p3,BayesInfo.p4);
125if any(info)
126    fprintf('The prior density evaluated at the initial values is Inf for the following parameters: %s\n',BayesInfo.name{info,1})
127    error('The initial value of the prior is -Inf')
128end
129
130if DynareOptions.ramsey_policy
131    %test whether specification matches
132    inst_nbr = size(DynareOptions.instruments,1);
133    if inst_nbr~=0
134        orig_endo_aux_nbr = Model.orig_endo_nbr + min(find([Model.aux_vars.type] == 6)) - 1;
135        implied_inst_nbr = orig_endo_aux_nbr - Model.orig_eq_nbr;
136        if inst_nbr>implied_inst_nbr
137            error('You have specified more instruments than there are omitted equations')
138        elseif inst_nbr<implied_inst_nbr
139            error('You have specified fewer instruments than there are omitted equations')
140        end
141    end
142end
143
144% Evaluate the likelihood.
145ana_deriv = DynareOptions.analytic_derivation;
146DynareOptions.analytic_derivation=0;
147if ~isequal(DynareOptions.mode_compute,11) || ...
148        (isequal(DynareOptions.mode_compute,11) && isequal(DynareOptions.order,1))
149    %shut off potentially automatic switch to diffuse filter for the
150    %purpose of checking stochastic singularity
151    use_univariate_filters_if_singularity_is_detected_old=DynareOptions.use_univariate_filters_if_singularity_is_detected;
152    DynareOptions.use_univariate_filters_if_singularity_is_detected=0;
153    [fval,info] = feval(objective_function,xparam1,DynareDataset,DatasetInfo,DynareOptions,Model,EstimatedParameters,BayesInfo,BoundsInfo,DynareResults);
154    if info(1)==50
155        fprintf('\ninitial_estimation_checks:: The forecast error variance in the multivariate Kalman filter became singular.\n')
156        fprintf('initial_estimation_checks:: This is often a sign of stochastic singularity, but can also sometimes happen by chance\n')
157        fprintf('initial_estimation_checks:: for a particular combination of parameters and data realizations.\n')
158        fprintf('initial_estimation_checks:: If you think the latter is the case, you should try with different initial values for the estimated parameters.\n')
159        error('initial_estimation_checks:: The forecast error variance in the multivariate Kalman filter became singular.')
160    end
161    %reset options
162    DynareOptions.use_univariate_filters_if_singularity_is_detected=use_univariate_filters_if_singularity_is_detected_old;
163else
164    info=0;
165    fval = 0;
166end
167if DynareOptions.debug
168    DynareResults.likelihood_at_initial_parameters=fval;
169end
170DynareOptions.analytic_derivation=ana_deriv;
171
172if DynareOptions.mode_compute==13
173    error('Options mode_compute=13 is only compatible with quadratic objective functions')
174end
175
176
177% if DynareOptions.mode_compute==5
178%     if ~strcmp(func2str(objective_function),'dsge_likelihood')
179%         error('Options mode_compute=5 is not compatible with non linear filters or Dsge-VAR models!')
180%     end
181% end
182if isnan(fval)
183    error('The initial value of the likelihood is NaN')
184elseif imag(fval)
185    error('The initial value of the likelihood is complex')
186end
187
188if info(1) > 0
189    if DynareOptions.order>1
190        [eigenvalues_] = check(Model,DynareOptions, DynareResults);
191        if any(abs(1-abs(eigenvalues_))<abs(DynareOptions.qz_criterium-1))
192            error('Your model has at least one unit root and you are using a nonlinear filter. Please set nonlinear_filter_initialization=3.')
193        end
194    else
195        disp('Error in computing likelihood for initial parameter values')
196        print_info(info, DynareOptions.noprint, DynareOptions)
197    end
198end
199
200if DynareOptions.prefilter==1
201    if (~DynareOptions.loglinear && any(abs(DynareResults.steady_state(BayesInfo.mfys))>1e-9)) || (DynareOptions.loglinear && any(abs(log(DynareResults.steady_state(BayesInfo.mfys)))>1e-9))
202        disp(['You are trying to estimate a model with a non zero steady state for the observed endogenous'])
203        disp(['variables using demeaned data!'])
204        error('You should change something in your mod file...')
205    end
206end
207
208if ~isequal(DynareOptions.mode_compute,11)
209    disp(['Initial value of the log posterior (or likelihood): ' num2str(-fval)]);
210end
211