Any questions from newcomers on MQL4 and MQL5, help and discussion on algorithms and codes - page 755

 

Hello. I can't figure out what is wrong.

There are two orders with smaller and larger volume and different take profit. The order with the smaller volume is opened first, then the order with the larger volume. We need to find a Take Profit for the order with larger volume.

//MaxLotBuy() - функция находит ордер с наибольшим объемом (в Comment("") показывает правильные значения)
//buyTpL - в глобальных переменных
//---------------------------------------------
for(i = total-1; i >= 0; i--)
{
   if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
   {
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
      { 
         if(OrderType() == OP_BUY)
         { 
            if(OrderLots() == MaxLotBuy())
               buyTpL = OrderTakeProfit();
         }
      }
   }
} 

Everything seems to be correct but for some reason, we get take profit values of the order with a smaller volume (it was opened first). What is wrong?

P.S. total = OrdersTotal()

 
Youri Lazurenko:

Hello. I can't figure out what is wrong.

There are two orders with smaller and larger volume and different take profit. The order with the smaller volume is opened first, then the order with the larger volume. We need to find a Take Profit for the order with larger volume.

Everything seems to be correct but for some reason, we get take profit values of the order with a smaller volume (it was opened first). What is wrong?

P.S. Total = OrdersTotal()

It seems that the function MaxLotBuy() contains its own order search and another order appears to be selected when we return to this function. Avoid order rebound outside some order rebound cycle. I do not understand what I said. But it's true.

In this situation, we'd better declare a variable before the loop and assign to it the OrderLots() value provided that the new value is larger than the previous one.

double orderLot = 0;
for(i = total-1; i >= 0; i--)
{
  if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
   {
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
      { 
         if(OrderType() == OP_BUY)
         { 
            if(OrderLots() > orderLot)
             {
              orderLot = OrderLots();
              buyTpL = OrderTakeProfit();
             }
         }
      }
   }
} 
 
Alexey Viktorov:

The MaxLotBuy() function seems to have its own order loop and another order is selected when returning to this function. You should avoid going through the order outside of any order loop. I do not understand what I said. But it's true.

In this situation, we'd better declare a variable before the loop and assign it the OrderLots() value provided that the new value is larger than the previous one.

Thank you. Yes,MaxLotBuy() has its own enumeration of orders, but the return value is the maximal one (I'll give you the code).

//  GetLots() - функция мани менеджмента
//------------------------
double MaxLotBuy()
{
   int    i;
   int    total  = OrdersTotal();
   double lot    = GetLots();
   
   if(CountBuy() == 0)
      lot = GetLots();
   
   if(CountBuy() >= 1)
   {   
      for(i = total-1; i >= 0; i--)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
            {
               if(OrderType() == OP_BUY) 
               {
                  if(lot < OrderLots())
                     lot = OrderLots();
               }
            }
         }
      }
   }
   return(lot);
}

But I have understood your idea, thanks. I will try it now.

 
Konstantin Nikitin:
That's probably the right way to go.

Thank you, that seems better.

 
Konstantin Nikitin:
I think the right thing to do would be

Thank you. It's not just when you write to yourself that you have to be careful.

Although that's what it says in words.

declare a variable before the loop


 

Guys, thank you very much; it works as it should. Just added a reset to the original position as well.

   int    i;     
   int    total       = OrdersTotal();
   double orderLotBuy = GetLots();

   if(CountBuy() == 0)
      orderLotBuy = GetLots();

   for(i = total-1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
         { 
            if(OrderType() == OP_BUY)
            { 
               if(OrderLots() > orderLotBuy)
               {
                  buyTpL      = OrderTakeProfit();
                  orderLotBuy = OrderLots();
               }
            }
         }
      }
   } 
   
 
Youri Lazurenko:

Guys, thank you very much; it works as it should. Just added a reset to the original position as well.

Well, yeah. My example is not complete. I just corrected it, supplemented it and my correction coincided with your message in time.
 
Alexey Viktorov:
Well, yes. My example is not complete. I just corrected it, supplemented it and my correction coincided with your message in time.

It doesn't matter that it's not complete, what matters is the right idea, the right approach. Thank you all again.

 
Youri Lazurenko:

It doesn't matter that it's not complete, what matters is the right idea, the right approach. Thank you all once again.

Then it goes like this

   int    total       = OrdersTotal();
   double orderLotBuy = GetLots();

   if(CountBuy() > 0)
      for(i = total-1; i >= 0; i--)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
            { 
               if(OrderType() == OP_BUY)
               { 
                  if(OrderLots() > orderLotBuy)
                  {
                     buyTpL      = OrderTakeProfit();
                     orderLotBuy = OrderLots();
                  }
               }
            }
         }
      } 
 
Konstantin Nikitin:

Then it looks like this

Basically I haven't posted all the code, but only a part of finding the take profit of the order with the highest lot. The whole point is as follows - when the price reverses, a pending order with a bigger lot is placed. If it works, a stop loss is set on the opposite order so that when the order with big lot is closed at Take Profit, the order with negative profit at stop loss is also closed. The full code of modification with setting a stop loss looks like this

// sp            - величина спреда
// FirstOrderBuy - дабы избежать error1
//----------------------------------------------- 
     int i;
      
      int    total        = OrdersTotal();
      double orderLotBuy  = GetLots();     
   
      static int FirstOrderBuy  = 0;     

      if(CountBuy() < FirstOrderBuy)
         FirstOrderBuy = 0; 
         
      if(CountBuy() == 0)
         orderLotBuy = GetLots();
      
      if(CountSell() >= 1 && CountBuy() > FirstOrderBuy && MaxLotBuy() > MaxLotSell())
      {
         for(i = total-1; i >= 0; i--)
         {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
               { 
                  if(OrderType() == OP_BUY)
                  { 
                     if(OrderLots() > orderLotBuy)
                     {
                        buyTpL      = OrderTakeProfit();
                        orderLotBuy = OrderLots();
                     }
                  }
               }
            }
         } 
                        
         for(i = total-1; i >= 0; i--)
         {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
               { 
                  if(OrderType() == OP_SELL)  
                  {               
                     if(OrderStopLoss() == 0 || (OrderStopLoss() != 0 && OrderStopLoss() > OrderOpenPrice()))
                     {
                        slSell = NormalizeDouble(buyTpL + sp*point, Digits);
                        
                        OrderModifyX(OrderTicket(), OrderOpenPrice(), slSell, OrderTakeProfit(), 0, 0);
                     }
                  }    
               }
            }
         }
         FirstOrderBuy = CountBuy();
      }

P.S. During testing, there are so many nuances that need to be "explained" to the Expert Advisor as to how it should behave in certain cases.