One EA running on many charts

 

Hi all, I have an EA I made that I am running on about 10 different currencies at once (in a demo account). I am just wondering if there is any special things one should consider when doing such a thing (as opposed to a separate EA on each chart). The reason I ask is that the EA seems to be behaving strangely sometime and not acting as I expect. I have made sure to give each chart a unique magic number, so that can't be the problem. But is there some basic thing that I am not aware of that I should be doing in my EA?


Thanks

Shawn

 

the EA gets only executed when a new tick arrives on the chart the EA is attached. maybe this could be a problem.

what do you mean with strange behaviour

 
zzuegg:

the EA gets only executed when a new tick arrives on the chart the EA is attached. maybe this could be a problem.

what do you mean with strange behaviour



Yup, I know this Zzeugg... so if 10 of the same EA are running at once (one on each unique hourly chart), that in itself shouldn't cause a problem, no?


Strange behaviour - well a couple of things. I have an indicator running on each chart that updates 4 global variables for each currency. Each instance of the EA reads the 4 global variables for its own currency - these global variables dictate my entry and exit prices. Sometimes they are what I expect, sometimes they are not... I can't figure it out. When I check Tools|Global Variables in MT4, all the global variables seem to have the proper values that I expect. But it seems during the process of the EA reading these and processing them, something is going wrong.


What else... well, I have code in the EA to delete any pending order (for that particular symbol/chart) that is not filled when the next new hourly bar occurs. I even created a brute-force "while" loop for the OrderDelete statement to repeat until the statement returns "true". Yet, still some pending orders don't get deleted when the next bar rolls around.


I am thinking I need to run my EA on only ONE chart and monitor it closely. and try and debug. Having it run on 10 at once is making it hard to try and debug.


Thanks

Shawn

 
  1. Sometimes they are what I expect, sometimes they are not... I can't figure it out. When I check Tools|Global Variables in MT4, all the global variables seem to have the proper values that I expect.

    You're being contradictory there. You should have 4*10=40 variables. The EA's are not using their own variables. Delete all the variables, run one chart and verify 4. Add a second verify 8...


  2. What else... well, I have code in the EA to delete any pending order (for that particular symbol/chart) that is not filled when the next new hourly bar occurs. I even created a brute-force "while" loop for the OrderDelete statement to repeat until the statement returns "true". Yet, still some pending orders don't get deleted when the next bar rolls around.

    You must count down when deleting or closing, or modifying (in the presence of other EAs or not.)
        for(int pos = OrdersTotal()-1; pos >= 0; pos--) if (
            OrderSelect(pos, SELECT_BY_POS)           // Only my orders w/
        &&  OrderMagicNumber() == Magic.Number        // my magic number
        &&  OrderSymbol()      == Symbol() ){         // and symbol
    

  3. I have made sure to give each chart a unique magic number
    Not strictly necessary if you check for symbol as well.
 

I have done EA that run on one chart and trade any pair. Here is the basic idea, you need to run the expert on a infinite loop and every part of the expert where you need a calculation or value of a expecific pair you need to loop the info into an array, this expert will not work on all pair during testing because you can´t acess other pairs value during testing.

I hope this helps.

Make and array withe the Paris you like to use like

string      symbol [30];

 symbol [0] = "EURUSD";
 symbol [1] = "GBPSUD";

and son on.

Now lets say you need a moving average for all pairs for your signal .

for (int x= 0; x <30;x++) 
   {
       MoveAVg[x] = iMA(symbol [x],0,13,8,MODE_SMMA,PRICE_MEDIAN,0);
   } 

Now lets say you need the Bid and Ask 

for (int x= 0; x <30;x++) 
   {
      Bid_All[x] = MarketInfo((symbol [x],MODE_BID);
   } 

 
shawnh:

But is there some basic thing that I am not aware of that I should be doing in my EA?

Use the liborderreliable.mqh and replace all calls to OrderSend(), OrderClose(), OrderDelete(), OrderModify() with their thread-safe and error-catching counterparts from that library. It will be a simple Search&replace in your EA, these replacement functions have the exact same signatures.

Never use the OrderXxxx() functions in your EA directly unless you are just doing some quick prototyping or testing. As soon as you plan to use your EA anywhere outside of the backtester in a real account (even on a demo) you need these improved OrderXxxx() functions.


Of course this will not magically solve logical errors in your code, such as counting the orders forward when closing orders without decreasing the loop variable by 1 after each successful close or completely restarting the loop after each successful close (while ignoring FIFO errors!) or similar mistakes. You still have to take care of that.

 

BillyJoe - thanks for the suggestion, but that would be too much major surgery on my EA, I think.


7Bit - a very good suggestion, thanks. Where can I download this library and how is it used please? (I'm a little bit "green" still with mql4).


WHRoeder - I think I *might* have found my inconsistency problem with the global variables - as usual, just an oversight on my part. I think I'll be able to track it down. Regarding my other issue - the deletion of a pending order when the next hourly bar opens - I already have code that does something very similar to what you suggest:


bool NewBar()
{
   static datetime lastbar;
   datetime curbar = Time[0];
   if(lastbar!=curbar)
   {
      lastbar=curbar;
      return (true);
   }
   else
   {
      return(false);
   }
}


int start() {
   int Order = SIGNAL_NONE;
   int Total, Ticket;
   double BuyStopPrice, BuyPrice, BuyProfTarg, FinalBuyPrice;
   double SellPrice, SellProfTarg, FinalSellPrice, FinalSellProfTarg, FinalSellStopPrice, ProfitRisk;

   if (EachTickMode && Bars != BarCount) TickCheck = False;
   Total = OrdersTotal();
   Order = SIGNAL_NONE;


   // delete any pending orders if we're rolled around to a new hourly bar
   
   if (NewBar())
   {
    Print("In NewBar for ", Symbol(), " TotalOrders = ", Total);
    
    // delete any pending orders for this symbol first
    
    for (int i = 0; i < Total; i ++) 
    {
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if(OrderType() == OP_BUYSTOP && OrderSymbol() == Symbol()) 
      {
        rtnerr = false;
        while(rtnerr == false)
        {
         rtnerr = OrderDelete(OrderTicket(), Yellow); 
         Sleep(500);
        }
        Print("Deleted pending Buy order for ", Symbol());
      }
      if(OrderType() == OP_SELLSTOP && OrderSymbol() == Symbol()) 
      {
        rtnerr = false;
        while(rtnerr == false)
        {
         rtnerr = OrderDelete(OrderTicket(), Yellow); 
         Sleep(500);
        }
        Print("Deleted pending Sell order for ", Symbol());
      }
    } // end for
    
    
    IsTrade = False;    
    Total = OrdersTotal();
    
    // now check if there are any currently open trades
    
    for (i = 0; i < Total; i ++) 
    {
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if(OrderType() == OP_BUY && OrderSymbol() == Symbol()) 
      {
        IsTrade = True;
      }
      if(OrderType() == OP_SELL && OrderSymbol() == Symbol()) 
      {
        IsTrade = True;
      }
    } // end for        
    
    Print("In NewBar for ", Symbol(), " IsTrade = ", IsTrade);   
    
   } // end if
.
.
.


That "NewBar" routine I found online somewhere - and I'm beginning to have doubts that it might be that which is the culprit.... I don't know. Anyway, further down in my "Start" routine you can see my similar code to yours for looping though orders. I even have it within a brute-force "while" loop... but still, not always do my pending orders get deleted when a new hourly bar rolls around :-(


Thanks to all!

Shawn

 
I'm beginning to have doubts that it might be that which is the culprit
Asked and answered. You MUST count DOWN
// for (int i = 0; i < Total; i ++) 
//     {
//       OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
//       if(OrderType() == OP_BUYSTOP && OrderSymbol() == Symbol()) 

for(int pos = OrdersTotal()-1; pos >= 0; pos--) if (
    OrderSelect(pos, SELECT_BY_POS)            // Only my orders w/
&&  OrderMagicNumber() == Magic.Number         // my magic number
&&  OrderSymbol()      == Symbol()             // and symbol
&&  OrderType()         > OP_SELL ){           // Pending only

Don't need the overhead of a function call per tick for a newBar:
start(){
    static datetime time0; if (time0==Time[0]) return(0); time0 = Time[0];
    //newBar ...
 
WHRoeder:
Asked and answered. You MUST count DOWN
Don't need the overhead of a function call per tick for a newBar:

premature optimization is the root of all evil!


There is nothing wrong with factoring out such commonly used things into separate functions. It is recommended best practice to modularize the code by decomposing it into separate functions as much as reasonable and possible.

Please don't tell newbies to avoid the usage of functions, there is already a lot of spaghetti code around here, there is no need to further encourage this. Functions are a good thing. After all functions are the only code reuse pattern that is available in mql4, so it should be used.

 

Thanks to both of you WHRoeder and 7Bit - I have implemented your suggestions. I am going to begin testing and I think this should make a world of difference!


Thanks!

Shawn

P.S: 7Bit - I am VERY glad to learn about these "Reliable" functions... this is going to be invaluable for my future EA programming (I have yet to trade real money).

Reason: