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

 
Yury Kirillov:

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

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

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

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

Исторический кеш убиваемого графика удаляется не сразу после удаления графика, а после некого таймаута. Соответственно, индикаторы, работающие на данном символе-периоде, - тоже.

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

Удаленные графики - Дополнительные возможности - Графики котировок, технический и фундаментальный анализ - Справка по MetaTrader 5
Удаленные графики - Дополнительные возможности - Графики котировок, технический и фундаментальный анализ - Справка по MetaTrader 5
  • www.metatrader5.com
В процессе работы некоторые графики становятся ненужными, и возникает необходимость их удалить. Нажмите "Закрыть" в меню "Файл" или клавиши "Ctrl+F4". Шаблоны удаленных графиков сохраняются, в дальнейшем их можно использовать. Например, если график был удален случайно, его можно восстановить. Нажмите...
 
Slava:

Исторический кеш убиваемого графика удаляется не сразу после удаления графика, а после некого таймаута. Соответственно, индикаторы, работающие на данном символе-периоде, - тоже.

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


У меня запускается советник, который запускает два индикатора, которые обращаются друг к другу за данными.

1. Как корректно прервать работу такой системы программным образом?

2. В настоящий момент я удаляю с графика советник, который удаляет с графика индикаторы. Что я ещё должен сделать для прекращения работы индикаторов?

3. При удалении индикатора с графика через ChartIndicatorDelete() выполняется ли секция OnDeinit() индикатора?

//-----

Первое, что приходит на ум: завести глобальную переменную с флагом разрешения запросов к данным советника и прекращать запрос к данным при сбросе этого флага, но уж больно костыльно как-то.

 
Yury Kirillov:

У меня запускается советник, который запускает два индикатора, которые обращаются друг к другу за данными. Как корректно прервать работу такой системы программным образом?

В советнике и индикаторах грохнуть соответствующие хэндлы в OnDeinit.

Документация по MQL5: Доступ к таймсериям и индикаторам / IndicatorRelease
Документация по MQL5: Доступ к таймсериям и индикаторам / IndicatorRelease
  • www.mql5.com
//|                                        Test_IndicatorRelease.mq5 | //|                        Copyright 2010, MetaQuotes Software Corp. | //|                                             https://www.mql5.com | //| Expert initialization function                                   |...
 

OnDeinit индикатора вызывается только если убита последняя копия этого индикатора (счётчик использования равен 0)

В Вашем случае:

Создание индикатора с получением хэндла - счётчик равен 1

Добавление индикатора на график ChartIndicatorAdd - счётчик равен 2

Удаление индикатора с графика ChartIndicatorDelete - счётчик равен 1

Счётчик индикатора обнулится либо после OnDeinit программы, её создавшей, либо после явного вызова IndicatorRelease

 
fxsaber:

В советнике и индикаторах грохнуть соответствующие хэндлы в OnDeinit.


Выше выложены коды советника и индикаторов.

Для индикатора секция DeInit()

//============================================================================================= MQL5 ===   if()
//    OnDeinit()
//------------------------------------------------------------------------------------------------------
void OnDeinit(const int reason){
//Удаление из окон
   string   iName;
   int      iWindow;
   int      iNumber;
   {if( false                                                                    //Тут надо проверить какой режим с каким совместим
      || ((!MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION)))    //Не тестирование и не оптимизация
      || ((MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_VISUAL_MODE)))      //или тестирование, но не визуальный режим
      )
   {   
      //----- Удалить индикатор с экрана
      iName="";
      iWindow=0;
      iNumber=0;
      {if(!Indicator_Delete_Handle(indicator_handle_01,iName,iWindow,iNumber))
      {
         Print("EXP: \"Indicator_04_01.ex5\" Не удален! Имя:",iName," Окно=",iWindow," Номер в окне=",iNumber," Хендл:",indicator_handle_01);
      }else{
         Print("EXP: \"Indicator_04_01.ex5\" Удален! Имя:",iName," Окно=",iWindow," Номер в окне=",iNumber," Хендл:",indicator_handle_01);
      }}//f(!Indicator_Delete_Handle(indicator_handle,iName))
      //----- Удалить индикатор с экрана
      iName="";
      iWindow=0;
      iNumber=0;
      {if(!Indicator_Delete_Handle(indicator_handle_02,iName,iWindow,iNumber))
      {
         Print("EXP: \"Indicator_04_02.ex5\" Не удален! Имя:",iName," Окно=",iWindow," Номер в окне=",iNumber," Хендл:",indicator_handle_02);
      }else{
         Print("EXP: \"Indicator_04_02.ex5\" Удален! Имя:",iName," Окно=",iWindow," Номер в окне=",iNumber," Хендл:",indicator_handle_02);
      }}//f(!Indicator_Delete_Handle(indicator_handle,iName))
   }else{
      Print("EXP: Удалить индикаторы при помощи Indicator_Delete_Handle() невозможно!");
   }}//if(...
//Удаление хендлов по IndicatorRelease()
   {if( false                                                                    //Тут надо проверить какой режим с каким совместим
      || ((!MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION)))    //Не тестирование и не оптимизация
      || ((MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_VISUAL_MODE)))      //или тестирование, но не визуальный режим
      )
   {   
      //----- Удалить индикатор с экрана
      {if(!IndicatorRelease(indicator_handle_01))
      {
         Print("EXP: \"Indicator_04_01.ex5\" Не удален!  Хендл:",indicator_handle_01);
      }else{
         Print("EXP: \"Indicator_04_01.ex5\" Удален!  Хендл:",indicator_handle_01);
      }}//if(!IndicatorRelease(indicator_handle_01))
      //----- Удалить индикатор с экрана
      {if(!IndicatorRelease(indicator_handle_02))
      {
         Print("EXP: \"Indicator_04_02.ex5\" Не удален!  Хендл:",indicator_handle_02);
      }else{
         Print("EXP: \"Indicator_04_02.ex5\" Удален!  Хендл:",indicator_handle_02);
      }}//if(!IndicatorRelease(indicator_handle_02))
   }else{
      Print("EXP: Удалить индикаторы при помощи IndicatorRelease() невозможно!");
   }}//if(...
//-----
   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(ChartID(),CHART_WINDOWS_TOTAL); //Количество окон на графике (всегда есть хотя бы одно главное окно) {for(int nWindow=0;nWindow<Chart_Windows_Total;nWindow++) //Проход по окнам { int Chart_Indicators_Total=ChartIndicatorsTotal(ChartID(),nWindow); //Сколько индикаторов в данном окне/подокне {for(int nIndicator=0;nIndicator<Chart_Indicators_Total;nIndicator++) //Переберем все индикаторы в окне { Chart_Indicator_Name=ChartIndicatorName(ChartID(),nWindow,nIndicator); //Получим короткое имя индикатора int Indicator_Handle=ChartIndicatorGet(ChartID(),nWindow,Chart_Indicator_Name); //Получим хэндл индикатора {if(Indicator_Handle==iIndicatorHandle) //Сравниваем найденное и искомое значения хендлов { IndicatorRelease(Indicator_Handle); //Освобождаем хендл индикатора, как только он становится ненужным {if(ChartIndicatorDelete(ChartID(),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()

Это считается за грохнуть?

 
Slava:
OnDeinit индикатора вызывается только если убита последняя копия этого индикатора (счётчик использования равен 0)

1. Что такое "счетчик использования" и как его контролировать?

2. Как "убить последнюю копию" индикатора? Особенно, если его уже нет на чарте и самого чарта тоже уже нет?

 
Yury Kirillov:

Выше выложены коды советника и индикаторов.

Это считается за грохнуть?

Без обид, но выложенный Вами код - это почти проявление неуважения к другим. Код по проблеме должен быть лаконичным, все лишнее, что не касается проблемы (проверки, логирование и т.д.) должны быть убраны. Только тогда возможно нормально обсуждать. Сейчас же 90% времени любой чтец должен разбираться не в поднятой проблеме, а в огромном коде. Поставьте себя на место другого.

 
Yury Kirillov:

1. Что такое "счетчик использования" и как его контролировать?

2. Как "убить последнюю копию" индикатора? Особенно, если его уже нет на чарте и самого чарта тоже уже нет?

Я дополнил свой пост

В Вашем случае:

Создание индикатора с получением хэндла - счётчик равен 1

Добавление индикатора на график ChartIndicatorAdd - счётчик равен 2

Удаление индикатора с графика ChartIndicatorDelete - счётчик равен 1

Счётчик индикатора обнулится либо после OnDeinit программы, её создавшей, либо после явного вызова IndicatorRelease
 
Slava:

OnDeinit индикатора вызывается только если убита последняя копия этого индикатора (счётчик использования равен 0)

В Вашем случае:

Создание индикатора с получением хэндла - счётчик равен 1

Добавление индикатора на график ChartIndicatorAdd - счётчик равен 2

Удаление индикатора с графика ChartIndicatorDelete - счётчик равен 1

Счётчик индикатора обнулится либо после OnDeinit программы, её создавшей, либо после явного вызова IndicatorRelease


1. Я правильно понимаю, что после "Добавление индикатора на график ChartIndicatorAdd - счётчик равен 2" я имею две запущенных копии одного и того же индикатора и они обе активны?

2. Вопрос по поводу "Счётчик индикатора обнулится либо после OnDeinit программы, её создавшей, либо после явного вызова IndicatorRelease":

При удалении индикатора с графика при помощи ChartIndicatorDelete() последующий вызов IndicatorRelease() приводит к ошибке, как в этом случае понизить счетчик?

При вызове IndicatorRelease() последующий вызов ChartIndicatorDelete() тоже в свою очередь приводит к ошибке.

3. OnDeinit советника создавшего индикатор у меня вызывается, но индикаторы работают - стало быть счетчик не обнуляется?

 

1. Нет. В данном случае копия одна, но со счётчиком равным 2

2,3. У Вас какие то сложные случаи. Зачем добавлять индикатор на график? Если добавили, то надо делать ChartIndicatorDelete до вызова IndicatorRelease/

Зачем вызывать IndicatorRelease? Индикатор зарелизится автоматически. Вы что-то перемудрили.

После всех освобождений индикаторы работают больше 20 минут? Проверьте все другие обращения к этому же символу-периоду.

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