Новая статья: Типичные ошибки в программах на MQL4 и методы их устранения

 

Опубликована статья Типичные ошибки в программах на MQL4 и методы их устранения

При использовании новой версии компилятора языка MQL4 некоторые старые программы могут выдавать ошибки.

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

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

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

  1. Ошибки компиляции
  2. Ошибки времени выполнения
  3. Предупреждения компилятора

Типичные ошибки в программах на MQL4 и методы их устранения

 

Суть проблемы. Эксперт. МТ4 билд 625. Из функции OnTick() вызывается пользовательская функция OrderStatus(). При наличии, например, в рынке ордера Buy с меткой, пусть это будет "11", соответствующий счетчик Buy, объявленный на глобальном уровне, в функции OrderStatus() увеличивается на 1, если метка рыночного ордера соответствует выше указанной. При открытии терминала счетчик Buy (соответственный рыночный ордер существует) после вызова функции OrderStatus() в функции OnTick() всегда имеет Buy=0, нулевое значение. Как правило, в течение 2-4 проходов. В тоже время, если терминал открыт, например, после компиляции эксперта при наличии соответствующего ордера счётчик увеличивается на единицу, как положено :) .

Учитывая, что в старой версии МТ4 все работало много лет подряд, вероятно, что - то делаю неправильно. Прошу разъяснить. За ранее, спасибо.

 
dArd:

Суть проблемы. Эксперт. МТ4 билд 625. Из функции OnTick() вызывается пользовательская функция OrderStatus(). При наличии, например, в рынке ордера Buy с меткой, пусть это будет "11", соответствующий счетчик Buy, объявленный на глобальном уровне, в функции OrderStatus() увеличивается на 1, если метка рыночного ордера соответствует выше указанной. При открытии терминала счетчик Buy (соответственный рыночный ордер существует) после вызова функции OrderStatus() в функции OnTick() всегда имеет Buy=0, нулевое значение. Как правило, в течение 2-4 проходов. В тоже время, если терминал открыт, например, после компиляции эксперта при наличии соответствующего ордера счётчик увеличивается на единицу, как положено :) .

Учитывая, что в старой версии МТ4 все работало много лет подряд, вероятно, что - то делаю неправильно. Прошу разъяснить. За ранее, спасибо.


попробуйте перед закрывающейся функцией подсчета ордеров с меткой "11" поставить break;

Или выложить эксперта.

 
Странно обсуждать код при отсутствия самого кода.
 
Renat:
Странно обсуждать код при отсутствия самого кода.


Прошу прощения.

Код. Удалил всё, что не отражает суть проблемы. Проще не бывает ... :) ... но, при "первой загрузке" терминала ... BuyStop=0, если терминал работает и удалить и снова загрузить эксперт - все работает нормально.

Проверка проведена для ордера BuyStop. При наличии ордера BuyStop в рынке, счетчик BuyStop=1 с момента начала работы эксперта.

// Входные данные

input string   Метка                   = "Метка Ордеров";   // Метка ордеров
input string   МеткаОрдера             = "11";
      
      int      Buy=0,Sell=0,
               BuyStop=0,SellStop=0;          // Кол-во соответствующих ордеров в рынке
               

//----                           // Г Л А В Н Ы Е    Ф У Н К Ц И И    Э К С П Е Р Т А

//----                                    // Ф У Н К Ц И Я      O N  I N I T ( )
void OnInit()
  {
//---- 
   return;
//----
   } //---- Конец функции OnInit
                                          // Ф У Н К Ц И Я      O N  T I C K ( )
void OnTick()
  {
//----
   if(Bars<100 || IsTradeAllowed()==false)
      return;
//----
// Блок управления ордерами
//----
   OrderStatus();
//----
   Comment(SellStop," ",Sell," ",BuyStop," ",Buy);
//----
// Конец блока управления ордерами
//----
   return;
//----
  } // Конец функции OnTick
//----

//+------------------------------------------------------------------+
//| Модуль данных для управления                                     |
//+------------------------------------------------------------------+
void OrderStatus() 
{
//=====
   Buy=0; Sell=0; BuyStop=0; SellStop=0;
//=====
   int total=OrdersTotal();   // if(total<1) return;
//----
  for (int i=0; i<total; i++)
  {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
      if (OrderSymbol()==Symbol())
      {
         if (OrderType()==OP_BUY && OrderComment()==МеткаОрдера)
         {
            Buy++;
         } // if         
         if (OrderType()==OP_BUYSTOP && OrderComment()==МеткаОрдера)
         {
            BuyStop++;
         } // if         
         if (OrderType()==OP_SELL && OrderComment()==МеткаОрдера)    
         {
            Sell++;
         } // if
         if (OrderType()==OP_SELLSTOP && OrderComment()==МеткаОрдера)
         {
            SellStop++;
         } // if         
    } // OrderSymbol
  }   // OrderSelect
  }   // for
//-----
   return;
//----
} // OrderStatus
//-------
 

Вы забываете обнулять глобальные переменные в функции OnInit.

При переинициализации (смена таймфрейма, символа и тд) экспертов не происходит автоматическая зачистка глобальных переменных, а вызывается лишь OnInit().

 
Renat:

Вы забываете обнулять глобальные переменные в функции OnInit.

При переинициализации (смена таймфрейма, символа и тд) экспертов не происходит автоматическая зачистка глобальных переменных, а вызывается лишь OnInit().



Учту, что обнулять необходимо и в OnInit(). В тоже время, глобальная переменная, например, BuyStop, обнуляется и в самой функции OrderStatus(), следовательно, как мне кажется, дело не в этом.

Приведу скриншот, Print() введена непосредственно после вызова OrderStatus() в OnTick(). При наличии ордера BuyStop в рынке ожидается что счетчик BuyStop будет равен 1, но ... реальный результат на скриншоте. Не могу понять в чем суть! :(

Данный результат возникает только после загрузки терминала.

 
dArd:


Учту, что обнулять необходимо и в OnInit(). В тоже время, глобальная переменная, например, BuyStop, обнуляется и в самой функции OrderStatus(), следовательно, как мне кажется, дело не в этом.


Добавьте директиву #property strict, попробуйте скомпилировать и избавьтесь от всех ошибок и ворнингов. В том числе и использование одинаковых имен для локальных и глобальных переменных. Так будете меньше путаться.
 
Rosh:

Добавьте директиву #property strict, попробуйте скомпилировать и избавьтесь от всех ошибок и ворнингов. В том числе и использование одинаковых имен для локальных и глобальных переменных. Так будете меньше путаться.

Вполне, вероятно. Уловил идею. Ясно. Спасибо.
 
Rosh:

Добавьте директиву #property strict, попробуйте скомпилировать и избавьтесь от всех ошибок и ворнингов. В том числе и использование одинаковых имен для локальных и глобальных переменных. Так будете меньше путаться.
В чем конкретно может быть путаница при передаче переменной по ссылке в функцию? Ведь новой переменной при этом не создается, а передается она сама, так зачем тогда вводить путаницу и придумывать этой переменной новое название?
 
dArd:


Учту, что обнулять необходимо и в OnInit(). В тоже время, глобальная переменная, например, BuyStop, обнуляется и в самой функции OrderStatus(), следовательно, как мне кажется, дело не в этом.

Приведу скриншот, Print() введена непосредственно после вызова OrderStatus() в OnTick(). При наличии ордера BuyStop в рынке ожидается что счетчик BuyStop будет равен 1, но ... реальный результат на скриншоте. Не могу понять в чем суть! :(

Данный результат возникает только после загрузки терминала.


В качестве эксперимента добавьте в Print() вывод OrdersTotal()

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