diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc
index fcf94a423543f48e9f2123a465b7712e8ec78bc5..8f65bc0a5ee6b3a0f8cf106ca56288a449c5855d 100644
--- a/src/ComputingTasks.cc
+++ b/src/ComputingTasks.cc
@@ -1019,20 +1019,6 @@ EstimationStatement::writeOutput(ostream &output, const string &basename, bool m
 {
   options_list.writeOutput(output);
 
-  bool occbin_option_present = false;
-  if (auto it = options_list.num_options.find("occbin_likelihood");
-      it != options_list.num_options.end() && it->second == "true")
-    occbin_option_present = true;
-
-  if (auto it = options_list.num_options.find("occbin_smoother");
-      it != options_list.num_options.end() && it->second == "true")
-    occbin_option_present = true;
-
-  if (occbin_option_present)
-    output << "options_ = set_default_occbin_options(options_, M_);" << endl
-           << "clear mr_runsim_occbin_fn" << endl
-           << "M_ = get_wish_list(M_);" << endl;
-
   // Special treatment for order option and particle filter
   if (auto it = options_list.num_options.find("order");
       it == options_list.num_options.end())
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index f6c19af001181a841393d91eb792fec43bea2c1c..ab209904b6782e1b3e88836071e912a4d4440c69 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -2798,7 +2798,7 @@ DynamicModel::writeBlockDriverOutput(ostream &output, const string &basename,
 }
 
 void
-DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool block_decomposition, bool use_dll, bool estimation_present, bool compute_xrefs) const
+DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool block_decomposition, bool use_dll, bool occbin, bool estimation_present, bool compute_xrefs) const
 {
   /* Writing initialisation for M_.lead_lag_incidence matrix
      M_.lead_lag_incidence is a matrix with as many columns as there are
@@ -2895,7 +2895,8 @@ DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool bl
   equation_tags.writeOutput(output);
 
   // Write Occbin tags
-  equation_tags.writeOccbinOutput(output);
+  if (occbin)
+    equation_tags.writeOccbinOutput(output);
 
   // Write mapping for variables and equations they are present in
   for (const auto &variable : variableMapping)
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index d98b13c503d4c4a3c28041fc69edde551bd4ba46..c64ef06266efa954004ec76ce32c38902f3bf4d6 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -300,7 +300,7 @@ public:
   void computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsOrder,
                      const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode);
   //! Writes information about the dynamic model to the driver file
-  void writeDriverOutput(ostream &output, const string &basename, bool block, bool use_dll, bool estimation_present, bool compute_xrefs) const;
+  void writeDriverOutput(ostream &output, const string &basename, bool block, bool use_dll, bool occbin, bool estimation_present, bool compute_xrefs) const;
 
   //! Write JSON AST
   void writeJsonAST(ostream &output) const;
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 6876586558a8e0d40ca88a9887beb8359926b21c..6c47638a14f28d81821ce890f003200bb606ecec 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -107,7 +107,7 @@ class ParsingDriver;
 %token USE_PENALIZED_OBJECTIVE_FOR_HESSIAN INIT_STATE FAST_REALTIME RESCALE_PREDICTION_ERROR_COVARIANCE GENERATE_IRFS
 %token NAN_CONSTANT NO_STATIC NOBS NOCONSTANT NODISPLAY NOCORR NODIAGNOSTIC NOFUNCTIONS NO_HOMOTOPY
 %token NOGRAPH POSTERIOR_NOGRAPH POSTERIOR_GRAPH NOMOMENTS NOPRINT NORMAL_PDF SAVE_DRAWS MODEL_NAME STDERR_MULTIPLES DIAGONAL_ONLY
-%token DETERMINISTIC_TRENDS OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS MAX_DIM_COVA_GROUP ADVANCED OUTFILE OUTVARS OVERWRITE DISCOUNT
+%token DETERMINISTIC_TRENDS OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS MAX_DIM_COVA_GROUP ADVANCED OUTFILE OUTVARS OVERWRITE DISCOUNT OCCBIN
 %token PARALLEL_LOCAL_FILES PARAMETERS PARAMETER_SET PARTIAL_INFORMATION PERIODS PERIOD PLANNER_OBJECTIVE PLOT_CONDITIONAL_FORECAST PLOT_PRIORS PREFILTER PRESAMPLE
 %token PERFECT_FORESIGHT_SETUP PERFECT_FORESIGHT_SOLVER NO_POSTERIOR_KERNEL_DENSITY FUNCTION
 %token PRINT PRIOR_MC PRIOR_TRUNC PRIOR_MODE PRIOR_MEAN POSTERIOR_MODE POSTERIOR_MEAN POSTERIOR_MEDIAN MLE_MODE PRUNING PARTICLE_FILTER_OPTIONS
@@ -131,7 +131,7 @@ class ParsingDriver;
 %precedence UNARY
 %nonassoc POWER
 %token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN ERF DIFF ADL AUXILIARY_MODEL_NAME
-%token SQRT CBRT NORMCDF NORMPDF STEADY_STATE EXPECTATION OCCBIN_LIKELIHOOD OCCBIN_SMOOTHER
+%token SQRT CBRT NORMCDF NORMPDF STEADY_STATE EXPECTATION
 /* GSA analysis */
 %token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV
 %token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB LOGTRANS_REDFORM THRESHOLD_REDFORM
@@ -873,6 +873,7 @@ model_options : BLOCK { driver.block(); }
               | o_linear
               | PARALLEL_LOCAL_FILES EQUAL '(' parallel_local_filename_list ')'
               | BALANCED_GROWTH_TEST_TOL EQUAL non_negative_number { driver.balanced_growth_test_tol($3); }
+              | OCCBIN { driver.occbin(); }
               ;
 
 model_options_list : model_options_list COMMA model_options
@@ -2089,8 +2090,6 @@ estimation_options : o_datafile
                    | o_emas_max_iter
                    | o_stderr_multiples
                    | o_diagonal_only
-                   | o_occbin_likelihood
-                   | o_occbin_smoother
                    | o_no_init_estimation_check_first_obs
                    | o_heteroskedastic_filter
                    ;
@@ -3518,8 +3517,6 @@ o_proposal_approximation : PROPOSAL_APPROXIMATION EQUAL CUBATURE {driver.option_
 o_distribution_approximation : DISTRIBUTION_APPROXIMATION EQUAL CUBATURE {driver.option_num("particle.distribution_approximation.cubature", "true"); driver.option_num("particle.distribution_approximation.unscented", "false"); driver.option_num("particle.distribution_approximation.montecarlo", "false");}
 		| DISTRIBUTION_APPROXIMATION EQUAL UNSCENTED {driver.option_num("particle.distribution_approximation.cubature", "false"); driver.option_num("particle.distribution_approximation.unscented", "true"); driver.option_num("particle.distribution_approximation.montecarlo", "false");}
 		| DISTRIBUTION_APPROXIMATION EQUAL MONTECARLO {driver.option_num("particle.distribution_approximation.cubature", "false"); driver.option_num("particle.distribution_approximation.unscented", "false"); driver.option_num("particle.distribution_approximation.montecarlo", "true");} ;
-o_occbin_likelihood : OCCBIN_LIKELIHOOD { driver.option_num("occbin_likelihood", "true"); };
-o_occbin_smoother : OCCBIN_SMOOTHER { driver.option_num("occbin_smoother", "true"); };
 o_gsa_identification : IDENTIFICATION EQUAL INT_NUMBER { driver.option_num("identification", $3); }; /*not in doc */
 o_gsa_morris : MORRIS EQUAL INT_NUMBER { driver.option_num("morris", $3); };
 o_gsa_stab : STAB  EQUAL INT_NUMBER { driver.option_num("stab", $3); };
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index b37ea326a881fec365dae46f8f3572d5c4838cf0..feedb7905b25b9672cf7267bff2f42d9faa40fd0 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -434,8 +434,6 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
 <DYNARE_STATEMENT>rescale_prediction_error_covariance {return token::RESCALE_PREDICTION_ERROR_COVARIANCE;}
 <DYNARE_STATEMENT>use_penalized_objective_for_hessian {return token::USE_PENALIZED_OBJECTIVE_FOR_HESSIAN;}
 <DYNARE_STATEMENT>expression    {return token::EXPRESSION;}
-<DYNARE_STATEMENT>occbin_likelihood {return token::OCCBIN_LIKELIHOOD;}
-<DYNARE_STATEMENT>occbin_smoother {return token::OCCBIN_SMOOTHER;}
 <DYNARE_STATEMENT>first_simulation_period {return token::FIRST_SIMULATION_PERIOD;}
 <DYNARE_STATEMENT>no_init_estimation_check_first_obs {return token::NO_INIT_ESTIMATION_CHECK_FIRST_OBS;}
 
@@ -836,6 +834,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
 <DYNARE_BLOCK>no_static {return token::NO_STATIC;}
 <DYNARE_BLOCK>differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;}
 <DYNARE_BLOCK>parallel_local_files {return token::PARALLEL_LOCAL_FILES;}
+<DYNARE_BLOCK>occbin {return token::OCCBIN;}
 
 <DYNARE_STATEMENT,DYNARE_BLOCK>linear {return token::LINEAR;}
 
diff --git a/src/EquationTags.cc b/src/EquationTags.cc
index c86fd51af3d5313ceca224665c95ede7af8cec59..18cacd5f245c4c70b7d72620a78944cbdbfe21cb 100644
--- a/src/EquationTags.cc
+++ b/src/EquationTags.cc
@@ -165,3 +165,16 @@ EquationTags::writeJsonAST(ostream &output, const int eqn) const
     }
   output << "}";
 }
+
+bool
+EquationTags::hasOccbinTags() const
+{
+  for (const auto & [eqn, tags] : eqn_tags)
+    for (const auto & [key, value] : tags)
+      if (key == "pswitch"
+          || key == "bind"
+          || key == "relax"
+          || key == "pcrit")
+        return true;
+  return false;
+}
diff --git a/src/EquationTags.hh b/src/EquationTags.hh
index d573f8c0791db75784250ffa36eed7433c37c4d7..b983fbd480e95a77f6ec4264985c1f24bd7bf45a 100644
--- a/src/EquationTags.hh
+++ b/src/EquationTags.hh
@@ -115,6 +115,10 @@ public:
   void writeOccbinOutput(ostream &output) const;
   void writeLatexOutput(ostream &output, int eqn) const;
   void writeJsonAST(ostream &output, const int eq) const;
+
+  /* Returns true if at least one equation has a tag associated to occbin
+     (bind/relax/pswitch/pcrit) */
+  bool hasOccbinTags() const;
 };
 
 #endif
diff --git a/src/ModFile.cc b/src/ModFile.cc
index d340903d071cbbae032bd72082a2109d8bf22214..e72e5825f340e693e95e185b6185257b961475ac 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -686,6 +686,23 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
       exit(EXIT_FAILURE);
     }
 
+  if (occbin && !dynamic_model.hasOccbinTags())
+    {
+      cerr << "ERROR: the 'occbin' option is present, but there is no equation with the associated tags (bind/relax/pswitch/pcrit)" << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  if (occbin
+      && (mod_file_struct.stoch_simul_present || mod_file_struct.osr_present
+          || mod_file_struct.ramsey_model_present || mod_file_struct.ramsey_policy_present
+          || mod_file_struct.discretionary_policy_present || mod_file_struct.extended_path_present
+          || mod_file_struct.identification_present || mod_file_struct.sensitivity_present
+          || mod_file_struct.mom_estimation_present || mod_file_struct.calib_smoother_present))
+    {
+      cerr << "ERROR: the 'occbin' option is not compatible with commands other than 'estimation'" << endl;
+      exit(EXIT_FAILURE);
+    }
+
   if (!mod_file_struct.ramsey_model_present)
     cout << "Found " << dynamic_model.equation_number() << " equation(s)." << endl;
   else
@@ -1018,11 +1035,16 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
 
   if (dynamic_model.equation_number() > 0)
     {
-      dynamic_model.writeDriverOutput(mOutputFile, basename, block, use_dll, mod_file_struct.estimation_present, compute_xrefs);
+      dynamic_model.writeDriverOutput(mOutputFile, basename, block, use_dll, occbin, mod_file_struct.estimation_present, compute_xrefs);
       if (!no_static)
         static_model.writeDriverOutput(mOutputFile, block);
     }
 
+  if (occbin)
+    mOutputFile << "options_ = set_default_occbin_options(options_, M_);" << endl
+                << "clear mr_runsim_occbin_fn" << endl
+                << "M_ = get_wish_list(M_);" << endl;
+
   if (onlymodel || gui)
     for (const auto &statement : statements)
       {
diff --git a/src/ModFile.hh b/src/ModFile.hh
index 01e1a471d1192d588533e5648efa8cdb7cb18740..6ab993f75b3716a952f2d46e84d677c22e8e1519 100644
--- a/src/ModFile.hh
+++ b/src/ModFile.hh
@@ -99,6 +99,9 @@ public:
     with a lead */
   vector<string> differentiate_forward_vars_subset;
 
+  //! Whether “occbin” option is used
+  bool occbin{false};
+
   //! Are nonstationary variables present ?
   bool nonstationary_variables{false};
 
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index e6fc89d7f6c42f3f404f53abbb63d09d22bd994b..906c285c4f6674433c7cb6b0deb6cd1e97d6cdfd 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -2120,3 +2120,9 @@ ModelTree::updateReverseVariableEquationOrderings()
       eq_idx_orig2block[eq_idx_block2orig[i]] = i;
     }
 }
+
+bool
+ModelTree::hasOccbinTags() const
+{
+  return equation_tags.hasOccbinTags();
+}
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index 6cfdfcf6932469dcac7394fbe0641bb75b650f44..f295a04d75f9ae223fdd8ae18f12dc54e527d4da 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -494,6 +494,10 @@ public:
         return "UNKNOWN                      ";
       }
   }
+
+  /* Returns true if at least one equation has a tag associated to occbin
+     (bind/relax/pswitch/pcrit) */
+  bool hasOccbinTags() const;
 };
 
 #endif
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index 4b0d95200d51d8bde69ca7272653e0b629b07f04..f25e0ef54cb2ef64a73197e28020f5a9b00b1a4f 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -634,6 +634,12 @@ ParsingDriver::bytecode()
   mod_file->bytecode = true;
 }
 
+void
+ParsingDriver::occbin()
+{
+  mod_file->occbin = true;
+}
+
 void
 ParsingDriver::differentiate_forward_vars_all()
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 4402222ef830e8eff7641e897faf9a76fd5fd687..46c3fde55a9e2b8dc4d5c890517c06a82ff5a8a5 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -325,6 +325,8 @@ public:
 
   //! the model is stored in a binary file
   void bytecode();
+  //! the model has occasional binding constraints
+  void occbin();
   //! the static model is not computed
   void no_static();
   //! the differentiate_forward_vars option is enabled (for all vars)