Если советником создается индикатор (например через iCustom()) в режиме тестирования с визуализацией или в режиме реальной работы,
то индикатор живёт в подокне некоторого окна и имеет свой номер среди прочих индикаторов этого подокна (ну или главного окна данного инструмента).
А если индикатор без подокна? Он ведь тогда не отображается на графике (кроме тех случаев, когда он создает графические объекты).
Вопрос 1: где живёт индикатор созданный советником в режиме тестирования без визуализации? В каком окне (подокне) и с каким номером?
Вопрос 2: где живёт индикатор созданный советником в режиме оптимизации?
Для проверки прописки индикатора, были написаны примитивный советник и индикатор.
Советник:
//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()
При запуске советника и последующем удалении на график видим, что индикатор создаётся в окне номер 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
Запуск советника:
Удаление советника:
При запуске советника в тестере с использованием визуализации, получаем следующий набор сообщений:
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. Что собственно видно и визуально:
Удаление индикатора по завершению тестирования произведено неудачно.
Тестирование без визуализации приводит к многочисленным попыткам инициализации индикатора:
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.
Такое разнообразие поведений несколько напрягает.
Возникают сомнения, в достоверности тестирования, так как поведение даже достаточно простых програмных систем в тестере очень уж отличается от поведения в реальных условиях.
Нужно иметь в виду, что пока индикатор со свойством separate window не проинициализирован, новое подокно создано не будет. Зачем создавать новое подокно, если индикатор возвращает INIT_FAILED из OnInit?
Поэтому попытки создавать объекты в подокне этого самого индикатора как правило неудачны
Нужно иметь в виду, что пока индикатор со свойством 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() индикатора? Как это можно регулировать/запретить программно?- www.metatrader5.com
1. "Индикатор проинициализирован" - это значит, что функция OnInit выполнена. При этом, если тип возврата OnInit интовый, то OnInit должна возвратить INIT_SUCCEEDED
2. В режиме визуализации новое подокно индикатора создаётся сразу после обработки экспертного OnInit или OnTick, в котором было вызвано создание индикатора (что равнозначно получению его хэндла). То есть, перед вызовом следующего OnTick. В простом тестировании/инициализации подокно индикатора не создаётся, а используется только его расчётная часть
3. В простом тестировании ChartIndicatorAdd это просто пустышка. Да и при визуализации не надо вызывать ChartIndicatorAdd, так как индикатор добавляется на график визуализации автоматически
4. Потому что Вы обращаетесь к этому индикатору снова и снова. А так как он ещё не инициализирован (никто ведь не знает, почему он не инициализирован), то производится попытка инициализации
1. "Индикатор проинициализирован" - это значит, что функция OnInit выполнена. При этом, если тип возврата OnInit интовый, то OnInit должна возвратить INIT_SUCCEEDED
2. В режиме визуализации новое подокно индикатора создаётся сразу после обработки экспертного OnInit или OnTick, в котором было вызвано создание индикатора (что равнозначно получению его хэндла). То есть, перед вызовом следующего OnTick. В простом тестировании/инициализации подокно индикатора не создаётся, а используется только его расчётная часть
3. В простом тестировании ChartIndicatorAdd это просто пустышка. Да и при визуализации не надо вызывать ChartIndicatorAdd, так как индикатор добавляется на график визуализации автоматически
4. Потому что Вы обращаетесь к этому индикатору снова и снова. А так как он ещё не инициализирован (никто ведь не знает, почему он не инициализирован), то производится попытка инициализации
Экспериментируя с индикаторами иногда получаю интересный результат после удаления с графика всех советников и индикаторов, и удаления (закрытия) собственно всех графиков:
индикаторы которые ранее были размещены на чарте продолжают работать, взаимодействовать друг с другом и даже выводить информацию через Print().
Причем этот процесс продолжается уже вот минут 20.
Повторяемость эффекта достаточно высокая.
//----------------------
Складывается ощущение, что индикаторы живут в параллельной вселенной... :-)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Если советником создается индикатор (например через iCustom()) в режиме тестирования с визуализацией или в режиме реальной работы,
то индикатор живёт в подокне некоторого окна и имеет свой номер среди прочих индикаторов этого подокна (ну или главного окна данного инструмента).
Вопрос 1: где живёт индикатор созданный советником в режиме тестирования без визуализации? В каком окне (подокне) и с каким номером?
Вопрос 2: где живёт индикатор созданный советником в режиме оптимизации?