Grid maker 1.1 - page 4

Forex Trader
114538
Forex Trader  
sorry cori, i only have one order for any given grid postion and i have tested just about all the variations - over several weeks now.

I do occasionally delete all open orders so that our MT4 friends dont get upset.

u will get this problem in back testing but this is not a script problem.. but a MT4 backtesting problem.

If it continues, please let me know or send me some reports showing the problem...

thanks and reagrds,

hugues
Forex Trader
114538
Forex Trader  
I have found it. And I am not amused about it.

The advisor is creating the grid with my given comment "GridEURUSD". This comment stands in the Commentfield as long as the order is waiting. If the order is activated, the comment changes to "activate/auto". After all its clear that this behavior leds to the described problem.

I am trading with Alpari. They are supporting MT4 in demo accounts

I will check, if I can go around this behavior, i.e. using the magic of the order as identifier for the grid and let you know the results.

While testing this, I have also made modifications to the cleanup script for the grid. I have added functionality to close open orders too. Unfortunately I get error 129 which means Order locked, if I try to close an open order. But it deletes all pending orders for the given grid.

//+------------------------------------------------------------------+
//|                                                   RemoveGrid.mq4 |
//|                                            Copyright © 2005, hdb |
//|                                       http://www.dubois1.net/hdb |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, hdb"
#property link      "http://www.dubois1.net/hdb"

extern string GridName      = "Grid";
extern bool   closeOpen     = false;

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
 
 
 #property show_inputs              // shows the parameters - thanks Slawa... 

//---- 
  int total = OrdersTotal();
  int i ;
  
      for(i=total-1; i>=0;i--)
 
      {
        OrderSelect(i, SELECT_BY_POS);
        int type   = OrderType();

        if ( OrderSymbol()==Symbol() && OrderComment() == GridName )
        {
          bool result = false;
    
          switch(type)
          {
            case OP_BUY       : if  ( closeOpen ) {
                                    result = OrderClose( OrderTicket(), OrderLots(), Ask, 0, Blue );
                                }
                                break;
            case OP_SELL      : if  ( closeOpen ) {
                                    result = OrderClose( OrderTicket(), OrderLots(), Bid, 0, Blue );
                                }
                                break;
            //Close pending orders
            case OP_BUYLIMIT  : result = OrderDelete( OrderTicket() );
                                break; 
            case OP_BUYSTOP   : result = OrderDelete( OrderTicket() ); 
                                break; 
            case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); 
                                break; 
            case OP_SELLSTOP  : result = OrderDelete( OrderTicket() ); 
                                break; 
          }
    
          if(result == false)
          {
            Print("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
     //       Sleep(3000);
          }  
        }
      }
 
//----
   return(0);
  }
//+------------------------------------------------------------------+




cori

Forex Trader
114538
Forex Trader  
ok cori, thanks..

let me know if it works and i will use the magic.. as i was unaware that the broker does strange things like that!!

thanks and regards,

hugues
Forex Trader
114538
Forex Trader  
Now, thats it.

I have changed the gridMaker to use the OrderMagicNumber instead of the comment. I have also made some small modification about building the comment.

Here is the result.

//+------------------------------------------------------------------+
//|                                                     MakeGrid.mq4 |
//|                                            Copyright © 2005, hdb |
//|                                       http://www.dubois1.net/hdb |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, hdb"
#property link      "http://www.dubois1.net/hdb"
//#property version      "1.4beta"

// modified by cori. Using OrderMagicNumber to identify the trades of the grid
extern int    uniqueGridMagic = 11111;   // Magic number of the trades. must be unique to identify
                                         // the trades of one grid    
extern double Lots = 0.1;                // 
extern double GridSize = 6;              // pips between orders - grid or mesh size
extern double GridSteps = 12;            // total number of orders to place
extern double TakeProfit = 6 ;           // number of ticks to take profit. normally is = grid size but u can override
extern double StopLoss = 0;              // if u want to add a stop loss. normal grids dont use stop losses
extern double UpdateInterval = 1;        // update orders every x minutes
extern bool   wantLongs = true;          //  do we want long positions
extern bool   wantShorts = true;         //  do we want short positions
extern bool   wantBreakout = true;       // do we want longs above price, shorts below price
extern bool   wantCounter = true;        // do we want longs below price, shorts above price
extern bool   limitEMA34 = false;        // do we want longs above ema only, shorts below ema only

// modified by cori. internal variables only
double        LastUpdate = 0;            // counter used to note time of last update
double        GridMaxOpen = 0;           // maximum number of open positions
string        GridName = "Grid";         // identifies the grid. allows for several co-existing grids
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
 #property show_inputs                  // shows the parameters - thanks Slawa...    
 if ( TakeProfit <= 0 )                 // 
   { TakeProfit = GridSize; }
//----
   GridName = StringConcatenate( "Grid", Symbol() );
   return(0);
  }
//+------------------------------------------------------------------------+
//| tests if there is an open position or order in the region of atRate    |
//|     will check for longs if checkLongs is true, else will check        |
//|     for shorts                                                         |
//+------------------------------------------------------------------------+

bool IsPosition(double atRate, double inRange, bool checkLongs )
  {
  
     int totalorders = OrdersTotal();
     for(int j=0;j<totalorders;j++)                                // scan all orders and positions...
      {
        OrderSelect(j, SELECT_BY_POS);
        // modified by cori. Using OrderMagicNumber to identify the trades of the grid
        if ( OrderSymbol()==Symbol() && OrderMagicNumber() == uniqueGridMagic )  // only look if mygrid and symbol...
         {  int type = OrderType();
            if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // dont look for exact price but price proximity (less than gridsize)
              { if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT  || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT  || type == OP_SELLSTOP ) ) )
                 { 
                    return(true); 
                 }
              }
         }
      } 

   return(false);
  }
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   int    i, j,k, ticket, entermode, totalorders;
   bool   doit;
   double point, startrate, traderate;
 
//----
  if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60)           // we update the first time it is called and every UpdateInterval minutes
   {
   LastUpdate = CurTime();
   Print("Updating");
   point = MarketInfo(Symbol(),MODE_POINT);
   startrate = ( Ask + point*GridSize/2 ) / point / GridSize;    // round to a number of ticks divisible by GridSize
   k = startrate ;
   k = k * GridSize ;
   startrate = k * point - GridSize*GridSteps/2*point ;          // calculate the lowest entry point
   
   double EMA34=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE,0);
   
   for( i=0;i<GridSteps;i++)
   {
     traderate = startrate + i*point*GridSize;
     
     if ( wantLongs && (!limitEMA34 || traderate > EMA34))
       {
         if ( IsPosition(traderate,point*GridSize,true) == false )           // test if i have no open orders close to my price: if so, put one on
          {
            double myStopLoss = 0;
             if ( StopLoss > 0 )
               { myStopLoss = traderate-point*StopLoss ; }
               
             if ( traderate > Ask ) 
              { entermode = OP_BUYSTOP; } 
              else 
              { entermode = OP_BUYLIMIT ; } 
              
              if ( ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter)) ) 

              { 
                  // modified by cori. Using OrderMagicNumber to identify the trades of the grid
                  ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green); 
   
             }
          }
       }

     if ( wantShorts && (!limitEMA34 || traderate < EMA34))
       {
         if (IsPosition(traderate,point*GridSize,false)== false )           // test if i have no open orders close to my price: if so, put one on
          {
             myStopLoss = 0;
             if ( StopLoss > 0 )
               { myStopLoss = traderate+point*StopLoss ; }
             if ( traderate > Bid ) 
              { entermode = OP_SELLLIMIT; } 
              else 
              { entermode = OP_SELLSTOP ; } 
              
              if ( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) ) 
               {    
                  // modified by cori. Using OrderMagicNumber to identify the trades of the grid
                  ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red); }
          }
       }

    }
   }
   return(0);
  }
//+------------------------------------------------------------------+



with regards, cori

Forex Trader
114538
Forex Trader  
thanks cori...

since i had already done a few changes myself, i integrated your changes into the newer version.

I did do 1 little variation: in order to keep my current grids active, i put a test on magic OR gridname...

can u check if i did it correctly?



//+------------------------------------------------------------------+
//|                                                     MakeGrid.mq4 |
//|                                            Copyright © 2005, hdb |
//|                                       http://www.dubois1.net/hdb |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, hdb"
#property link      "http://www.dubois1.net/hdb"
//#property version      "1.6beta"

// modified by cori. Using OrderMagicNumber to identify the trades of the grid
extern int    uniqueGridMagic = 11111;   // Magic number of the trades. must be unique to identify
                                         // the trades of one grid    
extern double Lots = 0.1;              // 
extern double GridSize = 6;            // pips between orders - grid or mesh size
extern double GridSteps = 12;          // total number of orders to place
extern double TakeProfit = 12 ;        // number of ticks to take profit. normally is = grid size but u can override
extern double StopLoss = 0;            // if u want to add a stop loss. normal grids dont use stop losses
extern double UpdateInterval = 1;      // update orders every x minutes
extern bool   wantLongs = true;        //  do we want long positions
extern bool   wantShorts = false;      //  do we want short positions
extern bool   wantBreakout = true;     // do we want longs above price, shorts below price
extern bool   wantCounter = true;      // do we want longs below price, shorts above price
extern bool   limitEMA34 = true;       // do we want longs above ema only, shorts below ema only
extern double GridMaxOpen = 0;         // maximum number of open positions : not yet implemented..
extern bool   UseMACD = true;          // if true, will use macd >0 for longs only, macd >0 for shorts only
                                       // on crossover, will cancel all pending orders. This will override any
                                       // wantLongs and wantShort settings - at least for now.
extern bool CloseOpenPositions = false;// if UseMACD, do we also close open positions with a loss?

// modified by cori. internal variables only
string GridName = "Grid";       // identifies the grid. allows for several co-existing grids
double LastUpdate = 0;          // counter used to note time of last update

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
 #property show_inputs                  // shows the parameters - thanks Slawa...    
 if ( TakeProfit <= 0 )                 // 
   { TakeProfit = GridSize; }
//----
// added my corri and removed by hdb!! lol.. just to stay compatible with open grids...
//   GridName = StringConcatenate( "Grid", Symbol() );
   return(0);
  }
//+------------------------------------------------------------------------+
//| tests if there is an open position or order in the region of atRate    |
//|     will check for longs if checkLongs is true, else will check        |
//|     for shorts                                                         |
//+------------------------------------------------------------------------+

bool IsPosition(double atRate, double inRange, bool checkLongs )
  {
  
     int totalorders = OrdersTotal();
     for(int j=0;j<totalorders;j++)                                // scan all orders and positions...
      {
        OrderSelect(j, SELECT_BY_POS);
// modified by cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility
        if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // only look if mygrid and symbol...
         {  int type = OrderType();
            if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // dont look for exact price but price proximity (less than gridsize)
              { if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT  || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT  || type == OP_SELLSTOP ) ) )
                 { 
                    return(true); 
                 }
              }
         }
      } 
   return(false);
  }

//+------------------------------------------------------------------------+
//| cancells all pending orders                                      |
//+------------------------------------------------------------------------+

void CloseAllPendingOrders( )
  {
     int totalorders = OrdersTotal();
     for(int j=totalorders-1;j>=0;j--)                                // scan all orders and positions...
      {
        OrderSelect(j, SELECT_BY_POS);
// modified as per cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility
        if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // only look if mygrid and symbol...
         {  
          int type = OrderType();
          bool result = false;
          switch(type)
          {
             case OP_BUY       : result = true ;
             case OP_SELL      : result = true ;
            //Close pending orders
            case OP_BUYLIMIT  : result = OrderDelete( OrderTicket() ); 
            case OP_BUYSTOP   : result = OrderDelete( OrderTicket() ); 
            case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); 
            case OP_SELLSTOP  : result = OrderDelete( OrderTicket() ); 
          }
         }
      } 
   return;
  }


//+------------------------------------------------------------------------+
//| cancells all pending orders    and closes open positions               |
//+------------------------------------------------------------------------+

void CloseOpenOrders()
{
  int total = OrdersTotal();
  for(int i=total-1;i>=0;i--)
 {
    OrderSelect(i, SELECT_BY_POS);
    int type    = OrderType();
    bool result = false;
// modified by cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility
    if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // only look if mygrid and symbol...
     {
//    Print("Closing 2 ",type);
        switch(type)
         {
           //Close opened long positions
           case OP_BUY       : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red );
                               break;
           //Close opened short positions
           case OP_SELL      : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red );
                               break;
           //Close pending orders
           case OP_BUYLIMIT  :
           case OP_BUYSTOP   :
           case OP_SELLLIMIT :
           case OP_SELLSTOP  : result = OrderDelete( OrderTicket() );
         }
      }
    if(result == false)
    {
 //     Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
 //     Sleep(3000);
    }  
  }
  return;
}

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   int    i, j,k, ticket, entermode, totalorders;
   bool   doit;
   double point, startrate, traderate;
//----
  if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60)           // we update the first time it is called and every UpdateInterval minutes
   {
   LastUpdate = CurTime();
   point = MarketInfo(Symbol(),MODE_POINT);
   startrate = ( Ask + point*GridSize/2 ) / point / GridSize;    // round to a number of ticks divisible by GridSize
   k = startrate ;
   k = k * GridSize ;
   startrate = k * point - GridSize*GridSteps/2*point ;          // calculate the lowest entry point
   double EMA34=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE,0);
   if ( UseMACD )  {
      double Macd0=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
      double Macd1=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
      double Macd2=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,2);
       if( Macd0>0 && Macd1>0  &&  Macd2<0)     // cross up
        {
         CloseAllPendingOrders();
         if ( CloseOpenPositions == true ) { CloseOpenOrders(); }
        }
       if( Macd0<0 && Macd1<0  &&  Macd2>0)     // cross down
        {
         CloseAllPendingOrders();
         if ( CloseOpenPositions == true ) { CloseOpenOrders(); }
        }
       wantLongs = false;
       wantShorts = false;
       if( Macd0>0 && Macd1>0  &&  Macd2>0)     // is well above zero
        {
         wantLongs = true;
        }
       if( Macd0<0 && Macd1<0  &&  Macd2<0)     // is well below zero
        {
         wantShorts = true;
        }
   }
   for( i=0;i<GridSteps;i++)
   {
     traderate = startrate + i*point*GridSize;
     if ( wantLongs && (!limitEMA34 || traderate > EMA34))
       {
         if ( IsPosition(traderate,point*GridSize,true) == false )           // test if i have no open orders close to my price: if so, put one on
          {
            double myStopLoss = 0;
             if ( StopLoss > 0 )
               { myStopLoss = traderate-point*StopLoss ; }
             if ( traderate > Ask ) 
              { entermode = OP_BUYSTOP; } 
              else 
              { entermode = OP_BUYLIMIT ; } 
              if ( ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter)) ) 
              { 
                  // modified by cori. Using OrderMagicNumber to identify the trades of the grid
                 ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green); 
             }
          }
       }
     if ( wantShorts && (!limitEMA34 || traderate < EMA34))
       {
         if (IsPosition(traderate,point*GridSize,false)== false )           // test if i have no open orders close to my price: if so, put one on
          {
             myStopLoss = 0;
             if ( StopLoss > 0 )
               { myStopLoss = traderate+point*StopLoss ; }
             if ( traderate > Bid ) 
              { entermode = OP_SELLLIMIT; } 
              else 
              { entermode = OP_SELLSTOP ; } 
              
              if ( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) ) 
                { 
                   // modified by cori. Using OrderMagicNumber to identify the trades of the grid
                   ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red); 
                }
          }
       }
    }
   }
   return(0);
  }
//+------------------------------------------------------------------+
Forex Trader
114538
Forex Trader  
Hi hdb,

seems ok. But you should define the GridName as extern, which I changed, because I didn't need it as parameter.

greetings, cori
Forex Trader
114538
Forex Trader  
ATTENTION all users of GridMaker - there is a bug in the function IsPosition - the result is that not all grid slots are filled.

You can change the line :

if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // dont look for exact price but price proximity (less than gridsize)

to

if (MathAbs( OrderOpenPrice() - atRate ) < (inRange*0.9)) // dont look for exact price but price proximity (less than gridsize) - added 0.9 because of floating pont errors


and this corrects the problem.

Sorry for any inconvenience...

hugues
Forex Trader
114538
Forex Trader  
Hi hugues,

Is this Problem already in there?

Found something similar in old MQL2.

The really sure way to go around this problem is to do something like:

int intOOP = MathRound( OrdeOpenPrice() / Point );

for all your double variables. Then you have all straight int variables which are comparable without faults.

Its a bit more to write to keep it clear and understandable but its less faulty.

with regards,

cori
Forex Trader
114538
Forex Trader  
U are right Cori, that is much more elegant ! Just me being lazy!

regards,
hugues
Forex Trader
114538
Forex Trader  
Here is an update to the GridMaker EA. In this version I have:

1) changed the logic for UseMACD, wantLongs, wantShorts. Previously, if useMACD was set, the EA took longs and shorts, irrecspective of wnatLongs and wantShorts flags. Now, useMACD will not override these flags so u can be long only with useMACD or short only.

2) I added an additional check to make shure there were no open orders the wrong side of the EMA if the limitEMA34 was set. What used to happen is orders were well placed above or below the EMA but after a few hours the EMA moved.. so there were orders on both sides of the EMA.

3) There seems to be a bug in the switch statement on OrderType().. i am not sure what it is but it really behaves funny. I simply eliminated the switch statements and replaced by "if"... i dont like it but it works!

4) I made the EMA period variable... nice for backtesting..

I also have a few companion scripts if someone wants :

1) to remove unfilled open orders for a pair
2) to remove all open orders for all pairs in one go
3) to close out all positions and remove open orders.
4) to get some simple stats on the grid behaviour from the open positions and history.

Here is the code of V1.08:


//+------------------------------------------------------------------+
//|                                                     MakeGrid.mq4 |
//|                                            Copyright © 2005, hdb |
//|                                       http://www.dubois1.net/hdb |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, hdb"
#property link      "http://www.dubois1.net/hdb"
//#property version      "1.8"
// DISCLAIMER ***** IMPORTANT NOTE ***** READ BEFORE USING ***** 
// This expert advisor can open and close real positions and hence do real trades and lose real money.
// This is not a 'trading system' but a simple robot that places trades according to fixed rules.
// The author has no pretentions as to the profitability of this system and does not suggest the use
// of this EA other than for testing purposes in demo accounts.
// Use of this system is free - but u may not resell it - and is without any garantee as to its
// suitability for any purpose.
// By using this program you implicitly acknowledge that you understand what it does and agree that 
// the author bears no responsibility for any losses.
// Before using, please also check with your broker that his systems are adapted for the frequest trades
// associated with this expert.
// 1.8 changes
// made wantLongs and wantShorts into local variables. Previously, if u set UseMACD to true, 
//       it did longs and shorts and simply ignored the wantLongs and wantShorts flags. 
//       Now, these flags are not ignored.
// added a loop to check if there are 'illicit' open orders above or below the EMA when the limitEMA34
//       flag is used. These accumulate over time and are never removed and is due to the EMA moving.
// removed the switch instruction as they dont seem to work - replaced with if statements
// made the EMA period variable
//
//
// modified by cori. Using OrderMagicNumber to identify the trades of the grid
extern int    uniqueGridMagic = 11111;   // Magic number of the trades. must be unique to identify
                                         // the trades of one grid    
extern double Lots = 0.1;              // 
extern double GridSize = 6;            // pips between orders - grid or mesh size
extern double GridSteps = 12;          // total number of orders to place
extern double TakeProfit = 12 ;        // number of ticks to take profit. normally is = grid size but u can override
extern double StopLoss = 0;            // if u want to add a stop loss. normal grids dont use stop losses
extern double UpdateInterval = 1;      // update orders every x minutes
extern bool   wantLongs = true;        // do we want long positions
extern bool   wantShorts = true;       // do we want short positions
extern bool   wantBreakout = true;     // do we want longs above price, shorts below price
extern bool   wantCounter = true;      // do we want longs below price, shorts above price
extern bool   limitEMA = true;         // do we want longs above ema only, shorts below ema only
extern int    EMAperiod = 34;          // the length of the EMA.. was previously fixed at 34
extern double GridMaxOpen = 0;         // maximum number of open positions : not yet implemented..
extern bool   UseMACD = true;          // if true, will use macd >0 for longs only, macd >0 for shorts only
                                       // on crossover, will cancel all pending orders. This will override any
                                       // wantLongs and wantShort settings - at least for now.
extern bool CloseOpenPositions = false;// if UseMACD, do we also close open positions with a loss?
extern bool doHouseKeeping = true;     // just a test

// modified by cori. internal variables only
string GridName = "Grid";       // identifies the grid. allows for several co-existing grids
double LastUpdate = 0;          // counter used to note time of last update

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
 #property show_inputs                  // shows the parameters - thanks Slawa...    
//----
// added my corri and removed by hdb!! lol.. just to stay compatible with open grids...
//   GridName = StringConcatenate( "Grid", Symbol() );
   return(0);
  }
//+------------------------------------------------------------------------+
//| tests if there is an open position or order in the region of atRate    |
//|     will check for longs if checkLongs is true, else will check        |
//|     for shorts                                                         |
//+------------------------------------------------------------------------+

bool IsPosition(double atRate, double inRange, bool checkLongs )
  {
     int totalorders = OrdersTotal();
     for(int j=0;j<totalorders;j++)                                // scan all orders and positions...
      {
        OrderSelect(j, SELECT_BY_POS);
// modified by cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility
        if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // only look if mygrid and symbol...
         {  int type = OrderType();
            if (MathAbs( OrderOpenPrice() - atRate ) < (inRange*0.9)) // dont look for exact price but price proximity (less than gridsize) - added 0.9 because of floating point errors
              { if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT  || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT  || type == OP_SELLSTOP ) ) )
                 { 
                    return(true); 
                 }
              }
         }
      } 
   return(false);
  }

//+------------------------------------------------------------------------+
//| cancells all pending orders                                      |
//+------------------------------------------------------------------------+

void CloseAllPendingOrders( )
  {
     int totalorders = OrdersTotal();
     for(int j=totalorders-1;j>=0;j--)                                // scan all orders and positions...
      {
        OrderSelect(j, SELECT_BY_POS);
// modified as per cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility
        if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // only look if mygrid and symbol...
         {  
          int type = OrderType();
          if ( type > 1 ) bool result = OrderDelete( OrderTicket() );
         }
      } 
   return;
  }
//+------------------------------------------------------------------------+
//| cancells all pending orders    and closes open positions               |
//+------------------------------------------------------------------------+

void CloseOpenOrders()
{
  int total = OrdersTotal();
  for(int i=total-1;i>=0;i--)
 {
    OrderSelect(i, SELECT_BY_POS);
    int type    = OrderType();
    bool result = false;
// modified by cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility
    if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // only look if mygrid and symbol...
     {
           //Close opened long positions
           if ( type == OP_BUY )  result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red );
           //Close opened short positions
           if ( type == OP_SELL )  result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red );
           //Close pending orders
           if ( type > 1 ) result = OrderDelete( OrderTicket() );
      }
  }
  return;
}

//+------------------------------------------------------------------------+
//| cancells all open orders which fall on the wrong side of the EMA                                     |
//+------------------------------------------------------------------------+

void CloseOrdersfromEMA( double theEMAValue )
  {
     int totalorders = OrdersTotal();
     for(int j=totalorders-1;j>=0;j--)                                // scan all orders and positions...
      {
        OrderSelect(j, SELECT_BY_POS);
        if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // only look if mygrid and symbol...
         {  
          int type = OrderType();
          bool result = false;
//if (type > 1) Print(type,"  ",theEMAValue,"  ",OrderOpenPrice());
          if ( type == OP_BUYLIMIT && OrderOpenPrice() <= theEMAValue ) result = OrderDelete( OrderTicket() ); 
          if ( type == OP_BUYSTOP && OrderOpenPrice() <= theEMAValue ) result = OrderDelete( OrderTicket() ); 
          if ( type == OP_SELLLIMIT && OrderOpenPrice() >= theEMAValue ) result = OrderDelete( OrderTicket() ); 
          if ( type == OP_SELLSTOP && OrderOpenPrice() >= theEMAValue ) result = OrderDelete( OrderTicket() ); 
         }
      } 
   return;
  }
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   int    i, j,k, ticket, entermode, totalorders;
   bool   doit;
   double point, startrate, traderate;
//---- setup parameters 

 if ( TakeProfit <= 0 )                 // 
   { TakeProfit = GridSize; }

 bool myWantLongs = wantLongs;
 bool myWantShorts = wantShorts;

//----

  if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60)           // we update the first time it is called and every UpdateInterval minutes
   {
   LastUpdate = CurTime();
   point = MarketInfo(Symbol(),MODE_POINT);
   startrate = ( Ask + point*GridSize/2 ) / point / GridSize;    // round to a number of ticks divisible by GridSize
   k = startrate ;
   k = k * GridSize ;
   startrate = k * point - GridSize*GridSteps/2*point ;          // calculate the lowest entry point
   double myEMA=iMA(NULL,0,EMAperiod,0,MODE_EMA,PRICE_CLOSE,0);
   
   if (limitEMA) 
     {
    if (doHouseKeeping) CloseOrdersfromEMA(myEMA);
     }
   if ( UseMACD )  
     {
      double Macd0=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
      double Macd1=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
      double Macd2=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,2);
       if( Macd0>0 && Macd1>0  &&  Macd2<0)     // cross up
        {
         CloseAllPendingOrders();
         if ( CloseOpenPositions == true ) { CloseOpenOrders(); }
        }
       if( Macd0<0 && Macd1<0  &&  Macd2>0)     // cross down
        {
         CloseAllPendingOrders();
         if ( CloseOpenPositions == true ) { CloseOpenOrders(); }
        }
       myWantLongs = false;
       myWantShorts = false;
       if( Macd0>0 && Macd1>0  &&  Macd2>0 && wantLongs )     // is well above zero
        {
         myWantLongs = true;
        }
       if( Macd0<0 && Macd1<0  &&  Macd2<0 && wantShorts )     // is well below zero
        {
         myWantShorts = true;
        }
   }
   for( i=0;i<GridSteps;i++)
   {
     traderate = startrate + i*point*GridSize;
     if ( myWantLongs && (!limitEMA || traderate > myEMA))
       {
         if ( IsPosition(traderate,point*GridSize,true) == false )           // test if i have no open orders close to my price: if so, put one on
          {
            double myStopLoss = 0;
             if ( StopLoss > 0 )
               { myStopLoss = traderate-point*StopLoss ; }
             if ( traderate > Ask ) 
              { entermode = OP_BUYSTOP; } 
              else 
              { entermode = OP_BUYLIMIT ; } 
              if ( ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter)) ) 
              { 
                  // modified by cori. Using OrderMagicNumber to identify the trades of the grid
                 ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green); 
             }
          }
       }
     if ( myWantShorts && (!limitEMA || traderate < myEMA))
       {
         if (IsPosition(traderate,point*GridSize,false)== false )           // test if i have no open orders close to my price: if so, put one on
          {
             myStopLoss = 0;
             if ( StopLoss > 0 )
               { myStopLoss = traderate+point*StopLoss ; }
             if ( traderate > Bid ) 
              { entermode = OP_SELLLIMIT; } 
              else 
              { entermode = OP_SELLSTOP ; } 
              
              if ( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) ) 
                { 
                   // modified by cori. Using OrderMagicNumber to identify the trades of the grid
                   ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red); 
                }
          }
       }
    }
   }
   return(0);
  }
//+------------------------------------------------------------------+