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
Sébastien Villemot 2021-07-09 18:12:10 +02:00
parent 9f934bbcf1
commit abd64c256e
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
8 changed files with 268 additions and 2 deletions

View File

@ -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;

View File

@ -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 cant 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)];

View File

@ -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

View File

@ -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.")

View File

@ -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

View File

@ -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
1 Exo x x x x x x x
2 Period (info) 1 2 3 4 5 6 7
3 Terminal 1 1.1 1.2 1.2 1.2 1.1 1.1
4 Period 1 (real) 1.2
5 Period 2 (real) 1 1.3
6 Period 3 (real) 1 1 1.4
7 Period 4 (real) 1 1 1 1
8 Period 5 (real) 1 1 1 1 1
9 Period 6 (real) 1 1 1 1 1 1.1
10 Period 7 (real) 1 1 1 1 1 1.1 1.1

View File

@ -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