From 2f07fa292183dbe75e461d07511a576a4332affe Mon Sep 17 00:00:00 2001 From: Willi Mutschler <willi@mutschler.eu> Date: Thu, 21 Dec 2023 01:40:29 +0100 Subject: [PATCH] irf_matching: adaptations for new interface --- matlab/+mom/display_comparison_moments_irfs.m | 18 ++- matlab/+mom/graph_comparison_irfs.m | 51 ++++---- matlab/+mom/matched_irfs_blocks.m | 112 ++++++++++++++---- matlab/+mom/run.m | 4 +- meson.build | 7 +- .../method_of_moments/CET/cet_imh.mod | 7 -- ...cet_matched_irfs_no_interface_workaround.m | 86 -------------- .../method_of_moments/CET/cet_mle.mod | 7 -- .../method_of_moments/CET/cet_model.inc | 101 +++++++++++++++- .../method_of_moments/CET/cet_rwmh.mod | 6 - .../method_of_moments/CET/cet_slice.mod | 6 - .../method_of_moments/CET/cet_tarb.mod | 8 +- 12 files changed, 240 insertions(+), 173 deletions(-) delete mode 100644 tests/estimation/method_of_moments/CET/cet_matched_irfs_no_interface_workaround.m diff --git a/matlab/+mom/display_comparison_moments_irfs.m b/matlab/+mom/display_comparison_moments_irfs.m index da31a4e34a..f21c745f37 100644 --- a/matlab/+mom/display_comparison_moments_irfs.m +++ b/matlab/+mom/display_comparison_moments_irfs.m @@ -42,9 +42,21 @@ function display_comparison_moments_irfs(M_, options_mom_, data_moments, model_m if strcmp(options_mom_.mom.mom_method,'IRF_MATCHING') titl = upper('Comparison of matched data IRFs and model IRFs'); headers = {'IRF','Data','Model'}; - for jm = 1:size(M_.matched_irfs,1) - labels{jm,1} = [M_.endo_names{M_.matched_irfs{jm,1}(1)} ' ' M_.exo_names{M_.matched_irfs{jm,1}(2)} ' (' num2str(M_.matched_irfs{jm,1}(3)) ')']; - labels_TeX{jm,1} = [M_.endo_names_tex{M_.matched_irfs{jm,1}(1)} ' ' M_.exo_names_tex{M_.matched_irfs{jm,1}(2)} ' (' num2str(M_.matched_irfs{jm,1}(3)) ')']; + 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,')']; diff --git a/matlab/+mom/graph_comparison_irfs.m b/matlab/+mom/graph_comparison_irfs.m index ee6d09e73b..5e7f574871 100644 --- a/matlab/+mom/graph_comparison_irfs.m +++ b/matlab/+mom/graph_comparison_irfs.m @@ -1,5 +1,5 @@ -function graph_comparison_irfs(matched_irfs,irf_model_varobs,varobs_id,irf_horizon,relative_irf,endo_names,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,exo_names,exo_names_tex,dname,fname,graph_format,TeX,nodisplay,figures_textwidth) +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 % ------------------------------------------------------------------------- @@ -10,6 +10,7 @@ function graph_comparison_irfs(matched_irfs,irf_model_varobs,varobs_id,irf_horiz % 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 @@ -59,40 +60,48 @@ if TeX && any(strcmp('eps',cellstr(graph_format))) fprintf(fid_TeX,['%% ' datestr(now,0) '\n']); fprintf(fid_TeX,' \n'); end -shock_entries = cellfun(@(x) x(2), matched_irfs(:, 1)); -unique_shock_entries = unique(shock_entries); +unique_shock_entries = unique(matched_irfs(:, 2)); colDarkGrey = [0.3, 0.3, 0.3]; % dark grey -for jexo = unique_shock_entries' - entries_data_irfs = find(cellfun(@(x) x(2) == jexo, matched_irfs(:, 1))); - unique_variables = unique(cellfun(@(x) x(1), matched_irfs(entries_data_irfs,1))); +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 ' exo_names{jexo} ' figure ' int2str(fig)]); + fig_irf = dyn_figure(nodisplay,'Name',['IRF matching shock to ' jexo{:} ' figure ' int2str(fig)]); end - plt = jvar-(fig-1)*nstar; - data_irf_rows = find(cellfun(@(x) x(1) == unique_variables(jvar) && x(2) == jexo, matched_irfs(:, 1))); - data_irf_periods = cellfun(@(x) x(3), matched_irfs(data_irf_rows,1)); - data_irf_values = cell2mat(matched_irfs(data_irf_rows,2)); + plt = jvar-(fig-1)*nstar; if nbplt>1 && fig==nbplt subplot(lr,lc,plt); else subplot(nr,nc,plt); end - plt_data = plot(data_irf_periods,data_irf_values,'h', 'MarkerEdgeColor',colDarkGrey,'MarkerFaceColor',colDarkGrey,'MarkerSize',8); + 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==unique_variables(jvar),jexo),'-k','linewidth',2); + 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{unique_variables(jvar)} '$'],'Interpreter','latex'); + title(['$' endo_names_tex{ismember(endo_names,unique_variables(jvar))} '$'],'Interpreter','latex'); else - title(endo_names{unique_variables(jvar)},'Interpreter','none'); + title(unique_variables{jvar},'Interpreter','none'); end set(gca,'FontSize',12); if (plt==nstar) || jvar==length(unique_variables) @@ -101,17 +110,17 @@ for jexo = unique_shock_entries' 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_' exo_names{jexo} int2str(fig)],nodisplay,graph_format); + 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],exo_names{jexo},int2str(fig)); + 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$).}', exo_names_tex{jexo}); + 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$).}', exo_names_tex{jexo}); + fprintf(fid_TeX,'\\caption{Impulse response functions (orthogonalized shock to $%s$).}', jexo{:}); end - fprintf(fid_TeX,'\\label{Fig:MatchedIRF:%s:%s}\n', exo_names{jexo},int2str(fig)); + fprintf(fid_TeX,'\\label{Fig:MatchedIRF:%s:%s}\n', jexo{:},int2str(fig)); fprintf(fid_TeX,'\\end{figure}\n'); fprintf(fid_TeX,' \n'); end diff --git a/matlab/+mom/matched_irfs_blocks.m b/matlab/+mom/matched_irfs_blocks.m index cce2d82781..ed8f01aa8f 100644 --- a/matlab/+mom/matched_irfs_blocks.m +++ b/matlab/+mom/matched_irfs_blocks.m @@ -1,5 +1,5 @@ -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) -% [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) +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. @@ -10,7 +10,8 @@ function [data_irfs, weight_mat, irf_index, max_irf_horizon] = matched_irfs_bloc % 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] list of endogenous 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 @@ -39,29 +40,78 @@ function [data_irfs, weight_mat, irf_index, max_irf_horizon] = matched_irfs_bloc % 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 -max_irf_horizon = max(cellfun(@(x) x(end), matched_irfs(:,1))); % get maximum IRF horizon -% create full matrix where 1st dimension are IRF periods, 2nd dimension are variables as declared in VAROBS, 3rd dimension are shocks. +% 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); -% overwrite NaN values if they are declared in matched_irfs block; remaining NaN values will be later ignored in the matching +% 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 = matched_irfs{jj,1}(1); + id_var = find(ismember(endo_names,matched_irfs{jj,1})); id_varobs = find(varobs_id==id_var,1); - id_shock = matched_irfs{jj,1}(2); - id_irf_period = matched_irfs{jj,1}(3); - irf_value = matched_irfs{jj,2}; + 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 - data_irfs(id_irf_period,id_varobs,id_shock) = irf_value; end -% create (full) empirical weighting matrix -weight_mat = eye(max_irf_horizon*obs_nbr*exo_nbr); % identity matrix by default: all IRFs are equally important + +% fine-tune weighting matrix using matched_irfs_weights for jj = 1:size(matched_irfs_weight,1) - id_var1 = matched_irfs_weight{jj,1}(1); id_varobs1 = find(varobs_id==id_var1,1); id_shock1 = matched_irfs_weight{jj,1}(2); id_irf_period1 = matched_irfs_weight{jj,1}(3); - id_var2 = matched_irfs_weight{jj,2}(1); id_varobs2 = find(varobs_id==id_var2,1); id_shock2 = matched_irfs_weight{jj,2}(2); id_irf_period2 = matched_irfs_weight{jj,2}(3); - weight_mat_value = matched_irfs_weight{jj,3}; + 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}) @@ -70,12 +120,32 @@ for jj = 1:size(matched_irfs_weight,1) 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 - idweight_mat1 = sub2ind(size(data_irfs),id_irf_period1,id_varobs1,id_shock1); - idweight_mat2 = sub2ind(size(data_irfs),id_irf_period2,id_varobs2,id_shock2); - weight_mat(idweight_mat1,idweight_mat2) = weight_mat_value; - weight_mat(idweight_mat2,idweight_mat1) = weight_mat_value; % symmetry + 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 -% focus only on specified IRFs + +% 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/run.m b/matlab/+mom/run.m index c53d3aece5..19b1a6206b 100644 --- a/matlab/+mom/run.m +++ b/matlab/+mom/run.m @@ -230,7 +230,7 @@ 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); + [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); @@ -799,7 +799,7 @@ if strcmp(options_mom_.mom.mom_method,'SMM') || strcmp(options_mom_.mom.mom_meth 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_.exo_names,M_.exo_names_tex,M_.dname,M_.fname,options_mom_.graph_format,options_mom_.TeX,options_mom_.nodisplay,options_mom_.figures.textwidth) + 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 diff --git a/meson.build b/meson.build index 65d6775600..8e9d27d68e 100644 --- a/meson.build +++ b/meson.build @@ -910,39 +910,34 @@ mod_and_m_tests = [ { 'test' : [ 'estimation/method_of_moments/AFVRR/AFVRR_MFB_RRA.mod' ], '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' ] }, + 'estimation/method_of_moments/AFVRR/AFVRR_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_matched_irfs_no_interface_workaround.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_matched_irfs_no_interface_workaround.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_matched_irfs_no_interface_workaround.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_matched_irfs_no_interface_workaround.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_matched_irfs_no_interface_workaround.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' ] }, diff --git a/tests/estimation/method_of_moments/CET/cet_imh.mod b/tests/estimation/method_of_moments/CET/cet_imh.mod index 44d91a7ee3..f2cacb89a8 100644 --- a/tests/estimation/method_of_moments/CET/cet_imh.mod +++ b/tests/estimation/method_of_moments/CET/cet_imh.mod @@ -25,13 +25,6 @@ options_.prior_interval= 0.95; - -%%%%%%%%%%%%%%%%%%%%%% -%% NO INTERFACE YET %% -%%%%%%%%%%%%%%%%%%%%%% -[M_.matched_irfs, M_.matched_irfs_weights] = cet_matched_irfs_no_interface_workaround(M_.endo_names,M_.exo_names); - - method_of_moments(mom_method = irf_matching %, add_tiny_number_to_cholesky = 1e-14 %, additional_optimizer_steps = [4] diff --git a/tests/estimation/method_of_moments/CET/cet_matched_irfs_no_interface_workaround.m b/tests/estimation/method_of_moments/CET/cet_matched_irfs_no_interface_workaround.m deleted file mode 100644 index 5f8bf190d8..0000000000 --- a/tests/estimation/method_of_moments/CET/cet_matched_irfs_no_interface_workaround.m +++ /dev/null @@ -1,86 +0,0 @@ -function [matched_irfs, matched_irfs_weights] = cet_matched_irfs_no_interface_workaround(endo_names,exo_names) -% [matched_irfs, matched_irfs_weights] = cet_matched_irfs_no_interface_workaround(endo_names,exo_names) -% ------------------------------------------------------------------------- -% Based on replication codes for Christiano, Eichenbaum, Trabandt (2016, Econometrica) - Unemployment and the Business Cycle -% This currently replaces the interface for the IRF Matching capabilities of the method_of_moments toolbox. -% ------------------------------------------------------------------------- - -% 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/>. - -%% settings -irf_horizon = 15; % horizon of impulse responses to match -do_monetary_shock_only = 0; % if = 0 all shocks are used in estimation - -%% load VAR impulse responses from Christiano, Trabandt and Walentin (2010)- Handbook of Monetary Economics Chapter -% 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 -load('cet_data','IRFz','IRFzSE','IRFFF','IRFFFSE','IRFu','IRFuSE'); - -%% map empirical irf data to a model variable -% note that any further required transformations or manipulations to model variables (such as cumsum, adding muF and mupsiF) -% as well as selection of which periods to match occurs in an extra function cet_irf_matching_file.m -% if no such function is given then the mapping is exact and the whole horizon will be considered - -% irfs with respect to monetary shock -if do_monetary_shock_only - SHOCKNAMES = {'epsR_eps'}; -else - SHOCKNAMES = {'epsR_eps', 'muz_eps', 'mupsi_eps'}; -end -VARNAMES = {'GDPAGG' 'piAGG' 'RAGG' 'ukAGG' 'lAGG' 'wAGG' 'cAGG' 'iAGG' 'pinvestAGG' 'unempAGG' 'vTotAGG' 'fAGG'}; -RESCALE = [1 400 400 1 1 1 1 1 1 100 1 100 ]; -idx=1; -for jexo = 1:length(SHOCKNAMES) - id_shock = strmatch(SHOCKNAMES{jexo},exo_names); - if SHOCKNAMES{jexo}=="epsR_eps" - IRF = -1*IRFFF(:,[1:11 14]); IRFSE = IRFFFSE(:,[1:11 14]); - elseif SHOCKNAMES{jexo}=="muz_eps" - IRF = IRFz(:,[1:11 14]); IRFSE = IRFzSE(:,[1:11 14]); - elseif SHOCKNAMES{jexo}=="mupsi_eps" - IRF = IRFu(:,[1:11 14]); IRFSE = IRFuSE(:,[1:11 14]); - end - for jvar = 1:length(VARNAMES) - id_var = strmatch(VARNAMES{jvar},endo_names); - for jirf=1:irf_horizon - if IRF(jirf,jvar) ~= 0 - matched_irfs(idx,:) = {[id_var, id_shock, jirf], IRF(jirf,jvar)/RESCALE(jvar)}; - matched_irfs_weights(idx,:) = {[id_var, id_shock, jirf], [id_var, id_shock, jirf], 1/(IRFSE(jirf,jvar)/RESCALE(jvar))^2 }; - idx = idx+1; - end - end - end -end - -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 index bf7057584e..a05a44b0eb 100644 --- a/tests/estimation/method_of_moments/CET/cet_mle.mod +++ b/tests/estimation/method_of_moments/CET/cet_mle.mod @@ -24,13 +24,6 @@ options_.prior_interval= 0.95; - -%%%%%%%%%%%%%%%%%%%%%% -%% NO INTERFACE YET %% -%%%%%%%%%%%%%%%%%%%%%% -[M_.matched_irfs, M_.matched_irfs_weights] = cet_matched_irfs_no_interface_workaround(M_.endo_names,M_.exo_names); - - method_of_moments(mom_method = irf_matching %, add_tiny_number_to_cholesky = 1e-14 %, additional_optimizer_steps = [4] diff --git a/tests/estimation/method_of_moments/CET/cet_model.inc b/tests/estimation/method_of_moments/CET/cet_model.inc index 678d6fe070..3e19aed60e 100644 --- a/tests/estimation/method_of_moments/CET/cet_model.inc +++ b/tests/estimation/method_of_moments/CET/cet_model.inc @@ -742,4 +742,103 @@ rhomupsi , , , , beta_pdf , 0.75, 0.100; end; @#endif -varobs GDPAGG piAGG RAGG ukAGG lAGG wAGG cAGG iAGG pinvestAGG unempAGG vTotAGG fAGG; \ No newline at end of file +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_rwmh.mod b/tests/estimation/method_of_moments/CET/cet_rwmh.mod index 870d12b628..c83515690f 100644 --- a/tests/estimation/method_of_moments/CET/cet_rwmh.mod +++ b/tests/estimation/method_of_moments/CET/cet_rwmh.mod @@ -28,12 +28,6 @@ options_.prior_interval= 0.95; -%%%%%%%%%%%%%%%%%%%%%% -%% NO INTERFACE YET %% -%%%%%%%%%%%%%%%%%%%%%% -[M_.matched_irfs, M_.matched_irfs_weights] = cet_matched_irfs_no_interface_workaround(M_.endo_names,M_.exo_names); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% RUN 1: FIND POSTERIOR MODE USING MODEFILE %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/tests/estimation/method_of_moments/CET/cet_slice.mod b/tests/estimation/method_of_moments/CET/cet_slice.mod index 27a5652fce..6316c9bead 100644 --- a/tests/estimation/method_of_moments/CET/cet_slice.mod +++ b/tests/estimation/method_of_moments/CET/cet_slice.mod @@ -28,12 +28,6 @@ options_.prior_interval= 0.95; -%%%%%%%%%%%%%%%%%%%%%% -%% NO INTERFACE YET %% -%%%%%%%%%%%%%%%%%%%%%% -[M_.matched_irfs, M_.matched_irfs_weights] = cet_matched_irfs_no_interface_workaround(M_.endo_names,M_.exo_names); - - %%%%%%%%%%%%%%%%%%%%%%%%%% %% RUN 1: DEFAULT SLICE %% %%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/tests/estimation/method_of_moments/CET/cet_tarb.mod b/tests/estimation/method_of_moments/CET/cet_tarb.mod index f7af30dee1..c9d5a03561 100644 --- a/tests/estimation/method_of_moments/CET/cet_tarb.mod +++ b/tests/estimation/method_of_moments/CET/cet_tarb.mod @@ -26,12 +26,6 @@ options_.prior_interval= 0.95; -%%%%%%%%%%%%%%%%%%%%%% -%% NO INTERFACE YET %% -%%%%%%%%%%%%%%%%%%%%%% -[M_.matched_irfs, M_.matched_irfs_weights] = cet_matched_irfs_no_interface_workaround(M_.endo_names,M_.exo_names); - - method_of_moments(mom_method = irf_matching %, add_tiny_number_to_cholesky = 1e-14 , additional_optimizer_steps = [4] @@ -168,7 +162,7 @@ method_of_moments(mom_method = irf_matching , irf_matching_file = cet_irf_matching_file , mh_conf_sig = 0.90 , mh_replic=0 -, mode_check +%, mode_check , mode_compute = 4 , mode_file = 'cet_tarb_results/method_of_moments/cet_tarb_mh_mode' , plot_priors = 0 -- GitLab