Обсуждение статьи "Событийная архитектура в MQL5: как превратить советник в полноценную торговую систему"

 

Опубликована статья Событийная архитектура в MQL5: как превратить советник в полноценную торговую систему:

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

При разработке советника в MQL5 многие начинают с самого очевидного решения: складывают всю логику в метод OnTick. Так действительно проще стартовать. Но у такого подхода есть скрытая цена. По мере роста проекта в одном обработчике смешиваются торговые правила, проверка условий, работа с ордерами, обновление данных, интерфейс, расчёты и логирование. В итоге код разрастается до состояния, когда он уже не программируется, а удерживается на честном слове. Любое изменение в одном месте начинает затрагивать совсем другие части системы. Исправляешь визуальную панель — внезапно ломается торговый сценарий. Меняешь фильтр входа — всплывает ошибка в фоновой проверке. Такой советник быстро превращается в хрупкий монолит, где сложность растёт быстрее, чем уверенность разработчика.

Платформа MetaTrader 5 устроена гораздо интереснее, чем просто поток котировок. Она живёт событиями. В терминале постоянно возникают тики, сигналы таймера, действия пользователя, изменения торгового состояния и события стакана. Эти сообщения следует обрабатывать раздельно. Для этого в MQL5 предусмотрены разные обработчики, каждый со своей зоной ответственности. OnTick отвечает за рыночные обновления. OnTimer — за периодические и фоновые задачи. OnChartEvent — за реакцию на графический интерфейс и пользовательские действия. Когда логика распределена по назначению, код перестаёт быть перегруженным. Он становится ближе к нормальной инженерной системе, где каждый модуль делает своё дело и не мешает соседям.

События в MQL5

В этой статье мы разберём, как перейти от модели всё в OnTick к более зрелой событийной архитектуре. Разберём роли предопределённых обработчиков и пользовательских событий, а также сервисы без привязки к графику. Отдельно рассмотрим типовые ошибки, которые ломают архитектуру ещё до реальной работы. Главная мысль здесь проста: когда MQL5 используется по назначению, он позволяет строить не только торговых роботов, но и полноценные прикладные системы.

Автор: MetaQuotes

 
Работать в советнике с индикаторами без буферов - наверное, для примера пойдет.
 
//+------------------------------------------------------------------+
//| Trade function                                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
   Sleep(0);
//---
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
   Sleep(0);
//---
  }
Для чего?
 
            if(!cTrade.PositionClose(cPosition.Ticket()))
              {
               PrintFormat("Error close Sell position: %d", GetLastError());
               return;
              }
Вроде, cTrade содержит вывод на случай ошибки.
 
fxsaber #:
Работать в советнике с индикаторами без буферов - наверное, для примера пойдет.


В примере делается строгое обновление данных символа (хорошо бы использовать MQL_TESTER).

void OnTick()
  {
//---
   if(BuySignal)
     {
      cSymbol.Refresh();
      cSymbol.RefreshRates();


Но не делается проверка на актуальность вычисленного через события сигнала и тика. И это реальная проблема.


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