dynare/matlab/+occbin/shock_decomposition.m

267 lines
9.0 KiB
Matlab

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 <https://www.gnu.org/licenses/>.
% 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