diff --git a/doc/manual/source/bibliography.rst b/doc/manual/source/bibliography.rst index 1df9cb36de4d3438583047cc79bcc26eea16d246..fc82232a2fbdee63c54774a1456276f209fb1909 100644 --- a/doc/manual/source/bibliography.rst +++ b/doc/manual/source/bibliography.rst @@ -21,6 +21,8 @@ Bibliography * Brooks, Stephen P., and Andrew Gelman (1998): “General methods for monitoring convergence of iterative simulations,” *Journal of Computational and Graphical Statistics*, 7, pp. 434–455. * Cardoso, Margarida F., R. L. Salcedo and S. Feyo de Azevedo (1996): “The simplex simulated annealing approach to continuous non-linear optimization,” *Computers & Chemical Engineering*, 20(9), 1065-1080. * Chib, Siddhartha and Srikanth Ramamurthy (2010): “Tailored randomized block MCMC methods with application to DSGE models,” *Journal of Econometrics*, 155, 19–38. +* Christiano, Lawrence J., Martin Eichenbaum and Charles L. Evans (2005): “Nominal Rigidities and the Dynamic Effects of a Shock to Monetary Policy,” *Journal of Political Economy*, 113(1), 1–45. +* Christiano, Lawrence J., Mathias Trabandt, and Karl Walentin (2010): “DSGE Models for Monetary Policy Analysis,” In: *Handbook of Monetary Economics 3*, 285–367. * Christiano, Lawrence J., Mathias Trabandt and Karl Walentin (2011): “Introducing financial frictions and unemployment into a small open economy model,” *Journal of Economic Dynamics and Control*, 35(12), 1999–2041. * Christoffel, Kai, Günter Coenen and Anders Warne (2010): “Forecasting with DSGE models,” *ECB Working Paper Series*, 1185. * Collard, Fabrice (2001): “Stochastic simulations with Dynare: A practical guide”. diff --git a/doc/manual/source/the-model-file.rst b/doc/manual/source/the-model-file.rst index 34dc61b1cbeb396be6ac510ad2090740b391701f..55a52d85fab571ef4b3998feef08c7ad3d8bc0a7 100644 --- a/doc/manual/source/the-model-file.rst +++ b/doc/manual/source/the-model-file.rst @@ -6648,7 +6648,7 @@ observed variables. .. option:: mh_tune_guess = DOUBLE Specifies the initial value for the :opt:`mh_tune_jscale - <mh_tune_jscale [= DOUBLE]>` option. Default: ``2.39/sqrt(n)``. Must not + <mh_tune_jscale [= DOUBLE]>` option. Default: ``2.38/sqrt(n)``. Must not be set if :opt:`mh_tune_jscale <mh_tune_jscale [= DOUBLE]>` is not used. @@ -9076,21 +9076,27 @@ Dynare also has the ability to estimate Bayesian VARs: Estimation based on moments =========================== +Provided that you have observations on some endogenous variables +or their dynamic behavior following structural shocks, +Dynare provides a suite of tools for parameter estimation utilizing the method of moments approach. +This includes the Simulated Method of Moments (SMM), +the Generalized Method of Moments (GMM), +and Impulse Response Function Matching (IRF matching). +Each of these methods offers a distinct strategy for estimating some or all parameters +by minimizing the distances between unconditional model objects (moments or impulse responses) +and their empirical counterparts. -Provided that you have observations on some endogenous variables, it -is possible to use Dynare to estimate some or all parameters using a -method of moments approach. Both the Simulated Method of Moments (SMM) -and the Generalized Method of Moments (GMM) are available. The general -idea is to minimize the distance between unconditional model moments -and corresponding data moments (so called orthogonality or moment -conditions). For SMM, Dynare computes model moments via stochastic + +**GMM and SMM estimation** + +For SMM Dynare computes model moments via stochastic simulations based on the perturbation approximation up to any order, whereas for GMM model moments are computed in closed-form based on the -pruned state-space representation of the perturbation solution up to third -order. The implementation of SMM is inspired by *Born and Pfeifer (2014)* +pruned state-space representation of the perturbation solution up to third order. +The implementation of SMM is inspired by *Born and Pfeifer (2014)* and *Ruge-Murcia (2012)*, whereas the one for GMM is adapted from -*Andreasen, Fernández-Villaverde and Rubio-Ramírez (2018)* and *Mutschler -(2018)*. Successful estimation heavily relies on the accuracy and efficiency of +*Andreasen, Fernández-Villaverde and Rubio-Ramírez (2018)* and *Mutschler (2018)*. +Successful estimation heavily relies on the accuracy and efficiency of the perturbation approximation, so it is advised to tune this as much as possible (see :ref:`stoch-sol-simul`). The method of moments estimator is consistent and asymptotically normally distributed given certain regularity conditions @@ -9134,10 +9140,45 @@ to more plausible regions of the parameter space. Ideally, these regions are characterized by only slightly worse values of the objective function. Note that adding prior information comes at the cost of a loss in efficiency of the estimator. +**IRF matching** + +Dynare employs a user-specified `simulation_method` to compute the impulse response function (IRF) +for observable variables with respect to the structural shocks. +Currently, only stochastic simulations based on the perturbation method are supported +and it is advised to fine-tune the perturbation approximation as much as possible for optimal results +(see :ref:`stoch-sol-simul` for guidance). + +The core idea of IRF matching is then to treat empirical impulse responses +(e.g. given from a SVAR or local projection estimation) as data +and select model parameters that align the model's IRFs closely with their empirical counterparts. +Dynare supports both Frequentist and Bayesian IRF matching approaches, +using the same optimization and sampling techniques as those applied in likelihood-based estimation +(sharing many options with the :ref:`estimation command <estim-comm>`). +The Frequentist approach to this is inspired by the work of *Christiano, Eichenbaum, and Evans (2005)*, +while the Bayesian method adapts from *Christiano, Trabandt, and Walentin (2010)*. +A crucial element in IRF matching is the choice of the weighting matrix, +which influences how the distances between model-generated and empirical IRFs are weighted in the estimation process. +It is common practice to employ a diagonal weighting matrix, +with the diagonal elements set to the inverse of the estimated variance of the respective empirical impulse response, +thereby prioritizing more precisely estimated IRFs. +While it's possible to also specify weights using covariances between different IRF components (possibly with shrinking), +this is less common due to the complex interpretation involved +(cross effects of different variables or different shocks or both). + +Importantly, it is the user's responsibility to supply +(1) the values of the empirical IRFs intended for matching +and (2) their importance by choosing an appropriate weighting matrix. +Dynare does not perform the SVAR or local projection estimation, +it treats the empirical IRFs as given. + +Method of moments specific blocks +--------------------------------- + .. command:: varobs VARIABLE_NAME...; - |br| Required. All variables used in the :bck:`matched_moments` block - need to be observable. See :ref:`varobs <varobs>` for more details. + |br| Required. All variables used in the :bck:`matched_moments`, :bck:`matched_irfs`, + or :bck:`matched_irfs_weights` block need to be observable. + See :ref:`varobs <varobs>` for more details. .. block:: matched_moments ; @@ -9198,17 +9239,147 @@ adding prior information comes at the cost of a loss in efficiency of the estima last row, which is the same as the second-to-last one. The original block is saved in ``M_.matched_moments_orig``. -.. block:: estimated_params ; +.. block:: matched_irfs ; + matched_irfs(overwrite); + + |br| This block specifies the values and diagonal weights of the empirical IRFs that are matched in estimation. + The ``overwrite`` option replaces the current ``matched_irfs`` block with the new one. + + Each line inside of the block should be of the form:: + + var ENDOGENOUS_NAME; + varexo EXOGENOUS_NAME; + periods INTEGER[:INTEGER] [[,] INTEGER[:INTEGER]]...; + values DOUBLE | (EXPRESSION) [[,] DOUBLE | (EXPRESSION) ]...; + weights DOUBLE | (EXPRESSION) [[,] DOUBLE | (EXPRESSION) ]...; + + `ENDOGENOUS_NAME` is the name of a declared observable variable, + whereas `EXOGENOUS_NAME` is the name of an exogenous variable. + It is possible to specify individual horizons or a range of specified periods + as lists with the ``periods`` keyword. + Note that for each entry a corresponding entry in ``values`` needs to be provided; + that is ``values`` is a list of the same length as ``periods``. + If only one value is specified, it is used at all corresponding ``periods`` in the list. + ``weights`` are optional and specify the diagonal element of the corresponding + entry in the weighting matrix. + Typically, these are set to the inverse of the variance of the empirical IRF. + If only one weight is specified, it is used at all corresponding ``periods`` in the list. + If not specified, the weight defaults to 1. + For ``values`` and ``weights`` you can use expressions (e.g. variables or anonymous functions + in the workspace) by by putting paranthesis around them. + A new statement is started with either the ``var`` or ``varexo`` keyword. + + *Example* + You can either enter the values directly or load them from variables in the workspace. + + :: + % MATLAB expressions that can be used + xx = [23,24,25]; + ww = [51,52]; + irfs_eR = @(j) IRFFF(2:15,j); % gdp is the 3th column of IRFFF + weights_eR = @(j) 1./(IRFFFSE(2:15,j).^2); + R_eR = IRFFF(1:15,3); + weight_R_eR = 1./(IRFFFSE(1:15,3).^2); + + matched_irfs; + var gdp; varexo eR; periods 2:15; values (irfs_eR(3)); weights (weights_eR(3)); + var R; varexo eR; periods 1:15; values (R_eR); weights (weight_R_eR); + var y; varexo eD; periods 5; values 7; weights 25; + var r; varexo eD; periods 1,2; values 17,18; weights 37,38; + var c; varexo eA; periods 3:5; values (xx); + var y; varexo eA; periods 1:2; values 30; weights (ww); + + varexo eR; + var w; + periods 1, 13:15, 2:12; + values 2, (xx), 15; + weights 3, (xx), 4; + end; + + + *Limitations* + + *Output* + + Dynare translates the :bck:`matched_irfs` block into a cell array + where the rows correspond to the statements in the block + ``M_.matched_irfs`` where: + + * the first column contains the names of the endogenous variables + * the second column contains the names of the exogenous variables + * the third column contains a nested cell array that contains + the list of horizons, values and weights. + + +.. block:: matched_irfs_weights ; + matched_irfs_weights(overwrite) ; - |br| Required. See :bck:`estimated_params` for the meaning and syntax. + |br| This optional block specifies elements of the weighting matrix used for IRF matching. + The ``overwrite`` option replaces the current ``matched_irfs_weights`` block with the new one. + + The weighting matrix is initialized as a diagonal matrix with ones on the diagonal. + Each line inside of the block should be of the form:: + + ENDOGENOUS_NAME_1(HORIZON_1), EXOGENOUS_NAME_1, ENDOGENOUS_NAME_2(HORIZON_2), EXOGENOUS_NAME_2, WEIGHT; + + where `ENDOGENOUS_NAME_1` and `ENDOGENOUS_NAME_2` are the names of declared observable variables, + `EXOGENOUS_NAME_1` and `EXOGENOUS_NAME_2` are the names of exogenous variables, + `HORIZON_1` and `HORIZON_2` are integers indicating the horizon of the IRFs + and `WEIGHT` is a double value of the weight one wants to assign to the covariance between the two specified IRFs. + + *Example* + You can either enter the values directly or load them from variables in the workspace. + + :: + + matched_irfs_weights; + c(1), e_A, c(1), e_A, 20; + y(3), e_R, y(2), e_R, (empIRFsCovInv_yR3_yR2); + end; + + *Limitations* + *Output* + + Dynare translates the :bck:`matched_irfs_weigths` block into a cell array + ``M_.matched_irfs_weights`` where: + + * the first column contains the names of the first endogenous variables + * the second column contains the names of the first exogenous variables + * the third column contains the horizons of the IRFs for the first endogneous variable + * the fourth column contains the names of the second endogenous variables + * the fifth column contains the names of the second exogenous variables + * the sixth column contains the horizons of IRFs for the second endogenous variable + * the seventh column contains the vector of weights + + All values that are not specified will be either one (if they are on the diagonal) + or zero (if they are not on the diagonal). + Symmetry is respected, so one does not need to specify both + ``c(1), e_A, y(3), e_R, WEIGHT`` and ``y(3), e_R, c(1), e_A, WEIGHT``. + Default: empty cell. + +.. block:: estimated_params ; + + |br| Required. + This block lists all parameters to be estimated and specifies + bounds and priors as necessary. + See :bck:`estimated_params` for details and syntax. + .. block:: estimated_params_init ; - |br| See :bck:`estimated_params_init` for the meaning and syntax. + |br| Optional. + This block declares numerical initial values for the + optimizer when these ones are different from the prior mean. + See :bck:`estimated_params_init` for details and syntax. .. block:: estimated_params_bounds ; - |br| See :bck:`estimated_params_bounds` for the meaning and syntax. + |br| Optional. + This block declares lower and upper bounds for parameters in maximum likelihood estimation. + See :bck:`estimated_params_bounds` for details and syntax. + +method_of_moments command +------------------------- .. command:: method_of_moments (OPTIONS...); @@ -9218,27 +9389,32 @@ adding prior information comes at the cost of a loss in efficiency of the estima * Overview of options chosen by the user * Estimation results for each stage and iteration * Value of minimized moment distance objective function - * Result of the J-test - * Table of data moments and estimated model moments + * Result of the J-test (for SMM/GMM) + * Comparison plot of model IRFs and empirical IRFs (for IRF matching) + * Table of data moments/IRFs and estimated model moments/IRFs - *Necessary options* +Necessary Options +^^^^^^^^^^^^^^^^^^ - .. option:: mom_method = SMM|GMM + .. option:: mom_method = SMM|GMM|IRF_MATCHING - "Simulated Method of Moments" is triggered by `SMM` and - "Generalized Method of Moments" by `GMM`. + "Simulated Method of Moments" is triggered by `SMM`, + "Generalized Method of Moments" by `GMM` and + "Impulse Response Function Matching" by `IRF_MATCHING`. .. option:: datafile = FILENAME - The name of the file containing the data. See + The name of the file containing the data (for GMM and SMM only). See :opt:`datafile <datafile = FILENAME>` for the meaning and syntax. + For IRF matching, the data is specified in the :bck:`matched_irfs` block. - *Options common for SMM and GMM* - +Common Options +^^^^^^^^^^^^^^ + .. option:: order = INTEGER Order of perturbation approximation. For GMM only orders 1|2|3 are - supported. For SMM, you can choose an arbitrary order. Note that the + supported. For SMM and IRF matching, you can choose an arbitrary order. Note that the order set in other functions will not overwrite the default. Default: ``1``. @@ -9246,7 +9422,15 @@ adding prior information comes at the cost of a loss in efficiency of the estima Discard higher order terms when iteratively computing simulations of the solution. See :opt:`pruning <pruning>` for more details. - Default: not set for SMM, always set for GMM. + Default: not set for SMM and IRF matching, always set for GMM. + + .. option:: verbose + + Display and store intermediate estimation results in ``oo_.mom``. + Default: not set. + + + *Common options for SMM and GMM* .. option:: penalized_estimator @@ -9306,12 +9490,8 @@ adding prior information comes at the cost of a loss in efficiency of the estima errors with a two-sided finite difference method. Default: ``1e-5``. - .. option:: verbose - - Display and store intermediate estimation results in ``oo_.mom``. - Default: not set. - - *SMM-specific options* +SMM specific options +^^^^^^^^^^^^^^^^^^^^ .. option:: burnin = INTEGER @@ -9333,7 +9513,8 @@ adding prior information comes at the cost of a loss in efficiency of the estima Multiple of data length used for simulation. Default: ``7``. - *GMM-specific options* +GMM specific options +^^^^^^^^^^^^^^^^^^^^ .. option:: analytic_standard_errors @@ -9342,7 +9523,54 @@ adding prior information comes at the cost of a loss in efficiency of the estima Default: not set, i.e. standard errors are computed using a two-sided finite difference method, see :opt:`se_tolx <se_tolx = DOUBLE>`. - *General options* +IRF matching specific options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + .. option:: simulation_method = METHOD + + Method to compute IRFs. Possible values for ``METHOD`` are: + + ``STOCH_SIMUL`` + + Simulate the model with stochastic simulations and compute IRFs + as the difference between the simulated and steady state values. + See :opt:`stoch_simul` for more details. + + .. option:: irf_matching_file = FILENAME + + A MATLAB file containing additional transformations on the model IRFs. + This enables more flexibility in matching the model IRFs to the empirical IRFs, + e.g. by adding constants to model IRFs, multiplying them with factors, + taking the cumulative sum, creating ratios etc. + See ``NK_irf_matching_file.m`` in the examples directory for an example. + Default: empty, i.e. model IRFs exactly match empirical IRFs. + + .. option:: add_tiny_number_to_cholesky = DOUBLE + + In case of a non-positive definite covariance matrix, + a tiny number is added to the Cholesky factor + to avoid numerical problems when computing IRFs. + Default: `1e-14`. + + .. option:: drop = INTEGER + + Truncation when computing IRFs with perturbation at orders greater than 1. + Default: ``100``. + + .. option:: relative_irf + + Requests the computation of normalized IRFs. + See :opt:`relative_irf` for more details. + Default: false. + + .. option:: replic = INTEGER + + Number of simulated series used to compute the IRFs. + Default: ``1`` if ``order=1``, and ``50`` otherwise. + + +General options +^^^^^^^^^^^^^^^ .. option:: dirname = FILENAME @@ -9383,7 +9611,15 @@ adding prior information comes at the cost of a loss in efficiency of the estima See :opt:`tex`. Default: not set. - *Data options* +Data options +^^^^^^^^^^^^ + + .. option:: prefilter = INTEGER + + A value of 1 means that the estimation procedure will demean each data + series by its empirical mean and each model moment by its theoretical + mean. See :opt:`prefilter <prefilter = INTEGER>` for more details. + Default: ``0``, i.e. no prefiltering. .. option:: first_obs = INTEGER @@ -9395,13 +9631,6 @@ adding prior information comes at the cost of a loss in efficiency of the estima See :opt:`nobs <nobs = INTEGER>`. Default: all observations are considered. - .. option:: prefilter = INTEGER - - A value of 1 means that the estimation procedure will demean each data - series by its empirical mean and each model moment by its theoretical - mean. See :opt:`prefilter <prefilter = INTEGER>` for more details. - Default: ``0``, i.e. no prefiltering. - .. option:: logdata See :opt:`logdata <logdata>`. Default: not set. @@ -9409,43 +9638,219 @@ adding prior information comes at the cost of a loss in efficiency of the estima .. option:: xls_sheet = QUOTED_STRING See :opt:`xls_sheet <xls_sheet = QUOTED_STRING>`. + Default: ``1``. .. option:: xls_range = RANGE See :opt:`xls_range <xls_range = RANGE>`. + Default: empty. - *Optimization options* +Optimization options +^^^^^^^^^^^^^^^^^^^^ - .. option:: huge_number = DOUBLE + .. option:: mode_file = FILENAME - See :opt:`huge_number <huge_number = DOUBLE>`. - Default: ``1e7``. + Name of the file containing previous value for the mode. + See :opt:`mode_file <mode_file = FILENAME>`. + Default: empty. .. option:: mode_compute = INTEGER | FUNCTION_NAME See :opt:`mode_compute <mode_compute = INTEGER | FUNCTION_NAME>`. - Default: ``13``, i.e. ``lsqnonlin`` if the MATLAB Optimization Toolbox or - the Octave optim-package are present, ``4``, i.e. ``csminwel`` otherwise. - + Default: ``13`` for GMM and SMM and ``5`` for IRF matching. + .. option:: additional_optimizer_steps = [INTEGER] additional_optimizer_steps = [INTEGER1:INTEGER2] additional_optimizer_steps = [INTEGER1 INTEGER2] - Vector of additional minimization algorithms run after - ``mode_compute``. If :opt:`verbose` option is set, then the additional estimation + Vector of additional minimization algorithms run after ``mode_compute``. + If :opt:`verbose` option is set, then the additional estimation results are saved into the ``oo_.mom`` structure prefixed with `verbose_`. - Default: no additional optimization iterations. + Default: empty, i.e. no additional optimization iterations. .. option:: optim = (NAME, VALUE, ...) See :opt:`optim <optim = (NAME, VALUE, ...)>`. + Default: empty. + + .. option:: analytic_jacobian + + Use analytic Jacobian in optimization, only available for GMM and gradient-based optimizers. + Default: not set. + + .. option:: huge_number = DOUBLE + + See :opt:`huge_number <huge_number = DOUBLE>`. + Default: ``1e7``. .. option:: silent_optimizer See :opt:`silent_optimizer`. Default: not set. + + .. option:: use_penalized_objective_for_hessian + + See :opt:`use_penalized_objective_for_hessian <use_penalized_objective_for_hessian>`. + Default: not set. + + +Bayesian estimation options +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**General options** + + .. option:: posterior_sampling_method = NAME + + See :opt:`posterior_sampling_method <posterior_sampling_method = NAME>`. + Default: ``random_walk_metropolis_hastings``. + + .. option:: posterior_sampler_options = (NAME, VALUE, ...) + + See :opt:`posterior_sampler_options <posterior_sampler_options = (NAME, VALUE, ...)>`. + Default: not set. + + .. option:: mh_posterior_mode_estimation + + See :opt:`mh_posterior_mode_estimation`. + Default: not set. + + .. option:: cova_compute = INTEGER + + See :opt:`cova_compute <cova_compute = INTEGER>`. + Default: ``1``. + + .. option:: mcmc_jumping_covariance = OPTION + + See :opt:`mcmc_jumping_covariance <mcmc_jumping_covariance = OPTION>`. + Default: ``hessian``. + + .. option:: mh_replic = INTEGER + + See :opt:`mh_replic <mh_replic = INTEGER>`. + Default: ``0``. + + .. option:: mh_nblocks = INTEGER + + See :opt:`mh_nblocks <mh_nblocks = INTEGER>`. + Default: ``2``. + + .. option:: mh_jscale = DOUBLE + + See :opt:`mh_jscale <mh_jscale = DOUBLE>`. + Default: ``2.38`` divided by the square root of the number of estimated parameters. + + .. option:: mh_tune_jscale [= DOUBLE] + + See :opt:`mh_tune_jscale <mh_tune_jscale [= DOUBLE]>`. + Default: ``0.33``. + + .. option:: mh_tune_guess = DOUBLE + + See :opt:`mh_tune_guess <mh_tune_guess = DOUBLE>`. + Default: ``2.38`` divided by the square root of the number of estimated parameters. + + .. option:: mh_conf_sig = DOUBLE + + See :opt:`mh_conf_sig <mh_conf_sig = DOUBLE>`. + Default: ``0.9``. + + .. option:: mh_drop = DOUBLE + + See :opt:`mh_drop <mh_drop = DOUBLE>`. + Default: ``0.5``. + + .. option:: mh_init_scale_factor = DOUBLE + + See :opt:`mh_init_scale_factor <mh_init_scale_factor = DOUBLE>`. + Default: ``2``. + + .. option:: no_posterior_kernel_density + + See :opt:`no_posterior_kernel_density`. + Default: not set. + + .. option:: posterior_max_subsample_draws = INTEGER + + See :opt:`posterior_max_subsample_draws <posterior_max_subsample_draws = INTEGER>`. + Default: ``1200``. + + .. option:: sub_draws = INTEGER + + See :opt:`sub_draws <sub_draws = INTEGER>`. + Default: ``min(posterior_max_subsample_draws, (Total number of draws)*(number of chains) )``. + +**MCMC initialization and recovery** + + .. option:: load_mh_file + + See :opt:`load_mh_file`. + Default: not set. + + .. option:: load_results_after_load_mh + + See :opt:`load_results_after_load_mh`. + Default: not set. + + .. option:: mh_initialize_from_previous_mcmc + + See :opt:`mh_initialize_from_previous_mcmc`. + Default: not set. + + .. option:: mh_initialize_from_previous_mcmc_directory = FILENAME + + See :opt:`mh_initialize_from_previous_mcmc_directory <mh_initialize_from_previous_mcmc_directory = FILENAME>`. + Default: empty. + + .. option:: mh_initialize_from_previous_mcmc_prior = FILENAME + + See :opt:`mh_initialize_from_previous_mcmc_prior <mh_initialize_from_previous_mcmc_prior = FILENAME>`. + Default: empty. + + .. option:: mh_initialize_from_previous_mcmc_record = FILENAME + + See :opt:`mh_initialize_from_previous_mcmc_record <mh_initialize_from_previous_mcmc_record = FILENAME>`. + Default: empty. + + .. option:: mh_recover + + See :opt:`mh_recover`. + Default: not set. + +**Convergence diagnostics** + + .. option:: nodiagnostic + + See :opt:`nodiagnostic`. + Default: not set. + + .. option:: brooks_gelman_plotrows = INTEGER + + See :opt:`brooks_gelman_plotrows <brooks_gelman_plotrows = INTEGER>`. + Default: ``3``. + + .. option:: geweke_interval = [DOUBLE DOUBLE] + + See :opt:`geweke_interval <geweke_interval = [DOUBLE DOUBLE]>`. + Default: ``[0.2 0.5]``. + + .. option:: taper_steps = [INTEGER1 INTEGER2 ...] + + See :opt:`taper_steps <taper_steps = [INTEGER1 INTEGER2 ...]>`. + Default: ``[4 8 15]``. + + .. option:: raftery_lewis_diagnostics + + See :opt:`raftery_lewis_diagnostics`. + Default: not set. + + .. option:: raftery_lewis_qrs = [DOUBLE DOUBLE DOUBLE] - *Numerical algorithms options* + See :opt:`raftery_lewis_qrs <raftery_lewis_qrs = [DOUBLE DOUBLE DOUBLE]>`. + Default: ``[0.025 0.005 0.95]``. + + +Numerical algorithms options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. option:: aim_solver @@ -9495,10 +9900,11 @@ adding prior information comes at the cost of a loss in efficiency of the estima See :opt:`lyapunov_doubling_tol <lyapunov_doubling_tol = DOUBLE>`. Default: ``1e-16``. - + .. option:: qz_criterium = DOUBLE See :opt:`qz_criterium <qz_criterium = DOUBLE>`. + For unit roots (only possible at order=1) set e.g. to 1.000001. Default: ``0.999999`` as it is assumed that the observables are weakly stationary. @@ -9515,8 +9921,8 @@ adding prior information comes at the cost of a loss in efficiency of the estima .. option:: mode_check Plots univariate slices through the moments distance objective function around the - computed minimum for each estimated parameter. This is - helpful to diagnose problems with the optimizer. + computed minimum for each estimated parameter. + This is helpful to diagnose problems with the optimizer. Default: not set. .. option:: mode_check_neighbourhood_size = DOUBLE @@ -9535,71 +9941,76 @@ adding prior information comes at the cost of a loss in efficiency of the estima Default: ``20``. - *Output* +Method of moments specific outputs +---------------------------------- ``method_of_moments`` stores user options in a structure called `options_mom_` in the global workspace. After running the estimation, the parameters ``M_.params`` and the covariance matrices of the shocks ``M_.Sigma_e`` and of the measurement errors ``M_.H`` are set to the - parameters that minimize the quadratic moments distance objective - function. The estimation results are stored in the ``oo_.mom`` structure - with the following fields: + parameters that either minimize the quadratic moments distance objective + function or at the posterior mean in case of Bayesian MCMC estimation. + The estimation results are stored in a subfolder of :opt:`dirname <dirname = FILENAME>` + called `method_of_moments`. + Moreover, output is stored in the ``oo_.mom`` structure with the following fields: + +**Common outputs** .. matvar:: oo_.mom.data_moments Variable set by the ``method_of_moments`` command. Stores the mean - of the selected empirical moments of data. NaN values due to leads/lags - or missing data are omitted when computing the mean. Vector of dimension - equal to the number of orthogonality conditions. - - - .. matvar:: oo_.mom.m_data - - Variable set by the ``method_of_moments`` command. Stores the selected - empirical moments at each point in time. NaN values due to leads/lags - or missing data are replaced by the corresponding mean of the moment. - Matrix of dimension time periods times number of orthogonality conditions. - - - .. matvar:: oo_.mom.Sw - - Variable set by the ``method_of_moments`` command. Stores the - Cholesky decomposition of the currently used weighting matrix. - Square matrix of dimensions equal to the number of orthogonality - conditions. - - + of the selected empirical moments/IRFs of data. NaN values due to leads/lags + or missing data are omitted when computing the mean for moments. + Vector of dimension equal to the number of orthogonality conditions or IRFs. + .. matvar:: oo_.mom.model_moments Variable set by the ``method_of_moments`` command. Stores the implied - selected model moments given the current parameter guess. Model moments + selected model moments or IRFs given the current parameter guess. Model moments are computed in closed-form from the pruned state-space system for GMM, - whereas for SMM these are based on averages of simulated data. Vector of dimension equal - to the number of orthogonality conditions. + whereas for SMM these are based on averages of simulated data. + Model IRFs are computed from the specified `simulation_method`. + Vector of dimension equal to the number of orthogonality conditions. + + .. matvar:: oo_.mom.model_moments_params_derivs + Variable set by the ``method_of_moments`` command. Stores the analytically + computed Jacobian matrix of the derivatives of the model moments with + respect to the estimated parameters. Only for GMM with :opt:`analytic_standard_errors`. + Matrix with dimension equal to the number of orthogonality conditions + times number of estimated parameters. + + .. matvar:: oo_.mom.weighting_info + Variable set by the ``method_of_moments`` command. + Stores the currently used weighting matrix (`W`), its Cholesky factor (`Sw`), + and an indicator whether the weighting matrix is the optimal one (`Woptflag`). + The inverse (`Winv`) and its log determinant (`Winv_logdet`) are also stored. + .. matvar:: oo_.mom.Q Variable set by the ``method_of_moments`` command. Stores the scalar value of the quadratic moment's distance objective function. + + .. matvar:: oo_.mom.verbose + Structure that contains intermediate estimation results if ``verbose`` is used. - .. matvar:: oo_.mom.model_moments_params_derivs - Variable set by the ``method_of_moments`` command. Stores the analytically - computed Jacobian matrix of the derivatives of the model moments with - respect to the estimated parameters. Only for GMM with :opt:`analytic_standard_errors`. - Matrix with dimension equal to the number of orthogonality conditions - times number of estimated parameters. +**SMM and GMM specific outputs** + .. matvar:: oo_.mom.m_data - .. matvar:: oo_.mom.gmm_stage_*_mode - .. matvar:: oo_.mom.smm_stage_*_mode - .. matvar:: oo_.mom.verbose_gmm_stage_*_mode - .. matvar:: oo_.mom.verbose_smm_stage_*_mode + Variable set by the ``method_of_moments`` command. Stores the selected + empirical moments at each point in time. NaN values due to leads/lags + or missing data are replaced by the corresponding mean of the moment. + Matrix of dimension time periods times number of orthogonality conditions. + .. matvar:: oo_.mom.gmm_mode + .. matvar:: oo_.mom.smm_mode + Variables set by the ``method_of_moments`` command when estimating - with GMM or SMM. Stores the estimated values at stages 1, 2,.... + with GMM or SMM. Stores the estimated values of the final stage. The structures contain the following fields: - ``measurement_errors_corr``: estimated correlation between two measurement errors @@ -9608,16 +10019,11 @@ adding prior information comes at the cost of a loss in efficiency of the estima - ``shocks_corr``: estimated correlation between two structural shocks. - ``shocks_std``: estimated standard deviation of structural shocks. - If the :opt:`verbose` option is set, additional fields prefixed with - ``verbose_`` are saved for all :opt:`additional_optimizer_steps<additional_optimizer_steps = [INTEGER]>`. - - .. matvar:: oo_.mom.gmm_stage_*_std_at_mode - .. matvar:: oo_.mom.smm_stage_*_std_at_mode - .. matvar:: oo_.mom.verbose_gmm_stage_*_std_at_mode - .. matvar:: oo_.mom.verbose_smm_stage_*_std_at_mode - + .. matvar:: oo_.mom.gmm_std_at_mode + .. matvar:: oo_.mom.smm_std_at_mode + Variables set by the ``method_of_moments`` command when estimating - with GMM or SMM. Stores the estimated standard errors at stages 1, 2,.... + with GMM or SMM. Stores the estimated standard errors of the final stage. The structures contain the following fields: - ``measurement_errors_corr``: standard error of estimated correlation between two measurement errors @@ -9625,11 +10031,7 @@ adding prior information comes at the cost of a loss in efficiency of the estima - ``parameters``: standard error of estimated model parameters - ``shocks_corr``: standard error of estimated correlation between two structural shocks. - ``shocks_std``: standard error of estimated standard deviation of structural shocks. - - If the :opt:`verbose` option is set, additional fields prefixed with - ``verbose_`` are saved for all :opt:`additional_optimizer_steps<additional_optimizer_steps = [INTEGER]>`. - - + .. matvar:: oo_.mom.J_test Variable set by the ``method_of_moments`` command. Structure where the @@ -9637,7 +10039,187 @@ adding prior information comes at the cost of a loss in efficiency of the estima degress of freedom into a field called ``degrees_freedom`` and the p-value of the test statistic into a field called ``p_val``. +**IRF matching specific outputs** + + .. matvar:: oo_.mom.irf_model_varobs + + Variable set by the ``method_of_moments`` command. Stores all the implied + model impulse response functions (not only the matched ones) + and is used for the comparison plot. + Array of dimension equal to number of observables by number of shocks + by maximum horizon. + + +**Bayesian specific outputs** + + .. matvar:: oo_.mom.prior + + Variable set by the ``method_of_moments`` command if Bayesian estimation is used. + Stores information of the joint prior. Fields are of the form:: + + oo_.mom.prior.OBJECT + + where OBJECT is one of the following: + + ``mean`` + Prior mean parameter vector. + + ``mode`` + + Prior mode parameter vector. + + ``variance`` + + Covariance matrix of joint prior. + + ``hyperparameters`` + + Vectors of hyperparameters of the prior distributions stored in fields + ``first`` and ``second``. + + .. matvar:: oo_.mom.posterior.optimization + + Variable set by the ``method_of_moments`` command if mode-finding is used. + Stores the results at the mode. Fields are of the form:: + + oo_.mom.posterior.optimization.OBJECT + + where OBJECT is one of the following: + + ``mode`` + + Parameter vector at the mode. + + ``Variance`` + + Inverse Hessian matrix at the mode or MCMC jumping + covariance matrix when used with the + :opt:`MCMC_jumping_covariance <mcmc_jumping_covariance = OPTION>` option. + + ``log_density`` + + Log likelihood (ML)/log posterior density (Bayesian) at the + mode when used with ``mode_compute>0``. + + + .. matvar:: oo_.mom.posterior.metropolis + + Variable set by the ``method_of_moments`` command if ``mh_replic>0`` is used. + Fields are of the form:: + + oo_.mom.posterior.metropolis.OBJECT + + where OBJECT is one of the following: + + ``mean`` + + Mean parameter vector from the MCMC. + + ``Variance`` + + Covariance matrix of the parameter draws in the MCMC. + + .. matvar:: oo_.mom.prior_density + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.mom.prior_density.PARAMETER_NAME + + .. matvar:: oo_.mom.posterior_density + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.mom.posterior_density.PARAMETER_NAME + + .. matvar:: oo_.mom.posterior_hpdinf + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.mom.posterior_hpdinf.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.posterior_hpdsup + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.mom.posterior_hpdsup.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.posterior_mean + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.posterior_mean.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.posterior_mode + + Variable set by the ``method_of_moments`` command during mode-finding. + Fields are of the form:: + + oo_.mom.posterior_mode.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.posterior_std_at_mode + + Variable set by the ``method_of_moments`` command during mode-finding. + It is based on the inverse Hessian at ``oo_.mom.posterior_mode``. + Fields are of the form:: + + oo_.mom.posterior_std_at_mode.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.posterior_std + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.mom.posterior_std.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.posterior_variance + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.mom.posterior_variance.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.posterior_median + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.mom.posterior_median.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.posterior_deciles + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. + Fields are of the form:: + + oo_.mom.posterior_deciles.ESTIMATED_OBJECT.VARIABLE_NAME + + .. matvar:: oo_.mom.MarginalDensity.LaplaceApproximation + + Variable set by the ``method_of_moments`` command. Stores the marginal + data density based on the Laplace Approximation. + + .. matvar:: oo_.mom.MarginalDensity.ModifiedHarmonicMean + + Variable set by the ``method_of_moments`` command, if it is used with + ``mh_replic > 0`` or ``load_mh_file`` option. Stores the + marginal data density based on *Geweke (1999)* Modified + Harmonic Mean estimator. + + Model Comparison ================ diff --git a/matlab/+mom/Jtest.m b/matlab/+mom/Jtest.m index 254d55ceceb5b0e2f69a13e0676c0da82970199c..955756fb1dc78dff0f9389f3972dc9d6bf34c1b9 100644 --- a/matlab/+mom/Jtest.m +++ b/matlab/+mom/Jtest.m @@ -1,22 +1,28 @@ -function oo_ = Jtest(xparam, objective_function, Woptflag, oo_, options_mom_, bayestopt_, Bounds, estim_params_, M_, nobs) -% function oo_ = Jtest(xparam, objective_function, Woptflag, oo_, options_mom_, bayestopt_, Bounds, estim_params_, M_, nobs) +function J_test = Jtest(xparam, objective_function, Q, model_moments, m_data, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) +% J_test = Jtest(xparam, objective_function, Q, model_moments, m_data, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) +% ------------------------------------------------------------------------- +% Computes the J-test statistic and p-value given a GMM/SMM estimation % ------------------------------------------------------------------------- -% Computes the J-test statistic and p-value for a GMM/SMM estimation -% ========================================================================= % INPUTS -% xparam: [vector] estimated parameter vector -% objective_function: [function handle] objective function -% Woptflag: [logical] flag if optimal weighting matrix has already been computed -% oo_: [struct] results -% options_mom_: [struct] options -% bayestopt_: [struct] information on priors -% Bounds: [struct] bounds on parameters -% estim_params_: [struct] information on estimated parameters -% M_: [struct] information on the model -% nobs: [scalar] number of observations +% xparam: [vector] estimated parameter vector +% objective_function: [function handle] objective function +% Q: [scalar] value of moments distance criterion +% model_moments: [vector] model moments +% m_data: [matrix] selected empirical moments at each point in time +% data_moments: [vector] empirical moments +% weighting_info: [struct] information on weighting matrix +% options_mom_: [struct] options +% M_: [struct] model information +% estim_params_: [struct] estimated parameters +% bayestopt_: [struct] info on prior distributions +% BoundsInfo: [struct] info bounds on parameters +% dr: [struct] reduced form model +% endo_steady_state: [vector] steady state of endogenous variables (initval) +% exo_steady_state: [vector] steady state of exogenous variables (initval) +% exo_det_steady_state: [vector] steady state of deterministic exogenous variables (initval) % ------------------------------------------------------------------------- % OUTPUT -% oo_: [struct] updated results +% J_test: [struct] results of J test % ------------------------------------------------------------------------- % This function is called by % o mom.run @@ -24,7 +30,8 @@ function oo_ = Jtest(xparam, objective_function, Woptflag, oo_, options_mom_, ba % This function calls % o mom.objective_function % o mom.optimal_weighting_matrix -% ========================================================================= +% ------------------------------------------------------------------------- + % Copyright © 2023 Dynare Team % % This file is part of Dynare. @@ -41,27 +48,26 @@ function oo_ = Jtest(xparam, objective_function, Woptflag, oo_, options_mom_, ba % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ========================================================================= + if options_mom_.mom.mom_nbr > length(xparam) % 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, xparam, Bounds, oo_J, estim_params_, M_, options_mom_); + if ~weighting_info.Woptflag + W_opt = mom.optimal_weighting_matrix(m_data, model_moments, options_mom_.mom.bartlett_kernel_lag); + weighting_info.Sw = chol(W_opt); + fval = feval(objective_function, xparam, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); else - fval = oo_.mom.Q; + fval = Q; end % Compute J statistic if strcmp(options_mom_.mom.mom_method,'SMM') - Variance_correction_factor = options_mom_.mom.variance_correction_factor; + variance_correction_factor = options_mom_.mom.variance_correction_factor; elseif strcmp(options_mom_.mom.mom_method,'GMM') - Variance_correction_factor = 1; + variance_correction_factor = 1; end - oo_.mom.J_test.j_stat = nobs*Variance_correction_factor*fval/options_mom_.mom.weighting_matrix_scaling_factor; - oo_.mom.J_test.degrees_freedom = length(oo_.mom.model_moments)-length(xparam); - 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); + J_test.j_stat = options_mom_.nobs*variance_correction_factor*fval/options_mom_.mom.weighting_matrix_scaling_factor; + J_test.degrees_freedom = length(model_moments)-length(xparam); + J_test.p_val = 1-chi2cdf(J_test.j_stat, J_test.degrees_freedom); + fprintf('\nValue of J-test statistic: %f\n',J_test.j_stat); + fprintf('p-value of J-test statistic: %f\n',J_test.p_val); end \ No newline at end of file diff --git a/matlab/+mom/check_irf_matching_file.m b/matlab/+mom/check_irf_matching_file.m new file mode 100644 index 0000000000000000000000000000000000000000..3aa5db2726446db02de2cb6b6686b08a9806d208 --- /dev/null +++ b/matlab/+mom/check_irf_matching_file.m @@ -0,0 +1,57 @@ +function [irf_matching_file_name, irf_matching_file_path] = check_irf_matching_file(irf_matching_file) +% [irf_matching_file_name, irf_matching_file_path] = check_irf_matching_file(irf_matching_file) +% ------------------------------------------------------------------------- +% Check if the provided irf_matching_file is a valid MATLAB function with +% .m extension and return name, path and extension of the file. +% ------------------------------------------------------------------------- +% INPUTS +% - irf_matching_file: [string] user provided name (with possible path and extension) +% of the MATLAB function that transforms model IRFs +% ------------------------------------------------------------------------- +% OUTPUTS +% - irf_matching_file_name: [string] name of the MATLAB function (without extension) +% - irf_matching_file_path: [string] path to irf_matching_file_name +% ------------------------------------------------------------------------- +% This function is called by +% - mom.run +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + + +if isempty(irf_matching_file) + % no irf_matching_file provided, so no transformations will be done + irf_matching_file_name = ''; + irf_matching_file_path = ''; +else + [irf_matching_file_path, irf_matching_file_name, irf_matching_file_ext] = fileparts(irf_matching_file); + % make sure file is a MATLAB function with .m extension + if ~strcmp(irf_matching_file_ext,'.m') + if strcmp(irf_matching_file_ext,'') + irf_matching_file_ext = '.m'; + else + error('method_of_moments: ''irf_matching_file'' needs to point towards a MATLAB function with extension ''.m''!'); + end + end + if isempty(irf_matching_file_path) + irf_matching_file_path = '.'; + end + if exist([irf_matching_file_path filesep irf_matching_file_name irf_matching_file_ext],'file') ~= 2 + error('method_of_moments: Could not find a ''irf_matching_file'' called ''%s''!',[irf_matching_file_path filesep irf_matching_file_name irf_matching_file_ext]); + end +end \ No newline at end of file diff --git a/matlab/+mom/default_option_mom_values.m b/matlab/+mom/default_option_mom_values.m index 3c105e27d743a26cd996b27cbc04db6181238ac0..5ce9d34a94e491d76a27b9fb754a4d2c6dccf850 100644 --- a/matlab/+mom/default_option_mom_values.m +++ b/matlab/+mom/default_option_mom_values.m @@ -1,33 +1,33 @@ -function options_mom_ = default_option_mom_values(options_mom_, options_, dname, doBayesianEstimation) -% function options_mom_ = default_option_mom_values(options_mom_, options_, dname, doBayesianEstimation) - -% Returns structure containing the options for method_of_moments command - -% 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. - -% ========================================================================= +function options_mom_ = default_option_mom_values(options_mom_, options_, dname, do_bayesian_estimation) +% options_mom_ = default_option_mom_values(options_mom_, options_, dname, do_bayesian_estimation) +% ------------------------------------------------------------------------- +% Returns structure containing the options for method_of_moments command. +% Note 1: 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. +% Note 2: we call a "mode" the minimum of the objective function, i.e. +% the parameter vector that minimizes the distance between the moments/IRFs +% computed from the model and the moments/IRFs computed from the data. +% ------------------------------------------------------------------------- % INPUTS -% o options_mom_: [structure] information about all (user-specified and updated) settings used in estimation (options_mom_) -% o options_: [structure] information on global options -% o dname: [string] name of directory to store results -% o doBayesianEstimation [boolean] indicator whether we do Bayesian estimation +% o options_mom_: [structure] all user-specified settings (from the method_of_moments command) +% o options_: [structure] global options +% o dname: [string] default name of directory to store results +% o do_bayesian_estimation [boolean] indicator whether we do Bayesian estimation % ------------------------------------------------------------------------- % 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_) +% o options_mom_: [structure] all user-specified and updated settings required for method_of_moments estimation % ------------------------------------------------------------------------- % This function is called by % o mom.run % ------------------------------------------------------------------------- % This function calls -% o set_default_option -% o user_has_matlab_license -% o user_has_octave_forge_package +% o set_default_option +% o user_has_matlab_license +% o user_has_octave_forge_package % ------------------------------------------------------------------------- % Copyright © 2023 Dynare Team @@ -46,34 +46,43 @@ function options_mom_ = default_option_mom_values(options_mom_, options_, dname, % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ========================================================================= mom_method = options_mom_.mom.mom_method; % this is a required option + % ------------------------------------------------------------------------- % LIMITATIONS % ------------------------------------------------------------------------- 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.') + error('method_of_moments: The loglinear option is not supported. Please append the required logged variables as auxiliary equations.'); else options_mom_.logged_steady_state = 0; options_mom_.loglinear = false; end -options_mom_.hessian.use_penalized_objective = false; % penalized objective not yet -% options related to variable declarations +if isfield(options_mom_,'hessian') && options_mom_.hessian.use_penalized_objective + warning('method_of_moments: The ''use_penalized_objective_for_hessian'' option is not supported yet and will be skipped.'); +end +options_mom_.hessian.use_penalized_objective = false; % penalized objective not yet supported if isfield(options_,'trend_coeffs') - error('method_of_moments: %s does not allow for trend in data',mom_method) + error('method_of_moments: %s does not allow for trend in data',mom_method); end -% options related to endogenous prior restrictions are not supported if ~isempty(options_.endogenous_prior_restrictions.irf) && ~isempty(options_.endogenous_prior_restrictions.moment) - fprintf('method_of_moments: Endogenous prior restrictions are not supported yet and will be skipped.\n') + warning('method_of_moments: Endogenous prior restrictions are not supported yet and will be skipped.'); end options_mom_.endogenous_prior_restrictions.irf = {}; options_mom_.endogenous_prior_restrictions.moment = {}; - -options_mom_.mom.analytic_jacobian_optimizers = [1, 3, 4, 13, 101]; % these are currently supported optimizers that are able to use the analytical_jacobian option +if isfield(options_mom_,'bayesian_irf') && options_mom_.bayesian_irf % do we need this at all?? + warning('method_of_moments: The ''bayesian_irf'' option is not supported yet and will be skipped.'); +end +options_mom_.bayesian_irf = false; +if strcmp(mom_method,'IRF_MATCHING') + if isfield(options_mom_.mom,'penalized_estimator') && options_mom_.mom.penalized_estimator + warning('method_of_moments: The ''penalized_estimator'' option is not supported yet for IRF_MATCHING and will be ignored.'); + end + options_mom_.mom.penalized_estimator = false; +end % ------------------------------------------------------------------------- % OPTIONS POSSIBLY SET BY THE USER @@ -87,8 +96,7 @@ options_mom_ = set_default_option(options_mom_,'nograph',false); % do no options_mom_ = set_default_option(options_mom_,'noprint',false); % do not print output to console options_mom_ = set_default_option(options_mom_,'TeX',false); % print TeX tables and graphics options_mom_.mom = set_default_option(options_mom_.mom,'verbose',false); % display and store intermediate estimation results -%options_mom_ = set_default_option(options_mom_,'verbosity',false); % -if doBayesianEstimation +if do_bayesian_estimation 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 end @@ -111,6 +119,16 @@ end if strcmp(mom_method,'GMM') 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. end +if strcmp(mom_method,'IRF_MATCHING') + if ~isfield(options_mom_.mom,'irf_matching_file') + options_mom_.mom.irf_matching_file = []; % irf_matching file enables to transform model IRFs before matching them to data IRFs + end + options_mom_.mom.irf_matching_file = set_default_option(options_mom_.mom.irf_matching_file,'name',''); + options_mom_.mom = set_default_option(options_mom_.mom,'simulation_method','STOCH_SIMUL'); % simulation method used to compute IRFs + options_mom_ = set_default_option(options_mom_,'add_tiny_number_to_cholesky',1e-14); % add tiny number to Cholesky factor to avoid numerical problems when computing IRFs + options_mom_ = set_default_option(options_mom_,'drop',100); % truncation / burnin for order>1 irf simulations + options_mom_ = set_default_option(options_mom_,'relative_irf',false); % requests the computation of normalized IRFs +end % data related options if strcmp(mom_method,'GMM') || strcmp(mom_method,'SMM') @@ -123,12 +141,14 @@ if strcmp(mom_method,'GMM') || strcmp(mom_method,'SMM') end % optimization related -if (isoctave && user_has_octave_forge_package('optim')) || (~isoctave && user_has_matlab_license('optimization_toolbox')) - if strcmp(mom_method,'GMM') || strcmp(mom_method,'SMM') +if strcmp(mom_method,'GMM') || strcmp(mom_method,'SMM') + 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 + else + options_mom_ = set_default_option(options_mom_,'mode_compute',5); % specifies newrat as fallback default option for minimization end -else - options_mom_ = set_default_option(options_mom_,'mode_compute',4); % specifies csminwel as fallback default option for minimization +elseif strcmp(mom_method,'IRF_MATCHING') + options_mom_ = set_default_option(options_mom_,'mode_compute',5); % specifies newrat as fallback default option for minimization 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 @@ -136,9 +156,20 @@ options_mom_ = set_default_option(options_mom_,'silent_optimizer',false); 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 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 options_mom_.optimizer_vec = [options_mom_.mode_compute;num2cell(options_mom_.additional_optimizer_steps)]; +options_mom_.mom.analytic_jacobian_optimizers = [1, 3, 4, 13, 101]; % these are currently supported optimizers that are able to use the analytic_jacobian option +options_mom_.analytic_derivation = 0; % force to 0 as we check this seperately in dynare_minimize_objective.m +options_mom_ = set_default_option(options_mom_,'mode_file',''); % name of the file containing initial values for the mode +options_mom_ = set_default_option(options_mom_,'cova_compute',true); % 1: computed covariance via Hessian after the computation of the mode, 0: turn off computation of covariance matrix % perturbation related options_mom_ = set_default_option(options_mom_,'order',1); % order of Taylor approximation in perturbation +if strcmp(mom_method,'IRF_MATCHING') % number of simulated series used to compute IRFs + if options_mom_.order == 1 + options_mom_ = set_default_option(options_mom_,'replic',1); + else + options_mom_ = set_default_option(options_mom_,'replic',50); + end +end options_mom_ = set_default_option(options_mom_,'pruning',false); % use pruned state space system at order>1 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 @@ -161,12 +192,121 @@ options_mom_ = set_default_option(options_mom_,'lyapunov_complex_threshold',1e-1 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 -% mode check plot +% Bayesian MCMC related +if do_bayesian_estimation + options_mom_ = set_default_option(options_mom_,'mh_replic',0); % number of draws in Metropolis-Hastings and slice samplers + options_mom_ = set_default_option(options_mom_,'mh_posterior_mode_estimation',false); % skip optimizer-based mode-finding and instead compute the mode based on a run of a MCMC + options_mom_ = set_default_option(options_mom_,'load_mh_file',false); % add to previous Metropolis-Hastings or slice simulations instead of starting from scratch + options_mom_ = set_default_option(options_mom_,'load_results_after_load_mh',false); % load the previously computed convergence diagnostics, marginal data density, and posterior statistics from an existing mom_results file instead of recomputing them + + if options_mom_.mh_replic > 0 || options_mom_.load_mh_file + options_mom_ = set_default_option(options_mom_,'sub_draws',[]); + options_mom_ = set_default_option(options_mom_,'posterior_max_subsample_draws',1200); + options_mom_ = set_default_option(options_mom_,'mh_nblck',2); % number of parallel chains for Metropolis-Hastings or slice algorithm + options_mom_ = set_default_option(options_mom_,'mh_drop',0.5); % fraction of initially generated parameter vectors to be dropped as a burn-in before using posterior simulations + options_mom_ = set_default_option(options_mom_,'mh_conf_sig',0.9); % confidence/HPD interval used for the computation of prior and posterior statistics + options_mom_ = set_default_option(options_mom_,'mh_recover',false); % attempts to recover a Metropolis-Hastings simulation that crashed prematurely + options_mom_ = set_default_option(options_mom_,'MCMC_jumping_covariance','hessian'); % which covariance to use for the proposal density of the MCMC sampler + if ~isfield(options_mom_,'mh_initialize_from_previous_mcmc') + options_mom_.mh_initialize_from_previous_mcmc.status = false; % pick initial values for new MCMC from a previous one + end + options_mom_.mh_initialize_from_previous_mcmc = set_default_option(options_mom_.mh_initialize_from_previous_mcmc,'directory',''); % pick initial values for new MCMC from a previous one: directory + options_mom_.mh_initialize_from_previous_mcmc = set_default_option(options_mom_.mh_initialize_from_previous_mcmc,'record',''); % pick initial values for new MCMC from a previous one: record file name + options_mom_.mh_initialize_from_previous_mcmc = set_default_option(options_mom_.mh_initialize_from_previous_mcmc,'prior',''); % pick initial values for new MCMC from a previous one: prior file name + if ~isfield(options_mom_,'posterior_sampler_options') + options_mom_.posterior_sampler_options = []; + end + options_mom_.posterior_sampler_options = set_default_option(options_mom_.posterior_sampler_options,'posterior_sampling_method','random_walk_metropolis_hastings'); % selects the sampler used to sample from the posterior distribution during Bayesian estimation + options_mom_.posterior_sampler_options = set_default_option(options_mom_.posterior_sampler_options,'sampling_opt',[]); % used to set options for the posterior sampling methods + switch options_mom_.posterior_sampler_options.posterior_sampling_method + case 'random_walk_metropolis_hastings' + if ~isfield(options_mom_.posterior_sampler_options,'rwmh') + options_mom_.posterior_sampler_options.rwmh = []; + end + options_mom_.posterior_sampler_options.rwmh = set_default_option(options_mom_.posterior_sampler_options.rwmh,'proposal_distribution','rand_multivariate_normal'); + options_mom_.posterior_sampler_options.rwmh = set_default_option(options_mom_.posterior_sampler_options.rwmh,'student_degrees_of_freedom',3); + options_mom_.posterior_sampler_options.rwmh = set_default_option(options_mom_.posterior_sampler_options.rwmh,'use_mh_covariance_matrix',false); + options_mom_.posterior_sampler_options.rwmh = set_default_option(options_mom_.posterior_sampler_options.rwmh,'save_tmp_file',false); + case 'tailored_random_block_metropolis_hastings' + if ~isfield(options_mom_.posterior_sampler_options,'tarb') + options_mom_.posterior_sampler_options.tarb = []; + end + options_mom_.posterior_sampler_options.tarb = set_default_option(options_mom_.posterior_sampler_options.tarb,'proposal_distribution','rand_multivariate_normal'); + options_mom_.posterior_sampler_options.tarb = set_default_option(options_mom_.posterior_sampler_options.tarb,'student_degrees_of_freedom',3); + options_mom_.posterior_sampler_options.tarb = set_default_option(options_mom_.posterior_sampler_options.tarb,'mode_compute',4); + options_mom_.posterior_sampler_options.tarb = set_default_option(options_mom_.posterior_sampler_options.tarb,'new_block_probability',0.25); + options_mom_.posterior_sampler_options.tarb = set_default_option(options_mom_.posterior_sampler_options.tarb,'optim_opt',''); + options_mom_.posterior_sampler_options.tarb = set_default_option(options_mom_.posterior_sampler_options.tarb,'save_tmp_file',true); + case 'slice' + if ~isfield(options_mom_.posterior_sampler_options,'slice') + options_mom_.posterior_sampler_options.slice = []; + end + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'proposal_distribution',''); + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'rotated',0); + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'slice_initialize_with_mode',false); % must be used with rotated + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'use_mh_covariance_matrix',false); % must be used with rotated + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'WR',[]); + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'mode_files',[]); + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'mode',[]); + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'initial_step_size',0.8); + options_mom_.posterior_sampler_options.slice = set_default_option(options_mom_.posterior_sampler_options.slice,'save_tmp_file',true); + case 'independent_metropolis_hastings' + if ~isfield(options_mom_.posterior_sampler_options,'imh') + options_mom_.posterior_sampler_options.imh = []; + end + options_mom_.posterior_sampler_options.imh = set_default_option(options_mom_.posterior_sampler_options.imh,'proposal_distribution','rand_multivariate_normal'); + options_mom_.posterior_sampler_options.imh = set_default_option(options_mom_.posterior_sampler_options.imh,'use_mh_covariance_matrix',false); + options_mom_.posterior_sampler_options.imh = set_default_option(options_mom_.posterior_sampler_options.imh,'save_tmp_file',false); + end + if ~strcmp(options_mom_.posterior_sampler_options.posterior_sampling_method,'slice') + options_mom_ = set_default_option(options_mom_,'mh_init_scale_factor',2); + options_mom_ = set_default_option(options_mom_,'mh_jscale',[]); + end + + % mh_tune_jscale options + if strcmp(options_mom_.posterior_sampler_options.posterior_sampling_method,'random_walk_metropolis_hastings') + if ~isfield(options_mom_,'mh_tune_jscale') + options_mom_.mh_tune_jscale = []; + end + options_mom_.mh_tune_jscale = set_default_option(options_mom_.mh_tune_jscale,'status',false); + options_mom_.mh_tune_jscale = set_default_option(options_mom_.mh_tune_jscale,'target',0.33); + options_mom_.mh_tune_jscale = set_default_option(options_mom_.mh_tune_jscale,'guess',[]); + options_mom_.mh_tune_jscale.maxiter = options_.mh_tune_jscale.maxiter; + options_mom_.mh_tune_jscale.rho = options_.mh_tune_jscale.rho; + options_mom_.mh_tune_jscale.stepsize = options_.mh_tune_jscale.stepsize; + options_mom_.mh_tune_jscale.c1 = options_.mh_tune_jscale.c1; + options_mom_.mh_tune_jscale.c2 = options_.mh_tune_jscale.c2; + options_mom_.mh_tune_jscale.c3 = options_.mh_tune_jscale.c3; + end + + % convergence diagnostics + options_mom_ = set_default_option(options_mom_,'nodiagnostic',false); + if ~isfield(options_mom_,'convergence') + options_mom_.convergence = []; + end + if ~isfield(options_mom_.convergence,'geweke') + options_mom_.convergence.geweke = []; + end + if ~isfield(options_mom_.convergence,'rafterylewis') + options_mom_.convergence.rafterylewis = []; + end + if ~isfield(options_mom_.convergence,'brooksgelman') + options_mom_.convergence.brooksgelman = []; + end + options_mom_.convergence.geweke = set_default_option(options_mom_.convergence.geweke,'taper_steps', [4 8 15]); + options_mom_.convergence.geweke = set_default_option(options_mom_.convergence.geweke,'geweke_interval', [0.2 0.5]); + options_mom_.convergence.rafterylewis = set_default_option(options_mom_.convergence.rafterylewis,'indicator', false); + options_mom_.convergence.rafterylewis = set_default_option(options_mom_.convergence.rafterylewis,'qrs', [0.025 0.005 0.95]); + options_mom_.convergence.brooksgelman = set_default_option(options_mom_.convergence.brooksgelman,'plotrows',3); + end +end + +% mode check plot options 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) +options_mom_.mode_check = set_default_option(options_mom_.mode_check,'status',false); % plot the target function for values around the computed mode 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 mode 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 mode. A value of 0 allows to have asymmetric plots, which can be useful if the mode 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 mode where the target function is evaluated (for each parameter) % ------------------------------------------------------------------------- @@ -180,8 +320,12 @@ options_mom_.obs_nbr = length(options_mom_.varobs); % number of observed variabl % related to call of dynare options_mom_.console_mode = options_.console_mode; +if options_mom_.console_mode + options_mom_.nodisplay = true; +end options_mom_.parallel = options_.parallel; options_mom_.parallel_info = options_.parallel_info; +options_mom_.debug = options_.debug; % debug option is needed by some functions, e.g. check_plot % related to estimated_params and estimated_params_init blocks options_mom_.use_calibration_initialization = options_.use_calibration_initialization; @@ -250,19 +394,82 @@ end options_mom_.gstep = options_.gstep; % needed by hessian.m options_mom_.trust_region_initial_step_bound_factor = options_.trust_region_initial_step_bound_factor; % used in dynare_solve for trust_region -% other +% miscellaneous +options_mom_.threads = options_.threads; options_mom_.MaxNumberOfBytes = options_.MaxNumberOfBytes; -%options_mom_.MaximumNumberOfMegaBytes = options_.MaximumNumberOfMegaBytes; +options_mom_.marginal_data_density = options_.marginal_data_density; % ------------------------------------------------------------------------- % DEFAULT VALUES % ------------------------------------------------------------------------- - -options_mom_.analytic_derivation = 0; +options_mom_.mom.compute_derivs = false; % flag to compute derivs in objective function (might change for GMM with either analytic_standard_errors or analytic_jacobian (dependent on optimizer)) +options_mom_.mom.vector_output = false; % specifies whether the objective function returns a vector 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_.initialize_estimated_parameters_with_the_prior_mode = 0; % needed by set_prior.m -options_mom_.figures = options_.figures; % needed by plot_priors.m -options_mom_.ramsey_policy = false; % needed by evaluate_steady_state -options_mom_.risky_steadystate = false; % needed by resol -options_mom_.jacobian_flag = true; % needed by dynare_solve \ No newline at end of file +options_mom_.figures = options_.figures; % needed by plot_priors.m +options_mom_.ramsey_policy = false; % needed by evaluate_steady_state +options_mom_.risky_steadystate = false; % needed by resol +options_mom_.jacobian_flag = true; % needed by dynare_solve +options_mom_.use_mh_covariance_matrix = false; % needed by posterior_sampler, get's overwritten by same option in options_mom_.posterior_sampler_options + + +% ------------------------------------------------------------------------- +% CHECKS ON SETTINGS +% ------------------------------------------------------------------------- +if strcmp(mom_method,'GMM') || strcmp(mom_method,'SMM') + if numel(options_mom_.nobs) > 1 + error('method_of_moments: Recursive estimation is not supported. Please set an integer as ''nobs''!'); + end + if numel(options_mom_.first_obs) > 1 + error('method_of_moments: Recursive estimation is not supported. Please set an integer as ''first_obs''!'); + end +end +if options_mom_.order < 1 + error('method_of_moments: The order of the Taylor approximation cannot be 0!') +end +if options_mom_.order > 2 + fprintf('Dynare will use ''k_order_solver'' as the order>2\n'); + options_mom_.k_order_solver = true; +end +if strcmp(mom_method,'SMM') + if options_mom_.mom.simulation_multiple < 1 + fprintf('The simulation horizon is shorter than the data. Dynare resets the simulation_multiple to 7.\n') + options_mom_.mom.simulation_multiple = 7; + end +end +if strcmp(mom_method,'GMM') + % require 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!'); + end +end +if strcmp(mom_method,'IRF_MATCHING') && do_bayesian_estimation + if isfield(options_mom_,'mh_tune_jscale') && options_mom_.mh_tune_jscale.status && (options_mom_.mh_tune_jscale.maxiter<options_mom_.mh_tune_jscale.stepsize) + warning('method_of_moments: You specified mh_tune_jscale, but the maximum number of iterations is smaller than the step size. No update will take place.') + end + if options_mom_.load_results_after_load_mh + if ~exist([options_mom_.dirname filesep 'method_of_moments' filesep M_.fname '_mom_results.mat'],'file') + fprintf('\nYou specified the ''load_results_after_load_mh'' option, but no ''%s_mom_results.mat'' file\n',M_.fname); + fprintf('was found in the folder %s%smethod_of_moments.\n',options_mom_.dirname,filesep); + fprintf('Results will be recomputed and option ''load_results_after_load_mh'' is reset to false.\n'); + options_mom_.load_results_after_load_mh = false; + end + end + if options_mom_.mh_replic>0 && options_mom_.mh_nblck<1 + error('method_of_moments: Bayesian MCMC estimation cannot be conducted with ''mh_nblocks''=0!') + end +end +if options_mom_.mom.analytic_jacobian && ~strcmp(mom_method,'GMM') + options_mom_.mom.analytic_jacobian = false; + fprintf('\n''analytic_jacobian'' option will be dismissed as it only works with GMM.\n'); +end +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + if any(cellfun(@(x) isnumeric(x) && any(x == 13), options_mom_.optimizer_vec)) + error('method_of_moments: lsqnonlin (mode_compute=13) is not yet supported for IRF matching!'); + end +end \ No newline at end of file diff --git a/matlab/+mom/display_comparison_moments.m b/matlab/+mom/display_comparison_moments.m deleted file mode 100644 index bcd1584edcb2e728dd8a399babaddddfef13689d..0000000000000000000000000000000000000000 --- a/matlab/+mom/display_comparison_moments.m +++ /dev/null @@ -1,74 +0,0 @@ -function display_comparison_moments(M_, options_mom_, data_moments, model_moments) -% function display_comparison_moments(M_, options_mom_, data_moments, model_moments) -% ------------------------------------------------------------------------- -% Displays and saves to disk the comparison of the data moments and the model moments -% ========================================================================= -% INPUTS -% M_: [structure] model information -% options_mom_: [structure] method of moments options -% data_moments: [vector] data moments -% model_moments: [vector] model moments -% ------------------------------------------------------------------------- -% OUTPUT -% No output, just displays and saves to disk the comparison of the data moments and the model moments -% ------------------------------------------------------------------------- -% This function is called by -% o mom.run -% ------------------------------------------------------------------------- -% This function calls -% o dyn_latex_table -% o dyntable -% o cellofchararraymaxlength -% ========================================================================= -% Copyright © 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 <https://www.gnu.org/licenses/>. -% ========================================================================= - -titl = ['Comparison of matched 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 = [data_moments model_moments]; -dyntable(options_mom_, titl, headers, labels, data_mat, cellofchararraymaxlength(labels)+2, 10, 7); -if options_mom_.TeX - dyn_latex_table(M_, options_mom_, titl, ['comparison_moments_', options_mom_.mom.mom_method], headers, labels_TeX, data_mat, cellofchararraymaxlength(labels)+2, 10, 7); -end \ No newline at end of file diff --git a/matlab/+mom/display_comparison_moments_irfs.m b/matlab/+mom/display_comparison_moments_irfs.m new file mode 100644 index 0000000000000000000000000000000000000000..f21c745f37f61dc2d60c4050ba7364d76b8d0651 --- /dev/null +++ b/matlab/+mom/display_comparison_moments_irfs.m @@ -0,0 +1,96 @@ +function display_comparison_moments_irfs(M_, options_mom_, data_moments, model_moments) +% display_comparison_moments_irfs(M_, options_mom_, data_moments, model_moments) +% ------------------------------------------------------------------------- +% Displays and saves to disk the comparison of the data moments/IRFs and the model moments/IRFs +% ------------------------------------------------------------------------- +% INPUTS +% M_: [structure] model information +% options_mom_: [structure] method of moments options +% data_moments: [vector] data moments +% model_moments: [vector] model moments +% ------------------------------------------------------------------------- +% OUTPUT +% No output, just displays and saves to disk the comparison of the data moments and the model moments +% ------------------------------------------------------------------------- +% This function is called by +% o mom.run +% ------------------------------------------------------------------------- +% This function calls +% o dyn_latex_table +% o dyntable +% o cellofchararraymaxlength +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + + +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + titl = upper('Comparison of matched data IRFs and model IRFs'); + headers = {'IRF','Data','Model'}; + idx = 1; + for jj = 1:size(M_.matched_irfs,1) + irf_varname = M_.matched_irfs{jj,1}; + irf_shockname = M_.matched_irfs{jj,2}; + % note that periods can span over multiple rows + IRF_PERIODS = []; + for kk = 1:size(M_.matched_irfs{jj,3},1) + irf_periods = M_.matched_irfs{jj,3}{kk,1}; + IRF_PERIODS = [IRF_PERIODS; irf_periods(:)]; + end + for hh = 1:length(IRF_PERIODS) + labels{idx,1} = sprintf('%s %s (%u)',irf_varname,irf_shockname,IRF_PERIODS(hh)); + labels_TeX{idx,1} = sprintf('%s %s (%u)',M_.endo_names_tex{ismember(M_.endo_names,irf_varname)},M_.exo_names_tex{ismember(M_.exo_names,irf_shockname)},IRF_PERIODS(hh)); + idx = idx+1; + end + end +else + titl = ['Comparison of matched 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 +end +data_mat = [data_moments model_moments]; +dyntable(options_mom_, titl, headers, labels, data_mat, cellofchararraymaxlength(labels)+2, 10, 7); +if options_mom_.TeX + dyn_latex_table(M_, options_mom_, titl, ['comparison_moments_', options_mom_.mom.mom_method], headers, labels_TeX, data_mat, cellofchararraymaxlength(labels)+2, 10, 7); +end \ No newline at end of file diff --git a/matlab/+mom/get_data_moments.m b/matlab/+mom/get_data_moments.m index aedf02f28976349dd5b5e3c2ffce1bf76da67e3b..e00f6de2ed5922dd342357c68c497a3d04336b89 100644 --- a/matlab/+mom/get_data_moments.m +++ b/matlab/+mom/get_data_moments.m @@ -1,7 +1,8 @@ -function [dataMoments, m_data] = get_data_moments(data, obs_var, inv_order_var, matched_moments_, options_mom_) -% [dataMoments, m_data] = get_data_moments(data, obs_var, inv_order_var, matched_moments_, options_mom_) -% This function computes the user-selected empirical moments from data -% ========================================================================= +function [data_moments, m_data] = get_data_moments(data, obs_var, inv_order_var, matched_moments_, options_mom_) +% [data_moments, m_data] = get_data_moments(data, obs_var, inv_order_var, matched_moments_, options_mom_) +% ------------------------------------------------------------------------- +% Computes the user-selected empirical moments from data +% ------------------------------------------------------------------------- % INPUTS % o data [T x varobs_nbr] data set % o obs_var: [integer] index of observables @@ -10,13 +11,14 @@ function [dataMoments, m_data] = get_data_moments(data, obs_var, inv_order_var, % o options_mom_: [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 data_moments [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 mom.run % o mom.objective_function -% ========================================================================= +% ------------------------------------------------------------------------- + % Copyright © 2020-2023 Dynare Team % % This file is part of Dynare. @@ -33,15 +35,11 @@ function [dataMoments, m_data] = get_data_moments(data, obs_var, inv_order_var, % % 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 (johannes.pfeifer@unibw.de) -% ========================================================================= + % Initialization T = size(data,1); % Number of observations (T) -dataMoments = NaN(options_mom_.mom.mom_nbr,1); +data_moments = NaN(options_mom_.mom.mom_nbr,1); m_data = NaN(T,options_mom_.mom.mom_nbr); % Product moment for each time period, i.e. each row t contains y_t1(l1)^p1*y_t2(l2)^p2*... % note that here we already are able to treat leads and lags and any power product moments @@ -61,10 +59,10 @@ for jm = 1:options_mom_.mom.mom_nbr end % We replace NaN (due to leads and lags and missing values) with the corresponding mean if isoctave && octave_ver_less_than('8') - dataMoments(jm,1) = nanmean(m_data_tmp); + data_moments(jm,1) = nanmean(m_data_tmp); else - dataMoments(jm,1) = mean(m_data_tmp,'omitnan'); + data_moments(jm,1) = mean(m_data_tmp,'omitnan'); end - m_data_tmp(isnan(m_data_tmp)) = dataMoments(jm,1); + m_data_tmp(isnan(m_data_tmp)) = data_moments(jm,1); m_data(:,jm) = m_data_tmp; end diff --git a/matlab/+mom/graph_comparison_irfs.m b/matlab/+mom/graph_comparison_irfs.m new file mode 100644 index 0000000000000000000000000000000000000000..5e7f574871047b4f0eee565d9f60c92a0fa30dbf --- /dev/null +++ b/matlab/+mom/graph_comparison_irfs.m @@ -0,0 +1,129 @@ +function graph_comparison_irfs(matched_irfs,irf_model_varobs,varobs_id,irf_horizon,relative_irf,endo_names,endo_names_tex,exo_names,exo_names_tex,dname,fname,graph_format,TeX,nodisplay,figures_textwidth) +% graph_comparison_irfs(matched_irfs,irf_model_varobs,varobs_id,irf_horizon,relative_irf,endo_names,endo_names_tex,exo_names,exo_names_tex,dname,fname,graph_format,TeX,nodisplay,figures_textwidth) +% ------------------------------------------------------------------------- +% Plots and saves to disk the comparison of the selected data IRFs and corresponding model IRfs +% ------------------------------------------------------------------------- +% INPUTS +% matched_irfs: [matrix] information on matched data IRFs +% irf_model_varobs: [matrix] model IRFs for observable variables +% varobs_id: [vector] index for observable variables in endo_names +% irf_horizon: [scalar] maximum horizon of IRFs +% relative_irf: [boolean] if true, plots normalized IRFs +% endo_names: [cell] names of endogenous variables +% endo_names_tex: [cell] names of endogenous variables in latex +% exo_names: [cell] names of exogenous variables +% exo_names_tex: [cell] names of exogenous variables in latex +% dname: [string] name of the directory where to save the graphs +% fname: [string] name of the mod file +% graph_format: [cell] format of the graphs +% TeX: [boolean] if true, uses latex for plots +% nodisplay: [boolean] if true, does not display the graphs +% figures_textwidth: [scalar] textwidth used in plots +% ------------------------------------------------------------------------- +% OUTPUT +% No output, just displays and saves to disk the graphs +% ------------------------------------------------------------------------- +% This function is called by +% o mom.run +% ------------------------------------------------------------------------- +% This function calls +% o dyn_figure +% o dyn_saveas +% o remove_fractional_xticks +% o CheckPath +% o pltorg +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + + +graph_directory_name = CheckPath('graphs',dname); +latex_directory_name = CheckPath('latex',dname); +if TeX && any(strcmp('eps',cellstr(graph_format))) + fid_TeX = fopen([latex_directory_name '/' fname '_irf_matching_plot.tex'],'w'); + fprintf(fid_TeX,'%% TeX eps-loader file generated by mom.run.m (Dynare).\n'); + fprintf(fid_TeX,['%% ' datestr(now,0) '\n']); + fprintf(fid_TeX,' \n'); +end +unique_shock_entries = unique(matched_irfs(:, 2)); +colDarkGrey = [0.3, 0.3, 0.3]; % dark grey +for jexo = unique_shock_entries' % loop over cell with shock names + unique_variables = unique(matched_irfs(ismember(matched_irfs(:, 2),jexo), 1)); + [nbplt,nr,nc,lr,lc,nstar] = pltorg(length(unique_variables)); + fig = 0; + for jvar = 1:length(unique_variables) + % get data points, note that periods and values can span over multiple rows + jj = ismember(matched_irfs(:,1), unique_variables(jvar)) & ismember(matched_irfs(:,2), jexo); + IRF_PERIODS = []; IRF_VALUES = []; + for kk = 1:size(matched_irfs{jj,3},1) + irf_periods = matched_irfs{jj,3}{kk,1}; + irf_values = matched_irfs{jj,3}{kk,2}; + if length(irf_values)==1 + irf_values = repmat(irf_values,length(irf_periods),1); + end + IRF_PERIODS = [IRF_PERIODS; irf_periods(:)]; + IRF_VALUES = [IRF_VALUES; irf_values(:)]; + end + + if jvar==1 || ~( (fig-1)*nstar<jvar && jvar<=fig*nstar ) + fig = fig+1; + fig_irf = dyn_figure(nodisplay,'Name',['IRF matching shock to ' jexo{:} ' figure ' int2str(fig)]); + end + plt = jvar-(fig-1)*nstar; + if nbplt>1 && fig==nbplt + subplot(lr,lc,plt); + else + subplot(nr,nc,plt); + end + plt_data = plot(IRF_PERIODS,IRF_VALUES,'h', 'MarkerEdgeColor',colDarkGrey,'MarkerFaceColor',colDarkGrey,'MarkerSize',8); + hold on + plt_model = plot(1:irf_horizon, irf_model_varobs(:,varobs_id==find(ismember(endo_names,unique_variables(jvar))) , ismember(exo_names,jexo)),'-k','linewidth',2); + hold on + plot([1 irf_horizon],[0 0],'-r','linewidth',1); + hold off + xlim([1 irf_horizon]); + remove_fractional_xticks + if TeX + title(['$' endo_names_tex{ismember(endo_names,unique_variables(jvar))} '$'],'Interpreter','latex'); + else + title(unique_variables{jvar},'Interpreter','none'); + end + set(gca,'FontSize',12); + if (plt==nstar) || jvar==length(unique_variables) + % Adding a legend at the bottom + axes('Position',[0, 0, 1, 1],'Visible','off'); + lgd = legend([plt_data,plt_model],{'Data', 'Model'}, 'Location', 'southeast','NumColumns',2,'FontSize',14); + lgd.Position = [0.37 0.01 lgd.Position(3) lgd.Position(4)]; + + dyn_saveas(fig_irf,[graph_directory_name filesep fname '_matched_irf_' jexo{:} int2str(fig)],nodisplay,graph_format); + if TeX && any(strcmp('eps',cellstr(graph_format))) + fprintf(fid_TeX,'\\begin{figure}[H]\n'); + fprintf(fid_TeX,'\\centering \n'); + fprintf(fid_TeX,'\\includegraphics[width=%2.2f\\textwidth]{%s_matched_irf_%s%s}\n',figures_textwidth*min(plt/nc,1),[graph_directory_name '/' fname],jexo{:},int2str(fig)); + if relative_irf + fprintf(fid_TeX,'\\caption{Relative impulse response functions (orthogonalized shock to $%s$).}', jexo{:}); + else + fprintf(fid_TeX,'\\caption{Impulse response functions (orthogonalized shock to $%s$).}', jexo{:}); + end + fprintf(fid_TeX,'\\label{Fig:MatchedIRF:%s:%s}\n', jexo{:},int2str(fig)); + fprintf(fid_TeX,'\\end{figure}\n'); + fprintf(fid_TeX,' \n'); + end + end + end +end \ No newline at end of file diff --git a/matlab/+mom/matched_irfs_blocks.m b/matlab/+mom/matched_irfs_blocks.m new file mode 100644 index 0000000000000000000000000000000000000000..ed8f01aa8f3ec5cbe6be2b27b09ba710511e83fe --- /dev/null +++ b/matlab/+mom/matched_irfs_blocks.m @@ -0,0 +1,151 @@ +function [data_irfs, weight_mat, irf_index, max_irf_horizon] = matched_irfs_blocks(matched_irfs, matched_irfs_weight, varobs_id, obs_nbr, exo_nbr, endo_names, exo_names) +% [data_irfs, weight_mat, irf_index, max_irf_horizon] = matched_irfs_blocks(matched_irfs, matched_irfs_weight, varobs_id, obs_nbr, exo_nbr, endo_names, exo_names) +% ------------------------------------------------------------------------- +% Checks and transforms matched_irfs and matched_irfs_weight blocks +% for further use in the estimation. +% ------------------------------------------------------------------------- +% INPUTS +% matched_irfs: [cell array] original matched_irfs block +% matched_irfs_weight: [cell array] original matched_irfs_weight block +% varobs_id: [vector] index for observable variables in endo_names +% obs_nbr: [scalar] number of observable variables +% exo_nbr: [scalar] number of exogenous variables +% endo_names: [cell array] names of endogenous variables +% exo_names: [cell array] names of exogenous variables +% ------------------------------------------------------------------------- +% OUTPUT +% data_irfs: [matrix] IRFs for VAROBS as declared in matched_irfs block +% weight_mat: [matrix] weighting matrix for IRFs as declared in matched_irfs_weight block +% irf_index: [vector] index for selecting specific IRFs from full IRF matrix of observables +% max_irf_horizon: [scalar] maximum IRF horizon as declared in matched_irfs block +% ------------------------------------------------------------------------- +% This function is called by +% o mom.run +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + +% note matched_irfs block: +% - each row in the cell contains a unique combination of var and varexo, +% however the third column in each row is a nested cell with information +% on periods, values and weights +% - periods, values and weights can span several rows with different lengths of entries +% - in some cases we need to duplicate values and/or weights +% - at the end we want to have everything vectorized and the same length + +% get maximum IRF horizons +max_irf_horizon = []; +for jj = 1:size(matched_irfs,1) + max_irf_horizon = [max_irf_horizon; cell2mat(cellfun(@(c) c(:), matched_irfs{jj,3}(:,1), 'UniformOutput', false))]; +end +max_irf_horizon = max(max_irf_horizon); + +% create full matrix where 1st dimension are IRF periods, 2nd dimension are variables as declared in VAROBS, 3rd dimension are shocks +% idea: overwrite NaN values if they are declared in matched_irfs block; at the end the remaining NaN values will be removed +data_irfs = NaN(max_irf_horizon,obs_nbr,exo_nbr); +% create full empirical weighting matrix, identity matrix by default, i.e. all IRFs are equally important +% idea: first specify full matrix and then reduce it using only entries that are declared in matched_irfs block +weight_mat = speye(max_irf_horizon*obs_nbr*exo_nbr); + +for jj = 1:size(matched_irfs,1) + id_var = find(ismember(endo_names,matched_irfs{jj,1})); + id_varobs = find(varobs_id==id_var,1); + id_shock = find(ismember(exo_names,matched_irfs{jj,2})); + if isempty(id_varobs) + skipline; + error('method_of_moments: You specified an IRF matching involving variable %s, but it is not declared as a varobs!',endo_names{id_var}) + end + IRF_PERIODS = []; IRF_VALUES = []; IRF_WEIGHTS = []; + for kk = 1:size(matched_irfs{jj,3},1) + irf_periods = matched_irfs{jj,3}{kk,1}; + if length(unique(irf_periods)) < length(irf_periods) % row-specific check for unique periods + error('method_of_moments: You specified an IRF matching involving variable %s and shock %s, but there were duplicate ''periods'' in the specification!',endo_names{id_var},exo_names{id_shock}); + end + irf_values = matched_irfs{jj,3}{kk,2}; + if length(irf_values)==1 + irf_values = repmat(irf_values,length(irf_periods),1); + end + if length(irf_periods) ~= length(irf_values) % row-specific check for enough values + error('method_of_moments: You specified an IRF matching involving variable %s and shock %s, but the length of ''periods'' does not match the length of ''values''!',endo_names{id_var},exo_names{id_shock}); + end + irf_weights = matched_irfs{jj,3}{kk,3}; + if length(irf_weights)==1 + irf_weights = repmat(irf_weights,length(irf_periods),1); + end + if length(irf_periods) ~= length(irf_weights) % row-specific check for enough weights + error('method_of_moments: You specified an IRF matching involving variable %s and shock %s, but the length of ''periods'' does not match the length of ''weights''!',endo_names{id_var},exo_names{id_shock}); + end + IRF_PERIODS = [IRF_PERIODS; irf_periods(:)]; + IRF_VALUES = [IRF_VALUES; irf_values(:)]; + IRF_WEIGHTS = [IRF_WEIGHTS; irf_weights(:)]; + end + if length(unique(irf_periods)) < length(irf_periods) % overall check for unique periods + error('method_of_moments: You specified an IRF matching involving variable %s and shock %s, but there were duplicate ''periods'' in the specification!',endo_names{id_var},exo_names{id_shock}); + end + for hh = 1:length(IRF_PERIODS) + data_irfs(IRF_PERIODS(hh),id_varobs,id_shock) = IRF_VALUES(hh); + if IRF_WEIGHTS(hh) ~= 1 + idweight_mat = sub2ind(size(data_irfs),IRF_PERIODS(hh),id_varobs,id_shock); + weight_mat(idweight_mat,idweight_mat) = IRF_WEIGHTS(hh); + end + end +end + +% fine-tune weighting matrix using matched_irfs_weights +for jj = 1:size(matched_irfs_weight,1) + id_var1 = find(ismember(endo_names,matched_irfs_weight{jj,1})); + id_var2 = find(ismember(endo_names,matched_irfs_weight{jj,4})); + id_varobs1 = find(varobs_id==id_var1,1); + id_varobs2 = find(varobs_id==id_var2,1); + if isempty(id_varobs1) + skipline; + error('method_of_moments: You specified a weight for an IRF matching involving variable %s, but it is not a varobs!',endo_names{id_var1}) + end + if isempty(id_varobs2) + skipline; + error('method_of_moments: You specified a weight for an IRF matching involving variable %s, but it is not a varobs!',endo_names{id_var2}) + end + id_shock1 = find(ismember(exo_names,matched_irfs_weight{jj,3})); + id_shock2 = find(ismember(exo_names,matched_irfs_weight{jj,6})); + irf_periods1 = matched_irfs_weight{jj,2}; + irf_periods2 = matched_irfs_weight{jj,5}; + if length(irf_periods1) ~= length(irf_periods2) + error('method_of_moments: You specified a ''matched_irfs_weights'' entry for an IRF matching involving %s/%s and %s/%s,\n but the horizons do not have the same length!',endo_names{id_var1},exo_names{id_shock1},endo_names{id_var2},exo_names{id_shock2}); + end + if max([irf_periods1(:);irf_periods2(:)]) > max_irf_horizon + error('method_of_moments: You specified a ''matched_irfs_weights'' entry for an IRF matching involving %s/%s and %s/%s,\n but the horizon is larger than the maximum one declared in the ''matched_irfs'' block!',endo_names{id_var1},exo_names{id_shock1},endo_names{id_var2},exo_names{id_shock2}); + end + weight_mat_values = matched_irfs_weight{jj,7}; + if length(weight_mat_values)==1 && length(irf_periods1)>1 + weight_mat_values = repmat(weight_mat_values,length(irf_periods1),1); + end + if length(weight_mat_values) ~= length(irf_periods1) + error('method_of_moments: You specified a ''matched_irfs_weights'' entry for an IRF matching involving %s/%s and %s/%s,\n but the horizons do not match the length of ''weights''!',endo_names{id_var1},exo_names{id_shock1},endo_names{id_var2},exo_names{id_shock2}); + end + for hh = 1:length(irf_periods1) + idweight_mat1 = sub2ind(size(data_irfs),irf_periods1(hh),id_varobs1,id_shock1); + idweight_mat2 = sub2ind(size(data_irfs),irf_periods2(hh),id_varobs2,id_shock2); + weight_mat(idweight_mat1,idweight_mat2) = weight_mat_values(hh); + weight_mat(idweight_mat2,idweight_mat1) = weight_mat_values(hh); % symmetry + end +end + +% remove non-specified IRFs +irf_index = find(~isnan(data_irfs)); +data_irfs = data_irfs(irf_index); +weight_mat = weight_mat(irf_index,irf_index); \ No newline at end of file diff --git a/matlab/+mom/matched_moments_block.m b/matlab/+mom/matched_moments_block.m index a0b44c70b87b848001c744849b4fee29107c8760..5d7a5154552461fe27426eec0c1ec232a8dceaf2 100644 --- a/matlab/+mom/matched_moments_block.m +++ b/matlab/+mom/matched_moments_block.m @@ -1,8 +1,8 @@ function matched_moments = matched_moments_block(matched_moments, mom_method) -% function matched_moments = matched_moments_block(matched_moments, mom_method) +% matched_moments = matched_moments_block(matched_moments, mom_method) +% ------------------------------------------------------------------------- +% Checks and transforms matched_moments block for further use in the estimation % ------------------------------------------------------------------------- -% Checks and transforms matched_moments bock for further use in the estimation -% ========================================================================= % INPUTS % matched_moments: [cell array] original matched_moments block % mom_method: [string] method of moments method (GMM or SMM) @@ -12,7 +12,8 @@ function matched_moments = matched_moments_block(matched_moments, mom_method) % ------------------------------------------------------------------------- % This function is called by % o mom.run -% ========================================================================= +% ------------------------------------------------------------------------- + % Copyright © 2023 Dynare Team % % This file is part of Dynare. @@ -29,7 +30,7 @@ function matched_moments = matched_moments_block(matched_moments, mom_method) % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ========================================================================= + matched_moments_orig = matched_moments; % higher-order product moments not supported yet for GMM @@ -59,22 +60,22 @@ for jm = 1:size(matched_moments,1) 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,matched_moments(:,3))'; -UniqueMomIdx = []; +unique_mom_idx = []; for jpow = unique(powers) idx1 = find(powers==jpow); [~,idx2] = unique(cell2mat(matched_moments(idx1,:)),'rows'); - UniqueMomIdx = [UniqueMomIdx idx1(idx2)]; + unique_mom_idx = [unique_mom_idx idx1(idx2)]; end % remove duplicate elements -DuplicateMoms = setdiff(1:size(matched_moments_orig,1),UniqueMomIdx); -if ~isempty(DuplicateMoms) - fprintf('Duplicate declared moments found and removed in ''matched_moments'' block in rows:\n %s.\n',num2str(DuplicateMoms)) +duplicate_moms = setdiff(1:size(matched_moments_orig,1),unique_mom_idx); +if ~isempty(duplicate_moms) + fprintf('Duplicate declared moments found and removed in ''matched_moments'' block in rows:\n %s.\n',num2str(duplicate_moms)); fprintf('Dynare will continue with remaining moment conditions\n'); end if strcmp(mom_method, 'SMM') % for SMM: keep the original structure, but get rid of duplicate moments - matched_moments = matched_moments_orig(sort(UniqueMomIdx),:); + matched_moments = matched_moments_orig(sort(unique_mom_idx),:); elseif strcmp(mom_method, 'GMM') % for GMM we use the transformed matched_moments structure - matched_moments = matched_moments(sort(UniqueMomIdx),:); + matched_moments = matched_moments(sort(unique_mom_idx),:); end \ No newline at end of file diff --git a/matlab/+mom/mode_compute_gmm_smm.m b/matlab/+mom/mode_compute_gmm_smm.m index 2c1fc5ef6772b646a175701162e0190a3aefaebf..77d0e075d916e119dba3dad6e8a9346bb5bc019a 100644 --- a/matlab/+mom/mode_compute_gmm_smm.m +++ b/matlab/+mom/mode_compute_gmm_smm.m @@ -1,25 +1,30 @@ -function [xparam1, oo_, Woptflag] = mode_compute_gmm_smm(xparam0, objective_function, oo_, M_, options_mom_, estim_params_, bayestopt_, Bounds) -% function [xparam1, oo_, Woptflag] = mode_compute_gmm_smm(xparam0, objective_function, oo_, M_, options_mom_, estim_params_, bayestopt_, Bounds) +function [xparam1, weighting_info, mom_verbose] = mode_compute_gmm_smm(xparam0, objective_function, m_data, data_moments, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) +% [xparam1, weighting_info, mom_verbose] = mode_compute_gmm_smm(xparam0, objective_function, m_data, data_moments, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) % ------------------------------------------------------------------------- % Iterated method of moments for GMM and SMM, computes the minimum of the % objective function (distance between data moments and model moments) % for a sequence of optimizers and GMM/SMM iterations with different % weighting matrices. -% ========================================================================= +% ------------------------------------------------------------------------- % INPUTS -% xparam0: [vector] vector of initialized parameters -% objective_function: [func handle] name of the objective function -% oo_: [structure] results -% M_: [structure] model information -% options_mom_: [structure] options -% estim_params_: [structure] information on estimated parameters -% bayestopt_: [structure] information on priors -% Bounds: [structure] bounds for optimization +% xparam0: [vector] vector of initialized parameters +% objective_function: [func handle] name of the objective function +% m_data: [matrix] selected data moments at each point in time +% data_moments: [vector] vector of data moments +% options_mom_: [structure] options +% M_: [structure] model information +% estim_params_: [structure] information on estimated parameters +% bayestopt_: [structure] information on priors +% BoundsInfo: [structure] bounds for optimization +% dr: [structure] reduced form model +% endo_steady_state: [vector] steady state for endogenous variables (initval) +% exo_steady_state: [vector] steady state for exogenous variables (initval) +% exo_det_steady_state: [vector] steady state for exogenous deterministic variables (initval) % ------------------------------------------------------------------------- % OUTPUT -% xparam1: [vector] mode of objective function -% oo_: [structure] updated results -% Woptflag: [logical] true if optimal weighting matrix was computed +% xparam1: [vector] mode of objective function +% weighting_info: [structure] information on weighting matrix +% mom_verbose: [structure] information on intermediate estimation results % ------------------------------------------------------------------------- % This function is called by % o mom.run @@ -29,7 +34,9 @@ function [xparam1, oo_, Woptflag] = mode_compute_gmm_smm(xparam0, objective_func % o mom.display_estimation_results_table % o dynare_minimize_objective % o mom.objective_function -% ========================================================================= +% o prior_dist_names +% ------------------------------------------------------------------------- + % Copyright © 2023 Dynare Team % % This file is part of Dynare. @@ -46,15 +53,16 @@ function [xparam1, oo_, Woptflag] = mode_compute_gmm_smm(xparam0, objective_func % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ========================================================================= + +mom_verbose = []; 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') + 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; + weighting_info.Woptflag = false; switch lower(options_mom_.mom.weighting_matrix{stage_iter}) case 'identity_matrix' fprintf(' - identity weighting matrix\n'); @@ -63,44 +71,44 @@ for stage_iter = 1:size(options_mom_.mom.weighting_matrix,1) 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) )); + weighting_matrix = diag(diag( mom.optimal_weighting_matrix(m_data, 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) )); + weighting_matrix = diag(diag( mom.optimal_weighting_matrix(m_data, 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); + weighting_matrix = mom.optimal_weighting_matrix(m_data, 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; + weighting_matrix = mom.optimal_weighting_matrix(m_data, model_moments, options_mom_.mom.bartlett_kernel_lag); + weighting_info.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 !']) + 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!']) + if ~isequal(nrow,ncol) || ~isequal(nrow,length(data_moments)) %check if square and right size + error(['method_of_moments: ''weighting_matrix'' must be square and have ',num2str(length(data_moments)),' rows and columns!']); end end try % check for positive definiteness of weighting_matrix - oo_.mom.Sw = chol(weighting_matrix); + weighting_info.Sw = chol(weighting_matrix); catch - error('method_of_moments: Specified ''weighting_matrix'' is not positive definite. Check whether your model implies stochastic singularity!') + error('method_of_moments: Specified ''weighting_matrix'' is not positive definite. Check whether your model implies stochastic singularity!'); end for optim_iter = 1:length(options_mom_.optimizer_vec) options_mom_.current_optimizer = options_mom_.optimizer_vec{optim_iter}; if options_mom_.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_); + xparam1 = xparam0; % no minimization, evaluate objective at current values + fval = feval(objective_function, xparam1, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); else if options_mom_.optimizer_vec{optim_iter} == 13 options_mom_.mom.vector_output = true; @@ -112,18 +120,22 @@ for stage_iter = 1:size(options_mom_.mom.weighting_matrix,1) else options_mom_.mom.compute_derivs = false; end - [xparam1, fval] = dynare_minimize_objective(objective_function, xparam0, options_mom_.optimizer_vec{optim_iter}, options_mom_, [Bounds.lb Bounds.ub], bayestopt_.name, bayestopt_, [],... - Bounds, oo_, estim_params_, M_, options_mom_); + [xparam1, fval] = dynare_minimize_objective(objective_function, xparam0, options_mom_.optimizer_vec{optim_iter}, options_mom_, [BoundsInfo.lb BoundsInfo.ub], bayestopt_.name, bayestopt_, [],... + data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); if options_mom_.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) + 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_,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)); + fprintf('\n''verbose'' option: '); + std_via_invhessian_xparam1_iter = NaN(size(xparam1)); + tbl_title_iter = sprintf('FREQUENTIST %s (STAGE %d ITERATION %d) VERBOSE',options_mom_.mom.mom_method,stage_iter,optim_iter); + field_name_iter = sprintf('%s_stage_%d_iter_%d',lower(options_mom_.mom.mom_method),stage_iter,optim_iter); + mom_verbose.(field_name_iter) = display_estimation_results_table(xparam1,std_via_invhessian_xparam1_iter,M_,options_mom_,estim_params_,bayestopt_,[],prior_dist_names,tbl_title_iter,field_name_iter); end xparam0 = xparam1; end options_mom_.vector_output = false; - [~, ~, ~,~,~, oo_] = feval(objective_function, xparam1, Bounds, oo_, estim_params_, M_, options_mom_); % get oo_.mom.model_moments for iterated GMM/SMM to compute optimal weighting matrix + [~, ~, ~, ~, ~, ~, model_moments] = feval(objective_function, xparam1, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); % get model_moments for iterated GMM/SMM to compute optimal weighting matrix end diff --git a/matlab/+mom/mode_compute_irf_matching.m b/matlab/+mom/mode_compute_irf_matching.m new file mode 100644 index 0000000000000000000000000000000000000000..d7673b1261e98556933a4f29eff217a0e8555dbf --- /dev/null +++ b/matlab/+mom/mode_compute_irf_matching.m @@ -0,0 +1,122 @@ +function [xparam1, hessian_xparam1, fval, mom_verbose] = mode_compute_irf_matching(xparam0, hessian_xparam0, objective_function, doBayesianEstimation, weighting_info, data_moments, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) +% [xparam1, hessian_xparam1, fval, mom_verbose] = mode_compute_irf_matching(xparam0, hessian_xparam0, objective_function, doBayesianEstimation, weighting_info, data_moments, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) +% ------------------------------------------------------------------------- +% Computes the minimum of the objective function (distance between data IRFs +% and model IRFs) for a sequence of optimizers. +% Note that we call a "mode" the minimum of the objective function, i.e. +% the parameter vector that minimizes the distance between the IRFs +% computed from the model and the IRFs computed from the data. +% ------------------------------------------------------------------------- +% INPUTS +% xparam0: [vector] initialized parameters +% hessian_xparam0: [matrix] initialized hessian at xparam0 +% objective_function: [func handle] name of the objective function +% doBayesianEstimation: [logical] true if Bayesian estimation +% weighting_info: [structure] information on weighting matrix +% data_moments: [vector] data moments +% options_mom_: [structure] options +% M_: [structure] model information +% estim_params_: [structure] information on estimated parameters +% bayestopt_: [structure] information on priors +% BoundsInfo: [structure] bounds for optimization +% dr: [structure] information reduced-form model +% endo_steady_state: [vector] steady state of endogenous variables (initval) +% exo_steady_state: [vector] steady state of exogenous variables (initval) +% exo_det_steady_state: [vector] steady state of deterministic exogenous variables (initval) +% ------------------------------------------------------------------------- +% OUTPUT +% xparam1: [vector] mode of objective function +% hessian_xparam1: [matrix] hessian at xparam1 +% fval: [double] function value at mode +% mom_verbose: [structure] information on intermediate estimation results +% Also saves the computed mode and hessian to a file. +% ------------------------------------------------------------------------- +% This function is called by +% o mom.run +% ------------------------------------------------------------------------- +% This function calls +% o display_estimation_results_table +% o dynare_minimize_objective +% o hessian +% o mom.objective_function +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + + +mom_verbose = []; +for optim_iter = 1:length(options_mom_.optimizer_vec) + options_mom_.current_optimizer = options_mom_.optimizer_vec{optim_iter}; + if options_mom_.optimizer_vec{optim_iter}==0 + % no minimization, evaluate objective at current values + xparam1 = xparam0; + hessian_xparam1 = hessian_xparam0; + fval = feval(objective_function, xparam1, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); + else + [xparam1, fval, exitflag, hessian_xparam1, options_mom_, Scale, new_rat_hess_info] = dynare_minimize_objective(objective_function, xparam0, options_mom_.optimizer_vec{optim_iter}, options_mom_, [BoundsInfo.lb BoundsInfo.ub], bayestopt_.name, bayestopt_, hessian_xparam0,... + data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); + end + fprintf('\nMode Compute Iteration %d: Value of minimized moment distance objective function: %12.10f.\n',optim_iter,fval); + if options_mom_.mom.verbose + fprintf('\n''verbose'' option: '); + if options_mom_.cova_compute + if options_mom_.optimizer_vec{optim_iter}==0 + hessian_xparam1_iter = hessian_xparam1; + else + fprintf('computing Hessian'); + hessian_xparam1_iter = hessian(objective_function, xparam1, options_mom_.gstep,... + data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); + hessian_xparam1_iter = reshape(hessian_xparam1_iter, length(xparam1), length(xparam1)); + end + hsd_iter = sqrt(diag(hessian_xparam1_iter)); + invhessian_xparam1_iter = inv(hessian_xparam1_iter./(hsd_iter*hsd_iter'))./(hsd_iter*hsd_iter'); + std_via_invhessian_xparam1_iter = sqrt(diag(invhessian_xparam1_iter)); + else + std_via_invhessian_xparam1_iter = NaN(size(xparam1)); + end + fprintf(' and displaying intermediate results.'); + if doBayesianEstimation + tbl_title_iter = sprintf('BAYESIAN %s (OPTIM ITERATION %d) VERBOSE',strrep(options_mom_.mom.mom_method,'_',' '),optim_iter); + field_name_iter = sprintf('posterior_iter_%d',optim_iter); + else + tbl_title_iter = sprintf('FREQUENTIST %s (OPTIM ITERATION %d) VERBOSE',strrep(options_mom_.mom.mom_method,'_',' '),optim_iter); + field_name_iter = sprintf('iter_%d',optim_iter); + end + mom_verbose.(field_name_iter) = display_estimation_results_table(xparam1,std_via_invhessian_xparam1_iter,M_,options_mom_,estim_params_,bayestopt_,[],prior_dist_names,tbl_title_iter,field_name_iter); + end + xparam0 = xparam1; + hessian_xparam0 = hessian_xparam1; +end + +if options_mom_.cova_compute + if options_mom_.mom.verbose + hessian_xparam1 = hessian_xparam1_iter; + else + fprintf('\nComputing Hessian at the mode.\n'); + hessian_xparam1 = hessian(objective_function, xparam1, options_mom_.gstep,... + data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); + hessian_xparam1 = reshape(hessian_xparam1, length(xparam1), length(xparam1)); + end +end +parameter_names = bayestopt_.name; +if options_mom_.cova_compute || options_mom_.mode_compute==5 || options_mom_.mode_compute==6 + hh = hessian_xparam1; + save([M_.dname filesep 'method_of_moments' filesep M_.fname '_mode.mat'],'xparam1','hh','parameter_names','fval'); +else + save([M_.dname filesep 'method_of_moments' filesep M_.fname '_mode.mat'],'xparam1','parameter_names','fval'); +end \ No newline at end of file diff --git a/matlab/+mom/objective_function.m b/matlab/+mom/objective_function.m index 4144673539dddd4212e8deb6b42b4e608bad7dce..98247f51cbc698c2c0823fffd88afc6542577c6f 100644 --- a/matlab/+mom/objective_function.m +++ b/matlab/+mom/objective_function.m @@ -1,27 +1,33 @@ -function [fval, info, exit_flag, df, junkHessian, oo_, M_] = objective_function(xparam, Bounds, oo_, estim_params_, M_, options_mom_) -% [fval, info, exit_flag, df, junk1, oo_, M_] = objective_function(xparam, Bounds, oo_, estim_params_, M_, options_mom_) +function [fval, info, exit_flag, df, junk_hessian, Q, model_moments, model_moments_params_derivs, irf_model_varobs] = objective_function(xparam, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) +% [fval, info, exit_flag, df, junk_hessian, Q, model_moments, model_moments_params_derivs, irf_model_varobs] = objective_function(xparam, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) % ------------------------------------------------------------------------- -% This function evaluates the objective function for method of moments estimation -% ========================================================================= -% INPUTS -% o xparam: [vector] current value of estimated parameters as returned by set_prior() -% o Bounds: [structure] containing parameter bounds -% o oo_: [structure] for results -% o estim_params_: [structure] describing the estimated_parameters -% o M_ [structure] describing the model -% o options_mom_: [structure] information about all settings (specified by the user, preprocessor, and taken from global options_) +% This function evaluates the objective function for method of moments estimation, +% i.e. distance between model and data moments/IRFs, possibly augmented with priors. +% ------------------------------------------------------------------------- +% INPUTS (same ones as in dsge_likelihood.m and dsge_var_likelihood.m) +% - xparam: [vector] current value of estimated parameters as returned by set_prior() +% - data_moments: [vector] data with moments/IRFs to match (corresponds to dataset_ in likelihood-based estimation) +% - weighting_info: [structure] storing information on weighting matrices (corresponds to dataset_info in likelihood-based estimation) +% - options_mom_: [structure] information about all settings (specified by the user, preprocessor, and taken from global options_) +% - M_ [structure] model information +% - estim_params_: [structure] information from estimated_params block +% - bayestopt_: [structure] information on the prior distributions +% - BoundsInfo: [structure] parameter bounds +% - dr: [structure] reduced form model +% - endo_steady_state: [vector] steady state value for endogenous variables (initval) +% - exo_steady_state: [vector] steady state value for exogenous variables (initval) +% - exo_det_steady_state: [vector] steady state value for exogenous deterministic variables (initval) % ------------------------------------------------------------------------- % OUTPUTS -% o fval: [double] value of the quadratic form of the moment difference (except for lsqnonlin, where this is done implicitly) -% o info: [vector] information on error codes and penalties -% o exit_flag: [double] flag for exit status (0 if error, 1 if no error) -% o df: [matrix] analytical jacobian of the moment difference (wrt paramters), currently for GMM only -% o junkHessian: [matrix] empty matrix required for optimizer interface (Hessian would typically go here) -% o oo_: [structure] results with the following updated fields: -% - oo_.mom.model_moments: [vector] model moments -% - oo_.mom.Q: [double] value of the quadratic form of the moment difference -% - oo_.mom.model_moments_params_derivs: [matrix] analytical jacobian of the model moments wrt estimated parameters (currently for GMM only) -% o M_: [structure] updated model structure +% - fval: [double] value of the quadratic form of the moment difference (except for lsqnonlin, where this is done implicitly) +% - info: [vector] information on error codes and penalties +% - exit_flag: [double] flag for exit status (0 if error, 1 if no error) +% - df: [matrix] analytical jacobian of the moment difference (wrt paramters), currently for GMM only +% - junk_hessian: [matrix] empty matrix required for optimizer interface (Hessian would typically go here) +% - Q: [double] value of the quadratic form of the moment difference +% - model_moments: [vector] model moments +% - model_moments_params_derivs: [matrix] analytical jacobian of the model moments wrt estimated parameters (currently for GMM only) +% - irf_model_varobs: [matrix] model IRFs for observable variables (used for plotting matched IRfs in mom.run) % ------------------------------------------------------------------------- % This function is called by % o mom.run @@ -29,13 +35,18 @@ function [fval, info, exit_flag, df, junkHessian, oo_, M_] = objective_function( % ------------------------------------------------------------------------- % This function calls % o check_bounds_and_definiteness_estimation +% o get_lower_cholesky_covariance % o get_perturbation_params_derivs +% o getIrfShocksIndx +% o irf % o mom.get_data_moments +% o priordens % o pruned_state_space_system % o resol % o set_all_parameters % o simult_ -% ========================================================================= +% ------------------------------------------------------------------------- + % Copyright © 2020-2023 Dynare Team % % This file is part of Dynare. @@ -52,28 +63,27 @@ function [fval, info, exit_flag, df, junkHessian, oo_, M_] = objective_function( % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ========================================================================= - -%% TO DO -% check the info values and make use of meaningful penalties -% how do we do the penalty for the prior?? %------------------------------------------------------------------------------ % Initialization of the returned variables and others... %------------------------------------------------------------------------------ -junkHessian = []; +irf_model_varobs = []; +model_moments_params_derivs = []; +model_moments = []; +Q = []; +junk_hessian = []; df = []; % required to be empty by e.g. newrat if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_jacobian if options_mom_.mom.vector_output == 1 if options_mom_.mom.penalized_estimator - df = nan(size(oo_.mom.data_moments,1)+length(xparam),length(xparam)); + df = NaN(options_mom_.mom.mom_nbr+length(xparam),length(xparam)); else - df = nan(size(oo_.mom.data_moments,1),length(xparam)); + df = NaN(options_mom_.mom.mom_nbr,length(xparam)); end else - df = nan(length(xparam),1); + df = NaN(length(xparam),1); end end end @@ -82,14 +92,13 @@ end %-------------------------------------------------------------------------- % Get the structural parameters and define penalties %-------------------------------------------------------------------------- - % Ensure that xparam1 is a column vector; particleswarm.m requires this. xparam = xparam(:); M_ = set_all_parameters(xparam, estim_params_, M_); -[fval,info,exit_flag] = check_bounds_and_definiteness_estimation(xparam, M_, estim_params_, Bounds); +[fval,info,exit_flag] = check_bounds_and_definiteness_estimation(xparam, M_, estim_params_, BoundsInfo); if info(1) if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output - fval = ones(size(oo_.mom.data_moments,1),1)*options_mom_.huge_number; + fval = ones(options_mom_.mom.mom_nbr,1)*options_mom_.huge_number; end return end @@ -98,9 +107,8 @@ end %-------------------------------------------------------------------------- % Call resol to compute steady state and model solution %-------------------------------------------------------------------------- - % Compute linear approximation around the deterministic steady state -[oo_.dr, info, M_.params] = resol(0, M_, options_mom_, oo_.dr ,oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); +[dr, info, M_.params] = resol(0, M_, options_mom_, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); % Return, with endogenous penalty when possible, if resol issues an error code if info(1) if info(1) == 3 || info(1) == 4 || info(1) == 5 || info(1)==6 ||info(1) == 19 ||... @@ -111,7 +119,7 @@ if info(1) info(4) = info(2); exit_flag = 0; if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output - fval = ones(size(oo_.mom.data_moments,1),1)*options_mom_.huge_number; + fval = ones(options_mom_.mom.mom_nbr,1)*options_mom_.huge_number; end return else @@ -119,7 +127,7 @@ if info(1) info(4) = 0.1; exit_flag = 0; if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output - fval = ones(size(oo_.mom.data_moments,1),1)*options_mom_.huge_number; + fval = ones(options_mom_.mom.mom_nbr,1)*options_mom_.huge_number; end return end @@ -144,44 +152,44 @@ if strcmp(options_mom_.mom.mom_method,'GMM') indpcorr = estim_params_.corrx(:,1:2); % values correspond to varexo declaration order, row number corresponds to order in estimated_params end if estim_params_.nvn || estim_params_.ncn % nvn is number of stderr parameters and ncn is number of corr parameters of measurement innovations as declared in estimated_params - error('Analytic computation of standard errrors does not (yet) support measurement errors.\nInstead, define them explicitly as varexo and provide measurement equations in the model definition.\nAlternatively, use numerical standard errors.') + error('Analytic computation of standard errrors does not (yet) support measurement errors.\nInstead, define them explicitly as varexo and provide measurement equations in the model definition.\nAlternatively, use numerical standard errors.'); end modparam_nbr = estim_params_.np; % number of model parameters as declared in estimated_params stderrparam_nbr = estim_params_.nvx; % number of stderr parameters corrparam_nbr = estim_params_.ncx; % number of corr parameters totparam_nbr = stderrparam_nbr+corrparam_nbr+modparam_nbr; - oo_.dr.derivs = identification.get_perturbation_params_derivs(M_, options_mom_, estim_params_, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state, indpmodel, indpstderr, indpcorr, 0); %analytic derivatives of perturbation matrices - oo_.mom.model_moments_params_derivs = NaN(options_mom_.mom.mom_nbr,totparam_nbr); - pruned_state_space = pruned_SS.pruned_state_space_system(M_, options_mom_, oo_.dr, oo_.mom.obs_var, options_mom_.ar, 0, 1); + dr.derivs = identification.get_perturbation_params_derivs(M_, options_mom_, estim_params_, dr, endo_steady_state, exo_steady_state, exo_det_steady_state, indpmodel, indpstderr, indpcorr, 0); %analytic derivatives of perturbation matrices + model_moments_params_derivs = NaN(options_mom_.mom.mom_nbr,totparam_nbr); + pruned_state_space = pruned_SS.pruned_state_space_system(M_, options_mom_, dr, options_mom_.mom.obs_var, options_mom_.ar, 0, 1); else - pruned_state_space = pruned_SS.pruned_state_space_system(M_, options_mom_, oo_.dr, oo_.mom.obs_var, options_mom_.ar, 0, 0); + pruned_state_space = pruned_SS.pruned_state_space_system(M_, options_mom_, dr, options_mom_.mom.obs_var, options_mom_.ar, 0, 0); end - oo_.mom.model_moments = NaN(options_mom_.mom.mom_nbr,1); + model_moments = NaN(options_mom_.mom.mom_nbr,1); for jm = 1:size(M_.matched_moments,1) % First moments if ~options_mom_.prefilter && (sum(M_.matched_moments{jm,3}) == 1) - idx1 = (oo_.mom.obs_var == find(oo_.dr.order_var==M_.matched_moments{jm,1}) ); - oo_.mom.model_moments(jm,1) = pruned_state_space.E_y(idx1); + idx1 = (options_mom_.mom.obs_var == find(dr.order_var==M_.matched_moments{jm,1}) ); + model_moments(jm,1) = pruned_state_space.E_y(idx1); if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) - oo_.mom.model_moments_params_derivs(jm,:) = pruned_state_space.dE_y(idx1,:); + model_moments_params_derivs(jm,:) = pruned_state_space.dE_y(idx1,:); end end % second moments if (sum(M_.matched_moments{jm,3}) == 2) - idx1 = (oo_.mom.obs_var == find(oo_.dr.order_var==M_.matched_moments{jm,1}(1)) ); - idx2 = (oo_.mom.obs_var == find(oo_.dr.order_var==M_.matched_moments{jm,1}(2)) ); + idx1 = (options_mom_.mom.obs_var == find(dr.order_var==M_.matched_moments{jm,1}(1)) ); + idx2 = (options_mom_.mom.obs_var == find(dr.order_var==M_.matched_moments{jm,1}(2)) ); if nnz(M_.matched_moments{jm,2}) == 0 % covariance if options_mom_.prefilter - oo_.mom.model_moments(jm,1) = pruned_state_space.Var_y(idx1,idx2); + model_moments(jm,1) = pruned_state_space.Var_y(idx1,idx2); if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) - oo_.mom.model_moments_params_derivs(jm,:) = pruned_state_space.dVar_y(idx1,idx2,:); + model_moments_params_derivs(jm,:) = pruned_state_space.dVar_y(idx1,idx2,:); end else - oo_.mom.model_moments(jm,1) = pruned_state_space.Var_y(idx1,idx2) + pruned_state_space.E_y(idx1)*pruned_state_space.E_y(idx2)'; + model_moments(jm,1) = pruned_state_space.Var_y(idx1,idx2) + pruned_state_space.E_y(idx1)*pruned_state_space.E_y(idx2)'; if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) for jp=1:totparam_nbr - oo_.mom.model_moments_params_derivs(jm,jp) = pruned_state_space.dVar_y(idx1,idx2,jp) + pruned_state_space.dE_y(idx1,jp)*pruned_state_space.E_y(idx2)' + pruned_state_space.E_y(idx1)*pruned_state_space.dE_y(idx2,jp)'; + model_moments_params_derivs(jm,jp) = pruned_state_space.dVar_y(idx1,idx2,jp) + pruned_state_space.dE_y(idx1,jp)*pruned_state_space.E_y(idx2)' + pruned_state_space.E_y(idx1)*pruned_state_space.dE_y(idx2,jp)'; end end end @@ -189,15 +197,15 @@ if strcmp(options_mom_.mom.mom_method,'GMM') % autocovariance lag = -M_.matched_moments{jm,2}(2); %note that leads/lags in M_.matched_moments are transformed such that first entry is always 0 and the second is a lag if options_mom_.prefilter - oo_.mom.model_moments(jm,1) = pruned_state_space.Var_yi(idx1,idx2,lag); + model_moments(jm,1) = pruned_state_space.Var_yi(idx1,idx2,lag); if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) - oo_.mom.model_moments_params_derivs(jm,:) = pruned_state_space.dVar_yi(idx1,idx2,lag,:); + model_moments_params_derivs(jm,:) = pruned_state_space.dVar_yi(idx1,idx2,lag,:); end else - oo_.mom.model_moments(jm,1) = pruned_state_space.Var_yi(idx1,idx2,lag) + pruned_state_space.E_y(idx1)*pruned_state_space.E_y(idx2)'; + model_moments(jm,1) = pruned_state_space.Var_yi(idx1,idx2,lag) + pruned_state_space.E_y(idx1)*pruned_state_space.E_y(idx2)'; if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) for jp=1:totparam_nbr - oo_.mom.model_moments_params_derivs(jm,jp) = vec( pruned_state_space.dVar_yi(idx1,idx2,lag,jp) + pruned_state_space.dE_y(idx1,jp)*pruned_state_space.E_y(idx2)' + pruned_state_space.E_y(idx1)*pruned_state_space.dE_y(idx2,jp)'); + model_moments_params_derivs(jm,jp) = vec( pruned_state_space.dVar_yi(idx1,idx2,lag,jp) + pruned_state_space.dE_y(idx1,jp)*pruned_state_space.E_y(idx2)' + pruned_state_space.E_y(idx1)*pruned_state_space.dE_y(idx2,jp)'); end end end @@ -217,24 +225,20 @@ if strcmp(options_mom_.mom.mom_method,'SMM') scaled_shock_series = zeros(size(options_mom_.mom.shock_series)); % initialize scaled_shock_series(:,i_exo_var) = options_mom_.mom.shock_series(:,i_exo_var)*chol_S; % set non-zero entries % simulate series - y_sim = simult_(M_, options_mom_, oo_.dr.ys, oo_.dr, scaled_shock_series, options_mom_.order); - % provide meaningful penalty if data is nan or inf + y_sim = simult_(M_, options_mom_, dr.ys, dr, scaled_shock_series, options_mom_.order); + % provide meaningful penalty if data is NaN or Inf if any(any(isnan(y_sim))) || any(any(isinf(y_sim))) - if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output - fval = Inf(size(oo_.mom.Sw,1),1); - else - fval = Inf; - end info(1)=180; info(4) = 0.1; exit_flag = 0; + fval = Inf; if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output - fval = ones(size(oo_.mom.data_moments,1),1)*options_mom_.huge_number; + fval = ones(options_mom_.mom.mom_nbr,1)*options_mom_.huge_number; end return end % remove burn-in and focus on observables (note that y_sim is in declaration order) - y_sim = y_sim(oo_.dr.order_var(oo_.mom.obs_var) , end-options_mom_.mom.long+1:end)'; + y_sim = y_sim(dr.order_var(options_mom_.mom.obs_var) , end-options_mom_.mom.long+1:end)'; if ~all(diag(M_.H)==0) i_ME = setdiff(1:size(M_.H,1),find(diag(M_.H) == 0)); % find ME with 0 variance chol_S = chol(M_.H(i_ME,i_ME)); % decompose rest @@ -246,46 +250,119 @@ if strcmp(options_mom_.mom.mom_method,'SMM') if options_mom_.prefilter y_sim = bsxfun(@minus, y_sim, mean(y_sim,1)); end - oo_.mom.model_moments = mom.get_data_moments(y_sim, oo_.mom.obs_var, oo_.dr.inv_order_var, M_.matched_moments, options_mom_); + model_moments = mom.get_data_moments(y_sim, options_mom_.mom.obs_var, dr.inv_order_var, M_.matched_moments, options_mom_); +end + + +%------------------------------------------------------------------------------ +% IRF_MATCHING using STOCH_SIMUL: Compute IRFs given model solution and Cholesky +% decomposition on shock covariance matrix; this resembles the core codes in +% stoch_simul +%------------------------------------------------------------------------------ +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') && strcmp(options_mom_.mom.simulation_method,'STOCH_SIMUL') + cs = get_lower_cholesky_covariance(M_.Sigma_e,options_mom_.add_tiny_number_to_cholesky); + irf_shocks_indx = getIrfShocksIndx(M_, options_mom_); + model_irf = NaN(options_mom_.irf,M_.endo_nbr,M_.exo_nbr); + for i = irf_shocks_indx + if options_mom_.order>1 && options_mom_.relative_irf % normalize shock to 0.01 before IRF generation for GIRFs; multiply with 100 later + y_irf = irf(M_, options_mom_, dr, cs(:,i)./cs(i,i)/100, options_mom_.irf, options_mom_.drop, options_mom_.replic, options_mom_.order); + else % for linear model, rescaling is done later + y_irf = irf(M_, options_mom_, dr, cs(:,i), options_mom_.irf, options_mom_.drop, options_mom_.replic, options_mom_.order); + end + if any(any(isnan(y_irf))) && ~options_mom_.pruning && ~(options_mom_.order==1) + info(1) = 181; + info(4) = 0.1; + fval = Inf; + exit_flag = 0; + if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output + fval = ones(options_mom_.mom.mom_nbr,1)*options_mom_.huge_number; + end + message = get_error_message(info,options_mom_); + fprintf('\n%s\n info = %d for shock %s.\n', message, info(1), M_.exo_names{i}); + return + end + if options_mom_.relative_irf + if options_mom_.order==1 % multiply with 100 for backward compatibility + y_irf = 100*y_irf/cs(i,i); + end + end + model_irf(:,:,i) = transpose(y_irf); + end + % do transformations on model IRFs if irf_matching_file is provided + if ~isempty(options_mom_.mom.irf_matching_file.name) + [model_irf, check] = feval(str2func(options_mom_.mom.irf_matching_file.name), model_irf, M_, options_mom_, dr.ys); + if check + fval = Inf; + info(1) = 180; + info(4) = 0.1; + exit_flag = 0; + if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output + fval = ones(options_mom_.mom.mom_nbr,1)*options_mom_.huge_number; + end + return + end + end + irf_model_varobs = model_irf(:,options_mom_.varobs_id,:); % focus only on observables (this will be used later for plotting) + model_moments = irf_model_varobs(options_mom_.mom.irfIndex); % focus only on selected IRF periods end %-------------------------------------------------------------------------- % Compute quadratic target function %-------------------------------------------------------------------------- -moments_difference = oo_.mom.data_moments - oo_.mom.model_moments; +moments_difference = data_moments - model_moments; -if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') - residuals = sqrt(options_mom_.mom.weighting_matrix_scaling_factor)*oo_.mom.Sw*moments_difference; - oo_.mom.Q = residuals'*residuals; +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + Q = transpose(moments_difference)*weighting_info.W*moments_difference; + % log-likelihood + lnlik = options_mom_.mom.mom_nbr/2*log(1/2/pi) - 1/2*weighting_info.Winv_logdet - 1/2*Q; + if isinf(lnlik) + fval = Inf; info(1) = 50; info(4) = 0.1; exit_flag = 0; + return + end + if isnan(lnlik) + fval = Inf; info(1) = 45; info(4) = 0.1; exit_flag = 0; + return + end + if imag(lnlik)~=0 + fval = Inf; info(1) = 46; info(4) = 0.1; exit_flag = 0; + return + end + % add log prior if necessary + lnprior = priordens(xparam,bayestopt_.pshape,bayestopt_.p6,bayestopt_.p7,bayestopt_.p3,bayestopt_.p4); + fval = - (lnlik + lnprior); + +elseif strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') + residuals = sqrt(options_mom_.mom.weighting_matrix_scaling_factor)*weighting_info.Sw*moments_difference; + Q = residuals'*residuals; if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output fval = residuals; if options_mom_.mom.penalized_estimator - fval=[fval;(xparam-oo_.mom.prior.mean)./sqrt(diag(oo_.mom.prior.variance))]; + fval=[fval;(xparam-bayestopt_.p1)./bayestopt_.p2]; end else - fval = oo_.mom.Q; + fval = Q; if options_mom_.mom.penalized_estimator - fval=fval+(xparam-oo_.mom.prior.mean)'/oo_.mom.prior.variance*(xparam-oo_.mom.prior.mean); + fval=fval+(xparam-bayestopt_.p1)'/(diag(bayestopt_.p2.^2))*(xparam-bayestopt_.p1); end end if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_jacobian if options_mom_.mom.penalized_estimator - dxparam1 = eye(length(xparam)); + dxparam = eye(length(xparam)); end for jp=1:length(xparam) - dmoments_difference = - oo_.mom.model_moments_params_derivs(:,jp); - dresiduals = sqrt(options_mom_.mom.weighting_matrix_scaling_factor)*oo_.mom.Sw*dmoments_difference; + dmoments_difference = - model_moments_params_derivs(:,jp); + dresiduals = sqrt(options_mom_.mom.weighting_matrix_scaling_factor)*weighting_info.Sw*dmoments_difference; if options_mom_.mom.vector_output == 1 % lsqnonlin requires vector output if options_mom_.mom.penalized_estimator - df(:,jp)=[dresiduals;dxparam1(:,jp)./sqrt(diag(oo_.mom.prior.variance))]; + df(:,jp)=[dresiduals;dxparam(:,jp)./bayestopt_.p2]; else df(:,jp) = dresiduals; end else df(jp,1) = dresiduals'*residuals + residuals'*dresiduals; if options_mom_.mom.penalized_estimator - df(jp,1)=df(jp,1)+(dxparam1(:,jp))'/oo_.mom.prior.variance*(xparam-oo_.mom.prior.mean)+(xparam-oo_.mom.prior.mean)'/oo_.mom.prior.variance*(dxparam1(:,jp)); + df(jp,1)=df(jp,1)+(dxparam(:,jp))'/(diag(bayestopt_.p2.^2))*(xparam-bayestopt_.p1)+(xparam-bayestopt_.p1)'/(diag(bayestopt_.p2.^2))*(dxparam(:,jp)); end end end @@ -293,5 +370,4 @@ if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_meth end -end % main function end - +end % main function end \ No newline at end of file diff --git a/matlab/+mom/optimal_weighting_matrix.m b/matlab/+mom/optimal_weighting_matrix.m index c09e56fd37789831a79a1654ba71dc907be54c29..271983c48c4958c5c2f7d4325049ff0031569521 100644 --- a/matlab/+mom/optimal_weighting_matrix.m +++ b/matlab/+mom/optimal_weighting_matrix.m @@ -2,9 +2,10 @@ function W_opt = optimal_weighting_matrix(m_data, moments, q_lag) % W_opt = optimal_weighting_matrix(m_data, moments, q_lag) % ------------------------------------------------------------------------- % This function computes the optimal weigthing matrix by a Bartlett kernel with maximum lag q_lag -% 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. -% ========================================================================= +% Adapted from replication codes 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. +% ------------------------------------------------------------------------- % INPUTS % o m_data [T x numMom] selected data moments at each point in time % o moments [numMom x 1] selected estimated moments (either data_moments or estimated model_moments) @@ -17,9 +18,10 @@ function W_opt = optimal_weighting_matrix(m_data, moments, q_lag) % o mom.run.m % ------------------------------------------------------------------------- % This function calls: -% o CorrMatrix (embedded) -% ========================================================================= -% Copyright © 2020-2021 Dynare Team +% o corr_matrix (embedded) +% ------------------------------------------------------------------------- + +% Copyright © 2020-2023 Dynare Team % % This file is part of Dynare. % @@ -35,46 +37,42 @@ function W_opt = optimal_weighting_matrix(m_data, moments, q_lag) % % 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 (johannes.pfeifer@unibw.de) -% ========================================================================= -% Initialize -[T,num_Mom] = size(m_data); %note that in m_data NaN values (due to leads or lags in matched_moments and missing data) were replaced by the mean + +% initialize +[T,num_Mom] = size(m_data); % note that in m_data NaN values (due to leads or lags in matched_moments and missing data) were replaced by the mean % center around moments (could be either data_moments or model_moments) -h_Func = m_data - repmat(moments',T,1); +h_func = m_data - repmat(moments',T,1); -% The required correlation matrices -GAMA_array = zeros(num_Mom,num_Mom,q_lag); -GAMA0 = Corr_Matrix(h_Func,T,num_Mom,0); +% the required correlation matrices +gamma_array = zeros(num_Mom,num_Mom,q_lag); +gamma0 = corr_matrix(h_func,T,num_Mom,0); if q_lag > 0 for ii=1:q_lag - GAMA_array(:,:,ii) = Corr_Matrix(h_Func,T,num_Mom,ii); + gamma_array(:,:,ii) = corr_matrix(h_func,T,num_Mom,ii); end end -% The estimate of S -S = GAMA0; +% the estimate of S +S = gamma0; if q_lag > 0 for ii=1:q_lag - S = S + (1-ii/(q_lag+1))*(GAMA_array(:,:,ii) + GAMA_array(:,:,ii)'); + S = S + (1-ii/(q_lag+1))*(gamma_array(:,:,ii) + gamma_array(:,:,ii)'); end end -% The estimate of W +% the estimate of W W_opt = S\eye(size(S,1)); -W_opt=(W_opt+W_opt')/2; %assure symmetry -end +W_opt = (W_opt+W_opt')/2; % ensure symmetry +end % main function end % The correlation matrix -function GAMA_corr = Corr_Matrix(h_Func,T,num_Mom,v) - GAMA_corr = zeros(num_Mom,num_Mom); +function gamma_corr = corr_matrix(h_func,T,num_Mom,v) + gamma_corr = zeros(num_Mom,num_Mom); for t = 1+v:T - GAMA_corr = GAMA_corr + h_Func(t-v,:)'*h_Func(t,:); + gamma_corr = gamma_corr + h_func(t-v,:)'*h_func(t,:); end - GAMA_corr = GAMA_corr/T; -end + gamma_corr = gamma_corr/T; +end % corr_matrix end \ No newline at end of file diff --git a/matlab/+mom/print_info_on_estimation_settings.m b/matlab/+mom/print_info_on_estimation_settings.m index 45dfe832a551db8189f5b3fe7082b742a5a6e57d..4085f1e0f1344f1b55aff9fe18ef7071b451d583 100644 --- a/matlab/+mom/print_info_on_estimation_settings.m +++ b/matlab/+mom/print_info_on_estimation_settings.m @@ -1,11 +1,12 @@ -function print_info_on_estimation_settings(options_mom_, number_of_estimated_parameters) -% function print_info_on_estimation_settings(options_mom_, number_of_estimated_parameters) +function print_info_on_estimation_settings(options_mom_, number_of_estimated_parameters, do_bayesian_estimation) +% print_info_on_estimation_settings(options_mom_, number_of_estimated_parameters, do_bayesian_estimation) % ------------------------------------------------------------------------- % Print information on the method of moments estimation settings to the console -% ========================================================================= +% ------------------------------------------------------------------------- % INPUTS -% options_mom_ [struct] Options for the method of moments estimation -% number_of_estimated_parameters [integer] Number of estimated parameters +% options_mom_ [struct] options for the method of moments estimation +% number_of_estimated_parameters [integer] number of estimated parameters +% do_bayesian_estimation [boolean] true if the estimation is Bayesian % ------------------------------------------------------------------------- % OUTPUT % No output, just displays the chosen settings @@ -15,7 +16,8 @@ function print_info_on_estimation_settings(options_mom_, number_of_estimated_par % ------------------------------------------------------------------------- % This function calls % o skipline -% ========================================================================= +% ------------------------------------------------------------------------- + % Copyright © 2023 Dynare Team % % This file is part of Dynare. @@ -32,7 +34,8 @@ function print_info_on_estimation_settings(options_mom_, number_of_estimated_par % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ========================================================================= + + fprintf('\n---------------------------------------------------\n') if strcmp(options_mom_.mom.mom_method,'SMM') fprintf('Simulated method of moments with'); @@ -49,7 +52,16 @@ if strcmp(options_mom_.mom.mom_method,'SMM') || strcmp(options_mom_.mom.mom_meth fprintf('\n - penalized estimation using deviation from prior mean and weighted with prior precision'); end end - +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + if do_bayesian_estimation + fprintf('Bayesian Impulse Response Function Matching with'); + else + fprintf('Frequentist Impulse Response Function Matching with'); + end + if ~isempty(options_mom_.mom.irf_matching_file.name) + fprintf('\n - irf_matching_file: %s',[options_mom_.mom.irf_matching_file.path filesep options_mom_.mom.irf_matching_file.name '.m']); + end +end for i = 1:length(options_mom_.optimizer_vec) if i == 1 str = '- optimizer (mode_compute'; @@ -118,6 +130,8 @@ if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_meth fprintf('\n - standard errors: numerical derivatives'); end fprintf('\n - number of matched moments: %d', options_mom_.mom.mom_nbr); +elseif strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + fprintf('\n - number of matched IRFs: %d', options_mom_.mom.mom_nbr); end fprintf('\n - number of parameters: %d', number_of_estimated_parameters); fprintf('\n\n'); \ No newline at end of file diff --git a/matlab/+mom/run.m b/matlab/+mom/run.m index b5579aeb49ce6bb483a50334113b0c7e86ff9a5b..19b1a6206b58320160e526827ded402633237334 100644 --- a/matlab/+mom/run.m +++ b/matlab/+mom/run.m @@ -6,31 +6,47 @@ function [oo_, options_mom_, M_] = run(bayestopt_, options_, oo_, estim_params_, % o Preparing local options_mom_ structure % o Checking the options and the compatibility of the settings % o Initializations of variables, orderings and state space representation -% o Checks and transformations for matched moments structure +% o Checks and transformations for matched_moments structure +% o Checks and transformations for matched_irfs and matched_irfs_weights structure % o Checks and transformations for estimated parameters, priors, and bounds % o Checks and transformations for data % o Checks for objective function at initial parameters -% o GMM/SMM: iterated method of moments estimation -% o GMM/SMM: J-Test and fit of moments% +% o Mode computation: optimization +% - GMM/SMM: iterated optimization +% - IRF_MATCHING: optimization +% o Bayesian MCMC estimation % o Display of results +% - GMM/SMM: J-Test and fit of moments +% - IRF_MATCHING: fit of IRFs % o Clean up % ------------------------------------------------------------------------- +% Note that we call a "mode" the minimum of the objective function, i.e. +% the parameter vector that minimizes the distance between the moments/IRFs +% computed from the model and the moments/IRFs computed from the data. +% ------------------------------------------------------------------------- % This function is inspired by replication codes accompanied to the following papers: % GMM/SMM: % 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. -% ========================================================================= +% o Ruge-Murcia (2007): "Methods to Estimate Dynamic Stochastic General Equilibrium Models", Journal of Economic Dynamics and Control, 31(8):2599-2636. +% IRF MATCHING: +% o Christiano, Trabandt, Walentin (2010): "DSGE Models for Monetary Policy Analysis." In Handbook of Monetary Economics, 3:285–367. +% o Christiano, Eichenbaum, Trabandt (2016): "Unemployment and Business Cycles." Econometrica, 84: 1523-1569. +% o Ruge-Murcia (2020): "Estimating Nonlinear Dynamic Equilibrium Models by Matching Impulse Responses", Economics Letters, 197. +% ------------------------------------------------------------------------- % INPUTS % o bayestopt_: [structure] information about priors % o options_: [structure] information about global options -% o oo_: [structure] storage for results +% o oo_: [structure] 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 GMM/SMM estimation % vars: matched_moments{:,1}); % lead/lags: matched_moments{:,2}; % powers: matched_moments{:,3}; +% o matched_irfs: [cell] information about selected IRFs to match in IRF_MATCHING estimation +% o matched_irfs_weights: [cell] information about entries in weight matrix for an IRF_MATCHING estimation % o options_mom_: [structure] information about settings specified by the user % ------------------------------------------------------------------------- % OUTPUTS @@ -42,25 +58,26 @@ function [oo_, options_mom_, M_] = run(bayestopt_, options_, oo_, estim_params_, % o driver.m % ------------------------------------------------------------------------- % This function calls -% o cellofchararraymaxlength % o check_for_calibrated_covariances +% o check_mode_file +% o check_posterior_sampler_options % o check_prior_bounds % o check_prior_stderr_corr % o check_steady_state_changes_parameters % o check_varobs_are_endo_and_declared_once +% o check_hessian_at_the_mode % o display_estimation_results_table % o do_parameter_initialization -% o dyn_latex_table -% o dynare_minimize_objective -% o dyntable % o get_all_parameters % o get_dynare_random_generator_state % o get_matrix_entries_for_psd_check % o M_.fname '_prior_restrictions' % o makedataset -% o mom.check_plot +% o mode_check +% o mom.check_irf_matching_file % o mom.default_option_mom_values % o mom.get_data_moments +% o mom.matched_irfs_blocks % o mom.matched_moments_block % o mom.objective_function % o mom.optimal_weighting_matrix @@ -77,8 +94,9 @@ function [oo_, options_mom_, M_] = run(bayestopt_, options_, oo_, estim_params_, % o set_state_space % o skipline % o test_for_deep_parameters_calibration +% o transform_prior_to_laplace_prior % o warning_config -% ========================================================================= + % Copyright © 2020-2023 Dynare Team % % This file is part of Dynare. @@ -95,34 +113,8 @@ function [oo_, options_mom_, M_] = run(bayestopt_, options_, oo_, estim_params_, % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ------------------------------------------------------------------------- -% Maintaining Author(s): -% o Willi Mutschler (willi@mutschler.eu) -% o Johannes Pfeifer (johannes.pfeifer@unibw.de) -% ========================================================================= -% ------------------------------------------------------------------------- -% TO DO LISTS -% ------------------------------------------------------------------------- -% GENERAL -% - document all options in manual -% - document analytic_jacobian better -% - make endogenous_prior_restrictions work -% - dirname option to save output to different directory not yet implemented -% - create test for prior restrictions file -% - add mode_file option -% - implement penalty objective -% - test optimizers -% GMM/SMM -% - 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) -% - display scaled moments -% - enable first moments despite prefilter -% - do "true" Bayesian GMM and SMM not only penalized - -fprintf('\n==== Method of Moments Estimation (%s) ====\n\n',options_mom_.mom.mom_method) +fprintf('\n==== Method of Moments Estimation (%s) ====\n\n',options_mom_.mom.mom_method); % ------------------------------------------------------------------------- @@ -130,29 +122,33 @@ fprintf('\n==== Method of Moments Estimation (%s) ====\n\n',options_mom_.mom.mom % ------------------------------------------------------------------------- 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!') + 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!') + error('method_of_moments: The ''estimated_params'' block must not be empty!'); end end if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') if ~isfield(M_,'matched_moments') || isempty(M_.matched_moments) % structure storing the moments used for GMM and SMM estimation - error('method_of_moments: You need to provide a ''matched_moments'' block for ''mom_method=%s''!',options_mom_.mom.mom_method) + error('method_of_moments: You need to provide a ''matched_moments'' block for ''mom_method=%s''!',options_mom_.mom.mom_method); + end +elseif strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + if ~isfield(M_,'matched_irfs') || isempty(M_.matched_irfs) % structure storing the irfs used for matching + error('method_of_moments: You need to provide a ''matched_irfs'' block for ''mom_method=%s''!',options_mom_.mom.mom_method); end end if (~isempty(estim_params_.var_endo) || ~isempty(estim_params_.corrn)) && strcmp(options_mom_.mom.mom_method, 'GMM') - error('method_of_moments: GMM estimation does not support measurement error(s) yet. Please specify them as a structural shock!') + error('method_of_moments: GMM estimation does not support measurement error(s) yet. Please specify them as a structural shock!'); end -doBayesianEstimation = [estim_params_.var_exo(:,5); estim_params_.var_endo(:,5); estim_params_.corrx(:,6); estim_params_.corrn(:,6); estim_params_.param_vals(:,5)]; -if all(doBayesianEstimation~=0) - doBayesianEstimation = true; -elseif all(doBayesianEstimation==0) - doBayesianEstimation = false; +do_bayesian_estimation = [estim_params_.var_exo(:,5); estim_params_.var_endo(:,5); estim_params_.corrx(:,6); estim_params_.corrn(:,6); estim_params_.param_vals(:,5)]; +if all(do_bayesian_estimation~=0) + do_bayesian_estimation = true; +elseif all(do_bayesian_estimation==0) + do_bayesian_estimation = false; else - error('method_of_moments: Estimation must be either fully Frequentist or fully Bayesian. Maybe you forgot to specify a prior distribution!') + error('method_of_moments: Estimation must be either fully Frequentist or fully Bayesian. Maybe you forgot to specify a prior distribution!'); end if ~isfield(options_,'varobs') - error('method_of_moments: VAROBS statement is missing!') + error('method_of_moments: VAROBS statement is missing!'); end check_varobs_are_endo_and_declared_once(options_.varobs,M_.endo_names); @@ -166,7 +162,7 @@ check_varobs_are_endo_and_declared_once(options_.varobs,M_.endo_names); % 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. -options_mom_ = mom.default_option_mom_values(options_mom_, options_, M_.dname, doBayesianEstimation); +options_mom_ = mom.default_option_mom_values(options_mom_, options_, M_.dname, do_bayesian_estimation); % ------------------------------------------------------------------------- @@ -183,60 +179,27 @@ if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_meth end -% ------------------------------------------------------------------------- -% checks on settings -% ------------------------------------------------------------------------- -if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') - 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 -end -if options_mom_.order < 1 - error('method_of_moments: The order of the Taylor approximation cannot be 0!') -end -if options_mom_.order > 2 - fprintf('Dynare will use ''k_order_solver'' as the order>2\n'); - options_mom_.k_order_solver = true; -end -if strcmp(options_mom_.mom.mom_method,'SMM') - if options_mom_.mom.simulation_multiple < 1 - fprintf('The simulation horizon is shorter than the data. Dynare resets the simulation_multiple to 7.\n') - options_mom_.mom.simulation_multiple = 7; - end -end -if strcmp(options_mom_.mom.mom_method,'GMM') - % require 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!'); - end -end -if options_mom_.mom.analytic_jacobian && ~strcmp(options_mom_.mom.mom_method,'GMM') - options_mom_.mom.analytic_jacobian = false; - fprintf('\n''analytic_jacobian'' option will be dismissed as it only works with GMM.\n'); -end - - % ------------------------------------------------------------------------- % initializations % ------------------------------------------------------------------------- % create output directories to store results +M_.dname = options_mom_.dirname; +CheckPath(M_.dname,'.'); CheckPath('method_of_moments',M_.dname); -CheckPath('graphs',options_mom_.dirname); -% initialize options that might change -options_mom_.mom.compute_derivs = false; % flag to compute derivs in objective function (might change for GMM with either analytic_standard_errors or analytic_jacobian (dependent on optimizer)) -options_mom_.mom.vector_output = false; % specifies whether the objective function returns a vector +CheckPath('graphs',M_.dname); + +if do_bayesian_estimation + oo_.mom.posterior.optimization.mode = []; + oo_.mom.posterior.optimization.Variance = []; + oo_.mom.posterior.optimization.log_density=[]; +end +do_bayesian_estimation_mcmc = do_bayesian_estimation && ( (options_mom_.mh_replic>0) || options_mom_.load_mh_file ); +invhess = []; % decision rule oo_.dr = set_state_space(oo_.dr,M_); % get state-space representation -oo_.mom.obs_var = []; % create index of observed variables in DR order +options_mom_.mom.obs_var = []; % create index of observed variables in DR order for i = 1:options_mom_.obs_nbr - oo_.mom.obs_var = [oo_.mom.obs_var; find(strcmp(options_mom_.varobs{i}, M_.endo_names(oo_.dr.order_var)))]; + options_mom_.mom.obs_var = [options_mom_.mom.obs_var; find(strcmp(options_mom_.varobs{i}, M_.endo_names(oo_.dr.order_var)))]; end @@ -255,37 +218,76 @@ if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_meth % 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_.mom.obs_var); + not_observed_variables=setdiff(oo_.dr.inv_order_var([M_.matched_moments{:,1}]),options_mom_.mom.obs_var); if ~isempty(not_observed_variables) skipline; - error('method_of_moments: You specified moments involving %s, but it is not a varobs!',M_.endo_names{oo_.dr.order_var(not_observed_variables)}) + error('method_of_moments: You specified moments involving %s, but it is not a varobs!',M_.endo_names{oo_.dr.order_var(not_observed_variables)}); + end +end + + +% ------------------------------------------------------------------------- +% matched_irfs: checks and transformations +% ------------------------------------------------------------------------- +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + [oo_.mom.data_moments, oo_.mom.weighting_info.W, options_mom_.mom.irfIndex, options_mom_.irf] = mom.matched_irfs_blocks(M_.matched_irfs, M_.matched_irfs_weights, options_mom_.varobs_id, options_mom_.obs_nbr, M_.exo_nbr, M_.endo_names, M_.exo_names); + % compute inverse of weighting matrix + try + oo_.mom.weighting_info.Winv = inv(oo_.mom.weighting_info.W); + catch + error('method_of_moments: Something wrong while computing inv(W), check your weighting matrix!'); + end + if any(isnan(oo_.mom.weighting_info.Winv(:))) || any(isinf(oo_.mom.weighting_info.Winv(:))) + error('method_of_moments: There are NaN or Inf values in inv(W), check your weighting matrix!'); + end + % compute log determinant of inverse of weighting matrix in a robust way to avoid Inf or NaN + try + oo_.mom.weighting_info.Winv_logdet = 2*sum(log(diag(chol(oo_.mom.weighting_info.Winv)))); + catch + error('method_of_moments: Something wrong while computing log(det(inv(W))), check your weighting matrix!'); + end + if any(isnan(oo_.mom.weighting_info.Winv_logdet(:))) || any(isinf(oo_.mom.weighting_info.Winv_logdet(:))) + error('method_of_moments: There are NaN or Inf values in log(det(inv(W))), check your weighting matrix!'); end + options_mom_.mom.mom_nbr = length(options_mom_.mom.irfIndex); end % ------------------------------------------------------------------------- -% estimated parameters: checks and transformations on values, priors, bounds +% irf_matching_file: checks and transformations +% ------------------------------------------------------------------------- +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + [options_mom_.mom.irf_matching_file.name, options_mom_.mom.irf_matching_file.path] = mom.check_irf_matching_file(options_mom_.mom.irf_matching_file.name); + % check for irf_matching_file + if ~( isempty(options_mom_.mom.irf_matching_file.path) || strcmp(options_mom_.mom.irf_matching_file.path,'.') ) + fprintf('\nAdding %s to MATLAB''s path.\n',options_mom_.mom.irf_matching_file.path); + addpath(options_mom_.mom.irf_matching_file.path); + end +end + + +% ------------------------------------------------------------------------- +% estimated parameters: checks and transformations on values, priors, bounds, posterior options % ------------------------------------------------------------------------- % set priors and bounds over the estimated parameters [xparam0, estim_params_, bayestopt_, lb, ub, M_] = set_prior(estim_params_, M_, options_mom_); number_of_estimated_parameters = length(xparam0); hessian_xparam0 = []; % initialize hessian - % check if enough moments for estimation -if strcmp(options_mom_.mom.mom_method, 'GMM') || strcmp(options_mom_.mom.mom_method, 'SMM') - if options_mom_.mom.mom_nbr < length(xparam0) - skipline; - error('method_of_moments: There must be at least as many moments as parameters for a %s estimation!',options_mom_.mom.mom_method); - end - skipline(2); +if options_mom_.mom.mom_nbr < length(xparam0) + skipline; + error('method_of_moments: There must be at least as many moments as parameters for a %s estimation!',options_mom_.mom.mom_method); end - +skipline(2); % 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 - +% check that the provided mode_file is compatible with the current estimation settings +if ~isempty(options_mom_.mode_file) && ( ~do_bayesian_estimation || (do_bayesian_estimation && ~options_mom_.mh_posterior_mode_estimation) ) + [xparam0, hessian_xparam0] = check_mode_file(xparam0, hessian_xparam0, options_mom_, bayestopt_); +end % check on specified priors and penalized estimation (which uses Laplace approximated priors) if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') bayestopt_orig = bayestopt_; @@ -298,7 +300,6 @@ if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_meth bayestopt_ = mom.transform_prior_to_laplace_prior(bayestopt_); end end - % check for calibrated covariances before updating parameters estim_params_ = check_for_calibrated_covariances(estim_params_,M_); @@ -310,89 +311,104 @@ else estim_params_.full_calibration_detected = false; end if options_mom_.use_calibration_initialization % set calibration as starting values - if ~isempty(bayestopt_) && ~doBayesianEstimation && any(all(isnan([xparam_calib xparam0]),2)) + if ~isempty(bayestopt_) && ~do_bayesian_estimation && any(all(isnan([xparam_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_,xparam_calib,xparam0); % get explicitly initialized parameters that have precedence over calibrated values end end - % check initialization -if ~isempty(bayestopt_) && ~doBayesianEstimation && any(isnan(xparam0)) +if ~isempty(bayestopt_) && ~do_bayesian_estimation && any(isnan(xparam0)) error('method_of_moments: Frequentist %s 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_) && doBayesianEstimation +if ~isempty(bayestopt_) && do_bayesian_estimation % plot prior densities if ~options_mom_.nograph && options_mom_.plot_priors if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') plot_priors(bayestopt_orig,M_,estim_params_,options_mom_,'Original priors'); % only for visual inspection (not saved to disk, because overwritten in next call to plot_priors) plot_priors(bayestopt_,M_,estim_params_,options_mom_,'Laplace approximated priors'); clear('bayestopt_orig'); % make sure stale structure cannot be used + else + plot_priors(bayestopt_,M_,estim_params_,options_mom_,'Priors'); end end % set prior bounds - Bounds = prior_bounds(bayestopt_, options_mom_.prior_trunc); - Bounds.lb = max(Bounds.lb,lb); - Bounds.ub = min(Bounds.ub,ub); + BoundsInfo = prior_bounds(bayestopt_, options_mom_.prior_trunc); + BoundsInfo.lb = max(BoundsInfo.lb,lb); + BoundsInfo.ub = min(BoundsInfo.ub,ub); else - % no priors are declared so Dynare will estimate the parameters with - % Frequentist methods using 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') + % no priors are declared so Dynare will estimate the parameters with Frequentist methods using inequality constraints for the parameters + BoundsInfo.lb = lb; + BoundsInfo.ub = ub; + if (strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM')) && options_mom_.mom.penalized_estimator + fprintf('Penalized estimation turned off as you did not declare priors\n'); options_mom_.mom.penalized_estimator = 0; + else + if isfield(options_mom_,'mh_replic') && options_mom_.mh_replic > 0 + fprintf('Setting ''mh_replic=0'' as you did not declare priors.\n'); + options_mom_.mh_replic = 0; + end end end % set correct bounds for standard deviations and correlations -Bounds = mom.set_correct_bounds_for_stderr_corr(estim_params_,Bounds); - +BoundsInfo = mom.set_correct_bounds_for_stderr_corr(estim_params_,BoundsInfo); % 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_); + check_prior_bounds(xparam0,BoundsInfo,M_,estim_params_,options_mom_,bayestopt_); catch last_error - fprintf('Cannot use parameter values from calibration as they violate the prior bounds.') + 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_); + check_prior_bounds(xparam0,BoundsInfo,M_,estim_params_,options_mom_,bayestopt_); end - % check for positive definiteness 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 results -oo_.mom.prior.mean = bayestopt_.p1; -oo_.mom.prior.mode = bayestopt_.p5; -oo_.mom.prior.variance = diag(bayestopt_.p2.^2); -oo_.mom.prior.hyperparameters.first = bayestopt_.p6; -oo_.mom.prior.hyperparameters.second = bayestopt_.p7; - +% storing prior parameters in results structure +if do_bayesian_estimation || ( (strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM')) && options_mom_.mom.penalized_estimator) + oo_.mom.prior.mean = bayestopt_.p1; + oo_.mom.prior.mode = bayestopt_.p5; + oo_.mom.prior.variance = diag(bayestopt_.p2.^2); + oo_.mom.prior.hyperparameters.first = bayestopt_.p6; + oo_.mom.prior.hyperparameters.second = bayestopt_.p7; +end % 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_); - -if doBayesianEstimation - % warning if prior allows that stderr parameters are negative or corr parameters are outside the unit circle +% set jscale +if do_bayesian_estimation_mcmc + if ~strcmp(options_mom_.posterior_sampler_options.posterior_sampling_method,'slice') + if isempty(options_mom_.mh_jscale) + options_mom_.mh_jscale = 2.38/sqrt(number_of_estimated_parameters); % use optimal value for univariate normal distribution (check_posterior_sampler_options and mode_compute=6 may overwrite this setting) + end + bayestopt_.jscale(find(isnan(bayestopt_.jscale))) = options_mom_.mh_jscale; + end +end +% initialization of posterior sampler options +if do_bayesian_estimation_mcmc + [current_options, options_mom_, bayestopt_] = check_posterior_sampler_options([], M_.fname, M_.dname, options_mom_, BoundsInfo, bayestopt_); + options_mom_.posterior_sampler_options.current_options = current_options; + if strcmp(current_options.posterior_sampling_method,'slice') && current_options.use_mh_covariance_matrix && ~current_options.rotated + error('method_of_moments: Using the slice sampler with the ''use_mh_covariance_matrix'' option requires also setting the ''rotated'' option!'); + end +end +% warning if prior allows that stderr parameters are negative or corr parameters are outside the unit circle +if do_bayesian_estimation check_prior_stderr_corr(estim_params_,bayestopt_); - % check value of prior density - [~,~,~,info]= priordens(xparam0,bayestopt_.pshape,bayestopt_.p6,bayestopt_.p7,bayestopt_.p3,bayestopt_.p4); + [~,~,~,info] = priordens(xparam0,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!') + 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 end @@ -400,34 +416,34 @@ end % ------------------------------------------------------------------------- % datafile: checks and transformations % ------------------------------------------------------------------------- -% Build dataset +% build dataset if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') - % Check if datafile has same name as mod file + % check if datafile has same name as mod file [~,name] = fileparts(options_mom_.datafile); if strcmp(name,M_.fname) - error('method_of_moments: ''datafile'' and mod file are not allowed to have the same name; change the name of the ''datafile''!') + error('method_of_moments: ''datafile'' and mod file are not allowed to have the same name; change the name of the ''datafile''!'); end 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 + % check length of data for estimation of second moments if options_mom_.ar > options_mom_.nobs+1 error('method_of_moments: Dataset is too short to compute higher than first moments!'); end - % Provide info on data moments handling + % 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.get_data_moments(dataset_.data, oo_.mom.obs_var, oo_.dr.inv_order_var, M_.matched_moments, options_mom_); + % get data moments for the method of moments + [oo_.mom.data_moments, oo_.mom.m_data] = mom.get_data_moments(dataset_.data, options_mom_.mom.obs_var, oo_.dr.inv_order_var, M_.matched_moments, options_mom_); if ~isreal(dataset_.data) - error('method_of_moments: The data moments contain complex values!') + error('method_of_moments: The data moments contain complex values!'); end end % ------------------------------------------------------------------------- -% SMM: Get shock series fand set variance correction factor +% SMM: Get shock series 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); @@ -461,7 +477,6 @@ end % ------------------------------------------------------------------------- % checks for steady state at initial parameters % ------------------------------------------------------------------------- - % check if steady state solves static model and if steady-state changes estimated parameters if options_mom_.steadystate.nocheck steadystate_check_flag_vec = [0 1]; @@ -470,7 +485,7 @@ else end [oo_.steady_state, info, steady_state_changes_parameters] = check_steady_state_changes_parameters(M_, estim_params_, oo_, options_mom_, steadystate_check_flag_vec); if info(1) - fprintf('\nThe steady state at the initial parameters cannot be computed.\n') + fprintf('\nThe steady state at the initial parameters cannot be computed.\n'); print_info(info, 0, options_mom_); end if steady_state_changes_parameters && strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_standard_errors @@ -478,7 +493,6 @@ if steady_state_changes_parameters && strcmp(options_mom_.mom.mom_method,'GMM') fprintf('because the steady-state changes estimated parameters. Option ''analytic_derivation_mode'' reset to -2.'); options_mom_.analytic_derivation_mode = -2; end - % display warning if some parameters are still NaN test_for_deep_parameters_calibration(M_); @@ -488,17 +502,25 @@ test_for_deep_parameters_calibration(M_); % ------------------------------------------------------------------------- objective_function = str2func('mom.objective_function'); try - % Check for NaN or complex values of moment-distance-funtion evaluated at initial parameters + % check for NaN or complex values of moment-distance-funtion evaluated at initial parameters if strcmp(options_mom_.mom.mom_method,'SMM') || strcmp(options_mom_.mom.mom_method,'GMM') - oo_.mom.Sw = eye(options_mom_.mom.mom_nbr); % initialize with identity weighting matrix + oo_.mom.weighting_info.Sw = eye(options_mom_.mom.mom_nbr); % initialize with identity weighting matrix end tic_id = tic; - [fval, info, ~, ~, ~, oo_, M_] = feval(objective_function, xparam0, Bounds, oo_, estim_params_, M_, options_mom_); + [fval, info] = feval(objective_function, xparam0, oo_.mom.data_moments, oo_.mom.weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); elapsed_time = toc(tic_id); if isnan(fval) - error('method_of_moments: The initial value of the objective function with identity weighting matrix is NaN!') + if strcmp(options_mom_.mom.mom_method,'SMM') || strcmp(options_mom_.mom.mom_method,'GMM') + error('method_of_moments: The initial value of the objective function with identity weighting matrix is NaN!'); + else + error('method_of_moments: The initial value of the objective function is NaN!'); + end elseif imag(fval) - error('method_of_moments: The initial value of the objective function with identity weighting matrix is complex!') + if strcmp(options_mom_.mom.mom_method,'SMM') || strcmp(options_mom_.mom.mom_method,'GMM') + error('method_of_moments: The initial value of the objective function with identity weighting matrix is complex!'); + else + error('method_of_moments: The initial value of the objective function is complex!'); + end end if info(1) > 0 disp('method_of_moments: Error in computing the objective function for initial parameter values') @@ -513,10 +535,10 @@ try 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('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 @@ -527,60 +549,281 @@ end % ------------------------------------------------------------------------- % print some info to console % ------------------------------------------------------------------------- -mom.print_info_on_estimation_settings(options_mom_, number_of_estimated_parameters); +mom.print_info_on_estimation_settings(options_mom_, number_of_estimated_parameters, do_bayesian_estimation); + + +% ------------------------------------------------------------------------- +% compute mode for GMM/SMM +% ------------------------------------------------------------------------- +if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') + [xparam1, oo_.mom.weighting_info, oo_.mom.verbose] = mom.mode_compute_gmm_smm(xparam0, objective_function, oo_.mom.m_data, oo_.mom.data_moments, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); +end + +% ------------------------------------------------------------------------- +% compute mode for IRF matching +% ------------------------------------------------------------------------- +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + if ~do_bayesian_estimation || (do_bayesian_estimation && ~options_mom_.mh_posterior_mode_estimation) + [xparam1, hessian_xparam1, fval, oo_.mom.verbose] = mom.mode_compute_irf_matching(xparam0, hessian_xparam0, objective_function, do_bayesian_estimation, oo_.mom.weighting_info, oo_.mom.data_moments, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); + else + xparam1 = xparam0; + hessian_xparam1 = hessian_xparam0; + end +end % ------------------------------------------------------------------------- -% GMM/SMM: iterated estimation +% compute standard errors and initialize covariance of the proposal distribution % ------------------------------------------------------------------------- if strcmp(options_mom_.mom.mom_method,'GMM') || strcmp(options_mom_.mom.mom_method,'SMM') - % compute mode - [xparam1, oo_, Woptflag] = mom.mode_compute_gmm_smm(xparam0, objective_function, oo_, M_, options_mom_, estim_params_, bayestopt_, Bounds); % compute standard errors at mode options_mom_.mom.vector_output = false; % make sure flag is reset M_ = set_all_parameters(xparam1,estim_params_,M_); % update M_ and oo_ (in particular to get oo_.mom.model_moments) 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 - [~, ~, ~,~,~, oo_] = feval(objective_function, xparam1, Bounds, oo_, estim_params_, M_, options_mom_); % compute model moments and oo_.mom.model_moments_params_derivs + [~, ~, ~, ~, ~, oo_.mom.Q, oo_.mom.model_moments, oo_.mom.model_moments_params_derivs] = feval(objective_function, xparam1, oo_.mom.data_moments, oo_.mom.weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); options_mom_.mom.compute_derivs = false; % reset to not compute derivatives in objective function during optimization - [stdh,hessian_xparam1] = mom.standard_errors(xparam1, objective_function, Bounds, oo_, estim_params_, M_, options_mom_, Woptflag); + [stdh, invhess] = mom.standard_errors(xparam1, objective_function, oo_.mom.model_moments, oo_.mom.model_moments_params_derivs, oo_.mom.m_data, oo_.mom.data_moments, oo_.mom.weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); + if options_mom_.cova_compute + hessian_xparam1 = inv(invhess); + end +else + if ~do_bayesian_estimation || ~options_mom_.mh_posterior_mode_estimation + if do_bayesian_estimation + oo_.mom.posterior.optimization.mode = xparam1; + if exist('fval','var') + oo_.mom.posterior.optimization.log_density = -fval; + end + end + if options_mom_.cova_compute + hsd = sqrt(diag(hessian_xparam1)); % represent the curvature (or second derivatives) of the likelihood with respect to each parameter being estimated. + invhess = inv(hessian_xparam1./(hsd*hsd'))./(hsd*hsd'); % before taking the inverse scale the Hessian matrix by dividing each of its elements by the outer product of hsd such that the diagonal of the resulting matrix is approximately 1. This kind of scaling can help in regularizing the matrix and potentially improves its condition number, which in turn can make the matrix inversion more stable. + stdh = sqrt(diag(invhess)); + if do_bayesian_estimation + oo_.mom.posterior.optimization.Variance = invhess; + end + end + else + variances = bayestopt_.p2.*bayestopt_.p2; + id_Inf = isinf(variances); + variances(id_Inf) = 1; + invhess = options_mom_.mh_posterior_mode_estimation*diag(variances); + xparam1 = bayestopt_.p5; + id_NaN = isnan(xparam1); + xparam1(id_NaN) = bayestopt_.p1(id_NaN); + outside_bound_pars=find(xparam1 < BoundsInfo.lb | xparam1 > BoundsInfo.ub); + xparam1(outside_bound_pars) = bayestopt_.p1(outside_bound_pars); + end + if ~options_mom_.cova_compute + stdh = NaN(length(xparam1),1); + end +end + + +% ------------------------------------------------------------------------- +% display estimation results at mode +% ------------------------------------------------------------------------- +if do_bayesian_estimation && ~options_mom_.mom.penalized_estimator && ~options_mom_.mh_posterior_mode_estimation + % display table with Bayesian mode estimation results and store parameter estimates and standard errors in oo_ + oo_.mom = display_estimation_results_table(xparam1, stdh, M_, options_mom_, estim_params_, bayestopt_, oo_.mom, prior_dist_names, 'Posterior', 'posterior'); + % Laplace approximation to the marginal log density + if options_mom_.cova_compute + estim_params_nbr = size(xparam1,1); + if ispd(invhess) + log_det_invhess = log(det(invhess./(stdh*stdh')))+2*sum(log(stdh)); + likelihood = feval(objective_function, xparam1, oo_.mom.data_moments, oo_.mom.weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); + oo_.mom.MarginalDensity.LaplaceApproximation = .5*estim_params_nbr*log(2*pi) + .5*log_det_invhess - likelihood; + else + oo_.mom.MarginalDensity.LaplaceApproximation = NaN; + end + fprintf('\nLog data density [Laplace approximation] is %f.\n',oo_.mom.MarginalDensity.LaplaceApproximation); + end +elseif ~do_bayesian_estimation || (do_bayesian_estimation && options_mom_.mom.penalized_estimator) + % display table with Frequentist estimation results and store parameter estimates and standard errors in oo_ + oo_.mom = display_estimation_results_table(xparam1, stdh, M_, options_mom_, estim_params_, bayestopt_, oo_.mom, prior_dist_names, options_mom_.mom.mom_method, lower(options_mom_.mom.mom_method)); end % ------------------------------------------------------------------------- % checks for mode and hessian at the mode % ------------------------------------------------------------------------- +if (~do_bayesian_estimation && options_mom_.cova_compute) || (do_bayesian_estimation && ~options_mom_.mh_posterior_mode_estimation && options_mom_.cova_compute) + check_hessian_at_the_mode(hessian_xparam1, xparam1, M_, estim_params_, options_, BoundsInfo); +end if options_mom_.mode_check.status - mode_check(objective_function, xparam1, hessian_xparam1, options_mom_, M_, estim_params_, bayestopt_, Bounds, true,... - Bounds, oo_, estim_params_, M_, options_mom_); + if ~do_bayesian_estimation || (do_bayesian_estimation && ~options_mom_.mh_posterior_mode_estimation) + mode_check(objective_function, xparam1, diag(stdh), options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, true,... % use diag(stdh) instead of hessian_xparam1 as mode_check uses diagonal elements + oo_.mom.data_moments, oo_.mom.weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); + end +end + +% ------------------------------------------------------------------------- +% Bayesian MCMC estimation +% ------------------------------------------------------------------------- +if do_bayesian_estimation_mcmc + invhess = set_mcmc_jumping_covariance(invhess, length(xparam1), options_mom_.MCMC_jumping_covariance, bayestopt_, 'method_of_moments'); + % reset bounds as lb and ub must only be operational during mode-finding + BoundsInfo = set_mcmc_prior_bounds(xparam1, bayestopt_, options_mom_, 'method_of_moments'); + % tunes the jumping distribution's scale parameter + if isfield(options_mom_,'mh_tune_jscale') && options_mom_.mh_tune_jscale.status + if strcmp(options_mom_.posterior_sampler_options.posterior_sampling_method, 'random_walk_metropolis_hastings') + options_mom_.mh_jscale = tune_mcmc_mh_jscale_wrapper(invhess, options_mom_, M_, objective_function, xparam1, BoundsInfo,... + oo_.mom.data_moments, oo_.mom.weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); + bayestopt_.jscale(:) = options_mom_.mh_jscale; + fprintf('mh_tune_jscale: mh_jscale has been set equal to %s.\n', num2str(options_mom_.mh_jscale)); + else + warning('mh_tune_jscale is only available with ''random_walk_metropolis_hastings''!') + end + end + % run MCMC sampling + posterior_sampler_options = options_mom_.posterior_sampler_options.current_options; + posterior_sampler_options.invhess = invhess; + [posterior_sampler_options, options_mom_, bayestopt_] = check_posterior_sampler_options(posterior_sampler_options, M_.fname, M_.dname, options_mom_, BoundsInfo, bayestopt_,'method_of_moments'); + options_mom_.posterior_sampler_options.current_options = posterior_sampler_options; % store current options + if options_mom_.mh_replic>0 + posterior_sampler(objective_function,posterior_sampler_options.proposal_distribution,xparam1,posterior_sampler_options,BoundsInfo,oo_.mom.data_moments,oo_.mom.weighting_info,options_mom_,M_,estim_params_,bayestopt_,oo_,'method_of_moments::mcmc'); + end + CutSample(M_, options_mom_, 'method_of_moments::mcmc'); % discard first mh_drop percent of the draws + if options_mom_.mh_posterior_mode_estimation + % skip optimizer-based mode-finding and instead compute the mode based on a run of a MCMC + [~,~,posterior_mode,~] = compute_mh_covariance_matrix(bayestopt_,M_.fname,M_.dname,'method_of_moments'); + oo_.mom = fill_mh_mode(posterior_mode',NaN(length(posterior_mode),1),M_,options_mom_,estim_params_,bayestopt_,oo_.mom,'posterior'); + return + else + % get stored results if required + if options_mom_.load_mh_file && options_mom_.load_results_after_load_mh + oo_load_mh = load([M_.dname filesep 'method_of_moments' filesep M_.fname '_mom_results'],'oo_'); + end + % convergence diagnostics + if ~options_mom_.nodiagnostic + if (options_mom_.mh_replic>0 || (options_mom_.load_mh_file && ~options_mom_.load_results_after_load_mh)) + oo_.mom = mcmc_diagnostics(options_mom_, estim_params_, M_, oo_.mom); + elseif options_mom_.load_mh_file && options_mom_.load_results_after_load_mh + if isfield(oo_load_mh.oo_.mom,'convergence') + oo_.mom.convergence = oo_load_mh.oo_.mom.convergence; + end + end + end + % statistics and plots for posterior draws + if options_mom_.mh_replic || (options_mom_.load_mh_file && ~options_mom_.load_results_after_load_mh) + [~,oo_.mom] = marginal_density(M_, options_mom_, estim_params_, oo_.mom, bayestopt_, 'method_of_moments'); + oo_.mom = GetPosteriorParametersStatistics(estim_params_, M_, options_mom_, bayestopt_, oo_.mom, prior_dist_names); + if ~options_mom_.nograph + oo_.mom = PlotPosteriorDistributions(estim_params_, M_, options_mom_, bayestopt_, oo_.mom); + end + [oo_.mom.posterior.metropolis.mean,oo_.mom.posterior.metropolis.Variance] = GetPosteriorMeanVariance(options_mom_,M_); + elseif options_mom_.load_mh_file && options_mom_.load_results_after_load_mh + % load fields from previous MCMC run stored in results-file + field_names={'posterior_mode','posterior_std_at_mode',...% fields set by marginal_density + 'posterior_mean','posterior_hpdinf','posterior_hpdsup','posterior_median','posterior_variance','posterior_std','posterior_deciles','posterior_density',...% fields set by GetPosteriorParametersStatistics + 'prior_density',...% fields set by PlotPosteriorDistributions + }; + for field_iter=1:size(field_names,2) + if isfield(oo_load_mh.oo_.mom,field_names{1,field_iter}) + oo_.mom.(field_names{1,field_iter}) = oo_load_mh.oo_.mom.(field_names{1,field_iter}); + end + end + if isfield(oo_load_mh.oo_.mom,'MarginalDensity') && isfield(oo_load_mh.oo_.mom.MarginalDensity,'ModifiedHarmonicMean') % field set by marginal_density + oo_.mom.MarginalDensity.ModifiedHarmonicMean = oo_load_mh.oo_.mom.MarginalDensity.ModifiedHarmonicMean; + end + if isfield(oo_load_mh.oo_.mom,'posterior') && isfield(oo_load_mh.oo_.mom.posterior,'metropolis') % field set by GetPosteriorMeanVariance + oo_.mom.posterior.metropolis = oo_load_mh.oo_.mom.posterior.metropolis; + end + end + [error_flag,~,options_mom_]= metropolis_draw(1,options_mom_,estim_params_,M_); + if ~(~isempty(options_mom_.sub_draws) && options_mom_.sub_draws==0) + % THIS IS PROBABLY NOT USEFUL HERE AND CAN BE REMOVED (PREPROCESSOR: REMOVE bayesian_irf, moments_varendo) + %if options_mom_.bayesian_irf + % if error_flag + % error('method_of_moments: Cannot compute the posterior IRFs!'); + % end + % PosteriorIRF('posterior','method_of_moments::mcmc'); + %end + % if options_mom_.moments_varendo + % if error_flag + % error('method_of_moments: Cannot compute the posterior moments for the endogenous variables!'); + % end + % if options_mom_.load_mh_file && options_mom_.mh_replic==0 %user wants to recompute results + % [MetropolisFolder, info] = CheckPath('metropolis',options_mom_.dirname); + % if ~info + % generic_post_data_file_name={'Posterior2ndOrderMoments','decomposition','PosteriorVarianceDecomposition','correlation','PosteriorCorrelations','conditional decomposition','PosteriorConditionalVarianceDecomposition'}; + % for ii=1:length(generic_post_data_file_name) + % delete_stale_file([MetropolisFolder filesep M_.fname '_' generic_post_data_file_name{1,ii} '*']); + % end + % % restore compatibility for loading pre-4.6.2 runs where estim_params_ was not saved; see 6e06acc7 and !1944 + % NumberOfDrawsFiles = length(dir([M_.dname '/metropolis/' M_.fname '_posterior_draws*' ])); + % if NumberOfDrawsFiles>0 + % temp=load([M_.dname '/metropolis/' M_.fname '_posterior_draws1']); + % if ~isfield(temp,'estim_params_') + % for file_iter=1:NumberOfDrawsFiles + % save([M_.dname '/metropolis/' M_.fname '_posterior_draws' num2str(file_iter)],'estim_params_','-append') + % end + % end + % end + % end + % end + % oo_ = compute_moments_varendo('posterior',options_,M_,oo_,var_list_); + % end + else + fprintf('''sub_draws'' was set to 0. Skipping posterior computations.'); + end + xparam1 = get_posterior_parameters('mean',M_,estim_params_,oo_.mom,options_); + end + % MAYBE USEFUL???? + % % Posterior correlations + % extreme_corr_bound = 0.7; + % if ~isnan(extreme_corr_bound) + % tril_para_correlation_matrix=tril(para_correlation_matrix,-1); + % [row_index,col_index]=find(abs(tril_para_correlation_matrix)>extreme_corr_bound); + % extreme_corr_params=cell(length(row_index),3); + % for i=1:length(row_index) + % extreme_corr_params{i,1}=char(parameter_names(row_index(i),:)); + % extreme_corr_params{i,2}=char(parameter_names(col_index(i),:)); + % extreme_corr_params{i,3}=tril_para_correlation_matrix(row_index(i),col_index(i)); + % end + % end + % disp(' '); + % disp(['Correlations of Parameters (at Posterior Mode) > ',num2str(extreme_corr_bound)]); + % disp(extreme_corr_params) end % ------------------------------------------------------------------------- % display final estimation results % ------------------------------------------------------------------------- +M_ = set_all_parameters(xparam1,estim_params_,M_); % update parameters +[~, ~, ~, ~, ~, oo_.mom.Q, oo_.mom.model_moments, oo_.mom.model_moments_params_derivs, oo_.mom.irf_model_varobs] = objective_function(xparam1, oo_.mom.data_moments, oo_.mom.weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); % store final results in oo_.mom if strcmp(options_mom_.mom.mom_method,'SMM') || strcmp(options_mom_.mom.mom_method,'GMM') - % Store results in output structure - oo_.mom = display_estimation_results_table(xparam1,stdh,M_,options_mom_,estim_params_,bayestopt_,oo_.mom,prior_dist_names,options_mom_.mom.mom_method,lower(options_mom_.mom.mom_method)); % J test - oo_ = mom.Jtest(xparam1, objective_function, Woptflag, oo_, options_mom_, bayestopt_, Bounds, estim_params_, M_, dataset_.nobs); - % display comparison of model moments and data moments - mom.display_comparison_moments(M_, options_mom_, oo_.mom.data_moments, oo_.mom.model_moments); + oo_.mom.J_test = mom.Jtest(xparam1, objective_function, oo_.mom.Q, oo_.mom.model_moments, oo_.mom.m_data, oo_.mom.data_moments, oo_.mom.weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, oo_.dr, oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state); +elseif strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') + if ~options_mom_.nograph + mom.graph_comparison_irfs(M_.matched_irfs,oo_.mom.irf_model_varobs,options_mom_.varobs_id,options_mom_.irf,options_mom_.relative_irf,M_.endo_names,M_.endo_names_tex,M_.exo_names,M_.exo_names_tex,M_.dname,M_.fname,options_mom_.graph_format,options_mom_.TeX,options_mom_.nodisplay,options_mom_.figures.textwidth) + end end +% display comparison of model moments/IRFs and data moments/IRFs +mom.display_comparison_moments_irfs(M_, options_mom_, oo_.mom.data_moments, oo_.mom.model_moments); +% save results to _mom_results.mat +save([M_.dname filesep 'method_of_moments' filesep M_.fname '_mom_results.mat'], 'oo_', 'options_mom_', 'M_', 'estim_params_', 'bayestopt_'); +fprintf('\n==== Method of Moments Estimation (%s) Completed ====\n\n',options_mom_.mom.mom_method); % ------------------------------------------------------------------------- % clean up % ------------------------------------------------------------------------- -fprintf('\n==== Method of Moments Estimation (%s) Completed ====\n\n',options_mom_.mom.mom_method) - -%reset warning state -warning_config; - +warning_config; %reset warning state if isoctave && isfield(options_mom_, 'prior_restrictions') && ... isfield(options_mom_.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_mom_.prior_restrictions.routine = []; end +if strcmp(options_mom_.mom.mom_method,'SMM') || strcmp(options_mom_.mom.mom_method,'GMM') + if isfield(oo_.mom,'irf_model_varobs') && isempty(oo_.mom.irf_model_varobs) + oo_.mom = rmfield(oo_.mom,'irf_model_varobs'); % remove empty field + end +end +if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') && ~isempty(options_mom_.mom.irf_matching_file.path) && ~strcmp(options_mom_.mom.irf_matching_file.path,'.') + rmpath(options_mom_.irf_matching_file.path); % remove path to irf_matching_file +end \ No newline at end of file diff --git a/matlab/+mom/set_correct_bounds_for_stderr_corr.m b/matlab/+mom/set_correct_bounds_for_stderr_corr.m index d65e9473be22b91c06559b512531a195c7add5bc..3499cc399328e8fe683c603e85a5d9ce0b0c5ba8 100644 --- a/matlab/+mom/set_correct_bounds_for_stderr_corr.m +++ b/matlab/+mom/set_correct_bounds_for_stderr_corr.m @@ -1,18 +1,19 @@ -function Bounds = set_correct_bounds_for_stderr_corr(estim_params_,Bounds) -% function Bounds = set_correct_bounds_for_stderr_corr(estim_params_,Bounds) +function BoundsInfo = set_correct_bounds_for_stderr_corr(estim_params_,BoundsInfo) +% BoundsInfo = set_correct_bounds_for_stderr_corr(estim_params_,BoundsInfo) % ------------------------------------------------------------------------- % Set correct bounds for standard deviation and corrrelation parameters -% ========================================================================= +% ------------------------------------------------------------------------- % INPUTS % o estim_params_ [struct] information on estimated parameters -% o Bounds [struct] information on bounds +% o BoundsInfo [struct] information on bounds % ------------------------------------------------------------------------- % OUTPUT -% o Bounds [struct] updated bounds +% o BoundsInfo [struct] updated bounds % ------------------------------------------------------------------------- % This function is called by % o mom.run -% ========================================================================= +% ------------------------------------------------------------------------- + % Copyright © 2023 Dynare Team % % This file is part of Dynare. @@ -29,15 +30,15 @@ function Bounds = set_correct_bounds_for_stderr_corr(estim_params_,Bounds) % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ========================================================================= + number_of_estimated_parameters = estim_params_.nvx+estim_params_.nvn+estim_params_.ncx+estim_params_.ncn+estim_params_.np; % set correct bounds for standard deviations and corrrelations param_of_interest = (1:number_of_estimated_parameters)'<=estim_params_.nvx+estim_params_.nvn; -LB_below_0 = (Bounds.lb<0 & param_of_interest); -Bounds.lb(LB_below_0) = 0; +LB_below_0 = (BoundsInfo.lb<0 & param_of_interest); +BoundsInfo.lb(LB_below_0) = 0; param_of_interest = (1:number_of_estimated_parameters)'> estim_params_.nvx+estim_params_.nvn & (1:number_of_estimated_parameters)'<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; \ No newline at end of file +LB_below_minus_1 = (BoundsInfo.lb<-1 & param_of_interest); +UB_above_1 = (BoundsInfo.ub>1 & param_of_interest); +BoundsInfo.lb(LB_below_minus_1) = -1; +BoundsInfo.ub(UB_above_1) = 1; \ No newline at end of file diff --git a/matlab/+mom/standard_errors.m b/matlab/+mom/standard_errors.m index 6bfec1e72dadbdc117c1fec9767b27f0577324a2..c8336d68faf416b9eaeab368365a12ed8affc654 100644 --- a/matlab/+mom/standard_errors.m +++ b/matlab/+mom/standard_errors.m @@ -1,23 +1,32 @@ -function [SE_values, Asympt_Var] = standard_errors(xparam, objective_function, Bounds, oo_, estim_params_, M_, options_mom_, Wopt_flag) -% [SE_values, Asympt_Var] = standard_errors(xparam, objective_function, Bounds, oo_, estim_params_, M_, options_mom_, Wopt_flag) +function [stderr_values, asympt_cov_mat] = standard_errors(xparam, objective_function, model_moments, model_moments_params_derivs, m_data, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) +% [stderr_values, asympt_cov_mat] = standard_errors(xparam, objective_function, model_moments, model_moments_params_derivs, m_data, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state) % ------------------------------------------------------------------------- % 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. -% ========================================================================= +% Adapted from replication codes 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. +% ------------------------------------------------------------------------- % INPUTS -% o xparam: value of estimated parameters as returned by set_prior() -% o objective_function string of objective function -% o Bounds: structure containing parameter bounds -% o oo_: structure for results -% o estim_params_: structure describing the estimated_parameters -% o M_ structure describing the model -% o options_mom_: 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 +% - xparam: [vector] value of estimated parameters as returned by set_prior() +% - objective_function [func] function handle with string of objective function +% - model_moments: [vector] model moments +% - model_moments_params_derivs: [matrix] analytical jacobian of the model moments wrt estimated parameters (currently for GMM only) +% - m_data [matrix] selected empirical moments at each point in time +% - data_moments: [vector] data with moments/IRFs to match +% - weighting_info: [structure] storing information on weighting matrices +% - options_mom_: [structure] information about all settings (specified by the user, preprocessor, and taken from global options_) +% - M_ [structure] model information +% - estim_params_: [structure] information from estimated_params block +% - bayestopt_: [structure] information on the prior distributions +% - BoundsInfo: [structure] parameter bounds +% - dr: [structure] reduced form model +% - endo_steady_state: [vector] steady state value for endogenous variables (initval) +% - exo_steady_state: [vector] steady state value for exogenous variables (initval) +% - exo_det_steady_state: [vector] steady state value for exogenous deterministic variables (initval) % ------------------------------------------------------------------------- % OUTPUTS -% o SE_values [nparam x 1] vector of standard errors -% o Asympt_Var [nparam x nparam] asymptotic covariance matrix +% o stderr_values [nparam x 1] vector of standard errors +% o asympt_cov_mat [nparam x nparam] asymptotic covariance matrix % ------------------------------------------------------------------------- % This function is called by % o mom.run.m @@ -26,9 +35,10 @@ function [SE_values, Asympt_Var] = standard_errors(xparam, objective_function, B % o get_the_name % o get_error_message % o mom.objective_function -% o mom.optimal_weighting_matrix -% ========================================================================= -% Copyright © 2020-2021 Dynare Team +% o mom.optimal_weighting_matrix +% ------------------------------------------------------------------------- + +% Copyright © 2020-2023 Dynare Team % % This file is part of Dynare. % @@ -44,84 +54,74 @@ function [SE_values, Asympt_Var] = standard_errors(xparam, objective_function, B % % 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 (johannes.pfeifer@unibw.de) -% ========================================================================= % Some dimensions -num_mom = size(oo_.mom.model_moments,1); +num_mom = size(model_moments,1); dim_params = size(xparam,1); D = zeros(num_mom,dim_params); eps_value = options_mom_.mom.se_tolx; if strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_standard_errors fprintf('\nComputing standard errors using analytical derivatives of moments\n'); - D = oo_.mom.model_moments_params_derivs; %already computed in objective function via get_perturbation_params.m + D = model_moments_params_derivs; % already computed in objective function via get_perturbation_params.m idx_nan = find(any(isnan(D))); if any(idx_nan) for i = idx_nan fprintf('No standard errors available for parameter %s\n',get_the_name(i,options_mom_.TeX, M_, estim_params_, options_mom_.varobs)) end warning('There are NaN in the analytical Jacobian of Moments. Check your bounds and/or priors, or use a different optimizer.') - Asympt_Var = NaN(length(xparam),length(xparam)); - SE_values = NaN(length(xparam),1); + asympt_cov_mat = NaN(length(xparam),length(xparam)); + stderr_values = NaN(length(xparam),1); return end else fprintf('\nComputing standard errors using numerical derivatives of moments\n'); for i=1:dim_params - %Positive step + % positive step xparam_eps_p = xparam; - xparam_eps_p(i,1) = xparam_eps_p(i) + eps_value; - [~, info_p, ~, ~,~, oo__p] = feval(objective_function, xparam_eps_p, Bounds, oo_, estim_params_, M_, options_mom_); - - % Negative step + xparam_eps_p(i,1) = xparam_eps_p(i) + eps_value; + [~, info_p, ~, ~, ~, ~, model_moments_p] = feval(objective_function, xparam_eps_p, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); + % negative step xparam_eps_m = xparam; - xparam_eps_m(i,1) = xparam_eps_m(i) - eps_value; - [~, info_m, ~, ~,~, oo__m] = feval(objective_function, xparam_eps_m, Bounds, oo_, estim_params_, M_, options_mom_); - - % The Jacobian: + xparam_eps_m(i,1) = xparam_eps_m(i) - eps_value; + [~, info_m, ~, ~, ~, ~, model_moments_m] = feval(objective_function, xparam_eps_m, data_moments, weighting_info, options_mom_, M_, estim_params_, bayestopt_, BoundsInfo, dr, endo_steady_state, exo_steady_state, exo_det_steady_state); + % the Jacobian if nnz(info_p)==0 && nnz(info_m)==0 - D(:,i) = (oo__p.mom.model_moments - oo__m.mom.model_moments)/(2*eps_value); + D(:,i) = (model_moments_p - model_moments_m)/(2*eps_value); else - problpar = get_the_name(i,options_mom_.TeX, M_, estim_params_, options_mom_.varobs); + problematic_parameter = get_the_name(i,options_mom_.TeX, M_, estim_params_, options_mom_.varobs); if info_p(1)==42 - warning('method_of_moments:info','Cannot compute the Jacobian using finite differences for parameter %s due to hitting the upper bound - no standard errors available.\n',problpar) + warning('method_of_moments:info','Cannot compute the Jacobian using finite differences for parameter %s due to hitting the upper bound - no standard errors available.\n',problematic_parameter) else message_p = get_error_message(info_p, options_mom_); end if info_m(1)==41 - warning('method_of_moments:info','Cannot compute the Jacobian using finite differences for parameter %s due to hitting the lower bound - no standard errors available.\n',problpar) + warning('method_of_moments:info','Cannot compute the Jacobian using finite differences for parameter %s due to hitting the lower bound - no standard errors available.\n',problematic_parameter) else - message_m = get_error_message(info_m, options_mom_); + message_m = get_error_message(info_m, options_mom_); end if info_m(1)~=41 && info_p(1)~=42 - warning('method_of_moments:info','Cannot compute the Jacobian using finite differences for parameter %s - no standard errors available\n %s %s\nCheck your priors or use a different optimizer.\n',problpar, message_p, message_m) + warning('method_of_moments:info','Cannot compute the Jacobian using finite differences for parameter %s - no standard errors available\n %s %s\nCheck your priors or use a different optimizer.\n',problematic_parameter, message_p, message_m) end - Asympt_Var = NaN(length(xparam),length(xparam)); - SE_values = NaN(length(xparam),1); + asympt_cov_mat = NaN(length(xparam),length(xparam)); + stderr_values = NaN(length(xparam),1); return end end end - -T = options_mom_.nobs; %Number of observations +T = options_mom_.nobs; if isfield(options_mom_,'variance_correction_factor') T = T*options_mom_.variance_correction_factor; end - -WW = oo_.mom.Sw'*oo_.mom.Sw; -if Wopt_flag - % We have the optimal weighting matrix - Asympt_Var = 1/T*((D'*WW*D)\eye(dim_params)); +WW = weighting_info.Sw'*weighting_info.Sw; +if weighting_info.Woptflag + % we already have the optimal weighting matrix + asympt_cov_mat = 1/T*((D'*WW*D)\eye(dim_params)); else - % We do not have the optimal weighting matrix yet - WWopt = mom.optimal_weighting_matrix(oo_.mom.m_data, oo_.mom.model_moments, options_mom_.mom.bartlett_kernel_lag); + % we do not have the optimal weighting matrix yet + WWopt = mom.optimal_weighting_matrix(m_data, model_moments, options_mom_.mom.bartlett_kernel_lag); S = WWopt\eye(size(WWopt,1)); AA = (D'*WW*D)\eye(dim_params); - Asympt_Var = 1/T*AA*D'*WW*S*WW*D*AA; + asympt_cov_mat = 1/T*AA*D'*WW*S*WW*D*AA; end - -SE_values = sqrt(diag(Asympt_Var)); +stderr_values = sqrt(diag(asympt_cov_mat)); \ No newline at end of file diff --git a/matlab/+mom/transform_prior_to_laplace_prior.m b/matlab/+mom/transform_prior_to_laplace_prior.m index f2cdf7cd20b644c1f4f56848f0f9f047f41fe41c..358f9fd1e64638339a5f8b1e43c4ea40a48a094b 100644 --- a/matlab/+mom/transform_prior_to_laplace_prior.m +++ b/matlab/+mom/transform_prior_to_laplace_prior.m @@ -1,10 +1,10 @@ function bayestopt_ = transform_prior_to_laplace_prior(bayestopt_) -% function bayestopt_ = transform_prior_to_laplace_prior(bayestopt_) +% bayestopt_ = transform_prior_to_laplace_prior(bayestopt_) % ------------------------------------------------------------------------- % Transforms the prior specification to a Laplace type of approximation: % only the prior mean and standard deviation are relevant, all other shape % information, except for the parameter bounds, is ignored. -% ========================================================================= +% ------------------------------------------------------------------------- % INPUTS % bayestopt_ [structure] prior information % ------------------------------------------------------------------------- @@ -13,7 +13,8 @@ function bayestopt_ = transform_prior_to_laplace_prior(bayestopt_) % ------------------------------------------------------------------------- % This function is called by % o mom.run -% ========================================================================= +% ------------------------------------------------------------------------- + % Copyright © 2023 Dynare Team % % This file is part of Dynare. @@ -30,7 +31,7 @@ function bayestopt_ = transform_prior_to_laplace_prior(bayestopt_) % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -% ========================================================================= + if any(setdiff([0;bayestopt_.pshape],[0,3])) fprintf('\nNon-normal priors specified. Penalized estimation uses a Laplace type of approximation:'); fprintf('\nOnly the prior mean and standard deviation are relevant, all other shape information, except for the parameter bounds, is ignored.\n\n'); diff --git a/matlab/estimation/check_posterior_sampler_options.m b/matlab/estimation/check_posterior_sampler_options.m index c0d4235ff1f22091c40ca8019036780afacbeb2d..29de7cf6891de044ffe52e957f037e37262597fa 100644 --- a/matlab/estimation/check_posterior_sampler_options.m +++ b/matlab/estimation/check_posterior_sampler_options.m @@ -311,7 +311,7 @@ if init end % slice posterior sampler does not require mode or hessian to run - % needs to be set to 1 to skip parts in dynare_estimation_1.m + % needs to be set to 1 to skip parts in dynare_estimation_1.m or mom.run.m % requiring posterior maximization/calibrated smoother before MCMC options_.mh_posterior_mode_estimation=true; diff --git a/matlab/estimation/display_estimation_results_table.m b/matlab/estimation/display_estimation_results_table.m index a28c46ff60190062a0703f47022bc8a6defcb537..f24729cb30b9cf76ddfa255e254cab0c9611c995 100644 --- a/matlab/estimation/display_estimation_results_table.m +++ b/matlab/estimation/display_estimation_results_table.m @@ -50,7 +50,7 @@ LaTeXtitle=strrep(table_title,' ','_'); tstath = abs(xparam1)./stdh; header_width = row_header_width(M_, estim_params_, bayestopt_); -if strcmp(field_name,'posterior') +if contains(field_name,'posterior') tit1 = sprintf('%-*s %10s %8s %7s %6s %6s\n', header_width, ' ', 'prior mean', ... 'mode', 's.d.', 'prior', 'pstdev'); else @@ -62,7 +62,7 @@ if np disp(tit1) for i=1:np name = bayestopt_.name{ip}; - if strcmp(field_name,'posterior') + if contains(field_name,'posterior') fprintf('%-*s %10.4f %8.4f %7.4f %6s %6.4f \n', ... header_width,name, ... bayestopt_.p1(ip),xparam1(ip),stdh(ip), ... @@ -85,7 +85,7 @@ if nvx for i=1:nvx k = estim_params_.var_exo(i,1); name = M_.exo_names{k}; - if strcmp(field_name,'posterior') + if contains(field_name,'posterior') fprintf('%-*s %10.4f %8.4f %7.4f %6s %6.4f \n', ... header_width, name, bayestopt_.p1(ip), xparam1(ip), ... stdh(ip), pnames{bayestopt_.pshape(ip)+1}, ... @@ -106,7 +106,7 @@ if nvn ip = nvx+1; for i=1:nvn name = options_.varobs{estim_params_.nvn_observable_correspondence(i,1)}; - if strcmp(field_name,'posterior') + if contains(field_name,'posterior') fprintf('%-*s %10.4f %8.4f %7.4f %6s %6.4f \n', ... header_width, name, bayestopt_.p1(ip), ... xparam1(ip), stdh(ip), ... @@ -132,7 +132,7 @@ if ncx k2 = estim_params_.corrx(i,2); name = sprintf('%s,%s', M_.exo_names{k1}, M_.exo_names{k2}); NAME = sprintf('%s_%s', M_.exo_names{k1}, M_.exo_names{k2}); - if strcmp(field_name, 'posterior') + if contains(field_name,'posterior') fprintf('%-*s %10.4f %8.4f %7.4f %6s %6.4f \n', ... header_width, name, bayestopt_.p1(ip), xparam1(ip), stdh(ip), ... pnames{bayestopt_.pshape(ip)+1}, bayestopt_.p2(ip)); @@ -158,7 +158,7 @@ if ncn k2 = estim_params_.corrn(i,2); name = sprintf('%s,%s', M_.endo_names{k1}, M_.endo_names{k2}); NAME = sprintf('%s_%s', M_.endo_names{k1}, M_.endo_names{k2}); - if strcmp(field_name,'posterior') + if contains(field_name,'posterior') fprintf('%-*s %10.4f %8.4f %7.4f %6s %6.4f \n', ... header_width, name, bayestopt_.p1(ip), xparam1(ip), stdh(ip), ... pnames{bayestopt_.pshape(ip)+1}, bayestopt_.p2(ip)); diff --git a/matlab/estimation/posterior_sampler.m b/matlab/estimation/posterior_sampler.m index eb2b55ea8d47e1ab0ffdf5e246928174b9b6ba98..f1939042bacd97f2fa0f6b193cb22bad03d4d24a 100644 --- a/matlab/estimation/posterior_sampler.m +++ b/matlab/estimation/posterior_sampler.m @@ -10,8 +10,8 @@ function posterior_sampler(TargetFun,ProposalFun,xparam1,sampler_options,mh_boun % o xparam1 [double] (p*1) vector of parameters to be estimated (initial values). % o sampler_options structure % o mh_bounds [double] (p*2) matrix defining lower and upper bounds for the parameters. -% o dataset_ [structure] data structure -% o dataset_info [structure] dataset info structure +% o dataset_ [structure] data structure (likelihood-based) or data moments (method of moments) +% o dataset_info [structure] dataset info structure (likelihood-based) or info on weighting matrix (method of moments) % o options_ [structure] options structure % o M_ [structure] model structure % o estim_params_ [structure] estimated parameters structure diff --git a/matlab/estimation/posterior_sampler_initialization.m b/matlab/estimation/posterior_sampler_initialization.m index 1307588241be140b05f78e4b6e5494602ef4bce5..194f4c3c30f1401043e3157d734ecae1a143fd33 100644 --- a/matlab/estimation/posterior_sampler_initialization.m +++ b/matlab/estimation/posterior_sampler_initialization.m @@ -9,8 +9,8 @@ function [ ix2, ilogpo2, ModelName, MetropolisFolder, FirstBlock, FirstLine, npa % o xparam1 [double] (p*1) vector of parameters to be estimated (initial values). % o vv [double] (p*p) matrix, posterior covariance matrix (at the mode). % o mh_bounds [double] (p*2) matrix defining lower and upper bounds for the parameters. -% o dataset_ data structure -% o dataset_info dataset info structure +% o dataset_ data structure (likelihood based) or data moments/irfs (method of moments) +% o dataset_info dataset info structure (likelihood based) or info on weighting matrix (method of moments) % o options_ options structure % o M_ model structure % o estim_params_ estimated parameters structure diff --git a/matlab/get_error_message.m b/matlab/get_error_message.m index 581fb3f903188a87e26310bbe43817a248862c4e..1694dde4e2424c664e725911e6e358004fc1b079 100644 --- a/matlab/get_error_message.m +++ b/matlab/get_error_message.m @@ -168,6 +168,8 @@ switch info(1) message = 'Aim: Problem in SPEIG.'; case 180 message = 'SMM: simulation resulted in NaN/Inf. You may need to enable pruning.'; + case 181 + message = 'IRF Matching: simulated IRFs were explosive. Either reduce the shock size, use pruning, or set the approximation order to 1.'; case 201 message = 'Particle Filter: Initial covariance of the states is not positive definite. Try a different nonlinear_filter_initialization'; case 202 diff --git a/matlab/utilities/estimation/tune_mcmc_mh_jscale_wrapper.m b/matlab/utilities/estimation/tune_mcmc_mh_jscale_wrapper.m index 0da796f513cd6ebbf74e77a49be771094ff4eb35..82548cd5841fe74447bf1e9ff66ce2daac983cfe 100644 --- a/matlab/utilities/estimation/tune_mcmc_mh_jscale_wrapper.m +++ b/matlab/utilities/estimation/tune_mcmc_mh_jscale_wrapper.m @@ -18,6 +18,7 @@ function mh_jscale = tune_mcmc_mh_jscale_wrapper(invhess, options_, M_, objectiv % ------------------------------------------------------------------------- % This function is called by % o dynare_estimation_1 +% o mom.run % ------------------------------------------------------------------------- % Copyright © 2023 Dynare Team diff --git a/meson.build b/meson.build index bf00091ba6f161a15c84a1db4a7a358444b78568..9c33d94d78847c07176398200742e18e30249599 100644 --- a/meson.build +++ b/meson.build @@ -911,6 +911,42 @@ mod_and_m_tests = [ 'extra' : [ 'estimation/method_of_moments/AFVRR/AFVRR_common.inc', 'estimation/method_of_moments/AFVRR/AFVRR_data.mat', 'estimation/method_of_moments/AFVRR/AFVRR_steady_helper.m' ] }, + { 'test' : [ 'estimation/method_of_moments/CET/cet_interface.mod' ], + 'extra' : [ 'estimation/method_of_moments/CET/cet_data.mat', + 'estimation/method_of_moments/CET/cet_irf_matching_file.m', + 'estimation/method_of_moments/CET/cet_model.inc', + 'estimation/method_of_moments/CET/cet_original_mode.mat', + 'estimation/method_of_moments/CET/cet_steady_helper.m' ] }, + { 'test' : [ 'estimation/method_of_moments/CET/cet_imh.mod' ], + 'extra' : [ 'estimation/method_of_moments/CET/cet_data.mat', + 'estimation/method_of_moments/CET/cet_irf_matching_file.m', + 'estimation/method_of_moments/CET/cet_model.inc', + 'estimation/method_of_moments/CET/cet_original_mode.mat', + 'estimation/method_of_moments/CET/cet_steady_helper.m' ] }, + { 'test' : [ 'estimation/method_of_moments/CET/cet_mle.mod' ], + 'extra' : [ 'estimation/method_of_moments/CET/cet_data.mat', + 'estimation/method_of_moments/CET/cet_irf_matching_file.m', + 'estimation/method_of_moments/CET/cet_model.inc', + 'estimation/method_of_moments/CET/cet_original_mode.mat', + 'estimation/method_of_moments/CET/cet_steady_helper.m' ] }, + { 'test' : [ 'estimation/method_of_moments/CET/cet_rwmh.mod' ], + 'extra' : [ 'estimation/method_of_moments/CET/cet_data.mat', + 'estimation/method_of_moments/CET/cet_irf_matching_file.m', + 'estimation/method_of_moments/CET/cet_model.inc', + 'estimation/method_of_moments/CET/cet_original_mode.mat', + 'estimation/method_of_moments/CET/cet_steady_helper.m' ] }, + { 'test' : [ 'estimation/method_of_moments/CET/cet_slice.mod' ], + 'extra' : [ 'estimation/method_of_moments/CET/cet_data.mat', + 'estimation/method_of_moments/CET/cet_irf_matching_file.m', + 'estimation/method_of_moments/CET/cet_model.inc', + 'estimation/method_of_moments/CET/cet_original_mode.mat', + 'estimation/method_of_moments/CET/cet_steady_helper.m' ] }, + { 'test' : [ 'estimation/method_of_moments/CET/cet_tarb.mod' ], + 'extra' : [ 'estimation/method_of_moments/CET/cet_data.mat', + 'estimation/method_of_moments/CET/cet_irf_matching_file.m', + 'estimation/method_of_moments/CET/cet_model.inc', + 'estimation/method_of_moments/CET/cet_original_mode.mat', + 'estimation/method_of_moments/CET/cet_steady_helper.m' ] }, { 'test' : [ 'estimation/conditional-likelihood/1/fs2000_estimation_exact.mod', 'estimation/conditional-likelihood/1/fs2000_estimation_conditional.mod' ], 'extra' : [ 'estimation/fsdat_simul.m' ] }, diff --git a/preprocessor b/preprocessor index f8b2de715c57d3d66fff38b41fa3b4351c015c11..520876560d5bb4c886a11de681557dd05cbc200e 160000 --- a/preprocessor +++ b/preprocessor @@ -1 +1 @@ -Subproject commit f8b2de715c57d3d66fff38b41fa3b4351c015c11 +Subproject commit 520876560d5bb4c886a11de681557dd05cbc200e diff --git a/tests/estimation/method_of_moments/CET/cet_data.mat b/tests/estimation/method_of_moments/CET/cet_data.mat new file mode 100644 index 0000000000000000000000000000000000000000..5e9f6dd4fa2faa0f3e6cbeac441a29a71e2d2cf2 --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_data.mat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1958d890c5c2b01e9b67b0faefeb66e9a0052fcab3a8530d13bb22a8c035f0e2 +size 13553 diff --git a/tests/estimation/method_of_moments/CET/cet_imh.mod b/tests/estimation/method_of_moments/CET/cet_imh.mod new file mode 100644 index 0000000000000000000000000000000000000000..f2cacb89a83a664fcc3cb86768318118a6bbc74f --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_imh.mod @@ -0,0 +1,154 @@ +% ------------------------------------------------------------------------- +% Functionality testing of Bayesian IRF matching with +% - independent Metropolis-Hastings +% - more than one MCMC chains +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + +@#include "cet_model.inc" + +options_.prior_interval= 0.95; + +method_of_moments(mom_method = irf_matching +%, add_tiny_number_to_cholesky = 1e-14 +%, additional_optimizer_steps = [4] +%, aim_solver +%, analytic_jacobian +%, analytic_standard_errors +%, bartlett_kernel_lag +%, bounded_shock_support +%, brooks_gelman_plotrows +, cova_compute=0 +%, datafile +%, dirname=cet_imh_results +%, dr +%, dr_cycle_reduction_tol +%, dr_logarithmic_reduction_maxiter +%, dr_logarithmic_reduction_tol +%, drop +%, first_obs +%, geweke_interval +%, graph_format +%, huge_number +, irf_matching_file = cet_irf_matching_file +%, k_order_solver +%, load_mh_file +%, load_results_after_load_mh +%, logdata +%, lyapunov +%, lyapunov_complex_threshold +%, lyapunov_doubling_tol +%, lyapunov_fixed_point_tol +, mcmc_jumping_covariance = prior_variance +%, mh_conf_sig = 0.90 +%, mh_drop = 0.5 +%, mh_init_scale_factor +%, mh_initialize_from_previous_mcmc +%, mh_initialize_from_previous_mcmc_directory +%, mh_initialize_from_previous_mcmc_prior +%, mh_initialize_from_previous_mcmc_record +, mh_jscale = 0.5 +, mh_nblocks = 2 +%, mh_posterior_mode_estimation +%, mh_recover +, mh_replic=1000 +%, mh_tune_guess = 0.5 +%, mh_tune_jscale = 0.33 +%, mom_burnin +%, mom_seed +%, mom_se_tolx +%, mode_check +%, mode_check_neighbourhood_size +%, mode_check_number_of_points +%, mode_check_symmetric_plots = 0 +, mode_compute = 0 +, mode_file = cet_original_mode +%, nobs +%, no_posterior_kernel_density +%, nodiagnostic +, nodisplay +%, nograph +%, noprint +%, optim +%, order +, penalized_estimator +, plot_priors = 0 +%, posterior_max_subsample_draws +%, posterior_sampling_method = 'random_walk_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% , scale_file +% ) +%, posterior_sampling_method = 'tailored_random_block_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'new_block_probability',0.3 +% ,'mode_compute',1 +% ,optim +% ,'save_tmp_file',1 +% ,scale_file +% ) +, posterior_sampling_method = 'independent_metropolis_hastings' +, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' + ,'rand_multivariate_student' + ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ,scale_file + ) +%, posterior_sampling_method = 'slice' +%, posterior_sampler_options = ('rotated',1 +% ,'mode_files' +% ,'slice_initialize_with_mode',1 +% ,'initial_step_size',0.8 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ) +%, prefilter +%, prior_trunc +%, pruning +%, qz_criterium +%, qz_zero_threshold +%, raftery_lewis_diagnostics +%, raftery_lewis_qrs +%, relative_irf +%, replic +%, schur_vec_tol +%, silent_optimizer +%, simulation_method = stoch_simul +%, simulation_multiple +%, sub_draws +%, sylvester +%, sylvester_fixed_point_tol +%, taper_steps +%, tex +%, use_penalized_objective_for_hessian +%, verbose +%, weighting_matrix +%, weighting_matrix_scaling_factor +%, xls_range +%, xls_sheet +); \ No newline at end of file diff --git a/tests/estimation/method_of_moments/CET/cet_interface.mod b/tests/estimation/method_of_moments/CET/cet_interface.mod new file mode 100644 index 0000000000000000000000000000000000000000..c074da8400f21e8aaccad0076a8af897f6dc0b09 --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_interface.mod @@ -0,0 +1,183 @@ +% ------------------------------------------------------------------------- +% Functionality testing of interface for IRF matching +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + +@#include "cet_model.inc" +xx = [23,24,25]; +ww = [51,52]; + +matched_irfs(overwrite); +var GDPAGG; varexo epsR_eps; periods 5; values 7; weights 25; +var GDPAGG; varexo mupsi_eps; periods 1,2; values 17,18; weights 37,38; +var RAGG; varexo muz_eps; periods 3:5; values (xx); +var ukAGG; varexo mupsi_eps; periods 1:2; values 30; weights (ww); + +varexo epsR_eps; +var wAGG; +periods 1, 13:15, 2:12; +values 2, (xx), 15; +weights 3, (xx), 4; +end; + +method_of_moments(mom_method = irf_matching +, cova_compute=0 +, irf_matching_file = cet_irf_matching_file +, mcmc_jumping_covariance = prior_variance +, mh_jscale = 0.5 +, mh_nblocks = 1 +, mh_replic=1000 +, mode_compute = 0 +, mode_file = cet_original_mode +, plot_priors = 0 +, posterior_sampling_method = 'independent_metropolis_hastings' +); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% CHECKS ON INTERFACE AND TRANSFORMATIONS %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +verbatim; + +% check on matched_irfs +matched_irfs = [ + {'GDPAGG'} {'epsR_eps'} {[ {[5] [ 7] [25]} ]}; + {'GDPAGG'} {'mupsi_eps'} {[ {[1] [17] [37]}; + {[2] [18] [38]} ]}; + {'RAGG'} {'muz_eps'} {[ {[3 4 5] [23 24 25] [1]} ]}; + {'ukAGG'} {'mupsi_eps'} {[ {[1 2] [30] [51 52]} ]}; + {'wAGG'} {'epsR_eps'} {[ {[1] [2] [3]}; + {[13:15] [23 24 25] [23 24 25]}; + {[2:12] [15] [4]}; ]}; +]; +if ~isequal(M_.matched_irfs,matched_irfs) + error('Something wrong with the transformation of the matched_irfs block!') +else + fprintf('matched_irfs transformation was successful!\n\n') +end + +% check on data_moments +data_moments = [7 2 15 15 15 15 15 15 15 15 15 15 15 23 24 25 23 24 25 17 18 30 30]'; +if ~isequal(oo_.mom.data_moments,data_moments) + error('Something wrong with the creation of data_moments!') +else + fprintf('creation of data_moments was successful!\n\n') +end + +% check on weighting matrix +weighting_mat = sparse(size(data_moments,1)); +weighting_mat(1,1) = 25; +weighting_mat(2,2) = 3; +weighting_mat(3,3) = 4; +weighting_mat(4,4) = 4; +weighting_mat(5,5) = 4; +weighting_mat(6,6) = 4; +weighting_mat(7,7) = 4; +weighting_mat(8,8) = 4; +weighting_mat(9,9) = 4; +weighting_mat(10,10) = 4; +weighting_mat(11,11) = 4; +weighting_mat(12,12) = 4; +weighting_mat(13,13) = 4; +weighting_mat(14,14) = 23; +weighting_mat(15,15) = 24; +weighting_mat(16,16) = 25; +weighting_mat(17,17) = 1; +weighting_mat(18,18) = 1; +weighting_mat(19,19) = 1; +weighting_mat(20,20) = 37; +weighting_mat(21,21) = 38; +weighting_mat(22,22) = 51; +weighting_mat(23,23) = 52; +if ~isequal(oo_.mom.weighting_info.W,weighting_mat) + error('Something wrong with the creation of weighting_info.W!') +else + fprintf('creation of weighting_info.W was successful!\n\n') +end + +end;//verbatim + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% SIMPLIFIED EXAMPLE TO TEST INTERFACE ON WEIGHTING MATRIX %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +matched_irfs(overwrite); +var GDPAGG; varexo epsR_eps; periods 1 3; values 11 13; weights 111 222; +var RAGG; varexo muz_eps; periods 2 4; values 22 24; weights 333 444; +end; + +matched_irfs_weights(overwrite); +RAGG(2), muz_eps, GDPAGG(1), epsR_eps, 555; +GDPAGG(1), epsR_eps, RAGG(4), muz_eps, 666; +RAGG(2), muz_eps, GDPAGG(3), epsR_eps, 777; +GDPAGG(3), epsR_eps, RAGG(4), muz_eps, 888; +GDPAGG(1), epsR_eps, RAGG(1), muz_eps, 999; +end; + +verbatim; +% check on matched_irfs_weights +matched_irfs_weights = [ + {'GDPAGG'} {[1]} {'epsR_eps'} {'RAGG' } {[1]} {'muz_eps' } {[999]}; + {'GDPAGG'} {[1]} {'epsR_eps'} {'RAGG' } {[4]} {'muz_eps' } {[666]}; + {'GDPAGG'} {[3]} {'epsR_eps'} {'RAGG' } {[4]} {'muz_eps' } {[888]}; + {'RAGG' } {[2]} {'muz_eps' } {'GDPAGG'} {[1]} {'epsR_eps'} {[555]}; + {'RAGG' } {[2]} {'muz_eps' } {'GDPAGG'} {[3]} {'epsR_eps'} {[777]}; +]; +if ~isequal(M_.matched_irfs_weights,matched_irfs_weights) + error('Something wrong with the transformation of the matched_irfs_weights block!') +else + fprintf('matched_irfs_weights transformation was successful!\n\n') +end + +% test transformation function +[data_moments, W, irfIndex] = mom.matched_irfs_blocks(M_.matched_irfs, M_.matched_irfs_weights, options_mom_.varobs_id, length(options_mom_.varobs_id), M_.exo_nbr, M_.endo_names, M_.exo_names); + +if ~isequal(data_moments, [11 13 22 24]') + error('Something wrong with the creation of data_moments in simple example!'); +else + fprintf('simple example: creation of data_moments was successful!\n\n'); +end + +if ~isequal(irfIndex, [1 3 58 60]') + error('Something wrong with the creation of irfIndex in simple example!'); +else + fprintf('simple example: creation of irfIndex was successful!\n\n') +end + +W0 = eye(4); +W0(1,1) = 111; % (GDPAGG(1) epsR_eps) x (GDPAGG(1) epsR_eps) +W0(2,2) = 222; % (GDPAGG(3) epsR_eps) x (GDPAGG(3) epsR_eps) +W0(3,3) = 333; % (RAGG(2) muz_eps) x (RAGG(2) muz_eps) +W0(4,4) = 444; % (RAGG(4) muz_eps) x (RAGG(4) muz_eps) +W0(1,3) = 555; % (GDPAGG(1) epsR_eps) x (RAGG(2) muz_eps) +W0(3,1) = 555; % (RAGG(2) muz_eps) x (GDPAGG(1) epsR_eps) +W0(1,4) = 666; % (GDPAGG(1) epsR_eps) x (RAGG(4) muz_eps) +W0(4,1) = 666; % (RAGG(4) muz_eps) x (GDPAGG(1) epsR_eps) +W0(2,3) = 777; % (GDPAGG(3) epsR_eps) x (RAGG(2) muz_eps) +W0(3,2) = 777; % (RAGG(2) muz_eps) x (GDPAGG(3) epsR_eps) +W0(2,4) = 888; % (GDPAGG(3) epsR_eps) x (RAGG(4) muz_eps) +W0(4,2) = 888; % (RAGG(4) muz_eps) x (GDPAGG(3) epsR_eps) + +if ~isequal(W, W0) + error('Something wrong with the creation of W in simple example!') +else + fprintf('simple example: creation of W was successful!\n\n') +end +end; \ No newline at end of file diff --git a/tests/estimation/method_of_moments/CET/cet_irf_matching_file.m b/tests/estimation/method_of_moments/CET/cet_irf_matching_file.m new file mode 100644 index 0000000000000000000000000000000000000000..7d378894042a875fdd5f578c3600ac6aec5e87a1 --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_irf_matching_file.m @@ -0,0 +1,79 @@ +function [modelIrf, error_indicator] = cet_irf_matching_file(modelIrf, M_, options_mom_, ys_) +% [modelIrf, error_indicator] = cet_irf_matching_file(modelIrf, M_, options_mom_, ys_) +% ------------------------------------------------------------------------- +% This file manipulates model IRFs to be consistent with empirical IRFS +% ------------------------------------------------------------------------- +% INPUTS +% - modelIrf: [options_mom_.irf by M_.endo_nbr by M_.exo_nbr] +% array of IRFs for all model variables and all shocks +% - M_: [structure] Dynare model structure +% - options_mom_: [structure] Dynare options structure +% - ys_: [double] steady state values of all endogenous variables +% ------------------------------------------------------------------------- +% OUTPUTS +% - modelIrf: [options_mom_.irf by M_.endo_nbr by M_.exo_nbr] +% modified array of IRFs for all model variables and all shocks +% - error_indicator: [boolean] indicator of success (0) or failure (1) +% ------------------------------------------------------------------------- +% This function is called by +% - mom.run +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + +% initialize error indicator +error_indicator = 0; + +% get indices of variables +idmuF = ismember(M_.endo_names,'muF'); +idmupsiF = ismember(M_.endo_names,'mupsiF'); +idGDPAGG = ismember(M_.endo_names,'GDPAGG'); +idpiAGG = ismember(M_.endo_names,'piAGG'); +idRAGG = ismember(M_.endo_names,'RAGG'); +idukAGG = ismember(M_.endo_names,'ukAGG'); +idlAGG = ismember(M_.endo_names,'lAGG'); +idwAGG = ismember(M_.endo_names,'wAGG'); +idcAGG = ismember(M_.endo_names,'cAGG'); +idiAGG = ismember(M_.endo_names,'iAGG'); +idpinvestAGG = ismember(M_.endo_names,'pinvestAGG'); +idpunempAGG = ismember(M_.endo_names,'unempAGG'); +idvTotAGG = ismember(M_.endo_names,'vTotAGG'); +idfAGG = ismember(M_.endo_names,'fAGG'); + +modelIrf = 100.*modelIrf; % convert to percent deviations +for jexo=1:M_.exo_nbr + if jexo==1 + mulev_vec = 0; + mupsilev_vec = 0; + else + mulev_vec = cumsum(modelIrf(:,idmuF,jexo)); + mupsilev_vec = cumsum(modelIrf(:,idmupsiF,jexo)); + end + modelIrf(:,idGDPAGG,jexo) = modelIrf(:,idGDPAGG,jexo) + mulev_vec; % gdp = GDPAGG + cumsum(muF) + modelIrf(:,idpiAGG,jexo) = modelIrf(:,idpiAGG,jexo); % inflation = piAGG + modelIrf(:,idRAGG,jexo) = modelIrf(:,idRAGG,jexo); % Nominal interest rate = RAGG + modelIrf(:,idukAGG,jexo) = modelIrf(:,idukAGG,jexo); % capital utilization = ukAGG + modelIrf(:,idlAGG,jexo) = modelIrf(:,idlAGG,jexo); % labor = lAGG + modelIrf(:,idwAGG,jexo) = modelIrf(:,idwAGG,jexo) + mulev_vec; % real wage = wAGG + cumsum(muF) + modelIrf(:,idcAGG,jexo) = modelIrf(:,idcAGG,jexo) + mulev_vec; % consumption = cAGG + cumsum(muF) + modelIrf(:,idiAGG,jexo) = modelIrf(:,idiAGG,jexo) + mulev_vec + mupsilev_vec; % investment = iAGG + cumsum(muF) + cumsum(mupsiF) + modelIrf(:,idpinvestAGG,jexo) = cumsum(modelIrf(:,idpinvestAGG,jexo)); % rel. price investment = cumsum(pinvestAGG) + modelIrf(:,idpunempAGG,jexo) = modelIrf(:,idpunempAGG,jexo)*M_.params(ismember(M_.param_names,'u')); % vacancies = vTotAGG*u + modelIrf(:,idvTotAGG,jexo) = modelIrf(:,idvTotAGG,jexo); % aggregated total vacancies = vTotAGG + modelIrf(:,idfAGG,jexo) = modelIrf(:,idfAGG,jexo)*M_.params(ismember(M_.param_names,'f')); % job finding rate = fAGG*f +end \ No newline at end of file diff --git a/tests/estimation/method_of_moments/CET/cet_mle.mod b/tests/estimation/method_of_moments/CET/cet_mle.mod new file mode 100644 index 0000000000000000000000000000000000000000..a05a44b0ebb368cee1cfffa94f74d8ba9a63004e --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_mle.mod @@ -0,0 +1,153 @@ +% ------------------------------------------------------------------------- +% Functionality testing of Frequentist IRF matching +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + +@#define ML = 1 +@#include "cet_model.inc" + +options_.prior_interval= 0.95; + +method_of_moments(mom_method = irf_matching +%, add_tiny_number_to_cholesky = 1e-14 +%, additional_optimizer_steps = [4] +%, aim_solver +%, analytic_jacobian +%, analytic_standard_errors +%, bartlett_kernel_lag +%, bounded_shock_support +%, brooks_gelman_plotrows +%, cova_compute=0 +%, datafile +%, dirname=cet_imh_results +%, dr +%, dr_cycle_reduction_tol +%, dr_logarithmic_reduction_maxiter +%, dr_logarithmic_reduction_tol +%, drop +%, first_obs +%, geweke_interval +%, graph_format +%, huge_number +, irf_matching_file = cet_irf_matching_file +%, k_order_solver +%, load_mh_file +%, load_results_after_load_mh +%, logdata +%, lyapunov +%, lyapunov_complex_threshold +%, lyapunov_doubling_tol +%, lyapunov_fixed_point_tol +%, mcmc_jumping_covariance = prior_variance +%, mh_conf_sig = 0.90 +%, mh_drop = 0.5 +%, mh_init_scale_factor +%, mh_initialize_from_previous_mcmc +%, mh_initialize_from_previous_mcmc_directory +%, mh_initialize_from_previous_mcmc_prior +%, mh_initialize_from_previous_mcmc_record +%, mh_jscale = 0.5 +%, mh_nblocks = 2 +%, mh_posterior_mode_estimation +%, mh_recover +%, mh_replic=1000 +%, mh_tune_guess = 0.5 +%, mh_tune_jscale = 0.33 +%, mom_burnin +%, mom_seed +%, mom_se_tolx +%, mode_check +%, mode_check_neighbourhood_size +%, mode_check_number_of_points +%, mode_check_symmetric_plots = 0 +, mode_compute = 4 +%, mode_file = cet_original_mode +%, nobs +%, no_posterior_kernel_density +%, nodiagnostic +%, nodisplay +%, nograph +%, noprint +%, optim +%, order +%, penalized_estimator +%, plot_priors = 0 +%, posterior_max_subsample_draws +%, posterior_sampling_method = 'random_walk_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% , scale_file +% ) +%, posterior_sampling_method = 'tailored_random_block_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'new_block_probability',0.3 +% ,'mode_compute',1 +% ,optim +% ,'save_tmp_file',1 +% ,scale_file +% ) +%, posterior_sampling_method = 'independent_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ,scale_file +% ) +%, posterior_sampling_method = 'slice' +%, posterior_sampler_options = ('rotated',1 +% ,'mode_files' +% ,'slice_initialize_with_mode',1 +% ,'initial_step_size',0.8 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ) +%, prefilter +%, prior_trunc +%, pruning +%, qz_criterium +%, qz_zero_threshold +%, raftery_lewis_diagnostics +%, raftery_lewis_qrs +%, relative_irf +%, replic +%, schur_vec_tol +%, silent_optimizer +, simulation_method = stoch_simul +%, simulation_multiple +%, sub_draws +%, sylvester +%, sylvester_fixed_point_tol +%, taper_steps +%, tex +%, use_penalized_objective_for_hessian +%, verbose +%, weighting_matrix +%, weighting_matrix_scaling_factor +%, xls_range +%, xls_sheet +); \ No newline at end of file diff --git a/tests/estimation/method_of_moments/CET/cet_model.inc b/tests/estimation/method_of_moments/CET/cet_model.inc new file mode 100644 index 0000000000000000000000000000000000000000..3e19aed60eae8aa5fbb069c496d92ff6120c68cd --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_model.inc @@ -0,0 +1,844 @@ +/* + * Model codes kindly provided by Mathias Trabandt, modified to work with + * Parameters here are set such that the AOB Model is active. + * + * Please note that the following copyright notice only applies to this Dynare + * implementation of the model. + */ + +/* + * Copyright © 2023 Dynare Team + * + * This 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. + * + * It 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. + * + * For a copy of the GNU General Public License, + * see <https://www.gnu.org/licenses/>. + */ + + +/* + * Wanted: monetary policy shock is not in period t information set of agents + * (just as in VAR identified with Choleski decomp.) + * All other shocks are in period t information set. + * Solution: create two parallel economies which are structurally identical. + * One which is subject to the monetary shock only. + * This shock is not in period t info set. + * The other economy has the other shocks with the standard info set. + * Naming convention: variables ending with 'F' are in the economy with full info set + * variables ending with 'R' are in the restricted info set economy + * variables ending with 'AGG' are aggregated variables from both economies + * Note that in the 'R' economy, all exogenous variables are set to their steady states, except the monetary shock + * Likewise, in the 'F' economy, the monetary shock is set to zero while all other shocks are active + * Both steady states (i.e. 'R' and 'F' economy) are identical + * All variables are in logs + */ + +// Endogenous variables (R economy) +var +wpR wpF wR wF psiR cR RR piR iR pkprimeR FR KR ukR +kbarR lR xR varthetR phaloR yR JR UR GDPR fR vR +unempR VR AAR vTotR QR piwR whaloR FwR KwR +varthetpR +; + +// Endogenous variables (F economy) +var +psiF cF RF piF iF pkprimeF FF KF ukF +kbarF lF xF varthetF phaloF yF JF UF GDPF fF +vF unempF VF AAF vTotF QF piwF whaloF FwF KwF +muzF mupsiF muF nGF nPHIF nGAMF nDF nKAPF +varthetpF +; + +// Endogenous variables (AGG economy) +var +GDPAGG piAGG RAGG ukAGG lAGG wAGG cAGG +iAGG unempAGG vTotAGG fAGG pinvestAGG +; + +// Shocks +varexo +epsR_eps muz_eps mupsi_eps +; + +parameters +ydiffdataPercent,idiffdataPercent,alfa,rho,u,Q,sigm, +betta,lambda,deltak,tau,nuf,etag,kappa,b,xi,D,delta,gamma,Spp +sigmab sigmaa phi rhoR rpi ry sig_epsR sigmam kappaf DSHARE deltapercent +recSHAREpercent iota doNash eta doEHL xiw lambdaw AEHL +f rhomupsi rhomuz sig_mupsi sig_muz thetaG thetaPHI thetaKAP thetaD +dolagZBAR profy varkappaw pibreve thetaw varkappaf M sigmaL +tau_SS epsilon_SS upsilon_SS zetac_SS g_SS pibar thetaGAM kappaw +unemp_SS vTot_SS alp1 alp2 alp3 alp4 bet1 bet2 bet3 s searchSHAREpercent +; + +model; + +// auxiliary equations for R economy such that current realization fo monetary policy shock is not in information set +//information set in line with Choleski decomposition in VAR +//set exogenous variables to steady states (except monetary shock, of course) +#epsilonR=epsilon_SS; +#upsilonR=upsilon_SS; +#upsilonR_tp1=upsilon_SS; +#zetacR=zetac_SS; +#zetacR_tp1=zetac_SS; +#gR=g_SS; +#tauR=tau_SS; +#mupsiR=STEADY_STATE(mupsiF); +#mupsiR_tp1=STEADY_STATE(mupsiF); +#muzR=STEADY_STATE(muzF); +#muR=alfa/(1-alfa)*STEADY_STATE(mupsiF)+STEADY_STATE(muzF); +#muR_tp1=STEADY_STATE(muF); +#nGR=STEADY_STATE(nGF); +#nPHIR=STEADY_STATE(nPHIF); +#nGAMR=STEADY_STATE(nGAMF); +#nDR=STEADY_STATE(nDF); +#nKAPR=STEADY_STATE(nKAPF); + +//conditional expectations based on t-1 info; +#piR_tp1=EXPECTATION(-1)(piR(+1)); +#FR_tp1=EXPECTATION(-1)(FR(+1)); +#KR_tp1=EXPECTATION(-1)(KR(+1)); +#cR_tp1=EXPECTATION(-1)(cR(+1)); +#psiR_tp1=EXPECTATION(-1)(psiR(+1)); +#pkprimeR_tp1=EXPECTATION(-1)(pkprimeR(+1)); +#iR_tp1=EXPECTATION(-1)(iR(+1)); +#UR_tp1=EXPECTATION(-1)(UR(+1)); +#fR_tp1=EXPECTATION(-1)(fR(+1)); +#wR_tp1=EXPECTATION(-1)(wR(+1)); +#VR_tp1=EXPECTATION(-1)(VR(+1)); +#ukR_tp1=EXPECTATION(-1)(ukR(+1)); +#piwR_tp1=EXPECTATION(-1)(piwR(+1)); +#KwR_tp1=EXPECTATION(-1)(KwR(+1)); +#FwR_tp1=EXPECTATION(-1)(FwR(+1)); +#wpR_tp1=EXPECTATION(-1)(wpR(+1)); +#varthetpR_tp1=EXPECTATION(-1)(varthetpR(+1)); +#AAR_tp1=EXPECTATION(-1)(AAR(+1)); +#RRinfo=EXPECTATION(-1)(RR); + +// abbreviations +#aofukprimeR=sigmab*sigmaa*(exp(ukR))+sigmab*(1-sigmaa); +#aofukprimeR_tp1=sigmab*sigmaa*(exp(ukR_tp1))+sigmab*(1-sigmaa); +#aofukR=0.5*sigmab*sigmaa*(exp(ukR))^2+sigmab*(1-sigmaa)*exp(ukR)+sigmab*((sigmaa/2)-1); +#aofukR_tp1=0.5*sigmab*sigmaa*(exp(ukR_tp1))^2+sigmab*(1-sigmaa)*exp(ukR_tp1)+sigmab*((sigmaa/2)-1); +#RkR_tp1=log(((exp(ukR_tp1)*aofukprimeR_tp1-aofukR_tp1)+(1-deltak)*exp(pkprimeR_tp1))/(exp(pkprimeR+mupsiR_tp1-piR_tp1))); +#StildeR=(0.5*(exp(sqrt(Spp)*(exp(iR)/exp(iR(-1))*exp(muR)*exp(mupsiR)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF))))+exp(-sqrt(Spp)*(exp(iR)/exp(iR(-1))*exp(muR)*exp(mupsiR)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF))))-2)); +#StildeprimeR=(0.5*sqrt(Spp)*(exp(sqrt(Spp)*(exp(iR)/exp(iR(-1))*exp(muR)*exp(mupsiR)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF))))-exp(-sqrt(Spp)*(exp(iR)/exp(iR(-1))*exp(muR)*exp(mupsiR)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF)))))); +#StildeprimeR_tp1=(0.5*sqrt(Spp)*(exp(sqrt(Spp)*(exp(iR_tp1)/exp(iR)*exp(muR_tp1)*exp(mupsiR_tp1)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF))))-exp(-sqrt(Spp)*(exp(iR_tp1)/exp(iR)*exp(muR_tp1)*exp(mupsiR_tp1)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF)))))); +#mcR=tauR+alfa*mupsiR+( (1-doEHL)*varthetR+doEHL*wR) +log(nuf*(exp(RRinfo))+1-nuf)-epsilonR-log(1-alfa)-alfa*(kbarR(-1)+ukR-muR-lR-(doEHL*(lambdaw/(lambdaw-1))*whaloR) ); +#pitildewpiR=-piwR+kappaw*piR(-1)+(1-kappaw-varkappaw)*log(pibar)+varkappaw*log(pibreve)+thetaw*STEADY_STATE(muF); +#pitildewpiR_tp1=-piwR_tp1+kappaw*piR+(1-kappaw-varkappaw)*log(pibar)+varkappaw*log(pibreve)+thetaw*STEADY_STATE(muF); +#pitildepiR=-piR+kappaf*piR(-1)+(1-kappaf-varkappaf)*log(pibar)+varkappaf*log(pibreve); +#pitildepiR_tp1=-piR_tp1+kappaf*piR+(1-kappaf-varkappaf)*log(pibar)+varkappaf*log(pibreve); + +//R1 - Consumption FOC +exp(psiR)=exp(zetacR)/(exp(cR)-b*exp(cR(-1))/exp(muR))-betta*b*(exp(zetacR_tp1)/ +(exp(cR_tp1)*exp(muR_tp1)-b*exp(cR))); + +//R2 - Bond FOC (Fisher equation) +exp(psiR)=betta*exp(psiR_tp1)/exp(muR_tp1)*exp(RRinfo)/exp(piR_tp1); + +//R3 - Investment FOC +1=exp(pkprimeR)*exp(upsilonR)*(1-StildeR-StildeprimeR*exp(muR)*exp(mupsiR)*exp(iR)/exp(iR(-1)))+betta*exp(psiR_tp1)/exp(psiR)*exp(pkprimeR_tp1)*exp(upsilonR_tp1)*StildeprimeR_tp1*(exp(iR_tp1)/exp(iR))^2*exp(muR_tp1)*exp(mupsiR_tp1); + +//R4 - Capital FOC +1=betta*exp(psiR_tp1-psiR+RkR_tp1-muR_tp1-piR_tp1); + +//R5 - Law of motion for physical capital +exp(kbarR)=(1-deltak)/(exp(muR)*exp(mupsiR))*exp(kbarR(-1))+exp(upsilonR)*(1-StildeR)*exp(iR); + +//R6 - Cost minimization (opt. factor inputs) +0=aofukprimeR*exp(ukR)*exp(kbarR(-1))/(exp(muR)*exp(mupsiR))-alfa/(1-alfa)*(nuf*exp(RRinfo)+1-nuf)*exp(lR)*((1-doEHL)*(exp(varthetR))+doEHL*( exp(wR)*(exp(whaloR))^(lambdaw/(lambdaw-1)))); + +//R7 - Production +exp(yR)=exp(phaloR)^(lambda/(lambda-1))*(exp(epsilonR)*((doEHL*exp(whaloR)^(lambdaw/(lambdaw-1))+(1-doEHL)*1)*exp(lR))^(1-alfa)* + (exp(kbarR(-1)+ukR)/(exp(muR)*exp(mupsiR)))^alfa-phi*exp(nPHIR)); + +//R8 - Resource Constraint +exp(yR)=exp(gR)*exp(nGR)+exp(cR)+exp(iR)+aofukR*exp(kbarR(-1))/(exp(mupsiR)*exp(muR)) + +(1-doEHL)*( s*exp(nKAPR)*exp(xR)/exp(QR)*exp(lR(-1)) + kappa*exp(nKAPR)*exp(xR)*exp(lR(-1)) ); + +//R9 Monetary Policy Rule +RR=rhoR*RR(-1)+(1-rhoR)*(STEADY_STATE(RR)+rpi*(piR-STEADY_STATE(piF))+ry*(GDPR-STEADY_STATE(GDPF)))-sig_epsR*epsR_eps/400; + +//R10 Pricing 1 +exp(FR)-exp(psiR+yR)-betta*xi*exp( pitildepiR_tp1 /(1-lambda)+FR_tp1); + +//R11 Pricing 2 +exp(KR)-lambda*exp(psiR+yR+mcR)-betta*xi*exp( pitildepiR_tp1 *lambda/(1-lambda)+KR_tp1); + +//R12 Pricing 3 +KR-FR=(1-lambda)*log((1-xi*exp( pitildepiR /(1-lambda)))/(1-xi)); + +//R13 Price dispersion +exp(phaloR*lambda/(1-lambda))-(1-xi)^(1-lambda)*(1-xi*exp( pitildepiR /(1-lambda)))^lambda + -xi*(exp( pitildepiR +phaloR(-1)))^(lambda/(1-lambda)); + +//R14 Present value of wages +doEHL*(exp(wpR)-exp(STEADY_STATE(wpF)))=(1-doEHL)*(-exp(wpR)+exp(wR)+rho*betta*exp(psiR_tp1)/exp(psiR)*exp(wpR_tp1)); + +//R15 Present value of marginal revenue +doEHL*(exp(varthetpR)-exp(STEADY_STATE(varthetpF)))=(1-doEHL)*(-exp(varthetpR)+exp(varthetR)+rho*betta*exp(psiR_tp1)/exp(psiR)*exp(varthetpR_tp1)); + +//R16 Hiring FOC - zero profit/free entry condition +doEHL*(exp(xR)-exp(STEADY_STATE(xF)))=(1-doEHL)*( -s*exp(nKAPR)/exp(QR) -kappa*exp(nKAPR) + exp(JR) ); + +//R17 Value of firm +doEHL*(exp(JR)-exp(STEADY_STATE(JF)))=(1-doEHL)*(-exp(JR)+exp(varthetpR)-exp(wpR)); + +//R18 Value of work +doEHL*(exp(VR)-exp(STEADY_STATE(VF)))=(1-doEHL)*(-exp(VR)+exp(wpR)+exp(AAR)); + +//R19 Present value of worker payoff after separation +doEHL*(exp(AAR)-exp(STEADY_STATE(AAF)))=(1-doEHL)*(-exp(AAR)+(1-rho)*betta*exp(psiR_tp1)/exp(psiR)*(exp(fR_tp1)*exp(VR_tp1) ++(1-exp(fR_tp1))*exp(UR_tp1))+rho*betta*exp(psiR_tp1)/exp(psiR)*exp(AAR_tp1)); + +//R20 Unemployment value +doEHL*(exp(UR)-exp(STEADY_STATE(UF)))=(1-doEHL)*(-exp(UR)+D*exp(nDR)+betta*exp(psiR_tp1)/exp(psiR)*(exp(fR_tp1)*exp(VR_tp1)+(1-exp(fR_tp1))*exp(UR_tp1))); + +//R21 Sharing rule +doEHL*(exp(varthetR)-STEADY_STATE(exp(varthetF)))=(1-doEHL)*(doNash*(exp(VR)-exp(UR)-eta*(exp(JR)+exp(VR)-exp(UR)))+(1-doNash)*( + +-exp(JR)+bet1*(exp(VR)-exp(UR))-bet2*exp(nGAMR)*gamma+bet3*(exp(varthetR)-exp(nDR)*D) + +)); + +//R22 GDP +exp(GDPR)=exp(gR)*exp(nGR)+exp(cR)+exp(iR); + +//R23 Unempl. rate +doEHL*(exp(unempR)-exp(STEADY_STATE(unempF)))=(1-doEHL)*(-exp(unempR)+1-exp(lR)); + +//R24 Job finding rate +doEHL*(exp(fR)-exp(STEADY_STATE(fF)))=(1-doEHL)*(-exp(fR)+exp(xR)*exp(lR(-1))/(1-rho*exp(lR(-1)))); + +//R25 Matching function +doEHL*(exp(vTotR)-exp(STEADY_STATE(vTotF)))=(1-doEHL)*(-exp(xR)*exp(lR(-1))+sigmam*(1-rho*exp(lR(-1)))^sigm*(exp(vTotR))^(1-sigm)); + +//R26 Total vacancies +doEHL*(exp(vR)-exp(STEADY_STATE(vF)))=(1-doEHL)*(-exp(vTotR)+exp(vR)*exp(lR(-1))); + +//R27 Vacancy filling rate +doEHL*(exp(QR)-exp(STEADY_STATE(QF)))=(1-doEHL)*(-exp(QR)+exp(xR)/exp(vR)); + +//R28 Wage inflation (EHL) +exp(piwR)=exp(piR)*exp(muR)*exp(wR)/exp(wR(-1)); + +//R29 Wage dispersion +doEHL*(exp(whaloR*lambdaw/(1-lambdaw))-(1-xiw)^(1-lambdaw)*(1-xiw*exp(pitildewpiR/(1-lambdaw)))^lambdaw + -xiw*(exp(pitildewpiR+whaloR(-1)))^(lambdaw/(1-lambdaw)))=(1-doEHL)*(exp(whaloR)-exp(STEADY_STATE(whaloF))); + +//R30 wage setting 1 (EHL) +doEHL*(-exp(FwR) + exp(psiR)/lambdaw*exp(whaloR)^( lambdaw/(lambdaw-1))*exp(lR) + betta*xiw*(exp(wR_tp1)/exp(wR))*(exp(pitildewpiR_tp1))^( 1/(1-lambdaw) )*exp(FwR_tp1)) +=(1-doEHL)*(exp(FwR)-exp(STEADY_STATE(FwF))); + +//R31 Law of motion of employment or EHL wage setting 2 +doEHL*(-exp(KwR) + ( exp(whaloR)^( lambdaw/(lambdaw-1))*exp(lR))^(1+sigmaL) + betta*xiw*(exp(pitildewpiR_tp1))^( lambdaw*(1+sigmaL)/(1-lambdaw) )*exp(KwR_tp1)) +=(1-doEHL)*(-exp(lR)+(rho+exp(xR))*exp(lR(-1))); + +//R32 wage setting 3 (EHL) +doEHL*(1-(1-xiw)*(AEHL*exp(KwR)/(exp(FwR)*exp(wR)))^( 1/( 1-lambdaw*(1+sigmaL) )) - xiw*(exp(pitildewpiR))^(1/(1-lambdaw)))=(1-doEHL)*(exp(KwR)-exp(STEADY_STATE(KwF))); + +////////////////////////////////////////////////////////////////////// +//F economy, other shocks, current realization in info set /////////// +////////////////////////////////////////////////////////////////////// +//set not needed exogenous variables to steady states +#tauF=tau_SS; +#upsilonF=upsilon_SS; +#upsilonF_tp1=upsilon_SS; +#epsilonF=epsilon_SS; +#zetacF=zetac_SS; +#zetacF_tp1=zetac_SS; +#gF=g_SS; + +//abbreviations +#aofukprimeF=sigmab*sigmaa*(exp(ukF))+sigmab*(1-sigmaa); +#aofukprimeF_tp1=sigmab*sigmaa*(exp(ukF(+1)))+sigmab*(1-sigmaa); +#aofukF=0.5*sigmab*sigmaa*(exp(ukF))^2+sigmab*(1-sigmaa)*exp(ukF)+sigmab*((sigmaa/2)-1); +#aofukF_tp1=0.5*sigmab*sigmaa*(exp(ukF(+1)))^2+sigmab*(1-sigmaa)*exp(ukF(+1))+sigmab*((sigmaa/2)-1); +#RkF_tp1=log(((exp(ukF(+1))*aofukprimeF_tp1-aofukF_tp1)+(1-deltak)*exp(pkprimeF(+1)))/(exp(pkprimeF+mupsiF(+1)-piF(+1)))); +#StildeF=(0.5*(exp(sqrt(Spp)*(exp(iF)/exp(iF(-1))*exp(muF)*exp(mupsiF)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF))))+exp(-sqrt(Spp)*(exp(iF)/exp(iF(-1))*exp(muF)*exp(mupsiF)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF))))-2)); +#StildeprimeF=(0.5*sqrt(Spp)*(exp(sqrt(Spp)*(exp(iF)/exp(iF(-1))*exp(muF)*exp(mupsiF)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF))))-exp(-sqrt(Spp)*(exp(iF)/exp(iF(-1))*exp(muF)*exp(mupsiF)-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF)))))); +#StildeprimeF_tp1=(0.5*sqrt(Spp)*(exp(sqrt(Spp)*(exp(iF(+1))/exp(iF)*exp(muF(+1))*exp(mupsiF(+1))-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF))))-exp(-sqrt(Spp)*(exp(iF(+1))/exp(iF)*exp(muF(+1))*exp(mupsiF(+1))-exp(STEADY_STATE(muF))*exp(STEADY_STATE(mupsiF)))))); +#mcF=tauF+alfa*mupsiF+( (1-doEHL)*varthetF+doEHL*wF) +log(nuf*(exp(RF))+1-nuf)-epsilonF-log(1-alfa)-alfa*(kbarF(-1)+ukF-muF-lF-(doEHL*(lambdaw/(lambdaw-1))*whaloF) ); +#pitildewpiF=-piwF+kappaw*piF(-1)+(1-kappaw-varkappaw)*log(pibar)+varkappaw*log(pibreve)+thetaw*STEADY_STATE(muF); +#pitildewpiF_tp1=-piwF(+1)+kappaw*piF+(1-kappaw-varkappaw)*log(pibar)+varkappaw*log(pibreve)+thetaw*STEADY_STATE(muF); +#pitildepiF=-piF+kappaf*piF(-1)+(1-kappaf-varkappaf)*log(pibar)+varkappaf*log(pibreve); +#pitildepiF_tp1=-piF(+1)+kappaf*piF+(1-kappaf-varkappaf)*log(pibar)+varkappaf*log(pibreve); + +//F1 - Consumption FOC +exp(psiF)=exp(zetacF)/(exp(cF)-b*exp(cF(-1))/exp(muF))-betta*b*(exp(zetacF_tp1)/ +(exp(cF(+1))*exp(muF(+1))-b*exp(cF))); + +//F2 - Bond FOC (Fisher equation) +exp(psiF)=betta*exp(psiF(+1))/exp(muF(+1))*exp(RF)/exp(piF(+1)); + +//F3 - Investment FOC +1=exp(pkprimeF)*exp(upsilonF)*(1-StildeF-StildeprimeF*exp(muF)*exp(mupsiF)*exp(iF)/exp(iF(-1)))+betta*exp(psiF(+1))/exp(psiF)*exp(pkprimeF(+1))*exp(upsilonF_tp1)*StildeprimeF_tp1*(exp(iF(+1))/exp(iF))^2*exp(muF(+1))*exp(mupsiF(+1)); + +//F4 - Capital FOC +1=betta*exp(psiF(+1)-psiF+RkF_tp1-muF(+1)-piF(+1)); + +//F5 - Law of motion for physical capital +exp(kbarF)=(1-deltak)/(exp(muF)*exp(mupsiF))*exp(kbarF(-1))+exp(upsilonF)*(1-StildeF)*exp(iF); + +//F6 - Cost minimization (opt. factor inputs) +0=aofukprimeF*exp(ukF)*exp(kbarF(-1))/(exp(muF)*exp(mupsiF))-alfa/(1-alfa)*(nuf*exp(RF)+1-nuf)*exp(lF)*((1-doEHL)*(exp(varthetF))+doEHL*( exp(wF)*(exp(whaloF))^(lambdaw/(lambdaw-1)))); + +//F7 - Production +exp(yF)=exp(phaloF)^(lambda/(lambda-1))*(exp(epsilonF)*( (doEHL*exp(whaloF)^(lambdaw/(lambdaw-1))+(1-doEHL)*1)*exp(lF) )^(1-alfa)* + (exp(kbarF(-1)+ukF)/(exp(muF)*exp(mupsiF)))^alfa-phi*exp(nPHIF)); + +//F8 - Resource Constraint +exp(yF)=exp(gF)*exp(nGF)+exp(cF)+exp(iF)+aofukF*exp(kbarF(-1))/(exp(mupsiF)*exp(muF)) + +(1-doEHL)*( s*exp(nKAPF)*exp(xF)/exp(QF)*exp(lF(-1)) + kappa*exp(nKAPF)*exp(xF)*exp(lF(-1)) ); + + +//F9 Monetary Policy Rule +RF=rhoR*RF(-1)+(1-rhoR)*(STEADY_STATE(RF)+rpi*(piF-STEADY_STATE(piF))+ry*(GDPF-STEADY_STATE(GDPF))); + +//F10 Pricing 1 +exp(FF)-exp(psiF+yF)-betta*xi*exp( pitildepiF_tp1 /(1-lambda)+FF(+1)); + +//F11 Pricing 2 +exp(KF)-lambda*exp(psiF+yF+mcF)-betta*xi*exp( pitildepiF_tp1*lambda/(1-lambda)+KF(+1)); + +//F12 Pricing 3 +KF-FF=(1-lambda)*log((1-xi*exp( pitildepiF /(1-lambda)))/(1-xi)); + +//F13 Price dispersion +exp(phaloF*lambda/(1-lambda))-(1-xi)^(1-lambda)*(1-xi*exp( pitildepiF /(1-lambda)))^lambda + -xi*(exp( pitildepiF +phaloF(-1)))^(lambda/(1-lambda)); + +//F14 Present value of wages +doEHL*(exp(wpF)-STEADY_STATE(exp(wpF)))=(1-doEHL)*(-exp(wpF)+exp(wF)+rho*betta*exp(psiF(+1))/exp(psiF)*exp(wpF(+1))); + +//F15 Present value of marginal revenue +doEHL*(exp(varthetpF)-STEADY_STATE(exp(varthetpF)))=(1-doEHL)*(-exp(varthetpF)+exp(varthetF)+rho*betta*exp(psiF(+1))/exp(psiF)*exp(varthetpF(+1))); + +//F16 Hiring FOC - zero profit/free entry condition +doEHL*(exp(xF)-exp(STEADY_STATE(xF)))=(1-doEHL)*( -s*exp(nKAPF)/exp(QF) - kappa*exp(nKAPF) + exp(JF) ); + +//F17 Firm surplus +doEHL*(exp(JF)-STEADY_STATE(exp(JF)))=(1-doEHL)*(-exp(JF)+exp(varthetpF)-exp(wpF)); + +//F18 Value of work +doEHL*(exp(VF)-exp(STEADY_STATE(VF)))=(1-doEHL)*(-exp(VF)+exp(wpF)+exp(AAF)); + +//F19 Present value of worker payoff after separation +doEHL*(exp(AAF)-exp(STEADY_STATE(AAF)))=(1-doEHL)*(-exp(AAF)+(1-rho)*betta*exp(psiF(+1))/exp(psiF)*(exp(fF(+1))*exp(VF(+1))+(1-exp(fF(+1)))*exp(UF(+1)))+rho*betta*exp(psiF(+1))/exp(psiF)*exp(AAF(+1))); + +//F20 Unempoyment value +doEHL*(exp(UF)-exp(STEADY_STATE(UF)))=(1-doEHL)*(-exp(UF)+D*exp(nDF)+betta*exp(psiF(+1))/exp(psiF)*(exp(fF(+1))*exp(VF(+1))+(1-exp(fF(+1)))*exp(UF(+1)))); + +//R21 Sharing rule +doEHL*(exp(varthetF)-STEADY_STATE(exp(varthetF)))=(1-doEHL)*(doNash*(exp(VF)-exp(UF)-eta*(exp(JF)+exp(VF)-exp(UF)))+(1-doNash)*( + +-exp(JF)+bet1*(exp(VF)-exp(UF))-bet2*exp(nGAMF)*gamma+bet3*(exp(varthetF)-exp(nDF)*D) + +)); + +//F22 GDP +exp(GDPF)=exp(gF)*exp(nGF)+exp(cF)+exp(iF); + +//F23 Unempl. rate +doEHL*(exp(unempF)-exp(STEADY_STATE(unempF)))=(1-doEHL)*(-exp(unempF)+1-exp(lF)); + +//F24 Finding rate +doEHL*(exp(fF)-exp(STEADY_STATE(fF)))=(1-doEHL)*(-exp(fF)+exp(xF)*exp(lF(-1))/(1-rho*exp(lF(-1)))); + +//F25 Matching function +doEHL*(exp(vTotF)-exp(STEADY_STATE(vTotF)))=(1-doEHL)*(-exp(xF)*exp(lF(-1))+sigmam*(1-rho*exp(lF(-1)))^sigm*(exp(vTotF))^(1-sigm)); + +//F26 Total vacancies +doEHL*(exp(vF)-exp(STEADY_STATE(vF)))=(1-doEHL)*(-exp(vTotF)+exp(vF)*exp(lF(-1))); + +//F27 Vacancy filling rate +doEHL*(exp(QF)-exp(STEADY_STATE(QF)))=(1-doEHL)*(-exp(QF)+exp(xF)/exp(vF)); + +//F28 Wage inflation +exp(piwF)=exp(piF)*exp(muF)*exp(wF)/exp(wF(-1)); + +//F29 Wage dispersion +doEHL*(exp(whaloF*lambdaw/(1-lambdaw))-(1-xiw)^(1-lambdaw)*(1-xiw*exp(pitildewpiF/(1-lambdaw)))^lambdaw + -xiw*(exp(pitildewpiF+whaloF(-1)))^(lambdaw/(1-lambdaw)))=(1-doEHL)*(exp(whaloF)-exp(STEADY_STATE(whaloF))); + +//F30 wage setting 1 (EHL) +doEHL*(-exp(FwF) + exp(psiF)/lambdaw*exp(whaloF)^( lambdaw/(lambdaw-1))*exp(lF) + betta*xiw*(exp(wF(+1))/exp(wF))*(exp(pitildewpiF_tp1))^( 1/(1-lambdaw) )*exp(FwF(+1)) ) +=(1-doEHL)*(exp(FwF)-exp(STEADY_STATE(FwF))); + +//F31 Law of motion of employment or EHL wage setting 2 +doEHL*(-exp(KwF) + ( exp(whaloF)^( lambdaw/(lambdaw-1))*exp(lF))^(1+sigmaL) + betta*xiw*( exp(pitildewpiF_tp1) )^( lambdaw*(1+sigmaL)/(1-lambdaw) )*exp(KwF(+1))) +=(1-doEHL)*(-exp(lF)+(rho+exp(xF))*exp(lF(-1))); + +//F32 wage setting 3 (EHL) +doEHL*(1-(1-xiw)*(AEHL*exp(KwF)/(exp(FwF)*exp(wF)))^( 1/( 1-lambdaw*(1+sigmaL) )) - xiw*( exp(pitildewpiF) )^(1/(1-lambdaw)))=(1-doEHL)*(exp(KwF)-exp(STEADY_STATE(KwF))); +////////////////////////// +//Exogenous Variables///// +////////////////////////// + +//E1 Composite technology growth +muF=alfa/(1-alfa)*mupsiF+muzF; + +//E2 Unit root invest. Tech. +mupsiF=(1-rhomupsi)*STEADY_STATE(mupsiF)+rhomupsi*mupsiF(-1)+sig_mupsi*mupsi_eps/100; + +//E3 Unit root neutral Tech. +muzF=(1-rhomuz)*STEADY_STATE(muzF)+rhomuz*muzF(-1)+sig_muz*muz_eps/100; + +//E4 Diffusion of composite technology into gov. spending +(1-dolagZBAR)*(exp(nGF)-(exp(nGF(-1))/exp(muF))^(1-thetaG))=dolagZBAR*(exp(nGF)-(exp(nGF(-1)))^(1-thetaG)/exp(muF)); + +//E5 Diffusion of composite technology into fixed costs of production +nPHIF=nGF; + +//E6 Diffusion of composite technology into firm delay costs of bargaining +nGAMF=nGF; + +//E7 Diffusion of composite technology into unemployment benefits +nDF=nGF; + +//E8 Diffusion of composite technology into hiring/search costs +nKAPF=nGF; +////////////////////////////////////////////////////////////////////// +//Aggregating 'F' and 'R' economies, expressed in percent deviations// +////////////////////////////////////////////////////////////////////// +//A1 +GDPAGG-STEADY_STATE(GDPF)=GDPR-STEADY_STATE(GDPF)+GDPF-STEADY_STATE(GDPF); +//A2 +piAGG-STEADY_STATE(piF)=piR-STEADY_STATE(piF)+piF-STEADY_STATE(piF); +//A3 +RAGG-STEADY_STATE(RF)=RR-STEADY_STATE(RF)+RF-STEADY_STATE(RF); +//A4 +ukAGG-STEADY_STATE(ukF)=ukR-STEADY_STATE(ukF)+ukF-STEADY_STATE(ukF); +//A5 +lAGG-STEADY_STATE(lF)=lR-STEADY_STATE(lF)+lF-STEADY_STATE(lF); +//A6 +wAGG-STEADY_STATE(wF)=wR-STEADY_STATE(wF)+wF-STEADY_STATE(wF); +//A7 +cAGG-STEADY_STATE(cF)=cR-STEADY_STATE(cF)+cF-STEADY_STATE(cF); +//A8 +iAGG-STEADY_STATE(iF)=iR-STEADY_STATE(iF)+iF-STEADY_STATE(iF); +//A9 +unempAGG-STEADY_STATE(unempF)=unempR-STEADY_STATE(unempF)+unempF-STEADY_STATE(unempF); +//A10 +vTotAGG-STEADY_STATE(vTotF)=vTotR-STEADY_STATE(vTotF)+vTotF-STEADY_STATE(vTotF); +//A11 +fAGG-STEADY_STATE(fF)=fR-STEADY_STATE(fF)+fF-STEADY_STATE(fF); +//A12 +pinvestAGG=-mupsiF; +end; +///////////////////////////////// +//End Model ////////// +///////////////////////////////// + + +% model switches +doNash=0; %if =0, alt offer barg. ; if =1, Nash bargaining; note: requires doEHL=0 below +doEHL=0; %if=0, alt offer barg or Nash barg; if=1, EHL labor market +@#define do_given_bets=0 // 1: given values for beta's in sharing rule +%AOB sharing rule coefficients +bet1 = 0.0907; +bet2 = 28.9219; +bet3 = 0.4562; + +%Labor market parameters +u=0.055; %unemp. rate +rho=0.9; %job survival rate +sigm=0.5570; %matching function share of unemp. +recSHAREpercent=0.5; %hiring cost para; hiring cost relative to output, in percent +searchSHAREpercent=0.05; %search cost para; hiring cost relative to output, in percent + +DSHARE=0.6682; %unempl. benefits as share of w (replacement ratio) +Q=0.7; %vacancy filling rate + +deltapercent=0.3022; %prob. of barg. session determination +M=60; %maximum bargaining rounds per quarter, needs to be an even number!!!! + +if M<2, error('M must be at least equal to 2!');end +if mod(M,2)==1, error('M must be an even number so that the worker makes the last offer!');end + +%prices +xi=0.5841; %Calvo prices +pibar=1.00625; %inflation rate, gross, quarterly +kappaf=0; %price indexation to past inflation +varkappaf=1; %price indexation parameter; if kappaf=0 and varkappaf=1 and pibreve=1 -> no indexation at all. +pibreve=1; %price indexation to value pibreve + +lambda=1.4256; %steady state price markup +nuf=1; %working capital fraction +tau=1; %steady state markup shifter + +%technology and adjustment cost +alfa=0.2366; %capital share +deltak=0.025; %depreciation rate of capital +Spp=13.6684; %second derivative of invest. adjustment costs +sigmaa=0.0760; %capacity utilization costs + +%growth rates of investment and real GDP +idiffdataPercent=2.9; +ydiffdataPercent=1.7; + +%Preferences +betta=0.996783170280770; %discount factor households; implies 3% real rate +b=0.8320; %habit formation in consumption + +%Monetary Policy by Taylor rule +rhoR = 0.8555; %Interest rate smoothing +rpi = 1.3552; %Coefficient on inflation +ry = 0.0359; %Coef. on GDP + +%Government +etag=0.2; %Government spending-to-output in ss + +%technology diffusion into gov. spending and other parameters of the model +thetaG =0.0136; %gov spending +thetaPHI=thetaG; %fixed cost of production +thetaKAP=thetaG; %hiring cost +thetaGAM=thetaG; %cost of counteroffer +thetaD=0.7416; %replacement ratio +dolagZBAR=1; %if =1, diffusion speed: zbar_t=(zplus_t-1)^thetaj*(zbar_t-1)^(1-thetaj); + %if =0, zbar_t=(zplus_t)^thetaj*(zbar_t-1)^(1-thetaj) for j=G,GAM,KAP,BU,PHI + %check cet_steadystate.m for further restrictions on + %theta parameters! + +% steady state profits as share of output +profy=0; + +%EHL parameter +lambdaw=1.2; %wage markup (EHL) +xiw=0.75; %Calvo wage stickiness (EHL) +sigmaL=1; %inv. labor supply elast. (EHL) +kappaw=0; %wage indexation to past inflation (EHL) +varkappaw=1; %wage indexation parameter; if kappaw=0 and varkappaw=1 and pibreve=1 and thetaw=0 -> no indexation at all. +thetaw=0; %wage indexation to technology + + +% standard deviation of shocks (%) +sig_muz = 0.1362; %unit root neutral tech. +sig_mupsi = 0.1100; %unit root investment tech. +sig_epsR = 0.6028; %monetary policy + +sig_epsilon = 0; %stationary neutral tech. +sig_upsilon = 0; %stationary invest. tech. +sig_g = 0; %gov. spending +sig_taud = 0; %price markup +sig_zetac = 0; %cons. preference + +%AR(1) +rhomupsi = 0.7279; %unit root investment tech. +rhomuz = 0; %unit root neutral tech. + +rhoepsilon = 0; %stationary neutral tech. +rhoupsilon = 0; %stationary invest. tech. +rhozetac = 0; %cons. preference +rhog = 0; %gov. spending +rhotaud = 0; %price markup +rhosigmam = 0; %matching function shock + +iota=1; %This parameter does not apprear in the model anymore. Just ignore it. + + +shocks; +var epsR_eps = 1; //monetary policy +var muz_eps = 1; //neutral tech. +var mupsi_eps = 1; //invest. tech. +end; + +steady_state_model; +%% based on cet_steadystate.m, some code is put into cet_steady_helper.m +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%force the below parameters to be identical to thetaG +thetaPHI=thetaG;%thetaPHI =1; %fixed cost of production +thetaKAP=thetaG;%thetaKAP =1; %hiring cost +thetaGAM=thetaG;%thetaGAM =1; %counteroffer cost +thetaD=thetaG;%thetaD=1; %unemp. benefits +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%first, some easy steady states +delta=deltapercent/100; +mu=exp(ydiffdataPercent/100/4); +mupsi=exp(idiffdataPercent/100/4)/mu; +muz=mu/mupsi^(alfa/(1-alfa)); +[info,nG,nKAP,nD,nGAM,nPHI] = cet_steady_helper(0,0,0,0,0, dolagZBAR,mu,thetaG,thetaKAP,thetaD,thetaGAM,thetaPHI); +uk=1; +aofuk=0; +Stilde=0; +Sprimetilde=0; +l=1-u; +R=mu*pibar/betta; +pkprime=1; +Rk=pibar*mu/betta; +%Some more complicated steady states +sigmab=Rk*mupsi*pkprime/pibar-(1-deltak)*pkprime; +aofukprime=sigmab; +pitilde=pibar^kappaf*pibar^(1-kappaf-varkappaf)*pibreve^varkappaf; +mc=1/lambda*(1-betta*xi*(pitilde/pibar)^(lambda/(1-lambda)))/(1-betta*xi*(pitilde/pibar)^(1/(1-lambda))) *((1-xi*(pitilde/pibar)^(1/(1-lambda)))/(1-xi))^(1-lambda); +phalo=((1-xi*(pitilde/pibar)^(1/(1-lambda)))/(1-xi))^(1-lambda)/((1-xi*(pitilde/pibar)^(lambda/(1-lambda)))/(1-xi))^((1-lambda)/lambda); +kl=(alfa*(mupsi*mu)^(1-alfa)*mc/sigmab/tau)^(1/(1-alfa)); +%EHL as special case. Obviously, whalo has no meaning otherwise and is set to one! +piw=mu*pibar; +pitildew=(pibar)^kappaw*(pibar)^(1-kappaw-varkappaw)*pibreve^varkappaw*mu^thetaw; +whalo=doEHL*(((1-xiw*(pitildew/piw)^(1/(1-lambdaw)))/(1-xiw))^(1-lambdaw) / ((1-xiw*(pitildew/piw)^(lambdaw/(1-lambdaw)))/(1-xiw))^((1-lambdaw)/lambdaw))+(1-doEHL)*1; +varthet=(1-alfa)*mc/(tau*(mupsi*mu)^alfa*(nuf*R+1-nuf))*kl^alfa; +y=mc/( (phalo^(lambda/(1-lambda))-1)*mc+1-profy)*(kl/(mu*mupsi))^alfa*l*whalo^(lambdaw/(lambdaw-1)); +k=kl*l*whalo^(lambdaw/(lambdaw-1)); +phi=((k/(l*whalo^(lambdaw/(lambdaw-1)))/(mupsi*mu))^alfa*l*whalo^(lambdaw/(lambdaw-1))-y*phalo^(lambda/(1-lambda)))/nPHI; +i=(1-(1-deltak)/(mu*mupsi))*k; +c=(1-etag)*y-i-(1-doEHL)*recSHAREpercent/100*y-(1-doEHL)*searchSHAREpercent/100*y; +psi=(c-b*c/mu)^(-1)-betta*b*(c*mu-b*c)^(-1); +g=etag*y/nG; +gdp=g*nG+c+i; +K=lambda*psi*y*mc/(1-betta*xi*(pitilde/pibar)^(lambda/(1-lambda))); +F=psi*y/(1-betta*xi*(pitilde/pibar)^(1/(1-lambda))); +%steady states specific to unemployment models, except for real wage (switch) +x=1-rho; +f=x*l/(1-rho*l); +v=x/Q; +sigmam=x*l*(1-rho*l)^(-sigm)*(l*v)^(sigm-1); +kappa=recSHAREpercent/100/x/l*y/nKAP; +s=(searchSHAREpercent/100/((Q^(-1)*x))/l*y)/nKAP; +J=kappa*nKAP+s*nKAP*Q^(-1); +varthetp=varthet/(1-rho*betta); +wp=varthetp-J; +w=doEHL*(varthet)+(1-doEHL)*(wp*(1-rho*betta)); %EHL switch for wage +D=DSHARE*w/nD; +VminusU=(wp-nD*D/(1-rho*betta))/(1-(1-f)*betta*rho)*(1-rho*betta); +U=(nD*D+betta*f*VminusU)/(1-betta); +V=VminusU+U; +A=V-wp; +%AOB sharing rule +alp1=1-delta+(1-delta)^M; +alp2=1-(1-delta)^M; +alp3=alp2*(1-delta)/delta-alp1; +alp4=(1-delta)/(2-delta)*alp2/M+1-alp2; +@#if do_given_bets==0 + bet1=alp2/alp1; + bet2=alp3/alp1; + bet3=alp4/alp1; +@#endif +gamma=(bet1*(V-U)-J+bet3*(varthet-nD*D))/(nGAM*bet2); +recruiting=nKAP*kappa*x*l+nKAP*s*(Q^(-1)*x)*l; +%Worker surplus share under Nash sharing +eta=(V-U)/(V-U+J); +%EHL sticky wages +Kw=((l*whalo^(lambdaw/(lambdaw-1)))^(1+sigmaL))/(1-betta*xiw*(pitildew/piw)^(lambdaw*(1+sigmaL)/(1-lambdaw))); +Fw=(psi/lambdaw*(l*whalo^(lambdaw/(lambdaw-1))))/(1-betta*xiw*(pitildew/piw)^(1/(1-lambdaw))); +AEHL=1/(Kw)*(Fw*w)*((1- xiw*( pitildew/piw )^(1/(1-lambdaw)))/(1-xiw))^(( 1-lambdaw*(1+sigmaL) )); +%parameters for dynare +tau_SS=log(tau); epsilon_SS=log(1); upsilon_SS=log(1); +zetac_SS=log(1); g_SS=log(g); unemp_SS=log(1-l); vTot_SS=log(v*l); +%steady state variables for ys vector (R economy) +psiR=log(psi); cR=log(c); RR=log(R); piR=log(pibar); +iR=log(i); pkprimeR=log(pkprime); FR=log(F); KR=log(K); +ukR=log(uk); kbarR=log(k); lR=log(l); xR=log(x); varthetR=log(varthet); +phaloR=log(phalo); yR=log(y); VR=log(V); JR=log(J); UR=log(U); +GDPR=log(gdp); fR=log(f); vR=log(v); unempR=log(u); +vTotR=log(v*l); QR=log(Q); piwR=log(piw); whaloR=log(whalo); +FwR=log(Fw); KwR=log(Kw); wR=log(w); wpR=log(wp); +varthetpR=log(varthetp); AAR=log(A); +%steady state variables for ys vector (R economy) +psiF=log(psi); cF=log(c); RF=log(R); piF=log(pibar); +iF=log(i); pkprimeF=log(pkprime); FF=log(F); KF=log(K); +ukF=log(uk); kbarF=log(k); lF=log(l); xF=log(x); varthetF=log(varthet); +phaloF=log(phalo); yF=log(y); VF=log(V); JF=log(J); UF=log(U); +GDPF=log(gdp); fF=log(f); vF=log(v); unempF=log(u); nDF=log(nD); +vTotF=log(v*l); QF=log(Q); piwF=log(piw);nPHIF=log(nPHI);wF=log(w); +whaloF=log(whalo); FwF=log(Fw); KwF=log(Kw); muzF=log(muz); +mupsiF=log(mupsi); muF=log(mu); nGF=log(nG); nGAMF=log(nGAM); nKAPF=log(nKAP); +AAF=log(A);wpF=log(wp); varthetpF=log(varthetp); +%AGG econ +GDPAGG=log(gdp); piAGG=log(pibar); RAGG=log(R); ukAGG=log(uk); lAGG=log(l); +wAGG=wF; cAGG=log(c); iAGG=log(i); unempAGG=log(u); vTotAGG=log(v*l); +fAGG=log(f); pinvestAGG=-log(mupsi); + +info = cet_steady_helper(1,Kw,J,V,U); % THIS CHECKS WHETHER STEADY-STATES ARE NONZERO +end; + +resid; +steady; +check; + + +@#ifdef ML +%% FREQUENTIST ESTIMATION +estimated_params; +xi; +lambda , , 1.001, Inf; +rhoR , 0.85, -Inf, Inf; +rpi , 1.45, -Inf, Inf; +ry , 0.01, -Inf, Inf; +b , , -Inf, Inf; +sigmaa , , -Inf, Inf; +Spp , , -Inf, Inf; +alfa , , -Inf, 0.6; +thetaG , 0.10, 0, 1; +deltapercent , , -Inf, Inf; +DSHARE , , -Inf, Inf; +recSHAREpercent , , -Inf, Inf; +searchSHAREpercent , , -Inf, Inf; +sigm , , -Inf, Inf; +sig_epsR , , -Inf, Inf; +sig_muz , , -Inf, Inf; +sig_mupsi , , -Inf, Inf; +rhomupsi , , -Inf, Inf; +end; + +xi = 0.7363; +lambda = 1.4082; +rhoR = 0.8463; +rpi = 1.4566; +ry = 0.0407; +b = 0.8196; +sigmaa = 0.1544; +Spp = 15.1062; +alfa = 0.2404; +thetaG = 0.0502; +deltapercent = 0.1825; +DSHARE = 0.4596; +recSHAREpercent = 0.4849; +searchSHAREpercent = 0.0654; +sigm = 0.5403; +sig_epsR = 0.6163; +sig_muz = 0.1496; +sig_mupsi = 0.1150; +rhomupsi = 0.7314; + +estimated_params_init(use_calibration); +end; + +@#else + +%% BAYESIAN ESTIMATION +estimated_params; +xi , , , , beta_pdf , 0.66, 0.100; +lambda , , 1.001, , gamma_pdf , 1.20, 0.050; +rhoR , 0.85, , , beta_pdf , 0.70, 0.150; +rpi , 1.45, , , gamma_pdf , 1.70, 0.150; +ry , 0.01, , , gamma_pdf , 0.10, 0.050; +b , , , , beta_pdf , 0.50, 0.150; +sigmaa , , , , gamma_pdf , 0.50, 0.300; +Spp , , , , gamma_pdf , 8.00, 2.000; +@#ifndef LESSPARAMS +alfa , , , , beta_pdf , 0.33, 0.025; +thetaG , 0.10, , , beta_pdf , 0.50, 0.200; +deltapercent , , , , gamma_pdf , 0.50, 0.400; +DSHARE , , , , beta_pdf , 0.40, 0.100; +recSHAREpercent , , , , gamma_pdf , 1.00, 0.300; +searchSHAREpercent , , , , gamma_pdf , 0.10, 0.070; +sigm , , , , beta_pdf , 0.50, 0.100; +sig_epsR , , , , gamma_pdf , 0.65, 0.050; +sig_muz , , , , gamma_pdf , 0.10, 0.050; +sig_mupsi , , , , gamma_pdf , 0.10, 0.050; +rhomupsi , , , , beta_pdf , 0.75, 0.100; +@#endif +end; +@#endif + +varobs GDPAGG piAGG RAGG ukAGG lAGG wAGG cAGG iAGG pinvestAGG unempAGG vTotAGG fAGG; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% IRF DATA TRANSFORMATIONS %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +load('cet_data','IRFz','IRFzSE','IRFFF','IRFFFSE','IRFu','IRFuSE'); +% IRFFF: impulse responses with respect to monetary policy shock +% IRFFz: impulse responses with respect to neutral tech shock +% IRFFu: impulse responses with respect to invest tech shock +% IRFFFSE, IRFzSE, IRFuSE contain the corresponding estimated standard errors +% dimensions: rows are periods, columns are variables: +% - column 1: gdp corresponds to GDPAGG + cumsum(muF) +% - column 2: inflation corresponds to piAGG +% - column 3: federal funds rate corresponds to RAGG +% - column 4: capacity utilization corresponds to ukAGG +% - column 5: total hours corresponds to lAGG +% - column 6: real wage corresponds to wAGG + cumsum(muF) +% - column 7: consumption corresponds to cAGG + cumsum(muF) +% - column 7: investment corresponds to iAGG + cumsum(muF) + cumsum(mupsiF) +% - column 8: rel. price investment corresponds to cumsum(pinvestAGG) +% - column 10: unemployment rate corresponds to unempAGG +% - column 11: vacancies corresponds to vTotAGG*u +% - column 12: labor force +% - column 13: separation rate +% - column 14: job finding rate corresponds to fAGG*f +% transformations will be done in cet_irf_matching_file.m + +% change sign of monetary policy shock irfs +IRFFF = -1*IRFFF; +% rescale some irfs +IRFFF(:,[2 3] ) = IRFFF(:,[2 3] )./400; IRFFFSE(:,[2 3] ) = IRFFFSE(:,[2 3] )./400; +IRFFF(:,[10 14]) = IRFFF(:,[10 14])./100; IRFFFSE(:,[10 14]) = IRFFFSE(:,[10 14])./100; +IRFz( :,[2 3] ) = IRFz( :,[2 3] )./400; IRFzSE( :,[2 3] ) = IRFzSE( :,[2 3] )./400; +IRFz( :,[10 14]) = IRFz( :,[10 14])./100; IRFzSE( :,[10 14]) = IRFzSE( :,[10 14])./100; +IRFu( :,[2 3] ) = IRFu( :,[2 3] )./400; IRFuSE( :,[2 3] ) = IRFuSE( :,[2 3] )./400; +IRFu( :,[10 14]) = IRFu( :,[10 14])./100; IRFuSE( :,[10 14]) = IRFuSE( :,[10 14])./100; + +%%%%%%%%%%%%%%%%%%%%%%%% +%% MATCHED_IRFS BLOCK %% +%%%%%%%%%%%%%%%%%%%%%%%% +% use anonymous functions to quickly access variables in matrices +irfs_epsR_eps = @(j) IRFFF(2:15,j); % start in t=2 due to identification restrictions in SVAR +irfs_muz_eps = @(j) IRFz(1:15,j); +irfs_mupsi_eps = @(j) IRFu(1:15,j); +weights_epsR_eps = @(j) 1./(IRFFFSE(2:15,j).^2); % start in t=2 due to identification restrictions in SVAR +weights_muz_eps = @(j) 1./(IRFzSE(1:15,j).^2); +weights_mupsi_eps = @(j) 1./(IRFuSE(1:15,j).^2); +% for RAGG we also include t=1 + RAGG_epsR_eps = IRFFF(1:15,3); +w_RAGG_epsR_eps = 1./(IRFFFSE(1:15,3).^2); + +matched_irfs; +var GDPAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(1)); weights (weights_epsR_eps(1)); +var GDPAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(1)); weights (weights_muz_eps(1)); +var GDPAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(1)); weights (weights_mupsi_eps(1)); + +var piAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(2)); weights (weights_epsR_eps(2)); +var piAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(2)); weights (weights_muz_eps(2)); +var piAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(2)); weights (weights_mupsi_eps(2)); + +var RAGG; varexo epsR_eps; periods 1:15; values (RAGG_epsR_eps); weights (w_RAGG_epsR_eps); +var RAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(3)); weights (weights_muz_eps(3)); +var RAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(3)); weights (weights_mupsi_eps(3)); + +var ukAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(4)); weights (weights_epsR_eps(4)); +var ukAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(4)); weights (weights_muz_eps(4)); +var ukAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(4)); weights (weights_mupsi_eps(4)); + +var lAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(5)); weights (weights_epsR_eps(5)); +var lAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(5)); weights (weights_muz_eps(5)); +var lAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(5)); weights (weights_mupsi_eps(5)); + +var wAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(6)); weights (weights_epsR_eps(6)); +var wAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(6)); weights (weights_muz_eps(6)); +var wAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(6)); weights (weights_mupsi_eps(6)); + +var cAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(7)); weights (weights_epsR_eps(7)); +var cAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(7)); weights (weights_muz_eps(7)); +var cAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(7)); weights (weights_mupsi_eps(7)); + +var iAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(8)); weights (weights_epsR_eps(8)); +var iAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(8)); weights (weights_muz_eps(8)); +var iAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(8)); weights (weights_mupsi_eps(8)); + +var pinvestAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(9)); weights (weights_epsR_eps(9)); +var pinvestAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(9)); weights (weights_muz_eps(9)); +var pinvestAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(9)); weights (weights_mupsi_eps(9)); + +var unempAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(10)); weights (weights_epsR_eps(10)); +var unempAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(10)); weights (weights_muz_eps(10)); +var unempAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(10)); weights (weights_mupsi_eps(10)); + +var vTotAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(11)); weights (weights_epsR_eps(11)); +var vTotAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(11)); weights (weights_muz_eps(11)); +var vTotAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(11)); weights (weights_mupsi_eps(11)); + +var fAGG; varexo epsR_eps; periods 2:15; values (irfs_epsR_eps(14)); weights (weights_epsR_eps(14)); +var fAGG; varexo muz_eps; periods 1:15; values (irfs_muz_eps(14)); weights (weights_muz_eps(14)); +var fAGG; varexo mupsi_eps; periods 1:15; values (irfs_mupsi_eps(14)); weights (weights_mupsi_eps(14)); +end; \ No newline at end of file diff --git a/tests/estimation/method_of_moments/CET/cet_original_mode.mat b/tests/estimation/method_of_moments/CET/cet_original_mode.mat new file mode 100644 index 0000000000000000000000000000000000000000..6f804b6dc14568408ebe7d633548f03e808ce0b2 --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_original_mode.mat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d6cdcc7cfa32ee9128b0c457798034ffc01024679bcc43f7cbb4ac3ce1840bb +size 15040 diff --git a/tests/estimation/method_of_moments/CET/cet_rwmh.mod b/tests/estimation/method_of_moments/CET/cet_rwmh.mod new file mode 100644 index 0000000000000000000000000000000000000000..c83515690f15dac239faf5361aa1d7369667c48d --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_rwmh.mod @@ -0,0 +1,226 @@ +% ------------------------------------------------------------------------- +% Functionality testing of Bayesian IRF matching with +% - Random-Walk Metropolis-Hastings +% - loading mode files +% - whether results are stored and can be accessed in different directories +% - reuse previous MCMC to define covariance of proposal +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. +@#define LESSPARAMS=1 +@#include "cet_model.inc" + +options_.prior_interval= 0.95; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% RUN 1: FIND POSTERIOR MODE USING MODEFILE %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +method_of_moments(mom_method = irf_matching +%, add_tiny_number_to_cholesky = 1e-14 +, additional_optimizer_steps = [4] +%, aim_solver +%, analytic_jacobian +%, analytic_standard_errors +%, bartlett_kernel_lag +%, bounded_shock_support +%, brooks_gelman_plotrows +, cova_compute=0 +%, datafile +, dirname=cet_rwmh_results_1 +%, dr +%, dr_cycle_reduction_tol +%, dr_logarithmic_reduction_maxiter +%, dr_logarithmic_reduction_tol +%, drop +%, first_obs +%, geweke_interval +%, graph_format +%, huge_number +, irf_matching_file = cet_irf_matching_file +%, k_order_solver +%, load_mh_file +%, load_results_after_load_mh +%, logdata +%, lyapunov +%, lyapunov_complex_threshold +%, lyapunov_doubling_tol +%, lyapunov_fixed_point_tol +%, mcmc_jumping_covariance +, mh_conf_sig = 0.90 +%, mh_drop = 0.5 +%, mh_init_scale_factor +%, mh_initialize_from_previous_mcmc +%, mh_initialize_from_previous_mcmc_directory +%, mh_initialize_from_previous_mcmc_prior +%, mh_initialize_from_previous_mcmc_record +%, mh_jscale = 0.5 +%, mh_nblocks = 1 +%, mh_posterior_mode_estimation +%, mh_recover +, mh_replic=0 +%, mh_tune_guess = 0.5 +%, mh_tune_jscale = 0.33 +%, mom_burnin +%, mom_seed +%, mom_se_tolx +, mode_check +%, mode_check_neighbourhood_size +%, mode_check_number_of_points +, mode_check_symmetric_plots = 0 +, mode_compute = 1 +, mode_file = cet_original_mode +%, nobs +%, no_posterior_kernel_density +, nodiagnostic +, nodisplay +, nograph +, noprint +%, optim +%, order +%, penalized_estimator +, plot_priors = 1 +%, posterior_max_subsample_draws +%, posterior_sampling_method = 'random_walk_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% , scale_file +% ) +%, posterior_sampling_method = 'tailored_random_block_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'new_block_probability',0.3 +% ,'mode_compute',1 +% ,optim +% ,'save_tmp_file',1 +% ,scale_file +% ) +%, posterior_sampling_method = 'independent_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ,scale_file +% ) +%, posterior_sampling_method = 'slice' +%, posterior_sampler_options = ('rotated',1 +% ,'mode_files' +% ,'slice_initialize_with_mode',1 +% ,'initial_step_size',0.8 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ) +%, prefilter +%, prior_trunc +%, pruning +%, qz_criterium +%, qz_zero_threshold +%, raftery_lewis_diagnostics +%, raftery_lewis_qrs +%, relative_irf +%, replic +%, schur_vec_tol +%, silent_optimizer +%, simulation_method = stoch_simul +%, simulation_multiple +%, sub_draws +%, sylvester +%, sylvester_fixed_point_tol +%, taper_steps +, tex +%, use_penalized_objective_for_hessian +, verbose +%, weighting_matrix +%, weighting_matrix_scaling_factor +%, xls_range +%, xls_sheet +); +close all; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% RUN 2: LOAD POSTERIOR MODE, COMPUTE HESSIAN AND RUN 1 MCMC CHAIN %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +method_of_moments(mom_method = irf_matching +, cova_compute=1 +, dirname=cet_rwmh_results_2 +, irf_matching_file = cet_irf_matching_file +, mh_conf_sig = 0.95 +, mh_drop = 0.5 +, mh_jscale = 0.5 +, mh_nblocks = 1 +, mh_replic=200 +, mode_compute = 0 +, mode_file = 'cet_rwmh_results_1/method_of_moments/cet_rwmh_mode' +, plot_priors = 0 +, posterior_sampling_method = 'random_walk_metropolis_hastings' +, posterior_sampler_options = ('proposal_distribution' + ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% , scale_file + ) +, tex +); +close all; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% RUN 3: DEFINE COVARIANCE OF PROPOSAL FROM PREVIOUS MCMC % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +method_of_moments(mom_method = irf_matching +, dirname=cet_rwmh_results_2 +, irf_matching_file = cet_irf_matching_file +, load_mh_file +, mh_conf_sig = 0.95 +, mh_drop = 0.5 +, mh_jscale = 0.5 +, mh_nblocks = 1 +, mh_replic=60 +, mode_compute = 0 +, plot_priors = 0 +, posterior_sampling_method = 'random_walk_metropolis_hastings' +, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' + ,'rand_multivariate_student' + ,'student_degrees_of_freedom',4 + ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% , scale_file + ) +, tex +); + + +%%%%%%%%%%% +%% LATEX %% +%%%%%%%%%%% +collect_latex_files; +if system(['pdflatex -halt-on-error -interaction=batchmode ' M_.fname '_TeX_binder.tex']) + error('TeX-File did not compile.') +end \ No newline at end of file diff --git a/tests/estimation/method_of_moments/CET/cet_slice.mod b/tests/estimation/method_of_moments/CET/cet_slice.mod new file mode 100644 index 0000000000000000000000000000000000000000..6316c9bead827da6c1976463942aa639eb461b1d --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_slice.mod @@ -0,0 +1,204 @@ +% ------------------------------------------------------------------------- +% Functionality testing of Bayesian IRF matching with +% - slice +% - rotated slice with use_mh_covariance_matrix +% - rotated slice with slice_initialize_with_mode +% - reuse previous MCMC +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. +@#define LESSPARAMS=1 +@#include "cet_model.inc" + +options_.prior_interval= 0.95; + + +%%%%%%%%%%%%%%%%%%%%%%%%%% +%% RUN 1: DEFAULT SLICE %% +%%%%%%%%%%%%%%%%%%%%%%%%%% +method_of_moments(mom_method = irf_matching +%, add_tiny_number_to_cholesky = 1e-14 +%, additional_optimizer_steps = [4] +%, aim_solver +%, analytic_jacobian +%, analytic_standard_errors +%, bartlett_kernel_lag +%, bounded_shock_support +%, brooks_gelman_plotrows +%, cova_compute=0 +%, datafile +%, dirname=cet_slice_default +%, dr +%, dr_cycle_reduction_tol +%, dr_logarithmic_reduction_maxiter +%, dr_logarithmic_reduction_tol +%, drop +%, first_obs +%, geweke_interval +%, graph_format +%, huge_number +, irf_matching_file = cet_irf_matching_file +%, k_order_solver +%, load_mh_file +%, load_results_after_load_mh +%, logdata +%, lyapunov +%, lyapunov_complex_threshold +%, lyapunov_doubling_tol +%, lyapunov_fixed_point_tol +%, mcmc_jumping_covariance +, mh_conf_sig = 0.90 +%, mh_drop = 0.5 +%, mh_init_scale_factor +%, mh_initialize_from_previous_mcmc +%, mh_initialize_from_previous_mcmc_directory +%, mh_initialize_from_previous_mcmc_prior +%, mh_initialize_from_previous_mcmc_record +%, mh_jscale = 0.5 +, mh_nblocks = 1 +%, mh_posterior_mode_estimation +%, mh_recover +, mh_replic=40 % too few draws yield error due to non positive definite covariance in the following estimations +%, mh_tune_guess = 0.5 +%, mh_tune_jscale = 0.33 +%, mom_burnin +%, mom_seed +%, mom_se_tolx +%, mode_check +%, mode_check_neighbourhood_size +%, mode_check_number_of_points +%, mode_check_symmetric_plots = 0 +%, mode_compute = 1 +%, mode_file = cet_original_mode +%, nobs +%, no_posterior_kernel_density +%, nodiagnostic +%, nodisplay +, nograph +%, noprint +%, optim +%, order +%, penalized_estimator +, plot_priors = 0 +%, posterior_max_subsample_draws +%, posterior_sampling_method = 'random_walk_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% , scale_file +% ) +%, posterior_sampling_method = 'tailored_random_block_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'new_block_probability',0.3 +% ,'mode_compute',1 +% ,optim +% ,'save_tmp_file',1 +% ,scale_file +% ) +%, posterior_sampling_method = 'independent_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ,scale_file +% ) +, posterior_sampling_method = 'slice' +%, posterior_sampler_options = ('rotated',1 +% ,'mode_files' +% ,'slice_initialize_with_mode',1 +% ,'initial_step_size',0.8 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',0 +% ) +%, prefilter +%, prior_trunc +%, pruning +%, qz_criterium +%, qz_zero_threshold +%, raftery_lewis_diagnostics +%, raftery_lewis_qrs +%, relative_irf +%, replic +%, schur_vec_tol +%, silent_optimizer +, simulation_method = stoch_simul +%, simulation_multiple +%, sub_draws +%, sylvester +%, sylvester_fixed_point_tol +%, taper_steps +%, tex +%, use_penalized_objective_for_hessian +%, verbose +%, weighting_matrix +%, weighting_matrix_scaling_factor +%, xls_range +%, xls_sheet +); +close all; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% RUN 2: ROTATED SLICE WITH USE_MH_COVARIANCE_MATRIX %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +method_of_moments(mom_method = irf_matching +, irf_matching_file = cet_irf_matching_file +, mh_nblocks = 1 +, mh_replic=10 +, plot_priors = 0 +, nograph +, load_mh_file +, posterior_sampling_method = 'slice' +, posterior_sampler_options = ('rotated',1 +% ,'mode_files' +% ,'slice_initialize_with_mode',1 +% ,'initial_step_size',0.8 + ,'use_mh_covariance_matrix',1 + ,'save_tmp_file',0 + ) +); +close all; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% RUN 3: ROTATED SLICE WITH SLICE_INITIALIZE_WITH_MODE %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +method_of_moments(mom_method = irf_matching +, irf_matching_file = cet_irf_matching_file +, mh_nblocks = 1 +, mh_replic=10 +, plot_priors = 0 +, nograph +, mode_compute = 1 +, posterior_sampling_method = 'slice' +, posterior_sampler_options = ('rotated',1 +% ,'mode_files' + ,'slice_initialize_with_mode',1 +% ,'initial_step_size',0.8 +% ,'use_mh_covariance_matrix',1 + ,'save_tmp_file',0 + ) +); \ No newline at end of file diff --git a/tests/estimation/method_of_moments/CET/cet_steady_helper.m b/tests/estimation/method_of_moments/CET/cet_steady_helper.m new file mode 100644 index 0000000000000000000000000000000000000000..add0d93c62822d809940f2f123fe63ab6270508d --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_steady_helper.m @@ -0,0 +1,52 @@ +function [info,nG,nKAP,nD,nGAM,nPHI] = cet_steady_helper(justCheck,Kw,J,V,U,dolagZBAR,mu,thetaG,thetaKAP,thetaD,thetaGAM,thetaPHI) +% [info,nG,nKAP,nD,nGAM,nPHI] = cet_steady_helper(justCheck,Kw,J,V,U,dolagZBAR,mu,thetaG,thetaKAP,thetaD,thetaGAM,thetaPHI) +% ------------------------------------------------------------------------- +% Based on cet_steadystate.m of the replication codes for +% Christiano, Eichenbaum, Trabandt (2016, Econometrica); +% slightly modified such that most of the code is in a steady_state_model block +% and only the two if statements are computed in this helper function. +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. + +info = 0; +if justCheck + if (Kw<0) + disp('could not compute steadystate: Kw<0'); + elseif (J<0) + disp('could not compute steadystate: J<0'); + elseif (V-U<0) + disp('could not compute steadystate: V-U<0') + info=1; + end + return +else + if dolagZBAR==1 + nG=mu^(-1/thetaG); + nKAP=mu^(-1/thetaKAP); + nD=mu^(-1/thetaD); + nGAM=mu^(-1/thetaGAM); + nPHI=mu^(-1/thetaPHI); + else + nG=(1/mu)^((1-thetaG)/thetaG); + nKAP=(1/mu)^((1-thetaKAP)/thetaKAP); + nD=(1/mu)^((1-thetaD)/thetaD); + nGAM=(1/mu)^((1-thetaGAM)/thetaGAM); + nPHI=(1/mu)^((1-thetaPHI)/thetaPHI); + end +end \ No newline at end of file diff --git a/tests/estimation/method_of_moments/CET/cet_tarb.mod b/tests/estimation/method_of_moments/CET/cet_tarb.mod new file mode 100644 index 0000000000000000000000000000000000000000..c9d5a0356192aa64cc69aff5526b15da9e268b1b --- /dev/null +++ b/tests/estimation/method_of_moments/CET/cet_tarb.mod @@ -0,0 +1,178 @@ +% ------------------------------------------------------------------------- +% Functionality testing of Bayesian IRF matching with +% - Tailored-Randomized-Block Metropolis-Hastings +% - reuse previous MCMC mode for optimization +% ------------------------------------------------------------------------- + +% Copyright © 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 <https://www.gnu.org/licenses/>. +@#define LESSPARAMS=1 +@#include "cet_model.inc" + +options_.prior_interval= 0.95; + + +method_of_moments(mom_method = irf_matching +%, add_tiny_number_to_cholesky = 1e-14 +, additional_optimizer_steps = [4] +%, aim_solver +%, analytic_jacobian +%, analytic_standard_errors +%, bartlett_kernel_lag +%, bounded_shock_support +%, brooks_gelman_plotrows +, cova_compute=1 +%, datafile +, dirname=cet_tarb_results +%, dr +%, dr_cycle_reduction_tol +%, dr_logarithmic_reduction_maxiter +%, dr_logarithmic_reduction_tol +%, drop +%, first_obs +%, geweke_interval +%, graph_format +%, huge_number +, irf_matching_file = cet_irf_matching_file +%, k_order_solver +%, load_mh_file +%, load_results_after_load_mh +%, logdata +%, lyapunov +%, lyapunov_complex_threshold +%, lyapunov_doubling_tol +%, lyapunov_fixed_point_tol +%, mcmc_jumping_covariance +, mh_conf_sig = 0.90 +%, mh_drop = 0.5 +%, mh_init_scale_factor +%, mh_initialize_from_previous_mcmc +%, mh_initialize_from_previous_mcmc_directory +%, mh_initialize_from_previous_mcmc_prior +%, mh_initialize_from_previous_mcmc_record +, mh_jscale = 0.5 +, mh_nblocks = 1 +%, mh_posterior_mode_estimation +%, mh_recover +, mh_replic=5 +%, mh_tune_guess = 0.5 +%, mh_tune_jscale = 0.33 +%, mom_burnin +%, mom_seed +%, mom_se_tolx +, mode_check +%, mode_check_neighbourhood_size +%, mode_check_number_of_points +%, mode_check_symmetric_plots = 0 +, mode_compute = 0 +, mode_file = cet_original_mode +%, nobs +%, no_posterior_kernel_density +%, nodiagnostic +%, nodisplay +, nograph +%, noprint +%, optim +%, order +%, penalized_estimator +, plot_priors = 0 +%, posterior_max_subsample_draws +%, posterior_sampling_method = 'random_walk_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% , scale_file +% ) +, posterior_sampling_method = 'tailored_random_block_metropolis_hastings' +, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' + ,'rand_multivariate_student' + ,'student_degrees_of_freedom',4 + ,'new_block_probability',0.25 + ,'mode_compute',4 +% ,optim +% ,'save_tmp_file',1 +% ,scale_file + ) +%, posterior_sampling_method = 'independent_metropolis_hastings' +%, posterior_sampler_options = ('proposal_distribution' +% ,'rand_multivariate_normal' +% ,'rand_multivariate_student' +% ,'student_degrees_of_freedom',4 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ,scale_file +% ) +%, posterior_sampling_method = 'slice' +%, posterior_sampler_options = ('rotated',1 +% ,'mode_files' +% ,'slice_initialize_with_mode',1 +% ,'initial_step_size',0.8 +% ,'use_mh_covariance_matrix',1 +% ,'save_tmp_file',1 +% ) +%, prefilter +%, prior_trunc +%, pruning +%, qz_criterium +%, qz_zero_threshold +%, raftery_lewis_diagnostics +%, raftery_lewis_qrs +%, relative_irf +%, replic +%, schur_vec_tol +%, silent_optimizer +%, simulation_method = stoch_simul +%, simulation_multiple +%, sub_draws +%, sylvester +%, sylvester_fixed_point_tol +%, taper_steps +, tex +%, use_penalized_objective_for_hessian +%, verbose +%, weighting_matrix +%, weighting_matrix_scaling_factor +%, xls_range +%, xls_sheet +); + + +method_of_moments(mom_method = irf_matching +, additional_optimizer_steps = [1] +, cova_compute=1 +, dirname=cet_tarb_results +, irf_matching_file = cet_irf_matching_file +, mh_conf_sig = 0.90 +, mh_replic=0 +%, mode_check +, mode_compute = 4 +, mode_file = 'cet_tarb_results/method_of_moments/cet_tarb_mh_mode' +, plot_priors = 0 +, nograph +); + +%%%%%%%%%%% +%% LATEX %% +%%%%%%%%%%% +collect_latex_files; +if system(['pdflatex -halt-on-error -interaction=batchmode ' M_.fname '_TeX_binder.tex']) + error('TeX-File did not compile.') +end \ No newline at end of file