Типы программ и особенности их построения

В комплект поставки платформы MetaTrader 5 входит современная среда разработки MetaEditor, которая позволяет создавать различные программы для алгоритмического трейдинга. Для написания программ используется специально разработанный язык программирования MetaQuotes Language 5 (MQL5). Синтаксис языка максимально приближен к С++ с возможностью написания программ в стиле объектно-ориентированного программирования. Это облегчает переход на использование MQL5 большой армии программистов.

Взаимодействие платформы MetaTrader 5 с программами организовано таким образом, что ценовые движения инструментов и изменения торгового счета отслеживается платформой. При наступлении предопределенных изменений платформа генерирует события на открытом в платформе графике инструмента. При наступлении события проверяются пользовательские программы, прикрепленные к графику. Это могут быть электронные советники, индикаторы и скрипты. Для каждого события и типа программ в платформе определены обработчики событий.

Обработчик событий — это специальная функция, определенная языком программирования MQL5. Такая функция имеет строго прописанные наименование, тип возвращаемого значения, список и тип параметров. По типу возвращаемого значения и по типам параметров обработчик событий клиентского терминала идентифицирует функции для обработки наступившего события. Если у функции указаны иные, не соответствующие предопределенным, параметры или указан иной тип возвращаемого значения, то такая функция не будет использоваться для обработки события.

Встроенная среда разработки MetaEditor

Встроенная среда разработки MetaEditor

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

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

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

Электронные советники (эксперты)

Наверное, во главе алгоритмической торговли стоят электронные советники (торговые роботы) — программы, способные самостоятельно анализировать рынок и совершать торговые операции на основе запрограммированной стратегии и ее правил совершения торговых операций.

Технически в MetaTrader 5 советник привязан к определенному графику, на котором запущен. При этом он обрабатывает предопределенные события только своего графика. Наступление каждого из событий запускает соответствующий функционал торговой стратегии. Такими событиями могут быть запуск и деинициализация программы, срабатывание таймера, приход нового тика, события графика и пользовательские события.

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

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

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

Сразу после запуска советника терминал генерирует событие Init, которое запускает функцию OnInit. В теле данной функции происходит инициализация глобальных переменных и объектов. При необходимости запускается таймер. Функция не имеет входных параметров, но по результатам отработки возвращает целочисленное значение кода возврата. Отличный от нуля код возврата сигнализирует о неудачной инициализации — в этом случае терминал генерирует событие завершения программы Deinit.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
 
//--- create timer
   EventSetTimer(60);
//---
   return(INIT_SUCCEEDED);
  }

При завершении программы терминал MetaTrader 5 генерирует событие Deinit, которое запускает выполнение функции OnDeinit. Функция имеет один входной целочисленный параметр, в который передается код причины завершения работы программы. В теле функции при необходимости осуществляется удаление глобальных переменных, классов и графических объектов, сохранение данных в файловые ресурсы, закрытие таймера, запущенного при инициализации программы, и прочие операции, необходимые для нормального завершения работы программы и очистки следов ее работы в терминале.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
 
//--- destroy timer
   EventKillTimer();
  }

При поступлении нового тика по инструменту, на графике которого запущен советник, генерируется событие NewTick. При этом происходит запуск функции OnTick. Это событие генерируется только для экспертов, поэтому в других программах функция OnTick не будет запускаться. Конечно, указанную функцию всегда можно вызвать принудительно из любого места программы, но это уже не будет отработка события NewTick.

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

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }

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

Для этого при инициализации программы в функции OnInit необходимо инициализировать таймер с помощью функции EventSetTimer. В параметрах функции указывается период задержки таймера в секундах. После этого терминал будет генерировать событие Timer для графика, и при этом будет запускаться на выполнение функция OnTimer советника.

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   
  }

При использовании в коде программы таймера нужно обязательно его выгрузить из памяти терминала при завершении работы программы в функции OnDeinit. Для этого используется функция EventKillTimer. Данная функция не имеет параметров. Надо сказать, что платформой предусмотрено использование только одного таймера на графике.

В пределах одного советника при необходимости можно использовать и функцию OnTick, и функцию OnTimer.

Среди советников отдельно можно выделить подкласс полуавтоматических советников и торговых панелей. Такие программы не способны вести самостоятельную торговлю без участия человека. Напротив, программы данного вида осуществляют торговые операции по команде трейдера. Сами же программы призваны облегчить работу трейдера, взять на себя некие рутинные операции. Это может быть управление капиталом, установка уровней стоп-лосса и тейк-профита, сопровождение позиции и многое другое.

Для организации взаимодействия программы с пользователем в советниках обрабатываются события группы ChartEvent. События данной группы запускают выполнение функции OnChartEvent, которая принимает от терминала четыре параметра:

  • id — идентификатор события,
  • lparam — параметр события типа long,
  • dparam — параметр события типа double,
  • sparam — параметр события типа string.

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   
  }

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

Технические индикаторы

Другой тип возможных программ — пользовательские индикаторы. Это программы, которые выполняют аналитические функции для помощи трейдеру в проведении технического анализа рыночной ситуации. В процессе своей работы индикаторы обрабатывают каждое ценовое движение на графике своего торгового инструмента. Они могут выводить различные графические объекты, тем самым генерируя сигналы для последующего анализа трейдером.

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

Наравне с советниками, технические индикаторы имеют обработчики событий Init, Timer и ChartEvent. Построение функций для обработки указанных событий аналогично соответствующим функциям электронных советников, но вместо события NewTick для индикаторов генерируется событие Calculate. Данное событие обрабатывается функцией OnCalculate. В зависимости от области применения индикатора существует два вида функции OnCalculate:

  • краткая

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total
                 const int prev_calculated,
                 const int begin,
                 const doubleprice[] 
  {
//---
   
//--- return value of prev_calculated for the next call
   return(rates_total);
  }

  • полная

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 value of prev_calculated for the next call
   return(rates_total);
  }

В пределах одного индикатора можно использовать только один из вариантов функции.

Оба варианта функции OnCalculate имеют параметры:

  • rates_total — число элементов в таймсериях,
  • prev_calculated — число пересчитанных элементов таймсерии при предыдущем запуске функции.

Использование параметра prev_calculated позволяет реализовать алгоритмы, при которых индикатор не пересчитывает ранее посчитанные исторические значения. Тем самым снижается количество итераций при обработке каждого нового ценового колебания.

Работа индикаторов в терминале MetaTrader 5 организована следующим образом. В параметр prev_calculated передается значение, которое функция вернула при предыдущем запуске. Поэтому в общем случае в конце удачного завершения функции достаточно вернуть значение параметра rates_total. При возникновении ошибок в процессе работы функции, можно вернуть текущее значение prev_calculated. В таком варианте при следующем запуске функция начнет пересчет с текущего места. Если вернуть 0, при следующем запуске индикатор будет пересчитан на всей истории, как при первом запуске.

При кратком определении функция имеет только один входной массив таймсерии (price) и параметр сдвига значимых значений относительно начала таймсерии (begin). В таком варианте расчет значений индикатора строится на основе данных одной таймсерии. Какая именно таймсерия будет использоваться, задается трейдером при запуске технического индикатора. Это может быть как любая из ценовых таймсерий, так и значения буфера другого индикатора.

При использовании полного варианта функции OnCalculate, в параметрах функция получает все ценовые таймсерии. В таком случае у пользователя нет возможности выбора таймсерии при запуске индикатора. Если необходимо использовать буфер данных другого индикатора, это нужно явно прописывать в программном коде индикатора.

В MetaTrader 5 существует ограничение в возможности запуска только одного электронного советника для каждого графика. Если нужно запустить два и более советников в одном терминале, следует открыть отдельный график для каждого советника. Для индикаторов же нет такого ограничения — MetaTrader 5 позволяет параллельно на одном графике торгового инструмента использовать встроенные и пользовательские индикаторы в различных вариациях. При этом индикатор может выводить данные как на сам ценовой график инструмента, так и в подокнах.

Скрипты

Советники и пользовательские индикаторы после их запуска остаются в памяти терминала до моментах принудительного их закрытия трейдером. В процессе наступления тех или иных событий терминал запускает определенный функционал советников и индикаторов. Для выполнения каких-либо разовых операций предусмотрены скрипты. Это отдельный тип программ, которые не обрабатывают никаких событий, кроме события своего запуска.

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

В теле скрипта существует только один обработчик событий OnStart, который запускается сразу после запуска программы. Функция OnStart не получает параметров и не возвращает никаких кодов.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   
  }

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

Кроме того, в среде разработки MetaEditor существует возможность создания библиотек и включаемых файлов. Эти файлы предназначены для хранения и распространения часто используемых блоков программ. Библиотеки являются скомпилированными файлами и предоставляют отдельные функции для экспорта в другие выполняемые программы. Сам же код выполняемых функций скрыт. Включаемые файлы, в отличие от библиотек, являются файлами с открытым кодом. В плане производительности предпочтительнее использовать включаемые файлы, но они не обеспечивают тайну кода при распространении.

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

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

Следовательно, для построения своей нейронной сети мы можем использовать советники или скрипты.