From f5f47cd834049bd5111f23622fb2c68d0e6a619b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Adjemian=20=28Ry=C3=BBk=29?= <stepan@adjemian.eu> Date: Fri, 21 Jan 2022 16:45:45 +0100 Subject: [PATCH] Add new option last_simulation_period to initval_file command. Also adjust the periods in Simulated_time_series (output of the perfect foresight solver in the workspace). Note that this dseries object contains the observations for the initial condition (M_.orig_maximum_lag observations) and for the terminal condition (M_.orig_maximum_lead observations). See #1838. Fix testsuite (wrong file name) --- doc/manual/source/the-model-file.rst | 14 +++ matlab/histvalf_initvalf.m | 100 +++++++++++------- matlab/initvalf.m | 21 ++-- .../perfect_foresight_solver.m | 13 ++- preprocessor | 2 +- tests/Makefile.am | 1 + .../ramst_initval_file_with_dseries.mod | 36 +++++++ tests/histval_initval_file_unit_tests.m | 1 + 8 files changed, 136 insertions(+), 52 deletions(-) create mode 100644 tests/histval_initval_file/ramst_initval_file_with_dseries.mod diff --git a/doc/manual/source/the-model-file.rst b/doc/manual/source/the-model-file.rst index 38d43c3281..062114c2f4 100644 --- a/doc/manual/source/the-model-file.rst +++ b/doc/manual/source/the-model-file.rst @@ -1996,6 +1996,13 @@ in this case ``initval`` is used to specify the terminal conditions. file as the only dates necessary for initialization are before that date. + .. option:: last_simulation_period = {INTEGER | DATE} + + The observation number in the file or the date (see + :ref:`dates <dates-members>`) at which the simulation (or the forecast) is + ending. This option avoids to have to compute the maximum + number of leads in the model. + .. option:: last_obs = {INTEGER | DATE} The observaton number or the date (see @@ -2265,6 +2272,13 @@ in this case ``initval`` is used to specify the terminal conditions. file as the only dates necessary for initialization are before that date. + .. option:: last_simulation_period = {INTEGER | DATE} + + The observation number in the file or the date (see + :ref:`dates <dates-members>`) at which the simulation (or the forecast) is + ending. This option avoids to have to compute the maximum + number of leads in the model. + .. option:: last_obs = {INTEGER | DATE} The observation number or the date (see :ref:`dates-members`) of the diff --git a/matlab/histvalf_initvalf.m b/matlab/histvalf_initvalf.m index ac0b251688..4ce0da3cb0 100644 --- a/matlab/histvalf_initvalf.m +++ b/matlab/histvalf_initvalf.m @@ -1,18 +1,17 @@ -function series = histvalf_initvalf(caller, M, options) -% function initvalf(M) -% -% handles options for histvalf_initvalf() and initvalf() +function [series, p] = histvalf_initvalf(caller, DynareModel, options) + +% Handles options for histvalf() and initvalf() % % INPUTS -% caller: string, name of calling function -% M: model structure -% options: options specific to initivalf +% - caller [char] row array, name of calling function +% - DynareModel [struct] model description, a.k.a M_ +% - options [struct] options specific to initivalf % % OUTPUTS -% series: dseries containing selected data from a file or a dseries -% +% - series [dseries] selected data from a file or a dseries +% - p [integer] number of periods (excluding the initial and terminal conditions) -% Copyright (C) 2003-2021 Dynare Team +% Copyright © 2003-2022 Dynare Team % % This file is part of Dynare. % @@ -80,23 +79,23 @@ end % checking that all variable are present error_flag = false; -for i = 1:M.orig_endo_nbr - if ~series.exist(M.endo_names{i}) - dprintf('%s_FILE: endogenous variable %s is missing', caller, M.endo_names{i}) +for i = 1:DynareModel.orig_endo_nbr + if ~series.exist(DynareModel.endo_names{i}) + dprintf('%s_FILE: endogenous variable %s is missing', caller, DynareModel.endo_names{i}) error_flag = true; end end -for i = 1:M.exo_nbr - if ~series.exist(M.exo_names{i}) - dprintf('%s_FILE: exogenous variable %s is missing', caller, M.exo_names{i}) +for i = 1:DynareModel.exo_nbr + if ~series.exist(DynareModel.exo_names{i}) + dprintf('%s_FILE: exogenous variable %s is missing', caller, DynareModel.exo_names{i}) error_flag = true; end end -for i = 1:M.exo_det_nbr - if ~series.exist(M.exo_det_names{i}) - dprintf('%s_FILE: exo_det variable %s is missing', caller, M.exo_det_names{i}) +for i = 1:DynareModel.exo_det_nbr + if ~series.exist(DynareModel.exo_det_names{i}) + dprintf('%s_FILE: exo_det variable %s is missing', caller, DynareModel.exo_det_names{i}) error_flag = true; end end @@ -105,8 +104,8 @@ if error_flag error('%s_FILE: some variables are missing', caller) end -if exist(sprintf('+%s/dynamic_set_auxiliary_series.m', M.fname), 'file') - series = feval(sprintf('%s.dynamic_set_auxiliary_series', M.fname), series, M.params); +if exist(sprintf('+%s/dynamic_set_auxiliary_series.m', DynareModel.fname), 'file') + series = feval(sprintf('%s.dynamic_set_auxiliary_series', DynareModel.fname), series, DynareModel.params); end % selecting observations @@ -130,18 +129,18 @@ if isfield(options, 'first_obs') && ~isempty(options.first_obs) error('%s_FILE: first_obs = %d is larger than the number of observations in the data file (%d)', ... caller, options.first_obs, nobs0) elseif isfield(options, 'first_simulation_period') - if options.first_obs == options.first_simulation_period - M.orig_maximum_lag + if options.first_obs == options.first_simulation_period - DynareModel.orig_maximum_lag first_obs = periods(options.first_obs); else error('%s_FILE: first_obs = %d and first_simulation_period = %d have values inconsistent with a maximum lag of %d periods', ... - caller, options.first_obs, options.first_simulation_period, M.orig_maximum_lag) + caller, options.first_obs, options.first_simulation_period, DynareModel.orig_maximum_lag) end elseif isfield(options, 'firstsimulationperiod') - if periods(options.first_obs) == options.firstsimulationperiod - M.orig_maximum_lag + if periods(options.first_obs) == options.firstsimulationperiod - DynareModel.orig_maximum_lag first_obs = periods(options.first_obs); else error('%s_FILE: first_obs = %d and first_simulation_period = %s have values inconsistent with a maximum lag of %d periods', ... - caller, options.first_obs, options.firstsimulationperiod, M.orig_maximum_lag) + caller, options.first_obs, options.firstsimulationperiod, DynareModel.orig_maximum_lag) end else first_obs = periods(options.first_obs); @@ -151,18 +150,18 @@ end if isfield(options, 'firstobs') && ~isempty(options.firstobs) if isfield(options, 'first_simulation_period') - if options.firstobs == periods(options.first_simulation_period) - M.orig_maximum_lag + if options.firstobs == periods(options.first_simulation_period) - DynareModel.orig_maximum_lag first_obs = options.firstobs; else error('%s_FILE: first_obs = %s and first_simulation_period = %d have values inconsistent with a maximum lag of %d periods', ... - caller, options.firstobs, options.first_simulation_period, M.orig_maximum_lag) + caller, options.firstobs, options.first_simulation_period, DynareModel.orig_maximum_lag) end elseif isfield(options, 'firstsimulationperiod') - if options.firstobs == options.firstsimulationperiod - M.orig_maximum_lag + if options.firstobs == options.firstsimulationperiod - DynareModel.orig_maximum_lag first_obs = options.firstobs; else error('%s_FILE: firstobs = %s and first_simulation_period = %s have values inconsistent with a maximum lag of %d periods', ... - caller, options.firstobs, options.firstsimulationperiod, M.orig_maximum_lag) + caller, options.firstobs, options.firstsimulationperiod, DynareModel.orig_maximum_lag) end else first_obs = options.firstobs; @@ -172,26 +171,25 @@ end if ~first_obs_ispresent if isfield(options, 'first_simulation_period') - if options.first_simulation_period < M.orig_maximum_lag + if options.first_simulation_period < DynareModel.orig_maximum_lag error('%s_FILE: first_simulation_period = %d must be larger than the maximum lag (%d)', ... - caller, options.first_simulation_period, M.orig_maximum_lag) + caller, options.first_simulation_period, DynareModel.orig_maximum_lag) elseif options.first_simulation_period > nobs0 error('%s_FILE: first_simulations_period = %d is larger than the number of observations in the data file (%d)', ... caller, options.first_obs, nobs0) else - first_obs = periods(options.first_simulation_period) - M.orig_maximum_lag; + first_obs = periods(options.first_simulation_period) - DynareModel.orig_maximum_lag; end first_obs_ispresent = true; elseif isfield(options, 'firstsimulationperiod') - first_obs = options.firstsimulationperiod - M.orig_maximum_lag; + first_obs = options.firstsimulationperiod - DynareModel.orig_maximum_lag; first_obs_ispresent = true; end end if isfield(options, 'last_obs') if options.last_obs > nobs0 - error('%s_FILE: last_obs = %d is larger than the number of observations in the dataset (%d)', ... - caller, options.last_obs, nobs0) + error('%s_FILE: last_obs = %d is larger than the number of observations in the dataset (%d)', caller, options.last_obs, nobs0) elseif first_obs_ispresent if nobs > 0 && (periods(options.last_obs) ~= first_obs + nobs - 1) error('%s_FILE: FIST_OBS, LAST_OBS and NOBS contain inconsistent information. Use only two of these options.', caller) @@ -208,8 +206,7 @@ if isfield(options, 'last_obs') end elseif isfield(options, 'lastobs') if options.lastobs > series.last - error('%s_FILE: last_obs = %s is larger than the number of observations in the dataset (%s)', ... - caller, options.lastobs, series.last) + error('%s_FILE: last_obs = %s is larger than the number of observations in the dataset (%s)', caller, options.lastobs, series.last) elseif first_obs_ispresent if nobs > 0 && (options.lastobs ~= first_obs + nobs - 1) error('%s_FILE: FIST_OBS, LAST_OBS and NOBS contain inconsistent information. Use only two of these options.', caller) @@ -230,4 +227,31 @@ else last_obs = series.last; end -series = series(first_obs:last_obs); +if isfield(options, 'last_simulation_period') + lastsimulationperiod = periods(options.last_simulation_period); +end + +if isfield(options, 'lastsimulationperiod') + lastsimulationperiod = options.lastsimulationperiod; +end + + +if exist('lastsimulationperiod', 'var') + if lastsimulationperiod<=last_obs-DynareModel.orig_maximum_lead + last_obs = lastsimulationperiod+DynareModel.orig_maximum_lead; + else + error('%s_FILE: LAST_SIMULATION_PERIOD is too large compared to the available data.', caller) + end +end + +if exist('lastsimulationperiod', 'var') && exist('firstsimulationperiod', 'var') + p = lastsimulationperiod-firstsimulationperiod+1; +elseif exist('lastsimulationperiod', 'var') + p = lastsimulationperiod-(first_obs+DynareModel.orig_maximum_lag)+1; +elseif exist('firstsimulationperiod', 'var') + p = (last_obs-DynareModel.orig_maximum_lead)-firstsimulationperiod+1; +else + p = (last_obs-DynareModel.orig_maximum_lead)-(first_obs+DynareModel.orig_maximum_lag)+1; +end + +series = series(first_obs:last_obs); \ No newline at end of file diff --git a/matlab/initvalf.m b/matlab/initvalf.m index 707d349e17..c40009738f 100644 --- a/matlab/initvalf.m +++ b/matlab/initvalf.m @@ -1,18 +1,17 @@ -function series = initvalf(M, options) -% function initvalf(M) -% -% handles options for histvalf() and initvalf() +function [series, p] = initvalf(DynareModel, options) + +% Handles options for histvalf() and initvalf() % % INPUTS -% caller: string, name of calling function -% M: model structure -% options: options specific to initivalf +% - caller [char] row array, name of calling function +% - DynareModel [struct] model description, a.k.a M_ +% - options [struct] options specific to initivalf % % OUTPUTS -% series: dseries containing selected data from a file or a dseries -% +% - series [dseries] selected data from a file or a dseries +% - p [integer] number of periods (excluding the initial and terminal conditions) -% Copyright (C) 2003-2020 Dynare Team +% Copyright © 2003-2022 Dynare Team % % This file is part of Dynare. % @@ -29,4 +28,4 @@ function series = initvalf(M, options) % You should have received a copy of the GNU General Public License % along with Dynare. If not, see <https://www.gnu.org/licenses/>. -series = histvalf_initvalf('INITVALF', M, options); \ No newline at end of file +[series, p] = histvalf_initvalf('INITVALF', DynareModel, options); \ No newline at end of file diff --git a/matlab/perfect-foresight-models/perfect_foresight_solver.m b/matlab/perfect-foresight-models/perfect_foresight_solver.m index d303d59db4..3f1049925f 100644 --- a/matlab/perfect-foresight-models/perfect_foresight_solver.m +++ b/matlab/perfect-foresight-models/perfect_foresight_solver.m @@ -228,14 +228,23 @@ end dyn2vec(M_, oo_, options_); -if ~isdates(options_.initial_period) && isnan(options_.initial_period) +if isfield(oo_, 'initval_series') && ~isempty(oo_.initval_series) + initial_period = oo_.initval_series.dates(1)+(M_.orig_maximum_lag-1); +elseif ~isdates(options_.initial_period) && isnan(options_.initial_period) initial_period = dates(1,1); else initial_period = options_.initial_period; end ts = dseries([transpose(oo_.endo_simul(1:M_.orig_endo_nbr,:)), oo_.exo_simul], initial_period, [M_.endo_names(1:M_.orig_endo_nbr); M_.exo_names]); + +if isfield(oo_, 'initval_series') && ~isempty(oo_.initval_series) + names = ts.name; + ts = merge(oo_.initval_series{names{:}}, ts); +end + assignin('base', 'Simulated_time_series', ts); + if oo_.deterministic_simulation.status oo_.gui.ran_perfect_foresight = true; -end +end \ No newline at end of file diff --git a/preprocessor b/preprocessor index 5e8b478ccf..c56d58822e 160000 --- a/preprocessor +++ b/preprocessor @@ -1 +1 @@ -Subproject commit 5e8b478ccf795b4b4684b3c89e305cc083e3f0a3 +Subproject commit c56d58822e6c581926ac765b7604b29e1ecdf557 diff --git a/tests/Makefile.am b/tests/Makefile.am index 750ca5af64..c4e4371db3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -152,6 +152,7 @@ MODFILES = \ discretionary_policy/Gali_2015_chapter_3.mod \ discretionary_policy/Gali_2015_chapter_3_nonlinear.mod \ histval_initval_file/ramst_initval_file.mod \ + histval_initval_file/ramst_initval_file_with_dseries.mod \ histval_initval_file/ramst_data_generate.mod \ histval_initval_file/ramst_datafile.mod \ histval_initval_file/sim_exo_lead_lag.mod \ diff --git a/tests/histval_initval_file/ramst_initval_file_with_dseries.mod b/tests/histval_initval_file/ramst_initval_file_with_dseries.mod new file mode 100644 index 0000000000..e777d091ac --- /dev/null +++ b/tests/histval_initval_file/ramst_initval_file_with_dseries.mod @@ -0,0 +1,36 @@ +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/c(-2))^(-gam) - (1+bet)^(-1)*(aa*alph*x(+2)*k^(alph-1) + 1 - delt)*(c(+1)/c(-1))^(-gam); +end; + +kstar = ((delt+bet)/(1.0*aa*alph))^(1/(alph-1)); +cstar = aa*kstar^alph-delt*kstar; + +initval; +x = 1; +k = kstar; +c = cstar; +end; + +steady; + +// Instantiate dseries object with paths for the endogenous and exogenous variables +baseline= dseries([.81*kstar, .81*cstar, .81; .9*kstar, .9*cstar, .9; repmat([kstar, cstar, 1], 998, 1)], 2000Q1, {'k', 'c', 'x'}); + +initval_file(series=baseline, first_simulation_period=2000Q3, last_simulation_period=2050Q2); + +perfect_foresight_setup; +perfect_foresight_solver; + +Simulated_time_series(2000Q3:2050Q2) diff --git a/tests/histval_initval_file_unit_tests.m b/tests/histval_initval_file_unit_tests.m index 34f558b6b3..e2f6e514ea 100644 --- a/tests/histval_initval_file_unit_tests.m +++ b/tests/histval_initval_file_unit_tests.m @@ -17,6 +17,7 @@ M.exo_nbr = 1; M.exo_names = {'Variable_4'}; M.exo_det_nbr = 0; M.orig_maximum_lag = 2; +M.orig_maximum_lead = 0; caller = 'INITVAL'; -- GitLab