diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc
index 6f9208eaae4316d421f833febe36708341eac0c0..099a8500cd6019ca1a5fc5e499683f75627c027f 100644
--- a/src/ComputingTasks.cc
+++ b/src/ComputingTasks.cc
@@ -1722,6 +1722,99 @@ EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const
          << "}";
 }
 
+EstimatedParamsRemoveStatement::EstimatedParamsRemoveStatement(vector<EstimationParams> estim_params_list_arg,
+                                                               const SymbolTable &symbol_table_arg) :
+  estim_params_list{move(estim_params_list_arg)},
+  symbol_table{symbol_table_arg}
+{
+}
+
+void
+EstimatedParamsRemoveStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
+{
+  for (const auto &it : estim_params_list)
+    {
+      int tsid = symbol_table.getTypeSpecificID(it.name) + 1;
+      SymbolType symb_type = symbol_table.getType(it.name);
+
+      if (it.type < 3)
+        {
+          if (symb_type == SymbolType::exogenous)
+            output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl
+                   << "if isempty(tmp1)" << endl
+                   << "    error(sprintf('estimated_params_remove: the standard deviation of %s is not estimated.', M_.exo_names{" << tsid << "}))" << endl
+                   << "else" << endl
+                   << "    estim_params_.var_exo(tmp1,:) = [];"
+                   << "end" << endl;
+          else if (symb_type == SymbolType::endogenous)
+            output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl
+                   << "if isempty(tmp1)" << endl
+                   << "    error(sprintf('estimated_params_remove: the standard deviation of the measurement error on %s is not estimated.', M_.endo_names{" << tsid << "}))" << endl
+                   << "else" << endl
+                   << "    estim_params_.var_endo(tmp1,:) = [];"
+                   << "end" << endl;
+          else if (symb_type == SymbolType::parameter)
+              output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl
+                     << "if isempty(tmp1)" << endl
+                     << "    error(sprintf('estimated_params_remove: parameter %s is not estimated.', M_.param_names{" << tsid << "}))" << endl
+                     << "else" << endl
+                     << "    estim_params_.param_vals(tmp1,:) = [];"
+                     << "end" << endl;
+        }
+      else
+        {
+          int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
+          if (symb_type == SymbolType::exogenous)
+              output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid << " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
+                     <<             "(estim_params_.corrx(:,2)==" << tsid << " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl
+                     << "if isempty(tmp1)" << endl
+                     << "    error(sprintf('estimated_params_remove: the correlation between %s and %s is not estimated.', M_.exo_names{"
+                     << tsid << "}, M_.exo_names{" << tsid2 << "}))" << endl
+                     << "else" << endl
+                     << "    estim_params_.corrx(tmp1,:) = [];"
+                     << "end" << endl;
+          else if (symb_type == SymbolType::endogenous)
+            output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid << " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
+                   <<             "(estim_params_.corrn(:,2)==" << tsid << " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl
+                   << "if isempty(tmp1)" << endl
+                   << "    error(sprintf('estimated_params_remove: the correlation between measurement errors on %s and %s is not estimated.', M_.endo_names{"
+                   << tsid << "}, M_.endo_names{" << tsid2 << "}))" << endl
+                   << "else" << endl
+                   << "    estim_params_.corrn(tmp1,:) = [];"
+                   << "end" << endl;
+        }
+    }
+}
+
+void
+EstimatedParamsRemoveStatement::writeJsonOutput(ostream &output) const
+{
+  output << R"({"statementName": "estimated_params_remove", )"
+         << R"("params": [)";
+
+  for (auto it = estim_params_list.begin(); it != estim_params_list.end(); ++it)
+    {
+      if (it != estim_params_list.begin())
+        output << ", ";
+      output << "{";
+      switch (it->type)
+        {
+        case 1:
+          output << R"("var": ")" << it->name << R"(")";
+        case 2:
+          output << R"("param": ")" << it->name << R"(")";
+          break;
+        case 3:
+          output << R"("var1": ")" << it->name << R"(",)"
+                 << R"("var2": ")" << it->name2 << R"(")";
+          break;
+        }
+      output << "}";
+    }
+  output << "]"
+         << "}";
+}
+
 DeterministicTrendsStatement::DeterministicTrendsStatement(trend_elements_t trend_elements_arg,
                                                        const SymbolTable &symbol_table_arg) :
   trend_elements{move(trend_elements_arg)},
diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh
index 1a4e192fa644648de082e3a201dcc33cfc6dc4ed..c3008925852195a7b9a082697ffee37ee4248cb1 100644
--- a/src/ComputingTasks.hh
+++ b/src/ComputingTasks.hh
@@ -498,7 +498,7 @@ protected:
   AbstractEstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
                                    const SymbolTable &symbol_table_arg);
   virtual string blockName() const = 0;
-  // Part of the check pass that is common to the three estimated_params* blocks
+  // Part of the check pass that is common to the three estimated_params{,_init,bounds} blocks
   void commonCheckPass() const;
 };
 
@@ -538,6 +538,18 @@ public:
   void writeJsonOutput(ostream &output) const override;
 };
 
+class EstimatedParamsRemoveStatement : public Statement
+{
+public:
+  // Only the type, name and name2 fields of EstimationParams are used
+  const vector<EstimationParams> estim_params_list;
+  const SymbolTable &symbol_table;
+  EstimatedParamsRemoveStatement(vector<EstimationParams> estim_params_list_arg,
+                                 const SymbolTable &symbol_table_arg);
+  void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
+  void writeJsonOutput(ostream &output) const override;
+};
+
 class OptimWeightsStatement : public Statement
 {
 public:
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index a964d79066f55960865a85613b518f48c62bcecc..847ce76f20d0679120845e579a5f3f3d465cb077 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -184,7 +184,7 @@ class ParsingDriver;
 %token NO_IDENTIFICATION_MINIMAL NO_IDENTIFICATION_SPECTRUM NORMALIZE_JACOBIANS GRID_NBR
 %token TOL_RANK TOL_DERIV TOL_SV CHECKS_VIA_SUBSETS MAX_DIM_SUBSETS_GROUPS ZERO_MOMENTS_TOLERANCE
 %token MAX_NROWS SQUEEZE_SHOCK_DECOMPOSITION WITH_EPILOGUE MODEL_REMOVE MODEL_REPLACE MODEL_OPTIONS
-%token VAR_REMOVE
+%token VAR_REMOVE ESTIMATED_PARAMS_REMOVE
 
 %token <vector<string>> SYMBOL_VEC
 
@@ -248,6 +248,7 @@ statement : parameters
           | estimated_params
           | estimated_params_bounds
           | estimated_params_init
+          | estimated_params_remove
           | set_time
           | data
           | epilogue
@@ -1895,6 +1896,16 @@ estimated_bounds_elem : STDERR symbol COMMA expression COMMA expression ';'
                         }
                       ;
 
+estimated_params_remove : ESTIMATED_PARAMS_REMOVE ';' estimated_remove_list END ';'
+                          { driver.estimated_params_remove(); };
+
+estimated_remove_list : estimated_remove_elem
+                      | estimated_remove_list estimated_remove_elem
+                      ;
+
+estimated_remove_elem : estimated_elem1 ';'
+                        { driver.add_estimated_params_element(); }
+
 osr_params_bounds : OSR_PARAMS_BOUNDS ';' osr_bounds_list END ';'
                     { driver.osr_params_bounds(); };
 
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index 6b7cd4560a5de078666703f2a7d9480a59126f43..1bc54b01d05f013aaba48f655759d29f581b4f79 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -221,6 +221,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
 <INITIAL>priors {BEGIN DYNARE_BLOCK;return token::ESTIMATED_PARAMS;}
 <INITIAL>estimated_params_init 		{BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_INIT;}
 <INITIAL>estimated_params_bounds 	{BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_BOUNDS;}
+<INITIAL>estimated_params_remove {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_REMOVE;}
 <INITIAL>osr_params_bounds              {BEGIN DYNARE_BLOCK; return token::OSR_PARAMS_BOUNDS;}
 <INITIAL>observation_trends {BEGIN DYNARE_BLOCK; return token::OBSERVATION_TRENDS;}
 <INITIAL>deterministic_trends {BEGIN DYNARE_BLOCK; return token::DETERMINISTIC_TRENDS;}
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index a8cc7831aaa1f856d138ec93c34ca1c092cae704..9f89cbf4b1c66e0b7008e2e4ad58681fc12cd5ab 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -1489,6 +1489,13 @@ ParsingDriver::estimated_params_bounds()
   estim_params_list.clear();
 }
 
+void
+ParsingDriver::estimated_params_remove()
+{
+  mod_file->addStatement(make_unique<EstimatedParamsRemoveStatement>(estim_params_list, mod_file->symbol_table));
+  estim_params_list.clear();
+}
+
 void
 ParsingDriver::add_osr_params_element()
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 1584c3c6deef917c755efffb9f5bfbf2f567d060..ce07bd0a38fafda45de4fc2a400664e3cadf739b 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -512,6 +512,8 @@ public:
   void estimated_params_init(bool use_calibration = false);
   //! Writes estimated params bound command
   void estimated_params_bounds();
+  //! Add an estimated_params_remove block
+  void estimated_params_remove();
   //! Adds a declaration for a user-defined external function
   void external_function();
   //! Sets an external_function option to a string value