function oo_ = shock_decomposition(oo_, M_, options_, vname) % function oo_ = shock_decomposition(oo_, M_, options_, vname) % % INPUTS % - oo_ [structure] Matlab's structure containing the results (oo_). % - M_ [structure] Matlab's structure describing the model (M_). % - options_ [structure] Matlab's structure describing the current options (options_). % - vname [cell] array of variable names % OUTPUT % - oo_ [structure] Matlab's structure containing the results (oo_). % Copyright © 2021 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 . % list of options % T0, use_shock_groups, vname, file_name, nfrcst, init_names_ shock_decomp_options = options_.occbin.shock_decomp; if nargin<4 || isempty(vname) vname=cellstr(M_.endo_names(1:M_.orig_endo_nbr,:)); end opts_simul = options_.occbin.simul; opts_simul.periods = shock_decomp_options.periods; opts_simul.check_ahead_periods = shock_decomp_options.check_ahead_periods; opts_simul.maxit = shock_decomp_options.maxit; use_shock_groups = shock_decomp_options.use_shock_groups; init_names_ = shock_decomp_options.init_names_; nfrcst = shock_decomp_options.nfrcst; %% new dynare grouping if isempty(use_shock_groups) use_shock_groups = 'ALL'; ngroups = M_.exo_nbr; ex_names_ = cell(ngroups,1); for i=1:ngroups ex_names_{i} = M_.exo_names(i); end shock_decomp_options.main_effect=0; shock_decomp_options.additive = 0; else shock_groups = M_.shock_groups.(use_shock_groups); shock_ind = fieldnames(shock_groups); ngroups = length(shock_ind); ex_names_ = shock_ind; for i=1:ngroups ex_names_{i} = shock_groups.(shock_ind{i}).shocks; end end %% if iscell(vname{1}) vname0=vname; clear vname vname = cell(1,length(vname0)); decomp_type = cell(1,length(vname0)); gtrend = cell(1,length(vname0)); var_type = nan(1,length(vname0)); for j=1:length(vname0) vname{j}=vname0{j}{1}; decomp_type{j}=vname0{j}{2}; if strcmpi(decomp_type{j},'aoa') gtrend{j}=vname0{j}{3}; if strcmpi(vname0{j}{4},'flow') var_type(j)=1; elseif strcmpi(vname0{j}{4},'deflator') var_type(j)=2; elseif strcmpi(vname0{j}{4},'stock') var_type(j)=0; else error('wrong var type for aoa decomp') end end end clear vname0 else decomp_type = cell(1,length(vname)); for j=1:length(vname) decomp_type{j}='qoq'; end end % set time-varying state space matrices TT = oo_.occbin.smoother.T0; RR = oo_.occbin.smoother.R0; CC = oo_.occbin.smoother.C0; load (options_.datafile, 'T'); indx_init=zeros(length(init_names_),1); for j=1:length(init_names_) indx_init(j)=strmatch(init_names_{j},M_.endo_names(oo_.dr.order_var,:),'exact'); end if shock_decomp_options.debug % re-compute smoothed variables from T, R and smoothed shocks etahat a1=oo_.occbin.smoother.alphahat(:,1); as=a1; as0=zeros(length(a1),1); as0(indx_init)=a1(indx_init); etahat=[oo_.occbin.smoother.etahat zeros(size(oo_.occbin.smoother.etahat,1),nfrcst)]; for j=1:size(etahat,2)-1 TM = TT(:,:,j+1); RM = RR(:,:,j+1); CONST = CC(:,j+1); as(:,j+1)=TM*as(:,j)+RM*etahat(:,j+1)+CONST; as0(:,j+1)=TM*as0(:,j)+CONST; end err = max(max(abs(oo_.occbin.smoother.alphahat-as))); if err>1e-8 disp('WARNING CHECK SMOOTHER:') disp(['simulated model with smoothed shocks differs from stored smoother by ' num2str(err)]) else disp('CHECK SMOOTHER OK:') disp(['simulated model with smoothed shocks differs from stored smoother by less than 1e-8 (err=' num2str(err) ')']) end else etahat=[oo_.occbin.smoother.etahat zeros(size(oo_.occbin.smoother.etahat,1),nfrcst)]; as = oo_.occbin.smoother.alphahat; end gend=size(etahat,2); %% TT= 0:0.25:ceil(gend/4+1); TT=TT(1:gend); TT1= dates('0Q1'):(dates('0Q1')+gend-1); if exist('T','var') TT=T(options_.first_obs)+TT; TT1=TT1+T(options_.first_obs)*4; end shock_decomp_options = set_default_option(shock_decomp_options,'TINIT',TT1(1)); tinit = max([1,find(TT1==shock_decomp_options.TINIT)]); TINIT = char(TT1(tinit)); shock_decomp_options = set_default_option(shock_decomp_options,'file_name',['_' use_shock_groups '_' TINIT]); file_name = shock_decomp_options.file_name; %% %%%%%%%%%%%%%%%%%%%% LINEAR shock decomp as_lin=zeros(M_.endo_nbr,length(tinit:gend)); % linear smoother reconstructed att=zeros(M_.endo_nbr,length(tinit:gend)); % linear initial condition effect inn=zeros(M_.endo_nbr,length(tinit:gend)); % linear aggreage shocks effect without att, i.e. as_lin = inn+att; deco=zeros(M_.endo_nbr,M_.exo_nbr,length(tinit:gend)); % full decomposition into individual shocks att(:,1)=oo_.occbin.linear_smoother.alphahat(:,tinit); as_lin(:,1)=oo_.occbin.linear_smoother.alphahat(:,tinit); TM = oo_.occbin.linear_smoother.T0; RM= oo_.occbin.linear_smoother.R0; for j=2:length(tinit:gend) as_lin(:,j) = TM*as_lin(:,j-1)+RM*oo_.occbin.linear_smoother.etahat(:,j+tinit-1); att(:,j) = TM*att(:,j-1); inn(:,j) = RM*oo_.occbin.linear_smoother.etahat(:,j+tinit-1); if j>1 inn(:,j) = inn(:,j) + TM*inn(:,j-1); end for iexo=1:M_.exo_nbr deco(:,iexo,j) = RM(:,iexo)*oo_.occbin.linear_smoother.etahat(iexo,j+tinit-1); if j>1 deco(:,iexo,j) = deco(:,iexo,j) + TM*deco(:,iexo,j-1); end end end as_lin=as_lin(oo_.dr.inv_order_var,:); % linear smoother reconstructed att=att(oo_.dr.inv_order_var,:); % linear initial condition effect inn=inn(oo_.dr.inv_order_var,:); % linear aggreage shocks effect without att deco=deco(oo_.dr.inv_order_var,:,:); % full decomposition into individual shocks deco(:,M_.exo_nbr+1,:)=att; deco(:,M_.exo_nbr+2,:)=as_lin; oo_.occbin.linear_smoother.decomp=deco; %%%%%%%%%%%%%%%%%%%% END LINEAR shock decomp %% %%%%%%%%%%%%%%%%%%%% piecewise COONDITIONAL shock decomp as_p=zeros(M_.endo_nbr,length(tinit:gend)); % smoother reconstructed att_p=zeros(M_.endo_nbr,length(tinit:gend)); % initial condition effect inn_p=zeros(M_.endo_nbr,length(tinit:gend)); % aggreage shocks effect without att, i.e. as_lin = inn+att; deco_p=zeros(M_.endo_nbr,M_.exo_nbr,length(tinit:gend)); % full decomposition into individual shocks reg_p=zeros(M_.endo_nbr,length(tinit:gend)); % pure regime effect (CONST 'shocks') att_p(:,1)=oo_.occbin.smoother.alphahat(:,tinit); as_p(:,1)=oo_.occbin.smoother.alphahat(:,tinit); TT = oo_.occbin.smoother.T0; RR= oo_.occbin.smoother.R0; CC= oo_.occbin.smoother.C0; for j=2:length(tinit:gend) TM = TT(:,:,j+tinit-1); RM = RR(:,:,j+tinit-1); CONST = CC(:,j+tinit-1); as_p(:,j) = TM*as_p(:,j-1)+RM*oo_.occbin.smoother.etahat(:,j+tinit-1)+CONST; att_p(:,j) = TM*att_p(:,j-1); inn_p(:,j) = RM*oo_.occbin.smoother.etahat(:,j+tinit-1); reg_p(:,j) = TM*reg_p(:,j-1)+CONST; if j>1 inn_p(:,j) = inn_p(:,j) + TM*inn_p(:,j-1) ; end for iexo=1:M_.exo_nbr deco_p(:,iexo,j) = RM(:,iexo)*oo_.occbin.smoother.etahat(iexo,j+tinit-1); if j>1 deco_p(:,iexo,j) = deco_p(:,iexo,j) + TM*deco_p(:,iexo,j-1); end end end as_p=as_p(oo_.dr.inv_order_var,:); % occbin smoother reconstructed att_p=att_p(oo_.dr.inv_order_var,:); % occbin initial condition effect inn_p=inn_p(oo_.dr.inv_order_var,:); % occbin aggregage shocks effect without att deco_p=deco_p(oo_.dr.inv_order_var,:,:); % occbin full decomposition into individual shocks reg_p=reg_p(oo_.dr.inv_order_var,:); % occbin pure regime effect (CONST 'shocks') i_reg=strmatch('EPS_REGIME',M_.exo_names,'exact'); if ~isempty(i_reg) deco_p(:,i_reg,:)=reg_p; end deco_p(:,M_.exo_nbr+1,:)=att_p; deco_p(:,M_.exo_nbr+2,:)=as_p; %deco_p(:,M_.exo_nbr+3,:)=as_p-reg_p; oo_.occbin.smoother.decomp=deco_p; rr=abs(deco_p(:,1:end-1,:)); if isequal(use_shock_groups,'ALL') && ~isempty(i_reg) rr(:,i_reg,:)=0; end ww=zeros(size(rr)); for k=1:size(rr,3) tmp=sum(rr(:,:,k),2); tmp(tmp<1.e-10)=1; for g=1:size(rr,2) ww(:,g,k) = rr(:,g,k)./tmp; end end wdeco_p=deco_p; if ~isempty(i_reg) wdeco_p(:,i_reg,:)=0; end for k=1:size(rr,3) if any(any(reg_p(:,k))) for g=1:size(rr,2) wdeco_p(:,g,k) = wdeco_p(:,g,k)+reg_p(:,k).*ww(:,g,k); end end end oo_.occbin.smoother.wdecomp=wdeco_p; %%%%%%%%%%%%%%%%%%%% END CONDITIONAL shock decomp %% add here other fetures when ready % if shock_decomp_options.conditional_only ==1 % return % end