diff --git a/src/CodeInterpreter.hh b/src/CodeInterpreter.hh
index 2f933be52ba70d886700f14e4ef4b37744e5900f..207ae356f165788c233e0fb03f4d928c396555c4 100644
--- a/src/CodeInterpreter.hh
+++ b/src/CodeInterpreter.hh
@@ -152,7 +152,10 @@ enum class SymbolType
     statementDeclaredVariable = 14, //!< Local variable assigned within a Statement (see subsample statement for example)
     logTrend = 15,                 //!< Log-trend variable
     unusedEndogenous = 16,
-    endogenousVAR = 17             //!< Variables declared in a var_model statement
+    endogenousVAR = 17,            //!< Variables declared in a var_model statement
+    endogenousEpilogue = 18,       //!< Endogenous Variables used in the epilogue block
+    exogenousEpilogue = 19,        //!< Variables used in the epilogue block
+    parameterEpilogue = 20         //!< Variables used in the epilogue block
   };
 
 enum ExpressionType
diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh
index 7fc05721e52a1417690bf366f4044bc6f7b5cb0a..be6c5d1a6e3674e9e12defa3be8aa79742a18264 100644
--- a/src/ComputingTasks.hh
+++ b/src/ComputingTasks.hh
@@ -27,7 +27,7 @@
 #include "Statement.hh"
 #include "StaticModel.hh"
 #include "DynamicModel.hh"
-#include "SteadyStateModel.hh"
+#include "ModelEquationBlock.hh"
 
 class SteadyStatement : public Statement
 {
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 6093bc7a768816e351ab31b65df8497e21ae5cb3..90685fa94b9f39c865a0931b0ff8150c3ac65b07 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -148,7 +148,7 @@ class ParsingDriver;
 %token SBVAR TREND_VAR DEFLATOR GROWTH_FACTOR MS_IRF MS_VARIANCE_DECOMPOSITION GROWTH
 %token MS_ESTIMATION MS_SIMULATION MS_COMPUTE_MDD MS_COMPUTE_PROBABILITIES MS_FORECAST
 %token SVAR_IDENTIFICATION EQUATION EXCLUSION LAG UPPER_CHOLESKY LOWER_CHOLESKY MONTHLY QUARTERLY
-%token MARKOV_SWITCHING CHAIN DURATION NUMBER_OF_REGIMES NUMBER_OF_LAGS
+%token MARKOV_SWITCHING CHAIN DURATION NUMBER_OF_REGIMES NUMBER_OF_LAGS EPILOGUE
 %token SVAR SVAR_GLOBAL_IDENTIFICATION_CHECK COEFF COEFFICIENTS VARIANCES CONSTANTS EQUATIONS
 %token EXTERNAL_FUNCTION EXT_FUNC_NAME EXT_FUNC_NARGS FIRST_DERIV_PROVIDED SECOND_DERIV_PROVIDED
 %token SELECTED_VARIABLES_ONLY COVA_COMPUTE SIMULATION_FILE_TAG FILE_TAG
@@ -221,6 +221,7 @@ statement : parameters
           | estimated_params_init
           | set_time
           | data
+          | epilogue
           | var_model
           | pac_model
           | trend_component_model
@@ -348,6 +349,7 @@ log_trend_var_list : log_trend_var_list symbol
                    ;
 
 var : VAR var_list ';'
+    | VAR '(' EPILOGUE ')' epilogue_var_list ';'
     | VAR '(' DEFLATOR EQUAL { driver.begin_trend(); } hand_side ')' nonstationary_var_list ';'
       { driver.end_nonstationary_var(false, $6); }
     | VAR '(' LOG_DEFLATOR EQUAL { driver.begin_trend(); } hand_side ')' nonstationary_var_list ';'
@@ -537,13 +539,17 @@ nonstationary_var_list : nonstationary_var_list symbol
                          { driver.declare_nonstationary_var($1, $2, $3); }
                        ;
 
-varexo : VAREXO varexo_list ';';
+varexo : VAREXO varexo_list ';'
+       | VAREXO '(' EPILOGUE ')' epilogue_varexo_list ';'
+       ;
 
 varexo_det : VAREXO_DET varexo_det_list ';';
 
 predetermined_variables : PREDETERMINED_VARIABLES predetermined_variables_list ';';
 
 parameters : PARAMETERS parameter_list ';';
+           | PARAMETERS '(' EPILOGUE ')' epilogue_parameter_list ';';
+           ;
 
 model_local_variable : MODEL_LOCAL_VARIABLE model_local_variable_list ';';
 
@@ -598,6 +604,32 @@ var_list : var_list symbol
            { driver.declare_endogenous($1, $2, $3); }
          ;
 
+epilogue_var_list : epilogue_var_list symbol
+                    { driver.declare_epilogue_endogenous($2); }
+                  | epilogue_var_list COMMA symbol
+                    { driver.declare_epilogue_endogenous($3); }
+                  | symbol
+                    { driver.declare_epilogue_endogenous($1); }
+                  | epilogue_var_list symbol named_var
+                    { driver.declare_epilogue_endogenous($2, "", $3); }
+                  | epilogue_var_list COMMA symbol named_var
+                    { driver.declare_epilogue_endogenous($3, "", $4); }
+                  | symbol named_var
+                    { driver.declare_epilogue_endogenous($1, "", $2); }
+                  | epilogue_var_list symbol TEX_NAME
+                    { driver.declare_epilogue_endogenous($2, $3); }
+                  | epilogue_var_list COMMA symbol TEX_NAME
+                    { driver.declare_epilogue_endogenous($3, $4); }
+                  | symbol TEX_NAME
+                    { driver.declare_epilogue_endogenous($1, $2); }
+                  | epilogue_var_list symbol TEX_NAME named_var
+                    { driver.declare_epilogue_endogenous($2, $3, $4); }
+                  | epilogue_var_list COMMA symbol TEX_NAME named_var
+                    { driver.declare_epilogue_endogenous($3, $4, $5); }
+                  | symbol TEX_NAME named_var
+                    { driver.declare_epilogue_endogenous($1, $2, $3); }
+                  ;
+
 varexo_list : varexo_list symbol
               { driver.declare_exogenous($2); }
             | varexo_list COMMA symbol
@@ -650,6 +682,32 @@ varexo_det_list : varexo_det_list symbol
                    { driver.declare_exogenous_det($1, $2, $3); }
                 ;
 
+epilogue_varexo_list : epilogue_varexo_list symbol
+                       { driver.declare_epilogue_exogenous($2); }
+                     | epilogue_varexo_list COMMA symbol
+                       { driver.declare_epilogue_exogenous($3); }
+                     | symbol
+                       { driver.declare_epilogue_exogenous($1); }
+                     | epilogue_varexo_list symbol named_var
+                       { driver.declare_epilogue_exogenous($2, "", $3); }
+                     | epilogue_varexo_list COMMA symbol named_var
+                       { driver.declare_epilogue_exogenous($3, "", $4); }
+                     | symbol named_var
+                       { driver.declare_epilogue_exogenous($1, "", $2); }
+                     | epilogue_varexo_list symbol TEX_NAME
+                       { driver.declare_epilogue_exogenous($2, $3); }
+                     | epilogue_varexo_list COMMA symbol TEX_NAME
+                       { driver.declare_epilogue_exogenous($3, $4); }
+                     | symbol TEX_NAME
+                       { driver.declare_epilogue_exogenous($1, $2); }
+                     | epilogue_varexo_list symbol TEX_NAME named_var
+                       { driver.declare_epilogue_exogenous($2, $3, $4); }
+                     | epilogue_varexo_list COMMA symbol TEX_NAME named_var
+                       { driver.declare_epilogue_exogenous($3, $4, $5); }
+                     | symbol TEX_NAME named_var
+                       { driver.declare_epilogue_exogenous($1, $2, $3); }
+                     ;
+
 parameter_list : parameter_list symbol
                  { driver.declare_parameter($2); }
                | parameter_list COMMA symbol
@@ -676,6 +734,32 @@ parameter_list : parameter_list symbol
                  { driver.declare_parameter($1, $2, $3); }
                ;
 
+epilogue_parameter_list : epilogue_parameter_list symbol
+                          { driver.declare_parameter($2); }
+                        | epilogue_parameter_list COMMA symbol
+                          { driver.declare_parameter($3); }
+                        | symbol
+                          { driver.declare_parameter($1); }
+                        | epilogue_parameter_list symbol named_var
+                          { driver.declare_parameter($2, "", $3); }
+                        | epilogue_parameter_list COMMA symbol named_var
+                          { driver.declare_parameter($3, "", $4); }
+                        | symbol named_var
+                          { driver.declare_parameter($1, "", $2); }
+                        | epilogue_parameter_list symbol TEX_NAME
+                          { driver.declare_parameter($2, $3); }
+                        | epilogue_parameter_list COMMA symbol TEX_NAME
+                          { driver.declare_parameter($3, $4); }
+                        | symbol TEX_NAME
+                          { driver.declare_parameter($1, $2); }
+                        | epilogue_parameter_list symbol TEX_NAME named_var
+                          { driver.declare_parameter($2, $3, $4); }
+                        | epilogue_parameter_list COMMA symbol TEX_NAME named_var
+                          { driver.declare_parameter($3, $4, $5); }
+                        | symbol TEX_NAME named_var
+                          { driver.declare_parameter($1, $2, $3); }
+                        ;
+
 predetermined_variables_list : predetermined_variables_list symbol
                                { driver.add_predetermined_variable($2); }
                              | predetermined_variables_list COMMA symbol
@@ -864,6 +948,18 @@ histval_file : HISTVAL_FILE '(' FILENAME EQUAL filename ')' ';'
                { driver.histval_file($5); }
              ;
 
+epilogue : EPILOGUE ';' { driver.begin_epilogue(); }
+           epilogue_equation_list END ';' { driver.end_epilogue(); }
+         ;
+
+epilogue_equation_list : epilogue_equation_list epilogue_equation
+                       | epilogue_equation
+                       ;
+
+epilogue_equation : symbol EQUAL expression ';'
+                    { driver.add_epilogue_equal($1, $3); }
+                  ;
+
 model_options : BLOCK { driver.block(); }
               | o_cutoff
 							| o_mfs
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index 817a83fa415e0ab468728b61416fa34d3051c9ec..9869e1bb83ff2c787c91a37703ab4e3d5b50dcd9 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -204,6 +204,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
 <INITIAL>shock_groups {BEGIN DYNARE_BLOCK; return token::SHOCK_GROUPS;}
 <INITIAL>mshocks {BEGIN DYNARE_BLOCK; return token::MSHOCKS;}
 <INITIAL>estimated_params {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS;}
+<INITIAL>epilogue {BEGIN DYNARE_BLOCK; return token::EPILOGUE;}
  /* priors is an alias for estimated_params */
 <INITIAL>priors {BEGIN DYNARE_BLOCK;return token::ESTIMATED_PARAMS;}
 <INITIAL>estimated_params_init 		{BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_INIT;}
@@ -629,6 +630,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
 <DYNARE_STATEMENT>save_draws {return token::SAVE_DRAWS; }
 <DYNARE_STATEMENT>deflator {return token::DEFLATOR;}
 <DYNARE_STATEMENT>log_deflator {return token::LOG_DEFLATOR;}
+<DYNARE_STATEMENT>epilogue {return token::EPILOGUE;}
 <DYNARE_STATEMENT>growth_factor {return token::GROWTH_FACTOR;}
 <DYNARE_STATEMENT>log_growth_factor {return token::LOG_GROWTH_FACTOR;}
 <DYNARE_STATEMENT>growth {return token::GROWTH;}
diff --git a/src/ExprNode.cc b/src/ExprNode.cc
index 10c4737376c1dea56e197ff5c268c6c02c583697..80ca2741b22c2283d41870b5be8b97de927f1247 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -748,6 +748,9 @@ VariableNode::prepareForDerivation()
       break;
     case SymbolType::externalFunction:
     case SymbolType::endogenousVAR:
+    case SymbolType::endogenousEpilogue:
+    case SymbolType::exogenousEpilogue:
+    case SymbolType::parameterEpilogue:
       cerr << "VariableNode::prepareForDerivation: impossible case" << endl;
       exit(EXIT_FAILURE);
     }
@@ -781,7 +784,10 @@ VariableNode::computeDerivative(int deriv_id)
       exit(EXIT_FAILURE);
     case SymbolType::externalFunction:
     case SymbolType::endogenousVAR:
-      cerr << "Impossible case!" << endl;
+    case SymbolType::endogenousEpilogue:
+    case SymbolType::exogenousEpilogue:
+    case SymbolType::parameterEpilogue:
+      cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
       exit(EXIT_FAILURE);
     }
   // Suppress GCC warning
@@ -857,6 +863,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
   switch (type)
     {
     case SymbolType::parameter:
+    case SymbolType::parameterEpilogue:
       if (output_type == oMatlabOutsideModel)
         output << "M_.params" << "(" << tsid + 1 << ")";
       else
@@ -927,6 +934,13 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
           if (lag != 0)
             output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
           break;
+        case oEpilogueFile:
+          output << datatree.symbol_table.getName(symb_id)
+                 << LEFT_ARRAY_SUBSCRIPT(output_type) << "epilogue_it__";
+          if (lag != 0)
+            output << lag;
+          output << RIGHT_ARRAY_SUBSCRIPT(output_type);
+          break;
         default:
           cerr << "VariableNode::writeOutput: should not reach this point" << endl;
           exit(EXIT_FAILURE);
@@ -980,6 +994,13 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
           if (lag != 0)
             output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
           break;
+        case oEpilogueFile:
+          output << datatree.symbol_table.getName(symb_id)
+                 << LEFT_ARRAY_SUBSCRIPT(output_type) << "epilogue_it__";
+          if (lag != 0)
+            output << lag;
+          output << RIGHT_ARRAY_SUBSCRIPT(output_type);
+          break;
         default:
           cerr << "VariableNode::writeOutput: should not reach this point" << endl;
           exit(EXIT_FAILURE);
@@ -1033,19 +1054,33 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
           if (lag != 0)
             output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
           break;
+        case oEpilogueFile:
+          output << datatree.symbol_table.getName(symb_id)
+                 << LEFT_ARRAY_SUBSCRIPT(output_type) << "epilogue_it__";
+          if (lag != 0)
+            output << lag;
+          output << RIGHT_ARRAY_SUBSCRIPT(output_type);
+          break;
         default:
           cerr << "VariableNode::writeOutput: should not reach this point" << endl;
           exit(EXIT_FAILURE);
         }
       break;
-
+    case SymbolType::endogenousEpilogue:
+    case SymbolType::exogenousEpilogue:
+      output << datatree.symbol_table.getName(symb_id)
+             << LEFT_ARRAY_SUBSCRIPT(output_type) << "epilogue_it__";
+      if (lag != 0)
+        output << lag;
+      output << RIGHT_ARRAY_SUBSCRIPT(output_type);
+      break;
     case SymbolType::externalFunction:
     case SymbolType::trend:
     case SymbolType::logTrend:
     case SymbolType::statementDeclaredVariable:
     case SymbolType::unusedEndogenous:
     case SymbolType::endogenousVAR:
-      cerr << "Impossible case" << endl;
+      cerr << "VariableNode::writeOutput: Impossible case" << endl;
       exit(EXIT_FAILURE);
     }
 }
@@ -1264,7 +1299,10 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur
       exit(EXIT_FAILURE);
     case SymbolType::externalFunction:
     case SymbolType::endogenousVAR:
-      cerr << "Impossible case!" << endl;
+    case SymbolType::endogenousEpilogue:
+    case SymbolType::exogenousEpilogue:
+    case SymbolType::parameterEpilogue:
+      cerr << "VariableNode::getChainRuleDerivative: Impossible case" << endl;
       exit(EXIT_FAILURE);
     }
   // Suppress GCC warning
@@ -1302,6 +1340,9 @@ VariableNode::computeXrefs(EquationInfo &ei) const
     case SymbolType::unusedEndogenous:
     case SymbolType::externalFunction:
     case SymbolType::endogenousVAR:
+    case SymbolType::endogenousEpilogue:
+    case SymbolType::exogenousEpilogue:
+    case SymbolType::parameterEpilogue:
       break;
     }
 }
@@ -6705,6 +6746,7 @@ AbstractExternalFunctionNode::getIndxInTefTerms(int the_symb_id, const deriv_nod
   auto it = tef_terms.find({ the_symb_id, arguments });
   if (it != tef_terms.end())
     return it->second;
+  cout << endl << endl << tef_terms.size() <<  "." <<the_symb_id << endl << endl;
   throw UnknownFunctionNameAndArgs();
 }
 
diff --git a/src/ExprNode.hh b/src/ExprNode.hh
index d77f9a6fc380e17223c97c4c3eb7e1289d3aea75..a519d88afbd8451a0ab5d38a405d6736c36e3791 100644
--- a/src/ExprNode.hh
+++ b/src/ExprNode.hh
@@ -87,7 +87,8 @@ enum ExprNodeOutputType
     oJuliaDynamicSteadyStateOperator,             //!< Julia code, dynamic model, inside a steady state operator
     oSteadyStateFile,                             //!< Matlab code, in the generated steady state file
     oJuliaSteadyStateFile,                        //!< Julia code, in the generated steady state file
-    oMatlabDseries                                //!< Matlab code for dseries
+    oMatlabDseries,                               //!< Matlab code for dseries
+    oEpilogueFile                                 //!< Matlab code, in the generated epilogue file
   };
 
 #define IS_MATLAB(output_type) ((output_type) == oMatlabStaticModel     \
@@ -98,7 +99,8 @@ enum ExprNodeOutputType
                                 || (output_type) == oMatlabDynamicSteadyStateOperator \
                                 || (output_type) == oMatlabDynamicSparseSteadyStateOperator \
                                 || (output_type) == oSteadyStateFile \
-                                || (output_type) == oMatlabDseries)
+                                || (output_type) == oMatlabDseries \
+                                || (output_type) == oEpilogueFile)
 
 #define IS_JULIA(output_type) ((output_type) == oJuliaStaticModel       \
                                || (output_type) == oJuliaDynamicModel   \
diff --git a/src/Makefile.am b/src/Makefile.am
index 4fea410466b4da34fcf953568b5006d44183f6cd..1756b9212f179f58fe26c7670887fcf148c11486 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -48,8 +48,8 @@ dynare_m_SOURCES = \
 	CodeInterpreter.hh \
 	ExternalFunctionsTable.cc \
 	ExternalFunctionsTable.hh \
-	SteadyStateModel.hh \
-	SteadyStateModel.cc \
+	ModelEquationBlock.hh \
+	ModelEquationBlock.cc \
 	WarningConsolidation.hh \
 	WarningConsolidation.cc \
 	ExtendedPreprocessorTypes.hh \
diff --git a/src/ModFile.cc b/src/ModFile.cc
index e7183d5d1fa7109471d04e549135d1d0cd66ba26..7c97f03262ab11e683d1f63ad28b333301920c7a 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -44,6 +44,8 @@ ModFile::ModFile(WarningConsolidation &warnings_arg)
                                        trend_component_model_table, var_model_table),
     orig_ramsey_dynamic_model(symbol_table, num_constants, external_functions_table,
                               trend_component_model_table, var_model_table),
+    epilogue(symbol_table, num_constants, external_functions_table,
+             trend_component_model_table, var_model_table),
     static_model(symbol_table, num_constants, external_functions_table,
                  trend_component_model_table, var_model_table),
     steady_state_model(symbol_table, num_constants, external_functions_table,
@@ -127,6 +129,9 @@ ModFile::checkPass(bool nostrict, bool stochastic)
   // Check the steady state block
   steady_state_model.checkPass(mod_file_struct, warnings);
 
+  // Check epilogue block
+  epilogue.checkPass(warnings);
+
   if (mod_file_struct.write_latex_steady_state_model_present &&
       !mod_file_struct.steady_state_model_present)
     {
@@ -767,6 +772,8 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_deri
 
   for (auto & statement : statements)
     statement->computingPass();
+
+  epilogue.computingPass(true, true, false, 0, global_eval_context, true, false, false, false, true);
 }
 
 void
@@ -1074,6 +1081,9 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
 
       // Create steady state file
       steady_state_model.writeSteadyStateFile(basename, mod_file_struct.ramsey_model_present, false);
+
+      // Create epilogue file
+      epilogue.writeEpilogueFile(basename);
     }
 
   if (!nopreprocessoroutput)
diff --git a/src/ModFile.hh b/src/ModFile.hh
index 6b6d9c82083ffb352bf769b35538fbae992a7647..4e696e6164ad9e4947f6b1ce4a19f813d136f2dc 100644
--- a/src/ModFile.hh
+++ b/src/ModFile.hh
@@ -32,7 +32,7 @@ using namespace std;
 #include "NumericalInitialization.hh"
 #include "StaticModel.hh"
 #include "DynamicModel.hh"
-#include "SteadyStateModel.hh"
+#include "ModelEquationBlock.hh"
 #include "Statement.hh"
 #include "ExternalFunctionsTable.hh"
 #include "ConfigFile.hh"
@@ -68,6 +68,8 @@ public:
   DynamicModel ramsey_FOC_equations_dynamic_model;
   //! A copy of the original model, used to test model linearity under ramsey problem
   DynamicModel orig_ramsey_dynamic_model;
+  //! Epilogue model, as declared in the "epilogue" block
+  Epilogue epilogue;
   //! Static model, as derived from the "model" block when leads and lags have been removed
   StaticModel static_model;
   //! Static model, as declared in the "steady_state_model" block if present
diff --git a/src/SteadyStateModel.cc b/src/ModelEquationBlock.cc
similarity index 70%
rename from src/SteadyStateModel.cc
rename to src/ModelEquationBlock.cc
index 4b97d953f73a8f645016193447524cb324fe0910..5edeab5e16ff925c2f0b3e8050fef26a3f701c2b 100644
--- a/src/SteadyStateModel.cc
+++ b/src/ModelEquationBlock.cc
@@ -20,7 +20,7 @@
 #include <cassert>
 #include <algorithm>
 
-#include "SteadyStateModel.hh"
+#include "ModelEquationBlock.hh"
 
 SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg,
                                    NumericalConstants &num_constants_arg,
@@ -269,3 +269,109 @@ SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComput
 
   output << "]}";
 }
+
+Epilogue::Epilogue(SymbolTable &symbol_table_arg,
+                   NumericalConstants &num_constants_arg,
+                   ExternalFunctionsTable &external_functions_table_arg,
+                   TrendComponentModelTable &trend_component_model_table_arg,
+                   VarModelTable &var_model_table_arg) :
+  DynamicModel(symbol_table_arg, num_constants_arg, external_functions_table_arg,
+               trend_component_model_table_arg, var_model_table_arg)
+{
+}
+
+void
+Epilogue::addDefinition(int symb_id, expr_t expr)
+{
+  AddVariable(symb_id); // Create the variable node to be used in write method
+  def_table.emplace_back(symb_id, expr);
+  endogs.emplace(symb_id);
+  expr->collectVariables(SymbolType::endogenous, exogs);
+  expr->collectVariables(SymbolType::exogenous, exogs);
+  expr->collectVariables(SymbolType::endogenousEpilogue, exogs);
+  expr->collectVariables(SymbolType::exogenousEpilogue, exogs);
+  for (auto it : endogs)
+    exogs.erase(it);
+}
+
+void
+Epilogue::checkPass(WarningConsolidation &warnings) const
+{
+  if (def_table.size() == 0)
+    return;
+
+  vector<int> so_far_defined;
+  for (const auto & it : def_table)
+    {
+      if (find(so_far_defined.begin(), so_far_defined.end(), it.first) != so_far_defined.end())
+        {
+          cerr << "WARNING: in the 'epilogue' block, variable '" << symbol_table.getName(it.first)
+               << "' is declared twice" << endl;
+          exit(EXIT_FAILURE);
+        }
+      so_far_defined.push_back(it.first);
+    }
+}
+
+void
+Epilogue::writeEpilogueFile(const string &basename) const
+{
+  if (def_table.size() == 0)
+    return;
+
+  string filename = packageDir(basename) + "/epilogue.m";
+  ofstream output;
+  output.open(filename, ios::out | ios::binary);
+  if (!output.is_open())
+    {
+      cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  ExprNodeOutputType output_type = oEpilogueFile;
+  output << "function ds = epilogue(params, ds)" << endl
+         << "% function ds = epilogue(params, ds)" << endl
+         << "% Epilogue file generated by Dynare preprocessor" << endl << endl
+         << "epilogue_ds_first_date__ = ds.firstdate;" << endl
+         << "epilogue_loop_begin_idx__ = lastdate(ds) - ds.lastobservedperiod;" << endl
+         << "epilogue_loop_end_idx__ = lastdate(ds) - firstdate(ds) + 1;" << endl << endl;
+
+  output << "% endogenous" << endl;
+  for (auto symb_id : endogs)
+    output << symbol_table.getName(symb_id) << " = ds." << symbol_table.getName(symb_id) << ".data;" << endl;
+  output << endl
+         << "% exogenous" << endl;
+  for (auto symb_id : exogs)
+    output << symbol_table.getName(symb_id) << " = ds." << symbol_table.getName(symb_id) << ".data;" << endl;
+  output << endl
+         << "for epilogue_it__ = epilogue_loop_begin_idx__::epilogue_loop_end_idx__" << endl;
+
+  deriv_node_temp_terms_t tef_terms;
+  temporary_terms_t temporary_terms;
+  temporary_terms_idxs_t temporary_terms_idxs;
+  for (const auto & it : def_table)
+    if (it.second->containsExternalFunction())
+      {
+        output << "    ";
+        it.second->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
+      }
+  output << endl;
+  for (const auto & it : def_table)
+    {
+      auto node = variable_node_map.find({ it.first, 0 });
+      assert(node != variable_node_map.end());
+
+      output << "    ";
+      dynamic_cast<ExprNode *>(node->second)->writeOutput(output, output_type);
+      output << " = ";
+      it.second->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
+      output << ";" << endl;
+    }
+  output << "end" << endl << endl;
+  for (auto symb_id : endogs)
+    output << "ds." << symbol_table.getName(symb_id) << " = dseries(" << symbol_table.getName(symb_id)
+           << ", epilogue_ds_first_date__);" << endl;
+  output << endl
+         << "end" << endl;
+  output.close();
+}
diff --git a/src/SteadyStateModel.hh b/src/ModelEquationBlock.hh
similarity index 75%
rename from src/SteadyStateModel.hh
rename to src/ModelEquationBlock.hh
index bf436766ef609ff26efab36151b0af4a936d119a..5ad8ed0dad3bd39310184ca294f02c56fa4a1794 100644
--- a/src/SteadyStateModel.hh
+++ b/src/ModelEquationBlock.hh
@@ -23,6 +23,7 @@
 #include "DataTree.hh"
 #include "Statement.hh"
 #include "StaticModel.hh"
+#include "DynamicModel.hh"
 #include "WarningConsolidation.hh"
 
 class SteadyStateModel : public DataTree
@@ -61,4 +62,31 @@ public:
   void writeJsonSteadyStateFile(ostream &output, bool transformComputingPass) const;
 };
 
+class Epilogue : public DynamicModel
+{
+private:
+  //! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an expression (their assigned value)
+  vector<pair<int, expr_t>> def_table;
+
+  //! List of variables found in block
+  set<int> endogs;
+  set<int> exogs;
+public:
+  Epilogue(SymbolTable &symbol_table_arg,
+           NumericalConstants &num_constants_arg,
+           ExternalFunctionsTable &external_functions_table_arg,
+           TrendComponentModelTable &trend_component_model_table_arg,
+           VarModelTable &var_model_table_arg);
+
+  //! Add an expression of the form "var = expr;"
+  void addDefinition(int symb_id, expr_t expr);
+
+  //! Checks that no variable is declared twice
+  void checkPass(WarningConsolidation &warnings) const;
+
+  //! Write the steady state file
+  void writeEpilogueFile(const string &basename) const;
+};
+
+
 #endif
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index fe4e8184f36b3ca9b14ca9cd6e7ab1aa5853bab8..bcb9143059490c41c8cee5fa6e157f8e9bef2dba 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -201,6 +201,14 @@ ParsingDriver::declare_endogenous(const string &name, const string &tex_name, co
   declare_symbol(name, SymbolType::endogenous, tex_name, partition_value);
 }
 
+void
+ParsingDriver::declare_epilogue_endogenous(const string &name,
+                                           const string &tex_name,
+                                           const vector<pair<string, string>> &partition_value)
+{
+  declare_symbol(name, SymbolType::endogenousEpilogue, tex_name, partition_value);
+}
+
 void
 ParsingDriver::declare_var_endogenous(const string &name)
 {
@@ -230,12 +238,28 @@ ParsingDriver::declare_exogenous_det(const string &name, const string &tex_name,
   declare_symbol(name, SymbolType::exogenousDet, tex_name, partition_value);
 }
 
+void
+ParsingDriver::declare_epilogue_exogenous(const string &name,
+                                          const string &tex_name,
+                                          const vector<pair<string, string>> &partition_value)
+{
+  declare_symbol(name, SymbolType::exogenousEpilogue, tex_name, partition_value);
+}
+
 void
 ParsingDriver::declare_parameter(const string &name, const string &tex_name, const vector<pair<string, string>> &partition_value)
 {
   declare_symbol(name, SymbolType::parameter, tex_name, partition_value);
 }
 
+void
+ParsingDriver::declare_epilogue_parameter(const string &name,
+                                          const string &tex_name,
+                                          const vector<pair<string, string>> &partition_value)
+{
+  declare_symbol(name, SymbolType::parameterEpilogue, tex_name, partition_value);
+}
+
 void
 ParsingDriver::declare_statement_local_variable(const string &name)
 {
@@ -414,6 +438,9 @@ ParsingDriver::add_model_variable(int symb_id, int lag)
 expr_t
 ParsingDriver::add_expression_variable(const string &name)
 {
+  if (parsing_epilogue && !mod_file->symbol_table.exists(name))
+    error("Variable " + name + " used in the epilogue block but was not declared.");
+
   // If symbol doesn't exist, then declare it as a mod file local variable
   if (!mod_file->symbol_table.exists(name))
     mod_file->symbol_table.addSymbol(name, SymbolType::modFileLocalVariable);
@@ -817,6 +844,35 @@ ParsingDriver::end_homotopy()
   homotopy_values.clear();
 }
 
+void
+ParsingDriver::begin_epilogue()
+{
+  parsing_epilogue = true;
+  set_current_data_tree(&mod_file->epilogue);
+}
+
+void
+ParsingDriver::end_epilogue()
+{
+  parsing_epilogue = false;
+  reset_data_tree();
+}
+
+void
+ParsingDriver::add_epilogue_equal(const string &varname, expr_t expr)
+{
+  int id;
+  try
+    {
+      id = mod_file->symbol_table.getID(varname);
+    }
+  catch (SymbolTable::UnknownSymbolNameException &e)
+    {
+      error("Variable " + varname + " used in the epilogue block but was not declared.");
+    }
+  mod_file->epilogue.addDefinition(id, expr);
+}
+
 void
 ParsingDriver::begin_model()
 {
@@ -2887,7 +2943,7 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b
   expr_t nid;
   if (mod_file->symbol_table.exists(function_name))
     if (mod_file->symbol_table.getType(function_name) != SymbolType::externalFunction)
-      if (!in_model_block)
+      if (!in_model_block && !parsing_epilogue)
         {
           if (stack_external_function_args.top().size() > 0)
             error(string("Symbol ") + function_name + string(" cannot take arguments."));
@@ -2915,7 +2971,7 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b
         if (!mod_file->external_functions_table.exists(symb_id))
           error("Using a derivative of an external function (" + function_name + ") in the model block is currently not allowed.");
 
-        if (in_model_block)
+        if (in_model_block || parsing_epilogue)
           if (mod_file->external_functions_table.getNargs(symb_id) == eExtFunNotSet)
             error("Before using " + function_name
                   +"() in the model block, you must first declare it via the external_function() statement");
@@ -2925,6 +2981,9 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b
       }
   else
     { //First time encountering this external function i.e., not previously declared or encountered
+      if (parsing_epilogue)
+        error("Variable " + function_name + " used in the epilogue block but was not declared.");
+
       if (in_model_block)
         {
           // Continue processing, noting that it was not declared
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index b53af1ab9ede3b7a949737add58da5ca2787af2c..77a6020946a8347d9461678d6958474f16aeff5e 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -259,8 +259,12 @@ private:
   //! Used by VAR restrictions
   void clear_VAR_storage();
 
+  //! True when parsing the epilogue block
+  bool parsing_epilogue;
+
 public:
-  ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) : warnings(warnings_arg), nostrict(nostrict_arg) { };
+  ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) :
+    warnings(warnings_arg), nostrict(nostrict_arg), parsing_epilogue(false) { };
 
   //! Starts parsing, and constructs the MOD file representation
   unique_ptr<ModFile> parse(istream &in, bool debug);
@@ -335,12 +339,18 @@ public:
   void initval_file(const string &filename);
   //! Declares an endogenous variable
   void declare_endogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
+  //! Declares an endogenous variable in the epilogue block
+  void declare_epilogue_endogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
   //! Declares an exogenous variable
   void declare_exogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
+  //! Declares an exogenous variable in the epilogue block
+  void declare_epilogue_exogenous(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
   //! Declares an exogenous deterministic variable
   void declare_exogenous_det(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
   //! Declares a parameter
   void declare_parameter(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
+  //! Declare a parameter in the epilogue block
+  void declare_epilogue_parameter(const string &name, const string &tex_name = "", const vector<pair<string, string>> &partition_value = {});
   //! Declares a VAR variable and adds to symbol_list
   void declare_var_endogenous(const string &name);
   //! Declares a model local variable
@@ -402,6 +412,12 @@ public:
   void end_histval(bool all_values_required);
   //! Writes end of an homotopy_setup block
   void end_homotopy();
+  //! Begin epilogue block
+  void begin_epilogue();
+  //! Endepilogue block
+  void end_epilogue();
+  //! Add equation in epilogue block
+  void add_epilogue_equal(const string &varname, expr_t expr);
   //! Begin a model block
   void begin_model();
   //! End a model block, printing errors that were encountered in parsing