Grid maker 1.1

 
Here is version 1.1 of the 'Grid maker'... a script or expert advisor that sets up and maintains a series of evenly spaced buy or sell orders.
This version is either a script ot an expert advisor, u can change the update frequency, select longs and/or shorts, etc.. see the parameters for an explanation.

I think I have tested most variants but there are no garantees that it works in all cases! If u try it and find problems, let me know.

This is probably the last version I post. I developed it to test MT4. Future versions will be more complex, needing external data such as support and resistance levels, so it will not be appropriate to post them.



//+------------------------------------------------------------------+
//|                                                     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.1beta"

extern string GridName = "Grid";       // identifies the grid. allows for several co-existing grids
extern double Lots = 0.1;              // 
extern double GridSize = 6;            // pips between orders - grid or mesh size
extern double GridSteps = 10;          // total number of orders to place
extern double UpdateInterval = 15;     // 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
extern double LastUpdate = 0;          // counter used to note time of last update
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
 #property show_inputs              // shows the parameters - thanks Slawa...    
//----
   return(0);
  }
//+------------------------------------------------------------------------+
//| test 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);
        if ( OrderSymbol()==Symbol() && 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);
  }
//+------------------------------------------------------------------+
//| 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) )           // test if i have no open orders close to my price: if so, put one on
          {
             if ( traderate > Ask ) 
              { entermode = OP_BUYSTOP; } 
              else 
              { entermode = OP_BUYLIMIT ; } 
             if ( (traderate > Ask ) && (wantBreakout) || ((traderate < Ask ) && (wantCounter)) ) 
              { ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,0,traderate+point*GridSize,GridName,16384,0,Green); }
          }
       }

     if ( wantShorts && (!limitEMA34 || traderate < EMA34))
       {
         if (!IsPosition(traderate,point*GridSize,false) )           // test if i have no open orders close to my price: if so, put one on
          {
             if ( traderate > Bid ) 
              { entermode = OP_SELLLIMIT; } 
              else 
              { entermode = OP_SELLSTOP ; } 
              
              if ( (traderate < Bid ) && (wantBreakout) || ((traderate > Bid ) && (wantCounter)) ) 
                { ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,0,traderate-point*GridSize,GridName,16384,0,Red); }
          }
       }

    }
   }
   return(0);
  }
//+------------------------------------------------------------------+
 
Hi hdb,

I have been following this idea since a long time on MoneyTec (Simspeed), ET (ElectricSavant) and Oanda forums (MarkVH and Sympatico) and I have been thinking on how to develop some expert to improve the first script you sent to the forum, perhaps we could work together to get to something faster :) Please let me know if you are interested my e-mail is artefactodigital@gmail.com

Best regards,
Fernando.

Here is version 1.1 of the 'Grid maker'... a script or expert advisor that sets up and maintains a series of evenly spaced buy or sell orders.
This version is either a script ot an expert advisor, u can change the update frequency, select longs and/or shorts, etc.. see the parameters for an explanation.

I think I have tested most variants but there are no garantees that it works in all cases! If u try it and find problems, let me know.

This is probably the last version I post. I developed it to test MT4. Future versions will be more complex, needing external data such as support and resistance levels, so it will not be appropriate to post them.
 
ok sounds good.. see my email...
 
by the way, u are free to try it, use it, change it but please dont sell it!

I provide no garantees as to its effective working condition and any trading u may do with it it at your own risk.
I assume no responsibility for direct or indirect losses due to this script.


If u do use it, please post feedback occasionally - results, settings, bugs, observations, etc.

enjoy
 
ok, here goes.. one major market move later, the grid survives!! I started a demo account two weeks ago with 50k.
I lost 1k testing the gridmaker and then just before the euro plunge I put the default GridMaker expert on 9 currency pairs:
EUR/CHF, USD/JPY, GBP/JPY, EUR/GBP, USD/CHF, AUD/USD, GBP/USD, EUR/USD, EUR/JPY.

The grid spacing is 6 ticks for all currencies, and TP at 6 ticks. I placed 0.1 lot size. I went long AND short every 6 ticks for each currency pair.
The refresh was every 15 minutes (i.e. grid regererated every 15 minutes) except for EUR/USD and GBP/USD at 5 mins.

Balance is up 10k (20%), margin used is 13k (26%), free margin is 26k (52%) and unrealised p&l is -19k.

The net result of the euro bang (so far) is that I am down -9k. I was expecting much worse than this!

The grid is adding to the Balance at the rate of 600 to 2000 per day!

I look forward to seeing how this looks next week.

Long live the grid!!
 
Well, well, one week later and the grid really took a beating ! My fault because I did not do the necessary lot size / grid spacing calculations
needed to see how much of a hit one can take with the available equity.

Anyway, the balance is churning along pretty well : 700 to 1800 per day increase - balance is now 65k (started with 49k, so this is +16k )
Used margin is now 15k, available margin 21k - still lots of room to add positions when needed.
The unrealised p&l is -29k, giving a net loss of 13k, 4 worse than last week.

The positive side is that I changed the settings to avoid counter trades (CounterTrade flag false) and the unrealised p&l seems to have stabilised.
It was at -36k at one stage.

What I like about this forward test is that it started with a big hit - the euro drop of last week - so it will now be interesting to see how and when the
system recovers. I have no doubt it will.

I just cant wwait to see the results next week!!!

ps. I have a v1.2 with the possibility of changing the TP and adding a SL. Post here if u want it.
 
I've been playing with this one quite a bit. just running everything at default on all the pairs..
I have to say I have been very impressed at how its performed.

There is only one great big niggle with this..

lets take short positins only.. as price drops the short orders are activated.. but alot of times you may get 2 orders on the short side before price decides to reverse.

i.e the take profit is at the same price as the next short to be initiated and doesn't take into account the spread i.e bid and ask prices.

so in order to help prevent having 2 orders open before prices reverse to the long side TP needs to happen at the same time as the next short order is placed.

I reckon if this is possible my drawdown currently could be cut in half..

I'm guessing your latest vesion of this would solve this problem.

So if you could post it that would be fantastic...
 
hi,

i am glad u find it fun.. so do I..

there is no way I can have at the same time a TP = grid size and eliminate the possibility of having 2 open positions on a reversal.
this is not a software problem but simply related to spreads.

the only possibility of theoretically totally eliminating this is to lose the spread each time:
i.e. u go short at 1.2006 (bid), TP at 1.2000 (ask) and short at 1.1996 (bid) if u have a 4 tick spread.
u simply lose 4/10th of the range.

in the new version, u can set the grid size and TP to different numbers so u could implement what u are
looking for: u set the grid to 10 and TP to 6 if u have a 4 point spread.

i'm not sure it will reduce the dd by half - but it will certainly reduce your profit significantly.

let me know.

ps.. v1.2 in next post
 
here is v1.2 of gridmaker.

the only differences are:
1) i have added an optional stoploss if u want one. 0 means no stop loss, any positive number means a stoploss.
if u use a stop loss in a grid, u should make it big..
2) u can specify a TP different to the grid size. darkstonexa , in the previous post, wants to eliminate double 'hanging' positions.
my initial intention was to try bigger TPs relative to grid size.

save it to the expert advisor folder ( something like C:\Program Files\MetaTrader 4\experts\ ) and an optional copy to the scripts folder
if u want it as a script (C:\Program Files\MetaTrader 4\experts\scripts\).

I have a script to remove open grid orders if u want.. it is quite useful if u want to change settings.

NOTE: the default settings may have changed since the last version. make sure u put your preferred settings before recompiling.

QUESTION to an administrator: maybe I should put this sort of thing in the expert advisor library.. is this correct?

//+------------------------------------------------------------------+
//|                                                     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.2beta"

extern string GridName = "Grid";       // identifies the grid. allows for several co-existing grids
extern double Lots = 0.1;              // 
extern double GridSize = 6;            // pips between orders - grid or mesh size
extern double GridSteps = 10;          // 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 = 15;     // 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 = false;      // do we want longs below price, shorts above price
extern bool   limitEMA34 = false;      // do we want longs above ema only, shorts below ema only
extern 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; }
//----
   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);
        if ( OrderSymbol()==Symbol() && 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);
  }
//+------------------------------------------------------------------+
//| 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) )           // 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)) ) 
              { ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,16384,0,Green); }
          }
       }

     if ( wantShorts && (!limitEMA34 || traderate < EMA34))
       {
         if (!IsPosition(traderate,point*GridSize,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)) ) 
                { ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,16384,0,Red); }
          }
       }

    }
   }
   return(0);
  }
//+------------------------------------------------------------------+
 
Thats great..

Just the solution to the problem at the moment having a TP option.

I might have over estimated the amount of drawdown.. but it will hopefully stop alot of the cases where I have seen 2 orders at the end of a range
each wih a loss of $2000 + will be a thing of the past :)

now the last thing that might be of use is to work out to set the expire option on limit orders..
currently you have it set so they don't expire..
so you have to manually delete.

Currently I have a bunch of orders that are about 3 days old and not likely to be hit anytime soon..

Well I would like to say great work.. :)
 
here is a script to remove all open orders for a particular currency pair. the code is a bit nasty but it seems to work..

//+------------------------------------------------------------------+
//|                                                   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";

//+------------------------------------------------------------------+
//| 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       : 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() ); 
          }
    
          if(result == false)
          {
     //       Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
     //       Sleep(3000);
          }  
        }
      }
 
//----
   return(0);
  }
//+------------------------------------------------------------------+
Reason: