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