diff --git a/src/DynareBison.yy b/src/DynareBison.yy index 8c29deb7a6db4b38cf5d87daf69b7a85f1c62558..7e21d57d89bbff0ec8c24bd89de8d72ca0570000 100644 --- a/src/DynareBison.yy +++ b/src/DynareBison.yy @@ -1282,6 +1282,9 @@ svar_options : o_coefficients mshocks : MSHOCKS ';' mshock_list END ';' { driver.end_mshocks(false); } | MSHOCKS '(' OVERWRITE ')' ';' mshock_list END ';' { driver.end_mshocks(true); } + | MSHOCKS '(' LEARNT_IN EQUAL INT_NUMBER ')' ';' mshock_list END ';' { driver.end_mshocks_learnt_in($5, false); } + | MSHOCKS '(' LEARNT_IN EQUAL INT_NUMBER COMMA OVERWRITE ')' ';' mshock_list END ';' { driver.end_mshocks_learnt_in($5, true); } + | MSHOCKS '(' OVERWRITE COMMA LEARNT_IN EQUAL INT_NUMBER ')' ';' mshock_list END ';' { driver.end_mshocks_learnt_in($7, true); } ; mshock_list : mshock_list det_shock_elem diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc index 0cbba3a386be9bfa54ae6e81cc6cbde03775968e..f8ce2cac1222c396f303b5e7c6dbc6a1935aa4a9 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -921,10 +921,11 @@ ParsingDriver::end_shocks_learnt_in(const string &learnt_in_period, bool overwri end_shocks(overwrite); return; } - for (auto &[symb_id, vals] : det_shocks) - for (auto [period1, period2, expr] : vals) - if (period1 < learnt_in_period_int) - error("shocks: for variable " + mod_file->symbol_table.getName(symb_id) + ", shock period (" + to_string(period1) + ") is earlier than the period in which the shock is learnt (" + learnt_in_period + ")"); + for (auto &storage : { det_shocks, learnt_shocks_add, learnt_shocks_multiply } ) + for (auto &[symb_id, vals] : storage) + for (auto [period1, period2, expr] : vals) + if (period1 < learnt_in_period_int) + error("shocks: for variable " + mod_file->symbol_table.getName(symb_id) + ", shock period (" + to_string(period1) + ") is earlier than the period in which the shock is learnt (" + learnt_in_period + ")"); // Aggregate the three types of shocks ShocksLearntInStatement::learnt_shocks_t learnt_shocks; @@ -958,6 +959,42 @@ ParsingDriver::end_shocks_learnt_in(const string &learnt_in_period, bool overwri learnt_shocks_multiply.clear(); } +void +ParsingDriver::end_mshocks_learnt_in(const string &learnt_in_period, bool overwrite) +{ + int learnt_in_period_int = stoi(learnt_in_period); + if (learnt_in_period_int < 1) + error("mshocks: value '" + learnt_in_period + "' is not allowed for 'learnt_in' option"); + if (learnt_in_period_int == 1) + { + end_mshocks(overwrite); + return; + } + + for (auto &[symb_id, vals] : det_shocks) + for (auto [period1, period2, expr] : vals) + if (period1 < learnt_in_period_int) + error("mshocks: for variable " + mod_file->symbol_table.getName(symb_id) + ", shock period (" + to_string(period1) + ") is earlier than the period in which the shock is learnt (" + learnt_in_period + ")"); + + ShocksLearntInStatement::learnt_shocks_t learnt_shocks; + for (const auto &[id, v] : det_shocks) + { + vector<tuple<ShocksLearntInStatement::LearntShockType, int, int, expr_t>> v2; + for (auto [period1, period2, value] : v) + v2.emplace_back(ShocksLearntInStatement::LearntShockType::multiplySteadyState, period1, period2, value); + learnt_shocks[id] = v2; + } + + mod_file->addStatement(make_unique<ShocksLearntInStatement>(learnt_in_period_int, overwrite, + move(learnt_shocks), + mod_file->symbol_table)); + det_shocks.clear(); + if (!learnt_shocks_add.empty()) + error("mshocks: 'add' keyword not allowed"); + if (!learnt_shocks_multiply.empty()) + error("mshocks: 'multiply' keyword not allowed"); +} + void ParsingDriver::end_heteroskedastic_shocks(bool overwrite) { diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index d1acbae22a3b8fcadab87402eea4bdcf40b8fb1e..7c6f71446fb9a082a928b1746959bb4f89f5d437 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -149,7 +149,7 @@ private: //! Temporary storage of covariances from optim_weights OptimWeightsStatement::covar_weights_t covar_weights; /* Temporary storage for deterministic shocks. Also used for - conditional_forecast paths, for shocks(surprise), and shocks(learnt_in=…) + conditional_forecast paths, for mshocks, shocks(surprise) and shocks(learnt_in=…) (for the latter, only used for shocks declared in level through “valuesâ€). */ ShocksStatement::det_shocks_t det_shocks; // Temporary storage for shocks declared with “add†and “multiply†in shocks(learnt_in=…) @@ -452,6 +452,8 @@ public: void end_shocks_surprise(bool overwrite); //! Writes a shocks(learnt_in=…) block void end_shocks_learnt_in(const string &learnt_in_period, bool overwrite); + //! Writes a mshocks(learnt_in=…) block + void end_mshocks_learnt_in(const string &learnt_in_period, bool overwrite); //! Writes a heteroskedastic_shocks statement void end_heteroskedastic_shocks(bool overwrite); /* Adds a deterministic shock, a path element inside a diff --git a/src/Shocks.cc b/src/Shocks.cc index 1204a0d7d8374ab9c58eddfecc3626f776f10236..3924c1a411e6c0c3c33ee4dfe1d6a9ea4772a580 100644 --- a/src/Shocks.cc +++ b/src/Shocks.cc @@ -524,6 +524,8 @@ ShocksLearntInStatement::typeToString(LearntShockType type) return "add"; case LearntShockType::multiply: return "multiply"; + case LearntShockType::multiplySteadyState: + return "multiply_steady_state"; } exit(EXIT_FAILURE); // Silence GCC warning } diff --git a/src/Shocks.hh b/src/Shocks.hh index 01114a165935e6328efadad3607ade7cee324a77..e5743d0220b7c79b714b0f971d6559cd93d24b30 100644 --- a/src/Shocks.hh +++ b/src/Shocks.hh @@ -106,20 +106,21 @@ public: void writeJsonOutput(ostream &output) const override; }; -/* Represents a shocks(learnt_in=…) block. - Given the differences with the plain “shocks†block, it was easier to make - it a separate class. */ +/* Represents a shocks(learnt_in=…) or mshocks(learnt_in=…) block. + Given the differences with the plain “shocks†and “mshocks†blocks, + it was easier to make it a separate class. */ class ShocksLearntInStatement : public Statement { public: const int learnt_in_period; - //! Does this "shocks(learnt_in=…)" statement replace the previous ones? + //! Does this “shocks(learnt_in=…)†or “mshocks(learnt_in=…)†block replace the previous ones? const bool overwrite; enum class LearntShockType { - level, - add, - multiply + level, // The value is the level of the exogenous (“values†statement in “shocks(learnt_in=…)â€) + add, // The value is the additive change of the exogenous compared to previous information period (“add†statement in “shocks(learnt_in=…)â€) + multiply, // The value is the multiplicative change of the exogenous compared to previous information period (“multiply†statement in “shocks(learnt_in=…)â€) + multiplySteadyState // The value is the ratio of the exogenous over its (terminal) steady state as anticipated in the same informational period (“values†statement in “mshocks(learnt_in=…)â€) }; // The tuple is (type, period1, period2, value) using learnt_shocks_t = map<int, vector<tuple<LearntShockType, int, int, expr_t>>>;