MetaTrader 5 Build 245: Обработка событий кастомными индикаторами

 

Смотрим в тему https://www.mql5.com/ru/forum/23/page4 ("Список изменений в билдах MT5 Client Terminal") и видим:

MetaTrader 5 Client Terminal build 245
...

8. MQL5: Добавлена возможность обработки событий кастомными индикаторами, аналогично экспертам. Более подробное описание будет доступно в справке MQL5 в ближайшее время.

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

Собственно, меня интересует только один вопрос: какие новые группы событий теперь можно обрабатывать? Обработчики OnChartEvent(), OnTimer() работают?

Список изменений в билдах MetaTrader 5 Client Terminal
Список изменений в билдах MetaTrader 5 Client Terminal
  • www.mql5.com
Автоматическое обновление доступно через систему LiveUpdate:.
 

Нельзя сказать, что совсем ничего не отражено. Смотрим документацию прямо здесь на сайте:

OnTimer

OnTimer

Функция OnTimer() вызывается при наступлении события Timer, которое генерируется системным таймером только для экспертов и индикаторов – использовать ее в скриптах нельзя. Периодичность наступления этого события устанавливается при подписке на получение функцией EventSetTimer() уведомлений о событии Timer.

Отписывание от приема посылки событий таймера для конкретного эксперта производится функцией EventKillTimer(). Функция должна быть определена с типом void, параметров не имеет:

void OnTimer();

Рекомендуется вызывать функцию EventSetTimer() однократно в функции OnInit(), а функцию EventKillTimer() вызывать однократно в OnDeinit().

Каждый эксперт и каждый индикатор работает со своим таймером, и получает события только от него. При завершении работы mql5-программы таймер уничтожается принудительно, если он был создан, но не был отключен функцией EventKillTimer().

OnChartEvent

OnChartEvent

OnChartEvent() является обработчиком группы событий ChartEvent:

  • CHARTEVENT_KEYDOWN — событие нажатия клавиатуры, когда окно графика находится в фокусе;
  • CHARTEVENT_OBJECT_CREATE – событие создания графического объекта;
  • CHARTEVENT_OBJECT_DELETE – событие удаления графического объекта;
  • CHARTEVENT_OBJECT_CLICK — событие щелчка мыши на графическом объекте, принадлежащего графику;
  • CHARTEVENT_OBJECT_DRAG — событие перемещения графического объекта при помощи мыши;
  • CHARTEVENT_OBJECT_ENDEDIT — событие окончания редактирования текста в поле ввода графического объекта LabelEdit;
  • CHARTEVENT_CUSTOM+n — идентификатор пользовательского события, где n находится в диапазоне от 0 до 65535.
  • CHARTEVENT_CUSTOM_LAST — последний допустимый идентификатор пользовательского события (CHARTEVENT_CUSTOM+65535).

Функция может вызываться в экспертах и индикаторах, должна иметь тип void и 4 параметра:

void OnChartEvent(const int id,         // идентификатор события  
                  const long& lparam,   // параметр события типа long
                  const double& dparam, // параметр события типа double
                  const string& sparam  // параметр события типа string
  );

Автоматическое обновление справки производится не чаще чем раз в две недели.
 

Спасибо, Rosh.

В справку я смотрел, как раз в это же место, но в самом терминале. Там этих обновлений еще нет (249 билд поставил только сегодня и надеялся, что справка будет актуальной). А сюда на сайт за справкой заглянуть не удосужился. ОК, будем привыкать к необходимости более тщательного поиска инфы.

P.S. Rosh, Вы не могли бы пояснить, почему Metaquotes так долго решалась на этот шаг? Мы действительно жертвуем чем-то важным - с точки зрения внутренней архитектуры терминала?

Я помню, что Renat на mql4.com говорил (где-то в сентябре-октябре 2009), что "мы, возможно, попробуем". В тот момент дискуссия касалась в-основном работы с объектами в индикаторе и была довольно горячей. Пользователи были недовольны концепцией "чисто расчетно-вычислительной сущности", в которую был превращен индикатор.

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

 

Обработку событий не включали в индикаторы по причине возможного торможения работы терминала.

В связи с этим возникают следующие рассуждения и вопрос.

С приходом нового тика происходит пересчет индикатора в ОнКалькуляте. И, соответственно, включаются тормоза.

Мы обрабатываем событие в индикаторе. Событие обрабатывается своим куском кода, в своем цикле. Не в куске кода, где задействуется ОнКалькуляте.

Вопрос следующий. Когда включаются тормоза, в какой момент?

1) По приходу нового тика и начале работы индикатора. То есть уже к функции Инит?

2) Только когда управление передается в функцию ОнКалькуляте?

Допустим, индикатор не имеет в функции ОнКалькуляте никакой обработки. Имеется только обработчик событий.

В этом случае также будет происходить включение тормозов? 

 
nen:

Допустим, индикатор не имеет в функции ОнКалькуляте никакой обработки. Имеется только обработчик событий.

В этом случае также будет происходить включение тормозов? 

Т.е. тело обработчика OnCalculate() пустое? ОК, смотрим справку:

Функция OnCalculate() вызывается только в пользовательских индикаторах при необходимости произвести расчет значений индикатора по событию Calculate. Обычно это происходит при поступлении нового тика по символу, для которого рассчитывается индикатор.

Т.е. при приходе нового тика (вероятно, еще и при обновлении истории) обработчик все равно вызывается. Но тормозов не будет, он же пустой.

 

nen:

В связи с этим возникают следующие рассуждения и вопрос.

Допустим, индикатор не имеет в функции ОнКалькуляте никакой обработки. Имеется только обработчик событий.

В этом случае также будет происходить включение тормозов? 

К любой функции кастомного индикатора применяются те же принципы экономии времени как и к OnCalculate.

Дело в том, что вся обработка всех функций всех кастомных индикаторов по одному символу идет в одном расчетном потоке (для каждого символа) последовательно. То есть, затратный обработчик OnChartEvent тормозит все процессы пересчета индикаторов на том же символе.

То, что у индикатора пустая функция OnCalculate никак не означает, что индикатор имеет другие правила обработки, другую очередь или отдельный поток исполнения.


Мы действительно жертвуем чем-то важным - с точки зрения внутренней архитектуры терминала?

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


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

То есть, все индикаторы на EURUSD обрабатываются в своем независимом потоке, все индикаторы на XXXX - в своем.

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
Основы языка / Функции / Функции обработки событий - Документация по MQL5
 
Renat:

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

Это понятно, Renat. Но и раньше, в "четверке", ответственность за эффективность реализации лежала почти целиком на разработчике кода, и никто с этим особо не спорил. Но все равно как-то выкручивались и продолжают выкручиваться.

Надеюсь, что это решение окончательное и отмене не подлежит. 

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

 

Необходимо в справке отдельно БОЛЬШИМИ БУКВАМИ написать, что ответственность за медленную работу индикаторов и других программ, созданных с помощью MQL5, ПОЛНОСТЬЮ лежит на разработчике программы. БОЛЬШИМИ БУКВАМИ, значит, подробно и на видном месте. И желательно, чтобы было подробное описание того, что здесь нам сообщает Ренат. Чтобы была понятна "физика" процесса. В каких местах может возникнуть замедление работы программы и почему. Нам дали хороший инструмент. Предупредили, где могут быть допущены нами ошибки, из-за которых этот хороший инструмент может работать с неустраивающей пользователя скоростью. Выжимаем все возвожное из инструмента. Все, что нам положено знать, знаем. Все прозрачно, ясно.

 Что еще желать? 

 
nen:

Необходимо в справке отдельно БОЛЬШИМИ БУКВАМИ написать, что ответственность за медленную работу индикаторов и других программ, созданных с помощью MQL5, ПОЛНОСТЬЮ лежит на разработчике программы. БОЛЬШИМИ БУКВАМИ, значит, подробно и на видном месте. И желательно, чтобы было подробное описание того, что здесь нам сообщает Ренат. Чтобы была понятна "физика" процесса. В каких местах может возникнуть замедление работы программы и почему. Нам дали хороший инструмент. Предупредили, где могут быть допущены нами ошибки, из-за которых этот хороший инструмент может работать с неустраивающей пользователя скоростью. Выжимаем все возвожное из инструмента. Все, что нам положено знать, знаем. Все прозрачно, ясно.

 Что еще желать? 

 

Полностью согласен, знание "тонких" мест очень помогает в работе.

 

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

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
Основы языка / Функции / Функции обработки событий - Документация по MQL5
 
nen:

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

 

А для этого достаточно добавить вариант OnCalculate(void), без параметров и передачи массивов.

 

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