How to allow multiple trades but on different pairs?

 

I am familiar with the typical example in MetaTrader which allows only one trade at time:

total=OrdersTotal();
   if(total<1) 
     {
      .....
     }

But how can this be altered so that it can open one trade max per pair?

 
mostashar15:

I am familiar with the typical example in MetaTrader which allows only one trade at time:

But how can this be altered so that it can open one trade max per pair?


hi

maybe its better to check it before you open an order of the cuurent pair

OrderSelect(iCount, SELECT_BY_POS, MODE_TRADES);
if( OrderSymbol()==Symbol()

" and status of the order is open " )

then you dont open another

 
Thanks, I will try it.
 

make yourself a bunch of functions to count the orders and do many other useful things:

int getNumOpenOrders(int magic, string symbol){
   int cnt = 0;
   int i;
   for(i=0; i<OrdersTotal(); i++){
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if (OrderMagicNumber() == magic && OrderSymbol() == symbol){
         cnt++;
      }
   }
   return(cnt);
}

double getFloatingProfit(int magic, string symbol){
   ...
}

void closeOpenOrders(int magic, string symbol){
   ...
}

and so on...

Everybody should have a few dozen such handy functions in his repository. This makes it so much easier and include files make it easy to reuse them in all your EAs.

Here are mine: http://7bit.99k.org/common__functions_8mqh.html (mine are more centered around the magic number and not so much around the symbol so you need to be creative. You could for example work around this by creating an individual magic number for each symbol with my makeMagicNumber() function. But you can also just modify these functions to better fit your needs (give your modified functions new names so they don't collide in case you decide to keep using the rest of this library)).

 
  1. An EA should only be considering its own trades, not those from other pairs, other timeframes, or by other EAs/human:
        for(int pos = OrdersTotal()-1; pos >= 0 ; pos--) if (
            OrderSelect(pos, SELECT_BY_POS)                 // Only my orders w/
        &&  OrderMagicNumber() == Magic.Number.Base         // my magic number
        &&  OrderSymbol()      == Symbol() ){               // and period and symbol
    

  2. My equivalent of getFloatingProfit() returns the worst case if the market takes out all my positions:
    double  perLotPerPoint = PointValuePerLot(),
            profit         = 0;
    
        for(int pos = OrdersTotal()-1; pos >= 0 ; pos--) if (
            OrderSelect(pos, SELECT_BY_POS)                 // Only my orders w/
        &&  OrderMagicNumber() == Magic.Number.Base         // my magic number
        &&  OrderSymbol()      == Symbol() ){               // and period and symbol
            ...
            profit  += OrderLots() * (oo.SL-oo.price)*DIR * perLotPerPoint;
    ...
    double PointValuePerLot() { // Value in account currency of a Point of Symbol.
        /* In tester I had a sale: open=1.35883 close=1.35736 (0.00147)
         * gain$=97.32/6.62 lots/147 points=$0.10/point or $1.00/pip.
         * IBFX demo/mini       EURUSD TICKVALUE=0.1 MAXLOT=50 ELine=10,000
         * IBFX demo/standard   EURUSD TICKVALUE=1.0 MAXLOT=50 ELine=100,000
         *                                  $1.00/point or $10.00/pip.
         *
         * https://www.mql5.com/en/forum/127584 CB: MODE_TICKSIZE will usually return the
         * same value as MODE_POINT (or Point for the current symbol), however, an
         * example of where to use MODE_TICKSIZE would be as part of a ratio with
         * MODE_TICKVALUE when performing money management calculations which need
         * to take account of the pair and the account currency. The reason I use
         * this ratio is that although TV and TS may constantly be returned as
         * something like 7.00 and 0.00001 respectively, I've seen this
         * (intermittently) change to 14.00 and 0.00002 respectively (just example
         * tick values to illustrate). */
        return(  MarketInfo(Symbol(), MODE_TICKVALUE)
               / MarketInfo(Symbol(), MODE_TICKSIZE) ); // Not Point.
    }
    

  3. And my equivalent of plotClosedTradeLine() instead is to plot the TP and SL continuously on the chart (as well as indicator values)
    //+------------------------------------------------------------------+
    //| EA equivalent of indicator buffers                               |
    //+------------------------------------------------------------------+
    /*  Example 1:
     *  if (...) Ordermodify(...);
     *  Polyline("SL"+(ticket%99), SL, Color.SL, 0);
     *
     *  Example 2:
     *  double  ELineCurr = iMA(NULL,0, ELine.Period, 0, MODE_EMA, PRICE_CLOSE, 1);
     *  Polyline("ELine", ELineCurr, Color.ELine, 1);
     ******************************************************************************/
    #define POLYLINE_MAX 20 // Must match priceM
    double  price00[], price01[], price02[], price03[], price04[],  // \   Export
            price05[], price06[], price07[], price08[], price09[],  //  \  from
            price10[], price11[], price12[], price13[], price14[],  //  |  Polyline
            price15[], price16[], price17[], price18[], price19[];  //  |
    int     LRU[POLYLINE_MAX],  segNo[POLYLINE_MAX];                //   > Import to
    string  lineName[POLYLINE_MAX];                                 // _/  PLHelper
    datetime time0[POLYLINE_MAX];
    void Polyline(string name, double price, color clr, int shift){
        if (!Show.Objects)  return;
        for (int idx=0; idx < POLYLINE_MAX; idx++){     LRU[idx]++; }
        for (idx=0; idx < POLYLINE_MAX; idx++){
            bool new = lineName[idx] != name;   if (!new) break;    }
        if (new){   idx=ArrayMaximum(LRU);  lineName[idx]=name; segNo[idx]=0;   }
        LRU[idx] = 0;   switch (idx){
        case  0: PLHelper(name, price, clr, idx, new, shift, price00); return;
        case  1: PLHelper(name, price, clr, idx, new, shift, price01); return;
        case  2: PLHelper(name, price, clr, idx, new, shift, price02); return;
        case  3: PLHelper(name, price, clr, idx, new, shift, price03); return;
        case  4: PLHelper(name, price, clr, idx, new, shift, price04); return;
        case  5: PLHelper(name, price, clr, idx, new, shift, price05); return;
        case  6: PLHelper(name, price, clr, idx, new, shift, price06); return;
        case  7: PLHelper(name, price, clr, idx, new, shift, price07); return;
        case  8: PLHelper(name, price, clr, idx, new, shift, price08); return;
        case  9: PLHelper(name, price, clr, idx, new, shift, price09); return;
        case 10: PLHelper(name, price, clr, idx, new, shift, price10); return;
        case 11: PLHelper(name, price, clr, idx, new, shift, price11); return;
        case 12: PLHelper(name, price, clr, idx, new, shift, price12); return;
        case 13: PLHelper(name, price, clr, idx, new, shift, price13); return;
        case 14: PLHelper(name, price, clr, idx, new, shift, price14); return;
        case 15: PLHelper(name, price, clr, idx, new, shift, price15); return;
        case 16: PLHelper(name, price, clr, idx, new, shift, price16); return;
        case 17: PLHelper(name, price, clr, idx, new, shift, price17); return;
        case 18: PLHelper(name, price, clr, idx, new, shift, price18); return;
        case 19: PLHelper(name, price, clr, idx, new, shift, price19); return;
    }   }
    void PLHelper( string name, double price, color clr, int idx, bool new
                 , int shift, double& mem[] ){
        datetime    t0  = Time[shift];  int firstBar = ArraySize(mem);
        if (new){   t0 += 60*Period();      firstBar=0; }
        if (new || t0 != time0[idx]){
            ArraySetAsSeries(mem, true);        // Shift values m[2]=m[1]; m[1]=m[0]
            firstBar=ArrayResize(mem, firstBar+1)-1;    if (firstBar < 0){  Alert(
                "ArrayResize failed: ",GetLastError());                     return;}
            ArraySetAsSeries(mem, false);
            time0[idx]=Time[shift];  mem[0]=price;
        }
        else    firstBar--;
        if (ObjectMove(name, 1, t0,                     price))
            ObjectMove(name, 0, Time[shift+firstBar],   mem[firstBar]);
        else if (!ObjectCreate( name, OBJ_TREND, WINDOW_MAIN
                              , t0,                     price
                              , Time[shift+firstBar],   mem[firstBar] )){   Alert(
            "ObjectCreate(", name, "Trend) [1] failed: ",GetLastError());   return;}
        else if (!ObjectSet( name, OBJPROP_COLOR, clr ))                    Alert(
            "ObjectSet(", name, "Color) [2] failed: ", GetLastError());
        else if (!ObjectSet( name, OBJPROP_RAY, false ))                    Alert(
            "ObjectSet(", name, "Ray) [1] failed: ", GetLastError());
    
        double maxError=0;  int maxBar;
        for (int pos=1; pos < firstBar; pos++){
            double error=MathAbs(ObjectGetValueByShift(name, pos+shift)-mem[pos]);
            if (error > maxError){  maxError=error; maxBar=pos; }
        }
        if (maxError >= pips2dbl){  // Split the line into two segments at the max.
            segNo[idx]=(segNo[idx]+1)%1000; string newName=name+"-"+segNo[idx];
            /**/ if (ObjectMove(newName, 0, Time[firstBar+shift], mem[firstBar]))
                ObjectMove(newName, 1, Time[maxBar  +shift], mem[maxBar]);
            else if (!ObjectCreate( newName, OBJ_TREND, WINDOW_MAIN,
                Time[firstBar+shift],   mem[firstBar],
                Time[maxBar  +shift],   mem[maxBar] ))                      Alert(
                "ObjectCreate(", newName, "Trend) [2] failed: ",GetLastError());
            else if (!ObjectSet( newName, OBJPROP_COLOR, clr ))             Alert(
                "ObjectSet(", newName, "Color) [3] failed: ", GetLastError());
            else if (!ObjectSet( newName, OBJPROP_RAY, false ))             Alert(
                "ObjectSet(", newName, "Ray) [2] failed: ", GetLastError());
    
            ArrayResize(mem, maxBar+1); // Drop firstBar..(maxBar+1)
            if (!ObjectMove(name, 0, Time[maxBar+shift], mem[maxBar]))      Alert(
                "ObjectMove(",name,") [2] failed: ", GetLastError());
        }   // Split the line into two segments at the max.
    }   // PLHelper
    
Reason: