Почему не модифицируется ордер?

 

Уважаемые трейдеры, программисты, разработчики и просто сочувствующие!

Помогите понять почему не модифицируется выставленный ордер.

Устанавливаю усредняющий ордер и пытаюсь модифицировать полученные ордера и привести к средней цене. 

Вот кусок кода:

//+------------------------------------------------------------------+
// Усредняем
//+------------------------------------------------------------------+      
      if (orders[6]>0)  //Если есть открытые ордера
         {
         if (orders[0]>0 && orders[0]<Max_Orders && kray_BUY_order()-Ask>=step)    //Если есть открытые ордера BUY и их количество меньше максимально допустимого и цена от крайнего ордера больше шага разрешенного в настройках
            {
            OpenPosition(Symbol(),OP_BUY,ND(Sr_lot(OP_BUY)*LotMultiplikator),0,0,Magic,NULL);    //Открываем усредняющий лот BUY
            flag_new_order=true; Print(" Флаг открытия усредняющего ордера= ",flag_new_order);
            }
         if (orders[1]>0 && orders[1]<Max_Orders && Bid-kray_SELL_order()>=step)   //Если есть открытые ордера SELL и их количество меньше максимально допустимого и цена от крайнего ордера больше шага разрешенного в настройках
            {
            OpenPosition(Symbol(),OP_SELL,ND(Sr_lot(OP_SELL)*LotMultiplikator),0,0,Magic,NULL);  //Открываем усредняющий лот SELL
            flag_new_order=true;
            }  
           Comment ("\n",
                     "\n", "Ордера= ", orders[6],
                     "\n", "Ордера BUY= ", orders[0],
                     "\n", "Ордера SELL= ", orders[1],
                     "\n", "средняя цена BUY= ",Sr_Cena(OP_BUY),
                     "\n", "средняя цена SELL= ",Sr_Cena(OP_SELL));                
          }    
//+------------------------------------------------------------------+
// Выставляем усредняющий тейкпрофит
//+------------------------------------------------------------------+
      if (orders[6]>0)  //Если есть открытые ордера
         {bool tiket1;
         if (orders[0]>0 && flag_new_order==true)//Если ордера BUY и открыт усредняющий ордер
           {
            for (int i = OrdersTotal() - 1; i >= 0; i--)
               {tiket1=OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
                  if (tiket1==true)
                     {
                     if (OrderMagicNumber()==Magic && OrderSymbol()==Symbol() && OrderType() == OP_BUY)
                        {
                        if (OrderTakeProfit()!=ND(Sr_Cena(OP_BUY)+take_profit))
                           {
                           int tiketB=OrderModify(OrderTicket(),OrderOpenPrice(),0,ND(Sr_Cena(OP_BUY)+take_profit),0);
                           if (tiketB==false) Print (GetLastError()," OrderTicket= ",OrderTicket(), " TP= ", DoubleToString(ND(Sr_Cena(OP_BUY)+take_profit),8), " Ордер ТР= ", DoubleToString(OrderTakeProfit(),8)," Разница= ",DoubleToString((OrderTakeProfit()-ND(Sr_Cena(OP_BUY)+take_profit))*1000000,8) );
                           Print("Флаг прохождения= ОК");
                           }
                        }
                     }
               }
            }
          }
        flag_new_order=false;    
        
if (orders[6]>0)  //Если есть открытые ордера
         {bool tiket2;
         if (orders[1]>0 && flag_new_order==true)//Если ордера SELL и открыт усредняющий ордер
           {
            for (int pos = OrdersTotal() - 1; pos >= 0; pos--)
               {tiket2=OrderSelect(pos,SELECT_BY_POS,MODE_TRADES);
                  if (tiket2==true)
                     {
                     if (OrderMagicNumber()==Magic && OrderSymbol()==Symbol() && OrderType() == OP_SELL)
                        {
                        if (OrderTakeProfit()!=ND(Sr_Cena(OP_SELL)-take_profit))
                           {
                           int tiketS=OrderModify(OrderTicket(),OrderOpenPrice(),0,ND(Sr_Cena(OP_SELL)-take_profit),0);
                           if (tiketS==false) Print (GetLastError()," OrderTicket= ",OrderTicket(), " TP= ", DoubleToString(ND(Sr_Cena(OP_SELL)-take_profit),8), " Ордер ТР= ", DoubleToString(OrderTakeProfit(),8)," Разница= ",DoubleToString((OrderTakeProfit()-ND(Sr_Cena(OP_SELL)-take_profit))*1000000,8) );
                           Print("Флаг прохождения= ОК");
                           }
                        }
                     }
               }
            }
          }
        flag_new_order=false;    
      }
   return(0);

Установил флаги и в журнале ошибок видно, что при вхождении в цикл модификации ордеров, успешно модифицируется только самый крайний №3, а потом идет обращение опять к самому крайнему №3, но естественно его уже нельзя модифицировать, а оставшийся ордер №2 так и остался без изменений.... 
 

Журнал ошибок: 

 
Для начала нормализируйте цены до Digits
 
Vladimir Zubov:
Для начала нормализируйте цены до Digits

Цены нормализуются в функции:

//+-----------------------------------------------------------------------------+
//|Функция округления                                        |
//+-----------------------------------------------------------------------------+
double ND(double val)
{
   return(NormalizeDouble(val, Digits));
}


 

 
Alexandr Kambolin:

Уважаемые трейдеры, программисты, разработчики и просто сочувствующие!

Помогите понять почему не модифицируется выставленный ордер.

Устанавливаю усредняющий ордер и пытаюсь модифицировать полученные ордера и привести к средней цене.


if (orders[6]>0)  //Если есть открытые ордера
         {bool tiket2;
         if (orders[1]>0 && flag_new_order==true)//Если ордера SELL и открыт усредняющий ордер
           {
            for (int pos = OrdersTotal() - 1; pos >= 0; pos--)
               {tiket2=OrderSelect(pos,SELECT_BY_POS,MODE_TRADES);
                  if (tiket2==true)
                     {
                     if (OrderMagicNumber()==Magic && OrderSymbol()==Symbol() && OrderType() == OP_SELL)
                        {
                        if (OrderTakeProfit()!=ND(Sr_Cena(OP_SELL)-take_profit))
                           {
                           int tiketS=OrderModify(OrderTicket(),OrderOpenPrice(),0,ND(Sr_Cena(OP_SELL)-take_profit),0);
                           if (tiketS==false) Print (GetLastError()," OrderTicket= ",OrderTicket(), " TP= ", DoubleToString(ND(Sr_Cena(OP_SELL)-take_profit),8), " Ордер ТР= ", DoubleToString(OrderTakeProfit(),8)," Разница= ",DoubleToString((OrderTakeProfit()-ND(Sr_Cena(OP_SELL)-take_profit))*1000000,8) );
                           Print("Флаг прохождения= ОК");
                           }
                        }
                     }
               }
            }
          }
        flag_new_order=false;    
      }
   return(0);

Установил флаги и в журнале ошибок видно, что при вхождении в цикл модификации ордеров, успешно модифицируется только самый крайний №3, а потом идет обращение опять к самому крайнему №3, но естественно его уже нельзя модифицировать, а оставшийся ордер №2 так и остался без изменений....

 

В цикле с модификацией вы выбираете ордера типа SELL, а ордера № 2 и 3 имеют тип BUY.

Ошибка 1 выскакивает обычно, когда производиться попытка модифицировать ордер с прежними значениями цен. Проверяйте изменения перед отправкой запроса.

 
Vasiliy Pushkaryov:

В цикле с модификацией вы выбираете ордера типа SELL, а ордера № 2 и 3 имеют тип BUY.

Ошибка 1 выскакивает обычно, когда производиться попытка модифицировать ордер с прежними значениями цен. Проверяйте перед отправкой запроса изменения.

Василий, в том то и проблема.

В цикле с модификацией у меня сначала идет проверка ордеров BUY, затем SELL. Я могу вырезать кусок кода проверки на SELL, но проблема останется. Ошибка 1, как Вы и заметили, говорит о том, что советник пытается модифицировать уже модифицированный ордер, а не оставшийся ордер.

 
Alexandr Kambolin:

Василий, в том то и проблема.

В цикле с модификацией у меня сначала идет проверка ордеров BUY, затем SELL. Я могу вырезать кусок кода проверки на SELL, но проблема останется. Ошибка 1, как Вы и заметили, говорит о том, что советник пытается модифицировать уже модифицированный ордер, а не оставшийся ордер.

Нужно запросить цену установки ордера, и если она равна цене на которую нужно модифицировать - пропускаем и идём к следующему в цикле
 
Vitaly Muzichenko:
Нужно запросить цену установки ордера, и если она равна цене на которую нужно модифицировать - пропускаем и идём к следующему в цикле

Нужно нормализировать цены, отнять одну цену от другой и сравнить с нулем, иначе в цене может быть "шум" и сравнение двух цен иногда не даст корректный результат. Так как при запросе цены может быть 1.0756200001 и эта случайная единица в конце приводит к ошибке 1.

https://www.mql5.com/ru/articles/1561 

Особенности работы с числами типа double в MQL4
Особенности работы с числами типа double в MQL4
  • 2009.11.02
  • MetaQuotes Software Corp.
  • www.mql5.com
В данной заметке собраны советы по решению наиболее часто возникающих ошибок при работе с числами типа double в программах на MQL4.
 
Vladimir Zubov:

Нужно нормализировать цены, отнять одну цену от другой и сравнить с нулем, иначе в цене может быть "шум" и сравнение двух цен иногда не даст корректный результат. Так как при запросе цены может быть 1.0756200001 и эта случайная единица в конце приводит к ошибке 1.

https://www.mql5.com/ru/articles/1561 

Так в коде всё нормализуется у товарища:

ND(Sr_Cena(OP_SELL)-take_profit)


 

 
Vitaly Muzichenko:

Так в коде всё нормализуется у товарища:

ND(Sr_Cena(OP_SELL)-take_profit)


 

Так у него ошибка 1 вылазит. Если запросить цену тейкпрофита и сравнить её с предполагаемой ценой модификации, то из за шума в цифрах будет именно эта ошибка.
 
Vladimir Zubov:
Так у него ошибка 1 вылазит. Если запросить цену тейкпрофита и сравнить её с предполагаемой ценой модификации, то из за шума в цифрах будет именно эта ошибка.

Я тоже так думал, поэтому делал эту проверку:

" TP= ", DoubleToString(ND(Sr_Cena(OP_BUY)+take_profit),8), " Ордер ТР= ", DoubleToString(OrderTakeProfit(),8)," Разница= ",DoubleToString((OrderTakeProfit()-ND(Sr_Cena(OP_BUY)+take_profit))*1000000,8) )

 Преобразовал и нашел разницу и на всякий случай умножил разницу на 100000. Результат = 0.

Выделил на скриншоте это действие: 

На скриншоте ошибок видны цены открытия ордеров.  

Ордер #2: 1.19436

Ордер #3: 1.19236

Усредняющий должен быть:  1.19386

Ордер #3 - модифицируется уровень ТП до усредняемого, а проверка ордера #2 по видимому не происходит, т.к. идёт попытка опять модифицировать ордер#3. Либо я что то не могу понять, т.к. мало опыта.  

 

Все чудесатее и чудесатее...

Установил пару флагов и пару фигурных скобок чтобы быть уверенным в исполнении цикла. Один флаг печатает номер ордера сразу после его выбора, а второй печатает номер этого ордера перед началом его модификации. Вот кусок измененного кода:

//+------------------------------------------------------------------+
// Выставляем усредняющий тейкпрофит
//+------------------------------------------------------------------+
      if (orders[6]>0)  //Если есть открытые ордера
         {bool tiket1;
         if (orders[0]>0 && flag_new_order==true)//Если ордера BUY и открыт усредняющий ордер
           {
            for (int i = OrdersTotal() - 1; i >= 0; i--)
               {tiket1=OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
                  Print ("Выбираем Ордер №= ", OrderTicket());
                  {if (tiket1==true)
                     {
                     if (OrderMagicNumber()==Magic && OrderSymbol()==Symbol() && OrderType() == OP_BUY)
                        {
                        if (OrderTakeProfit()!=ND(Sr_Cena(OP_BUY)+take_profit))
                           {
                           Print ("Для модификации Выбираем Ордер №= ", OrderTicket()," Цена открытия ордера", DoubleToString(OrderOpenPrice(),8));
                           int tiketB=OrderModify(OrderTicket(),OrderOpenPrice(),0,ND(Sr_Cena(OP_BUY)+take_profit),0);
                           if (tiketB==false) Print (GetLastError()," OrderTicket= ",OrderTicket(), " TP= ", DoubleToString(ND(Sr_Cena(OP_BUY)+take_profit),8), " Ордер ТР= ", DoubleToString(OrderTakeProfit(),8)," Разница= ",DoubleToString((OrderTakeProfit()-ND(Sr_Cena(OP_BUY)+take_profit))*1000000,8) );
                           Print("Флаг прохождения= ОК");
                           }
                        }
                      }
                   }
                }
            }
          }
        flag_new_order=false;  

 Получил следующую картину в журнале ошибок:

 

 т.е. в цикле каким то образом происходит подмена выбранного ордера на предыдущий....

Может у кого есть мысли по этому поводу?  

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