Где живёт индикатор созданный в режиме тестирования без визуализации?

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Yury Kirillov
5298
Yury Kirillov  

Если советником создается индикатор (например через iCustom()) в режиме тестирования с визуализацией или в режиме реальной работы,

то индикатор живёт в подокне некоторого окна и имеет свой номер среди прочих индикаторов этого подокна (ну или главного окна данного инструмента).

Вопрос 1: где живёт индикатор созданный советником в режиме тестирования без визуализации? В каком окне (подокне) и с каким номером?

Вопрос 2: где живёт индикатор созданный советником в режиме оптимизации?

Как самому создать советника или индикатор - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
Как самому создать советника или индикатор - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
  • www.metatrader5.com
Для разработки торговых систем в платформу встроен собственный язык программирования MetaQuotes Language 5 (MQL5), среда разработки MetaEditor и инструменты тестирования стратегий. Любую информацию о разработке торговых стратегий на языке MQL5 можно найти на официальном сайте MQL5.community. На этом же сайте в разделе Code Base могут быть...
Ihor Herasko
21191
Ihor Herasko  
Yury Kirillov:

Если советником создается индикатор (например через iCustom()) в режиме тестирования с визуализацией или в режиме реальной работы,

то индикатор живёт в подокне некоторого окна и имеет свой номер среди прочих индикаторов этого подокна (ну или главного окна данного инструмента).

А если индикатор без подокна? Он ведь тогда не отображается на графике (кроме тех случаев, когда он создает графические объекты).

Вопрос 1: где живёт индикатор созданный советником в режиме тестирования без визуализации? В каком окне (подокне) и с каким номером?

Вопрос 2: где живёт индикатор созданный советником в режиме оптимизации?

Ни в каком. Все в памяти, доступной именно терминалу.
Yury Kirillov
5298
Yury Kirillov  

Для проверки прописки индикатора, были написаны примитивный советник и индикатор.

Советник:

//expert
#property   strict
#property   tester_indicator  "Projects\\Temp\\ExpAndIndTest\\Indicator_01.ex5"
//
int indicator_handle=0;
//
//============================================================================================= MQL5 ===
//    OnInit()
//------------------------------------------------------------------------------------------------------
int OnInit(){
//----- Подключаем индикатор
   ResetLastError(); 
   indicator_handle=iCustom( Symbol(),
                                 PERIOD_CURRENT,
                                 "Projects\\Temp\\ExpAndIndTest\\Indicator_01.ex5");
   {if(GetLastError()>0)
   {
      return(INIT_FAILED);                              
   }};
//----- Размещаем индикатор в новое окно
   //Чтобы добавить индикатор в новое окно, параметр должен быть на единицу больше, чем индекс последнего существующего окна, то есть равен CHART_WINDOWS_TOTAL.
   int nNewWindow=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL);
   {if(!ChartIndicatorAdd(0,nNewWindow,indicator_handle))
   {
      Print("EXP: \"Indicator_01.ex5\" не добавлен.");
      return(INIT_FAILED);
   }else{
      Print("EXP: \"Indicator_01.ex5\" добавлен в окно=",nNewWindow," хендл=",indicator_handle);
   }}//if(!ChartIndicatorAdd(0,(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL),indicator_handle))
   return(INIT_SUCCEEDED);
}//OnInit()
//
//============================================================================================= MQL5 ===
//    OnDeinit()
//------------------------------------------------------------------------------------------------------
void OnDeinit(const int reason){
//----- Удалить индикатор с экрана
   string   iName="";
   int      iWindow=0;
   int      iNumber=0;
   {if(!Indicator_Delete_Handle(indicator_handle,iName,iWindow,iNumber))
   {
      Print("EXP: \"Indicator_01.ex5\" Не удален! Имя:",iName," Окно=",iWindow," Номер в окне=",iNumber," Хендл:",indicator_handle);
   }else{
      Print("EXP: \"Indicator_01.ex5\" Удален! Имя:",iName," Окно=",iWindow," Номер в окне=",iNumber," Хендл:",indicator_handle);
   }}//f(!Indicator_Delete_Handle(indicator_handle,iName))
   //DeleteGraph();
//-----
   return;
}//OnDeinit()
//
//============================================================================================= MQL5 ===
//    Indicator_Delete_Handle()
//------------------------------------------------------------------------------------------------------
bool Indicator_Delete_Handle( int      iIndicatorHandle,
                              string   &Chart_Indicator_Name,
                              int      &Chart_Indicator_Window,
                              int      &Chart_Indicator_Number){
//-----
   int Chart_Windows_Total=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL);             //Количество окон на графике (всегда есть хотя бы одно главное окно)
   {for(int nWindow=0;nWindow<Chart_Windows_Total;nWindow++)                        //Проход по окнам 
   { 
      int Chart_Indicators_Total=ChartIndicatorsTotal(0,nWindow);                   //Сколько индикаторов в данном окне/подокне 
      {for(int nIndicator=0;nIndicator<Chart_Indicators_Total;nIndicator++)         //Переберем все индикаторы в окне 
      { 
         Chart_Indicator_Name=ChartIndicatorName(0,nWindow,nIndicator);             //Получим короткое имя индикатора
         int Indicator_Handle=ChartIndicatorGet(0,nWindow,Chart_Indicator_Name);    //Получим хэндл индикатора 
         {if(Indicator_Handle==iIndicatorHandle)                                    //Сравниваем найденное и искомое значения хендлов
         {
            IndicatorRelease(Indicator_Handle);                                     //Освобождаем хендл индикатора, как только он становится ненужным 
            {if(ChartIndicatorDelete(0,nWindow,Chart_Indicator_Name))               //Попытка удаления индикатора
            {
               Chart_Indicator_Window=nWindow;
               Chart_Indicator_Number=nIndicator;
               return(true);     
            }}//if(ChartIndicatorDelete(0,nWindow,iIndicatorName))
         }}//if(Chart_Indicator_Name==iIndicatorName)
      }}//for(int nIndicator=0;nIndicator<Chart_Indicators_Total;nIndicator++)
   }}//for(int nWindow=0;nWindow<Chart_Windows_Total;nWindow++) 
   return(false);     
}//Indicator_Delete_Handle()    
     

Индикатор:

//indicator
#property   strict
#property   indicator_separate_window//indicator_chart_window//
#property   indicator_buffers    0
#property   indicator_plots      0
#property   indicator_minimum    0
#property   indicator_maximum    100
#property   indicator_level1     50
//
//============================================================================================= MQL5 ===
//    OnInit()
//------------------------------------------------------------------------------------------------------
int OnInit(){
//-----
   ResetLastError();
   {if(!ObjectCreate(
                        ChartID(),                                                 //Идентификатор чарта - Текущий график
                        "TST_01",                                          //Имя графического объекта
                        OBJ_TEXT,                                          //Тип графического объекта
                        //0,
                        ChartWindowFind(ChartID(),MQLInfoString(MQL_PROGRAM_NAME)),//Номер подокна
                        TimeCurrent(),                                     //Координата по времени
                        //SymbolInfoDouble(Symbol(),SYMBOL_ASK)              //Координата по цене
                        50.0                                                
                     )
       )
   {
      Print("IND: Объект НЕ создан TST_01 Error=",GetLastError(),
            " MQLInfoString(MQL_PROGRAM_NAME)=",MQLInfoString(MQL_PROGRAM_NAME),
            " ChartID()=",ChartID(),
            " ChartWindowFind()=",ChartWindowFind(ChartID(),MQLInfoString(MQL_PROGRAM_NAME))
            );
      return(INIT_FAILED);
   }else{
      Print("IND: Объект создан TST_01 Error=",GetLastError(),
            " MQLInfoString(MQL_PROGRAM_NAME)=",MQLInfoString(MQL_PROGRAM_NAME),
            " ChartID()=",ChartID(),
            " ChartWindowFind()=",ChartWindowFind(ChartID(),MQLInfoString(MQL_PROGRAM_NAME))
            );
   }}//if(!ObjectCreate(...
   ObjectSetString(ChartID(),"TST_01",OBJPROP_TEXT,"TEXT");                        //Выводимый текст
   return(INIT_SUCCEEDED);
}//OnInit()
//
//============================================================================================= MQL5 ===
//    OnCalculate()
//------------------------------------------------------------------------------------------------------
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]){
//-----
   return(rates_total);
   //return(0);
}//OnCalculate()
//
//============================================================================================= MQL5 ===
//    OnDeinit()
//------------------------------------------------------------------------------------------------------
void OnDeinit(const int reason){
//----- Удалить инфо с экрана
   ObjectDelete(ChartID(),"TST_01");
//-----
   return;
}//OnDeinit()

Yury Kirillov
5298
Yury Kirillov  

При запуске советника и последующем удалении на график видим, что индикатор создаётся в окне номер 1 и имеет в этом окне порядковый номер 0.

2017.10.17 21:50:16.497 Expert_01 (EURUSD,M1)   EXP: "Indicator_01.ex5" добавлен в окно=1 хендл=10
2017.10.17 21:50:16.508 Indicator_01 (EURUSD,M1)        IND: Объект создан TST_01 Error=0 MQLInfoString(MQL_PROGRAM_NAME)=Indicator_01 ChartID()=128968168864101564 ChartWindowFind()=1
2017.10.17 21:51:56.302 Expert_01 (EURUSD,M1)   EXP: "Indicator_01.ex5" Удален! Имя:Indicator_01 Окно=1 Номер в окне=0 Хендл:10

Запуск советника:

01

Удаление советника:

02

Yury Kirillov
5298
Yury Kirillov  

При запуске советника в тестере с использованием визуализации, получаем следующий набор сообщений:

2017.10.17 21:57:07.135 EURUSD,M1: testing of Experts\Projects\Temp\ExpAndIndTest\Expert_01.ex5 from 2017.10.09 00:00 to 2017.10.17 00:00 started
2017.10.17 21:57:07.192 2017.10.09 00:00:00   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.17 21:57:07.192 2017.10.09 00:00:00   EXP: "Indicator_01.ex5" добавлен в окно=1 хендл=10
2017.10.17 21:57:07.211 2017.10.09 00:00:00   IND: Объект создан TST_01 Error=0 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=1
2017.10.17 21:57:07.529 EURUSD : real ticks begin from 2015.09.01 00:00:00
2017.10.17 21:57:08.788 final balance 1000000.00 RUR
2017.10.17 21:57:08.788 2017.10.16 23:59:58   EXP: "Indicator_01.ex5" Не удален! Имя:Projects\Temp\ExpAndIndTest\Indicator_01.ex5 Окно=0 Номер в окне=0 Хендл:10

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

03

Удаление индикатора по завершению тестирования произведено неудачно.

Yury Kirillov
5298
Yury Kirillov  

Тестирование без визуализации приводит к многочисленным попыткам инициализации индикатора:

2017.10.16 23:59:55   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:55   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:55   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:56   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:56   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:56   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:56   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:56   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:56   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:56   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:57   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:57   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:58   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:58   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:58   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:58   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:58   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
2017.10.16 23:59:58   IND: Объект НЕ создан TST_01 Error=4113 MQLInfoString(MQL_PROGRAM_NAME)=Projects\Temp\ExpAndIndTest\Indicator_01.ex5 ChartID()=12345 ChartWindowFind()=-1
final balance 1000000.00 RUR
2017.10.16 23:59:58   EXP: "Indicator_01.ex5" Не удален! Имя: Окно=0 Номер в окне=0 Хендл:10
EURUSD,M1: 484537 ticks, 1440 bars generated. Environment synchronized in 0:00:00.047. Test passed in 0:00:05.187 (including ticks preprocessing 0:00:00.063).
EURUSD,M1: total time from login to stop testing 0:00:05.234 (including 0:00:00.047 for history data synchronization)
933 Mb memory used including 38 Mb of history data, 64 Mb of tick data
log file "D:\VirtExch\MT5\AF894675\Tester\Agent-127.0.0.1-3000\logs\20171017.log" written
connection closed

Хотя вроде бы никаких зацикливаний при инициализации в программном коде не заложено.

Если же посмотреть на начало этого процесса, то видим:

EURUSD,M1: testing of Experts\Projects\Temp\ExpAndIndTest\Expert_01.ex5 from 2017.10.16 00:00 to 2017.10.17 00:00 started
2017.10.16 00:00:00   EXP: "Indicator_01.ex5" добавлен в окно=1 хендл=10

Индикатор таки был размещён в окно 1.

Yury Kirillov
5298
Yury Kirillov  

Такое разнообразие поведений несколько напрягает.

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

Slava
Модератор
13460
Slava  

Нужно иметь в виду, что пока индикатор со свойством separate window не проинициализирован, новое подокно создано не будет. Зачем создавать новое подокно, если индикатор возвращает INIT_FAILED из OnInit?

Поэтому попытки создавать объекты в подокне этого самого индикатора как правило неудачны

Yury Kirillov
5298
Yury Kirillov  
Slava:

Нужно иметь в виду, что пока индикатор со свойством separate window не проинициализирован, новое подокно создано не будет. Зачем создавать новое подокно, если индикатор возвращает INIT_FAILED из OnInit?

Поэтому попытки создавать объекты в подокне этого самого индикатора как правило неудачны


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

Если ответ "не может", то есть несколько уточняющих вопросов:

1. Фраза "индикатор со свойством separate window не проинициализирован" означает выполнение OnInit() индикатора, я правильно понимаю? Или необходимо ещё получить хендл и/или добавить индикатор в новое окно?

2. Новое подокно создается:

a. После получения хендла индикатора, например с помощью iCustom() ?

b. После добавления индикатора в новое окно, например при помощи ChartGetInteger()?

c. После создания первого графического объекта, например при помощи ObjectCreate() ?

Какое утверждение правильное?

3. Почему конструкция:

//----- Размещаем индикатор в новое окно
   //Чтобы добавить индикатор в новое окно, параметр должен быть на единицу больше, чем индекс последнего существующего окна, то есть равен CHART_WINDOWS_TOTAL.
   int nNewWindow=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL);
   {if(!ChartIndicatorAdd(0,nNewWindow,indicator_handle))
   {
      Print("EXP: \"Indicator_01.ex5\" не добавлен.");
      return(INIT_FAILED);
   }else{
      Print("EXP: \"Indicator_01.ex5\" добавлен в окно=",nNewWindow," хендл=",indicator_handle);
   }}//if(!ChartIndicatorAdd(0,(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL),indicator_handle))

Сообщает о добавлении индикатора в соответствующее окно графика в режиме тестирования без визуализации? Свидетельствует ли это о том, что окно создано и индикатор в него добавлен?

4. Зачем тестер пытается многократно и без непосредственного указания в коде выполнять секцию OnInit() индикатора? Как это можно регулировать/запретить программно?
Тестирование стратегий - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
Тестирование стратегий - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
  • www.metatrader5.com
Тестер стратегий позволяет тестировать и оптимизировать торговые стратегии (советники) перед началом использования их в реальной торговле. При тестировании советника происходит его однократная прогонка с начальными параметрами на исторических данных. При оптимизации торговая стратегия прогоняется несколько раз с различным набором параметров...
Slava
Модератор
13460
Slava  

1. "Индикатор проинициализирован" - это значит, что функция OnInit выполнена. При этом, если тип возврата OnInit интовый, то OnInit должна возвратить INIT_SUCCEEDED

2. В режиме визуализации новое подокно индикатора создаётся сразу после обработки экспертного OnInit или OnTick, в котором было вызвано создание индикатора (что равнозначно получению его хэндла). То есть, перед вызовом следующего OnTick. В простом тестировании/инициализации подокно индикатора не создаётся, а используется только его расчётная часть

3. В простом тестировании ChartIndicatorAdd это просто пустышка. Да и при визуализации не надо вызывать ChartIndicatorAdd, так как индикатор добавляется на график визуализации автоматически

4. Потому что Вы обращаетесь к этому индикатору снова и снова. А так как он ещё не инициализирован (никто ведь не знает, почему он не инициализирован), то производится попытка инициализации

Yury Kirillov
5298
Yury Kirillov  
Slava:

1. "Индикатор проинициализирован" - это значит, что функция OnInit выполнена. При этом, если тип возврата OnInit интовый, то OnInit должна возвратить INIT_SUCCEEDED

2. В режиме визуализации новое подокно индикатора создаётся сразу после обработки экспертного OnInit или OnTick, в котором было вызвано создание индикатора (что равнозначно получению его хэндла). То есть, перед вызовом следующего OnTick. В простом тестировании/инициализации подокно индикатора не создаётся, а используется только его расчётная часть

3. В простом тестировании ChartIndicatorAdd это просто пустышка. Да и при визуализации не надо вызывать ChartIndicatorAdd, так как индикатор добавляется на график визуализации автоматически

4. Потому что Вы обращаетесь к этому индикатору снова и снова. А так как он ещё не инициализирован (никто ведь не знает, почему он не инициализирован), то производится попытка инициализации

Экспериментируя с индикаторами иногда получаю интересный результат после удаления с графика всех советников и индикаторов,  и удаления (закрытия) собственно всех графиков:

индикаторы которые ранее были размещены на чарте продолжают работать, взаимодействовать друг с другом и даже выводить информацию через Print().

Причем этот процесс продолжается уже вот минут 20.

Повторяемость эффекта достаточно высокая.

//----------------------

Складывается ощущение, что индикаторы живут в параллельной вселенной... :-)

04
Файлы:
Temp.zip 8 kb
123
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий