diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 92fcc25326e3db2a87c18901c4030d215ff31456..9f206d63860a66981fd0bf287b37129439f3224f 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -3972,7 +3972,56 @@ 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_variables_as_dseries";
+  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();
+}
+
+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 +4897,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);
@@ -4928,12 +5010,18 @@ DynamicModel::substituteDiff(StaticModel &static_model)
   for (int i = 0; i < (int) neweqs.size(); i++)
     addEquation(neweqs[i], -1);
 
-  copy(neweqs.begin(), neweqs.end(), back_inserter(aux_equations));
+  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 dda2a2aaba63f5767580884a90d6b6fe1b869b31..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
@@ -394,6 +397,9 @@ public:
   //! Substitutes diff operator
   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 d0c28be33e9a61508f215e81481cde6d83932134..fa0cdf4275616fce7c82c59b91fa8de01a423af5 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -850,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);
@@ -902,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);
@@ -954,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);
@@ -2907,40 +2922,55 @@ UnaryOpNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table,
   diff_table_t::iterator it = diff_table.find(sthis);
   assert(it != diff_table.end() && it->second[-arg->maxLag()] == this);
 
-  int origin_arg_max_lag;
-  VariableNode *origin_aux_var;
+  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 (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);
-
       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
-          origin_arg_max_lag = rit->first;
-          origin_aux_var = datatree.AddVariable(symb_id, 0);
+          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(origin_aux_var,
+          neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(last_aux_var,
                                                                           datatree.AddMinus(argsubst,
                                                                                             argsubst->decreaseLeadsLags(1)))));
-          subst_table[rit->second] = dynamic_cast<VariableNode *>(origin_aux_var);
+          subst_table[rit->second] = dynamic_cast<VariableNode *>(last_aux_var);
         }
       else
         {
-          // just add equation of form: AUX_DIFF = ORIG_AUX_DIFF(origin_arg_max_lag - rit->first)
-          VariableNode *new_aux_var = datatree.AddVariable(symb_id, 0);
-          neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(new_aux_var,
-                                                                          origin_aux_var->decreaseLeadsLags(origin_arg_max_lag
-                                                                                                                - rit->first))));
+          // 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)
+                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]);
diff --git a/src/ExprNode.hh b/src/ExprNode.hh
index 052c148bc816515da77e7cb6f2e93454df0fcb42..1ea6dbb5a48020dd1078e70b9776a724862ec312 100644
--- a/src/ExprNode.hh
+++ b/src/ExprNode.hh
@@ -83,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     \
@@ -93,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   \
diff --git a/src/ModFile.cc b/src/ModFile.cc
index df36512cc309b254e981147daf5ee8b93757c7d9..b5fd81d87ba1cd0f32bf056b72a0c45d89c5abef 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -479,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/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;