diff --git a/matlab/conditional_variance_decomposition.m b/matlab/conditional_variance_decomposition.m index 4c79249efa18fe078770e888a4652a4ac799a310..088a62ddc8c63eb90063afd2efad09fa52b87221 100644 --- a/matlab/conditional_variance_decomposition.m +++ b/matlab/conditional_variance_decomposition.m @@ -1,11 +1,13 @@ -function [ConditionalVarianceDecomposition, ConditionalVarianceDecomposition_ME]= conditional_variance_decomposition(StateSpaceModel, Steps, SubsetOfVariables,sigma_e_is_diagonal) +function [ConditionalVarianceDecomposition, ConditionalVarianceDecomposition_ME]= conditional_variance_decomposition(M_,options_,dr, Steps, SubsetOfVariables) % This function computes the conditional variance decomposition of a given state space model % for a subset of endogenous variables. % % INPUTS -% StateSpaceModel [structure] Specification of the state space model. -% Steps [integer] 1*h vector of dates. -% SubsetOfVariables [integer] 1*q vector of indices (declaration order). +% M_ [struct] Matlab's structure describing the Model (initialized by dynare, see @ref{M_}). +% options_ [struct] Matlab's structure describing the options (initialized by dynare, see @ref{options_}). +% dr : [struct] Dynare decision rules structure +% Steps [integer] 1*h vector of dates. +% SubsetOfVariables [integer] 1*q vector of indices (declaration order). % % OUTPUTS % ConditionalVarianceDecomposition [double] [n h p] array, where @@ -17,7 +19,7 @@ function [ConditionalVarianceDecomposition, ConditionalVarianceDecomposition_ME] % h is the number of Steps % p is the number of state innovations and -% Copyright © 2010-2021 Dynare Team +% Copyright © 2010-2023 Dynare Team % % This file is part of Dynare. % @@ -39,22 +41,19 @@ if any(Steps <= 0) 'positive']) end -number_of_state_innovations = ... - StateSpaceModel.number_of_state_innovations; -transition_matrix = StateSpaceModel.transition_matrix; -number_of_state_equations = ... - StateSpaceModel.number_of_state_equations; -order_var = StateSpaceModel.order_var; +[transition_matrix, impulse_matrix] = kalman_transition_matrix(dr,(1:M_.endo_nbr)',M_.nstatic+(1:M_.nspred)',M_.exo_nbr); + +number_of_state_innovations = M_.exo_nbr; +number_of_state_equations = M_.endo_nbr; +order_var = dr.order_var; nSteps = length(Steps); ConditionalVariance = zeros(number_of_state_equations,nSteps,number_of_state_innovations); -if StateSpaceModel.sigma_e_is_diagonal - B = StateSpaceModel.impulse_matrix.* ... - repmat(sqrt(diag(StateSpaceModel.state_innovations_covariance_matrix)'),... - number_of_state_equations,1); +if M_.sigma_e_is_diagonal + B = impulse_matrix.* repmat(sqrt(diag(M_.Sigma_e)'),number_of_state_equations,1); else - B = StateSpaceModel.impulse_matrix*chol(StateSpaceModel.state_innovations_covariance_matrix)'; + B = impulse_matrix*chol(M_.Sigma_e)'; end for i=1:number_of_state_innovations @@ -88,9 +87,9 @@ end % get intersection of requested variables and observed variables with % Measurement error -if ~all(diag(StateSpaceModel.measurement_error)==0) - [observable_pos,index_subset,index_observables]=intersect(SubsetOfVariables,StateSpaceModel.observable_pos,'stable'); - ME_Variance=diag(StateSpaceModel.measurement_error); +if ~all(diag(M_.H)==0) + [observable_pos,index_subset,index_observables]=intersect(SubsetOfVariables,options_.varobs_id,'stable'); + ME_Variance=diag(M_.H); ConditionalVarianceDecomposition_ME = zeros(length(observable_pos),length(Steps),number_of_state_innovations+1); for i=1:number_of_state_innovations diff --git a/matlab/dsge_simulated_theoretical_conditional_variance_decomposition.m b/matlab/dsge_simulated_theoretical_conditional_variance_decomposition.m index 9602eafad3d073305b38516c49480e85fd348f89..5918b75e475f62a37f8b7490a3a6993b8e8194e8 100644 --- a/matlab/dsge_simulated_theoretical_conditional_variance_decomposition.m +++ b/matlab/dsge_simulated_theoretical_conditional_variance_decomposition.m @@ -19,7 +19,7 @@ function [nvar,vartan,NumberOfConditionalDecompFiles] = ... % vartan [char] array of characters (with nvar rows). % NumberOfConditionalDecompFiles [integer] scalar, number of prior or posterior data files (for covariance). -% Copyright © 2009-2021 Dynare Team +% Copyright © 2009-2023 Dynare Team % % This file is part of Dynare. % @@ -46,8 +46,7 @@ elseif strcmpi(type,'prior') CheckPath('prior/moments',M_.dname); posterior = 0; else - disp('dsge_simulated_theoretical_conditional_variance_decomposition:: Unknown type!') - error() + error('dsge_simulated_theoretical_conditional_variance_decomposition:: Unknown type requested!') end %delete old stale files before creating new ones @@ -82,15 +81,12 @@ options_.ar = 0; NumberOfSavedElementsPerSimulation = nvar*M_.exo_nbr*length(Steps); MaXNumberOfConditionalDecompLines = ceil(options_.MaxNumberOfBytes/NumberOfSavedElementsPerSimulation/8); -ME_present=0; -if ~all(diag(M_.H)==0) - [observable_pos_requested_vars,index_subset,index_observables]=intersect(ivar,options_.varobs_id,'stable'); - if ~isempty(observable_pos_requested_vars) - ME_present=1; - nobs_ME=length(observable_pos_requested_vars); - NumberOfSavedElementsPerSimulation_ME = nobs_ME*(M_.exo_nbr+1)*length(Steps); - MaXNumberOfConditionalDecompLines_ME = ceil(options_.MaxNumberOfBytes/NumberOfSavedElementsPerSimulation_ME/8); - end +[ME_present,observable_pos_requested_vars,index_subset,index_observables]=check_measurement_error_requested_vars(M_,options_,ivar); + +if ME_present && ~isempty(observable_pos_requested_vars) + nobs_ME=length(observable_pos_requested_vars); + NumberOfSavedElementsPerSimulation_ME = nobs_ME*(M_.exo_nbr+1)*length(Steps); + MaXNumberOfConditionalDecompLines_ME = ceil(options_.MaxNumberOfBytes/NumberOfSavedElementsPerSimulation_ME/8); end if SampleSize<=MaXNumberOfConditionalDecompLines @@ -118,12 +114,6 @@ end NumberOfConditionalDecompLines = size(Conditional_decomposition_array,4); ConditionalDecompFileNumber = 0; - -StateSpaceModel.number_of_state_equations = M_.endo_nbr; -StateSpaceModel.number_of_state_innovations = M_.exo_nbr; - -first_call = 1; - linea = 0; linea_ME = 0; for file = 1:NumberOfDrawsFiles @@ -142,28 +132,12 @@ for file = 1:NumberOfDrawsFiles dr = temp.pdraws{linee,2}; else M_=set_parameters_locally(M_,temp.pdraws{linee,1}); - [dr,info,M_,oo_] = compute_decision_rules(M_,options_,oo_) - end - if first_call - endo_nbr = M_.endo_nbr; - nstatic = M_.nstatic; - nspred = M_.nspred; - iv = (1:endo_nbr)'; - ic = [ nstatic+(1:nspred) endo_nbr+(1:size(dr.ghx,2)-nspred) ]'; - StateSpaceModel.number_of_state_equations = M_.endo_nbr; - StateSpaceModel.number_of_state_innovations = M_.exo_nbr; - StateSpaceModel.sigma_e_is_diagonal = M_.sigma_e_is_diagonal; - StateSpaceModel.order_var = dr.order_var; - StateSpaceModel.observable_pos=options_.varobs_id; - first_call = 0; - clear('endo_nbr','nstatic','nspred','k'); + [dr,info,M_,oo_] = compute_decision_rules(M_,options_,oo_); end - [StateSpaceModel.transition_matrix,StateSpaceModel.impulse_matrix] = kalman_transition_matrix(dr,iv,ic,M_.exo_nbr); - StateSpaceModel.state_innovations_covariance_matrix = M_.Sigma_e; + M_ = set_measurement_errors(temp.pdraws{linee,1},temp.estim_params_,M_); - StateSpaceModel.measurement_error=M_.H; - clear('dr'); - [ConditionalVarianceDecomposition, ConditionalVarianceDecomposition_ME]=conditional_variance_decomposition(StateSpaceModel, Steps, ivar); + [ConditionalVarianceDecomposition, ConditionalVarianceDecomposition_ME] = ... + conditional_variance_decomposition(M_,options_,dr, Steps, ivar); Conditional_decomposition_array(:,:,:,linea) =ConditionalVarianceDecomposition; if ME_present Conditional_decomposition_array_ME(:,:,:,linea) =ConditionalVarianceDecomposition_ME; diff --git a/matlab/dsge_simulated_theoretical_variance_decomposition.m b/matlab/dsge_simulated_theoretical_variance_decomposition.m index e3de660b5183699c546334a8d48f46dd74dbaad9..305dc76d227d3772a6bb01a809c729c1a68ad134 100644 --- a/matlab/dsge_simulated_theoretical_variance_decomposition.m +++ b/matlab/dsge_simulated_theoretical_variance_decomposition.m @@ -56,7 +56,8 @@ if posterior delete_stale_file([M_.dname '/metropolis/' M_.fname '_PosteriorVarianceDecompME*']); else delete_stale_file([M_.dname '/prior/moments/' M_.fname '_PriorVarianceDecomposition*']); - delete_stale_file([M_.dname '/prior/moments/' M_.fname '_PriorVarianceDecompME*']);end + delete_stale_file([M_.dname '/prior/moments/' M_.fname '_PriorVarianceDecompME*']); +end % Set varlist (vartan) if ~posterior @@ -78,22 +79,17 @@ nvar = length(ivar); nar = options_.ar; options_.ar = 0; - - nexo = M_.exo_nbr; NumberOfSavedElementsPerSimulation = nvar*(nexo+1); MaXNumberOfDecompLines = ceil(options_.MaxNumberOfBytes/NumberOfSavedElementsPerSimulation/8); -ME_present=0; -if ~all(diag(M_.H)==0) - [observable_pos_requested_vars,index_subset,index_observables]=intersect(ivar,options_.varobs_id,'stable'); - if ~isempty(observable_pos_requested_vars) - ME_present=1; - nobs_ME=length(observable_pos_requested_vars); - NumberOfSavedElementsPerSimulation_ME = nobs_ME*(nexo+1); - MaXNumberOfDecompLines_ME = ceil(options_.MaxNumberOfBytes/NumberOfSavedElementsPerSimulation_ME/8); - end +[ME_present,observable_pos_requested_vars,index_subset,index_observables]=check_measurement_error_requested_vars(M_,options_,ivar); + +if ME_present && ~isempty(observable_pos_requested_vars) + nobs_ME=length(observable_pos_requested_vars); + NumberOfSavedElementsPerSimulation_ME = nobs_ME*(nexo+1); + MaXNumberOfDecompLines_ME = ceil(options_.MaxNumberOfBytes/NumberOfSavedElementsPerSimulation_ME/8); end if SampleSize<=MaXNumberOfDecompLines diff --git a/matlab/dyn_first_order_solver.m b/matlab/dyn_first_order_solver.m index 41d49cbdd543f4ea0ba539dedd37e2915d127229..01226aaeaec4682a5866eaf7dbc49ec1a286981d 100644 --- a/matlab/dyn_first_order_solver.m +++ b/matlab/dyn_first_order_solver.m @@ -65,7 +65,6 @@ if isempty(reorder_jacobian_columns) nstatic = DynareModel.nstatic; ndynamic = DynareModel.ndynamic; nsfwrd = DynareModel.nsfwrd; - n = DynareModel.endo_nbr; k1 = 1:(npred+nboth); k2 = 1:(nfwrd+nboth); @@ -76,16 +75,10 @@ if isempty(reorder_jacobian_columns) nz = nnz(lead_lag_incidence); lead_id = find(lead_lag_incidence(maximum_lag+2,:)); - lead_idx = lead_lag_incidence(maximum_lag+2,lead_id); if maximum_lag lag_id = find(lead_lag_incidence(1,:)); - lag_idx = lead_lag_incidence(1,lag_id); - static_id = find((lead_lag_incidence(1,:) == 0) & ... - (lead_lag_incidence(3,:) == 0)); else lag_id = []; - lag_idx = []; - static_id = find(lead_lag_incidence(2,:)==0); end both_id = intersect(lead_id,lag_id); @@ -277,7 +270,6 @@ if nstatic > 0 end end ghx = [temp; ghx]; - temp = []; end A_ = real([B_static C*gx+B_pred B_fyd]); % The state_variable of the block are located at [B_pred B_both] diff --git a/matlab/dynare_config.m b/matlab/dynare_config.m index c6617a02758fe5e7b832f43d01c2d629c4758c78..c272e937e5cc60591b07831ec9f559eafdaea111 100644 --- a/matlab/dynare_config.m +++ b/matlab/dynare_config.m @@ -59,6 +59,7 @@ p = {'/../contrib/jsonlab/' ; ... '/modules/dseries/src/' ; ... '/modules/reporting/macros/'; ... '/modules/reporting/src/' ; ... + '/moments/'; ... '/ms-sbvar/' ; ... '/ms-sbvar/identification/' ; ... '/nonlinear-filters/' ; ... diff --git a/matlab/moments/check_measurement_error_requested_vars.m b/matlab/moments/check_measurement_error_requested_vars.m new file mode 100644 index 0000000000000000000000000000000000000000..76bee009d90b1b135418bd15a58f90bea7320729 --- /dev/null +++ b/matlab/moments/check_measurement_error_requested_vars.m @@ -0,0 +1,45 @@ +function [ME_present,observable_pos_requested_vars,index_subset,index_observables]=check_measurement_error_requested_vars(M_,options_,ivar) +% [ME_present,observable_pos_requested_vars,index_subset,index_observables]=check_measurement_error_requested_vars(M_,options_,ivar) +% This function checks for the presence of measurement error and outputs +% the indices of the affected variables +% +% INPUTS +% M_ [struct] Matlab's structure describing the Model +% options_ [struct] Matlab's structure describing the options +% i_var : [double] Index of requested variables in declaration order +% +% OUTPUTS +% ME_present [boolean] indicator whether measurement error is present for requested variables +% observable_pos_requested_vars [integer] index of observables in list of endogenous variables +% index_subset [integer] index of observables in ivar +% index_observables [integer] index of requested i_var in observables + +% 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/>. + + +index_subset=[]; +index_observables=[]; +observable_pos_requested_vars=[]; + +ME_present=false; +if ~all(diag(M_.H)==0) + [observable_pos_requested_vars,index_subset,index_observables]=intersect(ivar,options_.varobs_id,'stable'); + if ~isempty(observable_pos_requested_vars) + ME_present=true; + end +end diff --git a/matlab/moments/compute_variance_decomposition.m b/matlab/moments/compute_variance_decomposition.m new file mode 100644 index 0000000000000000000000000000000000000000..97b7afde20570ce3ecbc783b54c4e27dee1aab70 --- /dev/null +++ b/matlab/moments/compute_variance_decomposition.m @@ -0,0 +1,64 @@ +function var_decomp=compute_variance_decomposition(M_,options_,var_stationary,A,A_stationary,ghu,ghu_states_only,stationary_vars,index_stationary_vars,nvars_requested) +% function var_decomp=compute_variance_decomposition(M_,options_,var_stationary,A,A_stationary,ghu,ghu_states_only,stationary_vars,index_stationary_vars,nvars_requested) +% Computes the theoretical auto-covariances, Gamma_y, for an AR(p) process +% with coefficients dr.ghx and dr.ghu and shock variances Sigma_e +% for a subset of variables ivar. +% Theoretical HP-filtering and band-pass filtering is available as an option +% +% INPUTS +% M_ [structure] Global dynare's structure, description of the DSGE model. +% options_ [structure] Global dynare's structure. +% var_stationary [double] unconditional variance of stationary +% variables +% A [double] State transition matrix +% A_stationary [double] Reaction of stationary variables to states +% ghu [double] Reaction of variables to shocks +% ghu_states_only [double] Reaction of stationary variables to shocks +% stationary_vars [integer] index of stationary vars in requested output +% index_stationary_vars [integer] index of stationary vars in decision rules +% nvars_requested [integer] number of originally requested variables +% +% OUTPUTS +% stationary_vars [double] [#stationary vars by shocks] Matrix containing the variance decomposition +% +% Copyright © 2001-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 M_.exo_nbr == 1 + var_decomp = ones(size(ghu,1),1); +else + var_decomp = NaN(nvars_requested,M_.exo_nbr); + cs = get_lower_cholesky_covariance(M_.Sigma_e,options_.add_tiny_number_to_cholesky); + b1 = ghu_states_only*cs; + b2 = ghu(index_stationary_vars,:)*cs; + variance_sum_loop = 0; + for i=1:M_.exo_nbr + if i==1 % first time, do Schur decomposition + variance_states = lyapunov_symm(A,b1(:,i)*b1(:,i)',options_.lyapunov_fixed_point_tol,options_.qz_criterium,options_.lyapunov_complex_threshold,1,options_.debug); + else + variance_states = lyapunov_symm(A,b1(:,i)*b1(:,i)',options_.lyapunov_fixed_point_tol,options_.qz_criterium,options_.lyapunov_complex_threshold,2,options_.debug); + end + vx2 = diag(A_stationary*variance_states*A_stationary'+b2(:,i)*b2(:,i)'); + var_decomp(stationary_vars,i) = vx2; + variance_sum_loop = variance_sum_loop +vx2; %track overall variance over shocks + end + if ~options_.pruning && max(abs(variance_sum_loop-var_stationary)./var_stationary) > 1e-4 + warning(['Aggregate variance and sum of variances by shocks ' ... + 'differ by more than 0.01 %']) + end + var_decomp(stationary_vars,:) = var_decomp(stationary_vars,:)./repmat(variance_sum_loop,1,M_.exo_nbr); +end \ No newline at end of file diff --git a/matlab/disp_th_moments.m b/matlab/moments/disp_th_moments.m similarity index 58% rename from matlab/disp_th_moments.m rename to matlab/moments/disp_th_moments.m index 46a05223f9c7bd8670118ed03af3036006c7c4dd..01c59e0ddb89f9f130458394a5fe223c99c2dc41 100644 --- a/matlab/disp_th_moments.m +++ b/matlab/moments/disp_th_moments.m @@ -1,8 +1,29 @@ function oo_ = disp_th_moments(dr, var_list, M_, options_, oo_) - +%oo_ = disp_th_moments(dr, var_list, M_, options_, oo_) % Display theoretical moments of variables +% INPUTS: +% dr : [struct] Dynare decision rules structure +% var_list [cell] list of variables considered +% M_ [struct] structure describing the Model +% options_ [struct] structure describing the options +% oo_ [struct] structure describing the Model +% +% OUTPUTS: +% oo_ [struct] structure describing the Model, containing +% gamma_y [cell] Matlab cell of nar+1 arrays, where nar is the order of the autocorrelation function. +% gamma_y{1} [double] Covariance matrix. +% gamma_y{i+1} [double] Autocorrelation function (for i=1,...,options_.ar). +% mean [vector] Unconditional mean +% var [matrix] Unconditional covariance matrix +% autocorr [cell] Cell storing the theoretical autocorrelation +% contemporaneous_correlation [matrix] matrix of contemporaneous correlations +% autocorr [cell] Cell storing the theoretical autocorrelation +% variance_decomposition [matrix] Unconditional variance decomposition matrix +% variance_decomposition_ME [matrix] Unconditional variance decomposition matrix with measurement error +% conditional_variance_decomposition [array] Conditional variance decomposition array +% conditional_variance_decomposition_ME [array] Conditional variance decomposition array with measurement error -% Copyright © 2001-2021 Dynare Team +% Copyright © 2001-2023 Dynare Team % % This file is part of Dynare. % @@ -53,24 +74,9 @@ z = [ m sd s2 ]; oo_.mean = m; oo_.var = oo_.gamma_y{1}; -ME_present=0; -if ~all(diag(M_.H)==0) - [observable_pos_requested_vars,index_subset,index_observables]=intersect(ivar,options_.varobs_id,'stable'); - if ~isempty(observable_pos_requested_vars) - ME_present=1; - end -end if size(stationary_vars, 1) > 0 - if ~nodecomposition - oo_.variance_decomposition=100*oo_.gamma_y{options_.ar+2}; - if ME_present - ME_Variance=diag(M_.H); - oo_.variance_decomposition_ME=oo_.variance_decomposition(index_subset,:).*repmat(diag(oo_.var(index_subset,index_subset))./(diag(oo_.var(index_subset,index_subset))+ME_Variance(index_observables)),1,M_.exo_nbr); - oo_.variance_decomposition_ME(:,end+1)=100-sum(oo_.variance_decomposition_ME,2); - end - end - if ~options_.noprint %options_.nomoments == 0 + if ~options_.noprint if options_.order == 2 title = 'APPROXIMATED THEORETICAL MOMENTS'; else @@ -86,61 +92,34 @@ if size(stationary_vars, 1) > 0 lh = cellofchararraymaxlength(labels)+2; dyn_latex_table(M_, options_, title, 'th_moments', headers, labels, z, lh, 11, 4); end + end + [ME_present,observable_pos_requested_vars,index_subset,index_observables]=check_measurement_error_requested_vars(M_,options_,ivar); + %store unconditional variance decomposition + if ~nodecomposition + oo_.variance_decomposition=100*oo_.gamma_y{options_.ar+2}; + if ME_present + ME_Variance=diag(M_.H); + oo_.variance_decomposition_ME=oo_.variance_decomposition(index_subset,:).*repmat(diag(oo_.var(index_subset,index_subset))./(diag(oo_.var(index_subset,index_subset))+ME_Variance(index_observables)),1,M_.exo_nbr); + oo_.variance_decomposition_ME(:,end+1)=100-sum(oo_.variance_decomposition_ME,2); + end + end + if ~options_.noprint %options_.nomoments == 0 if M_.exo_nbr > 1 && ~nodecomposition - skipline() - if options_.order == 2 - title = 'APPROXIMATED VARIANCE DECOMPOSITION (in percent)'; - else - title = 'VARIANCE DECOMPOSITION (in percent)'; - end - title = add_filter_subtitle(title, options_); - headers = M_.exo_names; - headers = vertcat(' ', headers); - labels=get_labels_transformed_vars(M_.endo_names,ivar(stationary_vars),options_,false); - lh = cellofchararraymaxlength(labels)+2; - dyntable(options_, title, headers, labels, 100*oo_.gamma_y{options_.ar+2}(stationary_vars,:), lh, 8, 2); - if ME_present - [stationary_observables, pos_index_subset] = intersect(index_subset, stationary_vars, 'stable'); - headers_ME = vertcat(headers, 'ME'); - labels=get_labels_transformed_vars(M_.endo_names,ivar(stationary_observables),options_,false); - dyntable(options_, [title,' WITH MEASUREMENT ERROR'], headers_ME, labels, ... - oo_.variance_decomposition_ME(pos_index_subset,:), lh, 8, 2); - end - if options_.TeX - headers = M_.exo_names_tex; - headers = vertcat(' ', headers); - labels=get_labels_transformed_vars(M_.endo_names_tex,ivar(stationary_vars),options_,true); - lh = cellofchararraymaxlength(labels)+2; - dyn_latex_table(M_, options_, title, 'th_var_decomp_uncond', headers, labels, 100*oo_.gamma_y{options_.ar+2}(stationary_vars,:), lh, 8, 2); - if ME_present - headers_ME = vertcat(headers, 'ME'); - labels=get_labels_transformed_vars(M_.endo_names_tex,ivar(stationary_observables),options_,true); - dyn_latex_table(M_, options_, [title,' WITH MEASUREMENT ERROR'], ... - 'th_var_decomp_uncond_ME', headers_ME, labels, oo_.variance_decomposition_ME(pos_index_subset,:), lh, 8, 2); - end - end + display_unconditional_variance_decomposition(M_,options_,oo_,ivar,stationary_vars,index_subset,ME_present) end end - conditional_variance_steps = options_.conditional_variance_decomposition; - if ~isempty(conditional_variance_steps) - StateSpaceModel.number_of_state_equations = M_.endo_nbr; - StateSpaceModel.number_of_state_innovations = M_.exo_nbr; - StateSpaceModel.sigma_e_is_diagonal = M_.sigma_e_is_diagonal; - [StateSpaceModel.transition_matrix, StateSpaceModel.impulse_matrix] = ... - kalman_transition_matrix(dr,(1:M_.endo_nbr)',M_.nstatic+(1:M_.nspred)',M_.exo_nbr); - StateSpaceModel.state_innovations_covariance_matrix = M_.Sigma_e; - StateSpaceModel.order_var = dr.order_var; - StateSpaceModel.measurement_error = M_.H; - StateSpaceModel.observable_pos = options_.varobs_id; - [oo_.conditional_variance_decomposition, oo_.conditional_variance_decomposition_ME] = ... - conditional_variance_decomposition(StateSpaceModel, conditional_variance_steps, ivar); - if ~options_.noprint - display_conditional_variance_decomposition(oo_.conditional_variance_decomposition, conditional_variance_steps, ivar, M_, options_); - if ME_present - display_conditional_variance_decomposition(oo_.conditional_variance_decomposition_ME, conditional_variance_steps, ... - observable_pos_requested_vars, M_, options_); - end +end +%% Conditional variance decomposition +conditional_variance_steps = options_.conditional_variance_decomposition; +if ~isempty(conditional_variance_steps) + [oo_.conditional_variance_decomposition, oo_.conditional_variance_decomposition_ME] = ... + conditional_variance_decomposition(M_,options_,dr, conditional_variance_steps, ivar); + if ~options_.noprint + display_conditional_variance_decomposition(oo_.conditional_variance_decomposition, conditional_variance_steps, ivar, M_, options_); + if ME_present + display_conditional_variance_decomposition(oo_.conditional_variance_decomposition_ME, conditional_variance_steps, ... + observable_pos_requested_vars, M_, options_); end end end @@ -195,13 +174,13 @@ if options_.ar > 0 && size(stationary_vars, 1) > 0 title = 'COEFFICIENTS OF AUTOCORRELATION'; end title = add_filter_subtitle(title, options_); - labels=get_labels_transformed_vars(M_.endo_names,ivar(i1),options_,false); - headers = vertcat('Order ', cellstr(int2str([1:options_.ar]'))); + labels=get_labels_transformed_vars(M_.endo_names,ivar(i1),options_,false); + headers = vertcat('Order ', cellstr(int2str((1:options_.ar)'))); lh = cellofchararraymaxlength(labels)+2; dyntable(options_, title, headers, labels, z, lh, 8, 4); if options_.TeX labels=get_labels_transformed_vars(M_.endo_names_tex,ivar(i1),options_,true); - headers = vertcat('Order ', cellstr(int2str([1:options_.ar]'))); + headers = vertcat('Order ', cellstr(int2str((1:options_.ar)'))); lh = cellofchararraymaxlength(labels)+2; dyn_latex_table(M_, options_, title, 'th_autocorr_matrix', headers, labels, z, lh, 8, 4); end diff --git a/matlab/disp_th_moments_pruned_state_space.m b/matlab/moments/disp_th_moments_pruned_state_space.m similarity index 51% rename from matlab/disp_th_moments_pruned_state_space.m rename to matlab/moments/disp_th_moments_pruned_state_space.m index 5675fabe3f8bbf8da35d94970ca1c1efa22b964c..8db2dad713d9b03f2aae2e0aec0f4b047d8b4757 100644 --- a/matlab/disp_th_moments_pruned_state_space.m +++ b/matlab/moments/disp_th_moments_pruned_state_space.m @@ -4,23 +4,27 @@ function oo_=disp_th_moments_pruned_state_space(dr,M_,options_,i_var,oo_) % pruned state-space % % INPUTS: -% dr : Dynare decision rules structure -% M_ : Matlab's structure describing the Model (initialized by dynare, see @ref{M_}). -% options_ : Matlab's structure describing the options (initialized by dynare, see @ref{options_}). -% i_var : Index of requested variables in declaration order -% oo_ : Matlab's structure describing the Model (initialized by dynare, see @ref{M_}), containing +% dr : [struct] Dynare decision rules structure +% M_ [struct] structure describing the Model +% options_ [struct] structure describing the options +% i_var [double] Index of requested variables in declaration order +% oo_ [struct] structure describing the Model % % OUTPUTS: -% oo_ : Matlab's structure describing the Model (initialized by dynare, see @ref{M_}), containing -% gamma_y [cell] Matlab cell of nar+1 arrays, where nar is the order of the autocorrelation function. -% gamma_y{1} [double] Covariance matrix. -% gamma_y{i+1} [double] Autocorrelation function (for i=1,...,options_.ar). -% mean [vector] Unconditional mean -% var [matrix] Unconditional covariance matrix -% autocorr [cell] Cell storing the theoretical autocorrelation -% contemporaneous_correlation [matrix] matrix of contemporaneous correlations -% -% Copyright © 2020 Dynare Team +% gamma_y [cell] Matlab cell of nar+1 arrays, where nar is the order of the autocorrelation function. +% gamma_y{1} [double] Covariance matrix. +% gamma_y{i+1} [double] Autocorrelation function (for i=1,...,options_.ar). +% mean [vector] Unconditional mean +% var [matrix] Unconditional covariance matrix +% autocorr [cell] Cell storing the theoretical autocorrelation +% contemporaneous_correlation [matrix] matrix of contemporaneous correlations +% autocorr [cell] Cell storing the theoretical autocorrelation +% variance_decomposition [matrix] Unconditional variance decomposition matrix +% variance_decomposition_ME [matrix] Unconditional variance decomposition matrix with measurement error +% conditional_variance_decomposition [array] Conditional variance decomposition array +% conditional_variance_decomposition_ME [array] Conditional variance decomposition array with measurement error + +% Copyright © 2020-2023 Dynare Team % % This file is part of Dynare. % @@ -123,4 +127,38 @@ if options_.ar > 0 %&& size(stationary_vars, 1) > 0 dyn_latex_table(M_,options_,title,'th_autocorr_matrix',headers,labels,z,lh,8,4); end end +end + +if options_.order==2 && ~options_.nodecomposition && M_.exo_nbr > 1% do variance decomposition + index_stationary_vars = dr.inv_order_var(i_var); %no nonstationary variables in pruning + ghu_states_only = zeros(M_.nspred,M_.exo_nbr); + ghu_states_only(1:M_.nspred,:) = dr.ghu(M_.nstatic+(1:M_.nspred),:); %get shock impact on states only + [A] = kalman_transition_matrix(dr,M_.nstatic+(1:M_.nspred)',1:M_.nspred); + oo_.gamma_y{options_.ar+2}=compute_variance_decomposition(M_,options_,s2,A,dr.ghx(index_stationary_vars,:),dr.ghu,ghu_states_only,1:length(i_var),index_stationary_vars,nvars); + + [ME_present,observable_pos_requested_vars,index_subset,index_observables]=check_measurement_error_requested_vars(M_,options_,i_var); + %store unconditional variance decomposition + oo_.variance_decomposition=100*oo_.gamma_y{options_.ar+2}; + if ME_present + ME_Variance=diag(M_.H); + oo_.variance_decomposition_ME=oo_.variance_decomposition(index_subset,:).*repmat(diag(oo_.var(index_subset,index_subset))./(diag(oo_.var(index_subset,index_subset))+ME_Variance(index_observables)),1,M_.exo_nbr); + oo_.variance_decomposition_ME(:,end+1)=100-sum(oo_.variance_decomposition_ME,2); + end + if ~options_.noprint %options_.nomoments == 0 + display_unconditional_variance_decomposition(M_,options_,oo_,i_var,1:length(i_var),index_subset,ME_present) + end + + %% Conditional variance decomposition + conditional_variance_steps = options_.conditional_variance_decomposition; + if ~isempty(conditional_variance_steps) + [oo_.conditional_variance_decomposition, oo_.conditional_variance_decomposition_ME] = ... + conditional_variance_decomposition(M_,options_,dr, conditional_variance_steps, i_var); + if ~options_.noprint + display_conditional_variance_decomposition(oo_.conditional_variance_decomposition, conditional_variance_steps, i_var, M_, options_); + if ME_present + display_conditional_variance_decomposition(oo_.conditional_variance_decomposition_ME, conditional_variance_steps, ... + observable_pos_requested_vars, M_, options_); + end + end + end end \ No newline at end of file diff --git a/matlab/display_conditional_variance_decomposition.m b/matlab/moments/display_conditional_variance_decomposition.m similarity index 100% rename from matlab/display_conditional_variance_decomposition.m rename to matlab/moments/display_conditional_variance_decomposition.m diff --git a/matlab/moments/display_unconditional_variance_decomposition.m b/matlab/moments/display_unconditional_variance_decomposition.m new file mode 100644 index 0000000000000000000000000000000000000000..df547d02cf12d4083605c385c3905d20f8ca921a --- /dev/null +++ b/matlab/moments/display_unconditional_variance_decomposition.m @@ -0,0 +1,67 @@ +function display_unconditional_variance_decomposition(M_,options_,oo_,ivar,stationary_vars,index_subset,ME_present) +% display_unconditional_variance_decomposition(M_,options_,oo_,ivar,stationary_vars,index_subset,ME_present) +% This function displays the unconditional variance decomposition +% +% INPUTS +% M_ [struct] Matlab's structure describing the Model (initialized by dynare, see @ref{M_}). +% options_ [struct] Matlab's structure describing the options (initialized by dynare, see @ref{options_}). +% oo_ [struct] structure describing the Model +% i_var [double] Index of requested variables in declaration order +% stationary_vars [double] index of stationary vars in requested output +% index_subset [integer] index of observables in requested variables +% ME_present [boolean] indicator whether measurement error is present for requested variables +% +% OUTPUTS +% None + +% 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 M_.exo_nbr > 1 + skipline() + if options_.order == 2 + title = 'APPROXIMATED VARIANCE DECOMPOSITION (in percent)'; + else + title = 'VARIANCE DECOMPOSITION (in percent)'; + end + title = add_filter_subtitle(title, options_); + headers = M_.exo_names; + headers = vertcat(' ', headers); + labels=get_labels_transformed_vars(M_.endo_names,ivar(stationary_vars),options_,false); + lh = cellofchararraymaxlength(labels)+2; + dyntable(options_, title, headers, labels, 100*oo_.gamma_y{options_.ar+2}(stationary_vars,:), lh, 8, 2); + if ME_present + [stationary_observables, pos_index_subset] = intersect(index_subset, stationary_vars, 'stable'); + headers_ME = vertcat(headers, 'ME'); + labels=get_labels_transformed_vars(M_.endo_names,ivar(stationary_observables),options_,false); + dyntable(options_, [title,' WITH MEASUREMENT ERROR'], headers_ME, labels, ... + oo_.variance_decomposition_ME(pos_index_subset,:), lh, 8, 2); + end + if options_.TeX + headers = M_.exo_names_tex; + headers = vertcat(' ', headers); + labels=get_labels_transformed_vars(M_.endo_names_tex,ivar(stationary_vars),options_,true); + lh = cellofchararraymaxlength(labels)+2; + dyn_latex_table(M_, options_, title, 'th_var_decomp_uncond', headers, labels, 100*oo_.gamma_y{options_.ar+2}(stationary_vars,:), lh, 8, 2); + if ME_present + headers_ME = vertcat(headers, 'ME'); + labels=get_labels_transformed_vars(M_.endo_names_tex,ivar(stationary_observables),options_,true); + dyn_latex_table(M_, options_, [title,' WITH MEASUREMENT ERROR'], ... + 'th_var_decomp_uncond_ME', headers_ME, labels, oo_.variance_decomposition_ME(pos_index_subset,:), lh, 8, 2); + end + end +end \ No newline at end of file diff --git a/matlab/th_autocovariances.m b/matlab/moments/th_autocovariances.m similarity index 85% rename from matlab/th_autocovariances.m rename to matlab/moments/th_autocovariances.m index dbcbcd56e42ad50ee2e8ab92310528a1b486f6b6..a3255e237a27288b18443185e36f40ff8bce0ff6 100644 --- a/matlab/th_autocovariances.m +++ b/matlab/moments/th_autocovariances.m @@ -100,16 +100,16 @@ ghu_states_only(1:M_.nspred,:) = ghu(index_states,:); %get shock impact on state % Compute stationary variables for unfiltered moments (filtering will remove unit roots) if options_.hp_filter ~= 0 || options_.bandpass.indicator % By construction, all variables are stationary when filtered - iky = inv_order_var(ivar); + index_stationary_vars = inv_order_var(ivar); stationary_vars = (1:length(ivar))'; else [variance_states, unit_root_Schur_vector] = lyapunov_symm(A,B*M_.Sigma_e*B',options_.lyapunov_fixed_point_tol,options_.qz_criterium,options_.lyapunov_complex_threshold,[],options_.debug); - iky = inv_order_var(ivar); + index_stationary_vars = inv_order_var(ivar); stationary_vars = (1:length(ivar))'; if ~isempty(unit_root_Schur_vector) x = abs(ghx*unit_root_Schur_vector); - iky = iky(all(x(iky,:) < options_.schur_vec_tol,2)); stationary_vars = find(all(x(inv_order_var(ivar),:) < options_.schur_vec_tol,2)); + index_stationary_vars = inv_order_var(ivar(stationary_vars)); end end @@ -119,17 +119,17 @@ if local_order == 2 % mean correction for 2nd order with no filters; oth Ex = (dr.ghs2(index_states)+dr.ghxx(index_states,:)*variance_states(:)+dr.ghuu(index_states,:)*M_.Sigma_e(:))/2; Ex = (eye(length(M_.nspred))-ghx(index_states,:))\Ex; Gamma_y{nar+3} = NaN*ones(nvar, 1); - Gamma_y{nar+3}(stationary_vars) = ghx(iky,:)*Ex+(dr.ghs2(iky)+dr.ghxx(iky,:)*variance_states(:)+... - dr.ghuu(iky,:)*M_.Sigma_e(:))/2; + Gamma_y{nar+3}(stationary_vars) = ghx(index_stationary_vars,:)*Ex+(dr.ghs2(index_stationary_vars)+dr.ghxx(index_stationary_vars,:)*variance_states(:)+... + dr.ghuu(index_stationary_vars,:)*M_.Sigma_e(:))/2; else %no static and no predetermined Gamma_y{nar+3} = NaN*ones(nvar, 1); - Gamma_y{nar+3}(stationary_vars) = (dr.ghs2(iky)+ dr.ghuu(iky,:)*M_.Sigma_e(:))/2; + Gamma_y{nar+3}(stationary_vars) = (dr.ghs2(index_stationary_vars)+ dr.ghuu(index_stationary_vars,:)*M_.Sigma_e(:))/2; end end if options_.hp_filter == 0 && ~options_.bandpass.indicator - aa = ghx(iky,:); - bb = ghu(iky,:); + aa = ghx(index_stationary_vars,:); + bb = ghu(index_stationary_vars,:); % unconditional variance v = NaN*ones(nvar,nvar); v(stationary_vars,stationary_vars) = aa*variance_states*aa'+ bb*M_.Sigma_e*bb'; @@ -151,35 +151,11 @@ if options_.hp_filter == 0 && ~options_.bandpass.indicator end % variance decomposition if ~nodecomposition && M_.exo_nbr > 0 && size(stationary_vars, 1) > 0 - if M_.exo_nbr == 1 - Gamma_y{nar+2} = ones(nvar,1); - else - Gamma_y{nar+2} = NaN(nvar,M_.exo_nbr); - cs = get_lower_cholesky_covariance(M_.Sigma_e,options_.add_tiny_number_to_cholesky); - b1 = ghu_states_only*cs; - b2 = ghu(iky,:)*cs; - variance_states = lyapunov_symm(A,b1*b1',options_.lyapunov_fixed_point_tol,options_.qz_criterium,options_.lyapunov_complex_threshold,1,options_.debug); - vv = diag(aa*variance_states*aa'+b2*b2'); - variance_sum_loop = 0; - for i=1:M_.exo_nbr - variance_states = lyapunov_symm(A,b1(:,i)*b1(:,i)',options_.lyapunov_fixed_point_tol,options_.qz_criterium,options_.lyapunov_complex_threshold,2,options_.debug); - vx2 = diag(aa*variance_states*aa'+b2(:,i)*b2(:,i)'); - Gamma_y{nar+2}(stationary_vars,i) = vx2; - variance_sum_loop = variance_sum_loop +vx2; %track overall variance over shocks - end - if max(abs(variance_sum_loop-vv)./vv) > 1e-4 - warning(['Aggregate variance and sum of variances by shocks ' ... - 'differ by more than 0.01 %']) - end - for i=1:M_.exo_nbr - Gamma_y{nar+2}(stationary_vars,i) = Gamma_y{nar+ ... - 2}(stationary_vars,i)./variance_sum_loop; - end - end + Gamma_y{nar+2}=compute_variance_decomposition(M_,options_,diag(v(stationary_vars,stationary_vars)),A,aa,ghu,ghu_states_only,stationary_vars,index_stationary_vars,nvar); end else% ==> Theoretical filters. - aa = ghx(iky,:); %R in Uhlig (2001) - bb = ghu(iky,:); %S in Uhlig (2001) + aa = ghx(index_stationary_vars,:); %R in Uhlig (2001) + bb = ghu(index_stationary_vars,:); %S in Uhlig (2001) ngrid = options_.filtered_theoretical_moments_grid; freqs = 0 : ((2*pi)/ngrid) : (2*pi*(1 - .5/ngrid)); %[0,2*pi) @@ -230,7 +206,7 @@ else% ==> Theoretical filters. cs = get_lower_cholesky_covariance(M_.Sigma_e); %make sure Covariance matrix is positive definite SS = cs*cs'; b1 = ghu_states_only; - b2 = ghu(iky,:); + b2 = ghu(index_stationary_vars,:); mathp_col = NaN(ngrid,length(ivar)^2); IA = eye(size(A,1)); IE = eye(M_.exo_nbr);