diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 84aefaafcfd0bf90aeb00de059978e3935c44bd8..3eb18aa3d17dba318775dc12ac2ae66e4875f817 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -3972,7 +3972,58 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool bytecode
   else if (julia)
     writeDynamicJuliaFile(basename);
   else
-    writeDynamicMFile(t_basename);
+    {
+      writeDynamicMFile(t_basename);
+      writeSetAuxiliaryVariables(t_basename, julia);
+    }
+}
+
+void
+DynamicModel::writeSetAuxiliaryVariables(const string &basename, const bool julia) const
+{
+  ostringstream output_func_body;
+  writeAuxVarRecursiveDefinitions(output_func_body, oMatlabDseries);
+
+  if (output_func_body.str().empty())
+    return;
+
+  string func_name = basename + "_set_auxiliary_series";
+  string filename = julia ? func_name + ".jl" : func_name + ".m";
+  string comment = julia ? "#" : "%";
+
+  ofstream output;
+  output.open(filename.c_str(), ios::out | ios::binary);
+  if (!output.is_open())
+    {
+      cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  output << "function ds = " << func_name + "(ds, params)" << endl
+         << comment << endl
+         << comment << " Status : Computes Auxiliary variables of the dynamic model and returns a dseries" << endl
+         << comment << endl
+         << comment << " Warning : this file is generated automatically by Dynare" << endl
+         << comment << "           from model file (.mod)" << endl << endl
+         << output_func_body.str();
+
+  output.close();
+}
+
+void
+DynamicModel::writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputType output_type) const
+{
+  deriv_node_temp_terms_t tef_terms;
+  temporary_terms_t temporary_terms;
+  for (int i = 0; i < (int) aux_equations.size(); i++)
+    if (dynamic_cast<ExprNode *>(aux_equations[i])->containsExternalFunction())
+      dynamic_cast<ExprNode *>(aux_equations[i])->writeExternalFunctionOutput(output, output_type,
+                                                                              temporary_terms, tef_terms);
+  for (int i = 0; i < (int) aux_equations.size(); i++)
+    {
+      dynamic_cast<ExprNode *>(aux_equations[i])->writeOutput(output, output_type, temporary_terms, tef_terms);
+      output << ";" << endl;
+    }
 }
 
 void
@@ -4848,6 +4899,39 @@ DynamicModel::substituteLeadLagInternal(aux_var_t type, bool deterministic_model
       aux_equations[i] = substeq;
     }
 
+ // Substitute in diff_aux_equations
+  // Without this loop, the auxiliary equations in equations
+  // will diverge from those in diff_aux_equations
+  for (int i = 0; i < (int) diff_aux_equations.size(); i++)
+    {
+      expr_t subst;
+      switch (type)
+        {
+        case avEndoLead:
+          subst = diff_aux_equations[i]->substituteEndoLeadGreaterThanTwo(subst_table,
+                                                                     neweqs, deterministic_model);
+          break;
+        case avEndoLag:
+          subst = diff_aux_equations[i]->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
+          break;
+        case avExoLead:
+          subst = diff_aux_equations[i]->substituteExoLead(subst_table, neweqs, deterministic_model);
+          break;
+        case avExoLag:
+          subst = diff_aux_equations[i]->substituteExoLag(subst_table, neweqs);
+          break;
+        case avDiffForward:
+          subst = diff_aux_equations[i]->differentiateForwardVars(subset, subst_table, neweqs);
+          break;
+        default:
+          cerr << "DynamicModel::substituteLeadLagInternal: impossible case" << endl;
+          exit(EXIT_FAILURE);
+        }
+      BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(subst);
+      assert(substeq != NULL);
+      diff_aux_equations[i] = substeq;
+    }
+
   // Add new equations
   for (int i = 0; i < (int) neweqs.size(); i++)
     addEquation(neweqs[i], -1);
@@ -4897,20 +4981,29 @@ DynamicModel::substituteAdl()
 }
 
 void
-DynamicModel::substituteDiff()
+DynamicModel::substituteDiff(StaticModel &static_model)
 {
-  ExprNode::subst_table_t subst_table;
-  vector<BinaryOpNode *> neweqs;
+  // Find diff Nodes
+  diff_table_t diff_table;
+  for (map<int, expr_t>::iterator it = local_variables_table.begin();
+       it != local_variables_table.end(); it++)
+    it->second->findDiffNodes(static_model, diff_table);
+
+  for (int i = 0; i < (int) equations.size(); i++)
+    equations[i]->findDiffNodes(static_model, diff_table);
 
   // Substitute in model local variables
+  vector<BinaryOpNode *> neweqs;
+  ExprNode::subst_table_t diff_subst_table;
   for (map<int, expr_t>::iterator it = local_variables_table.begin();
        it != local_variables_table.end(); it++)
-    it->second = it->second->substituteDiff(subst_table, neweqs);
+    it->second = it->second->substituteDiff(static_model, diff_table, diff_subst_table, neweqs);
 
   // Substitute in equations
   for (int i = 0; i < (int) equations.size(); i++)
     {
-      BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->substituteDiff(subst_table, neweqs));
+      BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->
+                                                           substituteDiff(static_model, diff_table, diff_subst_table, neweqs));
       assert(substeq != NULL);
       equations[i] = substeq;
     }
@@ -4919,10 +5012,18 @@ DynamicModel::substituteDiff()
   for (int i = 0; i < (int) neweqs.size(); i++)
     addEquation(neweqs[i], -1);
 
-  if (subst_table.size() > 0)
+  copy(neweqs.begin(), neweqs.end(), back_inserter(diff_aux_equations));
+
+  if (diff_subst_table.size() > 0)
     cout << "Substitution of Diff operator: added " << neweqs.size() << " auxiliary variables and equations." << endl;
 }
 
+void
+DynamicModel::combineDiffAuxEquations()
+{
+  copy(diff_aux_equations.begin(), diff_aux_equations.end(), back_inserter(aux_equations));
+}
+
 void
 DynamicModel::substituteExpectation(bool partial_information_model)
 {
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index afcd72b9bb34ecc2aadb03360f2445ac85dba70e..ad41e03f5f9c7b2dead60ab4a4bb761296cf3a91 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -116,6 +116,9 @@ private:
   //! Writes the code of the model in virtual machine bytecode
   void writeModelEquationsCode(string &file_name, const string &bin_basename, const map_idx_t &map_idx) const;
 
+  void writeSetAuxiliaryVariables(const string &basename, const bool julia) const;
+  void writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputType output_type) const;
+
   //! Computes jacobian and prepares for equation normalization
   /*! Using values from initval/endval blocks and parameter initializations:
     - computes the jacobian for the model w.r. to contemporaneous variables
@@ -392,7 +395,10 @@ public:
   void substituteAdl();
 
   //! Substitutes diff operator
-  void substituteDiff();
+  void substituteDiff(StaticModel &static_model);
+
+  //! Adds contents of diff_aux_equations to the back of aux_equations
+  void combineDiffAuxEquations();
 
   //! Fill var_expectation_functions_to_write
   void fillVarExpectationFunctionsToWrite();
diff --git a/src/ExprNode.cc b/src/ExprNode.cc
index 43095bcfcffc0a35acca8ef61a716a4d808d62f3..f6393c7d49a6ab442f4f40abde4cb67ecd378af6 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -451,6 +451,12 @@ NumConstNode::maxLead() const
   return 0;
 }
 
+int
+NumConstNode::maxLag() const
+{
+  return 0;
+}
+
 expr_t
 NumConstNode::decreaseLeadsLags(int n) const
 {
@@ -499,8 +505,13 @@ NumConstNode::substituteAdl() const
   return const_cast<NumConstNode *>(this);
 }
 
+void
+NumConstNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
+{
+}
+
 expr_t
-NumConstNode::substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+NumConstNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   return const_cast<NumConstNode *>(this);
 }
@@ -839,6 +850,11 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
         case oCSteadyStateFile:
           output << "ys_[" << tsid << "]";
           break;
+        case oMatlabDseries:
+          output << "ds." << datatree.symbol_table.getName(symb_id);
+          if (lag != 0)
+            output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
+          break;
         default:
           cerr << "VariableNode::writeOutput: should not reach this point" << endl;
           exit(EXIT_FAILURE);
@@ -891,6 +907,11 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
         case oCSteadyStateFile:
           output << "exo_[" << i - 1 << "]";
           break;
+        case oMatlabDseries:
+          output << "ds." << datatree.symbol_table.getName(symb_id);
+          if (lag != 0)
+            output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
+          break;
         default:
           cerr << "VariableNode::writeOutput: should not reach this point" << endl;
           exit(EXIT_FAILURE);
@@ -943,6 +964,11 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
         case oCSteadyStateFile:
           output << "exo_[" << i - 1 << "]";
           break;
+        case oMatlabDseries:
+          output << "ds." << datatree.symbol_table.getName(symb_id);
+          if (lag != 0)
+            output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
+          break;
         default:
           cerr << "VariableNode::writeOutput: should not reach this point" << endl;
           exit(EXIT_FAILURE);
@@ -1282,14 +1308,35 @@ VariableNode::maxLead() const
     }
 }
 
+int
+VariableNode::maxLag() const
+{
+  switch (type)
+    {
+    case eEndogenous:
+      return -lag;
+    case eExogenous:
+      return -lag;
+    case eModelLocalVariable:
+      return datatree.local_variables_table[symb_id]->maxLag();
+    default:
+      return 0;
+    }
+}
+
 expr_t
 VariableNode::substituteAdl() const
 {
   return const_cast<VariableNode *>(this);
 }
 
+void
+VariableNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
+{
+}
+
 expr_t
-VariableNode::substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+VariableNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   return const_cast<VariableNode *>(this);
 }
@@ -2788,6 +2835,12 @@ UnaryOpNode::maxLead() const
   return arg->maxLead();
 }
 
+int
+UnaryOpNode::maxLag() const
+{
+  return arg->maxLag();
+}
+
 expr_t
 UnaryOpNode::substituteAdl() const
 {
@@ -2829,38 +2882,101 @@ UnaryOpNode::isDiffPresent() const
   return arg->isDiffPresent();
 }
 
+void
+UnaryOpNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
+{
+  if (op_code != oDiff)
+    return;
+
+  arg->findDiffNodes(static_datatree, diff_table);
+
+  expr_t sthis = this->toStatic(static_datatree);
+  int arg_max_lag = -arg->maxLag();
+  diff_table_t::iterator it = diff_table.find(sthis);
+  if (it != diff_table.end())
+    {
+      for (map<int, expr_t>::const_iterator it1 = it->second.begin();
+           it1 != it->second.end(); it1++)
+        if (arg == it1->second)
+          return;
+      it->second[arg_max_lag] = const_cast<UnaryOpNode *>(this);
+    }
+  else
+    diff_table[sthis][arg_max_lag] = const_cast<UnaryOpNode *>(this);
+}
+
 expr_t
-UnaryOpNode::substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+UnaryOpNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   if (op_code != oDiff)
     {
-      expr_t argsubst = arg->substituteDiff(subst_table, neweqs);
+      expr_t argsubst = arg->substituteDiff(static_datatree, diff_table, subst_table, neweqs);
       return buildSimilarUnaryOpNode(argsubst, datatree);
     }
 
-  subst_table_t::iterator it = subst_table.find(const_cast<UnaryOpNode *>(this));
-  if (it != subst_table.end())
-    return const_cast<VariableNode *>(it->second);
+  subst_table_t::const_iterator sit = subst_table.find(this);
+  if (sit != subst_table.end())
+    return const_cast<VariableNode *>(sit->second);
 
-  expr_t argsubst = arg->substituteDiff(subst_table, neweqs);
-  assert(argsubst != NULL);
+  expr_t sthis = dynamic_cast<UnaryOpNode *>(this->toStatic(static_datatree));
+  diff_table_t::iterator it = diff_table.find(sthis);
+  assert(it != diff_table.end() && it->second[-arg->maxLag()] == this);
 
-  int symb_id = -1;
-  VariableNode *vn = dynamic_cast<VariableNode *>(argsubst);
-  if (vn != NULL)
-    symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, argsubst, vn->get_symb_id(), vn->get_lag());
-  else
-    symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, argsubst);
-
-  expr_t newAuxVar = datatree.AddVariable(symb_id, 0);
-
-  //AUX_DIFF_IDX = argsubst - argsubst(-1)
-  neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(newAuxVar,
-                                                                  datatree.AddMinus(argsubst, argsubst->decreaseLeadsLags(1)))));
-
-  assert(dynamic_cast<VariableNode *>(newAuxVar) != NULL);
-  subst_table[this] = dynamic_cast<VariableNode *>(newAuxVar);
-  return newAuxVar;
+  int last_arg_max_lag;
+  VariableNode *last_aux_var;
+  for (map<int, expr_t>::reverse_iterator rit = it->second.rbegin();
+       rit != it->second.rend(); rit++)
+    {
+      expr_t argsubst = dynamic_cast<UnaryOpNode *>(rit->second)->
+          get_arg()->substituteDiff(static_datatree, diff_table, subst_table, neweqs);
+      int symb_id;
+      VariableNode *vn = dynamic_cast<VariableNode *>(argsubst);
+      if (rit == it->second.rbegin())
+        {
+          if (vn != NULL)
+            symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, argsubst, vn->get_symb_id(), vn->get_lag());
+          else
+            symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, argsubst);
+
+          // make originating aux var & equation
+          last_arg_max_lag = rit->first;
+          last_aux_var = datatree.AddVariable(symb_id, 0);
+          //ORIG_AUX_DIFF = argsubst - argsubst(-1)
+          neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(last_aux_var,
+                                                                          datatree.AddMinus(argsubst,
+                                                                                            argsubst->decreaseLeadsLags(1)))));
+          subst_table[rit->second] = dynamic_cast<VariableNode *>(last_aux_var);
+        }
+      else
+        {
+          // just add equation of form: AUX_DIFF = ORIG_AUX_DIFF(last_arg_max_lag - rit->first)
+          VariableNode *new_aux_var;
+          for (int i = last_arg_max_lag; i > rit->first; i--)
+            {
+              if (vn == NULL)
+                if (i == last_arg_max_lag)
+                  symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, argsubst);
+                else
+                  symb_id = datatree.symbol_table.addDiffAuxiliaryVar(new_aux_var->idx, new_aux_var);
+              else
+                if (i == last_arg_max_lag)
+                  symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, argsubst,
+                                                                      vn->get_symb_id(), i - 1);
+                else
+                  symb_id = datatree.symbol_table.addDiffAuxiliaryVar(new_aux_var->idx, new_aux_var,
+                                                                      vn->get_symb_id(), i - 1);
+
+
+              new_aux_var = datatree.AddVariable(symb_id, 0);
+              neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(new_aux_var,
+                                                                              last_aux_var->decreaseLeadsLags(1))));
+              last_aux_var = new_aux_var;
+            }
+          subst_table[rit->second] = dynamic_cast<VariableNode *>(new_aux_var);
+          last_arg_max_lag = rit->first;
+        }
+    }
+  return const_cast<VariableNode *>(subst_table[this]);
 }
 
 expr_t
@@ -4355,6 +4471,12 @@ BinaryOpNode::maxLead() const
   return max(arg1->maxLead(), arg2->maxLead());
 }
 
+int
+BinaryOpNode::maxLag() const
+{
+  return max(arg1->maxLag(), arg2->maxLag());
+}
+
 expr_t
 BinaryOpNode::decreaseLeadsLags(int n) const
 {
@@ -4491,11 +4613,18 @@ BinaryOpNode::substituteAdl() const
   return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
 }
 
+void
+BinaryOpNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
+{
+  arg1->findDiffNodes(static_datatree, diff_table);
+  arg2->findDiffNodes(static_datatree, diff_table);
+}
+
 expr_t
-BinaryOpNode::substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+BinaryOpNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
-  expr_t arg1subst = arg1->substituteDiff(subst_table, neweqs);
-  expr_t arg2subst = arg2->substituteDiff(subst_table, neweqs);
+  expr_t arg1subst = arg1->substituteDiff(static_datatree, diff_table, subst_table, neweqs);
+  expr_t arg2subst = arg2->substituteDiff(static_datatree, diff_table, subst_table, neweqs);
   return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
 }
 
@@ -5260,6 +5389,12 @@ TrinaryOpNode::maxLead() const
   return max(arg1->maxLead(), max(arg2->maxLead(), arg3->maxLead()));
 }
 
+int
+TrinaryOpNode::maxLag() const
+{
+  return max(arg1->maxLag(), max(arg2->maxLag(), arg3->maxLag()));
+}
+
 expr_t
 TrinaryOpNode::decreaseLeadsLags(int n) const
 {
@@ -5346,12 +5481,20 @@ TrinaryOpNode::substituteAdl() const
   return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
 }
 
+void
+TrinaryOpNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
+{
+  arg1->findDiffNodes(static_datatree, diff_table);
+  arg2->findDiffNodes(static_datatree, diff_table);
+  arg3->findDiffNodes(static_datatree, diff_table);
+}
+
 expr_t
-TrinaryOpNode::substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+TrinaryOpNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
-  expr_t arg1subst = arg1->substituteDiff(subst_table, neweqs);
-  expr_t arg2subst = arg2->substituteDiff(subst_table, neweqs);
-  expr_t arg3subst = arg3->substituteDiff(subst_table, neweqs);
+  expr_t arg1subst = arg1->substituteDiff(static_datatree, diff_table, subst_table, neweqs);
+  expr_t arg2subst = arg2->substituteDiff(static_datatree, diff_table, subst_table, neweqs);
+  expr_t arg3subst = arg3->substituteDiff(static_datatree, diff_table, subst_table, neweqs);
   return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
 }
 
@@ -5634,6 +5777,16 @@ AbstractExternalFunctionNode::maxLead() const
   return val;
 }
 
+int
+AbstractExternalFunctionNode::maxLag() const
+{
+  int val = 0;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    val = max(val, (*it)->maxLag());
+  return val;
+}
+
 expr_t
 AbstractExternalFunctionNode::decreaseLeadsLags(int n) const
 {
@@ -5706,12 +5859,19 @@ AbstractExternalFunctionNode::substituteAdl() const
   return buildSimilarExternalFunctionNode(arguments_subst, datatree);
 }
 
+void
+AbstractExternalFunctionNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
+{
+  for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
+    (*it)->findDiffNodes(static_datatree, diff_table);
+}
+
 expr_t
-AbstractExternalFunctionNode::substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+AbstractExternalFunctionNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
-    arguments_subst.push_back((*it)->substituteDiff(subst_table, neweqs));
+    arguments_subst.push_back((*it)->substituteDiff(static_datatree, diff_table, subst_table, neweqs));
   return buildSimilarExternalFunctionNode(arguments_subst, datatree);
 }
 
@@ -7112,6 +7272,12 @@ VarExpectationNode::maxLead() const
   return 0;
 }
 
+int
+VarExpectationNode::maxLag() const
+{
+  return 0;
+}
+
 expr_t
 VarExpectationNode::decreaseLeadsLags(int n) const
 {
@@ -7229,8 +7395,13 @@ VarExpectationNode::substituteAdl() const
   return const_cast<VarExpectationNode *>(this);
 }
 
+void
+VarExpectationNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
+{
+}
+
 expr_t
-VarExpectationNode::substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+VarExpectationNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   return const_cast<VarExpectationNode *>(this);
 }
@@ -7530,6 +7701,12 @@ PacExpectationNode::maxLead() const
   return 0;
 }
 
+int
+PacExpectationNode::maxLag() const
+{
+  return 0;
+}
+
 expr_t
 PacExpectationNode::decreaseLeadsLags(int n) const
 {
@@ -7646,8 +7823,13 @@ PacExpectationNode::substituteAdl() const
   return const_cast<PacExpectationNode *>(this);
 }
 
+void
+PacExpectationNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
+{
+}
+
 expr_t
-PacExpectationNode::substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+PacExpectationNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   return const_cast<PacExpectationNode *>(this);
 }
diff --git a/src/ExprNode.hh b/src/ExprNode.hh
index 7fe371cc4368230694808cdbe7d39929f8a88731..1ea6dbb5a48020dd1078e70b9776a724862ec312 100644
--- a/src/ExprNode.hh
+++ b/src/ExprNode.hh
@@ -34,6 +34,7 @@ using namespace std;
 
 class DataTree;
 class VariableNode;
+class UnaryOpNode;
 class BinaryOpNode;
 class PacExpectationNode;
 
@@ -57,6 +58,9 @@ typedef map<int, double> eval_context_t;
 //! Type for tracking first/second derivative functions that have already been written as temporary terms
 typedef map<pair<int, vector<expr_t> >, int> deriv_node_temp_terms_t;
 
+//! Type for the substitution map used in the process of substitutitng diff expressions
+typedef map<expr_t, map<int, expr_t> > diff_table_t;
+
 //! Possible types of output when writing ExprNode(s)
 enum ExprNodeOutputType
   {
@@ -79,7 +83,8 @@ enum ExprNodeOutputType
     oJuliaDynamicSteadyStateOperator,             //!< Julia code, dynamic model, inside a steady state operator
     oSteadyStateFile,                             //!< Matlab code, in the generated steady state file
     oCSteadyStateFile,                            //!< C code, in the generated steady state file
-    oJuliaSteadyStateFile                         //!< Julia code, in the generated steady state file
+    oJuliaSteadyStateFile,                        //!< Julia code, in the generated steady state file
+    oMatlabDseries                                //!< Matlab code for dseries
   };
 
 #define IS_MATLAB(output_type) ((output_type) == oMatlabStaticModel     \
@@ -89,7 +94,8 @@ enum ExprNodeOutputType
                                 || (output_type) == oMatlabDynamicModelSparse \
                                 || (output_type) == oMatlabDynamicSteadyStateOperator \
                                 || (output_type) == oMatlabDynamicSparseSteadyStateOperator \
-                                || (output_type) == oSteadyStateFile)
+                                || (output_type) == oSteadyStateFile \
+                                || (output_type) == oMatlabDseries)
 
 #define IS_JULIA(output_type) ((output_type) == oJuliaStaticModel       \
                                || (output_type) == oJuliaDynamicModel   \
@@ -339,6 +345,10 @@ class ExprNode
       /*! A negative value means that the expression contains only lagged variables */
       virtual int maxLead() const = 0;
 
+      //! Returns the relative period of the most backward term in this expression
+      /*! A negative value means that the expression contains only leaded variables */
+      virtual int maxLag() const = 0;
+
       //! Returns a new expression where all the leads/lags have been shifted backwards by the same amount
       /*!
         Only acts on endogenous, exogenous, exogenous det
@@ -350,8 +360,7 @@ class ExprNode
       //! Type for the substitution map used in the process of creating auxiliary vars for leads >= 2
       typedef map<const ExprNode *, const VariableNode *> subst_table_t;
 
-      //! Type for the substitution map used in the process of substituting adl/diff expressions
-      //      typedef map<const ExprNode *, const UnaryOpNode *> subst_table_diff_t;
+      //! Type for the substitution map used in the process of substituting adl expressions
       typedef map<const ExprNode *, const expr_t> subst_table_adl_t;
 
       //! Creates auxiliary endo lead variables corresponding to this expression
@@ -466,7 +475,8 @@ class ExprNode
       virtual expr_t substituteAdl() const = 0;
 
       //! Substitute diff operator
-      virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
+      virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const = 0;
+      virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
 
       //! Substitute pac_expectation operator
       virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) = 0;
@@ -544,6 +554,7 @@ public:
   virtual int maxEndoLag() const;
   virtual int maxExoLag() const;
   virtual int maxLead() const;
+  virtual int maxLag() const;
   virtual expr_t decreaseLeadsLags(int n) const;
   virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
   virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@@ -551,7 +562,8 @@ public:
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
   virtual expr_t substituteAdl() const;
-  virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
+  virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const;
+  virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table);
   virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
   virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@@ -625,6 +637,7 @@ public:
   virtual int maxEndoLag() const;
   virtual int maxExoLag() const;
   virtual int maxLead() const;
+  virtual int maxLag() const;
   virtual expr_t decreaseLeadsLags(int n) const;
   virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
   virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@@ -632,7 +645,8 @@ public:
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
   virtual expr_t substituteAdl() const;
-  virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
+  virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const;
+  virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table);
   virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
   virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@@ -726,6 +740,7 @@ public:
   virtual int maxEndoLag() const;
   virtual int maxExoLag() const;
   virtual int maxLead() const;
+  virtual int maxLag() const;
   virtual expr_t decreaseLeadsLags(int n) const;
   virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
   //! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and argument
@@ -735,7 +750,8 @@ public:
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
   virtual expr_t substituteAdl() const;
-  virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
+  virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const;
+  virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table);
   virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
   virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@@ -845,6 +861,7 @@ public:
   virtual int maxEndoLag() const;
   virtual int maxExoLag() const;
   virtual int maxLead() const;
+  virtual int maxLag() const;
   virtual expr_t decreaseLeadsLags(int n) const;
   virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
   //! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and arguments
@@ -854,7 +871,8 @@ public:
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
   virtual expr_t substituteAdl() const;
-  virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
+  virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const;
+  virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table);
   virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
   virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@@ -941,6 +959,7 @@ public:
   virtual int maxEndoLag() const;
   virtual int maxExoLag() const;
   virtual int maxLead() const;
+  virtual int maxLag() const;
   virtual expr_t decreaseLeadsLags(int n) const;
   virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
   //! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and arguments
@@ -950,7 +969,8 @@ public:
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
   virtual expr_t substituteAdl() const;
-  virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
+  virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const;
+  virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table);
   virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
   virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@@ -1039,6 +1059,7 @@ public:
   virtual int maxEndoLag() const;
   virtual int maxExoLag() const;
   virtual int maxLead() const;
+  virtual int maxLag() const;
   virtual expr_t decreaseLeadsLags(int n) const;
   virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
   virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@@ -1046,7 +1067,8 @@ public:
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
   virtual expr_t substituteAdl() const;
-  virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
+  virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const;
+  virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table);
   virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const = 0;
   virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
@@ -1220,6 +1242,7 @@ public:
   virtual int maxEndoLag() const;
   virtual int maxExoLag() const;
   virtual int maxLead() const;
+  virtual int maxLag() const;
   virtual expr_t decreaseLeadsLags(int n) const;
   virtual void prepareForDerivation();
   virtual expr_t computeDerivative(int deriv_id);
@@ -1233,7 +1256,8 @@ public:
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
   virtual expr_t substituteAdl() const;
-  virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
+  virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const;
+  virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table);
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number,
@@ -1295,6 +1319,7 @@ public:
   virtual int maxEndoLag() const;
   virtual int maxExoLag() const;
   virtual int maxLead() const;
+  virtual int maxLag() const;
   virtual expr_t decreaseLeadsLags(int n) const;
   virtual void prepareForDerivation();
   virtual expr_t computeDerivative(int deriv_id);
@@ -1308,7 +1333,8 @@ public:
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
   virtual expr_t substituteAdl() const;
-  virtual expr_t substituteDiff(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
+  virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const;
+  virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table);
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number,
diff --git a/src/ModFile.cc b/src/ModFile.cc
index eb4a374b2b73e53277f46c15769ee4030dbff03e..b5fd81d87ba1cd0f32bf056b72a0c45d89c5abef 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -39,6 +39,7 @@ ModFile::ModFile(WarningConsolidation &warnings_arg)
     orig_ramsey_dynamic_model(symbol_table, num_constants, external_functions_table),
     static_model(symbol_table, num_constants, external_functions_table),
     steady_state_model(symbol_table, num_constants, external_functions_table, static_model),
+    diff_static_model(symbol_table, num_constants, external_functions_table),
     linear(false), block(false), byte_code(false), use_dll(false), no_static(false),
     differentiate_forward_vars(false), nonstationary_variables(false),
     param_used_with_lead_lag(false), warnings(warnings_arg)
@@ -362,7 +363,7 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
     }
 
   // Create auxiliary variable and equations for Diff operator
-  dynamic_model.substituteDiff();
+  dynamic_model.substituteDiff(diff_static_model);
 
   // Var Model
   map<string, pair<SymbolList, int> > var_model_info_var_expectation;
@@ -478,6 +479,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
       dynamic_model.substituteEndoLagGreaterThanTwo(true);
     }
 
+  dynamic_model.combineDiffAuxEquations();
+
   if (differentiate_forward_vars)
     dynamic_model.differentiateForwardVars(differentiate_forward_vars_subset);
 
diff --git a/src/ModFile.hh b/src/ModFile.hh
index ac678b5b52ba79970f086d25b72a0c50878e3410..08ee6c4213b839a854b705ab1b0acf70e43ae3e1 100644
--- a/src/ModFile.hh
+++ b/src/ModFile.hh
@@ -72,6 +72,8 @@ public:
   StaticModel static_model;
   //! Static model, as declared in the "steady_state_model" block if present
   SteadyStateModel steady_state_model;
+  //! Static model used for mapping arguments of diff operator
+  StaticModel diff_static_model;
   //! Option linear
   bool linear;
 
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index be6b66cbbf7646be6c35e1fa1e2414eadf836bd8..312169a1f90bfc7d3af1d8d3f2f14f76cfe6f1ed 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -60,6 +60,12 @@ protected:
 
   //! Only stores generated auxiliary equations, in an order meaningful for evaluation
   deque<BinaryOpNode *> aux_equations;
+  //! Temporarily stores aux equations for diff operator
+  //! This is a hack to make diff aux vars work: they must be substituted before we consider VARs
+  //! But leads lags can't be substituted until after we consider VARs
+  //! The diff_aux_vars may depend on aux_vars created for leads lags, as in
+  //! diff(x(-1)) => x(-1) - x(-2) => x(-1) - aux_var(-1); aux_var = x(-1);
+  deque<BinaryOpNode *> diff_aux_equations;
 
   //! Stores equation tags
   vector<pair<int, pair<string, string> > > equation_tags;
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 11a033a867280b3ce747d9ef8319d11c4bd58d43..1ef7bad5a0e1e0a7ace36d9577f1f00fd97216ba 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -2162,6 +2162,8 @@ StaticModel::writeSetAuxiliaryVariables(const string &basename, const bool julia
          << comment << " Warning : this file is generated automatically by Dynare" << endl
          << comment << "           from model file (.mod)" << endl << endl
          << output_func_body.str();
+
+  output.close();
 }
 
 void
diff --git a/src/SymbolTable.cc b/src/SymbolTable.cc
index ad61e3749c2b089a88d80af2b86d7bfd2cd7365d..3220685771f1013dafdb1bf21f7b23f37647f6e2 100644
--- a/src/SymbolTable.cc
+++ b/src/SymbolTable.cc
@@ -732,7 +732,7 @@ SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, i
 int
 SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg) throw (FrozenException)
 {
-  return addDiffAuxiliaryVar(index, expr_arg, 0, 0);
+  return addDiffAuxiliaryVar(index, expr_arg, -1, 0);
 }
 
 int