Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 755

 

Здравствуйте. Не могу понять что не так. 

Есть два ордера с меньшим и большим объемом и разными тейк профитами. Первым открыт ордер с меньшим объемом, потом с большим. Нужно найти тейк профит ордера с большим объемом. 

//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();
         }
      }
   }
} 

Кажется все правильно, но в результате, почему-то, выдаются значения тейк профита с меньшим объемом (он открыт первым). Что не так?

P.S. total = OrdersTotal()

 
Youri Lazurenko:

Здравствуйте. Не могу понять что не так. 

Есть два ордера с меньшим и большим объемом и разными тейк профитами. Первым открыт ордер с меньшим объемом, потом с большим. Нужно найти тейк профит ордера с большим объемом. 

Кажется все правильно, но в результате, почему-то, выдаются значения тейк профита с меньшим объемом (он открыт первым). Что не так?

P.S. total = OrdersTotal()

Видимо в функции MaxLotBuy() идёт свой перебор ордеров и вернувшись в эту функцию выбранным оказывается другой ордер. Избегайте перебора ордеров за пределами какого-то цикла перебора ордеров. Сам не понял что сказал. Но это так.

Для этой ситуации лучше объявить переменную перед циклом и присвоить ей значение OrderLots() при условии что новое значение больше предыдущего.

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:

Видимо в функции MaxLotBuy() идёт свой перебор ордеров и вернувшись в эту функцию выбранным оказывается другой ордер. Избегайте перебора ордеров за пределами какого-то цикла перебора ордеров. Сам не понял что сказал. Но это так.

Для этой ситуации лучше объявить переменную перед циклом и присвоить ей значение OrderLots() при условии что новое значение больше предыдущего.

Спасибо. Да, в MaxLotBuy() идет свой перебор ордеров, но возвращаемое значение максимальное значение (лучше приведу код)

//  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);
}

Но вашу идею понял, спасибо. Сейчас попробую. 

 
Konstantin Nikitin:
Наверно правильней так будет

Спасибо, кажется так лучше. 

 
Konstantin Nikitin:
Наверно правильней так будет

Спасибо. Внимательней надо быть не только когда пишешь себе.

Хотя на словах именно это и сказано.

объявить переменную перед циклом


 

Ребята, большое спасибо; работает как надо. Только еще добавил сброс в исходное положение.

   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:

Ребята, большое спасибо; работает как надо. Только еще добавил сброс в исходное положение.

Ну, да. Мой пример не полный. Я только-что исправил, дополнил его и моё исправление совпало с вашим сообщением по времени.
 
Alexey Viktorov:
Ну, да. Мой пример не полный. Я только-что исправил, дополнил его и моё исправление совпало с вашим сообщением по времени.

Не важно, что не полный, главное правильная идея, подход. Еще раз всем спасибо.

 
Youri Lazurenko:

Не важно, что не полный, главное правильная идея, подход. Еще раз всем спасибо.

Тогда так

   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:

Тогда так

В принципе я выложил не весь код, а только часть нахождения тейк профита ордера с наибольшим лотом. Полная суть в следующем - при развороте цены выставляется отложенный ордер с большим лотом. Если он срабатывает, на противоположном ордере выставляется стоп лосс, чтобы, при закрытии ордера с большим лотом по тейк профиту, закрывался и ордер с отрицательным профитом по стоп лоссу. Полный код, модификации с выставлением стоп лосса выглядит так:

// 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. В процессе тестирования выплывает столько нюансов, которые нужно "объяснить" советнику, как ему поступать в том или ином случае.
 

Причина обращения: