1function [forecast,info] = dyn_forecast(var_list,M,options,oo,task,dataset_info)
2% function dyn_forecast(var_list,M,options,oo,task,dataset_info)
3%   computes mean forecast for a given value of the parameters
4%   compues also confidence band for the forecast
5%
6% INPUTS
7%   var_list:    list of variables (character matrix)
8%   M:           Dynare model structure
9%   options:     Dynare options structure
10%   oo:          Dynare results structure
11%   task:        indicates how to initialize the forecast
12%                either 'simul' or 'smoother'
13%   dataset_info:   Various informations about the dataset (descriptive statistics and missing observations).
14
15% OUTPUTS
16%   nothing is returned but the procedure saves output
17%   in oo_.forecast.Mean
18%      oo_.forecast.HPDinf
19%      oo_.forecast.HPDsup
20%
21% SPECIAL REQUIREMENTS
22%    none
23
24% Copyright (C) 2003-2018 Dynare Team
25%
26% This file is part of Dynare.
27%
28% Dynare is free software: you can redistribute it and/or modify
29% it under the terms of the GNU General Public License as published by
30% the Free Software Foundation, either version 3 of the License, or
31% (at your option) any later version.
32%
33% Dynare is distributed in the hope that it will be useful,
34% but WITHOUT ANY WARRANTY; without even the implied warranty of
35% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36% GNU General Public License for more details.
37%
38% You should have received a copy of the GNU General Public License
39% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
40
41if nargin<6 && options.prefilter
42    error('The prefiltering option is not allowed without providing a dataset')
43elseif nargin==6
44    mean_varobs=dataset_info.descriptive.mean';
45end
46
47info = 0;
48
49oo=make_ex_(M,options,oo);
50
51maximum_lag = M.maximum_lag;
52
53endo_names = M.endo_names;
54if isempty(var_list)
55    var_list = endo_names(1:M.orig_endo_nbr);
56end
57i_var = [];
58for i = 1:length(var_list)
59    tmp = strmatch(var_list{i}, endo_names, 'exact');
60    if isempty(tmp)
61        error([var_list{i} ' isn''t an endogenous variable'])
62    end
63    i_var = [i_var; tmp];
64end
65
66n_var = length(i_var);
67
68trend = 0;
69switch task
70  case 'simul'
71    horizon = options.periods;
72    if horizon == 0
73        horizon = 5;
74    end
75    if isempty(M.endo_histval)
76        if options.loglinear && ~options.logged_steady_state
77            y0 = repmat(log(oo.dr.ys),1,maximum_lag);
78        else
79            y0 = repmat(oo.dr.ys,1,maximum_lag);
80        end
81    else
82        if options.loglinear
83            y0 = log_variable(1:M.endo_nbr,M.endo_histval,M);
84        else
85            y0 = M.endo_histval;
86        end
87    end
88  case 'smoother'
89    horizon = options.forecast;
90    y_smoothed = oo.SmoothedVariables;
91    y0 = zeros(M.endo_nbr,maximum_lag);
92    for i = 1:M.endo_nbr
93        v_name = M.endo_names{i};
94        y0(i,:) = y_smoothed.(v_name)(end-maximum_lag+1:end); %includes steady state or mean, but simult_ will subtract only steady state
95                                                              % 2. Subtract mean/steady state and add steady state; takes care of prefiltering
96        if isfield(oo.Smoother,'Constant') && isfield(oo.Smoother.Constant,v_name)
97            y0(i,:)=y0(i,:)-oo.Smoother.Constant.(v_name)(end-maximum_lag+1:end); %subtract mean or steady state
98            if options.loglinear
99                y0(i,:)=y0(i,:)+log_variable(i,oo.dr.ys,M);
100            else
101                y0(i,:)=y0(i,:)+oo.dr.ys(strmatch(v_name, M.endo_names, 'exact'));
102            end
103        end
104        % 2. Subtract trend
105        if isfield(oo.Smoother,'Trend') && isfield(oo.Smoother.Trend,v_name)
106            y0(i,:)=y0(i,:)-oo.Smoother.Trend.(v_name)(end-maximum_lag+1:end); %subtract trend, which is not subtracted by simult_
107        end
108    end
109    gend = options.nobs;
110    if isfield(oo.Smoother,'TrendCoeffs')
111        var_obs = options.varobs;
112        endo_names = M.endo_names;
113        order_var = oo.dr.order_var;
114        i_var_obs = [];
115        trend_coeffs = [];
116        for i=1:length(var_obs)
117            tmp = strmatch(var_obs{i}, endo_names(i_var), 'exact');
118            trend_var_index = strmatch(var_obs{i}, M.endo_names, 'exact');
119            if ~isempty(tmp)
120                i_var_obs = [ i_var_obs; tmp];
121                trend_coeffs = [trend_coeffs; oo.Smoother.TrendCoeffs(trend_var_index)];
122            end
123        end
124        if ~isempty(trend_coeffs)
125            trend = trend_coeffs*(options.first_obs+gend-1+(1-M.maximum_lag:horizon));
126            if options.prefilter
127                trend = trend - repmat(mean(trend_coeffs*[options.first_obs:options.first_obs+gend-1],2),1,horizon+1); %subtract mean trend
128            end
129        end
130    else
131        trend_coeffs=zeros(length(options.varobs),1);
132    end
133  otherwise
134    error('Wrong flag value')
135end
136
137if M.exo_det_nbr == 0
138    if isequal(M.H,0)
139        [yf,int_width] = forcst(oo.dr,y0,horizon,var_list,M,oo,options);
140    else
141        [yf,int_width,int_width_ME] = forcst(oo.dr,y0,horizon,var_list,M,oo,options);
142    end
143else
144    exo_det_length = size(oo.exo_det_simul,1)-M.maximum_lag;
145    if horizon > exo_det_length
146        ex = zeros(horizon,M.exo_nbr);
147        oo.exo_det_simul = [ oo.exo_det_simul;...
148                            repmat(oo.exo_det_steady_state',...
149                                   horizon- ...
150                                   exo_det_length,1)];
151    elseif horizon <= exo_det_length
152        ex = zeros(exo_det_length,M.exo_nbr);
153    end
154    if options.linear
155        iorder = 1;
156    else
157        iorder = options.order;
158    end
159    if isequal(M.H,0)
160        [yf,int_width] = simultxdet(y0,ex,oo.exo_det_simul,...
161                                    iorder,var_list,M,oo,options);
162    else
163        [yf,int_width,int_width_ME] = simultxdet(y0,ex,oo.exo_det_simul,...
164                                                 iorder,var_list,M,oo,options);
165    end
166end
167
168if ~isscalar(trend) %add trend back to forecast
169    yf(i_var_obs,:) = yf(i_var_obs,:) + trend;
170end
171
172if options.loglinear
173    if options.prefilter == 1 %subtract steady state and add mean for observables
174        yf(i_var_obs,:)=yf(i_var_obs,:)-repmat(log(oo.dr.ys(i_var_obs)),1,horizon+M.maximum_lag)+ repmat(mean_varobs,1,horizon+M.maximum_lag);
175    end
176else
177    if options.prefilter == 1 %subtract steady state and add mean for observables
178        yf(i_var_obs,:)=yf(i_var_obs,:)-repmat(oo.dr.ys(i_var_obs),1,horizon+M.maximum_lag)+ repmat(mean_varobs,1,horizon+M.maximum_lag);
179    end
180end
181
182for i=1:n_var
183    vname = var_list{i};
184    forecast.Mean.(vname) = yf(i,maximum_lag+(1:horizon))';
185    forecast.HPDinf.(vname)= yf(i,maximum_lag+(1:horizon))' - int_width(1:horizon,i);
186    forecast.HPDsup.(vname) = yf(i,maximum_lag+(1:horizon))' + int_width(1:horizon,i);
187    if ~isequal(M.H,0) && ismember(var_list{i},options.varobs)
188        forecast.HPDinf_ME.(vname)= yf(i,maximum_lag+(1:horizon))' - int_width_ME(1:horizon,i);
189        forecast.HPDsup_ME.(vname) = yf(i,maximum_lag+(1:horizon))' + int_width_ME(1:horizon,i);
190    end
191end
192
193for i=1:M.exo_det_nbr
194    forecast.Exogenous.(M.exo_det_names{i}) = oo.exo_det_simul(maximum_lag+(1:horizon),i);
195end
196
197if ~options.nograph
198    oo.forecast = forecast;
199    forecast_graphs(var_list, M, oo, options)
200end
201