New perfect_foresight_with_expectation_errors_{setup,solver} commands
These command solve the problem where agents think they know perfectly the future (they behave as in perfect foresight), but make expectation errors. Hence they can potentially be surprised in every period, and their expectations about the future (incl. the final steady state) may change. Currently the sequence of information sets needs to be passed through a CSV file. Another interface may be added in the future. The algorithm uses a sequence of (true) perfect foresight simulations (not necessarily as many as there are periods, because if the information set does not change between two periods, there is no need to do a new computation). There are two possibilities for guess values: — the default is to use the initial steady state for the simulation using the first-period information set; then use previously simulated values as guess values — alternatively, with the terminal_steady_state_as_guess_value option, use the terminal steady state as guess value for all future periods (this is actually what the “true” perfect foresight solver does by default)var-model-with-constant
parent
9f934bbcf1
commit
abd64c256e
|
@ -325,6 +325,9 @@ options_.minimal_solving_periods = 1;
|
|||
options_.endogenous_terminal_period = false;
|
||||
options_.no_homotopy = false;
|
||||
|
||||
% Perfect foresight with expectation errors
|
||||
options_.pfwee.terminal_steady_state_as_guess_value = false;
|
||||
|
||||
% Solution
|
||||
options_.order = 2;
|
||||
options_.pruning = false;
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
function perfect_foresight_with_expectation_errors_setup
|
||||
|
||||
% 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/>.
|
||||
|
||||
global M_ oo_ options_ ys0_
|
||||
|
||||
if ~isempty(ys0_)
|
||||
error('perfect_foresight_with_expectation_errors_setup: cannot be used in conjunction with endval')
|
||||
end
|
||||
|
||||
if ~isempty(M_.endo_histval)
|
||||
error('perfect_foresight_with_expectation_errors_setup: cannot be used in conjunction with histval')
|
||||
end
|
||||
if ~isempty(oo_.initval_series)
|
||||
error('perfect_foresight_with_expectation_errors_setup: cannot be used in conjunction with histval_file/initval_file')
|
||||
end
|
||||
|
||||
periods = options_.periods;
|
||||
|
||||
%% Read CSV file
|
||||
if ~exist(options_.datafile, 'file')
|
||||
error(['perfect_foresight_with_expectation_errors_setup: cannot find ' options_.datafile ])
|
||||
end
|
||||
%% We can’t use readcell (only in MATLAB ≥ R2019a), so instead rely on csvread and manual hacks
|
||||
% Read numeric data, skipping first row and first column
|
||||
raw_csv = csvread(options_.datafile, 1, 1);
|
||||
if size(raw_csv, 1)-2 ~= periods
|
||||
error(['perfect_foresight_with_expectation_errors_setup: the number of rows in ' options_.datafile ' does not match the periods setting'])
|
||||
end
|
||||
% Read first line (exogenous variable names)
|
||||
fid = fopen(options_.datafile);
|
||||
csv_first_line = fgetl(fid);
|
||||
fclose(fid);
|
||||
exo_header_names = strsplit(csv_first_line, ',');
|
||||
exo_header_names = exo_header_names(2:end); % Remove first column
|
||||
if numel(exo_header_names) ~= size(raw_csv, 2)
|
||||
error(['perfect_foresight_with_expectation_errors_setup: first line malformed in ' options_.datafile])
|
||||
end
|
||||
|
||||
%% Create and fill structures containing information sets
|
||||
oo_.pfwee.terminal_info = NaN(M_.exo_nbr, periods); % 2nd dimension is informational time
|
||||
oo_.pfwee.shocks_info = NaN(M_.exo_nbr, periods, periods); % 2nd dimension is real time, 3rd dimension is informational time
|
||||
for i = 1:size(raw_csv, 2)
|
||||
exo_id = strmatch(exo_header_names{i}, M_.exo_names, 'exact');
|
||||
period_id = raw_csv(1, i);
|
||||
oo_.pfwee.terminal_info(exo_id, period_id) = raw_csv(2, i);
|
||||
% Ignore irrelevant periods when copying shocks information
|
||||
oo_.pfwee.shocks_info(exo_id, period_id:end, period_id) = raw_csv(2+period_id:end, i);
|
||||
end
|
||||
|
||||
% Build initial paths for endos and exos (only initial conditions are set, the rest is NaN)
|
||||
oo_.endo_simul = [repmat(oo_.steady_state, 1, M_.maximum_lag) NaN(M_.endo_nbr, periods+M_.maximum_lead)];
|
||||
oo_.exo_simul = [repmat(oo_.exo_steady_state',M_.maximum_lag,1); NaN(periods+M_.maximum_lead,M_.exo_nbr)];
|
|
@ -0,0 +1,78 @@
|
|||
function perfect_foresight_with_expectation_errors_solver
|
||||
|
||||
% 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/>.
|
||||
|
||||
global M_ oo_ options_
|
||||
|
||||
% Save initial steady state, for restoring it at the end
|
||||
initial_steady_state = oo_.steady_state;
|
||||
initial_exo_steady_state = oo_.exo_steady_state;
|
||||
|
||||
% Same for periods (it will be modified before calling perfect_foresight_solver)
|
||||
periods = options_.periods
|
||||
|
||||
% Retrieve initial paths built by pfwee_setup
|
||||
% (the versions in oo_ will be truncated before calling perfect_foresight_solver)
|
||||
endo_simul = oo_.endo_simul;
|
||||
exo_simul = oo_.exo_simul;
|
||||
|
||||
% Start main loop around informational periods
|
||||
info_period = 1;
|
||||
while info_period <= periods
|
||||
% Compute terminal steady state as anticipated
|
||||
oo_.exo_steady_state = oo_.pfwee.terminal_info(:, info_period);
|
||||
steady_state_prev = oo_.steady_state;
|
||||
[oo_.steady_state,~,info] = evaluate_steady_state(steady_state_prev, M_, options_, oo_, true);
|
||||
|
||||
options_.periods = periods - info_period + 1;
|
||||
oo_.endo_simul = endo_simul(:, info_period:end); % Take initial conditions + guess values from previous simulation
|
||||
if options_.pfwee.terminal_steady_state_as_guess_value
|
||||
% Overwrite guess value with terminal steady state
|
||||
oo_.endo_simul(:, M_.maximum_lag+(1:periods-info_period+1)) = repmat(oo_.steady_state, 1, periods-info_period+1);
|
||||
elseif info_period == 1
|
||||
% Use initial steady state as guess value for first simulation if not using terminal steady state
|
||||
oo_.endo_simul(:, M_.maximum_lag+(1:periods)) = repmat(initial_steady_state, 1, periods);
|
||||
end
|
||||
oo_.endo_simul(:, end-M_.maximum_lead+1:end) = repmat(oo_.steady_state, 1, M_.maximum_lead);
|
||||
oo_.exo_simul = exo_simul(info_period:end, :);
|
||||
oo_.exo_simul(M_.maximum_lag+(1:periods-info_period+1), :) = oo_.pfwee.shocks_info(:, info_period:end, info_period)';
|
||||
oo_.exo_simul(end-M_.maximum_lead+1:end, :) = repmat(oo_.exo_steady_state, M_.maximum_lead, 1);
|
||||
|
||||
perfect_foresight_solver;
|
||||
|
||||
endo_simul(:, info_period:end) = oo_.endo_simul;
|
||||
exo_simul(info_period:end, :) = oo_.exo_simul;
|
||||
|
||||
% Increment info_period (as much as possible, if information set does not change for some time)
|
||||
increment = 1;
|
||||
while info_period+increment <= periods && ...
|
||||
all(oo_.pfwee.terminal_info(:, info_period) == oo_.pfwee.terminal_info(:, info_period+increment)) && ...
|
||||
all(all(oo_.pfwee.shocks_info(:, info_period+increment:end, info_period) == oo_.pfwee.shocks_info(:, info_period+increment:end, info_period+increment)))
|
||||
increment = increment + 1;
|
||||
end
|
||||
info_period = info_period + increment;
|
||||
end
|
||||
|
||||
% Set final paths
|
||||
oo_.endo_simul = endo_simul;
|
||||
oo_.exo_simul = exo_simul;
|
||||
|
||||
% Restore some values
|
||||
oo_.steady_state = initial_steady_state;
|
||||
oo_.exo_steady_state = initial_exo_steady_state;
|
||||
options_.periods = periods;
|
|
@ -1 +1 @@
|
|||
Subproject commit 365fb27f3d48ed208332a52f0f96e255f54c2dd4
|
||||
Subproject commit 6aeef11bb23169e7691ae0b60e1a8b8ad9dc2dc1
|
|
@ -76,6 +76,8 @@
|
|||
"markov_switching" "svar" "svar_global_identification_check"
|
||||
"external_function" "calib_smoother" "model_diagnostics" "extended_path"
|
||||
"smoother2histval" "perfect_foresight_setup" "perfect_foresight_solver"
|
||||
"perfect_foresight_with_expectation_errors_setup"
|
||||
"perfect_foresight_with_expectation_errors_solver"
|
||||
"std" "corr" "prior_function" "posterior_function" "end")
|
||||
"Dynare statement keywords.")
|
||||
|
||||
|
|
|
@ -364,6 +364,7 @@ MODFILES = \
|
|||
deterministic_simulations/rbc_det_stack_solve_algo_7.mod \
|
||||
deterministic_simulations/rbc_det_stack_solve_algo_7_exo_lag.mod \
|
||||
deterministic_simulations/rbc_det_stack_solve_algo_7_exo_lead.mod \
|
||||
deterministic_simulations/pfwee.mod \
|
||||
lmmcp/rbc.mod \
|
||||
lmmcp/sw_lmmcp.mod \
|
||||
lmmcp/sw_newton.mod \
|
||||
|
@ -1279,7 +1280,8 @@ EXTRA_DIST = \
|
|||
histval_initval_file/ramst_initval_file_data.m \
|
||||
run_kronecker_tests.m \
|
||||
kronecker/test_kron.m \
|
||||
kronecker/nash_matrices.mat
|
||||
kronecker/nash_matrices.mat \
|
||||
deterministic_simulations/pfwee.csv
|
||||
|
||||
if ENABLE_MATLAB
|
||||
check-local: check-matlab
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
Exo,x,x,x,x,x,x,x
|
||||
Period (info),1,2,3,4,5,6,7
|
||||
Terminal,1,1.1,1.2,1.2,1.2,1.1,1.1
|
||||
Period 1 (real),1.2,,,,,,
|
||||
Period 2 (real),1,1.3,,,,,
|
||||
Period 3 (real),1,1,1.4,,,,
|
||||
Period 4 (real),1,1,1,1,,,
|
||||
Period 5 (real),1,1,1,1,1,,
|
||||
Period 6 (real),1,1,1,1,1,1.1,
|
||||
Period 7 (real),1,1,1,1,1,1.1,1.1
|
|
|
@ -0,0 +1,103 @@
|
|||
// Tests perfect_foresight_with_expectation_errors_{setup,solver}
|
||||
|
||||
var c k;
|
||||
varexo x;
|
||||
|
||||
parameters alph gam delt bet aa;
|
||||
alph=0.5;
|
||||
gam=0.5;
|
||||
delt=0.02;
|
||||
bet=0.05;
|
||||
aa=0.5;
|
||||
|
||||
|
||||
model;
|
||||
c + k - aa*x*k(-1)^alph - (1-delt)*k(-1);
|
||||
c^(-gam) - (1+bet)^(-1)*(aa*alph*x(+1)*k^(alph-1) + 1 - delt)*c(+1)^(-gam);
|
||||
end;
|
||||
|
||||
initval;
|
||||
x = 1;
|
||||
k = ((delt+bet)/(1.0*aa*alph))^(1/(alph-1));
|
||||
c = aa*k^alph-delt*k;
|
||||
end;
|
||||
|
||||
steady;
|
||||
|
||||
check;
|
||||
|
||||
perfect_foresight_with_expectation_errors_setup(periods = 7, datafile = 'pfwee.csv');
|
||||
|
||||
// First simulation with default options
|
||||
perfect_foresight_with_expectation_errors_solver;
|
||||
pfwee1 = oo_.endo_simul;
|
||||
|
||||
// Second simulation with alternative guess values
|
||||
perfect_foresight_with_expectation_errors_solver(terminal_steady_state_as_guess_value);
|
||||
pfwee2 = oo_.endo_simul;
|
||||
|
||||
// Now compute the solution by hand to verify the results
|
||||
|
||||
perfect_foresight_setup;
|
||||
|
||||
// Information arriving in period 1 (temp shock now)
|
||||
oo_.exo_simul(2,1) = 1.2;
|
||||
perfect_foresight_solver;
|
||||
|
||||
// Information arriving in period 2 (temp shock now + permanent shock in future)
|
||||
oo_.exo_simul(3,1) = 1.3;
|
||||
oo_.exo_steady_state = 1.1;
|
||||
oo_.exo_simul(end, 1) = oo_.exo_steady_state;
|
||||
oo_.steady_state = evaluate_steady_state(oo_.steady_state, M_, options_, oo_, true);
|
||||
oo_.endo_simul(:, end) = oo_.steady_state;
|
||||
periods 6;
|
||||
saved_endo = oo_.endo_simul(:, 1);
|
||||
saved_exo = oo_.exo_simul(1, :);
|
||||
oo_.endo_simul = oo_.endo_simul(:, 2:end);
|
||||
oo_.exo_simul = oo_.exo_simul(2:end, :);
|
||||
perfect_foresight_solver;
|
||||
oo_.endo_simul = [ saved_endo oo_.endo_simul ];
|
||||
oo_.exo_simul = [ saved_exo; oo_.exo_simul ];
|
||||
|
||||
// Information arriving in period 3 (temp shock now + permanent shock in future)
|
||||
oo_.exo_simul(4,1) = 1.4;
|
||||
oo_.exo_steady_state = 1.2;
|
||||
oo_.exo_simul(end, 1) = oo_.exo_steady_state;
|
||||
oo_.steady_state = evaluate_steady_state(oo_.steady_state, M_, options_, oo_, true);
|
||||
oo_.endo_simul(:, end) = oo_.steady_state;
|
||||
periods 5;
|
||||
saved_endo = oo_.endo_simul(:, 1:2);
|
||||
saved_exo = oo_.exo_simul(1:2, :);
|
||||
oo_.endo_simul = oo_.endo_simul(:, 3:end);
|
||||
oo_.exo_simul = oo_.exo_simul(3:end, :);
|
||||
perfect_foresight_solver;
|
||||
oo_.endo_simul = [ saved_endo oo_.endo_simul ];
|
||||
oo_.exo_simul = [ saved_exo; oo_.exo_simul ];
|
||||
|
||||
// Information arriving in period 6 (permanent shock arriving now)
|
||||
oo_.exo_simul(7,1) = 1.1;
|
||||
oo_.exo_simul(8,1) = 1.1;
|
||||
oo_.exo_steady_state = 1.1;
|
||||
oo_.exo_simul(end, 1) = oo_.exo_steady_state;
|
||||
oo_.steady_state = evaluate_steady_state(oo_.steady_state, M_, options_, oo_, true);
|
||||
oo_.endo_simul(:, end) = oo_.steady_state;
|
||||
periods 2;
|
||||
saved_endo = oo_.endo_simul(:, 1:5);
|
||||
saved_exo = oo_.exo_simul(1:5, :);
|
||||
oo_.endo_simul = oo_.endo_simul(:, 6:end);
|
||||
oo_.exo_simul = oo_.exo_simul(6:end, :);
|
||||
perfect_foresight_solver;
|
||||
oo_.endo_simul = [ saved_endo oo_.endo_simul ];
|
||||
oo_.exo_simul = [ saved_exo; oo_.exo_simul ];
|
||||
|
||||
% We should have strict equality with first pfwee simulation, because algorithm
|
||||
% and guess values are exactly the same.
|
||||
if any(any(pfwee1-oo_.endo_simul ~= 0))
|
||||
error('Error in perfect_foresight_with_expectation_errors')
|
||||
end
|
||||
|
||||
% For the 2nd simulation, since the guess values are different, there are some
|
||||
% numerical differences
|
||||
if max(max(abs(pfwee2-oo_.endo_simul))) > 10*options_.dynatol.f
|
||||
error('Error in perfect_foresight_with_expectation_errors + terminal_steady_state_as_guess_value')
|
||||
end
|
Loading…
Reference in New Issue