2017-10-10 09:22:52 +02:00
function [deviations, baseline, irfs] = backward_model_irf ( initialcondition, innovationbaseline, listofshocks, listofvariables, varargin)
2017-05-18 13:43:13 +02:00
% Returns impulse response functions.
%
2017-10-10 09:22:52 +02:00
% INPUTS
2017-10-12 12:11:30 +02:00
% - initialcondition [dseries] Initial conditions for the endogenous variables, or period 0.
% - innovationbaseline [dseries] Baseline for the future innovations. If empty the baseline scenario is zero for future shocks.
% - listofshocks [cell of strings or dseries] The innovations for which the IRFs need to be computed.
% - listofvariables [cell of strings] The endogenous variables which will be returned.
% - periods [integer] scalar, the number of periods.
2017-05-18 13:43:13 +02:00
%
2017-10-10 09:22:52 +02:00
% OUTPUTS
% - irfs [struct of dseries]
2017-05-18 13:43:13 +02:00
%
2017-10-10 09:22:52 +02:00
% REMARKS
% - The names of the fields in the returned structure are given by the name
% of the innovations listed in the second input argument. Each field gather
% the associated paths for endogenous variables listed in the third input
% argument.
% - If second argument is not empty, periods must not be greater than innovationbaseline.nobs.
2017-05-18 13:43:13 +02:00
2017-10-10 10:05:59 +02:00
% Copyright (C) 2017-2018 Dynare Team
2017-05-18 13:43:13 +02:00
%
% 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 <http://www.gnu.org/licenses/>.
global M_ options_ oo_
% Check that the model is actually backward
if M_ . maximum_lead
2018-03-01 09:29:48 +01:00
error ( ' backward_model_irf:: The specified model is not backward looking!' )
2017-05-18 13:43:13 +02:00
end
% Set default value for the fourth input argument.
2017-10-10 09:22:52 +02:00
if nargin < 5
2017-05-18 13:43:13 +02:00
periods = 40 ;
2017-06-01 15:16:00 +02:00
else
periods = varargin { 1 } ;
2017-05-18 13:43:13 +02:00
end
% Set default value for the last input argument (no transformation).
2017-10-10 09:22:52 +02:00
if nargin < 6
2017-05-18 13:43:13 +02:00
notransform = true ;
else
notransform = false ;
2017-06-01 15:16:00 +02:00
transform = varargin { 2 } ;
2017-05-18 13:43:13 +02:00
end
2017-10-12 12:11:30 +02:00
% Check third argument.
if ~ iscell ( listofshocks )
error ( ' Third input argument has to be a cell of string or dseries objects!' )
else
if all ( cellfun ( @ ischar , listofshocks ) )
deterministicshockflag = false ;
elseif all ( cellfun ( @ isdseries , listofshocks ) )
deterministicshockflag = true ;
else
error ( ' Elements of third input argument must all be char arrays or dseries objects!' )
end
if deterministicshockflag
numberofexperiments = length ( listofshocks ) ;
2017-10-10 10:05:59 +02:00
exonames = M_ . exo_names ;
2017-10-12 12:11:30 +02:00
initialconditionperiod = initialcondition . dates ( end ) ;
for i = 1 : numberofexperiments
shock = listofshocks { i } ;
impulsenames = shock . name ;
listofunknownexo = setdiff ( impulsenames , exonames ) ;
if ~ isempty ( listofunknownexo )
disp ( listofunknownexo )
error ( ' In experiment n°%s, some of the declared shocks are unknown!' , int2str ( i ) )
end
if initialconditionperiod > = shock . dates ( 1 )
error ( ' In experiment n°%s, the shock period must follow %s!' , string ( initialconditionperiod ) )
end
end
end
end
2018-03-01 09:29:48 +01:00
% Set default initial conditions for the innovations.
for i = 1 : M_ . exo_nbr
if ~ ismember ( M_ . exo_names { i } , initialcondition . name )
initialcondition { M_ . exo_names { i } } = dseries ( zeros ( initialcondition . nobs , 1 ) , initialcondition . dates ( 1 ) , M_ . exo_names { i } ) ;
end
end
2017-10-10 09:22:52 +02:00
% Set default values for the baseline paths.
%
% TODO zero for all variables is probably a poor choice. It should be
% zero for additive exogenous variables and 1 for multiplicative
% exogenous variables.
Innovations = zeros ( periods , M_ . exo_nbr ) ;
if ~ isempty ( innovationbaseline )
if ~ isdseries ( innovationbaseline )
error ( ' If not empty, the second argument has to be a dseries object!' )
end
if ~ isequal ( innovationbaseline . dates ( 1 ) - initialcondition . dates ( end ) , 1 )
error ( ' The first date of the second input argument must follow the last date of the first input argument!' )
end
if innovationbaseline . nobs < periods
error ( ' The second input argument must at least have %s observations or lower the number of periods.' , periods )
end
% Fill innovations with provided paths for the innovations.
2017-10-10 10:05:59 +02:00
exonames = M_ . exo_names ;
2017-10-10 09:22:52 +02:00
for i = 1 : length ( exonames )
if ~ isempty ( strmatch ( exonames { i } , innovationbaseline . name ) )
Innovations ( : , i ) = innovationbaseline { exonames { i } } . data ( 1 : periods ) ;
end
end
end
2017-09-28 10:11:42 +02:00
% Set up initial conditions
2017-10-10 09:22:52 +02:00
[ initialcondition , periods , Innovations , DynareOptions , DynareModel , DynareOutput , endonames , exonames , nx , ny1 , iy1 , jdx , model_dynamic , y ] = ...
simul_backward_model_init ( initialcondition , periods , options_ , M_ , oo_ , Innovations ) ;
2017-05-18 13:43:13 +02:00
% Get the covariance matrix of the shocks.
2017-10-14 16:05:55 +02:00
if ~ deterministicshockflag
2017-11-15 15:01:34 +01:00
if nnz ( M_ . Sigma_e )
2017-10-14 16:05:55 +02:00
Sigma = M_ . Sigma_e + 1e-14 * eye ( M_ . exo_nbr ) ;
sigma = transpose ( chol ( Sigma ) ) ;
else
error ( ' You did not specify the size of the shocks!' )
end
end
2017-05-18 13:43:13 +02:00
2017-06-01 15:16:00 +02:00
% Initialization of the returned argument. Each will be a dseries object containing the IRFS for the endogenous variables listed in the third input argument.
2017-10-10 09:22:52 +02:00
deviations = struct ( ) ;
baseline = dseries ( ) ;
2017-06-01 15:16:00 +02:00
irfs = struct ( ) ;
2017-10-10 09:22:52 +02:00
% Baseline paths (get transition paths induced by the initial condition and
% baseline innovations).
if options_ . linear
ysim__0 = simul_backward_linear_model_ ( initialcondition , periods , DynareOptions , DynareModel , DynareOutput , Innovations , nx , ny1 , iy1 , jdx , model_dynamic ) ;
else
ysim__0 = simul_backward_nonlinear_model_ ( initialcondition , periods , DynareOptions , DynareModel , DynareOutput , Innovations , iy1 , model_dynamic ) ;
end
% Transform the endogenous variables.
if notransform
endo_simul__0 = ysim__0 ;
else
endo_simul__0 = feval ( transform , ysim__0 ) ;
end
2017-05-18 13:43:13 +02:00
% Compute the IRFs (loop over innovations).
for i = 1 : length ( listofshocks )
2017-10-10 09:22:52 +02:00
innovations = Innovations ;
2017-05-18 13:43:13 +02:00
% Add the shock.
2017-10-12 12:11:30 +02:00
if deterministicshockflag
shock = listofshocks { i } ;
2017-10-14 16:35:01 +02:00
timid = shock . dates - initialconditionperiod ;
2017-10-12 12:11:30 +02:00
for j = 1 : shock . vobs
2018-03-01 09:29:48 +01:00
k = find ( strcmp ( shock . name { j } , exonames ) ) ;
2017-10-14 16:35:01 +02:00
for l = 1 : length ( timid )
innovations ( timid ( l ) , k ) = innovations ( timid ( l ) , k ) + shock . data ( l , j ) ;
end
2017-10-12 12:11:30 +02:00
end
else
j = find ( strcmp ( listofshocks { i } , exonames ) ) ;
if isempty ( j )
error ( ' backward_model_irf: Exogenous variable %s is unknown!' , listofshocks { i } )
end
innovations ( 1 , : ) = innovations ( 1 , : ) + transpose ( sigma ( : , j ) ) ;
2017-05-18 13:43:13 +02:00
end
2017-09-28 10:11:42 +02:00
if options_ . linear
ysim__1 = simul_backward_linear_model_ ( initialcondition , periods , DynareOptions , DynareModel , DynareOutput , innovations , nx , ny1 , iy1 , jdx , model_dynamic ) ;
else
ysim__1 = simul_backward_nonlinear_model_ ( initialcondition , periods , DynareOptions , DynareModel , DynareOutput , innovations , iy1 , model_dynamic ) ;
end
2017-05-18 13:43:13 +02:00
% Transform the endogenous variables
2017-06-01 15:16:00 +02:00
if notransform
2017-09-28 10:11:42 +02:00
endo_simul__1 = ysim__1 ;
2017-05-18 13:43:13 +02:00
else
2017-09-28 10:11:42 +02:00
endo_simul__1 = feval ( transform , ysim__1 ) ;
2017-05-18 13:43:13 +02:00
end
% Instantiate a dseries object (with all the endogenous variables)
2017-10-10 10:05:59 +02:00
alldeviations = dseries ( transpose ( endo_simul__1 - endo_simul__0 ) , initialcondition . init , endonames ( 1 : M_ . orig_endo_nbr ) , DynareModel . endo_names_tex ( 1 : M_ . orig_endo_nbr ) ) ;
2017-10-10 09:22:52 +02:00
if nargout > 2
2017-10-10 10:05:59 +02:00
allirfs = dseries ( transpose ( endo_simul__1 ) , initialcondition . init , endonames ( 1 : M_ . orig_endo_nbr ) , DynareModel . endo_names_tex ( 1 : M_ . orig_endo_nbr ) ) ;
2017-10-10 09:22:52 +02:00
end
2017-05-18 13:43:13 +02:00
% Extract a sub-dseries object
2017-10-12 12:11:30 +02:00
if deterministicshockflag
name = sprintf ( ' experiment_%s' , int2str ( i ) ) ;
else
name = listofshocks { i } ;
end
deviations . ( name ) = alldeviations { listofvariables { : } } ;
2017-10-10 09:22:52 +02:00
if nargout > 2
2017-10-12 12:11:30 +02:00
irfs . ( name ) = allirfs { listofvariables { : } } ;
2017-11-16 17:54:00 +01:00
irfs . ( name ) = [ irfs . ( name ) dseries ( innovations , initialcondition . last + 1 , exonames ) ] ;
2017-10-10 09:22:52 +02:00
end
end
if nargout > 1
2017-10-10 10:05:59 +02:00
baseline = dseries ( transpose ( endo_simul__0 ) , initialcondition . init , endonames ( 1 : M_ . orig_endo_nbr ) , DynareModel . endo_names_tex ( 1 : M_ . orig_endo_nbr ) ) ;
2017-11-16 17:54:00 +01:00
baseline = [ baseline , innovationbaseline ] ;
2017-05-18 13:43:13 +02:00
end