Странный баг

 

много лет пользовался функцией закрытия ордеров вот такой: 

  for(int cnt=OrdersTotal()-1;cnt>=0;cnt--)
        {
         if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==_Symbol && OrderMagicNumber()==mag)
              {
               if(OrderType()==OP_BUY)
                 {
                  if(Bid>ch || Bid>=OrderOpenPrice()+TP*_Point || Bid<=OrderOpenPrice()-SL*_Point)
                    {
                     Print(st5(Bid),"  Close Buy  ",st5(ch));
                     o=OrderClose(OrderTicket(),OrderLots(),Bid,0);
                    }
                 }
               if(OrderType()==OP_SELL)
                 {
                  if(Ask<cl || Ask<=OrderOpenPrice()-TP*_Point || Ask>=OrderOpenPrice()+SL*_Point)
                    {
                     if((!TradeAfterRollover) && (Hour()==RolloverHour && Minute()<= Minute_after_RollOver)) return;
                     Print(st5(Ask),"  Close Sell  ",st5(cl));
                     o=OrderClose(OrderTicket(),OrderLots(),Ask,0);
                    }
                 }
              }
           }
        }

СфСегодня на счете запустил двух роботов одновременно с одинаковыми магиками. 

И обнаружил что ордера одного инструмента,на котором работает первый советник закрывает другой советник работающий на другом инструменте. 

Оказалось, что такое сравнение больше не работает. 

Приходится теперь везде переделывать вот так. 

  for(int cnt=OrdersTotal()-1;cnt>=0;cnt--)
        {
         if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderSymbol()==_Symbol && OrderMagicNumber()==mag)
              {
               if(OrderType()==OP_BUY)
                 {
                  if(Bid>ch || Bid>=OrderOpenPrice()+TP*_Point || Bid<=OrderOpenPrice()-SL*_Point)
                    {
                     Print(st5(Bid),"  Close Buy  ",st5(ch));
                     o=OrderClose(OrderTicket(),OrderLots(),Bid,0);
                    }
                 }
               if(OrderType()==OP_SELL)
                 {
                  if(Ask<cl || Ask<=OrderOpenPrice()-TP*_Point || Ask>=OrderOpenPrice()+SL*_Point)
                    {
                     if((!TradeAfterRollover) && (Hour()==RolloverHour && Minute()<= Minute_after_RollOver)) return;
                     Print(st5(Ask),"  Close Sell  ",st5(cl));
                     o=OrderClose(OrderTicket(),OrderLots(),Ask,0);
                    }
                 }
              }
           }
        }

Возникает вопрос почему раньше все работало нормально, а теперь прям беда ! ? 
 

Есть целая ветка, посвященная этому вопросу.

Организация цикла перебора ордеров
Организация цикла перебора ордеров
  • 2017.09.16
  • www.mql5.com
MQL4 и MetaTrader 4: Организация цикла перебора ордеров
 
Dmitiry Ananiev:

много лет пользовался функцией закрытия ордеров вот такой:

if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==_Symbol && OrderMagicNumber()==mag)

СфСегодня на счете запустил двух роботов одновременно с одинаковыми магиками. 

И обнаружил что ордера одного инструмента,на котором работает первый советник закрывает другой советник работающий на другом инструменте. 

Оказалось, что такое сравнение больше не работает. 

Приходится теперь везде переделывать вот так.

if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderSymbol()==_Symbol && OrderMagicNumber()==mag)
Возникает вопрос почему раньше все работало нормально, а теперь прям беда ! ? 

Когда один эксперт закрывает ордер , изменяется список ордеров.

Когда два эксперта хотят закрыть одновременно ордера, то происходит последовательно !

Тогда один (первой) срабатывает правильно, а второму нужно некоторое время для удаления закрытого ордера из списка.

 
 for(int cnt=OrdersTotal()-1;cnt>=0;cnt--)
        {
         if((OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)==true) && OrderSymbol()==_Symbol && OrderMagicNumber()==mag)
              {
               if(OrderType()==OP_BUY)
                 {
                  if(Bid>ch || Bid>=OrderOpenPrice()+TP*_Point || Bid<=OrderOpenPrice()-SL*_Point)
                    {
                     Print(st5(Bid),"  Close Buy  ",st5(ch));
                     o=OrderClose(OrderTicket(),OrderLots(),Bid,0);
                    }
                 }
               if(OrderType()==OP_SELL)
                 {
                  if(Ask<cl || Ask<=OrderOpenPrice()-TP*_Point || Ask>=OrderOpenPrice()+SL*_Point)
                    {
                     if((!TradeAfterRollover) && (Hour()==RolloverHour && Minute()<= Minute_after_RollOver)) return;
                     Print(st5(Ask),"  Close Sell  ",st5(cl));
                     o=OrderClose(OrderTicket(),OrderLots(),Ask,0);
                    }
                 }
              }
           }
        }

Интересно, а так будет?

 
Dmitiry Ananiev:
Возникает вопрос почему раньше все работало нормально, а теперь прям беда ! ? 

Возможно бага. Есть подозрение что OrderSymbol или OrderMagicNumber вызывается раньше OrderSelect из-за UB вычисления аргументов.

А бага в том, что для операторов && и || аргументы должны вычисляться по порядку, без UB. Если я опять же ничего не путаю.

 
Vladimir Deryagin:

Интересно, а так будет?

А какая разница?

if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==_Symbol && OrderMagicNumber()==mag)
if((OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)==true) && OrderSymbol()==_Symbol && OrderMagicNumber()==mag)
 
Комбинатор:

Возможно бага. Есть подозрение что OrderSymbol или OrderMagicNumber вызывается раньше OrderSelect из-за UB вычисления аргументов.

А бага в том, что для операторов && и || аргументы должны вычисляться по порядку, без UB. Если я опять же ничего не путаю.


Смеялись в какой то ветке с человека, который каждое условие в коде заключал в скобки и общее условие тоже. Оно вроде и не обязательно, но зная как работает компилятор и ассемблер, раздавая приоритеты исполнению и опыт глюков от версий к версии, скобки отнюдь не лишнее. Что бы "пережить" кучу апдейтов и багов компиляции от версии к версии и код остался рабочим.

 

Посмотрите функции KimIV они работают без багов с момента написания 2006-2008 года.

Потому что он учел все условия приоритетов исполнения при компиляции.

Казалось бы что из школы мы знаем что умножение делается первым а потом сложение, но такое условие в том же ассемблере будет совсем условно, сорри за тавтологию)

(2+2*x) или (2+(2*x)) результаты могут быть разными.

 

Да нет, приоритет проверки поменять не могли так просто.

Скорее всего, дело в этом:

fxsaber:

Есть целая ветка, посвященная этому вопросу.


Логи бы помогли, конечно.

 

У меня много таких конструкций, где проверки в блоках if() идут по порядку, и всё по сей день отрабатывает чётко и без сбоев.

 
Vladimir Zubov:

Посмотрите функции KimIV они работают без багов с момента написания 2006-2008 года.

Серьезно что ли? Мне до зубовного скрежета достало в свое время выкорчевывать баги из его кода, тем более что пользовалось народу этим кодом довольно много
Причина обращения: