diff --git a/preprocessor/ComputingTasks.cc b/preprocessor/ComputingTasks.cc
index 21b2dd7553863f114b30d657b84771a5011996c9..49a99385bbfc7cc125220d180fda5464061ad0e3 100644
--- a/preprocessor/ComputingTasks.cc
+++ b/preprocessor/ComputingTasks.cc
@@ -1053,6 +1053,51 @@ ObservationTrendsStatement::writeOutput(ostream &output, const string &basename,
     }
 }
 
+FilterInitialStateStatement::FilterInitialStateStatement(const filter_initial_state_elements_t &filter_initial_state_elements_arg,
+                                                         const SymbolTable &symbol_table_arg) :
+  filter_initial_state_elements(filter_initial_state_elements_arg),
+  symbol_table(symbol_table_arg)
+{
+}
+
+void
+FilterInitialStateStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
+{
+  output << "options_.filter_initial_state = cell(M_.endo_nbr, 1);" << endl;
+  for (filter_initial_state_elements_t::const_iterator it = filter_initial_state_elements.begin();
+       it != filter_initial_state_elements.end(); it++)
+    {
+      int symb_id = it->first.first;
+      int lag = it->first.second;
+      SymbolType type = symbol_table.getType(symb_id);
+
+      if ((type == eEndogenous && lag < 0) || type == eExogenous)
+        {
+          try
+            {
+              // This function call must remain the 1st statement in this block
+              symb_id = symbol_table.searchAuxiliaryVars(symb_id, lag);
+            }
+          catch (SymbolTable::SearchFailedException &e)
+            {
+              if (type == eEndogenous)
+                {
+                  cerr << "filter_initial_state: internal error, please contact the developers";
+                  exit(EXIT_FAILURE);
+                }
+              // We don't fail for exogenous, because they are not replaced by
+              // auxiliary variables in deterministic mode.
+            }
+        }
+
+      output << "options_.filter_initial_state{"
+             << symbol_table.getTypeSpecificID(symb_id) + 1
+             << "} = {'" << symbol_table.getName(symb_id) << "', ";
+      it->second->writeOutput(output);
+      output << "};" << endl;
+    }
+}
+
 OsrParamsStatement::OsrParamsStatement(const SymbolList &symbol_list_arg, const SymbolTable &symbol_table_arg) :
   symbol_list(symbol_list_arg),
   symbol_table(symbol_table_arg)
diff --git a/preprocessor/ComputingTasks.hh b/preprocessor/ComputingTasks.hh
index 596738c27cbd4f98b6dd0aa83b5c7ea3a521177a..43671c00ce3efa009e4a3e1442de3a104bee3785 100644
--- a/preprocessor/ComputingTasks.hh
+++ b/preprocessor/ComputingTasks.hh
@@ -248,6 +248,19 @@ public:
   virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
 };
 
+class FilterInitialStateStatement : public Statement
+{
+public:
+  typedef map<pair<int, int>, expr_t> filter_initial_state_elements_t;
+private:
+  const filter_initial_state_elements_t filter_initial_state_elements;
+  const SymbolTable &symbol_table;
+public:
+  FilterInitialStateStatement(const filter_initial_state_elements_t &filter_initial_state_elements_arg,
+                              const SymbolTable &symbol_table_arg);
+  virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
+};
+
 class OsrParamsStatement : public Statement
 {
 private:
diff --git a/preprocessor/DynareBison.yy b/preprocessor/DynareBison.yy
index c495801a03ecbbfb772cddd5ac706ea2636f9993..6c86f1dc7433a43872552d8f2984ce43bd6e5609 100644
--- a/preprocessor/DynareBison.yy
+++ b/preprocessor/DynareBison.yy
@@ -110,7 +110,7 @@ class ParsingDriver;
 %token MODE_CHECK MODE_CHECK_NEIGHBOURHOOD_SIZE MODE_CHECK_SYMMETRIC_PLOTS MODE_CHECK_NUMBER_OF_POINTS MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS ABS SIGN
 %token MODEL_DIAGNOSTICS MODIFIEDHARMONICMEAN MOMENTS_VARENDO CONTEMPORANEOUS_CORRELATION DIFFUSE_FILTER SUB_DRAWS TAPER_STEPS GEWEKE_INTERVAL RAFTERY_LEWIS_QRS RAFTERY_LEWIS_DIAGNOSTICS MCMC_JUMPING_COVARIANCE MOMENT_CALIBRATION
 %token NUMBER_OF_PARTICLES RESAMPLING SYSTEMATIC GENERIC RESAMPLING_THRESHOLD RESAMPLING_METHOD KITAGAWA STRATIFIED SMOOTH
-%token CPF_WEIGHTS AMISANOTRISTANI MURRAYJONESPARSLOW
+%token CPF_WEIGHTS AMISANOTRISTANI MURRAYJONESPARSLOW FILTER_INITIAL_STATE
 %token NONLINEAR_FILTER_INITIALIZATION FILTER_ALGORITHM PROPOSAL_APPROXIMATION CUBATURE UNSCENTED MONTECARLO DISTRIBUTION_APPROXIMATION
 %token <string_val> NAME
 %token USE_PENALIZED_OBJECTIVE_FOR_HESSIAN INIT_STATE
@@ -232,6 +232,7 @@ statement : parameters
           | options_eq
           | varobs
           | observation_trends
+          | filter_initial_state
           | unit_root_vars
           | dsample
           | rplot
@@ -1904,6 +1905,14 @@ trend_list : trend_list trend_element
 
 trend_element :  symbol '(' expression ')' ';' { driver.set_trend_element($1, $3); };
 
+filter_initial_state : FILTER_INITIAL_STATE ';' filter_initial_state_list END ';' { driver.set_filter_initial_state(); };
+
+filter_initial_state_list : filter_initial_state_list filter_initial_state_element
+                          | filter_initial_state_element
+                          ;
+
+filter_initial_state_element : symbol '(' signed_integer ')' EQUAL expression ';' { driver.set_filter_initial_state_element($1, $3, $6); };
+
 unit_root_vars : UNIT_ROOT_VARS symbol_list ';' { driver.set_unit_root_vars(); };
 
 optim_weights : OPTIM_WEIGHTS ';' optim_weights_list END ';' { driver.optim_weights(); };
diff --git a/preprocessor/DynareFlex.ll b/preprocessor/DynareFlex.ll
index 0a1588c5ae79d33eeb578b6501dcdb9f51dd0c81..1581ae094d3dc7f3f6eb8666b98a271e15f12d5f 100644
--- a/preprocessor/DynareFlex.ll
+++ b/preprocessor/DynareFlex.ll
@@ -189,6 +189,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>initval {BEGIN DYNARE_BLOCK; return token::INITVAL;}
 <INITIAL>endval {BEGIN DYNARE_BLOCK; return token::ENDVAL;}
 <INITIAL>histval {BEGIN DYNARE_BLOCK; return token::HISTVAL;}
+<INITIAL>filter_initial_state {BEGIN DYNARE_BLOCK; return token::FILTER_INITIAL_STATE;}
 <INITIAL>shocks {BEGIN DYNARE_BLOCK; return token::SHOCKS;}
 <INITIAL>shock_groups {BEGIN DYNARE_BLOCK; return token::SHOCK_GROUPS;}
 <INITIAL>mshocks {BEGIN DYNARE_BLOCK; return token::MSHOCKS;}
diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc
index c0f4729164487a325df2761971d419032ce76b90..8d1d24e887ee43ff6a928871a163c3d1c9a5b4f3 100644
--- a/preprocessor/ParsingDriver.cc
+++ b/preprocessor/ParsingDriver.cc
@@ -1783,6 +1783,13 @@ ParsingDriver::set_trends()
   trend_elements.clear();
 }
 
+void
+ParsingDriver::set_filter_initial_state()
+{
+  mod_file->addStatement(new FilterInitialStateStatement(filter_initial_state_elements, mod_file->symbol_table));
+  filter_initial_state_elements.clear();
+}
+
 void
 ParsingDriver::set_trend_element(string *arg1, expr_t arg2)
 {
@@ -1793,6 +1800,39 @@ ParsingDriver::set_trend_element(string *arg1, expr_t arg2)
   delete arg1;
 }
 
+void
+ParsingDriver::set_filter_initial_state_element(string *name, string *lag, expr_t rhs)
+{
+  check_symbol_existence(*name);
+  int symb_id = mod_file->symbol_table.getID(*name);
+  SymbolType type = mod_file->symbol_table.getType(symb_id);
+  int ilag = atoi(lag->c_str());
+
+  if (type != eEndogenous
+      && type != eExogenous
+      && type != eExogenousDet)
+    error("filter_initial_state: " + *name + " should be an endogenous or exogenous variable");
+
+  if ((type == eExogenous || type == eExogenousDet) && lag == 0)
+    error("filter_initial_state: exogenous variable " + *name + " must be provided with a lag");
+
+  pair<int, int> key(symb_id, ilag);
+  if (filter_initial_state_elements.find(key) != filter_initial_state_elements.end())
+    error("filter_initial_state: (" + *name + ", " + *lag + ") declared twice");
+
+  if (mod_file->dynamic_model.minLagForSymbol(symb_id) > ilag - 1)
+    {
+      ostringstream s;
+      s << ilag - 1;
+      error("filter_initial_state: variable " + *name + " does not appear in the model with the lag " + s.str() + " (see the reference manual for the timing convention in 'filter_initial_state')");
+    }
+
+  filter_initial_state_elements[key] = rhs;
+
+  delete name;
+  delete lag;
+}
+
 void
 ParsingDriver::set_optim_weights(string *name, expr_t value)
 {
diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh
index bc9729fff47dbba5dae1df6bc9294f87ef500262..5f277f2be1edc76e2a4aa28bb6b68e72b617cdce 100644
--- a/preprocessor/ParsingDriver.hh
+++ b/preprocessor/ParsingDriver.hh
@@ -125,6 +125,8 @@ private:
   OptionsList options_list;
   //! Temporary storage for trend elements
   ObservationTrendsStatement::trend_elements_t trend_elements;
+  //! Temporary storage for filter_initial_state elements
+  FilterInitialStateStatement::filter_initial_state_elements_t filter_initial_state_elements;
   //! Temporary storage for filename list of ModelComparison (contains weights)
   ModelComparisonStatement::filename_list_t filename_list;
   //! Temporary storage for list of EstimationParams (from estimated_params* statements)
@@ -523,6 +525,10 @@ public:
   void forecast();
   void set_trends();
   void set_trend_element(string *arg1, expr_t arg2);
+  //! filter_initial_state block
+  void set_filter_initial_state();
+  //! element for filter_initial_state block
+  void set_filter_initial_state_element(string *name, string *lag, expr_t rhs);
   void set_unit_root_vars();
   void optim_weights();
   void set_optim_weights(string *name, expr_t value);