From b8c5dfa472d2c416089706a8c8210e13a4595730 Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Wed, 26 Oct 2016 18:19:33 +0200 Subject: [PATCH] VAR(p) forecast first draft, preprocessor for var command and backend for forecast --- matlab/var_forecast.m | 113 +++++++++++++++++++++++++++++++++ preprocessor/ComputingTasks.cc | 44 +++++++++++++ preprocessor/ComputingTasks.hh | 14 ++++ preprocessor/DynareBison.yy | 17 ++++- preprocessor/DynareFlex.ll | 2 + preprocessor/ModFile.cc | 3 + preprocessor/ParsingDriver.cc | 8 +++ preprocessor/ParsingDriver.hh | 2 + preprocessor/Statement.hh | 5 +- 9 files changed, 204 insertions(+), 4 deletions(-) create mode 100644 matlab/var_forecast.m diff --git a/matlab/var_forecast.m b/matlab/var_forecast.m new file mode 100644 index 000000000..51eee8394 --- /dev/null +++ b/matlab/var_forecast.m @@ -0,0 +1,113 @@ +function y = var_forecast(M_, options_, name, h, y, fcv) + +% name : filename +% M_ +% options_ +% name string name of var model, provided in var statement +% h int number of steps-ahead forecast +% y matrix rows: realizations of endogenous variables in declaration order; cols: realizations in t, t-1, t-2 ... order of VAR +% fcv string name of variable we want forecast for + +% returns the h-step-ahead VAR(order) forecast for fcv + +% example calling: +% In Matlab: +% >> coefficients{1} = [0.5000 0.1000; 0.4000 0.5000]; +% >> coefficients{2} = [0 0 ; 0.2500 0 ]; +% >> mu = [0.0200; 0.0300]; +% >> save('m1.mat', 'mu','coefficients'); + +% In .mod file: +% var a b c d; +% ... +% var(model_name=m1,order=2) a c; + +% From Matlab backend: +% >> yt = [0.0600; 33.0000; 0.0300; 22.0000]; +% >> ytm1 = [0.0550; 11.0000; 0.0300; 88.0000]; +% >> var_forecast(M_, options_, 'm1', 1, [yt ytm1]) +% >> var_forecast(M_, options_, 'm1', 2, [yt ytm1], ['a']) + +%% Find var in options_ +order = ''; +var_list = ''; +for i=1:length(options_.var) + if strcmp(options_.var(i).name, name) + order = options_.var(i).order; + var_list = options_.var(i).var_list_; + break; + end +end + +if isempty(order) + error([name ' not found in var specification declared in .mod file']); +end + +%% construct y +assert(length(y) == length(M_.endo_names)); +endo_names = cellstr(M_.endo_names); +yidx = zeros(size(endo_names)); +for i=1:length(var_list) + yidx = yidx | strcmp(strtrim(var_list(i,:)), endo_names); +end +y = y(yidx,:); + +if nargin == 6 + fvidx = strcmp(fcv, endo_names); +end + +%% load .mat file and rewrite as VAR(1) +load(name, 'coefficients', 'mu'); +if ~exist('coefficients', 'var') || ~exist('mu', 'var') + error([name ' : must contain the variables coefficients and mu']); +end +assert(h >= 1); + +lm = length(mu); +lc = length(coefficients); +assert(lc == order); +if size(y,1) ~= lm || size(y,2) ~= order + error('The dimensions of y are not correct. It should be an nvars x order matrix'); +end + +A = zeros(lm*lc, lm*lc); +for i=1:lc + if any([lm lm] ~= size(coefficients{i})) + error('The dimensions of mu and coefficients are off'); + end + col = lm*(i-1)+1:lm*i; + A(1:lm, col) = coefficients{i}; + if i ~= lc + A(lm*i+1:lm*i+lm, col) = eye(lm, lm); + end +end + +mu = [mu; zeros(lm,1)]; + +%% Calculate Forecast +% New Introduction to Multiple Time Series Analysis +% Helmut Lutkepohl +% page 34 +% +% An = eye(size(A)); +% for i=1:h-1 +% An = An + A^i; +% end +% y = An*mu + A^h*y(:); + +for i=1:h + y = mu + A*y(:); +end +y = y(1:lm); + +if nargin == 6 + retidx = find(fvidx & yidx == 1); + if isempty(retidx) + return; + elseif retidx == 1 + y = y(1); + else + y = y(sum(yidx(1:retidx-1))+1); + end +end +end \ No newline at end of file diff --git a/preprocessor/ComputingTasks.cc b/preprocessor/ComputingTasks.cc index cfc3b59b5..81ce4cf9d 100644 --- a/preprocessor/ComputingTasks.cc +++ b/preprocessor/ComputingTasks.cc @@ -171,6 +171,50 @@ PriorPosteriorFunctionStatement::writeOutput(ostream &output, const string &base << "'" << type << "');" << endl; } +VARStatement::VARStatement(const SymbolList &symbol_list_arg, + const OptionsList &options_list_arg, + const SymbolTable &symbol_table_arg) : + symbol_list(symbol_list_arg), + options_list(options_list_arg), + symbol_table(symbol_table_arg) +{ +} + +void +VARStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) +{ + mod_file_struct.var_model_present = true; + vector symbols = symbol_list.get_symbols(); + for (vector::const_iterator it = symbols.begin(); it != symbols.end(); it++) + if (symbol_table.getType(*it) != eEndogenous) + { + cerr << "ERROR: You can only run VARs on endogenous variables." << endl; + exit(EXIT_FAILURE); + } + + OptionsList::num_options_t::const_iterator it = options_list.num_options.find("var(varidx).order"); + if (it == options_list.num_options.end()) + { + cerr << "ERROR: You must provide the order option to the var command." << endl; + exit(EXIT_FAILURE); + } + + OptionsList::string_options_t::const_iterator it1 = options_list.string_options.find("var(varidx).name"); + if (it1 == options_list.string_options.end()) + { + cerr << "ERROR: You must provide the model_name option to the var command." << endl; + exit(EXIT_FAILURE); + } +} + +void +VARStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const +{ + options_list.writeOutput(output); + symbol_list.writeOutput("options_.var(varidx).var_list_", output); + output << "varidx = varidx + 1;" << endl; +} + StochSimulStatement::StochSimulStatement(const SymbolList &symbol_list_arg, const OptionsList &options_list_arg) : symbol_list(symbol_list_arg), diff --git a/preprocessor/ComputingTasks.hh b/preprocessor/ComputingTasks.hh index e74211f78..d9a0c536d 100644 --- a/preprocessor/ComputingTasks.hh +++ b/preprocessor/ComputingTasks.hh @@ -110,6 +110,20 @@ public: virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const; }; +class VARStatement : public Statement +{ +private: + const SymbolList symbol_list; + const OptionsList options_list; + const SymbolTable &symbol_table; +public: + VARStatement(const SymbolList &symbol_list_arg, + const OptionsList &options_list_arg, + const SymbolTable &symbol_table_arg); + virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings); + virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const; +}; + class ForecastStatement : public Statement { private: diff --git a/preprocessor/DynareBison.yy b/preprocessor/DynareBison.yy index ebe98d143..3e23212b6 100644 --- a/preprocessor/DynareBison.yy +++ b/preprocessor/DynareBison.yy @@ -115,7 +115,7 @@ class ParsingDriver; %token NAME %token USE_PENALIZED_OBJECTIVE_FOR_HESSIAN INIT_STATE %token NAN_CONSTANT NO_STATIC NOBS NOCONSTANT NODISPLAY NOCORR NODIAGNOSTIC NOFUNCTIONS NO_HOMOTOPY -%token NOGRAPH POSTERIOR_NOGRAPH POSTERIOR_GRAPH NOMOMENTS NOPRINT NORMAL_PDF SAVE_DRAWS +%token NOGRAPH POSTERIOR_NOGRAPH POSTERIOR_GRAPH NOMOMENTS NOPRINT NORMAL_PDF SAVE_DRAWS MODEL_NAME %token OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS MAX_DIM_COVA_GROUP ADVANCED OUTFILE OUTVARS OVERWRITE %token PARALLEL_LOCAL_FILES PARAMETERS PARAMETER_SET PARTIAL_INFORMATION PERIODS PERIOD PLANNER_OBJECTIVE PLOT_CONDITIONAL_FORECAST PLOT_PRIORS PREFILTER PRESAMPLE %token PERFECT_FORESIGHT_SETUP PERFECT_FORESIGHT_SOLVER NO_POSTERIOR_KERNEL_DENSITY FUNCTION @@ -131,7 +131,7 @@ class ParsingDriver; %token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL USEAUTOCORR GSA_SAMPLE_FILE USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED %token VALUES VAR VAREXO VAREXO_DET VAROBS VAREXOBS PREDETERMINED_VARIABLES %token WRITE_LATEX_DYNAMIC_MODEL WRITE_LATEX_STATIC_MODEL WRITE_LATEX_ORIGINAL_MODEL -%token XLS_SHEET XLS_RANGE LMMCP OCCBIN BANDPASS_FILTER COLORMAP +%token XLS_SHEET XLS_RANGE LMMCP OCCBIN BANDPASS_FILTER COLORMAP VAR_MODEL %left COMMA %left EQUAL_EQUAL EXCLAMATION_EQUAL %left LESS GREATER LESS_EQUAL GREATER_EQUAL @@ -224,6 +224,7 @@ statement : parameters | estimated_params_init | set_time | data + | var_model | prior | prior_eq | subsamples @@ -346,6 +347,16 @@ var : VAR var_list ';' { driver.end_nonstationary_var(true, $6); } ; +var_model : VAR '(' var_model_options_list ')' symbol_list ';' { driver.var_model(); } ; + +var_model_options_list : var_model_options_list COMMA var_model_options + | var_model_options + ; + +var_model_options : o_var_name + | o_var_order + ; + nonstationary_var_list : nonstationary_var_list symbol { driver.declare_nonstationary_var($2); } | nonstationary_var_list COMMA symbol @@ -2816,6 +2827,8 @@ o_simul_seed : SIMUL_SEED EQUAL INT_NUMBER { driver.error("'simul_seed' option i o_qz_criterium : QZ_CRITERIUM EQUAL non_negative_number { driver.option_num("qz_criterium", $3); }; o_qz_zero_threshold : QZ_ZERO_THRESHOLD EQUAL non_negative_number { driver.option_num("qz_zero_threshold", $3); }; o_file : FILE EQUAL filename { driver.option_str("file", $3); }; +o_var_name : MODEL_NAME EQUAL symbol { driver.option_str("var(varidx).name", $3); }; +o_var_order : ORDER EQUAL INT_NUMBER { driver.option_num("var(varidx).order", $3); }; o_series : SERIES EQUAL symbol { driver.option_str("series", $3); }; o_datafile : DATAFILE EQUAL filename { driver.option_str("datafile", $3); }; o_dirname : DIRNAME EQUAL filename { driver.option_str("dirname", $3); }; diff --git a/preprocessor/DynareFlex.ll b/preprocessor/DynareFlex.ll index 38055136c..f8a462924 100644 --- a/preprocessor/DynareFlex.ll +++ b/preprocessor/DynareFlex.ll @@ -136,6 +136,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 check {BEGIN DYNARE_STATEMENT; return token::CHECK;} simul {BEGIN DYNARE_STATEMENT; return token::SIMUL;} stoch_simul {BEGIN DYNARE_STATEMENT; return token::STOCH_SIMUL;} +var_model {BEGIN DYNARE_STATEMENT; return token::VAR_MODEL;} dsample {BEGIN DYNARE_STATEMENT; return token::DSAMPLE;} Sigma_e {BEGIN DYNARE_STATEMENT; sigma_e = 1; return token::SIGMA_E;} planner_objective {BEGIN DYNARE_STATEMENT; return token::PLANNER_OBJECTIVE;} @@ -331,6 +332,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 nocorr {return token::NOCORR;} optim {return token::OPTIM;} periods {return token::PERIODS;} +model_name {return token::MODEL_NAME;} endogenous_terminal_period {return token::ENDOGENOUS_TERMINAL_PERIOD;} sub_draws {return token::SUB_DRAWS;} minimal_solving_periods {return token::MINIMAL_SOLVING_PERIODS;} diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc index 5719d0197..1b114d1e0 100644 --- a/preprocessor/ModFile.cc +++ b/preprocessor/ModFile.cc @@ -808,6 +808,9 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo static_model.writeOutput(mOutputFile, block); } + if (mod_file_struct.var_model_present) + mOutputFile << "varidx = 1;" << endl; + // Print statements for (vector::const_iterator it = statements.begin(); it != statements.end(); it++) diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc index 7d7c99b48..4fdf1396a 100644 --- a/preprocessor/ParsingDriver.cc +++ b/preprocessor/ParsingDriver.cc @@ -1279,6 +1279,14 @@ ParsingDriver::stoch_simul() options_list.clear(); } +void +ParsingDriver::var_model() +{ + mod_file->addStatement(new VARStatement(symbol_list, options_list, mod_file->symbol_table)); + symbol_list.clear(); + options_list.clear(); +} + void ParsingDriver::simul() { diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh index a9f731c3f..04d7291af 100644 --- a/preprocessor/ParsingDriver.hh +++ b/preprocessor/ParsingDriver.hh @@ -418,6 +418,8 @@ public: void rplot(); //! Writes a stock_simul command void stoch_simul(); + //! Writes a var (vector autoregression) command + void var_model(); //! Writes a simul command void simul(); //! Writes check command diff --git a/preprocessor/Statement.hh b/preprocessor/Statement.hh index 311260b0e..1676ff313 100644 --- a/preprocessor/Statement.hh +++ b/preprocessor/Statement.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2015 Dynare Team + * Copyright (C) 2006-2016 Dynare Team * * This file is part of Dynare. * @@ -122,7 +122,8 @@ public: int orig_eq_nbr; //! Stores the number of equations added to the Ramsey model int ramsey_eq_nbr; - + //! Whether a VAR statement is present + bool var_model_present; }; class Statement