dynare/matlab/kalman/store_smoother_results.m

273 lines
15 KiB
Matlab

function [oo_, yf]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty)
% oo_=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend)
% Writes the smoother results into respective fields in oo_
%
% Inputs:
% M_ [structure] storing the model information
% oo_ [structure] storing the results
% options_ [structure] storing the options
% bayestopt_ [structure] storing information about priors
% dataset_ [structure] storing the dataset
% atT [double] (m*T) matrix, smoothed endogenous variables (a_{t|T}) (decision-rule order)
% innov [double] (r*T) matrix, smoothed structural shocks (r>n is the umber of shocks).
% measurement_error [double] (n*T) matrix, smoothed measurement errors.
% updated_variables [double] (m*T) matrix, updated (endogenous) variables (a_{t|t}) (decision-rule order)
% ys [double] (m*1) vector specifying the steady state
% level of each endogenous variable (declaration order)
% trend_coeff [double] (n*1) vector, parameters specifying the slope of the trend associated to each observed variable.
% aK [double] (K,n,T+K) array, k (k=1,...,K) steps ahead
% filtered (endogenous) variables (decision-rule order)
% P [3D array] (m*m*(T+1)) array of one-step ahead forecast error variance
% matrices (decision-rule order)
% PK [4D array] (K*m*m*(T+K)) 4D array of k-step ahead forecast error variance
% matrices (meaningless for periods 1:d) (decision-rule order)
% decomp [4D array] (K*m*r*(T+K)) 4D array of shock decomposition of k-step ahead
% filtered variables (decision-rule order)
% Trend [double] [nvarobs*T] matrix of trends in observables
% state_uncertainty [double] (K,K,T) array, storing the uncertainty
% about the smoothed state (decision-rule order)
%
% Outputs:
% oo_ [structure] storing the results:
% oo_.Smoother.SteadyState: Steady states (declaration order)
% oo_.Smoother.TrendCoeffs: trend coefficients, with zeros where no trend applies (declaration order)
% oo_.Smoother.Variance: one-step ahead forecast error variance (declaration order)
% oo_.Smoother.Constant: structure storing the constant term of the smoother
% oo_.Smoother.Trend: structure storing the trend term of the smoother
% oo_.FilteredVariablesKStepAhead: k-step ahead filtered variables (declaration order)
% oo_.FilteredVariablesKStepAheadVariances: k-step ahead forecast error variance matrices (declaration order)
% oo_.FilteredVariablesShockDecomposition: shock decomposition of k-step ahead filtered variables (declaration order)
% oo_.FilteredVariables: structure storing the filtered variables
% oo_.UpdatedVariables: structure storing the updated variables
% oo_.SmoothedShocks: structure storing the smoothed shocks
% oo_.SmoothedMeasurementErrors: structure storing the smoothed measurement errors
% oo_.Smoother.State_uncertainty: smoothed state uncertainty (declaration order)
% yf [double] (nvarobs*T) matrix storing the smoothed observed variables (order of options_.varobs)
%
% Notes:
% m: number of endogenous variables (M_.endo_nbr)
% T: number of Time periods (options_.nobs)
% r: number of strucural shocks (M_.exo_nbr)
% n: number of observables (length(options_.varobs))
% K: maximum forecast horizon (max(options_.nk))
%
% First all smoothed variables are saved without trend and constant.
% Then trend and constant are added for the observed variables.
%
% Copyright © 2014-2018 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/>.
if nargin<15
PK=[];
end
if nargin<16
decomp=[];
end
gend=dataset_.nobs;
if nargin<17
Trend=zeros(options_.number_of_observed_variables,gend);
end
%make sure there are no stale results
field_names={'Smoother','SmoothedVariables','UpdatedVariables','FilteredVariables','FilteredVariablesKStepAhead','FilteredVariablesShockDecomposition','FilteredVariablesKStepAheadVariances','SmoothedShocks','SmoothedMeasurementErrors'};
for field_iter=1:length(field_names)
if isfield(oo_,field_names(field_iter))
oo_=rmfield(oo_,field_names(field_iter));
end
end
if options_.occbin.smoother.status
oo_.Smoother.occbin = true;
else
oo_.Smoother.occbin = false;
end
if options_.loglinear
oo_.Smoother.loglinear = true;
if ~isempty(M_.aux_vars) % deal with lead/lag of exogenous variables
exo_lead_lag_index = M_.orig_endo_nbr + find(([M_.aux_vars.type] == 2) | ([M_.aux_vars.type] == 3));
else
exo_lead_lag_index =[];
end
else
oo_.Smoother.loglinear = false;
end
%% write variable steady state
oo_.Smoother.SteadyState = ys;
%% write trend coefficients and trend
oo_.Smoother.TrendCoeffs = zeros(size(ys));
oo_.Smoother.TrendCoeffs(options_.varobs_id)=trend_coeff; %are in order of options_.varobs
if ~isempty(Trend)
for var_iter=1:M_.endo_nbr
if isempty(strmatch(M_.endo_names{var_iter}, options_.varobs, 'exact'))
oo_.Smoother.Trend.(M_.endo_names{var_iter}) = zeros(gend,1);
end
end
for var_iter=1:length(options_.varobs)
oo_.Smoother.Trend.(options_.varobs{var_iter}) = Trend(var_iter,:)';
end
end
%% Compute constant for observables
if options_.prefilter == 1 %as mean is taken after log transformation, no distinction is needed here
constant_part=repmat(dataset_info.descriptive.mean',1,gend);
elseif options_.prefilter == 0 && options_.loglinear %logged steady state must be used
constant_part=repmat(log(ys(bayestopt_.mfys)),1,gend);
elseif options_.prefilter == 0 && ~options_.loglinear %unlogged steady state must be used
constant_part=repmat(ys(bayestopt_.mfys),1,gend);
end
%% get observed variables including trend and constant
trend_constant_observables=constant_part+Trend;
yf = atT(bayestopt_.mf,:)+trend_constant_observables;
if options_.nk > 0
%filtered variable E_t(y_t+k) requires to shift trend by k periods
filter_steps_required=union(1,options_.filter_step_ahead); % 1 is required for standard filtered variables
for filter_iter=1:length(filter_steps_required)
filter_step=filter_steps_required(filter_iter);
trend_constant_observables_filtered.(['filter_ahead_' num2str(filter_step)])=constant_part+[Trend+repmat(filter_step*trend_coeff,1,gend)];
end
end
%% write smoother variance
if options_.filter_covariance
oo_.Smoother.Variance = P;
end
if options_.smoothed_state_uncertainty
oo_.Smoother.State_uncertainty=state_uncertainty;
end
%get indices of smoothed variables
i_endo_in_bayestopt_smoother_varlist = bayestopt_.smoother_saved_var_list;
i_endo_in_dr_matrices=bayestopt_.smoother_var_list(i_endo_in_bayestopt_smoother_varlist);
if ~isempty(options_.nk) && options_.nk ~= 0
%% Compute constant
i_endo_declaration_order = oo_.dr.order_var(i_endo_in_dr_matrices); %get indices of smoothed variables in name vector
if options_.loglinear %logged steady state must be used
constant_all_variables=repmat(log(ys(i_endo_declaration_order))',[length(options_.filter_step_ahead),1,gend+max(options_.filter_step_ahead)]);
if ~isempty(exo_lead_lag_index) && any(ismember(i_endo_declaration_order,exo_lead_lag_index)) % deal with lead/lag of exogenous variables
constant_all_variables(:,ismember(i_endo_declaration_order,exo_lead_lag_index),:)=repmat(ys(i_endo_declaration_order(ismember(i_endo_declaration_order,exo_lead_lag_index)))',[length(options_.filter_step_ahead),1,gend+max(options_.filter_step_ahead)]);
end
elseif ~options_.loglinear %unlogged steady state must be used
constant_all_variables=repmat((ys(i_endo_declaration_order))',[length(options_.filter_step_ahead),1,gend+max(options_.filter_step_ahead)]);
end
% add constant
oo_.FilteredVariablesKStepAhead = aK(options_.filter_step_ahead,i_endo_in_dr_matrices,:)+constant_all_variables;
if ~isempty(PK) && options_.filter_covariance %get K-step ahead variances
oo_.FilteredVariablesKStepAheadVariances = ...
PK(options_.filter_step_ahead,i_endo_in_dr_matrices,i_endo_in_dr_matrices,:);
end
if ~isempty(decomp) %get decomposition
oo_.FilteredVariablesShockDecomposition = ...
decomp(options_.filter_step_ahead,i_endo_in_dr_matrices,:,:);
end
end
for i_endo_in_bayestopt_smoother_varlist=bayestopt_.smoother_saved_var_list'
i_endo_in_dr=bayestopt_.smoother_var_list(i_endo_in_bayestopt_smoother_varlist);
i_endo_declaration_order = oo_.dr.order_var(i_endo_in_dr); %get indices of smoothed variables in name vector
%% Compute constant
if options_.loglinear == 1 %logged steady state must be used
if ~isempty(exo_lead_lag_index) && ismember(i_endo_declaration_order,exo_lead_lag_index)% deal with lead/lag of exogenous variables
constant_current_variable=repmat(ys(i_endo_declaration_order),gend,1);
else
constant_current_variable=repmat(log(ys(i_endo_declaration_order)),gend,1);
end
elseif options_.loglinear == 0 %unlogged steady state must be used
constant_current_variable=repmat((ys(i_endo_declaration_order)),gend,1);
end
oo_.Smoother.Constant.(M_.endo_names{i_endo_declaration_order})=constant_current_variable;
oo_.SmoothedVariables.(M_.endo_names{i_endo_declaration_order})=atT(i_endo_in_dr,:)'+constant_current_variable;
if ~isempty(options_.nk) && options_.nk > 0 % && ~((any(bayestopt_.pshape > 0) && options_.mh_replic) || (any(bayestopt_.pshape> 0) && options_.load_mh_file))
oo_.FilteredVariables.(M_.endo_names{i_endo_declaration_order})=squeeze(aK(1,i_endo_in_dr,2:end-(options_.nk-1)))+constant_current_variable;
end
oo_.UpdatedVariables.(M_.endo_names{i_endo_declaration_order})=updated_variables(i_endo_in_dr,:)'+constant_current_variable;
end
%% Add trend and constant for observed variables
for pos_iter=1:length(bayestopt_.mf)
oo_.Smoother.Constant.(M_.endo_names{bayestopt_.mfys(pos_iter)})=constant_part(pos_iter,:)';
if ismember(bayestopt_.mf(pos_iter),bayestopt_.smoother_var_list(bayestopt_.smoother_saved_var_list))
oo_.SmoothedVariables.(M_.endo_names{bayestopt_.mfys(pos_iter)})=yf(pos_iter,:)';
if ~isempty(options_.nk) && options_.nk > 0
%filtered variable E_t(y_t+1) requires to shift trend by 1 period
oo_.FilteredVariables.(M_.endo_names{bayestopt_.mfys(pos_iter)})=...
squeeze(aK(1,bayestopt_.mf(pos_iter),2:end-(options_.nk-1)))...
+trend_constant_observables_filtered.filter_ahead_1(pos_iter,:)';
for filter_iter=1:length(options_.filter_step_ahead)
filter_step=options_.filter_step_ahead(filter_iter);
oo_.FilteredVariablesKStepAhead(filter_iter,find(i_endo_in_dr_matrices==bayestopt_.mf(pos_iter)),1+filter_step:end-(max(options_.filter_step_ahead)-filter_step)) = ...
squeeze(aK(filter_step,bayestopt_.mf(pos_iter),1+filter_step:end-(max(options_.filter_step_ahead)-filter_step)))...
+trend_constant_observables_filtered.(['filter_ahead_' num2str(filter_step)])(pos_iter,:)';
end
end
%updated variables are E_t(y_t) so no trend shift is required
oo_.UpdatedVariables.(M_.endo_names{bayestopt_.mfys(pos_iter)})=...
updated_variables(bayestopt_.mf(pos_iter),:)'+trend_constant_observables(pos_iter,:)';
end
end
%% resort fields that are in decision rule order to declaration order
if ~isempty(options_.nk) && options_.nk ~= 0
positions_in_declaration_order=oo_.dr.order_var(bayestopt_.smoother_var_list(bayestopt_.smoother_saved_var_list));
if ~(options_.selected_variables_only && ~(options_.forecast > 0)) %happens only when selected_variables_only is not used
oo_.FilteredVariablesKStepAhead(:,positions_in_declaration_order,:)=oo_.FilteredVariablesKStepAhead;
if ~isempty(PK) && options_.filter_covariance %get K-step ahead variances
oo_.FilteredVariablesKStepAheadVariances(:,positions_in_declaration_order,positions_in_declaration_order,:)=oo_.FilteredVariablesKStepAheadVariances;
end
if ~isempty(decomp)
oo_.FilteredVariablesShockDecomposition(:,positions_in_declaration_order,:,:)=oo_.FilteredVariablesShockDecomposition;
end
else
positions_in_declaration_order=oo_.dr.order_var(bayestopt_.smoother_var_list(bayestopt_.smoother_saved_var_list));
[~,sorted_index_declaration_order]=sort(positions_in_declaration_order);
oo_.FilteredVariablesKStepAhead(:,sorted_index_declaration_order,:)=oo_.FilteredVariablesKStepAhead;
if ~isempty(PK) && options_.filter_covariance %get K-step ahead variances
oo_.FilteredVariablesKStepAheadVariances(:,sorted_index_declaration_order,sorted_index_declaration_order,:)=oo_.FilteredVariablesKStepAheadVariances;
end
if ~isempty(decomp)
oo_.FilteredVariablesShockDecomposition(:,sorted_index_declaration_order,:,:)=oo_.FilteredVariablesShockDecomposition;
end
end
end
if options_.filter_covariance
oo_.Smoother.Variance(oo_.dr.order_var,oo_.dr.order_var,:)=oo_.Smoother.Variance;
end
if options_.smoothed_state_uncertainty
oo_.Smoother.State_uncertainty(oo_.dr.order_var,oo_.dr.order_var,:)=state_uncertainty;
end
%% get smoothed shocks
for exo_iter=1:M_.exo_nbr
oo_.SmoothedShocks.(M_.exo_names{exo_iter})=innov(exo_iter,:)';
end
%% Smoothed measurement errors
if ~isequal(M_.H,0)
% measurement_error_indices=find(diag(M_.H)~=0);
for meas_error_iter=1:length(options_.varobs)
oo_.SmoothedMeasurementErrors.(options_.varobs{meas_error_iter})= measurement_error(meas_error_iter,:)';
end
end