Add Occbin routines

Syntax is not yet finalized (see preprocessor#68).
Documentation still to be done.

Ref. #569
var-model-with-constant
Marco Ratto 2021-05-17 21:24:25 +02:00 committed by Sébastien Villemot
parent 54f80e88d2
commit 02072dde39
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
61 changed files with 6364 additions and 251 deletions

View File

@ -25,6 +25,32 @@ Files: *
Copyright: 1996-2021 Dynare Team
License: GPL-3+
Files: matlab/+occbin/IVF_core.m
matlab/+occbin/make_chart.m
matlab/+occbin/map_regime.m
matlab/+occbin/match_function.m
matlab/+occbin/mkdata.m
matlab/+occbin/mkdatap_anticipated_2constraints_dyn.m
matlab/+occbin/mkdatap_anticipated_dyn.m
matlab/+occbin/process_constraint.m
matlab/+occbin/solve_one_constraint.m
matlab/+occbin/solve_two_constraints.m
matlab/+occbin/tokenize.m
Copyright: none
License: public-domain-occbin
Original authors: Luca Guerrieri and Matteo Iacoviello
Original file downloaded from:
https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
Adapted for Dynare by Dynare Team.
.
This code is in the public domain and may be used freely.
However the authors would appreciate acknowledgement of the source by
citation of any of the following papers:
.
Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
dynamic models with occasionally binding constraints easily"
Journal of Monetary Economics 70, 22-38
Files: matlab/AIM/SP*
Copyright: none
License: public-domain-aim

View File

@ -0,0 +1,391 @@
function [alphahat,etahat,epsilonhat,ahat0,SteadyState,trend_coeff,aKK,T0,R0,P,PKK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DSGE_smoother(xparam1,gend,Y,data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_,dataset_, dataset_info)
%function [alphahat,etahat,epsilonhat,ahat0,SteadyState,trend_coeff,aKK,T0,R0,P,PKK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DSGE_smoother(xparam1,gend,Y,data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_,dataset_, dataset_info)
% Runs a DSGE smoother with occasionally binding constraints
%
% INPUTS
% - xparam1 [double] (p*1) vector of (estimated) parameters.
% - gend [integer] scalar specifying the number of observations
% - Y [double] (n*T) matrix of data.
% - data_index [cell] 1*smpl cell of column vectors of indices.
% - missing_value [boolean] 1 if missing values, 0 otherwise
% - M_ [structure] Matlab's structure describing the model (M_).
% - oo_ [structure] Matlab's structure containing the results (oo_).
% - options_ [structure] Matlab's structure describing the current options (options_).
% - bayestopt_ [structure] describing the priors
% - estim_params_ [structure] characterizing parameters to be estimated
% - dataset_ [structure] the dataset after required transformation
% - dataset_info [structure] Various informations about the dataset (descriptive statistics and missing observations)
%
% OUTPUTS
% - alphahat [double] (m*T) matrix, smoothed endogenous variables (a_{t|T}) (decision-rule order)
% - etahat [double] (r*T) matrix, smoothed structural shocks (r>=n is the number of shocks).
% - epsilonhat [double] (n*T) matrix, smoothed measurement errors.
% - ahat0 [double] (m*T) matrix, updated (endogenous) variables (a_{t|t}) (decision-rule order)
% - SteadyState [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.
% - aKK [double] (K,n,T+K) array, k (k=1,...,K) steps ahead
% filtered (endogenous) variables (decision-rule order)
% - T0 and R0 [double] Matrices defining the state equation (T is the (m*m) transition matrix).
% - P: (m*m*(T+1)) 3D array of one-step ahead forecast error variance
% matrices (decision-rule order)
% - PKK (K*m*m*(T+K)) 4D array of k-step ahead forecast error variance
% matrices (meaningless for periods 1:d) (decision-rule order)
% - decomp (K*m*r*(T+K)) 4D array of shock decomposition of k-step ahead
% filtered variables (decision-rule order)
% - Trend [double] (n*T) pure trend component; stored in options_.varobs order
% - state_uncertainty [double] (K,K,T) array, storing the uncertainty
% about the smoothed state (decision-rule order)
% - M_ [structure] decribing the model
% - oo_ [structure] storing the results
% - options_ [structure] describing the options
% - bayestopt_ [structure] describing the priors
% Copyright (C) 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/>.
smoother_field_list = {'SmoothedVariables', 'UpdatedVariables', 'SmoothedShocks'};
regime_history=[];
if options_.occbin.smoother.linear_smoother && nargin==12
%% linear smoother
options_.occbin.smoother.status=false;
[alphahat,etahat,epsilonhat,ahat,SteadyState,trend_coeff,aK,T0,R0,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,gend,Y,data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_);
tmp_smoother=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,alphahat,etahat,epsilonhat,ahat,SteadyState,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty);
for jf=1:length(smoother_field_list)
oo_.occbin.linear_smoother.(smoother_field_list{jf}) = tmp_smoother.(smoother_field_list{jf});
end
oo_.occbin.linear_smoother.alphahat=alphahat;
oo_.occbin.linear_smoother.etahat=etahat;
oo_.occbin.linear_smoother.epsilonhat=epsilonhat;
oo_.occbin.linear_smoother.ahat=ahat;
oo_.occbin.linear_smoother.SteadyState=SteadyState;
oo_.occbin.linear_smoother.trend_coeff=trend_coeff;
oo_.occbin.linear_smoother.aK=aK;
oo_.occbin.linear_smoother.T0=T0;
oo_.occbin.linear_smoother.R0=R0;
oo_.occbin.linear_smoother.decomp=decomp;
fprintf('\nOccbin: linear smoother done.\n')
options_.occbin.smoother.status=true;
end
% if init_mode
%% keep these commented lines for the moment, should some nasty problem in the future call back for this option
% shocks1 = etahat(:,2:end)';
% clear regime_history ;
%
% for ii = 1:gend-1
%
% fprintf('Period number %d out of %d \n',ii,gend-1)
% opts_simul.SHOCKS = shocks1(ii,:);
% opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,ii);
% out = occbin.runsim_fn(opts_simul, M_, oo_, options_);
% regime_history(ii) = out.regime_history;
% end
%
% [TT,RR] = dynare_resolve(M_,options_,oo_);
% CC = zeros([size(RR,1),gend ]);
% else
opts_simul = options_.occbin.simul;
opts_simul.curb_retrench = options_.occbin.smoother.curb_retrench;
opts_simul.maxit = options_.occbin.smoother.maxit;
opts_simul.waitbar = options_.occbin.smoother.waitbar;
opts_simul.periods = options_.occbin.smoother.periods;
opts_simul.check_ahead_periods = options_.occbin.smoother.check_ahead_periods;
opts_simul.full_output = options_.occbin.smoother.full_output;
opts_simul.piecewise_only = options_.occbin.smoother.piecewise_only;
constraints = M_.occbin.constraint;
% init_mode = options_.occbin.smoother.init_mode; % 0 = standard; 1 = unconditional frcsts zero shocks+smoothed states in each period
% init_mode = 0;
occbin_options = struct();
occbin_options.constraints = constraints;
occbin_options.first_period_occbin_update = options_.occbin.smoother.first_period_occbin_update;
occbin_options.opts_regime = opts_simul; % this builds the opts_simul options field needed by occbin.solver
occbin_options.opts_regime.binding_indicator = options_.occbin.likelihood.init_binding_indicator;
occbin_options.opts_regime.regime_history=options_.occbin.likelihood.init_regime_history;
[alphahat,etahat,epsilonhat,ahat,SteadyState,trend_coeff,aK,T0,R0,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,gend,Y,data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_,occbin_options);% T1=TT;
oo_.occbin.smoother.realtime_regime_history = oo_.occbin.smoother.regime_history;
regime_history = oo_.occbin.smoother.regime_history;
opts_regime.regime_history = oo_.occbin.smoother.regime_history;
ahat0 = ahat;
aKK=aK;
PKK=PK;
clear aK PK;
occbin_options.first_period_occbin_update = inf;
opts_regime.binding_indicator=[];
regime_history0 = regime_history;
fprintf('Occbin smoother iteration 1.\n')
opts_simul.SHOCKS = [etahat(:,2:end)'; zeros(1,M_.exo_nbr)];
opts_simul.exo_pos = 1:M_.exo_nbr;
opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1);
opts_simul.init_regime=regime_history; % use realtime regime for guess, to avoid multiple solution issues!
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
regime_history = out.regime_history;
if options_.smoother_redux
occbin_options.opts_simul.restrict_state_space =1;
oo_.occbin.linear_smoother.T0=ss.T(oo_.dr.order_var,oo_.dr.order_var,1);
oo_.occbin.linear_smoother.R0=ss.R(oo_.dr.order_var,:,1);
end
TT = ss.T(oo_.dr.order_var,oo_.dr.order_var,:);
RR = ss.R(oo_.dr.order_var,:,:);
CC = ss.C(oo_.dr.order_var,:);
TT = cat(3,TT(:,:,1),TT);
RR = cat(3,RR(:,:,1),RR);
CC = cat(2,CC(:,1),CC);
opts_regime.regime_history = regime_history;
opts_regime.binding_indicator = [];
[TT, RR, CC, regime_history] = occbin.check_regimes(TT, RR, CC, opts_regime, M_, oo_, options_);
is_changed = ~isequal(regime_history0,regime_history);
if isempty(regime_history0)
regime_history0 = regime_history;
end
iter=1;
is_periodic = 0;
is_changed_start = 0;
maxiter = options_.occbin.smoother.max_number_of_iterations;
occbin_smoother_fast = options_.occbin.smoother.fast;
occbin_smoother_debug=options_.occbin.smoother.debug;
sto_alphahat=alphahat;
sto_etahat={etahat};
sto_CC = CC;
sto_RR = RR;
sto_TT = TT;
for k=1:size(TT,3)
sto_eee(:,k) = eig(TT(:,:,k));
end
while is_changed && maxiter>iter && ~is_periodic
iter=iter+1;
fprintf('Occbin smoother iteration %u.\n', iter)
occbin_options.opts_regime.regime_history=regime_history;
[alphahat,etahat,epsilonhat,ahat,SteadyState,trend_coeff,aK,T0,R0,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,gend,Y,data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_,occbin_options,TT,RR,CC);% T1=TT;
sto_etahat(iter)={etahat};
regime_history0(iter,:) = regime_history;
save('info1','regime_history0');
sto_CC = CC;
sto_RR = RR;
sto_TT = TT;
opts_simul.SHOCKS = [etahat(:,2:end)'; zeros(1,M_.exo_nbr)];
opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1);
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
regime_history = out.regime_history;
TT = ss.T(oo_.dr.order_var,oo_.dr.order_var,:);
RR = ss.R(oo_.dr.order_var,:,:);
CC = ss.C(oo_.dr.order_var,:);
TT = cat(3,TT(:,:,1),TT);
RR = cat(3,RR(:,:,1),RR);
CC = cat(2,CC(:,1),CC);
opts_regime.regime_history = regime_history;
[TT, RR, CC, regime_history] = occbin.check_regimes(TT, RR, CC, opts_regime, M_, oo_, options_);
is_changed = ~isequal(regime_history0(iter,:),regime_history);
if length(constraints)==2
for k=1:size(regime_history0,2)
isdiff_regime(k,1) = ~isequal(regime_history0(end,k).regime1,regime_history(k).regime1);
isdiff_start(k,1) = ~isequal(regime_history0(end,k).regimestart1,regime_history(k).regimestart1);
isdiff_(k,1) = isdiff_regime(k,1) || isdiff_start(k,1);
isdiff_regime(k,2) = ~isequal(regime_history0(end,k).regime2,regime_history(k).regime2);
isdiff_start(k,2) = ~isequal(regime_history0(end,k).regimestart2,regime_history(k).regimestart2);
isdiff_(k,2) = isdiff_regime(k,2) || isdiff_start(k,2);
end
is_changed_regime = ~isempty(find(isdiff_regime(:,1))) || ~isempty(find(isdiff_regime(:,2)));
is_changed_start = ~isempty(find(isdiff_start(:,1))) || ~isempty(find(isdiff_start(:,2)));
else
for k=1:size(regime_history0,2)
isdiff_regime(k,1) = ~isequal(regime_history0(end,k).regime,regime_history(k).regime);
isdiff_start(k,1) = ~isequal(regime_history0(end,k).regimestart,regime_history(k).regimestart);
isdiff_(k,1) = isdiff_regime(k,1) || isdiff_start(k,1);
end
is_changed_regime = ~isempty(find(isdiff_regime(:,1)));
is_changed_start = ~isempty(find(isdiff_start(:,1)));
end
if occbin_smoother_fast
is_changed = is_changed_regime;
end
if iter>1
for kiter=1:iter-1
is_tmp = isequal(regime_history0(kiter,:),regime_history);
if is_tmp
break
end
end
is_periodic = (is_changed && is_tmp);
end
if is_changed
for k=1:size(TT,3)
eee(:,k) = eig(TT(:,:,k));
end
err_eig(iter-1) = max(max(abs(sort(eee)-sort(sto_eee))));
err_alphahat(iter-1) = max(max(max(abs(alphahat-sto_alphahat))));
err_etahat(iter-1) = max(max(max(abs(etahat-sto_etahat{iter-1}))));
err_CC(iter-1) = max(max(max(abs(CC-sto_CC))));
err_RR(iter-1) = max(max(max(abs(RR-sto_RR))));
err_TT(iter-1) = max(max(max(abs(TT-sto_TT))));
end
if occbin_smoother_debug
regime_ = cell(0);
regime_new = regime_;
start_ = regime_;
start_new = regime_;
if length(constraints)==2
indx_init_1 = find(isdiff_(:,1));
if ~isempty(indx_init_1)
qq={regime_history0(end,indx_init_1).regime1}';
for j=1:length(qq), regime_(j,1) = {int2str(qq{j})}; end
qq={regime_history0(end,indx_init_1).regimestart1}';
for j=1:length(qq), start_(j,1) = {int2str(qq{j})}; end
qq={regime_history(indx_init_1).regime1}';
for j=1:length(qq), regime_new(j,1) = {int2str(qq{j})}; end
qq={regime_history(indx_init_1).regimestart1}';
for j=1:length(qq), start_new(j,1) = {int2str(qq{j})}; end
disp('Time points where regime 1 differs')
disp(table(indx_init_1, regime_, start_, regime_new, start_new))
end
indx_init_2 = find(isdiff_(:,2));
if ~isempty(indx_init_2)
regime_ = cell(0);
regime_new = regime_;
start_ = regime_;
start_new = regime_;
qq={regime_history0(end,indx_init_2).regime2}';
for j=1:length(qq), regime_(j,1) = {int2str(qq{j})}; end
qq={regime_history0(end,indx_init_2).regimestart2}';
for j=1:length(qq), start_(j,1) = {int2str(qq{j})}; end
qq={regime_history(indx_init_2).regime2}';
for j=1:length(qq), regime_new(j,1) = {int2str(qq{j})}; end
qq={regime_history(indx_init_2).regimestart2}';
for j=1:length(qq), start_new(j,1) = {int2str(qq{j})}; end
disp('Time points where regime 2 differs ')
disp(table(indx_init_2, regime_, start_, regime_new, start_new))
end
else
indx_init_1 = find(isdiff_(:,1));
if ~isempty(indx_init_1)
qq={regime_history0(end,indx_init_1).regime}';
for j=1:length(qq), regime_(j,1) = {int2str(qq{j})}; end
qq={regime_history0(end,indx_init_1).regimestart}';
for j=1:length(qq), start_(j,1) = {int2str(qq{j})}; end
qq={regime_history(indx_init_1).regime}';
for j=1:length(qq), regime_new(j,1) = {int2str(qq{j})}; end
qq={regime_history(indx_init_1).regimestart}';
for j=1:length(qq), start_new(j,1) = {int2str(qq{j})}; end
disp('Time points where regime differs')
disp(table(indx_init_1, regime_, start_, regime_new, start_new))
end
end
end
if is_changed
sto_alphahat=alphahat;
sto_eee = eee;
end
end
regime_history0(max(iter+1,1),:) = regime_history;
oo_.occbin.smoother.regime_history=regime_history0(end,:);
oo_.occbin.smoother.regime_history_iter=regime_history0;
save('info1','regime_history0')
if (maxiter==iter && is_changed) || is_periodic
disp(['Occbin smoother did not converge.'])
if is_periodic
disp(['Occbin smoother algo loops between two solutions.'])
end
else
disp(['Occbin smoother converged.'])
if occbin_smoother_fast && is_changed_start
disp('WARNING: fast algo is used, regime(s) duration(s) was not forced to converge')
end
end
if (~is_changed || occbin_smoother_debug) && nargin==12
if is_changed
CC = sto_CC;
RR = sto_RR;
TT = sto_TT;
oo_.occbin.smoother.regime_history=regime_history0(end-1,:);
end
tmp_smoother=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,alphahat,etahat,epsilonhat,ahat0,SteadyState,trend_coeff,aKK,P,PKK,decomp,Trend,state_uncertainty);
for jf=1:length(smoother_field_list)
oo_.occbin.smoother.(smoother_field_list{jf}) = tmp_smoother.(smoother_field_list{jf});
end
oo_.occbin.smoother.alphahat=alphahat;
oo_.occbin.smoother.etahat=etahat;
oo_.occbin.smoother.epsilonhat=epsilonhat;
oo_.occbin.smoother.ahat=ahat0;
oo_.occbin.smoother.SteadyState=SteadyState;
oo_.occbin.smoother.trend_coeff=trend_coeff;
oo_.occbin.smoother.aK=aKK;
oo_.occbin.smoother.T0=TT;
oo_.occbin.smoother.R0=RR;
oo_.occbin.smoother.C0=CC;
if options_.occbin.smoother.plot
GraphDirectoryName = CheckPath('graphs',M_.fname);
j1=0;
ifig=0;
for j=1:M_.exo_nbr
if M_.Sigma_e(j,j)
j1=j1+1;
if mod(j1,9)==1
hfig = dyn_figure(options_.nodisplay,'name','Occbin smoothed shocks');
ifig=ifig+1;
isub=0;
end
isub=isub+1;
subplot(3,3,isub)
if options_.occbin.smoother.linear_smoother
plot(oo_.occbin.linear_smoother.etahat(j,:)','linewidth',2)
hold on,
end
plot(oo_.occbin.smoother.etahat(j,:)','r--','linewidth',2)
hold on, plot([0 options_.nobs],[0 0],'k--')
set(gca,'xlim',[0 options_.nobs])
title(deblank(M_.exo_names(j,:)),'interpreter','none')
if mod(j1,9)==0
if options_.occbin.smoother.linear_smoother
annotation('textbox', [0.1,0,0.35,0.05],'String', 'Linear','Color','Blue','horizontalalignment','center','interpreter','none');
end
annotation('textbox', [0.55,0,0.35,0.05],'String', 'Piecewise','Color','Red','horizontalalignment','center','interpreter','none');
dyn_saveas(gcf,[GraphDirectoryName filesep M_.fname,'_smoothedshocks_occbin',int2str(ifig)],options_.nodisplay,options_.graph_format);
end
end
if mod(j1,9)~=0 && j==M_.exo_nbr
annotation('textbox', [0.1,0,0.35,0.05],'String', 'Linear','Color','Blue','horizontalalignment','center','interpreter','none');
annotation('textbox', [0.55,0,0.35,0.05],'String', 'Piecewise','Color','Red','horizontalalignment','center','interpreter','none');
dyn_saveas(hfig,[GraphDirectoryName filesep M_.fname,'_smoothedshocks_occbin',int2str(ifig)],options_.nodisplay,options_.graph_format);
end
end
end
end

129
matlab/+occbin/IVF_core.m Normal file
View File

@ -0,0 +1,129 @@
function [filtered_errs, resids, Emat, stateval, error_code] = IVF_core(M_,oo_,options_,err_index,filtered_errs_init,my_obs_list,obs,init_val)
% function [filtered_errs, resids, Emat, stateval] = IVF_core(M_,oo_,options_,err_index,filtered_errs_init,my_obs_list,obs,init_val)
% Computes thre
%
% Outputs:
% - filtered_errs [T by N_obs] filtered shocks
% - resids [T by N_obs] residuals
% - Emat [N by N_obs by T] response matrix of endogenous variables to shocks at each point in time
% - stateval [T by N] vector of endogenous variables
% - error_code [4 by 1] error code
%
% Inputs
% - M_ [structure] Matlab's structure describing the model (M_).
% - oo_ [structure] Matlab's structure containing the results (oo_).
% - options_ [structure] Matlab's structure describing the current options (options_).
% - err_index [double] index of shocks with strictly positive variance in M_.exo_names
% - filtered_errs_init [T by N_obs] initial values for the shocks
% - my_obs_list [cell] names of observables
% - obs [T by N_obs] observed data
% - init_val [N by 1] initial value of endogenous variables
% Original authors: Pablo Cuba-Borda, Luca Guerrieri, Matteo Iacoviello and Molin Zhong
% Original file downloaded from:
% http://www.lguerrieri.com/jae-replication.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Pablo Cuba-Borda, Luca Guerrieri, and Matteo Iacoviello (2019): "Likelihood evaluation of models
% with occasionally binding constraints", Journal of Applied Econometrics,
% 34(7), 1073-1085
%-------------------------------------
% Filter shocks
%-------------------------------------
[sample_length, n_obs]= size(obs);
nerrs = size(err_index,1);
if nargin<8
init_val = zeros(M_.endo_nbr,1);
end
resids = zeros(sample_length,nerrs);
stateval = zeros(sample_length,M_.endo_nbr);
Emat = zeros(M_.endo_nbr,nerrs,sample_length);
error_code = zeros(4,1);
%solver options (set locally)
options_.solve_algo = options_.occbin.solver.solve_algo;
options_.solve_tolf = options_.occbin.solver.solve_tolf;
options_.solve_tolx = options_.occbin.solver.solve_tolx;
options_.options.steady.maxit = options_.occbin.solver.maxit;
options_.jacobian_flag=1;
opts_simul = options_.occbin.simul;
opts_simul.curb_retrench = options_.occbin.likelihood.curb_retrench;
opts_simul.maxit = options_.occbin.likelihood.maxit;
opts_simul.waitbar = false;
opts_simul.periods = options_.occbin.likelihood.periods;
opts_simul.check_ahead_periods = options_.occbin.likelihood.check_ahead_periods;
opts_simul.periodic_solution = options_.occbin.likelihood.periodic_solution;
opts_simul.restrict_state_space = options_.occbin.likelihood.restrict_state_space;
opts_simul.piecewise_only = 1;
filtered_errs=zeros(sample_length,n_obs);
if options_.occbin.likelihood.waitbar
hh = dyn_waitbar(0,'IVF_core: Filtering the shocks');
set(hh,'Name','IVF_core: Filtering the shocks.');
end
for this_period=1:sample_length
if options_.occbin.likelihood.waitbar
dyn_waitbar(this_period/sample_length, hh, sprintf('Period %u of %u', this_period,sample_length));
end
current_obs = obs(this_period,:);
init_val_old = init_val;
inan = ~isnan(current_obs);
current_obs = current_obs(inan);
obs_list = my_obs_list(inan);
opts_simul.varobs_id=options_.varobs_id(inan)';
opts_simul.exo_pos=err_index(inan); %err_index is predefined mapping from observables to shocks
opts_simul.endo_init = init_val_old;
opts_simul.SHOCKS = filtered_errs_init(this_period,inan);
% [ err_vals_out, exitflag ] = csolve(@(err_vals) occbin.match_function(...
% err_vals, obs_list,current_obs, opts_simul, M_,oo_,options_),...
% err0',@(err_vals) occbin.match_function(...
% err_vals, obs_list,current_obs, opts_simul, M_,oo_,options_),options_.solve_tolf,options_.occbin.solver.maxit);
[err_vals_out, exitflag] = dynare_solve(@occbin.match_function, filtered_errs_init(this_period,inan)', options_, obs_list,current_obs, opts_simul, M_,oo_,options_);
if exitflag
filtered_errs=NaN;
error_code(1) = 304;
error_code(4) = 1000;
if options_.occbin.likelihood.waitbar; dyn_waitbar_close(hh); end
return
end
filtered_errs(this_period,inan)=err_vals_out';
opts_simul.SHOCKS = err_vals_out;
[ resids(this_period,inan), ~, stateval(this_period,:), Emat(:,inan,this_period), M_] = occbin.match_function(...
err_vals_out,obs_list,current_obs,opts_simul, M_,oo_,options_);
init_val = stateval(this_period,:); %update
if max(abs(err_vals_out))>1e8
error_code(1) = 306;
error_code(4) = max(abs(err_vals_out))/1000;
filtered_errs=NaN;
if options_.occbin.likelihood.waitbar; dyn_waitbar_close(hh); end
return
end
if max(abs(resids(this_period,:)))>0.001
disp_verbose('IVF_core: I am stopping because match_function could not find the shocks that',options_.verbosity)
disp_verbose('IVF_core: solve for the model''s observed variables',options_.verbosity)
filtered_errs=NaN;
error_code(1) = 303;
error_code(4) = max(abs(resids(this_period,:)))*100;
if options_.occbin.likelihood.waitbar; dyn_waitbar_close(hh); end
return
end
end
if options_.occbin.likelihood.waitbar
dyn_waitbar_close(hh);
end
end

View File

@ -0,0 +1,198 @@
function [fval,info,exit_flag,DLIK,Hess,SteadyState,trend_coeff,Model,DynareOptions,BayesInfo,DynareResults, atT, innov] = IVF_posterior(xparam1,...
dataset_,obs_info,DynareOptions,Model,EstimatedParameters,BayesInfo,BoundsInfo,DynareResults)
% function [fval,info,exit_flag,DLIK,Hess,SteadyState,trend_coeff,Model,DynareOptions,BayesInfo,DynareResults, atT, innov] = IVF_posterior(xparam1,...
% dataset_,obs_info,DynareOptions,Model,EstimatedParameters,BayesInfo,BoundsInfo,DynareResults)
% Computes Likelihood with inversion filter
%
% INPUTS
% - xparam1 [double] current values for the estimated parameters.
% - dataset_ [structure] dataset after transformations
% - DynareOptions [structure] Matlab's structure describing the current options (options_).
% - Model [structure] Matlab's structure describing the model (M_).
% - EstimatedParameters [structure] characterizing parameters to be estimated
% - BayesInfo [structure] describing the priors
% - BoundsInfo [structure] containing prior bounds
% - DynareResults [structure] Matlab's structure containing the results (oo_).
%
% OUTPUTS
% - fval [double] scalar, value of the likelihood or posterior kernel.
% - info [integer] 4×1 vector, informations resolution of the model and evaluation of the likelihood.
% - exit_flag [integer] scalar, equal to 1 (no issues when evaluating the likelihood) or 0 (not able to evaluate the likelihood).
% - DLIK [double] Empty array.
% - Hess [double] Empty array.
% - SteadyState [double] Empty array.
% - trend [double] Empty array.
% - Model [struct] Updated Model structure described in INPUTS section.
% - DynareOptions [struct] Updated DynareOptions structure described in INPUTS section.
% - BayesInfo [struct] See INPUTS section.
% - DynareResults [struct] Updated DynareResults structure described in INPUTS section.
% - 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).
% Copyright (C) 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/>.
DLIK=[];
Hess=[];
trend_coeff = [];
obs = obs_info.rawdata;
obs_list = DynareOptions.varobs(:);
exit_flag = 1;
if size(xparam1,1)<size(xparam1,2)
xparam1=xparam1';
end
%------------------------------------------------------------------------------
% 1. Get the structural parameters & define penalties
%------------------------------------------------------------------------------
if ~isempty(xparam1)
Model = set_all_parameters(xparam1,EstimatedParameters,Model);
[fval,info,exit_flag,Q,H]=check_bounds_and_definiteness_estimation(xparam1, Model, EstimatedParameters, BoundsInfo);
if info(1)
return
end
end
err_index=DynareOptions.occbin.likelihood.IVF_shock_observable_mapping; % err_index= find(diag(Model.Sigma_e)~=0);
COVMAT1 = Model.Sigma_e(err_index,err_index);
% Linearize the model around the deterministic steady state and extract the matrices of the state equation (T and R).
[T,R,SteadyState,info,Model,DynareResults] = dynare_resolve(Model,DynareOptions,DynareResults,'restrict');
% Return, with endogenous penalty when possible, if dynare_resolve issues an error code (defined in resol).
if info(1)
if info(1) == 3 || info(1) == 4 || info(1) == 5 || info(1)==6 ||info(1) == 19 ||...
info(1) == 20 || info(1) == 21 || info(1) == 23 || info(1) == 26 || ...
info(1) == 81 || info(1) == 84 || info(1) == 85 || info(1) == 86
%meaningful second entry of output that can be used
fval = Inf;
info(4) = info(2);
exit_flag = 0;
return
else
fval = Inf;
info(4) = 0.1;
exit_flag = 0;
return
end
end
%---------------------------------------------
% Calculate likelihood
%---------------------------------------------
sample_length = size(obs,1);
filtered_errs_init = zeros(sample_length,sum(err_index));
[filtered_errs, resids, Emat, stateval, info] = occbin.IVF_core(Model,DynareResults,DynareOptions,err_index,filtered_errs_init,obs_list,obs);
if info(1)
fval = Inf;
exit_flag = 0;
return
end
nobs=size(filtered_errs,1);
%-------------------------------------
% Calculate the selection matrix
%-------------------------------------
iobs=DynareOptions.varobs_id';
likei=NaN(nobs,1);
if ~any(any(isnan(obs)))
log_det_COV=log(det(COVMAT1));
for t = 1:nobs
Gmat1 = Emat(iobs,:,t);
log_det_jacobian = log_det_COV + 2*log(abs(det(Gmat1)));
trace_term = filtered_errs(t,:)/(COVMAT1)*filtered_errs(t,:)';
likei(t,1) = log_det_jacobian + trace_term;
end
likei=likei+length(iobs)*log(2*pi);
else
for t = 1:nobs
inan=~isnan(obs(t,:));
Gmat1 = Emat(iobs(inan),inan,t);
log_det_jacobian = log(det(COVMAT1(inan,inan))) + 2*log(abs(det(Gmat1)));
trace_term = filtered_errs(t,inan)/(COVMAT1(inan,inan))*filtered_errs(t,inan)';
likei(t,1) = log_det_jacobian + trace_term + length(iobs(inan))*log(2*pi);
end
end
like = 0.5*sum(likei(DynareOptions.presample+1:end));
if isinf(like)
fval = Inf;
info(1) = 301;
info(4) = 1000;
exit_flag = 0;
return
elseif isnan(like)
fval = Inf;
info(1) = 302;
info(4) = 1000;
exit_flag = 0;
return
end
maxresid = max(abs(resids(:)));
if maxresid>1e-3
disp_verbose('Penalize failure of residuals to be zero',options_.verbosity)
fval = Inf;
info(1) = 303;
info(4) = sum(resids(:).^2);
exit_flag = 0;
return
end
if ~isempty(xparam1)
prior = -priordens(xparam1,BayesInfo.pshape,BayesInfo.p6,BayesInfo.p7,BayesInfo.p3,BayesInfo.p4);
else
prior = 0;
end
if prior == Inf
% If parameters outside prior bound, minus prior density is very large
fval = Inf;
info(4) = 1000;
exit_flag = 0;
return
end
%---------------------------------------------
% Calculate posterior
%---------------------------------------------
% remember that the likelihood has already been multiplied by -1
% hence, posterior is -1 times the log of the prior
fval = like+prior;
atT = stateval(:,DynareResults.dr.order_var)';
innov = zeros(Model.exo_nbr,sample_length);
innov(diag(Model.Sigma_e)~=0,:)=filtered_errs';
updated_variables = atT*nan;
BayesInfo.mf = BayesInfo.smoother_var_list(BayesInfo.smoother_mf);
initDynareOptions=DynareOptions;
DynareOptions.nk=[]; %unset options_.nk and reset it later
[DynareResults]=store_smoother_results(Model,DynareResults,DynareOptions,BayesInfo,dataset_,obs_info,atT,innov,[],updated_variables,DynareResults.dr.ys,zeros(length(DynareOptions.varobs_id),1));
DynareOptions=initDynareOptions;

View File

@ -0,0 +1,146 @@
function [TT, RR, CC, regime_history] = check_regimes(TT, RR, CC, opts_regime, M_, oo_, options_)
%-function function [TT, RR, CC, regime_history] = check_regimes(TT, RR, CC, opts_regime, M_, oo_, options_)
%
% INPUTS
% - TT [N by N] transition matrix of state space
% - RR [N by N_exo] shock impact matrix of state space
% - CC [N by 1] constant of state space
% - opts_regime_ [structure] structure describing the regime
% - M_ [structure] Matlab's structure describing the model
% - oo_ [structure] Matlab's structure containing the results
% - options_ [structure] Matlab's structure describing the current options
%
% OUTPUTS
% - TT [N by N] transition matrix of state space for each period
% - RR [N by N_exo by T] shock impact matrix of state space for each period
% - CC [N by N_exo by T] constant of state space for each period
% - regime_history [structure] contains the regime history
% Copyright (C) 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/>.
binding_indicator = opts_regime.binding_indicator;
regime_history = opts_regime.regime_history;
gend = size(binding_indicator,1);
if gend ==0
gend = length(regime_history)+1;
end
number_of_constraints = length(M_.occbin.constraint);
if number_of_constraints==1
base_regime.regime = 0;
base_regime.regimestart = 1;
else
base_regime.regime1 = 0;
base_regime.regimestart1 = 1;
base_regime.regime2 = 0;
base_regime.regimestart2 = 1;
end
if isempty(regime_history)
% set default unconstrained regimes
regime_history = base_regime;
regime_history(2:gend-1) = base_regime;
end
init_=0;
if ndim(TT)==2
CC = zeros([size(RR,1),gend ]);
TT = repmat(TT, [1 1 gend]);
RR = repmat(RR, [1 1 gend]);
init_=1;
end
opts_simul = options_.occbin.simul;
opts_simul.full_output=0;
opts_simul.piecewise_only=1;
for tp=1:gend-1
change_it = 0;
if ~isempty(binding_indicator)
if number_of_constraints==1
if regime_history(tp).regime(1) > binding_indicator(tp+1,1)
regime_history(tp).regime = [0 regime_history(tp).regime];
regime_history(tp).regimestart = [1 regime_history(tp).regimestart+1];
change_it = 1;
end
if regime_history(tp).regime(1) < binding_indicator(tp+1,1)
regime_history(tp).regime = [1 regime_history(tp).regime];
regime_history(tp).regimestart = [1 regime_history(tp).regimestart+1];
change_it = 1;
end
else
if regime_history(tp).regime1(1) > binding_indicator(tp+1,1)
regime_history(tp).regime1 = [0 regime_history(tp).regime1];
regime_history(tp).regimestart1 = [1 regime_history(tp).regimestart1+1];
change_it = 1;
end
if regime_history(tp).regime1(1) < binding_indicator(tp+1,1)
regime_history(tp).regime1 = [1 regime_history(tp).regime1];
regime_history(tp).regimestart1 = [1 regime_history(tp).regimestart1+1];
change_it = 1;
end
if regime_history(tp).regime2(1) > binding_indicator(tp+1,2)
regime_history(tp).regime2 = [0 regime_history(tp).regime2];
regime_history(tp).regimestart2 = [1 regime_history(tp).regimestart2+1];
change_it = 1;
end
if regime_history(tp).regime2(1) < binding_indicator(tp+1,2)
regime_history(tp).regime2 = [1 regime_history(tp).regime2];
regime_history(tp).regimestart2 = [1 regime_history(tp).regimestart2+1];
change_it = 1;
end
end
end
if change_it || init_
check_it = 0;
jt=1;
while jt<=tp-1 && check_it==0
check_it = isequal(regime_history(tp),regime_history(jt));
jt = jt+1;
end
if ~check_it && isequal(regime_history(tp),base_regime) && init_
check_it = true;
jt=1;
end
if check_it %|| tp==1 % the matrices for regime have been already computed
TT(:,:,tp+1) = TT(:,:,jt);
RR(:,:,tp+1) = RR(:,:,jt);
CC(:,tp+1) = CC(:,jt);
else
if number_of_constraints==1
nperi = max(regime_history(tp).regimestart);
else
nperi = max([regime_history(tp).regimestart1 regime_history(tp).regimestart2]);
end
opts_simul.endo_init_=zeros(size(RR,1),1);
opts_simul.init_binding_indicator=[];
opts_simul.init_regime=regime_history(tp);
opts_simul.SHOCKS=zeros(1,size(RR,2));
opts_simul.maxit=1;
opts_simul.periods=nperi;
options_.occbin.simul=opts_simul;
[~, ~, ss] = occbin.solver(M_,oo_,options_);
TT(:,:,tp+1) = ss.T(oo_.dr.order_var,oo_.dr.order_var);
RR(:,:,tp+1) = ss.R(oo_.dr.order_var,:);
CC(:,tp+1) = ss.C(oo_.dr.order_var);
end
end
end

View File

@ -0,0 +1,72 @@
function [A,B,ys,info,M_,oo_,TT, RR, CC, A0, B0] ...
= dynare_resolve(M_,options_,oo_,regime_history, reduced_state_space, A, B)
% function [A,B,ys,info,M_,options_,oo_,TT, RR, CC, A0, B0] ...
% = dynare_resolve(M_,options_,oo_,regime_history, reduced_state_space, A, B)
% Computes the linear approximation and the matrices A and B of the
% transition equation. Mirrors dynare_resolve
%
% Inputs:
% - M_ [structure] Matlab's structure describing the model
% - options_ [structure] Matlab's structure containing the options
% - oo_ [structure] Matlab's structure containing the results
% - reduced_state_space [string]
% - A [double] State transition matrix
% - B [double] shock impact matrix
% Outputs:
% - A [double] State transition matrix (potentially for restricted state space)
% - B [double] shock impact matrix (potentially for restricted state space)
% - ys [double] vector of steady state values
% - info [double] 4 by 1 vector with exit flag and information
% - M_ [structure] Matlab's structure describing the model
% - options_ [structure] Matlab's structure containing the options
% - oo_ [structure] Matlab's structure containing the results
% - TT [N by N] transition matrix of state space for each period
% - RR [N by N_exo by T] shock impact matrix of state space for each period
% - CC [N by N_exo by T] constant of state space for each period
% - A0 [double] State transition matrix (unrestricted state space)
% - B0 [double] shock impact matrix (unrestricted state space)
% Copyright (C) 2001-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/>.
if nargin<6
[A,B,ys,info,M_,oo_] = dynare_resolve(M_,options_,oo_);
else
ys = oo_.dr.ys;
info = 0;
end
if ~info(1) && nargin>4 && ~isempty(regime_history)
opts_regime.regime_history=regime_history;
opts_regime.binding_indicator=[];
[TT, RR, CC] = ...
occbin.check_regimes(A, B, [], opts_regime, M_,oo_,options_);
else
TT=A;
RR=B;
CC=zeros(size(A,1),1);
end
A0=A;
B0=B;
if ~info(1) && nargin>4 && ischar(reduced_state_space) && ~isempty(reduced_state_space)
iv = oo_.dr.restrict_var_list;
A=A(iv,iv);
B=B(iv,:);
TT=TT(iv,iv,:);
RR=RR(iv,:,:);
CC=CC(iv,:);
end

View File

@ -0,0 +1,69 @@
function [h_minus_1, h, h_plus_1, h_exo, resid] = get_deriv(M_, ys_)
% function [h_minus_1, h, h_plus_1, h_exo, resid] = get_deriv(M_, ys_)
% Computes dynamic Jacobian and writes it to conformable matrices
%
% INPUTS
% - M_ [struct] Definition of the model.
% - ys vector steady state
%
% OUTPUTS
% - h_minus_1 [N by N] derivative matrix with respect to lagged endogenous variables
% - h [N by N] derivative matrix with respect to contemporanous endogenous variables
% - h_plus_1 [N by N] derivative matrix with respect to leaded endogenous variables
% - h_exo [N by N_exo] derivative matrix with respect to exogenous variables
% - resid [N by 1] vector of residuals
% Copyright (C) 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/>.
x = zeros(M_.maximum_lag + M_.maximum_lead + 1,M_.exo_nbr);
iyv = M_.lead_lag_incidence';
iyr0 = find(iyv(:)) ;
z=repmat(ys_,1,M_.maximum_lag + M_.maximum_lead + 1);
[resid,g1]=feval([M_.fname,'.dynamic'],z(iyr0),x, M_.params, ys_, M_.maximum_exo_lag+1);
% Initialize matrices
h_minus_1=zeros(M_.endo_nbr);
h = h_minus_1;
h_plus_1 = h_minus_1;
% build h_minus_1
if M_.maximum_lag
lag_columns=find(iyv(:,1));
n_lag_columns=length(lag_columns);
h_minus_1(:,lag_columns) = g1(:,1:n_lag_columns);
else
n_lag_columns=0;
end
% build h
contemporaneous_columns=find(iyv(:,M_.maximum_lag+1));
n_contemporaneous_columns = length(contemporaneous_columns);
h(:,contemporaneous_columns) = g1(:,1+n_lag_columns:n_lag_columns+n_contemporaneous_columns);
%build h_plus_1
if M_.maximum_lead
lead_columns=find(iyv(:,end));
n_lead_columns = length(lead_columns);
h_plus_1(:,lead_columns) = g1(:,n_lag_columns+n_contemporaneous_columns+1:n_lag_columns+n_contemporaneous_columns+n_lead_columns);
else
n_lead_columns=0;
end
h_exo =g1(:,n_lag_columns+n_contemporaneous_columns+n_lead_columns+1:end);

57
matlab/+occbin/get_info.m Normal file
View File

@ -0,0 +1,57 @@
function M_ = get_info(M_)
%function M_ = get_info(M_)
% Parses constraint to clean spaces and provide information on endogenous variables
% involved in constraints
%
% INPUTS
% - M_ [struct] Definition of the model.
%
% OUTPUTS
% - M_ [struct] Definition of the model.
% Copyright (C) 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/>.
delimiters = char(',',';','(',')','+','-','^','*','/','>','<','=');
iwish=0;
indx_=[];
wish_list='';
M_.occbin.constraint_nbr=length(M_.occbin.constraint);
for k=1:M_.occbin.constraint_nbr
%get rid of redundant spaces;
M_.occbin.constraint(k).bind=strrep(M_.occbin.constraint(k).bind,' ','');
M_.occbin.constraint(k).relax=strrep(M_.occbin.constraint(k).relax,' ','');
bind_clean = occbin.tokenize(M_.occbin.constraint(k).bind,delimiters);
relax_clean = occbin.tokenize(M_.occbin.constraint(k).relax,delimiters);
for j=1:M_.endo_nbr
tmp=ismember(M_.endo_names{j},bind_clean);
tmp1=ismember(M_.endo_names{j},relax_clean);
if tmp || tmp1
iwish = iwish+1;
indx_(iwish)=j;
if iwish>1
wish_list = char(wish_list,M_.endo_names{j});
else
wish_list = M_.endo_names{j};
end
end
end
end
M_.occbin.wish_list.endo = wish_list;
M_.occbin.wish_list.iendo = indx_;
end

32
matlab/+occbin/get_pq.m Normal file
View File

@ -0,0 +1,32 @@
function [p,q]=get_pq(dr)
% function [p,q]=get_pq(dr)
% Output decision rule matrices p and q in declaration order
%
% INPUTS
% - dr [struct] decision rules
%
% OUTPUTS
% - p [N by N] transition matrix ghu in declaration order
% - q [N by N_exo] shock response matrix ghx in declaration order
% Copyright (C) 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/>.
nvars = size(dr.ghx,1);
p = zeros(nvars);
p(dr.order_var,dr.state_var) = dr.ghx;
q = dr.ghu(dr.inv_order_var,:);

156
matlab/+occbin/graph.m Normal file
View File

@ -0,0 +1,156 @@
function graph(M_, options_, options_occbin_, oo_, var_list)
% function graph(M_, options_, options_occbin_, oo_, var_list)
%
% Inputs:
% - M_ [structure] Matlab's structure describing the model
% - options_ [structure] Matlab's structure containing the options
% - options_occbin_ [structure] Matlab's structure containing Occbin options
% - oo_ [structure] Matlab's structure containing the results
% - var_list [char] list of the variables to plot
% Copyright (C) 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/>.
options_ = occbin.set_option(options_,options_occbin_,'graph.steady_state');
if ~exist([M_.dname '/graphs'],'dir')
mkdir(M_.dname,'graphs');
end
fidTeX=write_latex_header(M_,options_);
if isempty(var_list)
var_list = M_.endo_names(1:M_.orig_endo_nbr);
end
%get endogenous variables
[i_var, number_of_plots_to_draw_endo, index_uniques] = varlist_indices(var_list, M_.endo_names, 1);
var_list_plots=var_list(index_uniques);
var_list_TeX = M_.endo_names_tex(i_var);
data_to_plot(:,:,1)=oo_.occbin.piecewise(:,i_var);
if isfield(oo_.occbin,'linear')
data_to_plot(:,:,2)=oo_.occbin.linear(:,i_var);
legend_list = {'Piecewise Linear','Linear'};
else
legend_list = {'Piecewise Linear'};
end
nperiods=size(data_to_plot,1);
ndim=size(data_to_plot,3);
if ~options_.occbin.graph.steady_state
data_to_plot=data_to_plot-repmat(oo_.occbin.ys(i_var)',nperiods,1,ndim);
end
%get exogenous variables
[i_var_exo, number_of_plots_to_draw_exo, index_uniques] = varlist_indices(var_list, M_.exo_names, 1);
var_list_plots=[var_list_plots; var_list(index_uniques)];
var_list_TeX = [var_list_TeX; M_.exo_names_tex(i_var_exo)];
if number_of_plots_to_draw_exo>0
exo_index=NaN(number_of_plots_to_draw_exo);
for ii=1:length(i_var_exo)
temp_index=find(oo_.occbin.exo_pos==i_var_exo(ii));
if ~isempty(temp_index)
exo_index(ii)=temp_index;
else
error('%s was not part of the shocks for Occbin.', var_list{i_var_exo(ii)});
end
end
data_to_plot(:,end+1:end+number_of_plots_to_draw_exo,1)=[oo_.occbin.shocks_sequence(:,exo_index); zeros(nperiods-size(oo_.occbin.shocks_sequence,1),number_of_plots_to_draw_exo)];
data_to_plot(:,end+1:end+number_of_plots_to_draw_exo,2)=NaN;
end
[nbplt,nr,nc,lr,lc,nstar] = pltorg(number_of_plots_to_draw_endo+number_of_plots_to_draw_exo);
for fig = 1:nbplt
hh = dyn_figure(options_.nodisplay,'Name',['Occbin simulated paths, figure ' int2str(fig)]);
for plt = 1:nstar
if fig==nbplt && ~lr==0
subplot(lr,lc,plt);
else
subplot(nr,nc,plt);
end
h_zero=plot([1 nperiods],[0 0],'--k','linewidth',0.5);
hold on
h1=plot(1:nperiods,data_to_plot(:,(fig-1)*nstar+plt,1),'b-','linewidth',2);
if ndim==2 && (fig-1)*nstar+plt<=number_of_plots_to_draw_endo
h2=plot(1:nperiods,data_to_plot(:,(fig-1)*nstar+plt,2),'r--','linewidth',2); hold on
end
hold off
max_y = max(max(data_to_plot(:,(fig-1)*nstar+plt,:)));
min_y = min(min(data_to_plot(:,(fig-1)*nstar+plt,:)));
y_bottom = min_y - .01*abs(min_y);
y_top = max_y + 0.01*abs(max_y);
if y_bottom==y_top
y_top=y_bottom+1;
end
axis([1 nperiods y_bottom y_top])
remove_fractional_xticks
if plt==1
if ndim==2
legend([h1,h2],legend_list,'box','off')
else
legend([h1],legend_list,'box','off')
end
end
if options_.TeX
title(['$' var_list_TeX{(fig-1)*nstar+plt,:} '$'],'Interpreter','latex');
else
title(deblank(var_list_plots((fig-1)*nstar+plt,:)),'Interpreter','none');
end
if number_of_plots_to_draw_endo+number_of_plots_to_draw_exo==(fig-1)*nstar+plt
break
end
end
dyn_saveas(hh,[M_.dname, '/graphs/' M_.fname '_occbin_' int2str(fig)],options_.nodisplay,options_.graph_format);
if options_.TeX && any(strcmp('eps',cellstr(options_.graph_format)))
fprintf(fidTeX,'\\begin{figure}[H]\n');
fprintf(fidTeX,'\\centering \n');
if fig==nbplt
fprintf(fidTeX,'\\includegraphics[width=%2.2f\\textwidth]{%s_occbin_%s}\n',options_.figures.textwidth*min(plt/nc,1),[M_.dname, '/graphs/' M_.fname],int2str(fig));
else
fprintf(fidTeX,'\\includegraphics[width=%2.2f\\textwidth]{%s_occbin_%s}\n',options_.figures.textwidth*min(plt/lc,1),[M_.dname, '/graphs/' M_.fname],int2str(fig));
end
fprintf(fidTeX,'\\caption{Simulated time paths over time. Blue solid line: taking occasionally binding constraint into account. Red dashed line: ignoring constraint.}\n');
fprintf(fidTeX,'\\label{Fig:occbin:%s}\n', int2str(fig));
fprintf(fidTeX,'\\end{figure}\n');
fprintf(fidTeX,' \n');
end
end
if options_.TeX && any(strcmp('eps',cellstr(options_.graph_format)))
fprintf(fidTeX,' \n');
fprintf(fidTeX,'%% End Of TeX file. \n');
fclose(fidTeX);
end
function fidTeX=write_latex_header(M_,options_)
if options_.TeX && any(strcmp('eps',cellstr(options_.graph_format)))
fidTeX = fopen([M_.dname, '/graphs/' M_.fname '_occbin.tex'],'w');
fprintf(fidTeX,'%% TeX eps-loader file generated by occbin.make_chart.m (Dynare).\n');
fprintf(fidTeX,['%% ' datestr(now,0) '\n']);
fprintf(fidTeX,' \n');
else
fidTeX =[];
end

View File

@ -0,0 +1,75 @@
function [M_, oo_, options_] = initialize(M_,oo_,options_)
% function [M_, oo_, options_] = initialize(M_,oo_,options_)
% Initializes run of Occbin: sets default options, parses constraints, creates
% eval_difference-file
%
% INPUT:
% - M_ [structure] Matlab's structure describing the model
% - oo_ [structure] Matlab's structure containing the results
% - options_ [structure] Matlab's structure containing the options
%
% OUTPUT:
% - M_ [structure] Matlab's structure describing the model
% - oo_ [structure] Matlab's structure containing the results
% - options_ [structure] Matlab's structure containing the options
% Copyright (C) 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/>.
options_.occbin = struct();
options_.occbin = occbin.set_default_options(options_.occbin, M_);
oo_.dr=set_state_space(oo_.dr,M_,options_);
M_ = occbin.get_info(M_);
if M_.occbin.constraint_nbr>2
error('Occbin: Only up to two constraints are supported')
end
for k=1:M_.occbin.constraint_nbr
M_.occbin.constraint(k).bind_difference = occbin.process_constraint(M_.occbin.constraint(k).bind,'_difference',M_.endo_names,false,M_.param_names);
M_.occbin.constraint(k).bind_error = occbin.process_error_constraint(M_.occbin.constraint(k).bind_difference);
if isempty(M_.occbin.constraint(k).relax)
M_.occbin.constraint(k).relax_difference = ['~binding.constraint_',int2str(k)];
else
M_.occbin.constraint(k).relax_difference = occbin.process_constraint(M_.occbin.constraint(k).relax,'_difference',M_.endo_names,false,M_.param_names);
end
M_.occbin.constraint(k).relax_error = occbin.process_error_constraint(M_.occbin.constraint(k).relax_difference);
M_.occbin.constraint(k).pswitch_index = strmatch(M_.occbin.constraint(k).pswitch,M_.param_names);
end
nwishes_ = size(M_.occbin.wish_list.endo,1);
fid = fopen(['+' M_.fname '/eval_difference.m'],'w+');
fprintf(fid,'function [binding, relax, err]=eval_difference(zdatalinear_,M_,ys);\n');
for i_indx_=1:nwishes_
fprintf(fid,'%s_difference=zdatalinear_(:,%i);\r\n',deblank(M_.occbin.wish_list.endo(i_indx_,:)),M_.occbin.wish_list.iendo(i_indx_));
end
for k=1:M_.occbin.constraint_nbr
fprintf(fid,'binding.constraint_%i = %s;\r\n',k,M_.occbin.constraint(k).bind_difference);
fprintf(fid,'relax.constraint_%i = %s;\r\n',k,M_.occbin.constraint(k).relax_difference);
% fprintf(fid,'try\r\n');
fprintf(fid,' err.binding_constraint_%i = abs(%s);\r\n',k,M_.occbin.constraint(k).bind_error);
fprintf(fid,' err.relax_constraint_%i = abs(%s);\r\n',k,M_.occbin.constraint(k).relax_error);
% fprintf(fid,'catch\r\n');
%
% fprintf(fid,' err.newviolvecbool_%i = nan(size(err.newviolvecbool_%i));\r\n',k,k);
% fprintf(fid,' err.relaxconstraint_%i = nan(size(err.relaxconstraint_%i));\r\n',k,k);
% fprintf(fid,'end\r\n');
end
fclose(fid);

View File

@ -0,0 +1,427 @@
function [a, a1, P, P1, v, T, R, C, regimes_, error_flag, M_, lik, etahat] = kalman_update_algo_1(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,T0,R0,TT,RR,CC,regimes0,M_,oo_,options_,occbin_options)
% function [a, a1, P, P1, v, T, R, C, regimes_, info, M_, lik, etahat] = kalman_update_algo_1(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,T0,R0,TT,RR,CC,regimes0,M_,oo_,options_,occbin_options)
% INPUTS
% - a [N by 1] t-1's state estimate
% - a1 [N by 2] state predictions made at t-1:t
% - P [N by N] t-1's covariance of states
% - P1 [N by N by 2] one-step ahead forecast error variance at t-1:t
% - data_index: [cell] 1*2 cell of column vectors of indices.
% - Z [N_obs ny N] Selector matrix
% - v [N_obs by 2] prediction error on observables at t-1:t
% - Y: [N_obs by 2] observations at t-1:t
% - H [N_obs by 1] vector of measurement error
% - QQQ [N_exo by N_exo by 3] covariance matrix of shocks at t-1:t+1
% - T0 [N by N] initial state transition matrix
% - R0 [N by N_exo] initial shock impact transition matrix
% - TT [N by N by 2] state transition matrix at t-1:t
% - RR [N by N_exo by 2] shock impact matrix at t-1:t
% - CC [N by 2] state space constant state transition matrix at t-1:t
% - regimes0 [structure] regime info at t-1:t
% - M_ [structure] Matlab's structure describing the model (M_).
% - oo_ [structure] Matlab's structure containing the results (oo_).
% - options_ [structure] Matlab's structure describing the current options (options_).
% - occbin_options_ [structure] Matlab's structure describing the Occbin options.
% - kalman_tol [double] tolerance for reciprocal condition number
%
% Outputs
% - a [N by 2] t-1's state estimate
% - a1 [N by 2] state predictions made at t-1:t
% - P [N by N by 2] t-1's covariance of states
% - P1 [N by N by 2] one-step ahead forecast error variance at t-1:t
% - v [N_obs by 2] prediction error on observables at t-1:t
% - T [N by N by 2] state transition matrix at t-1:t
% - R [N by N_exo by 2] shock impact matrix at t-1:t
% - C [N by 2] state space constant state transition matrix at t-1:t
% - regimes_ [structure] regime info at t-1:t
% - error_flag [integer] error code
% - M_ [structure] Matlab's structure describing the model (M_).
% - lik [double] likelihood
% - etahat: smoothed shocks
%
% Notes: The algorithm and implementation is based on Massimo Giovannini,
% Philipp Pfeiffer, Marco Ratto (2021), Efficient and robust inference of models with occasionally binding
% constraints, Working Papers 2021-03, Joint Research Centre, European Commission
% Copyright (C) 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/>.
warning off
sto.a=a;
sto.a1=a1;
sto.P=P;
sto.P1=P1;
number_constr = length(M_.occbin.constraint);
base_regime = struct();
if number_constr==1
base_regime.regime = 0;
base_regime.regimestart = 1;
else
base_regime.regime1 = 0;
base_regime.regimestart1 = 1;
base_regime.regime2 = 0;
base_regime.regimestart2 = 1;
end
mm=size(a,1);
%% store info in t=1
t=1;
di = data_index{t};
T = TT(:,:,t);
ZZ = Z(di,:);
di = data_index{t};
F = ZZ*P1(:,:,t)*ZZ' + H(di,di);
Fi(di,di,t)=F;
sig=sqrt(diag(F));
iF(di,di,t) = inv(F./(sig*sig'))./(sig*sig');
PZI = P1(:,:,t)*ZZ'*iF(di,di,t);
% K(:,di,t) = T*PZI;
% L(:,:,t) = T-K(:,di,t)*ZZ;
L(:,:,t) = eye(mm)-PZI*ZZ;
if ~options_.occbin.filter.use_relaxation
[a, a1, P, P1, v, alphahat, etahat, lik] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood);
else
[~,~,~,~,~,~, TTx, RRx, CCx] ...
= occbin.dynare_resolve(M_,options_,oo_, base_regime,'reduced_state_space',T0,R0);
TT(:,:,2) = TTx(:,:,end);
RR(:,:,2) = RRx(:,:,end);
CC(:,2) = CCx(:,end);
[a, a1, P, P1, v, alphahat, etahat, lik] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood);
regimes0(1)=base_regime;
end
%% run here the occbin simul
opts_simul = occbin_options.opts_simul;
opts_simul.SHOCKS = zeros(3,M_.exo_nbr);
opts_simul.exo_pos=1:M_.exo_nbr;
opts_simul.SHOCKS(1,:) = etahat(:,2)';
if opts_simul.restrict_state_space
tmp=zeros(M_.endo_nbr,1);
tmp(oo_.dr.restrict_var_list,1)=alphahat(:,1);
opts_simul.endo_init = tmp(oo_.dr.inv_order_var,1);
my_order_var = oo_.dr.order_var(oo_.dr.restrict_var_list);
else
opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1);
my_order_var = oo_.dr.order_var;
end
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
regimes_ = out.regime_history;
if number_constr==1
myregime = [regimes_.regime];
else
myregime = [regimes_.regime1 regimes_.regime2];
end
etahat_hist = {etahat};
regime_hist = {regimes0(1)};
if number_constr==1
regime_end = regimes0(1).regimestart(end);
end
lik_hist=lik;
niter=1;
is_periodic=0;
if options_.occbin.filter.use_relaxation || isequal(regimes0(1),base_regime)
nguess=1;
else
nguess=0;
end
newguess=0;
if any(myregime) || ~isequal(regimes_(1),regimes0(1))
while ~isequal(regimes_(1),regimes0(1)) && ~is_periodic && ~out.error_flag && niter<=options_.occbin.likelihood.max_number_of_iterations
niter=niter+1;
oldstart=1;
if number_constr==1 && length(regimes0(1).regimestart)>1
oldstart = regimes0(1).regimestart(end);
end
newstart=1;
if number_constr==1 && length(regimes_(1).regimestart)>1
newstart = regimes_(1).regimestart(end);
end
if number_constr==1 && (newstart-oldstart)>2 && options_.occbin.filter.use_relaxation
regimestart = max(oldstart+2,round(0.5*(newstart+oldstart)));
regimestart = min(regimestart,oldstart+4);
if regimestart<=regimes_(1).regimestart(end-1)
if length(regimes_(1).regimestart)<=3
regimestart = max(regimestart, min(regimes_(1).regimestart(end-1)+2,newstart));
else
regimes_(1).regime = regimes_(1).regime(1:end-2);
regimes_(1).regimestart = regimes_(1).regimestart(1:end-2);
regimestart = max(regimestart, regimes_(1).regimestart(end-1)+1);
end
end
regimes_(1).regimestart(end)=regimestart;
[~,~,~,~,~,~, TTx, RRx, CCx] ...
= occbin.dynare_resolve(M_,options_,oo_, [base_regime regimes_(1)],'reduced_state_space', T0, R0);
TT(:,:,2) = TTx(:,:,end);
RR(:,:,2) = RRx(:,:,end);
CC(:,2) = CCx(:,end);
elseif newguess==0
TT(:,:,2)=ss.T(my_order_var,my_order_var,1);
RR(:,:,2)=ss.R(my_order_var,:,1);
CC(:,2)=ss.C(my_order_var,1);
end
newguess=0;
regime_hist(niter) = {regimes_(1)};
if number_constr==1
regime_end(niter) = regimes_(1).regimestart(end);
end
[a, a1, P, P1, v, alphahat, etahat, lik] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood);
etahat_hist(niter) = {etahat};
lik_hist(niter) = lik;
opts_simul.SHOCKS(1,:) = etahat(:,2)';
if opts_simul.restrict_state_space
tmp=zeros(M_.endo_nbr,1);
tmp(oo_.dr.restrict_var_list,1)=alphahat(:,1);
opts_simul.endo_init = tmp(oo_.dr.inv_order_var,1);
else
opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1);
end
% opts_simul.init_regime=regimes_(1);
if number_constr==1
myregimestart = [regimes_.regimestart];
else
myregimestart = [regimes_.regimestart1 regimes_.regimestart2];
end
opts_simul.periods = max(opts_simul.periods,max(myregimestart));
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
regimes0=regimes_;
regimes_ = out.regime_history;
if niter>1
for kiter=1:niter-1
is_periodic(kiter) = isequal(regime_hist{kiter}, regimes_(1));
end
is_periodic = any(is_periodic);
if is_periodic
if nguess<3 && number_constr==1
newguess=1;
is_periodic=0;
nguess=nguess+1;
if nguess==1
% change starting regime
regimes_(1).regime=0;
regimes_(1).regimestart=1;
elseif nguess==2
% change starting regime
regimes_(1).regime=[0 1 0];
regimes_(1).regimestart=[1 2 3];
else
regimes_(1).regime=[1 0];
regimes_(1).regimestart=[1 2];
end
[~,~,~,~,~,~, TTx, RRx, CCx] ...
= occbin.dynare_resolve(M_,options_,oo_, [base_regime regimes_(1)],'reduced_state_space',T0,R0);
TT(:,:,2) = TTx(:,:,end);
RR(:,:,2) = RRx(:,:,end);
CC(:,2) = CCx(:,end);
regime_hist = regime_hist(1);
niter=1;
else
% re-set to previous regime
regimes_ = regimes0;
% force projection conditional on previous regime
opts_simul.init_regime=regimes0(1);
if number_constr==1
myregimestart = [regimes0.regimestart];
else
myregimestart = [regimes0.regimestart1 regimes0.regimestart2];
end
opts_simul.periods = max(opts_simul.periods,max(myregimestart));
opts_simul.maxit=1;
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
end
end
end
end
end
error_flag = out.error_flag;
if ~error_flag && niter>options_.occbin.likelihood.max_number_of_iterations && ~isequal(regimes_(1),regimes0(1))
error_flag = 1;
if number_constr==1 % try some other regime
[ll, il]=sort(lik_hist);
[ll, il]=sort(regime_end);
rr=regime_hist(il(2:3));
newstart=1;
if length(rr{1}.regimestart)>1
newstart = rr{1}.regimestart(end)-rr{1}.regimestart(end-1)+1;
end
oldstart=1;
if length(rr{2}.regimestart)>1
oldstart = rr{2}.regimestart(end)-rr{2}.regimestart(end-1)+1;
end
nstart=sort([newstart oldstart]);
regimes_=rr{1}(1);
for k=(nstart(1)+1):(nstart(2)-1)
niter=niter+1;
regimes_(1).regimestart(end)=k;
[~,~,~,~,~,~, TTx, RRx, CCx] ...
= occbin.dynare_resolve(M_,options_,oo_, [base_regime regimes_(1)],'reduced_state_space',T0,R0);
TT(:,:,2) = TTx(:,:,end);
RR(:,:,2) = RRx(:,:,end);
CC(:,2) = CCx(:,end);
[a, a1, P, P1, v, alphahat, etahat, lik] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood);
etahat_hist(niter) = {etahat};
lik_hist(niter) = lik;
regime_hist(niter) = {regimes_(1)};
opts_simul.SHOCKS(1,:) = etahat(:,2)';
if opts_simul.restrict_state_space
tmp=zeros(M_.endo_nbr,1);
tmp(oo_.dr.restrict_var_list,1)=alphahat(:,1);
opts_simul.endo_init = tmp(oo_.dr.inv_order_var,1);
else
opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1);
end
% opts_simul.init_regime=regimes_(1);
if number_constr==1
myregimestart = [regimes_.regimestart];
else
myregimestart = [regimes_.regimestart1 regimes_.regimestart2];
end
opts_simul.periods = max(opts_simul.periods,max(myregimestart));
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
if isequal(out.regime_history(1),regimes_(1))
error_flag=0;
break
end
end
regimes_ = out.regime_history;
end
end
a = out.piecewise(1:2,my_order_var)' - repmat(out.ys(my_order_var),1,2);
T = ss.T(my_order_var,my_order_var,1:2);
R = ss.R(my_order_var,:,1:2);
C = ss.C(my_order_var,1:2);
QQ = R(:,:,2)*QQQ(:,:,3)*transpose(R(:,:,2));
P(:,:,1) = P(:,:,2);
P(:,:,2) = T(:,:,2)*P(:,:,1)*transpose(T(:,:,2))+QQ;
% P = cat(3,P(:,:,2),P2);
regimes_=regimes_(1:3);
etahat=etahat(:,2);
warning on
end
function [a, a1, P, P1, v, alphahat, etahat, lik] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, rescale_prediction_error_covariance, IF_likelihood)
warning off
if nargin<18
IF_likelihood=0;
end
t=2;
%% forward pass
% given updated variables and covarnace in t=1, we make the step to t=2
T = TT(:,:,t);
R = RR(:,:,t);
C = CC(:,t);
Q=QQQ(:,:,t);
QQ = R*Q*transpose(R);
a1(:,t) = T*a(:,t-1)+C;
a(:,t) = a1(:,t);
P1(:,:,t) = T*P(:,:,t-1)*T' + QQ; %transition according to (6.14) in DK (2012)
P(:,:,t) = P1(:,:,t);
di = data_index{t};
if isempty(di)
a(:,t) = a1(:,t);
L(:,:,t) = eye(mm);
P1(:,:,t+1) = T*P(:,:,t)*T' + QQ; %p. 111, DK(2012)
else
ZZ = Z(di,:);
v(di,t) = Y(di,t) - ZZ*a(:,t);
F = ZZ*P(:,:,t)*ZZ' + H(di,di);
sig=sqrt(diag(F));
if rank(F)<size(F,1)
% here we trap cases when some OBC regime triggers singularity
% e.g. no shock to interest rate at ZLB
di=di(find(sig));
ZZ = Z(di,:);
v(di,t) = Y(di,t) - ZZ*a(:,t);
F = ZZ*P(:,:,t)*ZZ' + H(di,di);
sig=sqrt(diag(F));
data_index{t}=di;
end
if rescale_prediction_error_covariance
if IF_likelihood == 0
log_dF = log(det(F./(sig*sig')))+2*sum(log(sig));
end
iF(di,di,t) = inv(F./(sig*sig'))./(sig*sig');
else
if IF_likelihood == 0
log_dF = log(det(F));
end
iF(di,di,t) = inv(F);
end
if IF_likelihood == 0
lik = log_dF + transpose(v(di,t))*iF(di,di,t)*v(di,t) + length(di)*log(2*pi);
end
PZI = P(:,:,t)*ZZ'*iF(di,di,t);
a(:,t) = a(:,t) + PZI*v(di,t);
K = PZI*ZZ;
L(:,:,t) = (eye(mm) - K);
P(:,:,t) = P(:,:,t) - K*P(:,:,t);
end
%% do backward pass
r=zeros(mm,3);
t = t+1;
while t > 1
t = t-1;
di = data_index{t};
if isempty(di)
% in this case, L is simply T due to Z=0, so that DK (2012), eq. 4.93 obtains
r(:,t) = L(:,:,t)'*r(:,t+1); %compute r_{t-1}, DK (2012), eq. 4.38 with Z=0
else
ZZ = Z(di,:);
r(:,t) = ZZ'*iF(di,di,t)*v(di,t) + L(:,:,t)'*r(:,t+1); %compute r_{t-1}, DK (2012), eq. 4.38
end
Q=QQQ(:,:,t);
QRt = Q*transpose(RR(:,:,t));
T = TT(:,:,t);
alphahat(:,t) = a1(:,t) + P1(:,:,t)*r(:,t); %DK (2012), eq. 4.35
etahat(:,t) = QRt*r(:,t); %DK (2012), eq. 4.63
r(:,t) = T'*r(:,t); % KD (2003), eq. (23), equation for r_{t-1,p_{t-1}}
if IF_likelihood && t==2 && not(isempty(di))
ishocks = any(ZZ*RR(:,:,t));
ishocks(find(etahat(ishocks,t)==0))=false;
Gmat1 = ZZ*RR(:,ishocks,t);
if size(Gmat1,1) == size(Gmat1,2)
log_det_jacobian = log(det(Q(ishocks,ishocks))) + 2*log(abs(det(Gmat1)));
trace_term = etahat(ishocks,t)'*(Q(ishocks,ishocks)\etahat(ishocks,t));
lik = log_det_jacobian + trace_term + length(di)*log(2*pi);
else
lik = inf;
end
end
end
warning on
end

View File

@ -0,0 +1,392 @@
function [a, a1, P, P1, v, Fi, Ki, T, R, C, regimes_, error_flag, M_, alphahat, etahat, TT, RR, CC] = kalman_update_algo_3(a,a1,P,P1,data_index,Z,v,Fi,Ki,Y,H,QQQ,T0,R0,TT,RR,CC,regimes0,M_,oo_,options_,occbin_options,kalman_tol,nk)
% function [a, a1, P, P1, v, Fi, Ki, T, R, C, regimes_, error_flag, M_, alphahat, etahat, TT, RR, CC] = kalman_update_algo_3(a,a1,P,P1,data_index,Z,v,Fi,Ki,Y,H,QQQ,T0,R0,TT,RR,CC,regimes0,M_,oo_,options_,occbin_options,kalman_tol,nk)
%
% INPUTS
% - a [N by 1] t-1's state estimate
% - a1 [N by N by 2] state predictions made at t-1:t
% - P [N by N] t-1's covariance of states
% - P1 [N by N by 2] one-step ahead forecast error variance at t-1:t
% - data_index: [cell] 1*2 cell of column vectors of indices.
% - Z [N_obs ny N] Selector matrix
% - v [N_obs by 2] prediction error on observables at t-1:t
% - Fi [N_obs by 1] F_i matrix
% - Ki [N by N_obs] Kalman gain matrix
% - Y: [N_obs by 2] observations at t-1:t
% - H [N_obs by 1] vector of measurement error
% - QQQ [N_exo by N_exo by 3] covariance matrix of shocks at t-1:t+1
% - T0 [N by N] initial state transition matrix
% - R0 [N by N_exo] initial shock impact transition matrix
% - TT [N by N by 2] state transition matrix at t-1:t
% - RR [N by N_exo by 2] shock impact matrix at t-1:t
% - CC [N by 2] state space constant state transition matrix at t-1:t
% - regimes0 [structure] regime info at t-1:t
% - M_ [structure] Matlab's structure describing the model (M_).
% - options_ [structure] Matlab's structure describing the current options (options_).
% - oo_ [structure] Matlab's structure containing the results (oo_).
% - occbin_options_ [structure] Matlab's structure describing the Occbin options.
% - kalman_tol [double] tolerance for reciprocal condition number
% - nk [double] number of forecasting periods
%
% Outputs
% - a [N by 2] t-1's state estimate
% - a1 [N by N by 2] state predictions made at t-1:t
% - P [N by N by 2] t-1's covariance of states
% - P1 [N by N by 2] one-step ahead forecast error variance at t-1:t
% - v [N_obs by 2] prediction error on observables at t-1:t
% - Fi [N_obs by 2] F_i matrix
% - Ki [N by N_obs by 2] Kalman gain matrix
% - TT [N by N by 2] state transition matrix at t-1:t
% - RR [N by N_exo by 2] shock impact matrix at t-1:t
% - CC [N by 2] state space constant state transition matrix at t-1:t
% - regimes_ [structure] regime info at t-1:t
% - error_flag [structure] error flag
% - M_ [structure] Matlab's structure describing the model (M_).
% - alphahat: smoothed variables (a_{t|T})
% - etahat: smoothed shocks
% - TT [N by N by 2] state transition matrix at t-1:t
% - RR [N by N_exo by 2] shock impact matrix at t-1:t
% - CC [N by 2] state space constant state transition matrix at t-1:t
%
% Notes: The algorithm and implementation is based on Massimo Giovannini,
% Philipp Pfeiffer, Marco Ratto (2021), Efficient and robust inference of models with occasionally binding
% constraints, Working Papers 2021-03, Joint Research Centre, European Commission
% Copyright (C) 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/>.
if isempty(nk)
nk=1;
end
nk=max(nk,1);
number_constr = length(M_.occbin.constraint);
opts_simul = occbin_options.opts_regime;base_regime = struct();
if number_constr==1
base_regime.regime = 0;
base_regime.regimestart = 1;
else
base_regime.regime1 = 0;
base_regime.regimestart1 = 1;
base_regime.regime2 = 0;
base_regime.regimestart2 = 1;
end
myrestrict=[];
if options_.smoother_redux
opts_simul.restrict_state_space =1;
myrestrict='restrict';
end
mm=size(a,1);
if ~options_.occbin.filter.use_relaxation
[a, a1, P, P1, v, Fi, Ki, alphahat, etahat] = occbin_kalman_update(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,Ki,Fi,mm,kalman_tol);
else
[~,~,~,~,~,~, TTx, RRx, CCx] ...
= occbin.dynare_resolve(M_,options_,oo_, base_regime,myrestrict,T0,R0);
TT(:,:,2) = TTx(:,:,end);
RR(:,:,2) = RRx(:,:,end);
CC(:,2) = CCx(:,end);
[a, a1, P, P1, v, Fi, Ki, alphahat, etahat] = occbin_kalman_update(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,Ki,Fi,mm,kalman_tol);
regimes0(1)=base_regime;
end
%% run here the occbin simul
opts_simul.SHOCKS = zeros(max(3,1+nk),M_.exo_nbr);
opts_simul.SHOCKS(1,:) = etahat(:,2)';
opts_simul.exo_pos=1:M_.exo_nbr;
if opts_simul.restrict_state_space
tmp=zeros(M_.endo_nbr,1);
tmp(oo_.dr.restrict_var_list,1)=alphahat(:,1);
opts_simul.endo_init = tmp(oo_.dr.inv_order_var,1);
my_order_var = oo_.dr.order_var(oo_.dr.restrict_var_list);
else
opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1);
my_order_var = oo_.dr.order_var;
end
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
regimes_ = out.regime_history;
if number_constr==1
myregime = [regimes_.regime];
else
myregime = [regimes_.regime1 regimes_.regime2];
end
regime_hist = {regimes0};
if number_constr==1
regime_end = regimes0(1).regimestart(end);
end
niter=1;
is_periodic=0;
if options_.occbin.filter.use_relaxation || isequal(regimes0(1),base_regime)
nguess=1;
else
nguess=0;
end
newguess=0;
if any(myregime) || ~isequal(regimes_(1),regimes0(1))
while ~isequal(regimes_(1),regimes0(1)) && ~is_periodic && ~out.error_flag && niter<=options_.occbin.likelihood.max_number_of_iterations
niter=niter+1;
newstart=1;
if number_constr==1 && length(regimes_(1).regimestart)>1
newstart = regimes_(1).regimestart(end);
end
oldstart=1;
if number_constr==1 && length(regimes0(1).regimestart)>1
oldstart = regimes0(1).regimestart(end);
end
if number_constr==1 && (newstart-oldstart)>2 && options_.occbin.filter.use_relaxation
regimestart = max(oldstart+2,round(0.5*(newstart+oldstart)));
regimestart = min(regimestart,oldstart+4);
if regimestart<=regimes_(1).regimestart(end-1)
if length(regimes_(1).regimestart)<=3
regimestart = max(regimestart, min(regimes_(1).regimestart(end-1)+2,newstart));
else
regimes_(1).regime = regimes_(1).regime(1:end-2);
regimes_(1).regimestart = regimes_(1).regimestart(1:end-2);
regimestart = max(regimestart, regimes_(1).regimestart(end-1)+1);
end
end
% % if (newstart-oldstart)>3
% % regimestart = regimes_(1).regimestart(end-1)+oldstart+2;
% % % regimestart = regimes_(1).regimestart(end-1)+round(0.5*(newstart+oldstart))-1;
regimes_(1).regimestart(end)=regimestart;
[~,~,~,~,~,~, TTx, RRx, CCx] ...
= occbin.dynare_resolve(M_,options_,oo_, [base_regime regimes_(1)],myrestrict,T0,R0);
TT(:,:,2) = TTx(:,:,end);
RR(:,:,2) = RRx(:,:,end);
CC(:,2) = CCx(:,end);
elseif newguess==0
TT(:,:,2)=ss.T(my_order_var,my_order_var,1);
RR(:,:,2)=ss.R(my_order_var,:,1);
CC(:,2)=ss.C(my_order_var,1);
end
newguess=0;
regime_hist(niter) = {regimes_};
if number_constr==1
regime_end(niter) = regimes_(1).regimestart(end);
end
[a, a1, P, P1, v, Fi, Ki, alphahat, etahat] = occbin_kalman_update(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,Ki,Fi,mm,kalman_tol);
opts_simul.SHOCKS(1,:) = etahat(:,2)';
% if opts_simul.restrict_state_space
% tmp=zeros(M_.endo_nbr,1);
% tmp(oo_.dr.restrict_var_list,1)=alphahat(:,1);
% opts_simul.endo_init = tmp(oo_.dr.inv_order_var,1);
% else
if opts_simul.restrict_state_space
tmp=zeros(M_.endo_nbr,1);
tmp(oo_.dr.restrict_var_list,1)=alphahat(:,1);
opts_simul.endo_init = tmp(oo_.dr.inv_order_var,1);
else
opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1);
end
% end
% opts_simul.init_regime=regimes_(1); %% why don't we use this ???
if number_constr==1
myregimestart = [regimes_.regimestart];
else
myregimestart = [regimes_.regimestart1 regimes_.regimestart2];
end
opts_simul.periods = max(opts_simul.periods,max(myregimestart));
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
regimes0=regimes_;
regimes_ = out.regime_history;
if niter>1
for kiter=1:niter-1
is_periodic(kiter) = isequal(regime_hist{kiter}, regimes_);
end
is_periodic = any(is_periodic);
if is_periodic
if nguess<3 && number_constr==1
newguess=1;
is_periodic=0;
nguess=nguess+1;
if nguess==1
% change starting regime
regimes_(1).regime=0;
regimes_(1).regimestart=1;
elseif nguess==2
% change starting regime
regimes_(1).regime=[0 1 0];
regimes_(1).regimestart=[1 2 3];
else
regimes_(1).regime=[1 0];
regimes_(1).regimestart=[1 2];
end
[~,~,~,~,~,~, TTx, RRx, CCx] ...
= occbin.dynare_resolve(M_,options_,oo_, [base_regime regimes_(1)],myrestrict,T0,R0);
TT(:,:,2) = TTx(:,:,end);
RR(:,:,2) = RRx(:,:,end);
CC(:,2) = CCx(:,end);
regime_hist = regime_hist(1);
niter=1;
else
% re-set to previous regime
regimes_ = regimes0;
% force projection conditional on previous regime
opts_simul.init_regime=regimes0(1);
if number_constr==1
myregimestart = [regimes0.regimestart];
else
myregimestart = [regimes0.regimestart1 regimes0.regimestart2];
end
opts_simul.periods = max(opts_simul.periods,max(myregimestart));
opts_simul.maxit=1;
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
end
end
end
end
end
error_flag = out.error_flag;
if error_flag==0 && niter>options_.occbin.likelihood.max_number_of_iterations && ~isequal(regimes_(1),regimes0(1)) %fixed point algorithm did not converge
error_flag = 1;
if number_constr==1
% try some other regime before giving up
[ll, il]=sort(regime_end);
rr=regime_hist(il(2:3));
newstart=1;
if length(rr{1}(1).regimestart)>1
newstart = rr{1}(1).regimestart(end)-rr{1}(1).regimestart(end-1)+1;
end
oldstart=1;
if length(rr{2}(1).regimestart)>1
oldstart = rr{2}(1).regimestart(end)-rr{2}(1).regimestart(end-1)+1;
end
nstart=sort([newstart oldstart]);
regimes_=rr{1}(1);
for k=(nstart(1)+1):(nstart(2)-1)
niter=niter+1;
regimes_(1).regimestart(end)=k;
[~,~,~,~,~,~, TTx, RRx, CCx] ...
= occbin.dynare_resolve(M_,options_,oo_, [base_regime regimes_(1)],myrestrict,T0,R0);
TT(:,:,2) = TTx(:,:,end);
RR(:,:,2) = RRx(:,:,end);
CC(:,2) = CCx(:,end);
[a, a1, P, P1, v, Fi, Ki, alphahat, etahat] = occbin_kalman_update(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,Ki,Fi,mm,kalman_tol);
opts_simul.SHOCKS(1,:) = etahat(:,2)';
opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1);
if number_constr==1
myregimestart = [regimes_.regimestart];
else
myregimestart = [regimes_.regimestart1 regimes_.regimestart2];
end
opts_simul.periods = max(opts_simul.periods,max(myregimestart));
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
if isequal(out.regime_history(1),regimes_(1))
error_flag=0;
break
end
end
regimes_ = out.regime_history;
end
end
regimes_=regimes_(1:3);
a = out.piecewise(1:nk+1,my_order_var)' - repmat(out.ys(my_order_var),1,nk+1);
T = ss.T(my_order_var,my_order_var,:);
R = ss.R(my_order_var,:,:);
C = ss.C(my_order_var,:);
TT = ss.T(oo_.dr.order_var,oo_.dr.order_var,1);
RR = ss.R(oo_.dr.order_var,:,1);
CC = ss.C(oo_.dr.order_var,1);
QQ = R(:,:,2)*QQQ(:,:,3)*transpose(R(:,:,2));
P(:,:,1) = P(:,:,2);
for j=1:nk
P(:,:,j+1) = T(:,:,j+1)*P(:,:,j)*transpose(T(:,:,j+1))+QQ;
end
% P = cat(3,P(:,:,2),P2);
end
function [a, a1, P, P1, v, Fi, Ki, alphahat, etahat] = occbin_kalman_update(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,Ki,Fi,mm,kalman_tol)
% [a, a1, P, P1, v, Fi, Ki, alphahat, etahat] = occbin_kalman_update(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,Ki,Fi,mm,kalman_tol)
% - a
% - a1
% - P
% - P1
% - v
% - Fi
% - Ki
t=2;
%% forward pass
% given updated variables and covariance in t=1, we make the step to t=2
T = TT(:,:,t);
R = RR(:,:,t);
C = CC(:,t);
Q=QQQ(:,:,t);
QQ = R*Q*transpose(R);
a1(:,t) = T*a(:,t-1)+C;
a(:,t) = a1(:,t);
P1(:,:,t) = T*P(:,:,t-1)*T' + QQ; %transition according to (6.14) in DK (2012)
P(:,:,t) = P1(:,:,t);
di = data_index{t}';
if isempty(di)
Fi(:,t) = 0;
Ki(:,:,t) = 0;
end
for i=di
Zi = Z(i,:);
v(i,t) = Y(i,t) - Zi*a(:,t); % nu_{t,i} in 6.13 in DK (2012)
Fi(i,t) = Zi*P(:,:,t)*Zi' + H(i); % F_{t,i} in 6.13 in DK (2012), relies on H being diagonal
Ki(:,i,t) = P(:,:,t)*Zi'; % K_{t,i}*F_(i,t) in 6.13 in DK (2012)
if Fi(i,t) > kalman_tol
a(:,t) = a(:,t) + Ki(:,i,t)*v(i,t)/Fi(i,t); %filtering according to (6.13) in DK (2012)
P(:,:,t) = P(:,:,t) - Ki(:,i,t)*Ki(:,i,t)'/Fi(i,t); %filtering according to (6.13) in DK (2012)
else
% do nothing as a_{t,i+1}=a_{t,i} and P_{t,i+1}=P_{t,i}, see
% p. 157, DK (2012)
end
end
%% do backward pass
ri=zeros(mm,1);
t = t+1;
while t > 1
t = t-1;
di = flipud(data_index{t})';
for i = di
if Fi(i,t) > kalman_tol
Li = eye(mm)-Ki(:,i,t)*Z(i,:)/Fi(i,t);
ri = Z(i,:)'/Fi(i,t)*v(i,t)+Li'*ri; % DK (2012), 6.15, equation for r_{t,i-1}
end
end
r(:,t) = ri; % DK (2012), below 6.15, r_{t-1}=r_{t,0}
alphahat(:,t) = a1(:,t) + P1(:,:,t)*r(:,t);
Q=QQQ(:,:,t);
QRt = Q*transpose(RR(:,:,t));
T = TT(:,:,t);
etahat(:,t) = QRt*r(:,t);
ri = T'*ri; % KD (2003), eq. (23), equation for r_{t-1,p_{t-1}}
end
end

View File

@ -0,0 +1,67 @@
function make_chart(titlelist,legendlist,figlabel,ylabels,data_series)
% function make_chart(titlelist,legendlist,figlabel,ylabels,zdata)
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
titlelist = char(strrep(cellstr(titlelist),'_','.'));
ndsets=size(data_series,3); % default, changed below as applicable
nperiods = size(data_series,1);
xvalues = (1:nperiods)';
nvars = size(titlelist,1);
[nbplt,nr,nc,lr,lc,nstar] = pltorg(nvars);
style_cell={'k','r','b','g','c','y'};
for fig = 1:nbplt
figure('Name',[figlabel, ', Figure ' int2str(fig)]);
for plt = 1:nstar
h1=NaN(ndsets);
if fig==nbplt && ~lr==0
subplot(lr,lc,plt);
else
subplot(nr,nc,plt);
end
for data_set_iter=1:ndsets
h1(data_set_iter)=plot(xvalues,data_series(:,(fig-1)*nstar+plt,data_set_iter),style_cell{1+mod(data_set_iter-1,length(style_cell))},'linewidth',2);
hold on
end
grid on
max_y = max(max(data_series(:,(fig-1)*nstar+plt,:)));
min_y = min(min(data_series(:,(fig-1)*nstar+plt,:)));
y_bottom = min_y - .01*abs(min_y);
y_top = max_y + 0.01*abs(max_y);
if y_bottom==y_top
y_top=y_bottom+1;
end
axis([1 nperiods y_bottom y_top])
if plt==1
if numel(strvcat(legendlist(1,:)))
h=legend(legendlist,'Location','Northwest','Fontsize',8);
end
end
title(titlelist(plt,:),'Fontsize',11);
ylabel(ylabels(plt,:))
if nvars==(fig-1)*nstar+plt
break
end
end
end

View File

@ -0,0 +1,49 @@
function [regime, regime_start, error_flag]=map_regime(binding_indicator,debug_switch)
% function [regime, regime_start, error_flag]=map_regime(binding_indicator)
% Map regime indicator into information
%
% Inputs:
% - binding_indicator [integer] [nperiods by 1] vector of regime indices
% - debug_switch [boolean] indicator for printing warnings
%
% Outputs:
% - regime [integer] [1 by n_transitions] vector of regime number indices
% - regime_start [integer] [1 by n_transitions] vectors with period numbers in which regime starts
% - error_flag [boolean] 1 if regime never leaves 1 or is still there at the end of nperiods
% 0 otherwise
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
error_flag=0;
% analyse violvec and isolate contiguous periods in the other regime.
regime(1) = binding_indicator(1);
regime_index = 1;
regime_start(1) = 1;
for i=2:length(binding_indicator)
if binding_indicator(i)~=regime(regime_index)
regime_index=regime_index+1;
regime(regime_index) = binding_indicator(i);
regime_start(regime_index)=i;
end
end
if (regime(1) == 1 && length(regime_start)==1)
disp_verbose('map_regime: Binding regime was never left. nperiods needs to be increased.',debug_switch);
error_flag=1;
end
if (regime(end)==1)
disp_verbose('map_regime: Constraint(s) are binding at the end of the sample. nperiods needs to be increased.',debug_switch);
error_flag=1;
end

View File

@ -0,0 +1,56 @@
function [resids, grad, state_out, E, M_, out] = match_function(err_0, obs_list,current_obs, opts_simul,...
M_, oo_, options_)
% function [resids, grad, stateout, E, M_, out] = match_function(err_0, obs_list,current_obs, opts_simul,...
% M_, oo_, options_)
% Outputs:
% - resids [double] [n_exo by 1] vector of residuals
% - grad [double] [n by n_exo] gradient (response of observables to shocks)
% - state_out [double] [ny by 1] value of endogenous variables
% - E [double] response of endogenous variables to shocks
% - M_ [structure] Matlab's structure describing the model (M_).
% - out [structure] Occbin's results structure
%
% Inputs
% - err_ [double] value of shocks
% - obs_list [cell] names of observables
% - current_obs [double] [1 by n_obs] current value of observables
% - opts_simul [structure] Structure with simulation options
% - M_ [structure] Matlab's structure describing the model (M_).
% - oo_ [structure] Matlab's structure containing the results (oo_).
% - options_ [structure] Matlab's structure describing the current options (options_).
% Original authors: Pablo Cuba-Borda, Luca Guerrieri, Matteo Iacoviello, and Molin Zhong
% Original file downloaded from:
% http://www.lguerrieri.com/jae-replication.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Pablo Cuba-Borda, Luca Guerrieri, and Matteo Iacoviello (2019): "Likelihood evaluation of models
% with occasionally binding constraints", Journal of Applied Econometrics,
% 34(7), 1073-1085
opts_simul.SHOCKS = err_0';
options_.occbin.simul=opts_simul;
options_.occbin.simul.full_output=1;
options_.noprint = 1;
[~, out, ss] = occbin.solver(M_,oo_,options_);
state_out= out.piecewise(1,:)' - out.ys;
E = ss.R(:,opts_simul.exo_pos);
grad = ss.R(opts_simul.varobs_id,opts_simul.exo_pos);
nobs = size(obs_list,1);
resids = zeros(nobs,1);
if ~out.error_flag
% -- add observation block in model ---%
% % put in model file
resids = (out.piecewise(1,opts_simul.varobs_id)-current_obs)'; %-out.endo_ss.(obs_list{this_obs});
else
resids = resids+100;
end
end

76
matlab/+occbin/mkdata.m Normal file
View File

@ -0,0 +1,76 @@
function [data_mat]=make_linear_model_data(n_periods,dr_A,dr_B,endo_names,exo_names,wish_list,shock_pos,shock_size_vec,var_init)
% function [data_mat]=make_linear_model_data(n_periods,dr_A,dr_B,endo_names,exo_names,wish_list,shock_pos,shock_size_vec,var_init)
% Inputs:
% - n_periods [integer] number of simulation periods
% - dr_A [double] [n by n] transition matrix
% - dr_B [double] [n by nexo] shock response matrix
% - endo_names [cell] name of endogenous variables
% - exo_names [cell] name of exogenous variables
% - wish_list [cell] name of requested variables for output
% - shock_pos [integer] index of shocks
% - shock_size_vec [double] [shock periods by 1] vector of
% - var_init [double] [n by 1] vector of initial values (incl. states)
%
% Outputs:
% - data_mat [double] [n_periods by n] vector of regime number indices
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
% given decision rule
neqs = size(endo_names,1);
if nargin<9
var_init = zeros(neqs,1);
end
if nargin<8
shock_size_vec=1;
end
if nargin<7
error('Not enough inputs')
end
history = zeros(neqs,n_periods+1);
% generate data
% history will contain data, the state vector at each period in time will
% be stored columnwise.
history(:,1)= var_init;
lengthshock = size(shock_size_vec,1);
err_vec = zeros(size(exo_names,1),1);
for i = 2:n_periods+1
if i<=(lengthshock+1)
err_vec(shock_pos) = shock_size_vec(i-1,:);
history(:,i) = dr_A * history(:,i-1)+dr_B*err_vec;
else
% update endogenous variables
history(:,i) = dr_A * history(:,i-1);
end
end
% extract desired variables
if ~isempty(wish_list)
n_wish=size(wish_list,1);
wish_pos = zeros(n_wish,1);
for i=1:n_wish
wish_pos(i) = strmatch(wish_list(i,:),endo_names,'exact');
end
data_mat = history(wish_pos,2:end)';
else
data_mat = history(:,2:end)';
end

View File

@ -0,0 +1,169 @@
function [zdata, T, R, CONST, ss, update_flag]=mkdatap_anticipated_2constraints_dyn(n_periods,DM,T_max,...
binding_indicator,irfshock_pos,scalefactor_mod,init,update_flag)
% function [zdata, T, R, CONST, ss, update_flag]=mkdatap_anticipated_2constraints_dyn(n_periods,DM,T_max,...
% binding_indicator,irfshock_pos,scalefactor_mod,init,update_flag)
%
% Inputs:
% - n_periods [double] number for periods for simulation
% - DM [structure] Dynamic model
% - T_max [Tmax] last period where constraints bind
% - binding_indicator [T+1] indicator for constraint violations
% - irfshock_pos [double] shock position
% - scalefactor_mod [double] shock values
% - init [double] [N by 1] initial value of endogenous variables
% - update_flag [boolean] flag whether to update results
%
% Output:
% - zdata [double] T+1 by N matrix of simulated data
% - T [N by N] transition matrix of state space
% - R [N by N_exo] shock impact matrix of state space
% - CONST [N by 1] constant of state space
% - ss [structure] state space system
% - update_flag [boolean] flag that results have been updated
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
persistent dictionary
if update_flag
dictionary=[];
update_flag=false;
end
n_vars = DM.n_vars;
T = DM.decrulea;
CONST = zeros(n_vars,1);
R = DM.decruleb;
if nargin<7
init=zeros(n_vars,1);
end
if nargin<6
scalefactor_mod=1;
end
n_exo=DM.n_exo;
% Tmax = max([regimestart1(nregimes1) regimestart2(nregimes2)])-1; % Tmax is the position of the last period
% when the constraint binds
if ~isempty(dictionary)
if (length(binding_indicator(:))>size(dictionary.binding_indicator,1))
nviol_old = size(dictionary.binding_indicator,1)/2;
tmp = zeros(length(binding_indicator)-nviol_old,size(dictionary.binding_indicator,2));
dictionary.binding_indicator = [dictionary.binding_indicator(1:nviol_old,:); tmp; dictionary.binding_indicator(1+nviol_old:2*nviol_old,:); tmp];
end
if (length(binding_indicator(:))<size(dictionary.binding_indicator,1))
binding_indicator = [binding_indicator; zeros(size(dictionary.binding_indicator,1)/2-size(binding_indicator,1),2) ];
end
end
if T_max > 0
if isempty(dictionary)
tmp = [binding_indicator(T_max,:); zeros(n_periods,2)];
dictionary.binding_indicator(:,1) = tmp(:);
if (binding_indicator(T_max,1) && ~binding_indicator(T_max,2))
temp = -(DM.Abarmat10*DM.decrulea+DM.Bbarmat10)\[DM.Cbarmat10 DM.Jbarmat10 DM.Dbarmat10];
dictionary.ss(1).T = temp(:,1:n_vars);
dictionary.ss(1).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(1).C = temp(:,n_vars+n_exo+1:end);
elseif (binding_indicator(T_max,1) && binding_indicator(T_max,2))
temp = -(DM.Abarmat11*DM.decrulea+DM.Bbarmat11)\[DM.Cbarmat11 DM.Jbarmat11 DM.Dbarmat11];
dictionary.ss(1).T = temp(:,1:n_vars);
dictionary.ss(1).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(1).C = temp(:,n_vars+n_exo+1:end);
else
temp = -(DM.Abarmat01*DM.decrulea+DM.Bbarmat01)\[DM.Cbarmat01 DM.Jbarmat01 DM.Dbarmat01];
dictionary.ss(1).T = temp(:,1:n_vars);
dictionary.ss(1).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(1).C = temp(:,n_vars+n_exo+1:end);
end
end
ireg(T_max)=1;
icount=length(dictionary.ss);
for i = T_max-1:-1:1
tmp = 0*binding_indicator;
tmp(1:end-i+1,:) = binding_indicator(i:end,:);
itmp = find(~any(dictionary.binding_indicator(1:length(tmp)*2,:)-tmp(:)));
if ~isempty(itmp)
ireg(i) = itmp;
else
icount=icount+1;
ireg(i) = icount;
dictionary.binding_indicator(1:length(tmp)*2,icount) = tmp(:);
if (binding_indicator(i,1) && ~binding_indicator(i,2))
temp = -(DM.Bbarmat10+DM.Abarmat10*dictionary.ss(ireg(i+1)).T)\[DM.Cbarmat10 DM.Jbarmat10 DM.Abarmat10*dictionary.ss(ireg(i+1)).C+DM.Dbarmat10];
dictionary.ss(icount).T = temp(:,1:n_vars);
dictionary.ss(icount).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(icount).C = temp(:,n_vars+n_exo+1:end);
elseif (~binding_indicator(i,1) && binding_indicator(i,2))
temp = -(DM.Bbarmat01+DM.Abarmat01*dictionary.ss(ireg(i+1)).T)\[DM.Cbarmat01 DM.Jbarmat01 DM.Abarmat01*dictionary.ss(ireg(i+1)).C+DM.Dbarmat01];
dictionary.ss(icount).T = temp(:,1:n_vars);
dictionary.ss(icount).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(icount).C = temp(:,n_vars+n_exo+1:end);
elseif (binding_indicator(i,1) && binding_indicator(i,2))
temp = -(DM.Bbarmat11+DM.Abarmat11*dictionary.ss(ireg(i+1)).T)\[DM.Cbarmat11 DM.Jbarmat11 DM.Abarmat11*dictionary.ss(ireg(i+1)).C+DM.Dbarmat11];
dictionary.ss(icount).T = temp(:,1:n_vars);
dictionary.ss(icount).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(icount).C = temp(:,n_vars+n_exo+1:end);
else
temp = -(DM.Bbarmat+DM.Abarmat*dictionary.ss(ireg(i+1)).T)\[DM.Cbarmat DM.Jbarmat DM.Abarmat*dictionary.ss(ireg(i+1)).C];
dictionary.ss(icount).T = temp(:,1:n_vars);
dictionary.ss(icount).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(icount).C = temp(:,n_vars+n_exo+1:end);
end
end
end
E = dictionary.ss(ireg(1)).R;
ss = dictionary.ss(ireg(1:T_max));
else
ss = [];
end
% generate data
% history will contain data, the state vector at each period in time will
% be stored columnwise.
history = zeros(n_vars,n_periods+1);
history(:,1) = init;
errvec = zeros(n_exo,1);
errvec(irfshock_pos) = scalefactor_mod;
% deal with shocks
irfpos =1;
if irfpos <=T_max
history(:,irfpos+1) = dictionary.ss(ireg(irfpos)).T* history(:,irfpos)+...
dictionary.ss(ireg(irfpos)).C + E*errvec;
T = dictionary.ss(ireg(irfpos)).T;
CONST = dictionary.ss(ireg(irfpos)).C;
R = E;
else
history(:,irfpos+1) = DM.decrulea*history(:,irfpos)+DM.decruleb*errvec;
end
% all other periods
for irfpos=2:n_periods+1
if irfpos <=T_max
history(:,irfpos+1) = dictionary.ss(ireg(irfpos)).T* history(:,irfpos)+...
dictionary.ss(ireg(irfpos)).C;
else
history(:,irfpos+1) = DM.decrulea*history(:,irfpos);
end
end
zdata = history(:,2:end)';

View File

@ -0,0 +1,151 @@
function [zdata, T, R, CONST, ss, update_flag]=mkdatap_anticipated_dyn(n_periods,DM,...
T_max,binding_indicator,irfshock_pos,scalefactor_mod,init,update_flag)
% function [zdata, T, R, CONST, ss]=mkdatap_anticipated_dyn(nperiods,DM,...
% Tmax,binding_indicator,irfshockpos,scalefactormod,init,update_flag)
%
% Inputs:
% - n_periods [double] number for periods for simulation
% - DM [structure] Dynamic model
% - T_max [Tmax] last period where constraints bind
% - binding_indicator [T+1] indicator for constraint violations
% - irfshock_pos [double] shock position
% - scalefactor_mod [double] shock values
% - init [double] [N by 1] initial value of endogenous variables
% - update_flag [boolean] flag whether to update results
%
% Output:
% - zdata [double] T+1 by N matrix of simulated data
% - T [N by N] transition matrix of state space
% - R [N by N_exo] shock impact matrix of state space
% - CONST [N by 1] constant of state space
% - ss [structure] state space system
% - update_flag [boolean] flag that results have been updated
%
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
persistent dictionary
if update_flag
dictionary=[];
update_flag=false;
end
%Initialize outputs
n_vars = DM.n_vars;
n_exo = DM.n_exo;
T = DM.decrulea;
CONST = zeros(n_vars,1);
R = DM.decruleb;
if nargin<7
init=zeros(n_vars,1);
end
if nargin<6
scalefactor_mod=1;
end
% % get the time-dependent decision rules
if ~isempty(dictionary)
if (length(binding_indicator)>size(dictionary.binding_indicator,1))
dictionary.binding_indicator = [dictionary.binding_indicator; zeros(length(binding_indicator)-size(dictionary.binding_indicator,1),size(dictionary.binding_indicator,2))];
end
if (length(binding_indicator(:))<size(dictionary.binding_indicator,1))
binding_indicator = [binding_indicator; zeros(size(dictionary.binding_indicator,1)-size(binding_indicator,1),1) ];
end
end
if T_max > 0
if isempty(dictionary)
temp = -(DM.Astarbarmat*DM.decrulea+DM.Bstarbarmat)\[DM.Cstarbarmat DM.Jstarbarmat DM.Dstarbarmat];
dictionary.binding_indicator(:,1) = [1; zeros(n_periods,1)];
dictionary.ss(1).T = temp(:,1:n_vars);
dictionary.ss(1).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(1).C = temp(:,n_vars+n_exo+1:end);
end
ireg(T_max)=1;
% equivalent to pre-multiplying by the inverse above if the target
% matrix is invertible. Otherwise it yields the minimum state solution
%P(:,:,Tmax) = -(Astarbarmat*decrulea+Bstarbarmat)\Cstarbarmat;
%D(:,Tmax) = -(Astarbarmat*decrulea+Bstarbarmat)\Dstarbarmat;
icount=length(dictionary.ss);
for i = T_max-1:-1:1
tmp = 0*binding_indicator;
tmp(1:end-i+1) = binding_indicator(i:end);
itmp = find(~any(dictionary.binding_indicator-tmp));
if ~isempty(itmp)
ireg(i) = itmp;
else
icount=icount+1;
ireg(i) = icount;
dictionary.binding_indicator(1:length(tmp),icount) = tmp;
if binding_indicator(i)
temp = -(DM.Bstarbarmat+DM.Astarbarmat*dictionary.ss(ireg(i+1)).T)\[DM.Cstarbarmat DM.Jstarbarmat DM.Astarbarmat*dictionary.ss(ireg(i+1)).C+DM.Dstarbarmat];
dictionary.ss(icount).T = temp(:,1:n_vars);
dictionary.ss(icount).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(icount).C = temp(:,n_vars+n_exo+1:end);
else
temp = -(DM.Bbarmat+DM.Abarmat*dictionary.ss(ireg(i+1)).T)\[DM.Cbarmat DM.Jbarmat (DM.Abarmat*dictionary.ss(ireg(i+1)).C)];
dictionary.ss(icount).T = temp(:,1:n_vars);
dictionary.ss(icount).R = temp(:,n_vars+1:n_vars+n_exo);
dictionary.ss(icount).C = temp(:,n_vars+n_exo+1:end);
end
end
end
E = dictionary.ss(ireg(1)).R;
ss = dictionary.ss(ireg(1:T_max));
else
ss = [];
end
% generate data
% history will contain data, the state vector at each period in time will
% be stored columnwise.
history = zeros(n_vars,n_periods+1);
history(:,1) = init;
errvec = zeros(n_exo,1);
% deal with predetermined conditions
errvec(irfshock_pos) = scalefactor_mod;
% deal with shocks
irfpos =1;
if irfpos <=T_max
history(:,irfpos+1) = dictionary.ss(ireg(irfpos)).T* history(:,irfpos)+...
dictionary.ss(ireg(irfpos)).C + E*errvec;
T = dictionary.ss(ireg(irfpos)).T;
CONST = dictionary.ss(ireg(irfpos)).C;
R = E;
else
history(:,irfpos+1) = DM.decrulea*history(:,irfpos)+DM.decruleb*errvec;
end
% all other periods
for irfpos=2:n_periods+1
if irfpos <=T_max
history(:,irfpos+1) = dictionary.ss(ireg(irfpos)).T* history(:,irfpos)+...
dictionary.ss(ireg(irfpos)).C;
else
history(:,irfpos+1) = DM.decrulea*history(:,irfpos);
end
end
zdata = history(:,2:end)';

View File

@ -0,0 +1,81 @@
function constraint_parsed = process_constraint(constraint,suffix,endo_names,invert_switch,param_names)
%function constraint_parsed = process_constraint(constraint,suffix,endo_names,invert_switch,param_names)
% Processes constraints for use in Occbin, appending endogenous variables
% with suffix and replacing parameters by their value in M_.params
%
% INPUTS
% - constraint [char] constraint to be parsed
% - suffix [char] suffix to be appended
% - endo_names [cell] names of endogenous variables
% - invert_switch [bool] if true, invert direction of the inequality constraint
% - param_names [cell] names of parameters
%
% OUTPUTS
% - constraint_parsed [char] parsed constraint
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
% create a list of delimiters that can separate parameters and endogenoous
% variables in the string that expresses the constraint
delimiters = char(',',';','(',')','+','-','^','*','/','>','<','=');
% split the string that holds the constraint into tokens
tokens = occbin.tokenize(constraint,delimiters);
ntokens = length(tokens);
endo_ss=strcat(endo_names,repmat('_ss',length(endo_names),1));
% search for tokens that match the list of endogenous variables
for i=1:ntokens
valid_token=0;
if ~isempty(find(strcmp(tokens(i),delimiters)))
% if the invert_switch is true
% reverse the direction of the inequality
if invert_switch
if strcmp(tokens(i),cellstr('>'))
tokens(i) = cellstr('<');
elseif strcmp(tokens(i),cellstr('<'))
tokens(i) = cellstr('>');
end
end
valid_token=1;
continue;
end
if ~isempty(find(strcmp(tokens(i),endo_names)))
% when there is a match with an endogenous variable append the suffix
tokens(i) = cellstr([char(tokens(i)),suffix]);
valid_token=1;
continue;
end
par_index=find(strcmp(tokens(i),param_names));
if ~isempty(par_index)
tokens(i) = {['M_.params(',num2str(par_index),')']};
valid_token=1;
continue;
end
ss_index=find(strcmp(tokens(i),endo_ss));
if ~isempty(ss_index)
tokens(i) = {['ys(',num2str(ss_index),')']};
valid_token=1;
continue;
end
if isnan(str2double(tokens(i)))
error('Occbin: Constraint %s contains the uninterpretable token %s', constraint, tokens{i});
end
end
% reassemble the tokens to create a string that expresses the constraint
constraint_parsed = regexprep(strjoin(tokens),' ','');

View File

@ -0,0 +1,35 @@
function error_parsed = process_error_constraint(constraint)
% function constraint1 = process_error_constraint(constraint)
% Constructs a string with the constraint error, i.e. by how much it is violated
% INPUTS
% - constraint [char] constraint to be parsed
%
% OUTPUTS
% - error_parsed [char] parsed constraint
% Copyright (C) 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/>.
error_parsed = constraint;
error_parsed=regexprep(error_parsed,'=','');
num = length(regexp(error_parsed,'>'))+length(regexp(error_parsed,'<'));
error_parsed=regexprep(error_parsed,'>','-(');
error_parsed=regexprep(error_parsed,'<','-(');
for k=1:num
error_parsed=[error_parsed ')'];
end

View File

@ -0,0 +1,206 @@
function options_occbin_ = set_default_options(options_occbin_,M_,flag)
% function options_occbin_ = set_default_options(options_occbin_,M_,flag)
% Sets default options for Occbin
%
% INPUTS
% - options_occbin_ [structure] Matlab's structure describing the current options
% - M_ [structure] Matlab's structure describing the model
% - flag [cell] govern what/how much to initialize
%
% OUTPUTS
% - options_occbin_ [structure] Matlab's structure describing the current options
% Copyright (C) 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/>.
if nargin<3
flag='all';
end
if ismember(flag,{'all'})
options_occbin_.solver.solve_algo=3; %solver for match_function: csolve
options_occbin_.solver.solve_tolx=1e-10;
options_occbin_.solver.solve_tolf=1e-5;
options_occbin_.solver.maxit=10;
options_occbin_.write_regimes.periods=[];
options_occbin_.write_regimes.filename=[M_.fname '_occbin_regimes'];
end
if ismember(flag,{'filter','all'})
options_occbin_.filter.use_relaxation = false;
end
if ismember(flag,{'forecast','all'})
options_occbin_.forecast.debug_flag=false;
options_occbin_.forecast.frcst_regimes=[];
options_occbin_.forecast.maxit=30;
options_occbin_.forecast.periods=30;
options_occbin_.forecast.qmc=0;
options_occbin_.forecast.replic=0;
options_occbin_.forecast.SHOCKS0=[];
options_occbin_.forecast.treepath=1; % number of branches
end
if ismember(flag,{'irf','all'})
options_occbin_.irf.init_regime=[];
options_occbin_.irf.maxit=30;
options_occbin_.irf.threshold = 10^-6;
% options_occbin_.irf.periods=options_.irf;
options_occbin_.irf.shocksize=[];
options_occbin_.irf.shocksigns = {'1','_1'};
end
if ismember(flag,{'likelihood','all'})
options_occbin_.likelihood.curb_retrench = false;
options_occbin_.likelihood.first_period_occbin_update = true;
options_occbin_.likelihood.full_output = false;
options_occbin_.likelihood.IF_likelihood = false;
options_occbin_.likelihood.init_regime_history = [];
options_occbin_.likelihood.init_binding_indicator = false(0);
options_occbin_.likelihood.inversion_filter = false;
options_occbin_.likelihood.IVF_shock_observable_mapping = [];
options_occbin_.likelihood.maxit = 50; % this is for occbin solver algo
options_occbin_.likelihood.max_number_of_iterations = 10; % this is for occbin_kalman_update loop
options_occbin_.likelihood.periods = 100;
options_occbin_.likelihood.check_ahead_periods=200;
options_occbin_.likelihood.periodic_solution=true;
options_occbin_.likelihood.piecewise_only = true;
options_occbin_.likelihood.restrict_state_space = true;
options_occbin_.likelihood.status=true;
options_occbin_.likelihood.use_updated_regime = true;
options_occbin_.likelihood.waitbar=false;
end
if ismember(flag,{'plot_shock_decomp','all'})
options_occbin_.plot_shock_decomp.add_steadystate = false;
options_occbin_.plot_shock_decomp.add_zero_line = false;
options_occbin_.plot_shock_decomp.decomp_type='qoq';
options_occbin_.plot_shock_decomp.figure_size = [200 100 650 850];
options_occbin_.plot_shock_decomp.grid = false;
options_occbin_.plot_shock_decomp.graph_line=false;
options_occbin_.plot_shock_decomp.graph_regime=false;
options_occbin_.plot_shock_decomp.graph_simul=char('total','linear');
options_occbin_.plot_shock_decomp.graph_simul_zoom=char('total','piecewise','linear');
options_occbin_.plot_shock_decomp.graph_zoom=false;
options_occbin_.plot_shock_decomp.init_names_=[];
options_occbin_.plot_shock_decomp.lw=2;
options_occbin_.plot_shock_decomp.mystyles = {':','--',':','-.'};
options_occbin_.plot_shock_decomp.ncol = 3;
options_occbin_.plot_shock_decomp.no_legend = false;
options_occbin_.plot_shock_decomp.no_others = false;
options_occbin_.plot_shock_decomp.T0 = []; % initial date in plot (must be >= TINIT)
options_occbin_.plot_shock_decomp.TINIT = dates(); % date of initialized states for shock decomp
% options_occbin_.plot_shock_decomp.use_shock_groups=options_.plot_shock_decomp.use_shock_groups;
end
if ismember(flag,{'plot_simul','all'})
options_occbin_.plot_simul.add_steadystate = false;
options_occbin_.plot_simul.add_vertical_line = false;
options_occbin_.plot_simul.cutoff = false;
options_occbin_.plot_simul.figure_size = [50 50 850 850];
options_occbin_.plot_simul.labels = {'Linear','Piecewise','Simulation 3','Simulation 4'};
options_occbin_.plot_simul.legend = true;
options_occbin_.plot_simul.length_simul = [];
options_occbin_.plot_simul.linewidth = 2;
options_occbin_.plot_simul.log_normalize_graph = false;
options_occbin_.plot_simul.marg_h(1) = 0.08;
options_occbin_.plot_simul.marg_h(2) = 0.055;
options_occbin_.plot_simul.mycolors = get(groot,'DefaultAxesColorOrder');
options_occbin_.plot_simul.my_dir = 'OccBinSimul';
options_occbin_.plot_simul.mystyles = {'-','--',':','-.'};
options_occbin_.plot_simul.mystst_simul_pos = false;
options_occbin_.plot_simul.ncols = 3;
options_occbin_.plot_simul.normalization_point = 1;
options_occbin_.plot_simul.nrows = 3;
options_occbin_.plot_simul.print_emf = false;
options_occbin_.plot_simul.scale_y = false;
options_occbin_.plot_simul.scale_y1 = true;
options_occbin_.plot_simul.scale_y2 = true;
options_occbin_.plot_simul.simulname = 'occbin_simul';
options_occbin_.plot_simul.subplot_gap = 0.07;
options_occbin_.plot_simul.threshold = 10^-6;
options_occbin_.plot_simul.timeaxis = [];
options_occbin_.plot_simul.use_grid = true;
end
if ismember(flag,{'shock_decomp','all'})
options_occbin_.shock_decomp.additive=false;
options_occbin_.shock_decomp.curb_retrench=false;
options_occbin_.shock_decomp.debug=false;
options_occbin_.shock_decomp.init_in_others=false;
options_occbin_.shock_decomp.init_names_=[];
options_occbin_.shock_decomp.init_total=false;
options_occbin_.shock_decomp.init2shocks= false;
options_occbin_.shock_decomp.main_effect=false;
options_occbin_.shock_decomp.main_effect_init=false;
options_occbin_.shock_decomp.maxit = 100;
options_occbin_.shock_decomp.nfrcst=0;
options_occbin_.shock_decomp.periods = 60;
options_occbin_.shock_decomp.check_ahead_periods=200;
options_occbin_.shock_decomp.shocks_only=false;
options_occbin_.shock_decomp.total_effect=false;
options_occbin_.shock_decomp.conditional_only=true;
options_occbin_.shock_decomp.TINIT = dates(); % date to initialize states for shock decomp
% options_occbin_.shock_decomp.use_shock_groups=options_.plot_shock_decomp.use_shock_groups;
end
if ismember(flag,{'simul','all'})
options_occbin_.simul.debug = false;
options_occbin_.simul.curb_retrench=false;
options_occbin_.simul.endo_init=zeros(M_.endo_nbr,1);
options_occbin_.simul.full_output=true;
options_occbin_.simul.init_regime=[];
options_occbin_.simul.init_binding_indicator=false(0);
options_occbin_.simul.exo_pos=1:M_.exo_nbr;
options_occbin_.simul.local=true;
options_occbin_.simul.maxit=10;
options_occbin_.simul.max_periods=inf;
options_occbin_.simul.periods=30;
options_occbin_.simul.check_ahead_periods=200;
options_occbin_.simul.periodic_solution=true;
options_occbin_.simul.piecewise_only = false;
options_occbin_.simul.restrict_state_space=false;
options_occbin_.simul.SHOCKS=zeros(1,M_.exo_nbr);
options_occbin_.simul.waitbar=true;
end
if ismember(flag,{'smoother','all'})
options_occbin_.smoother.curb_retrench = false;
options_occbin_.smoother.debug = false;
options_occbin_.smoother.fast = false;
options_occbin_.smoother.first_period_occbin_update = true;
options_occbin_.smoother.full_output = false;
% options.occbin.smoother.init_mode = 1; % 0 = standard; 1 = unconditional frcsts zero shocks+smoothed states in each period
options_occbin_.smoother.init_regime_history = [];
options_occbin_.smoother.init_binding_indicator = false(0);
options_occbin_.smoother.inversion_filter = false;
options_occbin_.smoother.linear_smoother = true;
options_occbin_.smoother.maxit = 30; % this is for occbin solver algo
options_occbin_.smoother.max_number_of_iterations = 10; % this is for smoother loop
options_occbin_.smoother.periods = 100;
options_occbin_.smoother.check_ahead_periods=200;
options_occbin_.smoother.piecewise_only = true;
options_occbin_.smoother.plot = true;
options_occbin_.smoother.status=true;
options_occbin_.smoother.waitbar=true;
% options.occbin.smoother.restrict_state_space = 1;
end
if ismember(flag,{'graph','all'})
options_occbin_.graph.steady_state=true;
end

View File

@ -0,0 +1,34 @@
function options_=set_option(options_,options_occbin_,fieldname)
% function options_=set_option(options_,options_occbin_,fieldname)
% Set local option for Occbin
%
% Inputs:
% - options_ [structure] Matlab's structure containing the options
% - options_occbin_ [structure] Matlab's structure containing Occbin options
% - fieldname [string] name of the options field to set
%
% Outputs:
% - options_ [structure] Matlab's structure containing the options
% Copyright (C) 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/>.
dot_pos = strfind(fieldname,'.');
if isfield(options_occbin_,fieldname(1:dot_pos-1)) && isfield(options_occbin_.(fieldname(1:dot_pos-1)),fieldname(dot_pos+1:end))
options_.occbin.(fieldname(1:dot_pos-1)).(fieldname(dot_pos+1:end)) = options_occbin_.(fieldname(1:dot_pos-1)).(fieldname(dot_pos+1:end));
end

52
matlab/+occbin/setup.m Normal file
View File

@ -0,0 +1,52 @@
function [M_, options_] = setup(M_,options_, options_occbin_)
% function [M_, options_] = setup(M_, options_, options_occbin_)
% Sets up run of Occbin: creates shock matrix, sets options
%
% INPUT:
% - M_ [structure] Matlab's structure describing the model
% - options_ [structure] Matlab's structure containing the options
% - options_occbin_ [structure] Matlab's structure containing Occbin options
%
% OUTPUT:
% - M_ [structure] Matlab's structure describing the model
% - options_occbin_ [structure] Matlab's structure containing Occbin options
% Copyright (C) 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/>.
options_ = occbin.set_option(options_,options_occbin_,'simul.periods');
options_ = occbin.set_option(options_,options_occbin_,'simul.curb_retrench');
options_ = occbin.set_option(options_,options_occbin_,'simul.maxit');
options_ = occbin.set_option(options_,options_occbin_,'simul.check_ahead_periods');
options_ = occbin.set_option(options_,options_occbin_,'smoother.periods');
options_ = occbin.set_option(options_,options_occbin_,'smoother.curb_retrench');
options_ = occbin.set_option(options_,options_occbin_,'smoother.maxit');
options_ = occbin.set_option(options_,options_occbin_,'smoother.check_ahead_periods');
options_ = occbin.set_option(options_,options_occbin_,'filter.use_relaxation');
options_ = occbin.set_option(options_,options_occbin_,'likelihood.inversion_filter');
options_ = occbin.set_option(options_,options_occbin_,'smoother.inversion_filter');
if isfield(M_,'surprise_shocks') && ~isempty(M_.surprise_shocks)
temp=zeros(max(cat(2,M_.surprise_shocks.periods)),M_.exo_nbr);
for ii = 1:length(M_.surprise_shocks)
ivar = M_.surprise_shocks(ii).exo_id;
temp(M_.surprise_shocks(ii).periods,ivar) = M_.surprise_shocks(ii).value;
end
shock_index=~all(temp==0);
options_.occbin.simul.SHOCKS=temp(:,shock_index);
options_.occbin.simul.exo_pos=find(shock_index);
end

View File

@ -0,0 +1,266 @@
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 (C) 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

View File

@ -0,0 +1,297 @@
function [data, SS_out, error_flag ] = solve_one_constraint(M_,dr, opts_simul_, solve_DM)
%function [data, SS_out, error_flag ] = solve_one_constraint(M_,dr, opts_simul_, solve_DM)
%
% INPUT:
% - M_ [structure] Matlab's structure describing the model (M_).
% - dr [structure] decision rules for the model
% - opts_simul [structure] Matlab's structure containing the Occbin options (opts_simul).
% - solve_DM [double] indicator on whether to recompute decision rules
%
% OUTPUT:
% - data [structure] simulation result containing fields:
% - linear: paths for endogenous variables ignoring OBC (linear solution)
% - piecewise: paths for endogenous variables satisfying the OBC (occbin/piecewise solution)
% - ys: vector of steady state values
% - regime_history: information on number and time of regime transitions
% - SS_out [structure] State space solution
% - T: [n_vars by n_vars by n_shock_period] array of transition matrices
% - R: [n_vars by n_exo by n_shock_period] array of shock response matrices
% - C: [n_vars by n_shock_period] array of constants
% - error_flag [integer] 1 if a problem was encoutered, 0 otherwise
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
persistent DM
if isempty(DM)
solve_DM=true;
end
data.shocks_sequence = opts_simul_.SHOCKS; % sequence of unforeseen shocks under which one wants to solve the model
n_periods = opts_simul_.periods; % simulation horizon (can be longer than the sequence of shocks defined in shockssequence; must be long enough to ensure convergence back to the reference model at the end of the simulation horizon and may need to be varied depending on the sequence of shocks).
curb_retrench = opts_simul_.curb_retrench; % 0: updates guess based on previous iteration; 1: updates similar to Gauss-Jacobi scheme, slowing iterations down by updating guess only one period at a time
max_iter = opts_simul_.maxit; % maximum number of iterations allowed for the solution algorithm
endo_init = opts_simul_.endo_init; % initial condition for state variables, in deviation from steady state in declaration order
binding_indicator = opts_simul_.init_binding_indicator; % initial guess for constraint violations
regime_history_guess = opts_simul_.init_regime; % initial guess for constraint violations
periodic_solution = opts_simul_.periodic_solution;
data.exo_pos = opts_simul_.exo_pos;
n_shocks_periods = size(data.shocks_sequence,1);
if n_periods < n_shocks_periods
n_periods = n_shocks_periods;
end
nperiods_0 = max(opts_simul_.check_ahead_periods,n_periods-n_shocks_periods);
error_flag=0;
M_base = M_;
dr_base = dr;
% ensure that the two models have the same parameters
% use the parameters for the base model.
%Mstar_.params = Mbase_.params;
data.ys = dr_base.ys;
if solve_DM
DM.n_vars = M_base.endo_nbr;
DM.n_exo = M_base.exo_nbr;
% get the matrices holding the first derivatives for the model
% each regime is treated separately
[DM.Cbarmat, DM.Bbarmat, DM.Abarmat, DM.Jbarmat] = occbin.get_deriv(M_base,data.ys);
Mstar_= M_base;
Mstar_.params(M_.occbin.constraint(1).pswitch_index)= 1;
[DM.Cstarbarmat, DM.Bstarbarmat, DM.Astarbarmat, DM.Jstarbarmat, DM.Dstarbarmat] = occbin.get_deriv(Mstar_,data.ys);
[DM.decrulea,DM.decruleb]=occbin.get_pq(dr_base);
update_flag=true;
else
update_flag=false;
end
endo_names = M_base.endo_names;
exo_names = M_base.exo_names;
% set some initial conditions and loop through the shocks
% period by period
init_orig_ = endo_init;
zdatapiecewise_ = zeros(n_periods,DM.n_vars);
% nwishes_ = size(wishlist_,1);
if ~exist('binding_indicator','var')
binding_indicator = false(nperiods_0+1,1);
else
if length(binding_indicator)<(nperiods_0+1)
binding_indicator = [binding_indicator; false(nperiods_0+1-length(binding_indicator),1)];
end
end
SS_out.T = NaN(DM.n_vars,DM.n_vars,n_shocks_periods);
SS_out.R = NaN(DM.n_vars,DM.n_exo,n_shocks_periods);
SS_out.C = nan(DM.n_vars,n_shocks_periods);
if ~exist('regime_history_','var') || isempty(regime_history_guess)
regime_history = struct();
guess_history = false;
else
guess_history = true;
regime_history = regime_history_guess;
end
if opts_simul_.waitbar
hh = dyn_waitbar(0,'Occbin: Solving the model');
set(hh,'Name','Occbin: Solving the model.');
end
for shock_period = 1:n_shocks_periods
if opts_simul_.waitbar
dyn_waitbar(shock_period/n_shocks_periods, hh, sprintf('Period %u of %u', shock_period,n_shocks_periods));
end
regime_change_this_iteration=true;
iter = 0;
guess_history_it = false;
if guess_history && (shock_period<=length(regime_history_guess)) %beyond guess regime history
guess_history_it = true;
end
is_periodic=false;
binding_indicator_history={};
max_err = NaN(max_iter,1);
while (regime_change_this_iteration && iter<max_iter && ~is_periodic)
iter = iter +1;
if binding_indicator(end) && nperiods_0<opts_simul_.max_periods
binding_indicator = [binding_indicator; false ];
nperiods_0 = nperiods_0 + 1;
disp_verbose(['nperiods has been endogenously increased up to ' int2str(nperiods_0) '.'],opts_simul_.debug)
end
if length(binding_indicator)<(nperiods_0 + 1)
binding_indicator=[binding_indicator; false(nperiods_0 + 1-length(binding_indicator),1)];
end
binding_indicator_history{iter}=binding_indicator;
if iter==1 && guess_history_it
regime = regime_history_guess(shock_period).regime;
regime_start = regime_history_guess(shock_period).regimestart;
binding_indicator(:,1) = regime(end);
for ir=1:length(regime)-1
binding_indicator(regime_start(ir):regime_start(ir+1)-1,1) = regime(ir);
end
nperiods_0 = size(binding_indicator,1)-1; %if history is present, update may be required
end
% analyze when each regime starts based on current guess
[regime, regime_start, error_code_period]=occbin.map_regime(binding_indicator,opts_simul_.debug);
regime_history(shock_period).regime = regime;
regime_history(shock_period).regimestart = regime_start;
% get the hypothesized piece wise linear solution
if shock_period==1 || shock_period>1 && any(data.shocks_sequence(shock_period,:))
[zdatalinear_, SS_out.T(:,:,shock_period), SS_out.R(:,:,shock_period), SS_out.C(:,shock_period), SS, update_flag]=occbin.mkdatap_anticipated_dyn(nperiods_0,DM,...
regime_start(end)-1,binding_indicator,...
data.exo_pos,data.shocks_sequence(shock_period,:),endo_init,update_flag);
[binding, relax, err]=feval([M_.fname,'.eval_difference'],zdatalinear_,M_,dr_base.ys);
% check if changes to the hypothesis of the duration for each
% regime
if any(binding.constraint_1 & ~binding_indicator) || any(relax.constraint_1 & binding_indicator)
err_viol = err.binding_constraint_1(binding.constraint_1 & ~binding_indicator);
err_relax = err.relax_constraint_1(relax.constraint_1 & binding_indicator);
max_err(iter) = max(abs([err_viol;err_relax]));
regime_change_this_iteration = true;
else
regime_change_this_iteration = false;
max_err(iter) = 0;
end
if curb_retrench % apply Gauss-Seidel idea of slowing down the change in the guess
% for the constraint -- only relax one
% period at a time starting from the last
% one when each of the constraints is true.
retrench = false(numel(binding_indicator),1);
max_relax_constraint_1=find(relax.constraint_1 & binding_indicator,1,'last');
if ~isempty(max_relax_constraint_1) && find(relax.constraint_1,1,'last')>=find(binding_indicator,1,'last')
retrench(max_relax_constraint_1) = true;
end
binding_indicator = (binding_indicator | binding.constraint_1) & ~ retrench;
else
binding_indicator= (binding_indicator | binding.constraint_1) & ~(binding_indicator & relax.constraint_1);
end
if iter>1 && regime_change_this_iteration
for kiter=1:iter-1
vvv = [binding_indicator_history{kiter}; false(size(binding_indicator,1)- size(binding_indicator_history{kiter},1), 1)];
is_periodic(kiter) = isequal(vvv, binding_indicator);
end
is_periodic_all =is_periodic;
is_periodic = any(is_periodic);
if is_periodic && periodic_solution
[merr,imerr]=min(max_err(find(is_periodic_all,1):end));
inx = find(is_periodic_all,1):iter;
inx = inx(imerr);
binding_indicator=binding_indicator_history{inx};
if inx<iter
[regime, regime_start, error_code_period]=occbin.map_regime(binding_indicator,opts_simul_.debug);
regime_history(shock_period).regime = regime;
regime_history(shock_period).regimestart = regime_start;
% get the hypothesized piece wise linear solution
[zdatalinear_, SS_out.T(:,:,shock_period), SS_out.R(:,:,shock_period), SS_out.C(:,shock_period), SS, update_flag]=occbin.mkdatap_anticipated_dyn(nperiods_0,DM,...
regime_start(end)-1,binding_indicator,...
data.exo_pos,data.shocks_sequence(shock_period,:),endo_init,update_flag);
end
end
end
else
regime_change_this_iteration=false;
zdatalinear_(1:end-1,:)=zdatalinear_(2:end,:);
zdatalinear_(end,:) = DM.decrulea*zdatalinear_(end-1,:)';
if length(SS)>1
SS=SS(2:end);
else
SS=[];
end
if isempty(SS)
SS_out.T(:,:,shock_period)= DM.decrulea;
SS_out.R(:,:,shock_period)= DM.decruleb;
SS_out.C(:,shock_period)= 0;
else
SS_out.T(:,:,shock_period)= SS(1).T;
SS_out.R(:,:,shock_period)= SS(1).R;
SS_out.C(:,shock_period)= SS(1).C;
end
binding_indicator_history{iter}=binding_indicator;
end
end
if regime_change_this_iteration ==1 && max_iter>1
disp_verbose(['occbin solver:: period ' int2str(shock_period) '::'],opts_simul_.debug)
if is_periodic
disp_verbose('Occbin solver loops between two regimes.',opts_simul_.debug)
if periodic_solution
disp_verbose(['Max error:' num2str(merr) '.'],opts_simul_.debug)
else
if opts_simul_.waitbar; dyn_waitbar_close(hh); end
error_flag = 310;
return
end
else
disp_verbose('Did not converge -- increase maxit.',opts_simul_.debug)
if opts_simul_.waitbar; dyn_waitbar_close(hh); end
error_flag = 311;
return
end
end
if any(error_code_period)
disp_verbose('Increase nperiods.',opts_simul_.debug)
if opts_simul_.waitbar; dyn_waitbar_close(hh); end
error_flag = 312;
return
end
endo_init = zdatalinear_(1,:);
zdatapiecewise_(shock_period,:)=endo_init;
endo_init= endo_init';
% reset binding_indicator for next period's shock -- this resetting is
% consistent with expecting no additional shocks
binding_indicator=[binding_indicator(2:end); false];
end
% if necessary, fill in the rest of the path with the remainder of the
% last IRF computed.
zdatapiecewise_(n_shocks_periods+1:end,:)=zdatalinear_(2:n_periods-n_shocks_periods+1,:);
data.piecewise=zdatapiecewise_;
data.regime_history=regime_history;
if ~opts_simul_.piecewise_only
% get the linear responses
data.linear = occbin.mkdata(max(n_periods,size(data.shocks_sequence,1)),...
DM.decrulea,DM.decruleb,endo_names,exo_names,...
[],data.exo_pos,data.shocks_sequence,init_orig_);
end
if opts_simul_.waitbar
dyn_waitbar_close(hh);
end

View File

@ -0,0 +1,321 @@
function [ data, SS_out, error_flag] = solve_two_constraints(M_,dr, opts_simul_, solve_DM)
% function [ data, SS_out, error_flag] = solve_two_constraints(M_,dr, opts_simul_, solve_DM)
%
% INPUT:
% - M_ [structure] Matlab's structure describing the model (M_).
% - dr [structure] decision rules for the model
% - opts_simul [structure] Matlab's structure containing the Occbin options (opts_simul).
% - solve_DM [double] indicator on whether to recompute decision rules
%
% OUTPUT:
% - data [structure] simulation result containing fields:
% - linear: paths for endogenous variables ignoring OBC (linear solution)
% - piecewise: paths for endogenous variables satisfying the OBC (occbin/piecewise solution)
% - ys: vector of steady state values
% - regime_history: information on number and time of regime transitions
% - SS_out [structure] State space solution
% - T: [n_vars by n_vars by n_shock_period] array of transition matrices
% - R: [n_vars by n_exo by n_shock_period] array of shock response matrices
% - C: [n_vars by n_shock_period] array of constants
% - error_flag [integer] 1 if a problem was encoutered, 0 otherwise
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
persistent DM
if isempty(DM)
solve_DM=true;
end
data.shocks_sequence= opts_simul_.SHOCKS; % sequence of unforeseen shocks under which one wants to solve the model
n_periods = opts_simul_.periods; % simulation horizon (can be longer than the sequence of shocks defined in shockssequence; must be long enough to ensure convergence back to the reference model at the end of the simulation horizon and may need to be varied depending on the sequence of shocks).
curb_retrench = opts_simul_.curb_retrench; % 0: updates guess based on previous iteration; 1: updates similar to Gauss-Jacobi scheme, slowing iterations down by updating guess only one period at a time
max_iter = opts_simul_.maxit; % maximum number of iterations allowed for the solution algorithm
endo_init = opts_simul_.endo_init; % initial condition for state variables, in deviation from steady state in declaration order
binding_indicator = opts_simul_.init_binding_indicator; % initial guess for constraint violations
regime_history_guess = opts_simul_.init_regime; % initial guess for constraint violations
periodic_solution = opts_simul_.periodic_solution;
data.exo_pos = opts_simul_.exo_pos;
n_shocks_periods = size(data.shocks_sequence,1);
if n_periods < n_shocks_periods
n_periods = n_shocks_periods;
end
nperiods_0 = max(opts_simul_.check_ahead_periods,n_periods-n_shocks_periods);
error_flag=0;
M00_ = M_;
% ensure that all models have the same parameters
% use the parameters for the base model.
%keep the correct auxiliary regime specific parameter values
data.ys = dr.ys;
if solve_DM %recompute solution matrices
[DM.Cbarmat ,DM.Bbarmat, DM.Abarmat, DM.Jbarmat] = occbin.get_deriv(M00_,data.ys);
M10_ = M00_;
M10_.params(strmatch(M_.occbin.constraint(1).pswitch,M00_.param_names,'exact'))= 1;
[DM.Cbarmat10, DM.Bbarmat10, DM.Abarmat10, DM.Jbarmat10, DM.Dbarmat10] = occbin.get_deriv(M10_,data.ys);
M01_ = M00_;
M01_.params(strmatch(M_.occbin.constraint(2).pswitch,M00_.param_names,'exact'))= 1;
[DM.Cbarmat01, DM.Bbarmat01, DM.Abarmat01, DM.Jbarmat01, DM.Dbarmat01] = occbin.get_deriv(M01_,data.ys);
M11_ = M00_;
M11_.params(M_.occbin.constraint(1).pswitch_index)= 1;
M11_.params(M_.occbin.constraint(2).pswitch_index)= 1;
[DM.Cbarmat11, DM.Bbarmat11, DM.Abarmat11, DM.Jbarmat11, DM.Dbarmat11] = occbin.get_deriv(M11_,data.ys);
[DM.decrulea,DM.decruleb]=occbin.get_pq(dr);
update_flag=true;
DM.n_vars = M00_.endo_nbr;
DM.n_exo = M00_.exo_nbr;
else
update_flag=false;
end
endo_names = M00_.endo_names;
exo_names = M00_.exo_names;
init_orig_ = endo_init;
zdatapiecewise_ = zeros(n_periods,DM.n_vars);
if ~exist('binding_indicator','var')
binding_indicator = false(nperiods_0+1,2); % This sets the first guess for when
% the constraints are going to hold.
% The variable is a boolean with two columns. The first column refers to
% constrain1_; the second to constrain2_.
% Each row is a period in time.
% If the boolean is true it indicates the relevant constraint is expected
% to evaluate to true.
% The default initial guess is consistent with the base model always
% holding -- equivalent to the linear solution.
else
if size(binding_indicator,1)<(nperiods_0+1)
binding_indicator = [binding_indicator; false(nperiods_0+1-size(binding_indicator,1),2)];
end
end
SS_out.T = NaN(DM.n_vars,DM.n_vars,n_shocks_periods);
SS_out.R = NaN(DM.n_vars,DM.n_exo,n_shocks_periods);
SS_out.C = NaN(DM.n_vars,n_shocks_periods);
if ~exist('regime_history_','var') || isempty(regime_history_guess)
regime_history = struct();
guess_history = false;
else
guess_history = true; %previous information exists
regime_history = regime_history_guess;
end
if opts_simul_.waitbar
hh = dyn_waitbar(0,'Occbin: Solving the model');
set(hh,'Name','Occbin: Solving the model.');
end
for shock_period = 1:n_shocks_periods
if opts_simul_.waitbar
dyn_waitbar(shock_period/n_shocks_periods, hh, sprintf('Period %u of %u', shock_period,n_shocks_periods));
end
regime_change_this_iteration=true;
iter = 0;
guess_history_it = false;
if guess_history && (shock_period<=length(regime_history_guess)) %beyond guess regime history
guess_history_it = true;
end
is_periodic=false;
binding_indicator_history={};
max_err = NaN(max_iter,1);
while (regime_change_this_iteration && iter<max_iter && ~is_periodic)
iter = iter +1;
if any(binding_indicator(end,:)) && nperiods_0<opts_simul_.max_periods
binding_indicator = [binding_indicator; false(2,1)];
nperiods_0 = nperiods_0 + 1;
disp_verbose(['nperiods has been endogenously increased up to ' int2str(nperiods_0) '.'],opts_simul_.debug)
end
if size(binding_indicator,1)<(nperiods_0 + 1)
binding_indicator=[binding_indicator; false(nperiods_0 + 1-size(binding_indicator,1),2)];
end
binding_indicator_history{iter}=binding_indicator;
if iter==1 && guess_history_it
regime_1 = regime_history_guess(shock_period).regime1;
regime_start_1 = regime_history_guess(shock_period).regimestart1;
binding_indicator(:,1) = regime_1(end);
for ir=1:length(regime_1)-1
binding_indicator(regime_start_1(ir):regime_start_1(ir+1)-1,1) = regime_1(ir);
end
regime_2 = regime_history_guess(shock_period).regime2;
regime_start_2 = regime_history_guess(shock_period).regimestart2;
binding_indicator(:,2) = regime_2(end);
for ir=1:length(regime_2)-1
binding_indicator(regime_start_2(ir):regime_start_2(ir+1)-1,2) = regime_2(ir);
end
nperiods_0 = size(binding_indicator,1)-1; %if history is present, update may be required
end
% analyse violvec and isolate contiguous periods in the other regime.
[regime_1, regime_start_1, error_code_period(1)]=occbin.map_regime(binding_indicator(:,1),opts_simul_.debug);
regime_history(shock_period).regime1 = regime_1;
regime_history(shock_period).regimestart1 = regime_start_1;
[regime_2, regime_start_2, error_code_period(2)]=occbin.map_regime(binding_indicator(:,2),opts_simul_.debug);
regime_history(shock_period).regime2 = regime_2;
regime_history(shock_period).regimestart2 = regime_start_2;
if shock_period==1 || shock_period>1 && any(data.shocks_sequence(shock_period,:)) % first period or shock happening
Tmax=max([regime_start_1(end) regime_start_2(end)])-1;
[zdatalinear_, SS_out.T(:,:,shock_period), SS_out.R(:,:,shock_period), SS_out.C(:,shock_period), SS, update_flag]=occbin.mkdatap_anticipated_2constraints_dyn(nperiods_0,...
DM,Tmax,...
binding_indicator,...
data.exo_pos,data.shocks_sequence(shock_period,:),endo_init, update_flag);
[binding, relax, err]=feval([M_.fname,'.eval_difference'],zdatalinear_,M_,dr.ys);
binding_constraint_new=[binding.constraint_1;binding.constraint_2];
relaxed_constraint_new = [relax.constraint_1;relax.constraint_2];
err_binding_constraint_new = [err.binding_constraint_1; err.binding_constraint_2];
err_relaxed_constraint_new = [err.relax_constraint_1; err.relax_constraint_2];
% check if changes_
if any(binding_constraint_new & ~binding_indicator(:)) || any(relaxed_constraint_new & binding_indicator(:))
err_violation = err_binding_constraint_new(binding_constraint_new & ~binding_indicator(:));
err_relax = err_relaxed_constraint_new(relaxed_constraint_new & binding_indicator(:));
max_err(iter) = max(abs([err_violation;err_relax]));
regime_change_this_iteration = true;
else
regime_change_this_iteration = false;
max_err(iter) = 0;
end
if curb_retrench % apply Gauss-Seidel idea of slowing down the change in the guess
% for the constraint -- only relax one
% period at a time starting from the last
% one when each of the constraints is true.
retrench = false(numel(binding_indicator),1);
max_relax_constraint_1=find(relax.constraint_1 & binding_indicator(:,1),1,'last');
if ~isempty(max_relax_constraint_1) && find(relax.constraint_1,1,'last')>=find(binding_indicator(:,1),1,'last')
retrench(max_relax_constraint_1) = true;
end
max_relax_constraint_2=find(relax.constraint_2 & binding_indicator(:,2),1,'last');
if ~isempty(max_relax_constraint_2) && find(relax.constraint_2,1,'last')>=find(binding_indicator(:,2),1,'last')
retrench(max_relax_constraint_2+nperiods_0+1) = true;
end
binding_indicator = (binding_indicator(:) | binding_constraint_new) & ~ retrench;
else
binding_indicator= (binding_indicator(:) | binding_constraint_new) & ~(binding_indicator(:) & relaxed_constraint_new);
end
binding_indicator = reshape(binding_indicator,nperiods_0+1,2);
if iter>1 && regime_change_this_iteration
is_periodic=false(1,iter-1);
for kiter=1:iter-1
vvv = [binding_indicator_history{kiter}; false(size(binding_indicator,1)- size(binding_indicator_history{kiter},1), 2)];
is_periodic(kiter) = isequal(vvv, binding_indicator);
end
is_periodic_all = is_periodic;
is_periodic = any(is_periodic);
if is_periodic && periodic_solution
[min_err,index_min_err]=min(max_err(find(is_periodic_all,1):end));
inx = find(is_periodic_all,1):iter;
inx = inx(index_min_err);
binding_indicator=binding_indicator_history{inx}; %select regime history with same result, but smallest error
if inx<iter %update if needed
[regime_1, regime_start_1, error_code_period(1)]=occbin.map_regime(binding_indicator(:,1),opts_simul_.debug);
regime_history(shock_period).regime1 = regime_1;
regime_history(shock_period).regimestart1 = regime_start_1;
[regime_2, regime_start_2, error_code_period(2)]=occbin.map_regime(binding_indicator(:,2),opts_simul_.debug);
regime_history(shock_period).regime2 = regime_2;
regime_history(shock_period).regimestart2 = regime_start_2;
Tmax=max([regime_start_1(end) regime_start_2(end)])-1;
% get the hypothesized piece wise linear solution
[zdatalinear_, SS_out.T(:,:,shock_period), SS_out.R(:,:,shock_period), SS_out.C(:,shock_period), SS, update_flag]=occbin.mkdatap_anticipated_2constraints_dyn(nperiods_0,DM,...
Tmax,...
binding_indicator,...
data.exo_pos,data.shocks_sequence(shock_period,:),endo_init,update_flag);
end
end
end
else
regime_change_this_iteration= false;
zdatalinear_(1:end-1,:)=zdatalinear_(2:end,:);
zdatalinear_(end,:) = DM.decrulea*zdatalinear_(end-1,:)';
if length(SS)>1
SS=SS(2:end);
else
SS=[];
end
if isempty(SS)
SS_out.T(:,:,shock_period)= DM.decrulea;
SS_out.R(:,:,shock_period)= DM.decruleb;
SS_out.C(:,shock_period)= 0;
else
SS_out.T(:,:,shock_period)= SS(1).T;
SS_out.R(:,:,shock_period)= SS(1).R;
SS_out.C(:,shock_period)= SS(1).C;
end
binding_indicator_history{iter}=binding_indicator;
end
end
if regime_change_this_iteration && max_iter>1
disp_verbose(['occbin solver: period ' int2str(shock_period) ':'],opts_simul_.debug)
if is_periodic
disp_verbose('Occbin solver loops between two regimes.',opts_simul_.debug)
if periodic_solution
disp_verbose(['Max error:' num2str(min_err) '.'],opts_simul_.debug)
else
error_flag = 310;
if opts_simul_.waitbar; dyn_waitbar_close(hh); end
return;
end
else
disp_verbose('Did not converge -- increase maxit.',opts_simul_.debug)
error_flag = 311;
if opts_simul_.waitbar; dyn_waitbar_close(hh); end
return;
end
end
if any(error_code_period)
disp_verbose('Increase nperiods.',opts_simul_.debug)
error_flag = 312;
if opts_simul_.waitbar; dyn_waitbar_close(hh); end
return;
end
endo_init = zdatalinear_(1,:);
zdatapiecewise_(shock_period,:)=endo_init;
endo_init= endo_init';
% update the guess for constraint violations for next period
% update is consistent with expecting no additional shocks next period
binding_indicator=[binding_indicator(2:end,:); false(1,2)];
end
zdatapiecewise_(shock_period+1:end,:)=zdatalinear_(2:n_periods-shock_period+1,:);
data.piecewise=zdatapiecewise_;
data.regime_history=regime_history;
if ~opts_simul_.piecewise_only
% get the linear responses
data.linear = occbin.mkdata(n_periods,DM.decrulea,DM.decruleb,endo_names,exo_names,[],data.exo_pos,data.shocks_sequence,init_orig_);
end
if opts_simul_.waitbar
dyn_waitbar_close(hh);
end

83
matlab/+occbin/solver.m Normal file
View File

@ -0,0 +1,83 @@
function [oo_, out, ss] = solver(M_,oo_,options_)
% function [oo_, out, ss] = solver(M_,oo_,options_,opts_simul)
% Solves the model with an OBC and produces simulations/IRFs
%
% INPUT:
% - opts_simul [structure] Occbin simulation options
% - M_ [structure] Matlab's structure describing the model
% - options_ [structure] Matlab's structure containing the options
%
% OUTPUT:
% - oo_ [structure] Matlab's structure containing the results
% - out [structure] simulation result containing fields:
% - linear: paths for endogenous variables ignoring OBC (linear solution)
% - piecewise: paths for endogenous variables satisfying the OBC (occbin/piecewise solution)
% - ys: vector of steady state values
% - regime_history: information on number and time of regime transitions
% - ss [structure] State space solution
% - T: [n_vars by n_vars by n_shock_period] array of transition matrices
% - R: [n_vars by n_exo by n_shock_period] array of shock response matrices
% - C: [n_vars by n_shock_period] array of constants
% Copyright (C) 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/>.
persistent sto_M sto_dr
% check dr
solve_dr=0;
if isempty(sto_M) || isempty(sto_dr)
solve_dr=1;
else
inan = find(~isnan(M_.params));
inan0 = find(~isnan(sto_M.params));
if ~isequal(inan,inan0) || ~isequal(sto_M.params(inan),M_.params(inan))
solve_dr=1;
end
end
if solve_dr
[dr,error_flag,M_,oo_] = resol(0,M_,options_,oo_);
oo_.dr = dr;
sto_dr=dr;
sto_M=M_;
else
oo_.dr=sto_dr;
end
if M_.occbin.constraint_nbr==1
[out, ss, error_flag ] = occbin.solve_one_constraint(M_,oo_.dr,options_.occbin.simul,solve_dr);
elseif M_.occbin.constraint_nbr==2
[out, ss, error_flag ] = occbin.solve_two_constraints(M_,oo_.dr,options_.occbin.simul,solve_dr);
end
out.error_flag=error_flag;
if error_flag
print_info(error_flag, options_.noprint, options_)
out=[];
return;
end
% add back steady state
if ~options_.occbin.simul.piecewise_only
out.linear = out.linear + out.ys';
end
out.piecewise = out.piecewise+ out.ys';
out.exo_simul = options_.occbin.simul.SHOCKS;
out.exo_pos = options_.occbin.simul.exo_pos;
oo_.occbin=out;

66
matlab/+occbin/tokenize.m Normal file
View File

@ -0,0 +1,66 @@
function tokens = tokenize(source,delimiter)
%function tokens = tokenize(source,delimiter)
% Breaks down strings into its components (tokens)
% INPUTS
% - source [string] string to be broken into tokens
% - delimiter [char array] single character delimiters
%
% OUTPUTS:
% -tokens [cell] array containing the tokens
% Original authors: Luca Guerrieri and Matteo Iacoviello
% Original file downloaded from:
% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip
% Adapted for Dynare by Dynare Team.
%
% This code is in the public domain and may be used freely.
% However the authors would appreciate acknowledgement of the source by
% citation of any of the following papers:
%
% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving
% dynamic models with occasionally binding constraints easily"
% Journal of Monetary Economics 70, 22-38
posdelims = [];
% assumes that delimiter cannot be in the first position or the last position
ndelimiters = size(delimiter,1);
for i=1:ndelimiters
newpositions = strfind(source,delimiter(i,:));
if ~isempty(newpositions)
posdelims =[posdelims, newpositions];
end
end
% reorder posdelims in ascending order
posdelims = sort(posdelims);
if isempty(posdelims)
tokens = cellstr(source);
else
ndelims = length(posdelims);
% build positions for substrings
delims = zeros(ndelims+1,2);
for i=1:ndelims+1
if i==1
if posdelims(1) == 1
tokens = cellstr(source(1));
else
delims(i,:) = [1,posdelims(i)-1];
tokens = cellstr(source([delims(i,1):delims(i,2)]));
tokens = [tokens, source(posdelims(i))];
end
elseif i==ndelims+1
if (posdelims(i-1) < length(source))
delims(i,:) = [posdelims(i-1)+1,length(source)];
tokens = [tokens, cellstr(source([delims(i,1):delims(i,2)]))];
end
else
if posdelims(i)>posdelims(i-1)+1
delims(i,:) = [posdelims(i-1)+1,posdelims(i)-1];
tokens = [tokens, cellstr(source([delims(i,1):delims(i,2)]))];
end
tokens = [tokens, source(posdelims(i))];
end
end
end

View File

@ -0,0 +1,38 @@
function oo_=unpack_simulations(M_,oo_,options_)
% function oo_=unpack_simulations(M_,oo_,options_)
% Writes Occbin simulations from matrix to structure
%
% Inputs
% - M_ [structure] Matlab's structure describing the model
% - oo_ [structure] Matlab's structure containing the results
% - options_ [structure] Matlab's structure containing the options
%
% Outputs
% - oo_ [structure] Matlab's structure containing the results
% Copyright (C) 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/>.
for i=1:M_.endo_nbr
% unpack the IRFs
oo_.occbin.endo_linear.(M_.endo_names{i})= oo_.occbin.linear(:,i);
oo_.occbin.endo_piecewise.(M_.endo_names{i})=oo_.occbin.piecewise(:,i);
oo_.occbin.endo_ss.(M_.endo_names{i})=oo_.occbin.ys(i);
end
for i=1:length(oo_.occbin.exo_pos)
oo_.occbin.exo.(M_.exo_names{i})=options_.occbin.simul.SHOCKS(:,i);
end

View File

@ -0,0 +1,64 @@
function write_regimes_to_xls(regime_history,M_,options_)
% function write_regimes_to_xls(regime_history,M_,options_)
% writes regime results to Excel-file
%
% INPUTS
% - regime_history [struct] information on the regimes
% - M_ [struct] Matlab's structure describing the model
% - options_ [struct] Matlab's structure describing the current options
% Copyright (C) 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/>.
OutputDirectoryName = CheckPath('Output',M_.dname);
if isempty(options_.occbin.write_regimes.periods)
T=1:length(regime_history);
else
T=options_.occbin.write_regimes.periods;
end
xls_filename = options_.occbin.write_regimes.filename;
if isfield(regime_history,'regime')
Header = {'time', 'regime sequence', 'starting period of regime'};
for tp=1:length(T)
xlsmat{tp,1}=T(tp);
xlsmat{tp,2}=int2str(regime_history(tp).regime);
xlsmat{tp,3}=int2str(regime_history(tp).regimestart);
end
else
Header = {'time', 'regime sequence 1', 'starting period of regime 1', 'regime sequence 2', 'starting period of regime 2'};
for tp=1:length(T)
xlsmat{tp,1}=T(tp);
xlsmat{tp,2}=int2str(regime_history(tp).regime1);
xlsmat{tp,3}=int2str(regime_history(tp).regimestart1);
xlsmat{tp,4}=int2str(regime_history(tp).regime2);
xlsmat{tp,5}=int2str(regime_history(tp).regimestart2);
end
end
filename=[OutputDirectoryName filesep xls_filename '.xls'];
if matlab_ver_less_than('9.3')
if exist(filename,'file')
delete(filename)
end
else
if isfile(filename)
delete(filename)
end
end
writetable(array2table(xlsmat,'VariableNames',Header), filename, 'Sheet', 'Regimes');

View File

@ -1,4 +1,4 @@
function [alphahat,etahat,epsilonhat,ahat,SteadyState,trend_coeff,aK,T,R,P,PK,decomp,trend_addition,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,gend,Y,data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_)
function [alphahat,etahat,epsilonhat,ahat,SteadyState,trend_coeff,aK,T,R,P,PK,decomp,trend_addition,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,gend,Y,data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_,varargin)
% Estimation of the smoothed variables and innovations.
%
% INPUTS
@ -96,6 +96,7 @@ end
%------------------------------------------------------------------------------
% 2. call model setup & reduction program
%------------------------------------------------------------------------------
length_varargin=length(varargin);
if ~options_.smoother_redux
%store old setting of restricted var_list
@ -111,9 +112,22 @@ if ~options_.smoother_redux
bayestopt_.mf = bayestopt_.smoother_var_list(bayestopt_.smoother_mf);
else
[T,R,SteadyState,info,M_,oo_] = dynare_resolve(M_,options_,oo_,'restrict');
if ~options_.occbin.smoother.status
[T,R,SteadyState,info,M_,oo_] = dynare_resolve(M_,options_,oo_,'restrict');
else
[T,R,SteadyState,info,M_,oo_,~,~,~, T0, R0] = ...
occbin.dynare_resolve(M_,options_,oo_,[],'restrict');
varargin{length_varargin+1}=T0;
varargin{length_varargin+2}=R0;
end
bayestopt_.mf = bayestopt_.mf1;
end
if options_.occbin.smoother.status
occbin_info.status = true;
occbin_info.info= [{options_,oo_,M_} varargin];
else
occbin_info.status = false;
end
if info~=0
print_info(info,options_.noprint, options_);
@ -179,7 +193,7 @@ elseif options_.lik_init == 3 % Diffuse Kalman filter
kalman_algo = 3;
else
if ~all(all(abs(H-diag(diag(H)))<1e-14))% ie, the covariance matrix is not diagonal...
%Augment state vector (follows Section 6.4.3 of DK (2012))
%Augment state vector (follows Section 6.4.3 of DK (2012))
expanded_state_vector_for_univariate_filter=1;
T = blkdiag(T,zeros(vobs));
np = size(T,1);
@ -236,14 +250,23 @@ if options_.heteroskedastic_filter
Q=get_Qvec_heteroskedastic_filter(Q,smpl,M_);
end
if options_.occbin.smoother.status
if kalman_algo == 1
kalman_algo = 2;
end
if kalman_algo == 3
kalman_algo = 4;
end
end
if kalman_algo == 1 || kalman_algo == 3
a_initial = zeros(np,1);
a_initial=set_Kalman_smoother_starting_values(a_initial,M_,oo_,options_);
a_initial=T*a_initial; %set state prediction for first Kalman step;
a_initial=T*a_initial; %set state prediction for first Kalman step;
[alphahat,epsilonhat,etahat,ahat,P,aK,PK,decomp,state_uncertainty, aahat, eehat, d] = missing_DiffuseKalmanSmootherH1_Z(a_initial,ST, ...
Z,R1,Q,H,Pinf,Pstar, ...
data1,vobs,np,smpl,data_index, ...
options_.nk,kalman_tol,diffuse_kalman_tol,options_.filter_decomposition,options_.smoothed_state_uncertainty,options_.filter_covariance,options_.smoother_redux);
Z,R1,Q,H,Pinf,Pstar, ...
data1,vobs,np,smpl,data_index, ...
options_.nk,kalman_tol,diffuse_kalman_tol,options_.filter_decomposition,options_.smoothed_state_uncertainty,options_.filter_covariance,options_.smoother_redux);
if isinf(alphahat)
if kalman_algo == 1
fprintf('\nDsgeSmoother: Switching to univariate filter. This may be a sign of stochastic singularity.\n')
@ -292,16 +315,18 @@ if kalman_algo == 2 || kalman_algo == 4
%do nothing, state vector was already expanded
end
end
a_initial = zeros(np,1);
a_initial=set_Kalman_smoother_starting_values(a_initial,M_,oo_,options_);
a_initial=ST*a_initial; %set state prediction for first Kalman step;
[alphahat,epsilonhat,etahat,ahat,P,aK,PK,decomp,state_uncertainty, aahat, eehat, d] = missing_DiffuseKalmanSmootherH3_Z(a_initial,ST, ...
Z,R1,Q,diag(H), ...
Pinf,Pstar,data1,vobs,np,smpl,data_index, ...
options_.nk,kalman_tol,diffuse_kalman_tol, ...
options_.filter_decomposition,options_.smoothed_state_uncertainty,options_.filter_covariance,options_.smoother_redux);
[alphahat,epsilonhat,etahat,ahat,P,aK,PK,decomp,state_uncertainty, aahat, eehat, d, regimes_,TT,RR,CC] = missing_DiffuseKalmanSmootherH3_Z(a_initial,ST, ...
Z,R1,Q,diag(H), ...
Pinf,Pstar,data1,vobs,np,smpl,data_index, ...
options_.nk,kalman_tol,diffuse_kalman_tol, ...
options_.filter_decomposition,options_.smoothed_state_uncertainty,options_.filter_covariance,options_.smoother_redux,occbin_info);
if options_.occbin.smoother.status
oo_.occbin.smoother.regime_history = regimes_;
end
end
if expanded_state_vector_for_univariate_filter && (kalman_algo == 2 || kalman_algo == 4)
@ -327,7 +352,7 @@ if expanded_state_vector_for_univariate_filter && (kalman_algo == 2 || kalman_al
end
end
if ~options_.smoother_redux
if ~options_.smoother_redux
%reset old setting of restricted var_list
oo_.dr.restrict_var_list = oldoo.restrict_var_list;
oo_.dr.restrict_columns = oldoo.restrict_columns;
@ -338,107 +363,238 @@ else
ic = oo_.dr.restrict_columns;
end
[A,B] = kalman_transition_matrix(oo_.dr,(1:M_.endo_nbr)',ic,M_.exo_nbr);
iT = pinv(T);
Tstar = A(~ismember(1:M_.endo_nbr,oo_.dr.restrict_var_list),oo_.dr.restrict_var_list);
Rstar = B(~ismember(1:M_.endo_nbr,oo_.dr.restrict_var_list),:);
C = Tstar*iT;
D = Rstar-C*R;
static_var_list = ~ismember(1:M_.endo_nbr,oo_.dr.restrict_var_list);
ilagged = any(abs(C*T-Tstar)'>1.e-12);
static_var_list0 = static_var_list;
static_var_list0(static_var_list) = ilagged;
static_var_list(static_var_list) = ~ilagged;
% reconstruct smoothed variables
aaa=zeros(M_.endo_nbr,gend);
aaa(oo_.dr.restrict_var_list,:)=alphahat;
for k=1:gend
aaa(static_var_list,k) = C(~ilagged,:)*alphahat(:,k)+D(~ilagged,:)*etahat(:,k);
end
if any(ilagged)
if options_.occbin.smoother.status
% reconstruct occbin smoother
if length_varargin>0
isoccbin=1;
else
isoccbin=0;
end
if length_varargin>1
TT=varargin{2};
RR=varargin{3};
CC=varargin{4};
if size(TT,3)<(smpl+1)
TT=repmat(T,1,1,smpl+1);
RR=repmat(R,1,1,smpl+1);
CC=repmat(zeros(mm,1),1,smpl+1);
end
end
if isoccbin==0
[A,B] = kalman_transition_matrix(oo_.dr,(1:M_.endo_nbr)',ic,M_.exo_nbr);
else
opts_simul = options_.occbin.simul;
end
aaa=zeros(M_.endo_nbr,gend);
aaa(oo_.dr.restrict_var_list,:)=alphahat;
for k=2:gend
aaa(static_var_list0,k) = Tstar(ilagged,:)*alphahat(:,k-1)+Rstar(ilagged,:)*etahat(:,k);
if isoccbin
A = TT(:,:,k);
B = RR(:,:,k);
C = CC(:,k);
else
C=0;
end
aaa(:,k) = C+A*aaa(:,k-1)+B*etahat(:,k);
end
end
alphahat=aaa;
% reconstruct updated variables
aaa=zeros(M_.endo_nbr,gend);
aaa(oo_.dr.restrict_var_list,:)=ahat;
for k=1:gend
aaa(static_var_list,k) = C(~ilagged,:)*ahat(:,k)+D(~ilagged,:)*eehat(:,k);
end
if any(ilagged)
alphahat=aaa;
aaa=zeros(M_.endo_nbr,gend);
bbb=zeros(M_.endo_nbr,gend);
bbb(oo_.dr.restrict_var_list,:)=ahat;
aaa(oo_.dr.restrict_var_list,:)=aahat;
for k=d+2:gend
aaa(static_var_list0,k) = Tstar(ilagged,:)*aahat(:,k-1)+Rstar(ilagged,:)*eehat(:,k);
end
end
ahat1=aaa;
% reconstruct aK
aaa = zeros(options_.nk,M_.endo_nbr,gend+options_.nk);
aaa(:,oo_.dr.restrict_var_list,:)=aK;
for k=1:gend
for jnk=1:options_.nk
aaa(jnk,static_var_list,k+jnk) = C(~ilagged,:)*dynare_squeeze(aK(jnk,:,k+jnk));
end
end
if any(ilagged)
for k=1:gend
aaa(1,static_var_list0,k+1) = Tstar(ilagged,:)*ahat(:,k);
for jnk=2:options_.nk
aaa(jnk,static_var_list0,k+jnk) = Tstar(ilagged,:)*dynare_squeeze(aK(jnk-1,:,k+jnk-1));
if isoccbin
A = TT(:,:,k);
B = RR(:,:,k);
C = CC(:,k);
bbb(:,k) = C+A*aaa(:,k-1)+B*eehat(:,k);
else
opts_simul.curb_retrench = options_.occbin.smoother.curb_retrench;
opts_simul.waitbar = options_.occbin.smoother.waitbar;
opts_simul.maxit = options_.occbin.smoother.maxit;
opts_simul.periods = options_.occbin.smoother.periods;
opts_simul.check_ahead_periods = options_.occbin.smoother.check_ahead_periods;
opts_simul.full_output = options_.occbin.smoother.full_output;
opts_simul.piecewise_only = options_.occbin.smoother.piecewise_only;
opts_simul.SHOCKS = zeros(options_.nk,M_.exo_nbr);
opts_simul.SHOCKS(1,:) = eehat(:,k);
tmp=zeros(M_.endo_nbr,1);
tmp(oo_.dr.restrict_var_list,1)=aahat(:,k-1);
opts_simul.endo_init = tmp(oo_.dr.inv_order_var,1);
opts_simul.init_regime = []; %regimes_(k);
options_.occbin.simul=opts_simul;
[~, out] = occbin.solver(M_,oo_,options_);
% regime in out should be identical to regimes_(k-2) moved one
% period ahead (so if regimestart was [1 5] it should be [1 4]
% in out
% end
bbb(oo_.dr.inv_order_var,k) = out.zpiece(1,:);
end
end
end
aK=aaa;
ahat=ahat1;
% reconstruct P
if ~isempty(P)
PP=zeros(M_.endo_nbr,M_.endo_nbr,gend+1);
PP(oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:)=P;
DQD=D(~ilagged,:)*Q*transpose(D(~ilagged,:))+C(~ilagged,:)*R*Q*transpose(D(~ilagged,:))+D(~ilagged,:)*Q*transpose(C(~ilagged,:)*R);
DQR=D(~ilagged,:)*Q*transpose(R);
for k=1:gend+1
PP(static_var_list,static_var_list,k)=C(~ilagged,:)*P(:,:,k)*C(~ilagged,:)'+DQD;
PP(static_var_list,oo_.dr.restrict_var_list,k)=C(~ilagged,:)*P(:,:,k)+DQR;
PP(oo_.dr.restrict_var_list,static_var_list,k)=transpose(PP(static_var_list,oo_.dr.restrict_var_list,k));
ahat0=ahat;
ahat=bbb;
if ~isempty(P)
PP=zeros(M_.endo_nbr,M_.endo_nbr,gend+1);
PP(oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:)=P;
P=PP;
clear PP
end
P=PP;
clear('PP');
end
% reconstruct state_uncertainty
if ~isempty(state_uncertainty)
mm=size(T,1);
ss=length(find(static_var_list));
sstate_uncertainty=zeros(M_.endo_nbr,M_.endo_nbr,gend);
sstate_uncertainty(oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:)=state_uncertainty(1:mm,1:mm,:);
for k=1:gend
sstate_uncertainty(static_var_list,static_var_list,k)=[C(~ilagged,:) D(~ilagged,:)]*state_uncertainty(:,:,k)*[C(~ilagged,:) D(~ilagged,:)]';
tmp = [C(~ilagged,:) D(~ilagged,:)]*state_uncertainty(:,:,k);
sstate_uncertainty(static_var_list,oo_.dr.restrict_var_list,k)=tmp(1:ss,1:mm);
sstate_uncertainty(oo_.dr.restrict_var_list,static_var_list,k)=transpose(sstate_uncertainty(static_var_list,oo_.dr.restrict_var_list,k));
end
state_uncertainty=sstate_uncertainty;
clear('sstate_uncertainty');
end
% reconstruct PK TO DO!!
if ~isempty(PK)
PP = zeros(options_.nk,M_.endo_nbr,M_.endo_nbr,gend+options_.nk);
PP(:,oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:) = PK;
DQD=D(~ilagged,:)*Q*transpose(D(~ilagged,:))+C(~ilagged,:)*R*Q*transpose(D(~ilagged,:))+D(~ilagged,:)*Q*transpose(C(~ilagged,:)*R);
DQR=D(~ilagged,:)*Q*transpose(R);
for f=1:options_.nk
for k=1:gend
PP(f,static_var_list,static_var_list,k+f)=C(~ilagged,:)*squeeze(PK(f,:,:,k+f))*C(~ilagged,:)'+DQD;
PP(f,static_var_list,oo_.dr.restrict_var_list,k+f)=C(~ilagged,:)*squeeze(PK(f,:,:,k+f))+DQR;
PP(f,oo_.dr.restrict_var_list,static_var_list,k+f)=transpose(squeeze(PP(f,static_var_list,oo_.dr.restrict_var_list,k+f)));
if ~isempty(state_uncertainty)
sstate_uncertainty=zeros(M_.endo_nbr,M_.endo_nbr,gend);
sstate_uncertainty(oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:)=state_uncertainty;
state_uncertainty=sstate_uncertainty;
clear sstate_uncertainty
end
aaa = zeros(options_.nk,M_.endo_nbr,gend+options_.nk);
aaa(:,oo_.dr.restrict_var_list,:)=aK;
for k=2:gend+1
opts_simul.curb_retrench = options_.occbin.smoother.curb_retrench;
opts_simul.waitbar = options_.occbin.smoother.waitbar;
opts_simul.maxit = options_.occbin.smoother.maxit;
opts_simul.periods = options_.occbin.smoother.periods;
opts_simul.check_ahead_periods = options_.occbin.smoother.check_ahead_periods;
opts_simul.full_output = options_.occbin.smoother.full_output;
opts_simul.piecewise_only = options_.occbin.smoother.piecewise_only;
opts_simul.SHOCKS = zeros(options_.nk,M_.exo_nbr);
tmp=zeros(M_.endo_nbr,1);
tmp(oo_.dr.restrict_var_list,1)=ahat0(:,k-1);
opts_simul.endo_init = tmp(oo_.dr.inv_order_var,1);
opts_simul.init_regime = []; %regimes_(k);
options_.occbin.simul=opts_simul;
[~, out] = occbin.solver(M_,oo_,options_);
% regime in out should be identical to regimes_(k-2) moved one
% period ahead (so if regimestart was [1 5] it should be [1 4]
% in out
% end
for jnk=1:options_.nk
aaa(jnk,oo_.dr.inv_order_var,k+jnk-1) = out.zpiece(jnk,:);
end
end
PK=PP;
clear('PP');
aK=aaa;
if ~isempty(PK)
PP = zeros(options_.nk,M_.endo_nbr,M_.endo_nbr,gend+options_.nk);
PP(:,oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:) = PK;
PK=PP;
clear PP
end
else
% reconstruct smoother
[A,B] = kalman_transition_matrix(oo_.dr,(1:M_.endo_nbr)',ic,M_.exo_nbr);
iT = pinv(T);
Tstar = A(~ismember(1:M_.endo_nbr,oo_.dr.restrict_var_list),oo_.dr.restrict_var_list);
Rstar = B(~ismember(1:M_.endo_nbr,oo_.dr.restrict_var_list),:);
C = Tstar*iT;
D = Rstar-C*R;
static_var_list = ~ismember(1:M_.endo_nbr,oo_.dr.restrict_var_list);
ilagged = any(abs(C*T-Tstar)'>1.e-12);
static_var_list0 = static_var_list;
static_var_list0(static_var_list) = ilagged;
static_var_list(static_var_list) = ~ilagged;
% reconstruct smoothed variables
aaa=zeros(M_.endo_nbr,gend);
aaa(oo_.dr.restrict_var_list,:)=alphahat;
for k=1:gend
aaa(static_var_list,k) = C(~ilagged,:)*alphahat(:,k)+D(~ilagged,:)*etahat(:,k);
end
if any(ilagged)
for k=2:gend
aaa(static_var_list0,k) = Tstar(ilagged,:)*alphahat(:,k-1)+Rstar(ilagged,:)*etahat(:,k);
end
end
alphahat=aaa;
% reconstruct updated variables
aaa=zeros(M_.endo_nbr,gend);
aaa(oo_.dr.restrict_var_list,:)=ahat;
for k=1:gend
aaa(static_var_list,k) = C(~ilagged,:)*ahat(:,k)+D(~ilagged,:)*eehat(:,k);
end
if any(ilagged)
% bbb=zeros(M_.endo_nbr,gend);
% bbb(oo_.dr.restrict_var_list,:)=aahat;
for k=d+2:gend
aaa(static_var_list0,k) = Tstar(ilagged,:)*aahat(:,k-1)+Rstar(ilagged,:)*eehat(:,k);
end
end
ahat1=aaa;
% reconstruct aK
aaa = zeros(options_.nk,M_.endo_nbr,gend+options_.nk);
aaa(:,oo_.dr.restrict_var_list,:)=aK;
for k=1:gend
for jnk=1:options_.nk
aaa(jnk,static_var_list,k+jnk) = C(~ilagged,:)*dynare_squeeze(aK(jnk,:,k+jnk));
end
end
if any(ilagged)
for k=1:gend
aaa(1,static_var_list0,k+1) = Tstar(ilagged,:)*ahat(:,k);
for jnk=2:options_.nk
aaa(jnk,static_var_list0,k+jnk) = Tstar(ilagged,:)*dynare_squeeze(aK(jnk-1,:,k+jnk-1));
end
end
end
aK=aaa;
ahat=ahat1;
% reconstruct P
if ~isempty(P)
PP=zeros(M_.endo_nbr,M_.endo_nbr,gend+1);
PP(oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:)=P;
if ~options_.heteroskedastic_filter
DQD=D(~ilagged,:)*Q*transpose(D(~ilagged,:))+C(~ilagged,:)*R*Q*transpose(D(~ilagged,:))+D(~ilagged,:)*Q*transpose(C(~ilagged,:)*R);
DQR=D(~ilagged,:)*Q*transpose(R);
end
for k=1:gend+1
if options_.heteroskedastic_filter
DQD=D(~ilagged,:)*Q(:,:,k)*transpose(D(~ilagged,:))+C(~ilagged,:)*R*Q(:,:,k)*transpose(D(~ilagged,:))+D(~ilagged,:)*Q(:,:,k)*transpose(C(~ilagged,:)*R);
DQR=D(~ilagged,:)*Q(:,:,k)*transpose(R);
end
PP(static_var_list,static_var_list,k)=C(~ilagged,:)*P(:,:,k)*C(~ilagged,:)'+DQD;
PP(static_var_list,oo_.dr.restrict_var_list,k)=C(~ilagged,:)*P(:,:,k)+DQR;
PP(oo_.dr.restrict_var_list,static_var_list,k)=transpose(PP(static_var_list,oo_.dr.restrict_var_list,k));
end
P=PP;
clear PP
end
% reconstruct state_uncertainty
if ~isempty(state_uncertainty)
mm=size(T,1);
ss=length(find(static_var_list));
sstate_uncertainty=zeros(M_.endo_nbr,M_.endo_nbr,gend);
sstate_uncertainty(oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:)=state_uncertainty(1:mm,1:mm,:);
for k=1:gend
sstate_uncertainty(static_var_list,static_var_list,k)=[C(~ilagged,:) D(~ilagged,:)]*state_uncertainty(:,:,k)*[C(~ilagged,:) D(~ilagged,:)]';
tmp = [C(~ilagged,:) D(~ilagged,:)]*state_uncertainty(:,:,k);
sstate_uncertainty(static_var_list,oo_.dr.restrict_var_list,k)=tmp(1:ss,1:mm);
sstate_uncertainty(oo_.dr.restrict_var_list,static_var_list,k)=transpose(sstate_uncertainty(static_var_list,oo_.dr.restrict_var_list,k));
end
state_uncertainty=sstate_uncertainty;
clear sstate_uncertainty
end
% reconstruct PK
if ~isempty(PK)
PP = zeros(options_.nk,M_.endo_nbr,M_.endo_nbr,gend+options_.nk);
PP(:,oo_.dr.restrict_var_list,oo_.dr.restrict_var_list,:) = PK;
if ~options_.heteroskedastic_filter
DQD=D(~ilagged,:)*Q*transpose(D(~ilagged,:))+C(~ilagged,:)*R*Q*transpose(D(~ilagged,:))+D(~ilagged,:)*Q*transpose(C(~ilagged,:)*R);
DQR=D(~ilagged,:)*Q*transpose(R);
for f=1:options_.nk
for k=1:gend
PP(f,static_var_list,static_var_list,k+f)=C(~ilagged,:)*squeeze(PK(f,:,:,k+f))*C(~ilagged,:)'+DQD;
PP(f,static_var_list,oo_.dr.restrict_var_list,k+f)=C(~ilagged,:)*squeeze(PK(f,:,:,k+f))+DQR;
PP(f,oo_.dr.restrict_var_list,static_var_list,k+f)=transpose(squeeze(PP(f,static_var_list,oo_.dr.restrict_var_list,k+f)));
end
end
end
PK=PP;
clear PP
end
end
bayestopt_.mf = bayestopt_.smoother_var_list(bayestopt_.smoother_mf);
@ -446,14 +602,14 @@ end
function a=set_Kalman_smoother_starting_values(a,M_,oo_,options_)
% function a=set_Kalman_smoother_starting_values(a,M_,oo_,options_)
% Sets initial states guess for Kalman filter/smoother based on M_.filter_initial_state
%
% INPUTS
% Sets initial states guess for Kalman filter/smoother based on M_.filter_initial_state
%
% INPUTS
% o a [double] (p*1) vector of states
% o M_ [structure] decribing the model
% o oo_ [structure] storing the results
% o options_ [structure] describing the options
%
%
% OUTPUTS
% o a [double] (p*1) vector of set initial states

View File

@ -412,6 +412,9 @@ options_.recursive_estimation_restart = 0;
options_.MCMC_jumping_covariance='hessian';
options_.use_calibration_initialization = 0;
options_.endo_vars_for_moment_computations_in_estimation=[];
% occbin options
options_.occbin.likelihood.status=false;
options_.occbin.smoother.status=false;
% Run optimizer silently
options_.silent_optimizer = false;

View File

@ -183,9 +183,34 @@ end
%------------------------------------------------------------------------------
% 2. call model setup & reduction program
%------------------------------------------------------------------------------
is_restrict_state_space = true;
if DynareOptions.occbin.likelihood.status
occbin_options = set_occbin_options(DynareOptions, Model);
if occbin_options.opts_simul.restrict_state_space
[T,R,SteadyState,info,Model,DynareResults,TTx,RRx,CCx, T0, R0] = ...
occbin.dynare_resolve(Model,DynareOptions,DynareResults,[],'restrict');
else
is_restrict_state_space = false;
oldoo.restrict_var_list = DynareResults.dr.restrict_var_list;
oldoo.restrict_columns = DynareResults.dr.restrict_columns;
DynareResults.dr.restrict_var_list = BayesInfo.smoother_var_list;
DynareResults.dr.restrict_columns = BayesInfo.smoother_restrict_columns;
% Linearize the model around the deterministic steady state and extract the matrices of the state equation (T and R).
[T,R,SteadyState,info,Model,DynareOptions,DynareResults,TTx,RRx,CCx, T0, R0] = ...
occbin.dynare_resolve(Model,DynareOptions,DynareResults);
% Linearize the model around the deterministic steady state and extract the matrices of the state equation (T and R).
[T,R,SteadyState,info,Model,DynareResults] = dynare_resolve(Model,DynareOptions,DynareResults,'restrict');
DynareResults.dr.restrict_var_list = oldoo.restrict_var_list;
DynareResults.dr.restrict_columns = oldoo.restrict_columns;
end
occbin_.status = true;
occbin_.info= {DynareOptions, DynareResults, Model, occbin_options, TTx, RRx, CCx,T0,R0};
else
% Linearize the model around the deterministic steady state and extract the matrices of the state equation (T and R).
[T,R,SteadyState,info,Model,DynareResults] = dynare_resolve(Model,DynareOptions,DynareResults,'restrict');
occbin_.status = false;
end
% Return, with endogenous penalty when possible, if dynare_resolve issues an error code (defined in resol).
if info(1)
@ -223,8 +248,14 @@ if info(1)
return
end
% Define a vector of indices for the observed variables. Is this really usefull?...
BayesInfo.mf = BayesInfo.mf1;
if is_restrict_state_space
%% Define a vector of indices for the observed variables. Is this really usefull?...
BayesInfo.mf = BayesInfo.mf1;
else
%get location of observed variables and requested smoothed variables in
%decision rules
BayesInfo.mf = BayesInfo.smoother_var_list(BayesInfo.smoother_mf);
end
% Define the constant vector of the measurement equation.
if DynareOptions.noconstant
@ -283,7 +314,16 @@ switch DynareOptions.lik_init
a = zeros(mm,1);
a=set_Kalman_starting_values(a,Model,DynareResults,DynareOptions,BayesInfo);
a_0_given_tm1=T*a; %set state prediction for first Kalman step;
Zflag = 0;
if DynareOptions.occbin.likelihood.status
Z =zeros(length(BayesInfo.mf),size(T,1));
for i = 1:length(BayesInfo.mf)
Z(i,BayesInfo.mf(i))=1;
end
Zflag = 1;
else
Zflag = 0;
end
case 2% Initialization with large numbers on the diagonal of the covariance matrix if the states (for non stationary models).
if kalman_algo ~= 2
% Use standard kalman filter except if the univariate filter is explicitely choosen.
@ -294,7 +334,15 @@ switch DynareOptions.lik_init
a = zeros(mm,1);
a = set_Kalman_starting_values(a,Model,DynareResults,DynareOptions,BayesInfo);
a_0_given_tm1 = T*a; %set state prediction for first Kalman step;
Zflag = 0;
if DynareOptions.occbin.likelihood.status
Z =zeros(length(BayesInfo.mf),size(T,1));
for i = 1:length(BayesInfo.mf)
Z(i,BayesInfo.mf(i))=1;
end
Zflag = 1;
else
Zflag = 0;
end
case 3% Diffuse Kalman filter (Durbin and Koopman)
% Use standard kalman filter except if the univariate filter is explicitely choosen.
if kalman_algo == 0
@ -421,7 +469,15 @@ switch DynareOptions.lik_init
a = zeros(mm,1);
a = set_Kalman_starting_values(a,Model,DynareResults,DynareOptions,BayesInfo);
a_0_given_tm1 = T*a;
Zflag = 0;
if DynareOptions.occbin.likelihood.status
Z =zeros(length(BayesInfo.mf),size(T,1));
for i = 1:length(BayesInfo.mf)
Z(i,BayesInfo.mf(i))=1;
end
Zflag = 1;
else
Zflag = 0;
end
case 5 % Old diffuse Kalman filter only for the non stationary variables
[eigenvect, eigenv] = eig(T);
eigenv = diag(eigenv);
@ -443,7 +499,15 @@ switch DynareOptions.lik_init
a = zeros(mm,1);
a = set_Kalman_starting_values(a,Model,DynareResults,DynareOptions,BayesInfo);
a_0_given_tm1 = T*a;
Zflag = 0;
if DynareOptions.occbin.likelihood.status
Z =zeros(length(BayesInfo.mf),size(T,1));
for i = 1:length(BayesInfo.mf)
Z(i,BayesInfo.mf(i))=1;
end
Zflag = 1;
else
Zflag = 0;
end
otherwise
error('dsge_likelihood:: Unknown initialization approach for the Kalman filter!')
end
@ -604,7 +668,7 @@ end
singularity_has_been_detected = false;
% First test multivariate filter if specified; potentially abort and use univariate filter instead
if ((kalman_algo==1) || (kalman_algo==3))% Multivariate Kalman Filter
if no_missing_data_flag
if no_missing_data_flag && ~DynareOptions.occbin.likelihood.status
if DynareOptions.block
LIK = block_kalman_filter(T,R,Q,H,Pstar,Y,start,Z,kalman_tol,riccati_tol, Model.nz_state_var, Model.n_diag, Model.nobs_non_statevar);
elseif DynareOptions.fast_kalman_filter
@ -643,7 +707,7 @@ if ((kalman_algo==1) || (kalman_algo==3))% Multivariate Kalman Filter
kalman_tol, DynareOptions.riccati_tol, ...
DynareOptions.rescale_prediction_error_covariance, ...
DynareOptions.presample, ...
T,Q,R,H,Z,mm,pp,rr,Zflag,diffuse_periods);
T,Q,R,H,Z,mm,pp,rr,Zflag,diffuse_periods, occbin_);
end
end
if analytic_derivation
@ -895,3 +959,21 @@ if isfield(M_,'filter_initial_state') && ~isempty(M_.filter_initial_state)
end
end
function occbin_options = set_occbin_options(DynareOptions, Model)
% this builds the opts_simul options field needed by occbin.solver
occbin_options.opts_simul = DynareOptions.occbin.simul;
occbin_options.opts_simul.curb_retrench = DynareOptions.occbin.likelihood.curb_retrench;
occbin_options.opts_simul.maxit = DynareOptions.occbin.likelihood.maxit;
occbin_options.opts_simul.periods = DynareOptions.occbin.likelihood.periods;
occbin_options.opts_simul.check_ahead_periods = DynareOptions.occbin.likelihood.check_ahead_periods;
occbin_options.opts_simul.periodic_solution = DynareOptions.occbin.likelihood.periodic_solution;
occbin_options.opts_simul.restrict_state_space = DynareOptions.occbin.likelihood.restrict_state_space;
occbin_options.constraints = Model.occbin.constraint;
occbin_options.opts_simul.full_output = DynareOptions.occbin.likelihood.full_output;
occbin_options.opts_simul.piecewise_only = DynareOptions.occbin.likelihood.piecewise_only;
if ~isempty(DynareOptions.occbin.smoother.init_binding_indicator)
occbin_options.opts_simul.init_binding_indicator = DynareOptions.occbin.likelihood.init_binding_indicator;
occbin_options.opts_simul.init_regime_history=DynareOptions.occbin.likelihood.init_regime_history;
end

View File

@ -41,7 +41,6 @@ else
reset_options_related_to_estimation = false;
end
%store qz_criterium
qz_criterium_old=options_.qz_criterium;
if isnan(options_.first_obs)
@ -102,7 +101,11 @@ if ~options_.dsge_var
error(['Estimation: Unknown filter ' options_.particle.filter_algorithm])
end
else
objective_function = str2func('dsge_likelihood');
if options_.occbin.likelihood.status && options_.occbin.likelihood.inversion_filter
objective_function = str2func('occbin.IVF_posterior');
else
objective_function = str2func('dsge_likelihood');
end
end
else
objective_function = str2func('dsge_var_likelihood');
@ -176,8 +179,22 @@ end
if isequal(options_.mode_compute,0) && isempty(options_.mode_file) && options_.mh_posterior_mode_estimation==0
if options_.order==1 && ~options_.particle.status
if options_.smoother
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,gend,transpose(data),data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_);
[oo_]=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);
if options_.occbin.smoother.status && options_.occbin.smoother.inversion_filter
[~, ~, ~, ~, ~, ~, ~, ~, ~, ~, oo_, atT, innov] = occbin.IVF_posterior(xparam1,dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_);
updated_variables = atT*nan;
measurement_error=[];
ys = oo_.dr.ys;
trend_coeff = zeros(length(options_.varobs_id),1);
bayestopt_.mf = bayestopt_.smoother_var_list(bayestopt_.smoother_mf);
[oo_]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff);
else
if options_.occbin.smoother.status
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = occbin.DSGE_smoother(xparam1,gend,transpose(data),data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_,dataset_,dataset_info);
else
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,gend,transpose(data),data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_);
end
[oo_]=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);
end
if options_.forecast > 0
oo_.forecast = dyn_forecast(var_list_,M_,options_,oo_,'smoother',dataset_info);
end
@ -554,9 +571,22 @@ end
if (~((any(bayestopt_.pshape > 0) && options_.mh_replic) || (any(bayestopt_.pshape> 0) && options_.load_mh_file)) ...
|| ~options_.smoother ) && ~options_.partial_information % to be fixed
%% ML estimation, or posterior mode without Metropolis-Hastings or Metropolis without Bayesian smoothes variables
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_);
[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);
if options_.occbin.smoother.status && options_.occbin.smoother.inversion_filter
[~, ~, ~, ~, ~, ~, ~, ~, ~, ~, oo_, atT, innov] = occbin.IVF_posterior(xparam1,dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_);
updated_variables = atT*nan;
measurement_error=[];
ys = oo_.dr.ys;
trend_coeff = zeros(length(options_.varobs_id),1);
bayestopt_.mf = bayestopt_.smoother_var_list(bayestopt_.smoother_mf);
[oo_, yf]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff);
else
if options_.occbin.smoother.status
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = occbin.DSGE_smoother(xparam1,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_,dataset_,dataset_info);
else
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_);
end
[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);
end
if ~options_.nograph
[nbplt,nr,nc,lr,lc,nstar] = pltorg(M_.exo_nbr);
if ~exist([M_.dname '/graphs'],'dir')

View File

@ -685,3 +685,14 @@ if options_.heteroskedastic_filter
error('Scale and value defined for the same shock in the same period with "heteroskedastic_shocks".')
end
end
if options_.occbin.likelihood.status && options_.occbin.likelihood.inversion_filter
if isempty(options_.occbin.likelihood.IVF_shock_observable_mapping)
options_.occbin.likelihood.IVF_shock_observable_mapping=find(diag(M.Sigma_e)~=0);
else
zero_var_shocks=find(diag(M.Sigma_e)==0);
if any(ismember(options_.occbin.likelihood.IVF_shock_observable_mapping,zero_var_shocks))
error('IVF-filter: an observable is mapped to a zero variance shock.')
end
end
end

View File

@ -73,6 +73,10 @@ if isempty(dataset)
end
options_=select_qz_criterium_value(options_);
llik = -dsge_likelihood(parameters,dataset,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_);
if options_.occbin.likelihood.status && options_.occbin.likelihood.inversion_filter
llik = -occbin.IVF_posterior(parameters,dataset,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_);
else
llik = -dsge_likelihood(parameters,dataset,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_);
end
ldens = evaluate_prior(parameters,M_,estim_params_,oo_,options_,bayestopt_);
llik = llik - ldens;

View File

@ -101,10 +101,27 @@ if ischar(parameters)
end
end
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = ...
DsgeSmoother(parameters,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_);
[oo_]=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);
if options_.occbin.smoother.status
if options_.occbin.smoother.inversion_filter
[~, ~, ~, ~, ~, ~, ~, ~, ~, ~, oo_, atT, innov] = occbin.IVF_posterior(parameters,dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_);
updated_variables = atT*nan;
measurement_error=[];
ys = oo_.dr.ys;
trend_coeff = zeros(length(options_.varobs_id),1);
bayestopt_.mf = bayestopt_.smoother_var_list(bayestopt_.smoother_mf);
else
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = ...
occbin.DSGE_smoother(parameters,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_,dataset_,dataset_info);
end
else
[atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = ...
DsgeSmoother(parameters,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_);
end
if ~(options_.occbin.smoother.status && options_.occbin.smoother.inversion_filter)
[oo_]=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);
else
[oo_]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff);
end
if nargout>4
Smoothed_variables_declaration_order_deviation_form=atT(oo_.dr.inv_order_var(bayestopt_.smoother_var_list),:);
end

View File

@ -170,6 +170,22 @@ switch info(1)
message = 'Particle Filter: Initial covariance of the states is not positive definite. Try a different nonlinear_filter_initialization';
case 202
message = 'Particle Filter: Initial covariance of the states based on simulation resulted in NaN/Inf. Use pruning or try a different nonlinear_filter_initialization';
case 301
message = 'IVF: The likelihood is Inf.';
case 302
message = 'IVF: The likelihood is NaN.';
case 303
message = 'IVF: The residuals are not 0.';
case 304
message = 'IVF: The solver returned with an error code.';
case 305
message = 'IVF: The returned shocks are bigger than 1e8.';
case 310
message = 'Occbin: Simulation terminated with periodic solution (no convergence).';
case 311
message = 'Occbin: Simulation did not converge, increase maxit or check_ahead_periods.';
case 312
message = 'Occbin: Constraint(s) are binding at the end of the sample.';
otherwise
message = 'This case shouldn''t happen. Contact the authors of Dynare';
end

View File

@ -76,6 +76,18 @@ if DynareOptions.order>1
end
end
if (DynareOptions.occbin.likelihood.status && DynareOptions.occbin.likelihood.inversion_filter) || (DynareOptions.occbin.smoother.status && DynareOptions.occbin.smoother.inversion_filter)
err_index= find(diag(Model.Sigma_e)~=0);
if length(err_index)~=length(DynareOptions.varobs)
fprintf('initial_estimation_checks:: The IVF requires exactly as many shocks as observables.')
end
var_index=find(any(isnan(DynareDataset.data)));
if ~isempty(var_index)
fprintf('initial_estimation_checks:: The IVF requires exactly as many shocks as observables.\n')
fprintf('initial_estimation_checks:: The data series %s contains NaN, I am therefore dropping shock %s for these time points.\n',...
DynareOptions.varobs{var_index},Model.exo_names{DynareOptions.occbin.likelihood.IVF_shock_observable_mapping(var_index)})
end
end
if DynareOptions.order>1 || (DynareOptions.order==1 && ~ischar(DynareOptions.mode_compute) && DynareOptions.mode_compute==11)
if DynareOptions.order==1 && DynareOptions.mode_compute==11

View File

@ -1,4 +1,4 @@
function [LIK, lik, a, P] = missing_observations_kalman_filter(data_index,number_of_observations,no_more_missing_observations,Y,start,last,a,P,kalman_tol,riccati_tol,rescale_prediction_error_covariance,presample,T,Q,R,H,Z,mm,pp,rr,Zflag,diffuse_periods)
function [LIK, lik, a, P] = missing_observations_kalman_filter(data_index,number_of_observations,no_more_missing_observations,Y,start,last,a,P,kalman_tol,riccati_tol,rescale_prediction_error_covariance,presample,T,Q,R,H,Z,mm,pp,rr,Zflag,diffuse_periods,occbin_)
% Computes the likelihood of a state space model in the case with missing observations.
%
% INPUTS
@ -91,8 +91,57 @@ notsteady = 1;
F_singular = true;
s = 0;
rescale_prediction_error_covariance0=rescale_prediction_error_covariance;
if occbin_.status
Qt = repmat(Q,[1 1 3]);
a0 = zeros(mm,last);
a1 = zeros(mm,last);
P0 = zeros(mm,mm,last);
P1 = zeros(mm,mm,last);
vv = zeros(pp,last);
options_=occbin_.info{1};
oo_=occbin_.info{2};
M_=occbin_.info{3};
occbin_options=occbin_.info{4};
opts_regime.regime_history = occbin_options.opts_simul.init_regime;
opts_regime.binding_indicator = occbin_options.opts_simul.init_binding_indicator;
first_period_occbin_update = max(t+1,options_.occbin.likelihood.first_period_occbin_update);
if isempty(opts_regime.binding_indicator) && isempty(opts_regime.regime_history)
opts_regime.binding_indicator=zeros(last+2,length(M_.occbin.constraint));
end
[~, ~, ~, regimes_] = occbin.check_regimes([], [], [], opts_regime, M_, oo_, options_);
if length(occbin_.info)>4
TT=occbin_.info{5};
RR=occbin_.info{6};
CC=occbin_.info{7};
T0=occbin_.info{8};
R0=occbin_.info{9};
TT = cat(3,TT,T);
RR = cat(3,RR,R);
CC = cat(2,CC,zeros(mm,1));
if size(TT,3)<(last+1)
TT=repmat(T,1,1,last+1);
RR=repmat(R,1,1,last+1);
CC=repmat(zeros(mm,1),1,last+1);
end
end
else
first_period_occbin_update = inf;
C=0;
end
while notsteady && t<=last
if occbin_.status
a1(:,t) = a;
P1(:,:,t) = P;
C = CC(:,t+1);
R = RR(:,:,t+1);
T = TT(:,:,t+1);
if ~(isqvec)
QQ = R*Q*transpose(R); % Variance of R times the vector of structural innovations.
end
end
s = t-start+1;
d_index = data_index{t};
if isqvec
@ -129,39 +178,79 @@ while notsteady && t<=last
% badly_conditioned_F = true;
end
end
if badly_conditioned_F
if ~all(abs(F(:))<kalman_tol)
% Use univariate filter.
return
if ~occbin_.status || (occbin_.status && (options_.occbin.likelihood.use_updated_regime==0 || t<first_period_occbin_update))
if badly_conditioned_F && (~occbin_.status || (occbin_.status && t<first_period_occbin_update))
if ~all(abs(F(:))<kalman_tol)
% Use univariate filter.
return
else
% Pathological case, discard draw
return
end
else
% Pathological case, discard draw
return
end
else
F_singular = false;
if rescale_prediction_error_covariance
log_dF = log(det(F./(sig*sig')))+2*sum(log(sig));
iF = inv(F./(sig*sig'))./(sig*sig');
rescale_prediction_error_covariance=rescale_prediction_error_covariance0;
else
log_dF = log(det(F));
iF = inv(F);
end
lik(s) = log_dF + transpose(v)*iF*v + length(d_index)*log(2*pi);
if Zflag
K = P*z'*iF;
P = T*(P-K*z*P)*transpose(T)+QQ;
else
K = P(:,z)*iF;
P = T*(P-K*P(z,:))*transpose(T)+QQ;
end
a = T*(a+K*v);
if t>=no_more_missing_observations && ~isqvec
notsteady = max(abs(K(:)-oldK))>riccati_tol;
oldK = K(:);
F_singular = false;
if rescale_prediction_error_covariance
log_dF = log(det(F./(sig*sig')))+2*sum(log(sig));
iF = inv(F./(sig*sig'))./(sig*sig');
rescale_prediction_error_covariance=rescale_prediction_error_covariance0;
else
log_dF = log(det(F));
iF = inv(F);
end
lik(s) = log_dF + transpose(v)*iF*v + length(d_index)*log(2*pi);
if t<first_period_occbin_update
if Zflag
K = P*z'*iF;
if occbin_.status
P0(:,:,t) = (P-K*z*P);
end
P = T*(P-K*z*P)*transpose(T)+QQ;
else
K = P(:,z)*iF;
if occbin_.status
P0(:,:,t) = (P-K*P(z,:));
end
P = T*(P-K*P(z,:))*transpose(T)+QQ;
end
if occbin_.status
a0(:,t) = (a+K*v);
vv(d_index,t) = v;
end
a = T*(a+K*v)+C;
if t>=no_more_missing_observations && ~isqvec && ~occbin_.status
notsteady = max(abs(K(:)-oldK))>riccati_tol;
oldK = K(:);
end
end
end
end
end
if occbin_.status && t>=first_period_occbin_update
if isqvec
Qt = Qvec(:,:,t-1:t+1);
end
occbin_options.opts_simul.waitbar=0;
[ax, a1x, Px, P1x, vx, Tx, Rx, Cx, regimes_(t:t+2), info, M_, likx, etax(t,:)] = occbin.kalman_update_algo_1(a0(:,t-1),a1(:,t-1:t),P0(:,:,t-1),P1(:,:,t-1:t),data_index(t-1:t),Z,vv(:,t-1:t),Y(:,t-1:t),H,Qt,T0,R0,TT(:,:,t-1:t),RR(:,:,t-1:t),CC(:,t-1:t),regimes_(t:t+1),M_,oo_,options_,occbin_options);
if info
return
end
if options_.occbin.likelihood.use_updated_regime
lik(s) = likx;
end
a0(:,t) = ax(:,1);
a1(:,t) = a1x(:,2);
a = ax(:,2);
vv(d_index,t) = vx(d_index,2);
TT(:,:,t:t+1) = Tx;
RR(:,:,t:t+1) = Rx;
CC(:,t:t+1) = Cx;
P0(:,:,t) = Px(:,:,1);
P1(:,:,t) = P1x(:,:,2);
P = Px(:,:,2);
end
t = t+1;
end
@ -182,4 +271,4 @@ if presample>=diffuse_periods
LIK = sum(lik(1+presample-diffuse_periods:end));
else
LIK = sum(lik);
end
end

View File

@ -1 +1,2 @@
list_of_functions = {'discretionary_policy_1', 'dsge_var_likelihood', 'dyn_first_order_solver', 'dyn_waitbar', 'ep_residuals', 'evaluate_likelihood', 'prior_draw_gsa', 'identification_analysis', 'computeDLIK', 'univariate_computeDLIK', 'metropolis_draw', 'flag_implicit_skip_nan', 'moment_function', 'mr_hessian', 'masterParallel', 'auxiliary_initialization', 'auxiliary_particle_filter', 'conditional_filter_proposal', 'conditional_particle_filter', 'gaussian_filter', 'gaussian_filter_bank', 'gaussian_mixture_filter', 'gaussian_mixture_filter_bank', 'Kalman_filter', 'online_auxiliary_filter', 'pruned_state_space_system', 'sequential_importance_particle_filter', 'solve_model_for_online_filter', 'perfect_foresight_simulation', 'prior_draw', 'priordens'};
list_of_functions = {'discretionary_policy_1', 'dsge_var_likelihood', 'dyn_first_order_solver', 'dyn_waitbar', 'ep_residuals', 'evaluate_likelihood', 'prior_draw_gsa', 'identification_analysis', 'computeDLIK', 'univariate_computeDLIK', 'metropolis_draw', 'flag_implicit_skip_nan', 'moment_function', 'mr_hessian', 'masterParallel', 'auxiliary_initialization', 'auxiliary_particle_filter', 'conditional_filter_proposal', 'conditional_particle_filter', 'gaussian_filter', 'gaussian_filter_bank', 'gaussian_mixture_filter', 'gaussian_mixture_filter_bank', 'Kalman_filter', 'online_auxiliary_filter', 'pruned_state_space_system', 'sequential_importance_particle_filter', 'solve_model_for_online_filter', 'perfect_foresight_simulation', 'prior_draw', 'priordens',...
'+occbin/solver.m','+occbin/mkdatap_anticipated_dyn.m','+occbin/mkdatap_anticipated_2constraints_dyn.m','+occbin/match_function.m','+occbin/solve_one_constraint.m','+occbin/solve_two_constraint.m','+occbin/plot/shock_decomposition.m'};

View File

@ -1,5 +1,5 @@
function [alphahat,epsilonhat,etahat,a,P1,aK,PK,decomp,V, aalphahat,eetahat,d] = missing_DiffuseKalmanSmootherH3_Z(a_initial,T,Z,R,Q,H,Pinf1,Pstar1,Y,pp,mm,smpl,data_index,nk,kalman_tol,diffuse_kalman_tol,decomp_flag,state_uncertainty_flag, filter_covariance_flag, smoother_redux)
% function [alphahat,epsilonhat,etahat,a,P1,aK,PK,decomp,V, aalphahat,eetahat,d] = missing_DiffuseKalmanSmootherH3_Z(a_initial,T,Z,R,Q,H,Pinf1,Pstar1,Y,pp,mm,smpl,data_index,nk,kalman_tol,diffuse_kalman_tol,decomp_flag,state_uncertainty_flag, filter_covariance_flag, smoother_redux)
function [alphahat,epsilonhat,etahat,a,P1,aK,PK,decomp,V, aalphahat,eetahat,d,varargout] = missing_DiffuseKalmanSmootherH3_Z(a_initial,T,Z,R,Q,H,Pinf1,Pstar1,Y,pp,mm,smpl,data_index,nk,kalman_tol,diffuse_kalman_tol,decomp_flag,state_uncertainty_flag, filter_covariance_flag, smoother_redux, occbin_)
% function [alphahat,epsilonhat,etahat,a,P1,aK,PK,decomp,V, aalphahat,eetahat,d] = missing_DiffuseKalmanSmootherH3_Z(a_initial,T,Z,R,Q,H,Pinf1,Pstar1,Y,pp,mm,smpl,data_index,nk,kalman_tol,diffuse_kalman_tol,decomp_flag,state_uncertainty_flag, filter_covariance_flag, smoother_redux, occbin_)
% Computes the diffuse kalman smoother in the case of a singular var-cov matrix.
% Univariate treatment of multivariate time series.
%
@ -150,6 +150,71 @@ else
V=[];
end
if ~occbin_.status
isoccbin = 0;
C=0;
TT=[];
RR=[];
CC=[];
else
isoccbin = 1;
Qt = repmat(Q,[1 1 3]);
options_=occbin_.info{1};
oo_=occbin_.info{2};
M_=occbin_.info{3};
occbin_options=occbin_.info{4};
opts_regime = occbin_options.opts_regime;
% first_period_occbin_update = inf;
if isfield(opts_regime,'regime_history') && ~isempty(opts_regime.regime_history)
opts_regime.regime_history=[opts_regime.regime_history(1) opts_regime.regime_history];
else
opts_regime.binding_indicator=zeros(smpl+2,length(M_.occbin.constraint));
end
occbin_options.opts_regime = opts_regime;
[~, ~, ~, regimes_] = occbin.check_regimes([], [], [], opts_regime, M_, oo_, options_);
if length(occbin_.info)>4
if length(occbin_.info)==6 && options_.smoother_redux
TT=repmat(T,1,1,smpl+1);
RR=repmat(R,1,1,smpl+1);
CC=repmat(zeros(mm,1),1,smpl+1);
T0=occbin_.info{5};
R0=occbin_.info{6};
else
TT=occbin_.info{5};
RR=occbin_.info{6};
CC=occbin_.info{7};
% TT = cat(3,TT,T);
% RR = cat(3,RR,R);
% CC = cat(2,CC,zeros(mm,1));
if options_.smoother_redux
my_order_var = oo_.dr.restrict_var_list;
CC = CC(my_order_var,:);
RR = RR(my_order_var,:,:);
TT = TT(my_order_var,my_order_var,:);
T0=occbin_.info{8};
R0=occbin_.info{9};
end
if size(TT,3)<(smpl+1)
TT=repmat(T,1,1,smpl+1);
RR=repmat(R,1,1,smpl+1);
CC=repmat(zeros(mm,1),1,smpl+1);
end
end
else
TT=repmat(T,1,1,smpl+1);
RR=repmat(R,1,1,smpl+1);
CC=repmat(zeros(mm,1),1,smpl+1);
end
if ~smoother_redux
T0=T;
R0=R;
end
end
t = 0;
icc=0;
if ~isempty(Pinf(:,:,1))
@ -182,8 +247,8 @@ while newRank && t < smpl
elseif Fstar(i,t) > kalman_tol
a(:,t) = a(:,t) + Kstar(:,i,t)*v(i,t)/Fstar(i,t); % KD (2000), eq. (17)
Pstar(:,:,t) = Pstar(:,:,t) - Kstar(:,i,t)*Kstar(:,i,t)'/Fstar(i,t); % KD (2000), eq. (17)
% Pinf is passed through unaltered, see eq. (17) of
% Koopman/Durbin (2000)
% Pinf is passed through unaltered, see eq. (17) of
% Koopman/Durbin (2000)
else
% do nothing as a_{t,i+1}=a_{t,i} and P_{t,i+1}=P_{t,i}, see
% p. 157, DK (2012)
@ -198,6 +263,10 @@ while newRank && t < smpl
else
oldRank = 0;
end
if isoccbin,
TT(:,:,t+1)= T;
RR(:,:,t+1)= R;
end
a1(:,t+1) = T*a(:,t);
aK(1,:,t+1) = a1(:,t+1);
for jnk=2:nk
@ -221,7 +290,19 @@ while newRank && t < smpl
end
end
if isoccbin
first_period_occbin_update = max(t+2,occbin_options.first_period_occbin_update);
if occbin_options.opts_regime.waitbar
hh = dyn_waitbar(0,'Occbin: Piecewise Kalman Filter');
set(hh,'Name','Occbin: Piecewise Kalman Filter.');
waitbar_indicator=1;
else
waitbar_indicator=0;
end
else
first_period_occbin_update = inf;
waitbar_indicator=0;
end
d = t;
P(:,:,d+1) = Pstar(:,:,d+1);
Fstar = Fstar(:,1:d);
@ -237,63 +318,166 @@ while notsteady && t<smpl
a(:,t) = a1(:,t);
P1(:,:,t) = P(:,:,t);
di = data_index{t}';
for i=di
Zi = Z(i,:);
v(i,t) = Y(i,t) - Zi*a(:,t); % nu_{t,i} in 6.13 in DK (2012)
Fi(i,t) = Zi*P(:,:,t)*Zi' + H(i); % F_{t,i} in 6.13 in DK (2012), relies on H being diagonal
Ki(:,i,t) = P(:,:,t)*Zi'; % K_{t,i}*F_(i,t) in 6.13 in DK (2012)
if Fi(i,t) > kalman_tol
a(:,t) = a(:,t) + Ki(:,i,t)*v(i,t)/Fi(i,t); %filtering according to (6.13) in DK (2012)
P(:,:,t) = P(:,:,t) - Ki(:,i,t)*Ki(:,i,t)'/Fi(i,t); %filtering according to (6.13) in DK (2012)
if t>=first_period_occbin_update
if waitbar_indicator
dyn_waitbar(t/smpl, hh, sprintf('Period %u of %u', t,smpl));
end
if isqvec
Qt = Qvec(:,:,t-1:t+1);
end
occbin_options.opts_regime.waitbar=0;
[ax, a1x, Px, P1x, vx, Fix, Kix, Tx, Rx, Cx, tmp, error_flag, M_, aha, etaha,TTx,RRx,CCx] = occbin.kalman_update_algo_3(a(:,t-1),a1(:,t-1:t),P(:,:,t-1),P1(:,:,t-1:t),data_index(t-1:t),Z,v(:,t-1:t),Fi(:,t-1),Ki(:,:,t-1),Y(:,t-1:t),H,Qt,T0,R0,TT(:,:,t-1:t),RR(:,:,t-1:t),CC(:,t-1:t),regimes_(t:t+1),M_,oo_,options_,occbin_options,kalman_tol,nk);
if ~error_flag
regimes_(t:t+2)=tmp;
else
% do nothing as a_{t,i+1}=a_{t,i} and P_{t,i+1}=P_{t,i}, see
% p. 157, DK (2012)
varargout{1} = [];
varargout{2} = [];
varargout{3} = [];
varargout{4} = [];
return
end
end
if smoother_redux
ri=zeros(mm,1);
for st=t:-1:max(d+1,t-1)
di = flipud(data_index{st})';
for i = di
if Fi(i,st) > kalman_tol
Li = eye(mm)-Ki(:,i,st)*Z(i,:)/Fi(i,st);
ri = Z(i,:)'/Fi(i,st)*v(i,st)+Li'*ri; % DK (2012), 6.15, equation for r_{t,i-1}
end
end
if st==t-1
aalphahat(:,st) = a1(:,st) + P1(:,:,st)*ri;
if smoother_redux
aalphahat(:,t-1) = aha(:,1);
eetahat(:,t) = etaha(:,2);
end
a(:,t) = ax(:,1);
a1(:,t) = a1x(:,2);
a1(:,t+1) = ax(:,2);
v(di,t) = vx(di,2);
Fi(di,t) = Fix(di,2);
Ki(:,di,t) = Kix(:,di,2);
TT(:,:,t:t+1) = Tx(:,:,1:2);
RR(:,:,t:t+1) = Rx(:,:,1:2);
CC(:,t:t+1) = Cx(:,1:2);
TTT(:,:,t)=TTx;
RRR(:,:,t)=RRx;
CCC(:,t)=CCx;
P(:,:,t) = Px(:,:,1);
P1(:,:,t) = P1x(:,:,2);
P(:,:,t+1) = Px(:,:,2);
for jnk=1:nk
PK(jnk,:,:,t+jnk) = Px(:,:,1+jnk);
aK(jnk,:,t+jnk) = ax(:,1+jnk);
end
else
for i=di
Zi = Z(i,:);
v(i,t) = Y(i,t) - Zi*a(:,t); % nu_{t,i} in 6.13 in DK (2012)
Fi(i,t) = Zi*P(:,:,t)*Zi' + H(i); % F_{t,i} in 6.13 in DK (2012), relies on H being diagonal
Ki(:,i,t) = P(:,:,t)*Zi'; % K_{t,i}*F_(i,t) in 6.13 in DK (2012)
if Fi(i,t) > kalman_tol
a(:,t) = a(:,t) + Ki(:,i,t)*v(i,t)/Fi(i,t); %filtering according to (6.13) in DK (2012)
P(:,:,t) = P(:,:,t) - Ki(:,i,t)*Ki(:,i,t)'/Fi(i,t); %filtering according to (6.13) in DK (2012)
else
eetahat(:,st) = QRt*ri;
% do nothing as a_{t,i+1}=a_{t,i} and P_{t,i+1}=P_{t,i}, see
% p. 157, DK (2012)
end
ri = T'*ri; % KD (2003), eq. (23), equation for r_{t-1,p_{t-1}}
end
end
if isqvec
QQ = R*Qvec(:,:,t+1)*transpose(R);
end
a1(:,t+1) = T*a(:,t); %transition according to (6.14) in DK (2012)
P(:,:,t+1) = T*P(:,:,t)*T' + QQ; %transition according to (6.14) in DK (2012)
if filter_covariance_flag
Pf = P(:,:,t+1);
end
aK(1,:,t+1) = a1(:,t+1);
for jnk=1:nk
if isqvec
QQ = R*Qvec(:,:,t)*transpose(R);
end
if smoother_redux
ri=zeros(mm,1);
for st=t:-1:max(d+1,t-1)
di = flipud(data_index{st})';
for i = di
if Fi(i,st) > kalman_tol
Li = eye(mm)-Ki(:,i,st)*Z(i,:)/Fi(i,st);
ri = Z(i,:)'/Fi(i,st)*v(i,st)+Li'*ri; % DK (2012), 6.15, equation for r_{t,i-1}
end
end
if st==t-1
aalphahat(:,st) = a1(:,st) + P1(:,:,st)*ri;
else
if isoccbin
if isqvec
QRt = Qvec(:,:,st)*transpose(RR(:,:,st));
else
QRt = Q*transpose(RR(:,:,st));
end
T = TT(:,:,st);
else
if isqvec
QRt = Qvec(:,:,st)*transpose(R);
end
end
eetahat(:,st) = QRt*ri;
end
ri = T'*ri; % KD (2003), eq. (23), equation for r_{t-1,p_{t-1}}
end
end
if isoccbin
if isqvec
QQ = RR(:,:,t+1)*Qvec(:,:,t+1)*transpose(RR(:,:,t+1));
else
QQ = RR(:,:,t+1)*Q*transpose(RR(:,:,t+1));
end
T = TT(:,:,t+1);
C = CC(:,t+1);
else
if isqvec
QQ = R*Qvec(:,:,t+1)*transpose(R);
end
end
a1(:,t+1) = T*a(:,t)+C; %transition according to (6.14) in DK (2012)
P(:,:,t+1) = T*P(:,:,t)*T' + QQ; %transition according to (6.14) in DK (2012)
if filter_covariance_flag
if jnk>1
Pf = T*Pf*T' + QQ;
end
PK(jnk,:,:,t+jnk) = Pf;
Pf = P(:,:,t+1);
end
if jnk>1
aK(jnk,:,t+jnk) = T*dynare_squeeze(aK(jnk-1,:,t+jnk-1));
aK(1,:,t+1) = a1(:,t+1);
if ~isempty(nk) && nk>1 && isoccbin
opts_simul = occbin_options.opts_regime;
opts_simul.SHOCKS = zeros(nk,M_.exo_nbr);
if smoother_redux
tmp=zeros(M_.endo_nbr,1);
tmp(oo_.dr.restrict_var_list)=a(:,t);
opts_simul.endo_init = tmp(oo_.dr.inv_order_var);
else
opts_simul.endo_init = a(oo_.dr.inv_order_var,t);
end
opts_simul.init_regime = []; %regimes_(t);
options_.occbin.simul=opts_simul;
[~, out, ss] = occbin.solver(M_,oo_,options_);
end
for jnk=1:nk
if filter_covariance_flag
if jnk>1
Pf = T*Pf*T' + QQ;
end
PK(jnk,:,:,t+jnk) = Pf;
end
if isoccbin
if smoother_redux
aK(jnk,:,t+jnk) = out.zpiece(jnk,oo_.dr.order_var(oo_.dr.restrict_var_list));
else
aK(jnk,oo_.dr.inv_order_var,t+jnk) = out.zpiece(jnk,:);
end
elseif jnk>1
aK(jnk,:,t+jnk) = T*dynare_squeeze(aK(jnk-1,:,t+jnk-1));
end
end
end
% notsteady = ~(max(max(abs(P(:,:,t+1)-P(:,:,t))))<kalman_tol);
end
if waitbar_indicator
dyn_waitbar_close(hh);
end
P1(:,:,t+1) = P(:,:,t+1);
P1(:,:,t+1)=P(:,:,t+1);
if ~isinf(first_period_occbin_update) && isoccbin
regimes_ = regimes_(2:smpl+1);
else
regimes_ = struct();
TTT=TT;
RRR=RR;
CCC=CC;
% return
end
varargout{1} = regimes_;
varargout{2} = TTT;
varargout{3} = RRR;
varargout{4} = CCC;
% $$$ P_s=tril(P(:,:,t))+tril(P(:,:,t),-1)';
% $$$ P1_s=tril(P1(:,:,t))+tril(P1(:,:,t),-1)';
% $$$ Fi_s = Fi(:,t);
@ -346,8 +530,18 @@ while t > d+1
end
r(:,t) = ri; % DK (2012), below 6.15, r_{t-1}=r_{t,0}
alphahat(:,t) = a1(:,t) + P1(:,:,t)*r(:,t);
if isqvec
QRt = Qvec(:,:,t)*transpose(R);
if isoccbin
if isqvec
QRt = Qvec(:,:,t)*transpose(RR(:,:,t));
else
QRt = Q*transpose(RR(:,:,t));
end
R = RR(:,:,t);
T = TT(:,:,t);
else
if isqvec
QRt = Qvec(:,:,t)*transpose(R);
end
end
etahat(:,t) = QRt*r(:,t);
ri = T'*ri; % KD (2003), eq. (23), equation for r_{t-1,p_{t-1}}
@ -383,8 +577,8 @@ if d
Linf = eye(mm) - Kinf(:,i,t)*Z(i,:)/Finf(i,t);
L0 = (Kinf(:,i,t)*(Fstar(i,t)/Finf(i,t))-Kstar(:,i,t))*Z(i,:)/Finf(i,t);
r1(:,t) = Z(i,:)'*v(i,t)/Finf(i,t) + ...
L0'*r0(:,t) + ...
Linf'*r1(:,t); % KD (2000), eq. (25) for r_1
L0'*r0(:,t) + ...
Linf'*r1(:,t); % KD (2000), eq. (25) for r_1
r0(:,t) = Linf'*r0(:,t); % KD (2000), eq. (25) for r_0
if state_uncertainty_flag
N_2(:,:,t)=Z(i,:)'/Finf(i,t)^2*Z(i,:)*Fstar(i,t) ...
@ -406,8 +600,18 @@ if d
end
alphahat(:,t) = a1(:,t) + Pstar1(:,:,t)*r0(:,t) + Pinf1(:,:,t)*r1(:,t); % KD (2000), eq. (26)
r(:,t) = r0(:,t);
if isqvec
QRt = Qvec(:,:,t)*transpose(R);
if isoccbin
if isqvec
QRt = Qvec(:,:,t)*transpose(RR(:,:,t));
else
QRt = Q*transpose(RR(:,:,t));
end
R = RR(:,:,t);
T = TT(:,:,t);
else
if isqvec
QRt = Qvec(:,:,t)*transpose(R);
end
end
etahat(:,t) = QRt*r(:,t); % KD (2000), eq. (27)
if state_uncertainty_flag
@ -439,6 +643,8 @@ if d
end
end
end
else
alphahat0 = 0*a1(:,1) + P1(:,:,1)*ri;
end
if decomp_flag
@ -452,10 +658,20 @@ if decomp_flag
ri_d = Z(i,:)'/Fi(i,t)*v(i,t)+ri_d-Ki(:,i,t)'*ri_d/Fi(i,t)*Z(i,:)';
end
end
% calculate eta_tm1t
if isqvec
QRt = Qvec(:,:,t)*transpose(R);
if isoccbin
if isqvec
QRt = Qvec(:,:,t)*transpose(RR(:,:,t));
else
QRt = Q*transpose(RR(:,:,t));
end
R = RR(:,:,t);
T = TT(:,:,t);
else
if isqvec
QRt = Qvec(:,:,t)*transpose(R);
end
end
eta_tm1t = QRt*ri_d;
% calculate decomposition

View File

@ -223,8 +223,13 @@ for b=fpar:B
fprintf('\nprior_posterior_statistics: One of the draws failed with the error:\n%s\n',message)
fprintf('prior_posterior_statistics: This should not happen. Please contact the developers.\n',message)
end
[alphahat,etahat,epsilonhat,alphatilde,SteadyState,trend_coeff,aK,~,~,P,~,~,trend_addition,state_uncertainty,M_,oo_,bayestopt_] = ...
DsgeSmoother(deep,gend,Y,data_index,missing_value,M_,oo_,opts_local,bayestopt_,estim_params_);
if options_.occbin.smoother.status
[alphahat,etahat,epsilonhat,alphatilde,SteadyState,trend_coeff,aK,~,~,P,~,~,trend_addition,state_uncertainty,M_,oo_,bayestopt_] = ...
occbin.DSGE_smoother(deep,gend,Y,data_index,missing_value,M_,oo_,opts_local,bayestopt_,estim_params_);
else
[alphahat,etahat,epsilonhat,alphatilde,SteadyState,trend_coeff,aK,~,~,P,~,~,trend_addition,state_uncertainty,M_,oo_,bayestopt_] = ...
DsgeSmoother(deep,gend,Y,data_index,missing_value,M_,oo_,opts_local,bayestopt_,estim_params_);
end
stock_trend_coeff(options_.varobs_id,irun(9))=trend_coeff;
stock_smoothed_trend(IdObs,:,irun(11))=trend_addition;

View File

@ -72,6 +72,20 @@ function [oo_, yf]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,da
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
%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
gend=dataset_.nobs;
if nargin<16
Trend=zeros(options_.number_of_observed_variables,gend);

View File

@ -1,20 +1,20 @@
function [i_var, nvar, index_uniques] = varlist_indices(sublist, list)
function [i_var, nvar, index_unique_present] = varlist_indices(sublist, list, nocheck_dummy)
% returns the indices of a list of endogenous variables
% returns the indices of a list of variables
%
% INPUT
% sublist [cell of char arrays] sublist of variables
% list [cell of char arrays] list of variables
%
% OUTPUT
% i_var variable indices in M_.endo_names
% nvar number of variables in varlist
% index_uniques indices of unique elements in varlist
% i_var variable indices in list
% nvar number of unique variables contained in list
% index_uniques indices of unique and present elements in sublist
%
% SPECIAL REQUIREMENTS
% none
% Copyright (C) 2010-2018 Dynare Team
% Copyright (C) 2010-2021 Dynare Team
%
% This file is part of Dynare.
%
@ -31,6 +31,9 @@ function [i_var, nvar, index_uniques] = varlist_indices(sublist, list)
% 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<3
nocheck_dummy=0;
end
if isempty(sublist)
check = [];
i_var = [];
@ -38,27 +41,34 @@ else
[check, i_var] = ismember(sublist, list);
end
indices_not_present=[];
if ~all(check)
k = find(~check);
str = 'The following symbols are not endogenous variables:';
for ii = 1:length(k)
str = sprintf('%s %s', str, sublist{k(ii)});
k_not_present = find(~check);
if ~nocheck_dummy
str = 'The following symbols are not endogenous variables:';
for ii = 1:length(k_not_present)
str = sprintf('%s %s', str, sublist{k_not_present(ii)});
end
error(str)
else
indices_not_present=find(i_var==0);
end
error(str)
end
nvar = length(i_var);
[~, index_uniques, ~] = unique(i_var, 'first');
index_uniques = sort(index_uniques);
i_var_unique = i_var(index_uniques);
nvar_present = length(i_var(check));
[~, index_unique, ~] = unique(i_var, 'first');
index_unique_present = index_unique(~ismember(index_unique,indices_not_present));
index_unique_present = sort(index_unique_present);
i_var_unique_present = i_var(index_unique_present);
if length(i_var_unique)~=nvar
k = find(~ismember(1:nvar,index_uniques));
if length(i_var_unique_present)~=nvar_present
k = find(~ismember((1:length(i_var))',index_unique_present) & i_var~=0);
str = 'The following symbols are specified twice in the variable list and are considered only once:';
for ii = 1:length(k)
str = sprintf('%s %s', str, sublist{k(ii)});
str = sprintf('%s %s', str, sublist{i_var(k(ii))});
end
warning('%s\n', str)
i_var = i_var_unique;
nvar = length(i_var);
end
end
i_var = i_var_unique_present;
nvar = length(i_var);

@ -1 +1 @@
Subproject commit 6b9d94405c44fe2533a2d8bc377173a2a70f3a54
Subproject commit 08ac455fcddd032058738669ed6a84fda9c76e05

View File

@ -64,7 +64,8 @@
"write_latex_steady_state_model" "steady" "check" "simul" "stoch_simul"
"var_model" "trend_component_model" "var_expectation_model" "pac_model"
"dsample" "Sigma_e" "planner_objective" "ramsey_model" "ramsey_policy"
"evaluate_planner_objective"
"evaluate_planner_objective" "occbin_setup" "occbin_solver"
"occbin_write_regimes" "occbin_graph"
"discretionary_policy" "identification" "bvar_density" "bvar_forecast"
"dynare_sensitivity" "initval_file" "histval_file" "forecast"
"shock_decomposition" "realtime_shock_decomposition"
@ -84,7 +85,8 @@
;; Keywords that may appear in blocks, and that begin a statement which will be
;; closed by a semicolon
(defvar dynare-statements-like
'("stderr" "values" "scales" "restriction" "exclusion" "upper_cholesky" "lower_cholesky")
'("stderr" "values" "scales" "restriction" "exclusion" "upper_cholesky" "lower_cholesky"
"bind" "relax" "error_bind" "error_relax")
"Dynare statements-like keywords.")
;; Those keywords that makes the lexer enter the DYNARE_BLOCK start condition
@ -99,7 +101,7 @@
"observation_trends" "deterministic_trends" "optim_weights" "homotopy_setup"
"conditional_forecast_paths" "svar_identification" "moment_calibration"
"irf_calibration" "ramsey_constraints" "generate_irfs"
"matched_moments" "verbatim")
"matched_moments" "occbin_constraints" "verbatim")
"Dynare block keywords."))
;; Mathematical functions and operators used in model equations (see "hand_side" in Bison file)

2
tests/.gitignore vendored
View File

@ -120,6 +120,8 @@ wsOct
!/ms-sbvar/data.m
!/objectives/sgu_ex1.mat
!/observation_trends_and_prefiltering/generate_trend_stationary_AR1.m
!/occbin/filter/dataobsfile.mat
!/occbin/filter/NKM_mh_mode_saved.mat
!/optimal_policy/Ramsey/find_c.m
!/optimal_policy/Ramsey/oo_ramsey_policy_initval.mat
!/optimizers/optimizer_function_wrapper.m

View File

@ -1,5 +1,11 @@
MODFILES = \
walsh.mod \
occbin/model_irrcap_twoconstraints/dynrbc.mod \
occbin/model_irrcap_twoconstraints/dynrbc_0_std_shocks.mod \
occbin/model_borrcon/borrcon.mod \
occbin/model_borrcon/borrcon_0_std_shocks.mod \
occbin/filter/NKM.mod \
occbin/filter/NKM_0_std_shocks.mod \
optimizers/fs2000_6.mod \
moments/example1_hp_test.mod \
moments/fs2000_post_moments.mod \
@ -594,6 +600,7 @@ XFAIL_MODFILES = ramst_xfail.mod \
identification/LindeTrabandt/LindeTrabandt2019_xfail.mod \
steady_state/Linear_steady_state_xfail.mod \
optimal_policy/Ramsey/ramsey_histval_xfail.mod \
occbin/model_irrcap_twoconstraints/dynrbc_token_xfail.mod \
particle/first_spec_xfail_0.mod \
particle/first_spec_xfail_1.mod \
kalman_initial_state/fs2000_kalman_initial_xfail.mod \
@ -617,6 +624,12 @@ optimal_policy/neo_growth_ramsey_foresight.o.trs: optimal_policy/neo_growth_fore
optimal_policy/neo_growth_ramsey_k_order.m.trs: optimal_policy/neo_growth_k_order.m.trs
optimal_policy/neo_growth_ramsey_k_order.o.trs: optimal_policy/neo_growth_k_order.o.trs
occbin/model_irrcap_twoconstraints/dynrbc_0_std_shocks.m.trs: occbin/model_irrcap_twoconstraints/dynrbc.m.trs
occbin/model_irrcap_twoconstraints/dynrbc_0_std_shocks.o.trs: occbin/model_irrcap_twoconstraints/dynrbc.o.trs
occbin/model_borrcon/borrcon_0_std_shocks.m.trs: occbin/model_borrcon/borrcon.m.trs
occbin/model_borrcon/borrcon_0_std_shocks.o.trs: occbin/model_borrcon/borrcon.o.trs
example1_use_dll.m.trs: example1.m.trs
example1_use_dll.o.trs: example1.o.trs
@ -1245,6 +1258,10 @@ EXTRA_DIST = \
observation_trends_and_prefiltering/Trend_model_calib_no_prefilter_common.inc \
observation_trends_and_prefiltering/Trend_load_data_common.inc \
observation_trends_and_prefiltering/Trend_no_prefilter_conditional_forecast.inc \
occbin/model_borrcon/borrcon_common.inc \
occbin/model_irrcap_twoconstraints/dynrbc_common.inc \
occbin/filter/dataobsfile.mat \
occbin/filter/NKM_mh_mode_saved.mat \
optimal_policy/neo_growth_common.inc \
optimal_policy/neo_growth_ramsey_common.inc \
optimal_policy/Ramsey/oo_ramsey_policy_initval.mat \
@ -1479,6 +1496,8 @@ clean-local:
kalman/likelihood_from_dynare/fs_ns_dat_simul_uncorr_ME.m \
kalman/likelihood_from_dynare/fs_ns_dat_simul_uncorr_ME_missing.m
rm -f occbin/filter/dataobsfile2.mat
find . -name "*.tex" -type f -delete
find . -name "*.aux" -type f -delete
find . -name "*.log" -type f -delete

342
tests/occbin/filter/NKM.mod Normal file
View File

@ -0,0 +1,342 @@
//Tests Occbin estimation with IVF and PKF with 1 constraints
// this file implements the model in:
// Atkinson, T., A. W. Richter, and N. A. Throckmorton (2019).
// The zero lower bound andestimation accuracy.Journal of Monetary Economics
// original codes provided by Alexander Richter
// adapted for dynare implementation
// ------------------------- Settings -----------------------------------------//
@#ifndef small_model
@#define small_model = 0
@#endif
// if ~exist('run_ivf','var')
run_ivf=0;
// end
// ----------------- Defintions -----------------------------------------//
var
c //1 Consumption
n //2 Labor
y //5 Output
yf //6 Final goods
yg //11 Output growth gap
w //12 Real wage rate
wf //13 Flexible real wage
pigap //15 Inflation rate -> pi(t)/pibar = pigap
inom //16 Nominal interest rate
inomnot //17 Notional interest rate
mc //19 Real marginal cost
lam //20 Inverse marginal utility of wealth
g //21 Growth shock
s //22 Risk premium shock
mp //23 Monetary policy shock
pi //24 Observed inflation
@#if !(small_model)
x //3 Investment
k //4 Capital
u //7 Utilization cost
ups //8 Utilization choice
wg //9 Real wage growth gap
xg //10 Investment growth
rk //14 Real rental rate
q //18 Tobins q
@#endif
;
varexo
epsg // Productivity growth shock
epsi // Notional interest rate shock
epss // Risk premium shock
;
parameters
// Calibrated Parameters
beta // Discount factor
chi // Labor disutility scale
thetap // Elasticity of subs. between intermediate goods
thetaw // Elasticity of subs. between labor types
nbar // Steady state labor
eta // Inverse frish elasticity of labor supply
delta // Depreciation
alpha // Capital share
gbar // Mean growth rate
pibar // Inflation target
inombar // Steady gross nom interest rate
inomlb // Effective lower bound on gross nominal interest rate
sbar // Average risk premium
// Parameters for DGP and Estimated parameters
varphip // Rotemberg price adjustment cost
varphiw // Rotemberg wage adjustment cost
h // Habit persistence
rhos // Persistence
rhoi // Persistence
sigz // Standard deviation technology
sigs // Standard deviation risk premia
sigi // Standard deviation mon pol
phipi // Inflation responsiveness
phiy // Output responsiveness
nu // Investment adjustment cost
sigups // Utilization
// Switching parameters
zlb
;
// ---------------- Calibration -----------------------------------------//
beta = 0.9949; // Discount factor
thetap = 6; // Elasticity of subs. between intermediate goods
thetaw = 6; // Elasticity of subs. between labor types
nbar = 1/3; // Steady state labor
eta = 1/3; // Inverse frish elasticity of labor supply
delta = 0.025; // Depreciation
alpha = 0.35; // Capital share
gbar = 1.0034; // Mean growth rate
pibar = 1.0053; // Inflation target
sbar = 1.0058; // Average risk premium
rkbar = 1/beta;
varphiw = 100; // Rotemberg wage adjustment cost
nu = 4; // Investment adjustment cost
sigups = 5; // Utilization
varphip = 100; // Rotemberg price adjustment cost
h = 0.80; // Habit persistence
rhos = 0.80; // Persistence
rhoi = 0.80; // Persistence
sigz = 0.005; // Standard deviation
sigs = 0.005; // Standard deviation
sigi = 0.002; // Standard deviation
phipi = 2.0; // Inflation responsiveness
phiy = 0.5; // Output responsiveness
zlb = 0 ; // ZLB dummy
inomlb = 1 ; // Inom LB
// ---------------- Model -----------------------------------------------//
model;
@#if !(small_model)
[name = 'HH FOC utilization (1)']
rk = steady_state(rk)*exp(sigups*(ups-1));
[name = 'Utilization definition (3)']
u = steady_state(rk)*(exp(sigups*(ups-1))-1)/sigups;
[name = 'Firm FOC capital (4)']
rk = mc*alpha*g*yf/(ups*k(-1));
[name = 'HH FOC capital (17)']
q = beta*(lam/lam(+1))*(rk(+1)*ups(+1)-u(+1)+(1-delta)*q(+1))/g(+1);
[name = 'HH FOC investment (18)']
1 = q*(1-nu*(xg-1)^2/2-nu*(xg-1)*xg)+beta*nu*gbar*q(+1)*(lam/lam(+1))*xg(+1)^2*(xg(+1)-1)/g(+1);
[name = 'Wage Phillips Curve (20)']
varphiw*(wg-1)*wg = ((1-thetaw)*w+thetaw*wf)*n/yf + beta*varphiw*(lam/lam(+1))*(wg(+1)-1)*wg(+1)*(yf(+1)/yf) ;
[name = 'Real wage growth gap (6)']
wg = pigap*g*w/(gbar*w(-1));
[name = 'Law of motion for capital (15)']
k = (1-delta)*(k(-1)/g)+x*(1-nu*(xg-1)^2/2);
[name = 'Investment growth gap (14)']
xg = g*x/(gbar*x(-1));
@#endif
@#if small_model
[name = 'Production function (2)']
yf = n;
[name = 'Firm FOC labor (5)']
w = mc*yf/n;
[name = 'Output definition (7)']
y = (1-varphip*(pigap-1)^2/2)*yf;
[name = 'ARC (13)']
c = y;
[name = 'Household labpur supply equals flex wage']
w = wf;
@#else
[name = 'Production function (2)']
yf = (ups*k(-1)/g)^alpha*n^(1-alpha);
[name = 'Firm FOC labor (5)']
w = (1-alpha)*mc*yf/n;
[name = 'Output definition (7)']
y = (1-varphip*(pigap-1)^2/2-varphiw*(wg-1)^2/2)*yf - u*k(-1)/g;
[name = 'ARC (13)']
x = y-c;
@#endif
[name = 'Output growth gap (8)']
yg = g*y/(gbar*y(-1));
[name = 'Notional Interest Rate (9)']
inomnot = inomnot(-1)^rhoi*(inombar*pigap^phipi*yg^phiy)^(1-rhoi)*exp(mp);
[name = 'Nominal Interest Rate (10)']
inom = (inomnot*(1-zlb)+zlb*inomlb);
[name = 'Inverse MUC (11)']
lam = c-h*c(-1)/g;
[name = 'Flexible real wage definition (12)']
wf = chi*n^eta*lam;
[name = 'HH FOC bond (16)']
1 = beta*(lam/lam(+1))*s*inom/(g(+1)*pibar*pigap(+1));
[name = 'Price Phillips Curve (19)']
varphip*(pigap-1)*pigap = 1-thetap+thetap*mc+beta*varphip*(lam/lam(+1))*(pigap(+1)-1)*pigap(+1)*(yf(+1)/yf);
[name = 'Stochastic productivity growth (21)']
g = gbar+ sigz*epsg;
[name = 'Risk premium shock (22)']
s = (1-rhos)*sbar + rhos*s(-1)+sigs*epss ;
[name = 'Notional interest rate shock (23)']
mp = sigi*epsi;
[name = 'Observed inflation (24)']
pi = pigap*pibar;
end;
occbin_constraints;
name 'zlb'; bind inom+inombar <= inomlb; relax inom+inombar > inomlb;
end;
// ---------------- Steady state -----------------------------------------//
steady_state_model;
mp = 0;
xg = 1;
s = sbar;
n = nbar;
ups =1;
u =0;
q =1;
g = gbar;
yg = 1;
pigap = 1;
wg =1;
pi = pigap*pibar;
// FOC bond
inom = gbar*pibar/(beta*s);
inomnot = inom;
inombar = inom;
// Firm pricing
mc = (thetap-1)/thetap;
// FOC capital
rk = gbar/beta+delta-1;
// Marginal cost definition
@#if small_model
alpha = 0;
thetaw=1;
@#endif
w = (mc*(1-alpha)^(1-alpha)*alpha^alpha/rk^alpha)^(1/(1-alpha));
@#if small_model
wf = w;
@#else
wf = (thetaw-1)*w/thetaw;
@#endif
// Consolidated FOC firm
k = w*n*gbar*alpha/(rk*(1-alpha));
// Law of motion for capital
x = (1-(1-delta)/gbar)*k;
// Production function
yf = (k/gbar)^alpha*n^(1-alpha);
// Real GDP
y = yf;
// Aggregate resouce constraint
c = y-x;
// FOC labor
lam = (1-h/gbar)*c;
chi = wf/(n^eta*lam);
// try log observables
end;
// ---------------- Checks -----------------------------------------//
steady;
check;
// ---------------- Simulation -----------------------------------------//
shocks;
var epsi = 1;
var epss = 1;
var epsg = 1;
end;
steady;
check;
// ---------------- Estimation -----------------------------------------//
varobs yg inom pi;
estimated_params;
// PARAM NAME, INITVAL, LB, UB, PRIOR_SHAPE, PRIOR_P1, PRIOR_P2, PRIOR_P3, PRIOR_P4, JSCALE
// PRIOR_SHAPE: BETA_PDF, GAMMA_PDF, NORMAL_PDF, INV_GAMMA_PDF
varphip,,0,inf,NORMAL_PDF,100,25;
phipi,,,,NORMAL_PDF,2,0.25;
phiy,,0,inf,NORMAL_PDF,0.5,0.25;
h,,,,BETA_PDF,0.8,0.1;
rhos,,,,BETA_PDF,0.8,0.1;
rhoi,,,,BETA_PDF,0.8,0.1;
sigz,,,,INV_GAMMA_PDF,0.005,0.005;
sigs,,,,INV_GAMMA_PDF,0.005,0.005;
sigi,,,,INV_GAMMA_PDF,0.002,0.002;
end;
// dataloading_jme_beta(1,'sims.txt',30);
load('dataobsfile','inom')
// check if inom is at lb and remove data + associated shock
verbatim;
inom(inom==1)=NaN;
end;
inx = strmatch('epsi',M_.exo_names);
if any(isnan(inom))
M_.heteroskedastic_shocks.Qscale_orig.periods=find(isnan(inom));
M_.heteroskedastic_shocks.Qscale_orig.exo_id=inx;
M_.heteroskedastic_shocks.Qscale_orig.scale=0;
else
options_.heteroskedastic_filter=false;
end
copyfile dataobsfile.mat dataobsfile2.mat
save dataobsfile2 inom -append
// -----------------Occbin ----------------------------------------------//
options_.occbin.smoother.debug=1;
occbin_setup(filter_use_relaxation,likelihood_piecewise_kalman_filter);
// use PKF
estimation(
datafile=dataobsfile2, mode_file=NKM_mh_mode_saved,
mode_compute=0, nobs=120, first_obs=1,
mh_replic=0, plot_priors=0, smoother,
graph_format=(fig), nodisplay,consider_all_endogenous,heteroskedastic_filter);
oo0=oo_;
// use inversion filter (note that IF provides smoother together with likelihood)
occbin_setup(likelihood_inversion_filter,smoother_inversion_filter);
estimation(
datafile=dataobsfile2, mode_file=NKM_mh_mode_saved,
mode_compute=0, nobs=120, first_obs=1,
mh_replic=0, plot_priors=0, smoother,
graph_format=(fig), nodisplay, consider_all_endogenous,heteroskedastic_filter);
// show initial condition effect of IF
figure,
subplot(221)
plot([oo0.SmoothedShocks.epsg oo_.SmoothedShocks.epsg]), title('epsg')
subplot(222)
plot([oo0.SmoothedShocks.epsi oo_.SmoothedShocks.epsi]), title('epsi')
subplot(223)
plot([oo0.SmoothedShocks.epss oo_.SmoothedShocks.epss]), title('epss')
legend('PKF','IF')

View File

@ -0,0 +1,345 @@
//Tests Occbin estimation with IVF and PKF with 1 constraints and redundant shocks
// this file implements the model in:
// Atkinson, T., A. W. Richter, and N. A. Throckmorton (2019).
// The zero lower bound andestimation accuracy.Journal of Monetary Economics
// original codes provided by Alexander Richter
// adapted for dynare implementation
// ------------------------- Settings -----------------------------------------//
@#ifndef small_model
@#define small_model = 0
@#endif
// if ~exist('run_ivf','var')
run_ivf=0;
// end
// ----------------- Defintions -----------------------------------------//
var
c //1 Consumption
n //2 Labor
y //5 Output
yf //6 Final goods
yg //11 Output growth gap
w //12 Real wage rate
wf //13 Flexible real wage
pigap //15 Inflation rate -> pi(t)/pibar = pigap
inom //16 Nominal interest rate
inomnot //17 Notional interest rate
mc //19 Real marginal cost
lam //20 Inverse marginal utility of wealth
g //21 Growth shock
s //22 Risk premium shock
mp //23 Monetary policy shock
pi //24 Observed inflation
@#if !(small_model)
x //3 Investment
k //4 Capital
u //7 Utilization cost
ups //8 Utilization choice
wg //9 Real wage growth gap
xg //10 Investment growth
rk //14 Real rental rate
q //18 Tobins q
@#endif
;
varexo
junk1
epsg // Productivity growth shock
epsi // Notional interest rate shock
epss // Risk premium shock
junk2
;
parameters
// Calibrated Parameters
beta // Discount factor
chi // Labor disutility scale
thetap // Elasticity of subs. between intermediate goods
thetaw // Elasticity of subs. between labor types
nbar // Steady state labor
eta // Inverse frish elasticity of labor supply
delta // Depreciation
alpha // Capital share
gbar // Mean growth rate
pibar // Inflation target
inombar // Steady gross nom interest rate
inomlb // Effective lower bound on gross nominal interest rate
sbar // Average risk premium
// Parameters for DGP and Estimated parameters
varphip // Rotemberg price adjustment cost
varphiw // Rotemberg wage adjustment cost
h // Habit persistence
rhos // Persistence
rhoi // Persistence
sigz // Standard deviation technology
sigs // Standard deviation risk premia
sigi // Standard deviation mon pol
phipi // Inflation responsiveness
phiy // Output responsiveness
nu // Investment adjustment cost
sigups // Utilization
// Switching parameters
zlb
;
// ---------------- Calibration -----------------------------------------//
beta = 0.9949; // Discount factor
thetap = 6; // Elasticity of subs. between intermediate goods
thetaw = 6; // Elasticity of subs. between labor types
nbar = 1/3; // Steady state labor
eta = 1/3; // Inverse frish elasticity of labor supply
delta = 0.025; // Depreciation
alpha = 0.35; // Capital share
gbar = 1.0034; // Mean growth rate
pibar = 1.0053; // Inflation target
sbar = 1.0058; // Average risk premium
rkbar = 1/beta;
varphiw = 100; // Rotemberg wage adjustment cost
nu = 4; // Investment adjustment cost
sigups = 5; // Utilization
varphip = 100; // Rotemberg price adjustment cost
h = 0.80; // Habit persistence
rhos = 0.80; // Persistence
rhoi = 0.80; // Persistence
sigz = 0.005; // Standard deviation
sigs = 0.005; // Standard deviation
sigi = 0.002; // Standard deviation
phipi = 2.0; // Inflation responsiveness
phiy = 0.5; // Output responsiveness
zlb = 0 ; // ZLB dummy
inomlb = 1 ; // Inom LB
// ---------------- Model -----------------------------------------------//
model;
@#if !(small_model)
[name = 'HH FOC utilization (1)']
rk = steady_state(rk)*exp(sigups*(ups-1));
[name = 'Utilization definition (3)']
u = steady_state(rk)*(exp(sigups*(ups-1))-1)/sigups;
[name = 'Firm FOC capital (4)']
rk = mc*alpha*g*yf/(ups*k(-1));
[name = 'HH FOC capital (17)']
q = beta*(lam/lam(+1))*(rk(+1)*ups(+1)-u(+1)+(1-delta)*q(+1))/g(+1);
[name = 'HH FOC investment (18)']
1 = q*(1-nu*(xg-1)^2/2-nu*(xg-1)*xg)+beta*nu*gbar*q(+1)*(lam/lam(+1))*xg(+1)^2*(xg(+1)-1)/g(+1);
[name = 'Wage Phillips Curve (20)']
varphiw*(wg-1)*wg = ((1-thetaw)*w+thetaw*wf)*n/yf + beta*varphiw*(lam/lam(+1))*(wg(+1)-1)*wg(+1)*(yf(+1)/yf) ;
[name = 'Real wage growth gap (6)']
wg = pigap*g*w/(gbar*w(-1));
[name = 'Law of motion for capital (15)']
k = (1-delta)*(k(-1)/g)+x*(1-nu*(xg-1)^2/2);
[name = 'Investment growth gap (14)']
xg = g*x/(gbar*x(-1));
@#endif
@#if small_model
[name = 'Production function (2)']
yf = n;
[name = 'Firm FOC labor (5)']
w = mc*yf/n;
[name = 'Output definition (7)']
y = (1-varphip*(pigap-1)^2/2)*yf;
[name = 'ARC (13)']
c = y;
[name = 'Household labpur supply equals flex wage']
w = wf;
@#else
[name = 'Production function (2)']
yf = (ups*k(-1)/g)^alpha*n^(1-alpha);
[name = 'Firm FOC labor (5)']
w = (1-alpha)*mc*yf/n;
[name = 'Output definition (7)']
y = (1-varphip*(pigap-1)^2/2-varphiw*(wg-1)^2/2)*yf - u*k(-1)/g;
[name = 'ARC (13)']
x = y-c;
@#endif
[name = 'Output growth gap (8)']
yg = g*y/(gbar*y(-1)) + junk1 + junk2;
[name = 'Notional Interest Rate (9)']
inomnot = inomnot(-1)^rhoi*(inombar*pigap^phipi*yg^phiy)^(1-rhoi)*exp(mp);
[name = 'Nominal Interest Rate (10)']
inom = (inomnot*(1-zlb)+zlb*inomlb);
[name = 'Inverse MUC (11)']
lam = c-h*c(-1)/g;
[name = 'Flexible real wage definition (12)']
wf = chi*n^eta*lam;
[name = 'HH FOC bond (16)']
1 = beta*(lam/lam(+1))*s*inom/(g(+1)*pibar*pigap(+1));
[name = 'Price Phillips Curve (19)']
varphip*(pigap-1)*pigap = 1-thetap+thetap*mc+beta*varphip*(lam/lam(+1))*(pigap(+1)-1)*pigap(+1)*(yf(+1)/yf);
[name = 'Stochastic productivity growth (21)']
g = gbar+ sigz*epsg;
[name = 'Risk premium shock (22)']
s = (1-rhos)*sbar + rhos*s(-1)+sigs*epss ;
[name = 'Notional interest rate shock (23)']
mp = sigi*epsi;
[name = 'Observed inflation (24)']
pi = pigap*pibar;
end;
occbin_constraints;
name 'zlb'; bind inom+inombar <= inomlb; relax inom+inombar > inomlb;
end;
// ---------------- Steady state -----------------------------------------//
steady_state_model;
mp = 0;
xg = 1;
s = sbar;
n = nbar;
ups =1;
u =0;
q =1;
g = gbar;
yg = 1;
pigap = 1;
wg =1;
pi = pigap*pibar;
// FOC bond
inom = gbar*pibar/(beta*s);
inomnot = inom;
inombar = inom;
// Firm pricing
mc = (thetap-1)/thetap;
// FOC capital
rk = gbar/beta+delta-1;
// Marginal cost definition
@#if small_model
alpha = 0;
thetaw=1;
@#endif
w = (mc*(1-alpha)^(1-alpha)*alpha^alpha/rk^alpha)^(1/(1-alpha));
@#if small_model
wf = w;
@#else
wf = (thetaw-1)*w/thetaw;
@#endif
// Consolidated FOC firm
k = w*n*gbar*alpha/(rk*(1-alpha));
// Law of motion for capital
x = (1-(1-delta)/gbar)*k;
// Production function
yf = (k/gbar)^alpha*n^(1-alpha);
// Real GDP
y = yf;
// Aggregate resouce constraint
c = y-x;
// FOC labor
lam = (1-h/gbar)*c;
chi = wf/(n^eta*lam);
// try log observables
end;
// ---------------- Checks -----------------------------------------//
steady;
check;
// ---------------- Simulation -----------------------------------------//
shocks;
var epsi = 1;
var epss = 1;
var epsg = 1;
end;
steady;
check;
// ---------------- Estimation -----------------------------------------//
varobs yg inom pi;
estimated_params;
// PARAM NAME, INITVAL, LB, UB, PRIOR_SHAPE, PRIOR_P1, PRIOR_P2, PRIOR_P3, PRIOR_P4, JSCALE
// PRIOR_SHAPE: BETA_PDF, GAMMA_PDF, NORMAL_PDF, INV_GAMMA_PDF
varphip,,0,inf,NORMAL_PDF,100,25;
phipi,,,,NORMAL_PDF,2,0.25;
phiy,,0,inf,NORMAL_PDF,0.5,0.25;
h,,,,BETA_PDF,0.8,0.1;
rhos,,,,BETA_PDF,0.8,0.1;
rhoi,,,,BETA_PDF,0.8,0.1;
sigz,,,,INV_GAMMA_PDF,0.005,0.005;
sigs,,,,INV_GAMMA_PDF,0.005,0.005;
sigi,,,,INV_GAMMA_PDF,0.002,0.002;
end;
// dataloading_jme_beta(1,'sims.txt',30);
load('dataobsfile','inom')
// check if inom is at lb and remove data + associated shock
verbatim;
inom(inom==1)=NaN;
end;
inx = strmatch('epsi',M_.exo_names);
if any(isnan(inom))
M_.heteroskedastic_shocks.Qscale_orig.periods=find(isnan(inom));
M_.heteroskedastic_shocks.Qscale_orig.exo_id=inx;
M_.heteroskedastic_shocks.Qscale_orig.scale=0;
else
options_.heteroskedastic_filter=false;
end
copyfile dataobsfile.mat dataobsfile2.mat
save dataobsfile2 inom -append
// -----------------Occbin ----------------------------------------------//
options_.occbin.filter.use_relaxation=true;
// use PKF
estimation(
datafile=dataobsfile2, mode_file=NKM_mh_mode_saved,
mode_compute=0, nobs=120, first_obs=1,
mh_replic=0, plot_priors=0, smoother,
graph_format=(fig), nodisplay,consider_all_endogenous,heteroskedastic_filter);
oo0=oo_;
// use inversion filter (note that IF provides smoother together with likelihood)
options_.occbin.likelihood.inversion_filter = 1;
options_.occbin.smoother.inversion_filter = 1;
estimation(
datafile=dataobsfile2, mode_file=NKM_mh_mode_saved,
mode_compute=0, nobs=120, first_obs=1,
mh_replic=0, plot_priors=0, smoother,
graph_format=(fig), nodisplay, consider_all_endogenous,heteroskedastic_filter);
// show initial condition effect of IF
figure,
subplot(221)
plot([oo0.SmoothedShocks.epsg oo_.SmoothedShocks.epsg]), title('epsg')
subplot(222)
plot([oo0.SmoothedShocks.epsi oo_.SmoothedShocks.epsi]), title('epsi')
subplot(223)
plot([oo0.SmoothedShocks.epss oo_.SmoothedShocks.epss]), title('epss')
legend('PKF','IF')

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,53 @@
// --+ options: nostrict +--
//Test Occbin with 1 constraint and redundant shocks; also checks whether defaults for error_* are correct
var b ${b}$ (long_name='borrowing')
c ${c}$ (long_name='vonsumption')
ec ${E(c_t)}$ (long_name='expected consumption')
lb ${\lambda}$ (long_name='Lagrange multiplier')
y ${y}$ (long_name='Output')
c_hat ${\hat c}$
b_hat ${\hat c}$
y_hat ${\hat y}$
;
varexo u $u$;
parameters RHO ${\rho}$, BETA ${\beta}$, M $M$, R $R$, SIGMA ${\sigma}$, GAMMAC $\gamma_c$, relax_borrcon ;
model;
ec = c(1);
c = y + b - R*b(-1) ;
(1-relax_borrcon)*(b - M*y) + relax_borrcon*lb = 0;
lb = 1/c^GAMMAC - BETA*R/c(+1)^GAMMAC ;
log(y) = RHO*log(y(-1)) + u ;
c_hat = log(c) - log(steady_state(c));
b_hat = log(b) - log(steady_state(b));
y_hat = log(y) - log(steady_state(y));
end;
occbin_constraints;
% name 'relax_borrcon'; bind lb<-lb_ss; relax b>M*y; error_bind abs(lb+lb_ss); error_relax abs(b-M*y);
name 'relax_borrcon'; bind lb<-lb_ss; relax b>M*y;
end;
steady_state_model;
b=M;
c=1+M-R*M;
ec=c;
lb=(1-BETA*R)/c^GAMMAC;
y=1;
end;
R = 1.05;
BETA = 0.945;
RHO = 0.9;
SIGMA = 0.05;
M = 1;
GAMMAC = 1;
relax_borrcon = 0;
shocks;
var u; stderr SIGMA;
end;
@#include "borrcon_common.inc"

View File

@ -0,0 +1,58 @@
// --+ options: nostrict +--
//Test Occbin with 1 constraint and redundant shocks; also checks whether defaults for error_* are correct
var b ${b}$ (long_name='borrowing')
c ${c}$ (long_name='vonsumption')
ec ${E(c_t)}$ (long_name='expected consumption')
lb ${\lambda}$ (long_name='Lagrange multiplier')
y ${y}$ (long_name='Output')
c_hat ${\hat c}$
b_hat ${\hat c}$
y_hat ${\hat y}$
;
varexo junk1 u junk2 ;
parameters RHO ${\rho}$, BETA ${\beta}$, M $M$, R $R$, SIGMA ${\sigma}$, GAMMAC $\gamma_c$, relax_borrcon ;
model;
ec = c(1);
c = y + b - R*b(-1) ;
(1-relax_borrcon)*(b - M*y) + relax_borrcon*lb = 0;
lb = 1/c^GAMMAC - BETA*R/c(+1)^GAMMAC +junk1 + junk2;
log(y) = RHO*log(y(-1)) + u ;
c_hat = log(c) - log(steady_state(c));
b_hat = log(b) - log(steady_state(b));
y_hat = log(y) - log(steady_state(y));
end;
occbin_constraints;
name 'relax_borrcon'; bind lb<-lb_ss; relax b>M*y; error_bind abs(lb+lb_ss); error_relax abs(b-M*y);
end;
steady_state_model;
b=M;
c=1+M-R*M;
ec=c;
lb=(1-BETA*R)/c^GAMMAC;
y=1;
end;
R = 1.05;
BETA = 0.945;
RHO = 0.9;
SIGMA = 0.05;
M = 1;
GAMMAC = 1;
relax_borrcon = 0;
shocks;
var u; stderr SIGMA;
end;
@#include "borrcon_common.inc"
orig_results=load('borrcon_results.mat');
if max(max(abs(oo_.occbin.piecewise-orig_results.oo_.occbin.piecewise)))>1e-10
error('Results do not match')
end

View File

@ -0,0 +1,38 @@
steady;
check;
shocks(surprise,overwrite);
var u;
periods 10, 30;
values 0.03, -0.03;
end;
occbin_setup(simul_periods=80);
occbin_solver(simul_maxit=11,simul_curb_retrench);
%
titlelist = char('c (consumption)','b (borrowing)','y (income)','lb (multiplier)');
percent = 'Percent';
level = 'Level';
ylabels = char(percent,percent,percent,level);
figtitle = 'Simulated variables';
legendlist = cellstr(char('Piecewise Linear','Linear'));
options_.TeX=1;
occbin_graph;
occbin_graph c_hat b_hat y_hat;
write_latex_original_model(write_equation_tags);
//collect_latex_files;
oo_= occbin.unpack_simulations(M_,oo_,options_);
line1=100*[(oo_.occbin.endo_piecewise.c-oo_.occbin.endo_ss.c)/oo_.occbin.endo_ss.c, ...
(oo_.occbin.endo_piecewise.b-oo_.occbin.endo_ss.b)/oo_.occbin.endo_ss.b, ...
(oo_.occbin.endo_piecewise.y-oo_.occbin.endo_ss.y)/oo_.occbin.endo_ss.y, ...
oo_.occbin.endo_piecewise.lb/100];
line2=100*[(oo_.occbin.endo_linear.c-oo_.occbin.endo_ss.c)/oo_.occbin.endo_ss.c, ...
(oo_.occbin.endo_linear.b-oo_.occbin.endo_ss.b)/oo_.occbin.endo_ss.b, ...
(oo_.occbin.endo_linear.y-oo_.occbin.endo_ss.y)/oo_.occbin.endo_ss.y, ...
oo_.occbin.endo_linear.lb/100];
occbin.make_chart(titlelist,legendlist,figtitle,ylabels,cat(3,line1,line2));

View File

@ -0,0 +1,47 @@
//Tests Occbin with 2 constraints
// variables
var a, c, i, k, lambdak;
// innovations to shock processes
varexo erra;
// parameters
parameters ALPHA, DELTAK, BETA, GAMMAC, RHOA, PHI, PSI, PSINEG, INEG, IRR;
model;
# zkss = ((1/BETA-1+DELTAK)/ALPHA)^(1/(ALPHA-1));
# zcss = -DELTAK*zkss + zkss^ALPHA;
# ziss = DELTAK*zkss;
# zuss = (zcss^(1-GAMMAC)-1)/(1-GAMMAC);
# zvss = zuss/(1-BETA);
/////////////////////////////////////////////////////////////////
// 1.
-exp(c)^(-GAMMAC)*(1+2*INEG*PSI*(exp(k)/exp(k(-1))-1)/exp(k(-1)))
+ BETA*exp(c(1))^(-GAMMAC)*((1-DELTAK)-2*INEG*PSI*(exp(k(1))/exp(k)-1)*
(-exp(k(1))/exp(k)^2)+ALPHA*exp(a(1))*exp(k)^(ALPHA-1))=
-lambdak+BETA*(1-DELTAK)*lambdak(1);
// 2.
exp(c)+exp(k)-(1-DELTAK)*exp(k(-1))+
INEG*PSI*(exp(k)/exp(k(-1))-1)^2=exp(a)*exp(k(-1))^(ALPHA);
// 3.
exp(i) = exp(k)-(1-DELTAK)*exp(k(-1));
// 4.
lambdak*(1-IRR) + IRR*(i - log(PHI*ziss)) = 0;
// 5.
a = RHOA*a(-1)+erra;
end;
occbin_constraints;
name 'IRR'; bind i<PHI-1; relax lambdak<0;
name 'INEG'; bind i<-0.000001;
end;
@#include "dynrbc_common.inc"

View File

@ -0,0 +1,64 @@
//Tests Occbin with 2 constraints and redundant shocks
// variables
var a, c, i, k, lambdak;
// innovations to shock processes
varexo junk1 erra junk2;
// parameters
parameters ALPHA, DELTAK, BETA, GAMMAC, RHOA, PHI, PSI, PSINEG, INEG, IRR;
model;
# zkss = ((1/BETA-1+DELTAK)/ALPHA)^(1/(ALPHA-1));
# zcss = -DELTAK*zkss + zkss^ALPHA;
# ziss = DELTAK*zkss;
# zuss = (zcss^(1-GAMMAC)-1)/(1-GAMMAC);
# zvss = zuss/(1-BETA);
/////////////////////////////////////////////////////////////////
// 1.
-exp(c)^(-GAMMAC)*(1+2*INEG*PSI*(exp(k)/exp(k(-1))-1)/exp(k(-1)))
+ BETA*exp(c(1))^(-GAMMAC)*((1-DELTAK)-2*INEG*PSI*(exp(k(1))/exp(k)-1)*
(-exp(k(1))/exp(k)^2)+ALPHA*exp(a(1))*exp(k)^(ALPHA-1))=
-lambdak+BETA*(1-DELTAK)*lambdak(1);
// 2.
exp(c)+exp(k)-(1-DELTAK)*exp(k(-1))+
INEG*PSI*(exp(k)/exp(k(-1))-1)^2=exp(a)*exp(k(-1))^(ALPHA) + junk1 + junk2;
// 3.
exp(i) = exp(k)-(1-DELTAK)*exp(k(-1));
// 4.
lambdak*(1-IRR) + IRR*(i - log(PHI*ziss)) = 0;
// 5.
a = RHOA*a(-1)+erra;
end;
occbin_constraints;
name 'IRR'; bind i<PHI-1; relax lambdak<0; error_bind abs(i-(PHI-1)); error_relax abs(lambdak-0);
name 'INEG'; bind i<-0.000001; relax i>-0.000001; error_bind abs(i-0.000001); error_relax abs(i-0.000001);
end;
@#include "dynrbc_common.inc"
orig_results=load('dynrbc_results.mat');
if max(max(abs(oo_.occbin.piecewise-orig_results.oo_.occbin.piecewise)))>1e-10
error('Results do not match')
end
if max(max(abs(oo_.SmoothedShocks.erra-orig_results.oo_.SmoothedShocks.erra)))>1e-10
error('SmoothedShocks do not match')
end
if max(max(abs(struct2array(oo_.SmoothedVariables)-struct2array(orig_results.oo_.SmoothedVariables))))>1e-10
error('SmoothedShocks do not match')
end
if max(max(abs(oo_.Smoother.SteadyState-orig_results.oo_.Smoother.SteadyState)))>1e-10
error('SmoothedShocks do not match')
end

View File

@ -0,0 +1,116 @@
steady_state_model;
kss = ((1/BETA-1+DELTAK)/ALPHA)^(1/(ALPHA-1));
css = -DELTAK*kss +kss^ALPHA;
iss = DELTAK*kss;
k = log(kss);
c = log(css);
i = log(iss);
lambdak = 0;
a=0;
end;
BETA=0.96;
ALPHA=0.33;
DELTAK=0.10;
GAMMAC=2;
RHOA = 0.9;
PHI = 0.975;
PSI = 5; % adjustment cost for capital if investment is negative
INEG = 0;
IRR = 0;
shocks;
var erra; stderr 0.015;
end;
steady;
// run occbin simulations
% Option=1: impulse responses
% Option=2: random simulation
@#for option_val in [1, 2]
option=@{option_val};
%%%%%%%%%%%%%%%% Inputs stop here %%%%%%%%%%%%%%%%%%%%%
if option==1
shocks(surprise,overwrite);
var erra;
periods 1:9, 10, 50, 90, 130, 131:169;
values -0.0001, -0.01,-0.02, 0.01, 0.02, 0;
end;
elseif option==2
nperiods = 100;
randn('seed',1);
shockssequence = 1*randn(nperiods,1)*0.02 ;
shocks(surprise,overwrite);
var erra;
periods 1:100;
values (shockssequence);
end;
end
% set inputs
occbin_setup;
options_.occbin.smoother.debug=1;
occbin_solver(simul_periods=200,simul_maxit=200,simul_curb_retrench,simul_check_ahead_periods=200);
occbin_write_regimes(filename='test',periods=[1:100]);
%% Modify to plot IRFs
titlelist = char('c','lambdak','k','i','a');
percent = 'Percent';
value = 'value';
ylabels = char(percent,value,percent,percent,percent);
figtitle = 'Simulated variables';
legendlist = cellstr(char('Piecewise Linear','Linear'));
oo_= occbin.unpack_simulations(M_,oo_,options_);
line1=100*[oo_.occbin.endo_piecewise.c-oo_.occbin.endo_ss.c,oo_.occbin.endo_piecewise.lambdak/100,oo_.occbin.endo_piecewise.k-oo_.occbin.endo_ss.k,oo_.occbin.endo_piecewise.i-oo_.occbin.endo_ss.i,oo_.occbin.endo_piecewise.a-oo_.occbin.endo_ss.a];
line2=100*[oo_.occbin.endo_linear.c-oo_.occbin.endo_ss.c,oo_.occbin.endo_linear.lambdak/100,oo_.occbin.endo_linear.k-oo_.occbin.endo_ss.k,oo_.occbin.endo_linear.i-oo_.occbin.endo_ss.i,oo_.occbin.endo_linear.a-oo_.occbin.endo_ss.a];
occbin.make_chart(titlelist,legendlist,figtitle,ylabels,cat(3,line1,line2));
occbin_graph(noconstant) c erra lambdak k i a k;
@#if option_val==1
verbatim;
c=oo_.occbin.endo_piecewise.c;
end;
save('datasim','c');
varobs c;
occbin_solver(simul_periods=200,simul_maxit=200,simul_curb_retrench,simul_check_ahead_periods=200);
occbin_setup(smoother_periods=200,smoother_maxit=200,smoother_curb_retrench,smoother_check_ahead_periods=200);
calib_smoother(datafile=datasim);
oo_= occbin.unpack_simulations(M_,oo_,options_);
titlelist = char('c','lambdak','k','i','a','erra');
percent = 'Percent';
value = 'value';
ylabels = char(percent,value,percent,percent,percent, value);
figtitle = 'Smoothed variables (piecewise)';
legendlist = cellstr(char('Simulated','Piecewise smoother'));
shock_vector=[oo_.occbin.shocks_sequence./100; zeros(length(oo_.occbin.endo_piecewise.c)-size(oo_.occbin.shocks_sequence,1),size(oo_.occbin.shocks_sequence,2))];
line1=100*[oo_.occbin.endo_piecewise.c-oo_.occbin.endo_ss.c,oo_.occbin.endo_piecewise.lambdak/100,oo_.occbin.endo_piecewise.k-oo_.occbin.endo_ss.k,oo_.occbin.endo_piecewise.i-oo_.occbin.endo_ss.i,oo_.occbin.endo_piecewise.a-oo_.occbin.endo_ss.a, shock_vector];
line2=100*[oo_.occbin.smoother.SmoothedVariables.c-oo_.occbin.endo_ss.c,oo_.occbin.smoother.SmoothedVariables.lambdak/100,oo_.occbin.smoother.SmoothedVariables.k-oo_.occbin.endo_ss.k,oo_.occbin.smoother.SmoothedVariables.i-oo_.occbin.endo_ss.i,oo_.occbin.smoother.SmoothedVariables.a-oo_.occbin.endo_ss.a, oo_.occbin.smoother.SmoothedShocks.erra/100];
occbin.make_chart(titlelist,legendlist,figtitle,ylabels,cat(3,line1,line2));
figtitle = 'Smoothed variables (linear)';
legendlist = cellstr(char('Simulated','Linear smoother'));
line1=100*[oo_.occbin.endo_piecewise.c-oo_.occbin.endo_ss.c,oo_.occbin.endo_piecewise.lambdak/100,oo_.occbin.endo_piecewise.k-oo_.occbin.endo_ss.k,oo_.occbin.endo_piecewise.i-oo_.occbin.endo_ss.i,oo_.occbin.endo_piecewise.a-oo_.occbin.endo_ss.a, shock_vector];
line2=100*[oo_.occbin.linear_smoother.SmoothedVariables.c-oo_.occbin.endo_ss.c,oo_.occbin.linear_smoother.SmoothedVariables.lambdak/100,oo_.occbin.linear_smoother.SmoothedVariables.k-oo_.occbin.endo_ss.k,oo_.occbin.linear_smoother.SmoothedVariables.i-oo_.occbin.endo_ss.i,oo_.occbin.linear_smoother.SmoothedVariables.a-oo_.occbin.endo_ss.a, oo_.occbin.linear_smoother.SmoothedShocks.erra/100];
occbin.make_chart(titlelist,legendlist,figtitle,ylabels,cat(3,line1,line2));
@#endif
@#endfor

View File

@ -0,0 +1,80 @@
% check for correct error message if token cannot be interpreted
// variables
var a, c, i, k, lambdak;
// innovations to shock processes
varexo erra;
// parameters
parameters ALPHA, DELTAK, BETA, GAMMAC, RHOA, PHI, PSI, PSINEG, INEG, IRR;
model(occbin);
# zkss = ((1/BETA-1+DELTAK)/ALPHA)^(1/(ALPHA-1));
# zcss = -DELTAK*zkss + zkss^ALPHA;
# ziss = DELTAK*zkss;
# zuss = (zcss^(1-GAMMAC)-1)/(1-GAMMAC);
# zvss = zuss/(1-BETA);
/////////////////////////////////////////////////////////////////
// 1.
-exp(c)^(-GAMMAC)*(1+2*INEG*PSI*(exp(k)/exp(k(-1))-1)/exp(k(-1)))
+ BETA*exp(c(1))^(-GAMMAC)*((1-DELTAK)-2*INEG*PSI*(exp(k(1))/exp(k)-1)*
(-exp(k(1))/exp(k)^2)+ALPHA*exp(a(1))*exp(k)^(ALPHA-1))=
-lambdak+BETA*(1-DELTAK)*lambdak(1);
// 2.
exp(c)+exp(k)-(1-DELTAK)*exp(k(-1))+
INEG*PSI*(exp(k)/exp(k(-1))-1)^2=exp(a)*exp(k(-1))^(ALPHA);
// 3.
[pswitch = 'INEG',
// bind = 'exp(i+i_ss)<-0.000001',
// relax = 'exp(i+i_ss)>-0.000001' ]
bind = 'i<-b',
relax = 'i>-0.000001' ]
exp(i) = exp(k)-(1-DELTAK)*exp(k(-1));
// 4.
[pswitch = 'IRR',
bind = 'i<PHI-1',
relax = 'lambdak<0' ]
lambdak*(1-IRR) + IRR*(i - log(PHI*ziss)) = 0;
// 5.
a = RHOA*a(-1)+erra;
end;
steady_state_model;
kss = ((1/BETA-1+DELTAK)/ALPHA)^(1/(ALPHA-1));
css = -DELTAK*kss +kss^ALPHA;
iss = DELTAK*kss;
k = log(kss);
c = log(css);
i = log(iss);
lambdak = 0;
a=0;
end;
BETA=0.96;
ALPHA=0.33;
DELTAK=0.10;
GAMMAC=2;
RHOA = 0.9;
PHI = 0.975;
PSI = 5; % adjustment cost for capital if investment is negative
INEG = 0;
IRR = 0;
shocks;
var erra; stderr 0.015;
end;
steady;
stoch_simul(order=1,nocorr,nomoments,irf=0,noprint);