Функция OrderSelect, оператор while и удаление скрипта с чарта

 

Уважаемые разработчики,

хотел бы поделиться информацией о нетипичной ситуации (баге), которой не должно быть (build 216)

Суть проблемы: при удалении приведённого ниже скрипта с чарта это удаётся сделать только со второй попытки. При этом во вкладке "Эксперты" отображаются записи, которые не должны там появляться.

Было обнаружено в своём советнике. Ниже привожу простенький скрипт для воспроизведения проблемы на вашей стороне.

//+------------------------------------------------------------------+
//|                                                  test_select.mq4 |
//|                      Copyright © 2006, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//----
int ord_ticket=24181264;//необходимо вписать номер тикета открытого ордера

   while(OrderSelect(ord_ticket,SELECT_BY_TICKET,MODE_TRADES))
   {
         Print("ку-ку");
         Sleep(10000);
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+

Что нужно сделать.

1. Запускаем скрипт на чарте.

2. Наблюдаем сообщения на вкладе "Эксперты" например 1 минуту.

3. Производим удаление скрипта с чарта посредством нажатия правой кнопки мыши ->Удалить скрипт. Данный пункт понадобится сделать 2 раза, так как однократного нажатия оказывается недостаточно.

4. Ниже представлено содержимое вкладки "Эксперты" после выполненных операций (обратите внимание на время! - сначала команда Print срабатывает раз в 10 секунд, а после удаления скрипта с чарта начинается бесконечный цикл работы команды Print без пауз):

2008.07.03 23:58:49 test_select EURUSDm,H1: removed
2008.07.03 23:58:49 test_select EURUSDm,H1: uninit reason 1
2008.07.03 23:58:49 test_select EURUSDm,H1: shutdown by timeout
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:49 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:48 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:48 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:48 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:48 test_select EURUSDm,H1: ку-ку

*****<сокращено для экономии места>*******

2008.07.03 23:58:38 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:38 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:38 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:38 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:37 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:36 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:35 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:35 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:35 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:35 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:35 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:35 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:35 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:30 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:20 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:10 test_select EURUSDm,H1: ку-ку
2008.07.03 23:58:10 test_select EURUSDm,H1: loaded successfully

Вопрос состоит в следующем - откуда берётся пулемётное выстреливание функции Print при удалении данного скрипта с чарта?

Я в своей программе хочу использовать данную комбинацию оператора while с функцией OrderSelect, но у меня подобные сбои возникают и при штатной работе советника. Подскажите как это можно обойти?

Заранее благодарю за объяснение проблемы!

 

Я бы вот так сделал:

int start()
  {
int ord_ticket=26234130;//необходимо вписать номер тикета открытого ордера

   while(!IsStopped()&&OrderSelect(ord_ticket,SELECT_BY_TICKET))
//   while(OrderSelect(ord_ticket,SELECT_BY_TICKET,MODE_TRADES))
   {
         Print("ку-ку");
         Sleep(10000);
   }
   return(0);
  }
//+------------------------------------------------------------------+
 
KimIV писал (а) >>

Я бы вот так сделал:

У меня с зацикленными скриптами все тоже самое происходит не помогает и !IsStopped(), проверено.

 
Talex писал (а) >>

У меня с зацикленными скриптами все тоже самое происходит не помогает и !IsStopped(), проверено.

А Вы мой скрипт проверьте. У меня он нормально работает. Удаляется с графика без проблем. И пулемётных очередей нет. Вот протокол:

2008.07.04 09:38:56 test EURUSD,H1: removed
2008.07.04 09:38:56 test EURUSD,H1: uninit reason 1
2008.07.04 09:38:53 test EURUSD,H1: ку-ку
2008.07.04 09:38:42 test EURUSD,H1: ку-ку
2008.07.04 09:38:31 test EURUSD,H1: ку-ку
2008.07.04 09:38:21 test EURUSD,H1: ку-ку
2008.07.04 09:38:21 test EURUSD,H1: loaded successfully

 
KimIV писал (а) >>

А Вы мой скрипт проверьте. У меня он нормально работает. Удаляется с графика без проблем. И пулемётных очередей нет. Вот протокол:

Действительно, работает. Пошел смотреть свой скрипт. Спасибо, Игорь.

 

KimIV, спасибо за совет. Для данного скрипта наверное это выход из ситуации. Но всё-таки с точки зрения разработчиков наверное нужно бы обратить внимание на тот факт, что при снятии скрипта с оператором while начинается бесконечное выполнение оператора Print, при этом игнорируется выполнение функции Sleep(). С точки зрения пользователя такого происходить не должно. С обывательской точки зрения допустимы 2 варианта:

1. ВСЕ функции перестают выполняться при снятии скрипта с чарта.

2. ВСЕ функции продолжают выполняться в ПОЛНОМ объёме до следующего цикла оператора while.

Хотелось бы увидеть реализацию одного из этих вариантов в будущих билдах.

 

Можно ещё вот так сделать:

void start() {
  int ticket=26234130; //необходимо вписать номер тикета открытого ордера

//  while(!IsStopped()&&OrderSelect(ord_ticket,SELECT_BY_TICKET))
  while (OrderSelect(ticket, SELECT_BY_TICKET)) {
    Print("ку-ку ", UninitializeReason());
    if (UninitializeReason()>0) break;
    Sleep(10000);
  }
}
2008.07.04 11:52:56 test EURUSD,H1: removed
2008.07.04 11:52:56 test EURUSD,H1: uninit reason 1
2008.07.04 11:52:56 test EURUSD,H1: ку-ку 1
2008.07.04 11:52:54 test EURUSD,H1: ку-ку 0
2008.07.04 11:52:43 test EURUSD,H1: ку-ку 0
2008.07.04 11:52:43 test EURUSD,H1: loaded successfully
 
solandr писал (а) >>
Но всё-таки с точки зрения разработчиков наверное нужно бы обратить внимание на тот факт, что при снятии скрипта с оператором while начинается бесконечное выполнение оператора Print, при этом игнорируется выполнение функции Sleep(). С точки зрения пользователя такого происходить не должно.

Андрей, не знаю, поймёте Вы меня или обозлитесь, но всё-таки скажу. Я предпочитаю никого не напрягать своими проблемами. Стараюсь искать решения, раздражающие как можно мЕньшее количество людей. Это знаете, как "Вам шашечки или ехать", "ломиться в стену или поискать дверь". У разработчиков своих проблем хватает, а мы свои программистские дела запросто можем решить без их (разработчиков) привлечения.

 

Согласен, что никого напрягать своими проблемами не нужно. Единственный смысл моего послания - это bug reporting. Если это разработчикам неинтересно, то ничего страшного. А воркэраундов текущей ситуации существует огромное количество (как в скрипте так и в моём советнике, который не требуется снимать с чарта). Тем более что главный мотив, который побудил меня написать об этом здесь - это то, что в обычном советнике, который использует конструкцию while (OrderSelect(ticket, SELECT_BY_TICKET)) для закрытия ордера время от времени возникает подобная пулемётная стрельба функцией OrderClose. В данном примере Print является заменой функции OrderClose в моём советнике, но только позволяет смоделировать ситуацию наглядно, не высиживая сутками перед монитором. И я подразумеваю что случай с моим советником и приведённым выше скриптом содержат в своей основе одну и ту же причину. Какую именно могут предположить лишь разработчики, если им это конечно же интересно.

 

Для правильной остановки скрипта всегда используйте функцию IsStopped(). Почему?

Дело в том, что скрипту даётся шанс доделать своё дело. Если не использовать функцию IsStopped(), скрипт никогда не узнает, что его хотят остановить и будет продолжать работу. До тех пор пока ему повторно не прикажут закрыться. Если повторно выбрать пункт меню "Закрыть скрипт" (при том, что стоп-флаг уже взведён), то поток, в котором работает скрипт, прибивается насильно. И какое место цикла в данный момент обрабатывается, неизвестно.

 
stringo писал (а) >>

Для правильной остановки скрипта всегда используйте функцию IsStopped(). Почему?

Дело в том, что скрипту даётся шанс доделать своё дело. Если не использовать функцию IsStopped(), скрипт никогда не узнает, что его хотят остановить и будет продолжать работу. До тех пор пока ему повторно не прикажут закрыться. Если повторно выбрать пункт меню "Закрыть скрипт" (при том, что стоп-флаг уже взведён), то поток, в котором работает скрипт, прибивается насильно. И какое место цикла в данный момент обрабатывается, неизвестно.

Раз разработчикам проблема стала всё-таки интересна, то продолжу диалог дальше. (Выражаю по этому поводу респект!)

Ниже приведён код тестового советника, воспроизводящий ситуацию, описанную выше. Советник останавливать не требуется, но при этом результат выходит идентичный - не отрабатывается правильным образом связка while(Select)

//+------------------------------------------------------------------+
//|                                            while_select_test.mq4 |
//|                      Copyright © 2006, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----
double v=0.01;//установлен минимальный размер лота для теста (у других брокеров это значение может быть 0.1)
string symb=Symbol();
int magic_multi=111;
   
//Открываем тестовый ордер   
OrderSend(symb,OP_BUY,NormalizeDouble(v,2),NormalizeDouble(MarketInfo(symb,MODE_ASK),
	MarketInfo(symb,MODE_DIGITS)),6,NormalizeDouble(0,MarketInfo(symb,MODE_DIGITS)),
	NormalizeDouble(0,MarketInfo(symb,MODE_DIGITS)),"TEST_BUY",magic_multi,0);
Sleep(60000);
   

//Закрываем тестовый ордер
int ticket;
int ord_ticket;
   
for(ticket=0;ticket<OrdersTotal();ticket++)
{//внутренний for
   if (OrderSelect(ticket,SELECT_BY_POS,MODE_TRADES)==false) break;
   else
   {//начало else
      if (OrderMagicNumber()==magic_multi) 
      {
         ord_ticket=OrderTicket();
         if(OrderType()==OP_BUY) 
         {
            while(OrderSelect(ord_ticket,SELECT_BY_TICKET,MODE_TRADES))
            {
               Print("ЗАКРЫВАЕМ TEST_BUY");
               RefreshRates();
               OrderClose(OrderTicket(),OrderLots(),MarketInfo(symb,MODE_BID),5); 
               Sleep(1000);
            }
            
         }
      }
   }//конец else
}//внутренний for


//----
   return(0);
}
//+------------------------------------------------------------------+

22:25:19 while_select_test GBPUSDm,M30: loaded successfully
22:25:57 while_select_test GBPUSDm,M30: initialized
22:26:02 while_select_test GBPUSDm,M30: open #25016313 buy 0.01 GBPUSDm at 1.9960 ok
22:27:04 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:04 while_select_test GBPUSDm,M30: close #25016313 buy 0.01 GBPUSDm at 1.9960 at price 1.9950
22:27:06 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:06 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:07 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:07 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:08 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:08 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:09 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:09 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:10 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:10 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:11 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:11 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:12 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:12 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:13 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:13 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:14 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:14 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:15 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:15 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:16 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:16 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:17 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:17 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:18 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:18 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:19 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:19 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:20 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:20 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:20 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:20 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:20 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:20 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:20 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:20 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:20 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:20 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:20 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:20 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:20 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:20 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:21 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:21 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:22 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:22 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:22 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:22 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:22 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:22 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:22 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: ЗАКРЫВАЕМ TEST_BUY
22:27:22 while_select_test GBPUSDm,M30: unknown ticket 25016313 for OrderClose function
22:27:22 while_select_test GBPUSDm,M30: shutdown by timeout
22:27:22 while_select_test GBPUSDm,M30: deinitialized
22:27:22 while_select_test GBPUSDm,M30: uninit reason 1
22:27:22 while_select_test GBPUSDm,M30: removed

После наблюдения в течение 15 секунд за печатанием ЗАКРЫВАЕМ TEST_BUY в цикле while(Select) в 22:27:20 я вручную снял советник с графика дабы завершить тест (пулемётная стрельба после снятия эксперта с графика была объяснена выше).

Выше приложен лог файл.

Прошу объяснить где ошибка именно в этом коде советника?

Ниже справки из хелпа:

bool OrderSelect( int index, int select, int pool=MODE_TRADES)
Функция выбирает ордер для дальнейшей работы с ним. Возвращает TRUE при успешном завершении функции. Возвращает FALSE при неудачном завершении функции.

Если выражение истинно, то оператор выполняется до тех пор, пока выражение не станет ложным. Если выражение ложно, то управление передается следующему оператору.

while(выражение)
оператор;
Причина обращения: