diff --git a/src/CodeInterpreter.hh b/src/CodeInterpreter.hh
index 3d5b74b02dc770279424c2148994103d38c4a5ab..8d9631497fc2c59f1ae198ad23ad68c75edd1641 100644
--- a/src/CodeInterpreter.hh
+++ b/src/CodeInterpreter.hh
@@ -150,7 +150,8 @@ enum class SymbolType
     logTrend = 15,                  //!< Log-trend variable
     unusedEndogenous = 16,          //!< Type to mark unused endogenous variables when `nostrict` option is passed
     endogenousVAR = 17,             //!< Variables declared in a var_model statement
-    epilogue = 18                   //!< Variables created in epilogue block
+    epilogue = 18,                  //!< Variables created in epilogue block
+    excludedVariable = 19           //!< Type to use when an equation is excluded via include/exclude_eqs and the LHS variable is not used elsewhere in the model
   };
 
 enum ExpressionType
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index e6cd7e91a536d819e40432bffaf3fdbc0018647b..2ff943d6d5961a502bbc3e44779ae222db1f65cb 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -23,6 +23,7 @@
 #include <cassert>
 #include <algorithm>
 #include <numeric>
+#include <regex>
 
 #include "DynamicModel.hh"
 
@@ -103,6 +104,7 @@ DynamicModel::DynamicModel(const DynamicModel &m) :
   balanced_growth_test_tol {m.balanced_growth_test_tol},
   static_only_equations_lineno {m.static_only_equations_lineno},
   static_only_equations_equation_tags {m.static_only_equations_equation_tags},
+  static_only_equation_tags_xref {m.static_only_equation_tags_xref},
   deriv_id_table {m.deriv_id_table},
   inv_deriv_id_table {m.inv_deriv_id_table},
   dyn_jacobian_cols_table {m.dyn_jacobian_cols_table},
@@ -165,6 +167,7 @@ DynamicModel::operator=(const DynamicModel &m)
 
   static_only_equations_lineno = m.static_only_equations_lineno;
   static_only_equations_equation_tags = m.static_only_equations_equation_tags;
+  static_only_equation_tags_xref = m.static_only_equation_tags_xref;
   deriv_id_table = m.deriv_id_table;
   inv_deriv_id_table = m.inv_deriv_id_table;
   dyn_jacobian_cols_table = m.dyn_jacobian_cols_table;
@@ -2930,6 +2933,179 @@ DynamicModel::writeDynamicJacobianNonZeroElts(const string &basename) const
   output.close();
 }
 
+void
+DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_eq_tags, set<pair<string, string>> & eq_tag_set, bool exclude_eqs)
+{
+  string tags;
+  if (filesystem::exists(inc_exc_eq_tags))
+    {
+      ifstream exclude_file;
+      exclude_file.open(inc_exc_eq_tags, ifstream::in);
+      if (!exclude_file.is_open())
+        {
+          cerr << "ERROR: Could not open " << inc_exc_eq_tags << endl;
+          exit(EXIT_FAILURE);
+        }
+
+      string line;
+      bool tagname_on_first_line = false;
+      while (getline(exclude_file, line))
+        {
+          removeLeadingTrailingWhitespace(line);
+          if (!line.empty())
+            if (tags.empty() && line.find("=") != string::npos)
+              {
+                tagname_on_first_line = true;
+                tags += line + "(";
+              }
+            else
+              if (line.find("'") != string::npos)
+                tags += line + ",";
+              else
+                tags += "'" + line + "',";
+        }
+
+      if (!tags.empty())
+        {
+          tags = tags.substr(0, tags.size()-1);
+          if (tagname_on_first_line)
+            tags += ")";
+        }
+    }
+  else
+    tags = inc_exc_eq_tags;
+  removeLeadingTrailingWhitespace(tags);
+
+  if (tags.front() == '[' && tags.back() != ']')
+    {
+      cerr << "Error: " << (exclude_eqs ? "exclude_eqs" : "include_eqs")
+           << ": if the first character is '[' the last must be ']'" << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  if (tags.front() == '[' && tags.back() == ']')
+    tags = tags.substr(1, tags.length() - 2);
+  removeLeadingTrailingWhitespace(tags);
+
+  regex q ("^\\w+\\s*=");
+  smatch matches;
+  string tagname = "name";
+  if (regex_search(tags, matches, q))
+    {
+      tagname = matches[0].str();
+      tags = tags.substr(tagname.size(), tags.length() - tagname.size() + 1);
+      removeLeadingTrailingWhitespace(tags);
+      if (tags.front() == '(' && tags.back() == ')')
+        {
+          tags = tags.substr(1, tags.length() - 2);
+          removeLeadingTrailingWhitespace(tags);
+        }
+      tagname = tagname.substr(0, tagname.size()-1);
+      removeLeadingTrailingWhitespace(tagname);
+    }
+
+  string quote_regex = "'[^']+'";
+  string non_quote_regex = "[^,\\s]+";
+  regex r ("(\\s*" + quote_regex + "|" + non_quote_regex + "\\s*)(,\\s*(" + quote_regex + "|" + non_quote_regex + ")\\s*)*");
+  if (!regex_match (tags, r))
+    {
+      cerr << "Error: " << (exclude_eqs ? "exclude_eqs" : "include_eqs")
+           << ": argument is of incorrect format." << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  regex s (quote_regex + "|" + non_quote_regex);
+  for (auto it = sregex_iterator(tags.begin(), tags.end(), s);
+      it != sregex_iterator(); it++)
+    {
+      auto str = it->str();
+      if (str[0] == '\'' && str[str.size()-1] == '\'')
+        str = str.substr(1, str.size()-2);
+      eq_tag_set.insert({tagname, str});
+    }
+}
+
+void
+DynamicModel::includeExcludeEquations(const string & eqs, bool exclude_eqs)
+{
+  if (eqs.empty())
+    return;
+
+  set<pair<string, string>> eq_tag_set;
+  parseIncludeExcludeEquations(eqs, eq_tag_set, exclude_eqs);
+
+  vector<int> excluded_vars =
+    ModelTree::includeExcludeEquations(eq_tag_set, exclude_eqs,
+                                       equations, equations_lineno,
+                                       equation_tags, equation_tags_xref, false);
+
+  // `static_only_equation_tags` is `vector<vector<pair<string, string>>>`
+  // while `equation_tags` is `vector<pair<int, pair<string, string>>>`
+  // so convert former structure to latter to conform with function call
+  int n = 0;
+  vector<pair<int, pair<string, string>>> tmp_static_only_equation_tags;
+  for (auto & eqn_tags : static_only_equations_equation_tags)
+    {
+      for (auto & eqn_tag : eqn_tags)
+        tmp_static_only_equation_tags.emplace_back(make_pair(n, eqn_tag));
+      n++;
+    }
+  // Ignore output because variables are not excluded when equations marked 'static' are excluded
+  ModelTree::includeExcludeEquations(eq_tag_set, exclude_eqs,
+                                     static_only_equations, static_only_equations_lineno,
+                                     tmp_static_only_equation_tags,
+                                     static_only_equation_tags_xref, true);
+  if (!eq_tag_set.empty())
+    {
+      cerr << "ERROR: " << (exclude_eqs ? "exclude_eqs" : "include_eqs") << ": The equations specified by `";
+      cerr << eq_tag_set.begin()->first << "= ";
+      for (auto & it : eq_tag_set)
+        cerr << it.second << ", ";
+      cerr << "` were not found." << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  if (staticOnlyEquationsNbr() != dynamicOnlyEquationsNbr())
+    {
+      cerr << "ERROR: " << (exclude_eqs ? "exclude_eqs" : "include_eqs")
+           << ": You must remove the same number of equations marked `static` as equations marked `dynamic`." << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  // convert back static equation info
+  if (static_only_equations.empty())
+    static_only_equations_equation_tags.clear();
+  else
+    {
+      static_only_equations_equation_tags.resize(static_only_equations.size());
+      fill(static_only_equations_equation_tags.begin(), static_only_equations_equation_tags.end(), vector<pair<string, string>>());
+      for (auto & it : tmp_static_only_equation_tags)
+        static_only_equations_equation_tags.at(it.first).emplace_back(it.second);
+    }
+
+  // Collect list of used variables in updated list of equations
+  set<pair<int, int>> eqn_vars;
+  for (const auto & eqn : equations)
+    eqn->collectDynamicVariables(SymbolType::endogenous, eqn_vars);
+  for (const auto & eqn : static_only_equations)
+    eqn->collectDynamicVariables(SymbolType::endogenous, eqn_vars);
+
+  // Change LHS variable type of excluded equation if it is used in an eqution that has been kept
+  for (auto ev : excluded_vars)
+    {
+      bool found = false;
+      for (const auto & it : eqn_vars)
+        if (it.first == ev)
+          {
+            symbol_table.changeType(ev, SymbolType::exogenous);
+            found = true;
+            break;
+          }
+      if (!found)
+        symbol_table.changeType(ev, SymbolType::excludedVariable);
+    }
+}
+
 void
 DynamicModel::writeOutput(ostream &output, const string &basename, bool block_decomposition, bool linear_decomposition, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const
 {
@@ -6305,13 +6481,22 @@ DynamicModel::getEquationNumbersFromTags(const set<string> &eqtags) const
 {
   vector<int> eqnumbers;
   for (auto & eqtag : eqtags)
-    for (const auto & equation_tag : equation_tags)
-      if (equation_tag.second.first == "name"
-          && equation_tag.second.second == eqtag)
+    {
+      bool found = false;
+      for (const auto & equation_tag : equation_tags)
+        if (equation_tag.second.first == "name"
+            && equation_tag.second.second == eqtag)
+          {
+            found = true;
+            eqnumbers.push_back(equation_tag.first);
+            break;
+          }
+      if (!found)
         {
-          eqnumbers.push_back(equation_tag.first);
-          break;
+          cerr << "ERROR: looking for equation tag " << eqtag << " failed." << endl;
+          exit(EXIT_FAILURE);
         }
+    }
   return eqnumbers;
 }
 
@@ -6618,9 +6803,12 @@ DynamicModel::addStaticOnlyEquation(expr_t eq, int lineno, const vector<pair<str
   for (const auto & eq_tag : eq_tags)
     soe_eq_tags.push_back(eq_tag);
 
+  int n = static_only_equations.size();
   static_only_equations.push_back(beq);
   static_only_equations_lineno.push_back(lineno);
   static_only_equations_equation_tags.push_back(soe_eq_tags);
+  for (auto & it : soe_eq_tags)
+    static_only_equation_tags_xref.emplace(it, n);
 }
 
 size_t
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index 865d22d7198bd3a8b5dcf31152e92b716af6c338..31ee8c017b2bb37685724aa4936242e72dc7b16e 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -56,6 +56,9 @@ private:
   //! Stores the equation tags of equations declared as [static]
   vector<vector<pair<string, string>>> static_only_equations_equation_tags;
 
+  //! Stores mapping from equation tags to equation number
+  multimap<pair<string, string>, int> static_only_equation_tags_xref;
+
   using deriv_id_table_t = map<pair<int, int>, int>;
   //! Maps a pair (symbol_id, lag) to a deriv ID
   deriv_id_table_t deriv_id_table;
@@ -266,6 +269,32 @@ private:
       pointers into their equivalent in the new tree */
   void copyHelper(const DynamicModel &m);
 
+  // Internal helper functions for includeExcludeEquations()
+  /*! Handles parsing of argument passed to exclude_eqs/include_eqs*/
+  /*
+    Expects command line arguments of the form:
+      * filename.txt
+      * eq1
+      * ['eq 1', 'eq 2']
+      * [tagname='eq 1']
+      * [tagname=('eq 1', 'eq 2')]
+    If argument is a file, the file should be formatted as:
+        eq 1
+        eq 2
+    OR
+        tagname=
+        X
+        Y
+   */
+  void parseIncludeExcludeEquations(const string &inc_exc_eq_tags, set<pair<string, string>> & eq_tag_set, bool exclude_eqs);
+
+  // General function that removes leading/trailing whitespace from a string
+  inline void removeLeadingTrailingWhitespace(string & str)
+  {
+    str.erase(0, str.find_first_not_of("\t\n\v\f\r "));
+    str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1);
+  }
+
 public:
   DynamicModel(SymbolTable &symbol_table_arg,
                NumericalConstants &num_constants_arg,
@@ -397,6 +426,9 @@ public:
   //! Set the max leads/lags of the original model
   void setLeadsLagsOrig();
 
+  //! Removes equations from the model according to name tags
+  void includeExcludeEquations(const string & eqs, bool exclude_eqs);
+
   //! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
   void computeRamseyPolicyFOCs(const StaticModel &static_model);
   //! Replaces the model equations in dynamic_model with those in this model
diff --git a/src/DynareMain.cc b/src/DynareMain.cc
index 2dd6f803ee3da33e47a579697b0d812b13e3e91c..d4bc64083ef0a1530f32f5fb647277dcfdb05b37 100644
--- a/src/DynareMain.cc
+++ b/src/DynareMain.cc
@@ -46,6 +46,7 @@ void main2(stringstream &in, const string &basename, bool debug, bool clear_all,
            WarningConsolidation &warnings_arg, bool nostrict, bool stochastic, bool check_model_changes,
            bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
            LanguageOutputType lang, int params_derivs_order, bool transform_unary_ops,
+           const string &exclude_eqs, const string &include_eqs,
            JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple,
            const string &mexext, const filesystem::path &matlabroot,
            const filesystem::path &dynareroot, bool onlymodel);
@@ -60,7 +61,7 @@ usage()
   cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]"
        << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
        << " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=matlab|julia]"
-       << " [params_derivs_order=0|1|2] [transform_unary_ops]"
+       << " [params_derivs_order=0|1|2] [transform_unary_ops] [exclude_eqs=<equation_tag_list_or_file>] [include_eqs=<equation_tag_list_or_file>]"
        << " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]"
        << " [mexext=<extension>] [matlabroot=<path>] [onlymodel]"
        << endl;
@@ -154,6 +155,7 @@ main(int argc, char **argv)
   bool minimal_workspace = false;
   bool compute_xrefs = false;
   bool transform_unary_ops = false;
+  string exclude_eqs, include_eqs;
   vector<pair<string, string>> defines;
   vector<filesystem::path> paths;
   FileOutputType output_mode{FileOutputType::none};
@@ -371,6 +373,24 @@ main(int argc, char **argv)
             }
           mexext = s.substr(7);
         }
+      else if (s.substr(0, 11) == "exclude_eqs")
+        {
+          if (s.length() <= 12 || s.at(11) != '=')
+            {
+              cerr << "Incorrect syntax for exclude_eqs option" << endl;
+              usage();
+            }
+          exclude_eqs = s.substr(12);
+        }
+      else if (s.substr(0, 11) == "include_eqs")
+        {
+          if (s.length() <= 12 || s.at(11) != '=')
+            {
+              cerr << "Incorrect syntax for include_eqs option" << endl;
+              usage();
+            }
+          include_eqs = s.substr(12);
+        }
       else if (s.substr(0, 10) == "matlabroot")
         {
           if (s.length() <= 11 || s.at(10) != '=')
@@ -418,11 +438,17 @@ main(int argc, char **argv)
   if (only_macro)
     return EXIT_SUCCESS;
 
+  if (!exclude_eqs.empty() && !include_eqs.empty())
+    {
+      cerr << "You may only pass one of `include_eqs` and `exclude_eqs`" << endl;
+      exit(EXIT_FAILURE);
+    }
+
   // Do the rest
   main2(macro_output, basename, debug, clear_all, clear_global,
         no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
         parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace,
-        compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops,
+        compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops, exclude_eqs, include_eqs,
         json, json_output_mode, onlyjson, jsonderivsimple,
         mexext, matlabroot, dynareroot, onlymodel);
 
diff --git a/src/DynareMain2.cc b/src/DynareMain2.cc
index 38428887921b5cc0e3a961786b06b76749412519..abcb9ddae655f5fdf96b54f4e37ed847afb0dff2 100644
--- a/src/DynareMain2.cc
+++ b/src/DynareMain2.cc
@@ -32,6 +32,7 @@ main2(stringstream &in, const string &basename, bool debug, bool clear_all, bool
       WarningConsolidation &warnings, bool nostrict, bool stochastic, bool check_model_changes,
       bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
       LanguageOutputType language, int params_derivs_order, bool transform_unary_ops,
+      const string &exclude_eqs, const string &include_eqs,
       JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple,
       const string &mexext, const filesystem::path &matlabroot,
       const filesystem::path &dynareroot, bool onlymodel)
@@ -51,7 +52,8 @@ main2(stringstream &in, const string &basename, bool debug, bool clear_all, bool
     mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
 
   // Perform transformations on the model (creation of auxiliary vars and equations)
-  mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == JsonOutputPointType::transformpass, transform_unary_ops);
+  mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == JsonOutputPointType::transformpass,
+                          transform_unary_ops, exclude_eqs, include_eqs);
   if (json == JsonOutputPointType::transformpass)
     mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
 
diff --git a/src/ExprNode.cc b/src/ExprNode.cc
index 96829a7206cf42603a5cd71bf1ff9704ef3872a7..9d116abd6976b44ac455e78a99ba5f370acba21b 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -839,6 +839,11 @@ VariableNode::prepareForDerivation()
     case SymbolType::epilogue:
       cerr << "VariableNode::prepareForDerivation: impossible case" << endl;
       exit(EXIT_FAILURE);
+    case SymbolType::excludedVariable:
+      cerr << "VariableNode::prepareForDerivation: impossible case: "
+           << "You are trying to derive a variable that has been excluded via include_eqs/exclude_eqs: "
+           << datatree.symbol_table.getName(symb_id) << endl;
+      exit(EXIT_FAILURE);
     }
 }
 
@@ -871,6 +876,7 @@ VariableNode::computeDerivative(int deriv_id)
     case SymbolType::externalFunction:
     case SymbolType::endogenousVAR:
     case SymbolType::epilogue:
+    case SymbolType::excludedVariable:
       cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
       exit(EXIT_FAILURE);
     }
@@ -939,6 +945,9 @@ VariableNode::writeJsonAST(ostream &output) const
     case SymbolType::epilogue:
       output << "epilogue";
       break;
+    case SymbolType::excludedVariable:
+      cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
+      exit(EXIT_FAILURE);
     }
   output << R"(", "lag" : )" << lag << "}";
 }
@@ -1220,6 +1229,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
     case SymbolType::logTrend:
     case SymbolType::statementDeclaredVariable:
     case SymbolType::endogenousVAR:
+    case SymbolType::excludedVariable:
       cerr << "VariableNode::writeOutput: Impossible case" << endl;
       exit(EXIT_FAILURE);
     }
@@ -1439,6 +1449,7 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur
     case SymbolType::externalFunction:
     case SymbolType::endogenousVAR:
     case SymbolType::epilogue:
+    case SymbolType::excludedVariable:
       cerr << "VariableNode::getChainRuleDerivative: Impossible case" << endl;
       exit(EXIT_FAILURE);
     }
@@ -1478,6 +1489,7 @@ VariableNode::computeXrefs(EquationInfo &ei) const
     case SymbolType::externalFunction:
     case SymbolType::endogenousVAR:
     case SymbolType::epilogue:
+    case SymbolType::excludedVariable:
       break;
     }
 }
diff --git a/src/ModFile.cc b/src/ModFile.cc
index bb55a0c03a81c10f41bde806eca37234d77a52c9..e2581efc04be2655b2244409931411e628079d9c 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -381,7 +381,8 @@ ModFile::checkPass(bool nostrict, bool stochastic)
 }
 
 void
-ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops)
+ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops,
+                       const string &exclude_eqs, const string &include_eqs)
 {
   /* Save the original model (must be done before any model transformations by preprocessor)
      — except substituting out variables which we know are constant (they
@@ -390,6 +391,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
      — except diff operators with a lead which have been expanded by
        DataTree:AddDiff()
   */
+  dynamic_model.includeExcludeEquations(exclude_eqs, true);
+  dynamic_model.includeExcludeEquations(include_eqs, false);
   dynamic_model.simplifyEquations();
   dynamic_model.substituteAdl();
   dynamic_model.setLeadsLagsOrig();
diff --git a/src/ModFile.hh b/src/ModFile.hh
index fd79a2ebd328662a37d30afc23ce2de6b49a7200..e177934ef3b960a51fd5c71e9e88aebb7b65900a 100644
--- a/src/ModFile.hh
+++ b/src/ModFile.hh
@@ -146,7 +146,8 @@ public:
   void checkPass(bool nostrict, bool stochastic);
   //! Perform some transformations on the model (creation of auxiliary vars and equations)
   /*! \param compute_xrefs if true, equation cross references will be computed */
-  void transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops);
+  void transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops,
+                     const string &exclude_eqs, const string &include_eqs);
   //! Execute computations
   /*! \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic files */
   /*! \param params_derivs_order compute this order of derivs wrt parameters */
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 8ce37ef406f44d6887502abdfad8e6f452591d43..5109166c9b1497af235992fef945763a7cbacdb9 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -1934,6 +1934,104 @@ ModelTree::addEquation(expr_t eq, int lineno)
   equations_lineno.push_back(lineno);
 }
 
+vector<int>
+ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_eqs,
+                                   vector<BinaryOpNode *> &equations, vector<int> &equations_lineno,
+                                   vector<pair<int, pair<string, string>>> &equation_tags,
+                                   multimap<pair<string, string>, int> &equation_tags_xref, bool static_equations) const
+{
+  vector<int> excluded_vars;
+  if (equations.empty())
+    return excluded_vars;
+
+  // Get equation numbers of tags
+  set<int> tag_eqns;
+  for (auto & it : eqs)
+    if (equation_tags_xref.find(it) != equation_tags_xref.end())
+      {
+        auto range = equation_tags_xref.equal_range(it);
+        for_each ( range.first, range.second, [&tag_eqns](auto & x){ tag_eqns.insert(x.second); } );
+        eqs.erase(it);
+      }
+  if (tag_eqns.empty())
+    return excluded_vars;
+
+  set<int> eqns;
+  if (exclude_eqs)
+    eqns = tag_eqns;
+  else
+    for (size_t i = 0; i < equations.size(); i++)
+      if (tag_eqns.find(i) == tag_eqns.end())
+        eqns.insert(i);
+
+  // remove from equations, equations_lineno, equation_tags, equation_tags_xref
+  vector<BinaryOpNode *> new_eqns;
+  vector<int> new_equations_lineno;
+  map<int, int> old_eqn_num_2_new;
+  for (size_t i = 0; i < equations.size(); i++)
+    if (eqns.find(i) != eqns.end())
+      {
+        bool found = false;
+        for (const auto & it : equation_tags)
+          if (it.first == static_cast<int>(i) && it.second.first == "endogenous")
+            {
+              found = true;
+              excluded_vars.push_back(symbol_table.getID(it.second.second));
+              break;
+            }
+        if (!found)
+          {
+            set<pair<int, int>> result;
+            equations[i]->arg1->collectDynamicVariables(SymbolType::endogenous, result);
+            if (result.size() == 1)
+              excluded_vars.push_back(result.begin()->first);
+            else
+              {
+                cerr << "ERROR: Equation " << i
+                     << " has been excluded but does not have a single variable on LHS or `endogenous` tag" << endl;
+                exit(EXIT_FAILURE);
+              }
+          }
+      }
+    else
+      {
+        new_eqns.emplace_back(equations[i]);
+        old_eqn_num_2_new[i] = new_eqns.size() - 1;
+        new_equations_lineno.emplace_back(equations_lineno[i]);
+      }
+  int n_excl = equations.size() - new_eqns.size();
+
+  equations = new_eqns;
+  equations_lineno = new_equations_lineno;
+
+  equation_tags.erase(remove_if(equation_tags.begin(), equation_tags.end(),
+                                [&](const auto& it) { return eqns.find(it.first) != eqns.end(); }),
+                      equation_tags.end());
+  for (auto & it : old_eqn_num_2_new)
+    for (auto & it1 : equation_tags)
+      if (it1.first == it.first)
+        it1.first = it.second;
+
+  equation_tags_xref.clear();
+  for (const auto & it : equation_tags)
+    equation_tags_xref.emplace(it.second, it.first);
+
+  if (!static_equations)
+    for (size_t i = 0; i < excluded_vars.size(); i++)
+      for (size_t j = i+1; j < excluded_vars.size(); j++)
+        if (excluded_vars[i] == excluded_vars[j])
+          {
+            cerr << "Error: Variable " << symbol_table.getName(i) << " was excluded twice"
+                 << " via in/exclude_eqs option" << endl;
+            exit(EXIT_FAILURE);
+          }
+
+  cout << "Excluded " << n_excl << (static_equations ? " static " : " dynamic ")
+       << "equation" << (n_excl > 1 ? "s" : "" ) << " via in/exclude_eqs option" << endl;
+
+  return excluded_vars;
+}
+
 void
 ModelTree::simplifyEquations()
 {
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index 2a15f9558dc7f2a777a55c4bd1444f010d83e171..fe1976887e43e89682b0f8d6a70cda0798bea028 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -75,13 +75,10 @@ protected:
    */
   //! Stores declared and generated auxiliary equations
   vector<BinaryOpNode *> equations;
-
   //! Stores line numbers of declared equations; -1 means undefined
   vector<int> equations_lineno;
-
   //! Stores equation tags
   vector<pair<int, pair<string, string>>> equation_tags;
-
   //! Stores mapping from equation tags to equation number
   multimap<pair<string, string>, int> equation_tags_xref;
   /*
@@ -262,6 +259,11 @@ protected:
   void printBlockDecomposition(const vector<pair<int, int>> &blocks) const;
   //! Determine for each block if it is linear or not
   vector<bool> BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vector<int> &variable_reordered) const;
+  //! Remove equations specified by exclude_eqs
+  vector<int> includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_eqs,
+                                      vector<BinaryOpNode *> &equations, vector<int> &equations_lineno,
+                                      vector<pair<int, pair<string, string>>> &equation_tags,
+                                      multimap<pair<string, string>, int> &equation_tags_xref, bool static_equations) const;
 
   //! Determine the simulation type of each block
   virtual BlockSimulationType getBlockSimulationType(int block_number) const = 0;
@@ -348,6 +350,8 @@ public:
   void addEquation(expr_t eq, int lineno);
   //! Declare a node as an equation of the model, also giving its tags
   void addEquation(expr_t eq, int lineno, const vector<pair<string, string>> &eq_tags);
+  //! Add equation tags to equation tag table
+  void addEquationTagsToTable(const vector<pair<string, string>> &eq_tags);
   //! Declare a node as an auxiliary equation of the model, adding it at the end of the list of auxiliary equations
   void addAuxEquation(expr_t eq);
   //! Returns the number of equations in the model
diff --git a/src/NumericalInitialization.cc b/src/NumericalInitialization.cc
index fd3d0cacb00e31491806eee109230187649580bd..11f7de1e7ad2618ce7e0c213af980e7ba2bfd3f4 100644
--- a/src/NumericalInitialization.cc
+++ b/src/NumericalInitialization.cc
@@ -148,12 +148,25 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
       SymbolType type = symbol_table.getType(symb_id);
       int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
 
-      if (type == SymbolType::endogenous)
-        output << "oo_.steady_state";
-      else if (type == SymbolType::exogenous)
-        output << "oo_.exo_steady_state";
-      else if (type == SymbolType::exogenousDet)
-        output << "oo_.exo_det_steady_state";
+      switch (type)
+        {
+        case SymbolType::endogenous:
+          output << "oo_.steady_state";
+          break;
+        case SymbolType::exogenous:
+          output << "oo_.exo_steady_state";
+          break;
+        case SymbolType::exogenousDet:
+          output << "oo_.exo_det_steady_state";
+          break;
+        case SymbolType::excludedVariable:
+          cerr << "ERROR: Variable `" << symbol_table.getName(symb_id)
+               << "` was excluded but found in an initval or endval statement" << endl;
+          exit(EXIT_FAILURE);
+        default:
+          cerr << "Should not arrive here" << endl;
+          exit(EXIT_FAILURE);
+        }
 
       output << "( " << tsid << " ) = ";
       expression->writeOutput(output);