Как построить и протестировать стратегию бинарных опционов в Тестере Стратегий MetaTrader 4

Martin Amiri | 30 декабря, 2016


Оглавление

1. Введение
2. Установка
3. Образец стратегии бинарных опционов
3.1. Определение стратегии бинарных опционов
3.2. Создание стратегии бинарных опционов
3.2.1. Входные параметры
3.2.2. Включение библиотеки Binary-Options-Strategy-Library
3.2.3. Добавление CallStrategy()
3.2.4. Имплементация CheckMyRules() и вспомогательной функции
3.2.5. Отладочная печать
3.2.6. Использование внешних индикаторов (ex4-файлов)
3.3. Окончательный код
4. Запуск бэк-тестов (видео)
5. Запуск форвард-теста
6. FAQ
7. Разное


1. Введение

В Тестере Стратегий MetaTrader 4 можно тестировать советники и индикаторы на исторических данных, но он не может обрабатывать бинарные опционы с временем истечения. Поэтому, когда мне потребовалось протестировать стратегию бинарных опционов в MetaTrader 4, я создал для этих целей утилиту Binary-Options-Strategy-Tester.

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

Идея состоит из следующих частей:

Концепция утилиты Binary Options Strategy Tester

Это пошаговый пример того, как можно выстроить стратегию работы с бинарными опционами: индикатор (отмечен красным цветом на рисунке выше) через библиотеку Binary-Options-Strategy-Library связывается с Binary-Options-Strategy-Tester, далее стратегия размещает виртуальные ордера и обсчитывает результаты их работы с помощью бэк- и форвард-тестов.

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


2. Установка

Загрузите Binary-Options-Strategy-Tester из Маркета. Доступна и пробная конфигурация для тестирования стратегий бинарных опционов в Тестере Стратегий Metatrader 4. Стратегия будет вызывать функцию Binary-Options-Strategy-Tester (через библиотеку Binary-Options-Strategy-Library) для размещения виртуальных сделок. В связи с концепцией лицензионного соглашения MQL4, это будет работать только если продукт имеет рабочую лицензию. Поэтому вы должны будете либо приобрести платную версию продукта, либо демо-версию.

Загрузите Binary-Options-Strategy-Library и разместите ее в вашу папку \Include ([ваш путь к MetaTrader 4] \ MQL4 \ Include).  Бесплатная библиотека предоставляет несколько функций для построения стратегии бинарных опционов и для простой связи ее с продуктом Binary-Options-Strategy-Tester.

Загрузите бесплатный индикатор KVO и поместите его в папку Индикаторы \ Downloads ([ваш путь к MetaTrader 4] \ MQL4 \ Индикаторы \ Downloads. Этот индикатор используется в качестве примера доступа стратегии к внешним индикаторам и их ex4-файлам. Более подробная информация по этому индикатору находится здесь

Теперь вы можете перейти в раздел 3 и построить пример кода самостоятельно или же загрузить пример, представленный ниже: поместите его (и его скомпилированный файл ex4) в папку \Indicators ([путь к вашему MetaTrader 4]\MQL4\Indicators).



3. Пример построения стратегии бинарных опционов

Теперь шаг за шагом будет описано, как построить пример стратегии бинарных опционов в составе индикатора, чтобы он мог взаимодействовать с утилитой Binary-Options-Strategy-Tester.

Эта стратегия не приносит доход! Это просто пример того, как выстроить стратегию в виде индикатора, обменивающегося данными с утилитой Binary-Options-Strategy-Tester. Конечно, вы можете самостоятельно выстроить прибыльную стратегию. Но, как вы сможете убедиться, эта утилита поможет вам проверить и улучшить вашу собственную стратегию бинарных опционов.


3.1 Определение стратегии

В первую очередь, мы должны определить стратегию и изменяемые значения (входные параметры). Документация MQL4 описывает все технические индикаторы, к которым можно обращаться через интерфейс iCustom: https://docs.mql4.com/indicators

Допустим, мы хотим создать простую стратегию на основе пересечения одной "быстрой" и одной "медленной" скользящей средней, которая будет торговать на следующей после пересечения свече. Документация описывает, как мы можем получить значения простой МА: https://docs.mql4.com/indicators/ima.

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

int ma_period
int ma_method
int applied_price

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

int period_fast        =  5;
int period_slow        = 10;
int method_both        =  0; 
int applied_price_both =  0; 


3.2 Создание стратегии бинарных опционов

Построим индикатор, в котором будет заключена стратегия бинарных опционов и который можно будет перетаскивать на график, где будет запускаться также и утилита Binary-Options-Strategy-Tester.

Откройте редактор MQL (в Metatrader 4 кликните на "Сервис" -> "Редактор MetaQuotes Language" или просто нажмите F4) и кликните на "Создать":

Language Editor New

Появится Мастер MQL. Выберите "Пользовательский Индикатор", чтобы создать пустой индикатор, и кликните на "Далее":

Language Editor Custom Indicator

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

Language Editor Custom Indicator Values

Во вкладке обработчиков событий установите флажок "OnCalculate", поскольку нам нужно это событие для проверки стратегии на каждом тике. Нажмите "Далее":

Language Editor Custom Indicator Events

Во вкладке свойств отрисовки выберите флажок "Индикатор в отдельном окне", поскольку нам нужно будет отдельное окно для отладочной печати. Нажмите "Закончить":

Language Editor Custom Indicator Drawing Properties

Появится заготовка кода вашего индикатора:

//+------------------------------------------------------------------+
//|                                 BinaryOptionsStrategyExample.mq4 |
//|                                       Copyright 2016, __martin__ |
//|                         https://www.mql5.com/ru/users/__martin__ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, __martin__"
#property link      "https://www.mql5.com/ru/users/__martin__"
#property version   "1.00"
#property strict
#property indicator_separate_window
//--- input parameters
input int      period_fast=5;
input int      period_slow=10;
input int      method_both=0;
input int      applied_price_both=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Отображение индикаторных буферов
  
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
  
//--- Возвращает значение prev_calculated для следующего вызова
   return(rates_total);
  }
//+------------------------------------------------------------------+


3.2.1 Входные параметры

Начальные входные параметры создаются Мастером MQL (см. 3.2, Создании стратегии бинарных опционов), а мы их усовершенствуем с помощью следующих шагов. 

Чтобы избежать установки значения int для применяемой цены и метода усреднения для МА во входных параметрах, тип параметров method_both и applied_price_both изменяем с int на перечисление со значениями по умолчанию.

ENUM_MA_METHOD: https://docs.mql4.com/constants/indicatorconstants/enum_ma_method
ENUM_APPLIED_PRICE: https://docs.mql4.com/constants/indicatorconstants/prices#enum_applied_price_enum

Кроме того, добавлены комментарии для входных параметров, чтобы показать комментарии как метки вместо имен переменных:

...

//--- Входные параметры
input int                period_fast        =  5;           // Значения быстрой MA
input int                period_slow        = 10;           // Значения медленной MA
input ENUM_MA_METHOD     method_both        = MODE_SMA;     // Метод для расчета МА
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  // Цена для расчета МА

...

Эта модификация делает для входных параметров доступным выпадающее меню с позициями для выбора, а также включение меток :

Входные параметры для стратегии бинарных опционов


3.2.2 Включение библиотеки Binary-Options-Strategy-Library

Если вы скачали библиотеку (см 2. Установка) и установили ее в папку \Include ([путь к Metatrader 4]\MQL4\Include), можете подключить ее следующим образом:

//+------------------------------------------------------------------+
//|                                 BinaryOptionsStrategyExample.mq4 |
//|                                       Copyright 2016, __martin__ |
//|                         https://www.mql5.com/ru/users/__martin__ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, __martin__"
#property link      "https://www.mql5.com/ru/users/__martin__"
#property version   "1.00"
#property strict
#property indicator_separate_window

#include <BinaryOptionsStrategyLibrary.mqh>

//--- Входные параметры

...
Библиотека будет доступна только если вы разместите ее в папке \Include вашего терминала, как описано в примере.
Изменять содержимое библиотеки не требуется!

С помощью библиотеки мы дополним входные параметры еще двумя новыми:

  • На одну свечу размещается только одна сделка SELL или BUY
  • Проверка в рамках стратегии осуществляется только в начале новой свечи

Дополненные входные параметры стратегии бинарных опционов


3.2.3 Добавление CallStrategy()

Добавим вызов функции CallStrategy() в OnCalculate() вашего индикатора, чтобы обращаться к стратегии на каждом новом тике. CallStrategy() предоставляется библиотекой Binary-Options-Strategy-Library, которую вы уже подключили, как описано выше:

...

//+------------------------------------------------------------------+
//| 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[])
  {
//---

   CallStrategy(); // Вызов стратегии, функция находится в BinaryOptionsStrategyLibrary.mqh (подключенной выше)

//--- Возвращает значение prev_calculated для следующего вызова

   return
(rates_total);
  }
//+------------------------------------------------------------------+

Функция CallStrategy() в Binary-Options-Strategy-Library вызывает функцию CheckMyRules() в вашем индикаторе, в котором задаются условия стратегии.
Поэтому в стратегии необходимо реализовать функцию CheckMyRules().


3.2.4 Имплементация СheckMyRules() и вспомогательной функции

В функции CheckMyRules(), которая вызывается с помощью библиотеки Binary-Options-Strategy-Library, реализованы условия стратегии и происходит размещение сделок посредством функции PlaceTrade() из этой же библиотеки. Значения обеих МА берутся из вспомогательной функции GetValuesForMA() и временно хранятся в переменных для того, чтобы сравнивать их с помощью условия if.


...

//--- Входные параметры
input int                period_fast        =  5;           // Значения для быстрой MA
input int                period_slow        = 10;           // Значения для медленной MA
input ENUM_MA_METHOD     method_both        = MODE_SMA;     // Метод для расчета MA
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  // Цена для расчета MA

...

//+------------------------------------------------------------------+
//| Разместите здесь ваши торговые условия — см. пример ниже.        |
//| Тестер Стратегий вызывает эту функцию, чтобы разместить сделки.  |
//| НЕ СЛЕДУЕТ:                                                      |
//| - Переименовывать функцию                                        |
//| - Добавлять параметры функции, например, CheckMyRules(int a)     |
//| - Изменять тип возвращаемого значения функции                    |
//+------------------------------------------------------------------+
void CheckMyRules()
  {
  
   // Сохранить значения MA с shift=0 (текущая свеча) -> текущая свеча,
   // Вызов вспомогательной функции GetValueForMA() для получения значений — см. вспомогательные функции ниже
   double emaSlow_Current = GetValueForMA(period_slow, 0);
   double emaFast_Current = GetValueForMA(period_fast, 0);

   // Сохранить значения MA с shift=1 (прошедшая свеча) -> последняя свеча,
   // Вызов вспомогательной функции GetValueForMA() для получения значений — см. вспомогательные функции ниже
   double emaSlow_Past = GetValueForMA(period_slow, 1);
   double emaFast_Past = GetValueForMA(period_fast, 1);

   if(emaFast_Past > emaSlow_Past
   && emaFast_Current < emaSlow_Past) // Проверить, пересекаются ли медленная МА и быстрая МА
     {
      PlaceTrade(OP_SELL); // Разместить сделку SELL для Тестера Стратегий, функция находится в BinaryOptionsStrategyFunctions.mqh
     }
  
   if(emaFast_Past < emaSlow_Past
   && emaFast_Current > emaSlow_Past) // Проверить, пересекаются ли медленная МА и быстрая МА
     {
      PlaceTrade(OP_SELL); // Разместить сделку BUY для Тестера Стратегий, функция находится в BinaryOptionsStrategyFunctions.mqh
     }
  
  }

//+------------------------------------------------------------------+
//| Разместите вашу вспомогательную функцию здесь, см. пример ниже   |
//+------------------------------------------------------------------+
//----
//+---------------------------------------------------------------------+
//| Получить значения периода, метод, цену для расчета и сдвиг для МА   |
//| Для подробностей по iMA() см. https://docs.mql4.com/indicators/ima  |
//+---------------------------------------------------------------------+
double GetValueForMA(int _period,int _shift)
  {
   return iMA(NULL,0,_period,0,method_both,applied_price_both,_shift);
  }
 


3.2.5 Отладочная печать

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


...

//--- входные параметры
input int                period_fast        =  5;           // Значения для быстрой MA
input int                period_slow        = 10;           // Значения для медленной MA
input ENUM_MA_METHOD     method_both        = MODE_SMA;     // Метод для расчета MA
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  // Цена для расчета MA

...

//+-----------------------------------------------------------------------------+
//| Разместить здесь ваши торговые условия — смотрите пример ниже.         |
//| Тестер Стратегий вызывает эту функцию, чтобы разместить сделки.             |
//| НЕ СЛЕДУЕТ:                                                                 |
//| - Переименовать функцию                                                     |
//| - Добавить параметры функции, например, CheckMyRules(int a)                 |
//| - Изменить тип возвращаемого значения функции, например, int CheckMyRules() |
//+-----------------------------------------------------------------------------+
void CheckMyRules()
  {
  
   // Сохранить значения MA с помощью shift=0 (текущая свеча) -> текущая свеча,
   //вызов вспомогательной функции GetValueForMA() для получения значений — см. вспомогательные функции ниже <br50/>    double emaSlow_Current = GetValueForMA(period_slow, 0);
   double emaFast_Current = GetValueForMA(period_fast, 0);

   //Сохранить значения MA с помощью shift=1 (прошедшая свеча) -> последняя свеча,<br61/>    <s62>//вызов вспомогательной функции GetValueForMA() для получения значений — см. вспомогательные функции ниже </s62><br63/>    double emaSlow_Past = GetValueForMA(period_slow, 1);
   double emaFast_Past = GetValueForMA(period_fast, 1);

   PrintDebugValue("emaSlow_Current: ",(string)emaSlow_Current,0); // Метка и значение на линии 0
   PrintDebugValue("emaFast_Current: ",(string)emaFast_Current,1); // Метка и значение на линии 1
   PrintDebugValue("emaSlow_Past: ",(string)emaSlow_Past,2);       // Метка и значение на линии 2
   PrintDebugValue("emaFast_Past: ",(string)emaFast_Past,3);       // Метка и значение на линии 3

   if(emaFast_Past > emaSlow_Past
   && emaFast_Current < emaSlow_Past) // проверить, пересекаются ли медленная МА и быстрая МА
     {
      PlaceTrade(OP_SELL); // Разместить сделку SELL для Тестера Стратегий, функция находится в BinaryOptionsStrategyFunctions.mqh
     }
  
   if(emaFast_Past < emaSlow_Past
   && emaFast_Current < emaSlow_Past) // Проверить, пересекаются ли медленная МА и быстрая МА
     {
      PlaceTrade(OP_SELL); // Разместить сделку BUY для Тестера Стратегий, функция находится в BinaryOptionsStrategyFunctions.mqh
     }
  
  }

//+------------------------------------------------------------------+
//| Разместите вашу вспомогательную функцию здесь, см. пример ниже   |
//+------------------------------------------------------------------+
//----

//+--------------------------------------------------------------------+
//| Получить значения МА для периода, метод, цену для расчета и сдвиг. |
//| For details of iMA() see https://docs.mql4.com/indicators/ima      |
//+--------------------------------------------------------------------+
double GetValueForMA(int _period,int _shift)
  {
   return iMA(NULL,0,_period,0,method_both,applied_price_both,_shift);
  }
 


3.2.6 Использование внешних индикаторов (ex4-файлов)

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

Скажем, мы хотели бы подключить сигнальную линию индикатора KVO https://www.mql5.com/ru/code/8677 и размещать сделки BUY, если она выше 0, и SELL — если она ниже 0. Загрузим индикатор и поместим компилированный файл (ex4) в папку \Indicators\Downloads ([путь к MetaTrader 4]\MQL4\Indicators\Downloads).

Сначала мы должны определить соответствующие буферы для доступа, в которых будут храниться значения. Чтобы показать все доступные буферы используемых индикаторов, нажмем кнопку "Окно данных" терминала и перетащим индикатор KVO на график. При наведении перекрестия на график (нажмите колесо мышки, чтобы оно появилось), значения буфера индикатора на выделенном периоде будут показаны в окне данных.

Буферы и значения внешнего индикатора

Метки окна данных сообщат нам значение буфера индикатора с индексом. В этом буфере хранятся данные по сигнальной линии Если буферы индикаторов не снабжены метками, мы можем найти нужный путем сравнения значений буфера с отображаемым значением под наведенным перекрестием на графике индикатора. Индексы буферов индикатора начинаются с 0. Таким образом, значение буфера 1 соответствует значению буфера с индексом 0, и так далее. Мы должны иметь доступ к буферу 1, чтобы получить значение сигнала.

Затем мы должны узнать все входные параметры внешнего индикатора, к которому мы бы хотели получить доступ. При перетаскивании индикатора на график мы сможем открыть поле "Входные параметры":

Входные параметры KVO

Допустим, мы бы хотели получить доступ к индикатору с начальными значениями 34, 55 и 13. Используем вспомогательную функцию (на основе iCustom), которая позволит нам получать значения индикатора с параметрами для буфера и сдвига, в то время как сдвиг 0 будет значением текущей свечи, сдвиг 1 — значением предыдущей свечи, сдвиг 2 — значением позапрошлой свечи, и т.д. В дополнение мы временно сохраним значения индикаторных буферов и доработаем if-условия стратегии:


...

//--- Входные параметры
input int                period_fast        =  5;           // Значения быстрой МА
input int                period_slow        = 10;           // Значения медленной МА
input ENUM_MA_METHOD     method_both        = MODE_SMA;     // Метод расчета MA
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  // Цена для расчета MA

...

//+-------------------------------------------------------------------------------+
//| Разместите свои торговые правила здесь - см. пример ниже                      |
//| Тестер стратегий вызовет эту функцию для размещения сделок                    |
//| НЕ СЛЕДУЕТ:                                                                   |
//| - Переименовывать функцию                                                     |
//| - Добавлять параметры функции (например, CheckMyRules(int a)                  |
//| - Изменять тип возвращаемого значения функции (например, int CheckMyRules())  |
//+-------------------------------------------------------------------------------+
void CheckMyRules()
  {
  
   // Сохранение значений МА с помощью shift=0 (текущая свеча) -> current candle,
   // Вызов вспомогательной функции GetValueForMA() для получения значения - см. описание вспомогательной функции ниже
   double emaSlow_Current = GetValueForMA(period_slow, 0);
   double emaFast_Current = GetValueForMA(period_fast, 0);

   // Сохранение значений МА с помощью shift=1 (прошлая свеча) -> last candle,
   //    // Вызов вспомогательной функции GetValueForMA() для получения значения - см. описание вспомогательной функции ниже
   double emaSlow_Past = GetValueForMA(period_slow, 1);
   double emaFast_Past = GetValueForMA(period_fast, 1);

   // Сохранение сигнального значения (буфер 1) индикатора KVO с текущей свечи (shift 0)
   double kvoSignal = GetValuesFromIndicator__KVO__(1,0);

   PrintDebugValue("emaSlow_Current: ",(string)emaSlow_Current,0); // Метка и значение на линии 0
   PrintDebugValue("emaFast_Current: ",(string)emaFast_Current,1); // Метка и значение на линии 1
   PrintDebugValue("emaSlow_Past: ",(string)emaSlow_Past,2);       // Метка и значение на линии 2
   PrintDebugValue("emaFast_Past: ",(string)emaFast_Past,3);       // Метка и значение на линии 3

   if(emaFast_Past > emaSlow_Past
   && emaFast_Current < emaSlow_Past // Проверка, пересекаются ли медленная МА и быстрая МА

   && kvoSignal < 0) // Проверка, находится ли сигнальное значение KVO ниже нулевой линии

     {

      PlaceTrade(OP_SELL); // Разместите сделку SELL для Тестера Стратегий, функция расположена в BinaryOptionsStrategyFunctions.mqh
     }
  
   if(emaFast_Past < emaSlow_Past
   && emaFast_Current > emaSlow_Past // Проверка, пересекаются ли медленная МА и быстрая МА
   && kvoSignal > 0) // Проверка, находится ли сигнальное значение  KVO выше нулевой линии
     {
      PlaceTrade(OP_BUY); // Разместите сделку BUY для Тестера Стратегий, функция расположена в BinaryOptionsStrategyFunctions.mqh
     }
  
  }

//+------------------------------------------------------------------+
//| Разместите здесь вашу вспомогательную функцию (см. пример ниже)  |
//+------------------------------------------------------------------+
//----

//+------------------------------------------------------------------------+
//| Получить значений МА для периода, метод, цену для расчета и сдвиг      |
//| Для более подробно об iMA() см. https://docs.mql4.com/indicators/ima   |
//+------------------------------------------------------------------------+
double GetValueForMA(int _period,int _shift)
  {
   return iMA(NULL,0,_period,0,method_both,applied_price_both,_shift);
  }

//+------------------------------------------------------------------+
//| Пример получения значений от внешнего индикатора                 |
//| см. https://docs.mql4.com/indicators/icustom                     |
//| Параметры :                                                      |
//| int _buffer - индикаторный буфер (от 0)                          |
//| int _shift - значение сдвига; 0 = текущая свеча, 1 = предыдущая  |
//+------------------------------------------------------------------+
double GetValuesFromIndicator__KVO__(int _buffer, int _shift=0) // Изменить "__KVO__" на имя индикатора
  {

   return (
            iCustom (
                      NULL,                      // NULL для текущего таймфрейма, выбранного в тестере - НЕ ТРЕБУЕТСЯ ИЗМЕНЕНИЙ
                      0,                         // 0 для текущего символа в тестере - НЕ ТРЕБУЕТСЯ ИЗМЕНЕНИЙ

                      //BEGIN EDIT
                      "\\Downloads\\KVO.ex4",    // Путь к файлам и имена файлов индикатора(*.ex4)
                      //BEGIN INDICATORS INPUTS
                      34,
                      55,
                      13,
                      //END FOR INPUTS
                      //END EDIT

                      _buffer,                   // Индекс буфера (начинаются с 0), _buffer передается через параметры функции - НЕ ТРЕБУЕТСЯ ИЗМЕНЕНИЙ
                      _shift                     // Сдвиг(0 для текущей свечи), _shift передается через параметры функции - НЕ ТРЕБУЕТСЯ ИЗМЕНЕНИЙ
                    )
          );

  }

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


3.3 Полный код

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

//+------------------------------------------------------------------+
//|                                 BinaryOptionsStrategyExample.mq4 |
//|                                       Copyright 2016, __martin__ |
//|                         https://www.mql5.com/en/users/__martin__ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, __martin__"
#property link      "https://www.mql5.com/en/users/__martin__"
#property version   "1.00"
#property strict
#property indicator_separate_window

#include <BinaryOptionsStrategyLibrary.mqh>

//+------------------------------------------------------------------+
//| Разместите здесь ваши входные параметры - см. пример ниже        |
//+------------------------------------------------------------------+
//--- Входные параметры
input int                period_fast        =  5;           // Период быстрой МА
input int                period_slow        = 10;           // Период медленной МА
input ENUM_MA_METHOD     method_both        = MODE_SMA;     // Метод для расчета МА
input ENUM_APPLIED_PRICE applied_price_both = PRICE_CLOSE;  // Цена для расчета MA
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Расположение индикаторных буферов

//---
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| 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[])
  {
//---

   CallStrategy(); // Вызов стратегии, функция расположена в библиотеке BinaryOptionsStrategyLibrary.mqh (она подключена выше)

//--- возвращение значения prev_calculated для следующего вызова
   return(rates_total);
  }

//+-------------------------------------------------------------------------------+
//| Разместите свои торговые правила здесь - см. пример ниже                      |
//| Тестер стратегий вызовет эту функцию для размещения сделок                    |
//| НЕ СЛЕДУЕТ:                                                                   |
//| - Переименовывать функцию                                                     |
//| - Добавлять параметры функции (например, CheckMyRules(int a)                  |
//| - Изменять тип возвращаемого значения функции (например, int CheckMyRules())  |
//+-------------------------------------------------------------------------------+
void CheckMyRules()
  {
  
   // Сохранение значений МА с помощью shift=0 (текущая свеча) -> current candle,
   // Вызов вспомогательной функции GetValueForMA() для получения значения - см. вспомогательные функции ниже
   double emaSlow_Current = GetValueForMA(period_slow, 0);
   double emaFast_Current = GetValueForMA(period_fast, 0);

   // Сохранение значений  MA с помощью shift=1 (прошедшая свеча) -> last candle,
   // Вызов вспомогательной функции GetValueForMA() для получения значения - см. вспомогательные функции ниже
   double emaSlow_Past = GetValueForMA(period_slow, 1);
   double emaFast_Past = GetValueForMA(period_fast, 1);
  
   // Сохранение сигнального значения (буфер 1) индикатора KVO с текущей свечи (shift 0)
   double kvoSignal = GetValuesFromIndicator__KVO__(1,0);
  
   PrintDebugValue("emaSlow_Current: ",(string)emaSlow_Current,0); // Метка и значение на линии 0
   PrintDebugValue("emaFast_Current: ",(string)emaFast_Current,1); // Метка и значение на линии 1
   PrintDebugValue("emaSlow_Past: ",(string)emaSlow_Past,2);       // Метка и значение на линии 2
   PrintDebugValue("emaFast_Past: ",(string)emaFast_Past,3);       // Метка и значение на линии 3

   if(emaFast_Past > emaSlow_Past
   && emaFast_Current < emaSlow_Past    // Проверка, пересекаются ли медленная и быстрая МА
   && kvoSignal < 0)                    // Проверка, находится ли сигнальное значение KVO ниже нулевой линии 
     {
      PlaceTrade(OP_SELL);              // Разместить сделку SELL для Тестера Стратегий, функция расположена в BinaryOptionsStrategyLibrary.mqh
     }
  
   if(emaFast_Past < emaSlow_Past
   && emaFast_Current > emaSlow_Past    // Проверка, пересекаются ли медленная и быстрая МА
   && kvoSignal > 0)                    // Проверка, находится ли сигнальное значение KVO выше нулевой линии
     {
      PlaceTrade(OP_BUY);               // Разместить сделку BUY для Тестера Стратегий, функция расположена в BinaryOptionsStrategyLibrary.mqh
     }
  
  }

//+------------------------------------------------------------------+
//| Разместите здесь вспомогательную функцию, см. пример ниже        |
//+------------------------------------------------------------------+
//----

//+--------------------------------------------------------------------+
//| Получить значения МА для периода, метод, примененную цену и сдвиг  |
//| Подробнее об iMA() см. https://docs.mql4.com/indicators/ima        |
//+--------------------------------------------------------------------+
double GetValueForMA(int _period,int _shift)
  {
   return iMA(NULL,0,_period,0,method_both,applied_price_both,_shift);
  }

//+--------------------------------------------------------------------------+
//| Пример получения значений от внешних индикаторов,                        |
//| см. https://docs.mql4.com/indicators/icustom                             |
//| Параметры:                                                               |
//| int _buffer - индикаторный буфер (начинается с 0)                        |
//| int _shift - значения сдвига; 0 = текущая свеча, 1 = предыдущая свеча    |
//+--------------------------------------------------------------------------+
double GetValuesFromIndicator__KVO__(int _buffer, int _shift=0) // Изменить "__KVO__" на имя индикатора
  {
   return (
            iCustom (
                      NULL,                      // NULL для текущего таймфрейма, выбранного в Тестере - ИЗМЕНЕНИЙ НЕ ТРЕБУЕТСЯ
                      0,                         // 0 для текущего символа, выбранного в Тестере - ИЗМЕНЕНИЙ НЕ ТРЕБУЕТСЯ
                  
                      //BEGIN EDIT
                      "\\Downloads\\KVO.ex4",    // Имя индикатора (*.ex4 file) и путь к нему              
                      //BEGIN INDCATORS INPUTS
                      34,
                      55,
                      13,
                      //END FOR INPUTS
                      //END EDIT
                  
                      _buffer,                   // Буферный индекс (начинается с 0), _buffer передается через параметры функции - ИЗМЕНЕНИЙ НЕ ТРЕБУЕТСЯ
                      _shift                     // Сдвиг (0 для текущей свечи), _shift передается через параметры функции - ИЗМЕНЕНИЙ НЕ ТРЕБУЕТСЯ
                    )
          );
  }
//+-----------------------------------------------------------------+


4. Запуск бэк-теста (видео)

Нижеследующее видео показывает, как запустить бэк-тест в вашей стратегии бинарных опционов в Тестере Стратегий MetaTrader 4:

  • Запустите Binary-Options-Strategy-Tester в Тестере Стратегий MetaTrader 4 и установите входные параметры
  • Перетащите ваш индикатор стратегии на график, выставьте входные параметры и проверьте, выставлено ли "Разрешить импорт из внешних экспертов во вкладке "Общие"".
  • Перетащите ваш используемый индикатор с его входными параметрами на график, чтобы увидеть, как меняются его значения, пока запущен тестер (это опциональный пункт программы).
  • Сохраните все настройки в шаблоне, чтобы запустить тест со всеми этими настройками опять - используйте кнопку паузы в Тестере Стратегий (это тоже необязательно).
  • Теперь вы можете посмотреть результаты работы вашей стратегии бинарных опционов на графике Тестера Стратегий.  


5. Запустите форвард-тест

Чтобы запустить форвард-тестирование, просто перетащите утилиту Binary-Options-Strategy-Tester и ваш индикатор стратегии на ваш демо-график или на график реального счета вашего брокера, вместо того, чтобы использовать Тестер Стратегий.

  • Перетащите утилиту Binary-Options-Strategy-Tester на демо-графмк или на живой счет и установите входные параметры.
  • Перетащите ваш индикатор стратегии на график, выставьте входные параметры и проверьте, выставлено ли разрешение использовать параметры внешних экспертов в таблице условий.
  • Перетащите используемый вами индикатор с его параметрами на график, чтобы посмотреть, как изменяются его условия, пока идет форвард-тест.
  • Сохраните все настройки в шаблоне, чтобы потом запустить тест снова.
  • Теперь вы можете посмотреть результат работы вашей стратегии бинарных опционов на графике демонстрационного или реального счета.


6. Часто задаваемые вопросы

Вопрос: Почему вы показываете пример неприбыльной стратегии бинарных опционов?
Ответ: Это всего лишь пример того, как выстроить стратегию, связав ее индикатор с утилитой Binary-Options-Strategy-Tester, чтобы протестировать ее на рыночных условиях и доработать.

Вопрос: Утилита Binary-Options-Strategy-Tester прекращает работу с сообщением об ошибке "Array out of range" после того, как достигается определенное количество потерь. Почему?
Ответ: После некоего количества потерь — скажем, x, в работе Binary-Options-Strategy-Tester может выдать ошибку, чтобы остановить Тестер и проанализировать ситуацию на графике. Если вам этого не нужно — просто отключите эту опцию в настройках.

Вопрос: Некоторые стрелки-указатели, казалось бы, не обрабатываются утилитой Binary-Options-Strategy-Tester. Почему?
Ответ: Чтобы оставить некоторые различия между демо-версией и версией для продажи. В демонстрационном варианте не все ордера обрабатываются тестером. Необрабатываемые ордера обозначаются зелеными стрелками.

Вопрос: На графике не появляется стрелка после того, как я перетащил мой индикатор с работающей стратегией. Что случилось?
Ответ: Вы должны включить галочку "Разрешить импорт из внешних экспертов" перед перетаскиванием вашего индикатора стратегии на график (сообщение в логе будет показывать вам в этом случае ошибку).

Вопрос: Я не вижу результатов во вкладках Тестера Стратегий "Результаты", "График", "Отчет". Где я могу увидеть результаты тестирования?
Ответ: Тестер Стратегий MetaЕrader 4 не может обрабатывать бинарные опционы, поэтому эти вкладки не могут быть использованы. Поэтому наша утилита вычисляет все выигрыши и проигрыши и распечатывает результаты прямо на графике.


7. Разное

Эта утилита была разработана, поскольку мне нужна была возможность тестировать стратегии бинарных опционов в автоматическом режиме в MetaTrader 4 для долгосрочных периодов и делать форвард-тесты на брокерских чартах. Я провел много времени над разработкой концепции и над имплементацией утилиты Binary-Options-Strategy-Tester, а также над изучением ее документации. Может быть, есть и более удобный путь, чтобы сделать это, и может быть, некоторые улучшения сделают утилиту более подходящей для вас. Поэтому пожалуйста, не стесняйтесь связаться со мной, если у вас есть идеи по улучшению этой работы.