Глюк визуального тестирования?

 

Столкнулся с совершенно необъяснимым явлением. При попытке тестирования в визуальном режиме, тест вылетает с ошибкой:

QL      0       14:23:25.205    SZZ_2.01 (EURUSD,H1)    2018.09.01 00:00:00   Получен хендл индикатора handle_MSZ_main
MQ      0       14:23:25.255    SZZ_2.01 (EURUSD,H1)    2018.09.01 00:00:00   Получен хендл индикатора handle_MSZ_addi
EO      0       14:23:25.255    SZZ_2.01 (EURUSD,H1)    2018.09.01 00:00:00   Не удалось скопировать данные из индикаторного буфера в buffer_MSZ_main
CS      0       14:23:25.255    SZZ_2.01 (EURUSD,H1)    2018.09.01 00:00:00   LastError = 4806
............
EI      2       14:23:25.256    Tester  tester stopped because OnInit returns non-zero code
EE      3       14:23:25.320    127.0.0.1       MetaTester 5 forced to stop

При том, что в обычном режиме (без визуализации) тест проходит успешно.

Индикатор - стандартный ZigZag.

 
Сергей Таболин:

Столкнулся с совершенно необъяснимым явлением. При попытке тестирования в визуальном режиме, тест вылетает с ошибкой:

При том, что в обычном режиме (без визуализации) тест проходит успешно.

Индикатор - стандартный ZigZag.

Он же Вам пишет, что функция OnInit завершилась не строкой

return INIT_SUCCEEDED;

 
Функцию OnInit выложите.
 
Vladimir Simakov:
Функцию OnInit выложите.
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   if(SymbolInfoInteger(Symbol(),SYMBOL_DIGITS) != 3 && SymbolInfoInteger(Symbol(),SYMBOL_DIGITS) != 5)
   {
      MessageBox("Советник работает только на 3-х и 5-и значных счетах...","Не 3/5-и значный счёт...",MB_OK);
      Print("Советник работает только на 3-х и 5-и значных счетах...");
      return(INIT_FAILED);
   }
//+------------------------------------------------------------------+
   if((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_NETTING)   account_type = account_netting;
   else                                                                                                        account_type = account_hedge;
//+--------
   ArraySetAsSeries(rates,                true);
   ArraySetAsSeries(buffer_MSZ_main,      true);
   ArraySetAsSeries(buffer_MSZ_addi,      true);
//+--------
   int sw = 1;
   handle_MSZ_main = iCustom(Symbol(),0,"Examples\\Zigzag",trend_strengs_main,27,18);
   if(handle_MSZ_main == INVALID_HANDLE)                                // проверяем наличие хендла индикатора
   {
      Comment("Не удалось получить хендл индикатора handle_MSZ_main");  // если хендл не получен, то выводим сообщение в лог об ошибке
      Print("Не удалось получить хендл индикатора handle_MSZ_main");
      return(INIT_FAILED);                                              // завершаем работу с ошибкой
   }
   else
   {
      Print("Получен хендл индикатора handle_MSZ_main");
      ChartIndicatorAdd(ChartID(),0,handle_MSZ_main);                   // подключаем индикатор к графику
   }

   handle_MSZ_addi = iCustom(Symbol(),0,"Examples\\Zigzag",trend_strengs_addi,18,9);
   if(handle_MSZ_addi == INVALID_HANDLE)                                // проверяем наличие хендла индикатора
   {
      Comment("Не удалось получить хендл индикатора handle_MSZ_addi");  // если хендл не получен, то выводим сообщение в лог об ошибке
      Print("Не удалось получить хендл индикатора handle_MSZ_addi");
      return(INIT_FAILED);                                              // завершаем работу с ошибкой
   }
   else
   {
      Print("Получен хендл индикатора handle_MSZ_addi");
      ChartIndicatorAdd(ChartID(),0,handle_MSZ_addi);                   // подключаем индикатор к графику
   }
//+--------
   //--- проверить входной лот
   pos_set.start_lot = (SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN) <= Lot                  ? Lot             : SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN));
   pos_set.start_lot = (SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX) >= Lot                  ? Lot             : SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX));
   pos_set.start_lot = NormalizeDouble(pos_set.start_lot,2);
   pos_set.order_lot = pos_set.start_lot;
   //--- проверить шаг увеличения лота
   pos_set.step_lot  = (SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP)<= lot_increment        ? lot_increment   : SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP));
   pos_set.step_lot  = (SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX) >= lot_increment * 10.0 ? lot_increment   : SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX) / 10.0);
   pos_set.step_lot  = NormalizeDouble(pos_set.step_lot,2);
}
//+--------
   pos_get.order_set       = false;
   pos_get.order_stop_set  = false;
   pos_set.order_direction = trend_no;
   pos_set.start_balance   = my_Account.Balance();
//+--------
if(pos_set.order_direction == trend_no)
   // проверка направления закончившегося тренда ЗЗ
   {
      if(!copyBuffers()) return(INIT_FAILED);
      
      for(int i = 0; i < ArraySize(buffer_MSZ_main); i++)
      {
         if(buffer_MSZ_main[i] != 0.0 && pr_0_main == 0.0) pr_0_main = buffer_MSZ_main[i];
         else
         if(buffer_MSZ_main[i] != 0.0 && pr_0_main != 0.0)
         {
            pr_x_main = buffer_MSZ_main[i];
            break;
         }
      }
      
      pos_set.order_direction = (pr_0_main > pr_x_main ? trend_up : trend_dn);
   }
//+--------
   return(INIT_SUCCEEDED);
}

bool copyBuffers()
{
   int n = (pos_set.order_direction == trend_no ? 300 : 3);
   
   ArrayFree(rates);
   ArrayFree(buffer_MSZ_addi);
   ArrayFree(buffer_MSZ_main);
   
   ResetLastError();
   
   if(CopyRates(Symbol(),0,0,(gap_distance > 3 ? gap_distance : 3),rates) < 0) return(false);
      
   if(CopyBuffer(handle_MSZ_main,0,2,n,buffer_MSZ_main) < n) // копируем данные из индикаторного массива в массив buffer_MSZ_main
   {                                                                                         // если не скопировалось
      Print("Не удалось скопировать данные из индикаторного буфера в buffer_MSZ_main");      // то выводим сообщение об ошибке
      Print("LastError = "+string(GetLastError()));
      return(false);                                                                         // и выходим из функции
   }
   
   if(CopyBuffer(handle_MSZ_addi,0,2,n,buffer_MSZ_addi) < n) // копируем данные из индикаторного массива в массив buffer_MSZ_addi
   {                                                                                         // если не скопировалось
      Print("Не удалось скопировать данные из индикаторного буфера в buffer_MSZ_addi");      // то выводим сообщение об ошибке
      Print("LastError = "+string(GetLastError()));
      return(false);                                                                         // и выходим из функции
   }
   
   return(true);
}

Так в том то и дело, ошибка эта выскакивает ТОЛЬКО в визуальном режиме.

 
Сергей Таболин:

Так в том то и дело, ошибка эта выскакивает ТОЛЬКО в визуальном режиме.

В индикаторном буфере при инициализации советника еще пусто.
 
Vladimir Simakov:
В индикаторном буфере при инициализации советника еще пусто.

Хорошо. Значит при тесте там чё-то есть, а как только визуальный режим, то нету?

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

 

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

Визуальный режим отличается от простого тем, что в простом режиме индикаторы рассчитываются по запросу (создали индикатор, запросили данные, ах данных ещё нет, щас посчитаем), а в визуальном режиме индикаторы рассчитываются после OnInit, а дальше с приходом каждого нового сгенерированного тика

Зачем Вы в OnInit буфера-то запрашиваете?

 
Slava:

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

Визуальный режим отличается от простого тем, что в простом режиме индикаторы рассчитываются по запросу (создали индикатор, запросили данные, ах данных ещё нет, щас посчитаем), а в визуальном режиме индикаторы рассчитываются после OnInit, а дальше с приходом каждого нового сгенерированного тика

Зачем Вы в OnInit буфера-то запрашиваете?

Спасибо за разъяснение.

Я, по наивности, наверное, думал что визуальный - это тот же тест, только с отрисовкой картинки. Как оказалось, это разные процессы. )))

А в OnInit я хотел провести одноразовый расчёт, который впоследствии не нужен. Ну а раз так, то перенесу его уже в OnTick.

=======

Кстати, может есть ещё какие отличия/ограничения визуального и простого теста?