backward_model_irf.m 8.55 KB
Newer Older
1
function [deviations, baseline, irfs] = backward_model_irf(initialcondition, innovationbaseline, listofshocks, listofvariables, varargin)
2 3 4

% Returns impulse response functions.
%
5
% INPUTS
6 7 8 9 10
% - 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.
11
%
12 13
% OUTPUTS
% - irfs                [struct of dseries]
14
%
15 16 17 18 19 20
% 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.
21

22
% Copyright (C) 2017-2018 Dynare Team
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
%
% 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
43
    error('backward_model_irf:: The specified model is not backward looking!')
44 45 46
end

% Set default value for the fourth input argument.
47
if nargin<5
48
    periods = 40;
49 50
else
    periods = varargin{1};
51 52 53
end

% Set default value for the last input argument (no transformation).
54
if nargin<6
55 56 57
    notransform = true;
else
    notransform = false;
58
    transform = varargin{2};
59 60
end

61 62 63 64 65 66 67 68 69
% If first argument is empty, try to set the initial condition with histval.
if isempty(initialcondition)
    try
        initialcondition = dseries(M_.endo_histval', 1, cellstr(M_.endo_names), cellstr(M_.endo_names_tex));
    catch
        error('Use histval block to set the initial condition.')
    end
end

70 71 72 73 74 75 76 77 78 79 80 81 82
% 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);
83
        exonames = M_.exo_names;
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
        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

100 101 102 103 104 105 106
% 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

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
% 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.
125
    exonames = M_.exo_names;
126 127 128 129 130 131 132
    for i = 1:length(exonames)
        if ~isempty(strmatch(exonames{i}, innovationbaseline.name))
            Innovations(:,i) = innovationbaseline{exonames{i}}.data(1:periods);
        end
    end
end

133
% Set up initial conditions
134 135
[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);
136 137

% Get the covariance matrix of the shocks.
138
if ~deterministicshockflag
139
    if nnz(M_.Sigma_e)
140 141 142 143 144 145
        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
146

147
% Initialization of the returned argument. Each will be a dseries object containing the IRFS for the endogenous variables listed in the third input argument.
148 149
deviations = struct();
baseline = dseries();
150 151
irfs = struct();

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
% 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

167 168
% Compute the IRFs (loop over innovations).
for i=1:length(listofshocks)
169
    innovations = Innovations;
170
    % Add the shock.
171 172
    if deterministicshockflag
        shock = listofshocks{i};
173
        timid = shock.dates-initialconditionperiod;
174
        for j=1:shock.vobs
175
            k = find(strcmp(shock.name{j}, exonames));
176 177 178
            for l=1:length(timid)
                innovations(timid(l),k) = innovations(timid(l),k) + shock.data(l,j);
            end
179 180 181 182 183 184 185
        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));
186
    end
187 188 189 190 191
    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
192
    % Transform the endogenous variables
193
    if notransform
194
        endo_simul__1 = ysim__1;
195
    else
196
        endo_simul__1 = feval(transform, ysim__1);
197 198
    end
    % Instantiate a dseries object (with all the endogenous variables)
199
    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));
200
    if nargout>2
201
        allirfs = dseries(transpose(endo_simul__1), initialcondition.init, endonames(1:M_.orig_endo_nbr), DynareModel.endo_names_tex(1:M_.orig_endo_nbr));
202
    end
203
    % Extract a sub-dseries object
204 205 206 207 208 209
    if deterministicshockflag
        name = sprintf('experiment_%s', int2str(i));
    else
        name = listofshocks{i};
    end
    deviations.(name) = alldeviations{listofvariables{:}};
210
    if nargout>2
211
        irfs.(name) = allirfs{listofvariables{:}};
212
        irfs.(name) = [irfs.(name) dseries(innovations, initialcondition.last+1, exonames)];
213 214 215 216
    end
end

if nargout>1
217
    baseline = dseries(transpose(endo_simul__0), initialcondition.init, endonames(1:M_.orig_endo_nbr), DynareModel.endo_names_tex(1:M_.orig_endo_nbr));
218
    baseline = [baseline, innovationbaseline];
219
end