Раздельная оптимизация стратегии на тренде и флете

Alexander Fedosov | 10 декабря, 2018

Содержание


Введение

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

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

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


Понятие Раздельной Оптимизации

В данной статье предлагается рассмотреть применения инструмента Тестер стратегий в более широком смысле. Очевидно, что большинство системы на рынке торгует в двух направлениях, как покупают при определенных условиях, так и продают. На рис.1 изображен простой пример работы трендовой торговой стратегии в идеале. Суть её проста — покупаем по низкой цене и продаем по высокой.


Рис.1 Схема работы трендовой торговой стратегии.

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

Для этого потребуется два набора параметров, определяющих условия входа и выхода с рынка. И тут мы подходим к самому понятию "раздельной оптимизации".

Раздельная оптимизация — это определение оптимальных параметров торговой системы с помощью Тестера стратегий отдельно для восходящего и нисходящего тренда.

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


Выбор трендовой торговой стратегии

В качестве стратегии, которая будет использоваться в тестировании раздельной оптимизации выбрана следующая: она использует индикатор Центр гравитации Эллерса, представленный в виде гистограммы OSMA — CenterOfGravityOSMA. Его сигнал подтверждается индикатором, вычисляющим среднюю скорость цены Average Speed.

ПараметрОписание
Используемый индикаторCenterOfGravityOSMA
Используемый индикаторAverage Speed
ТаймфреймH1
Условия на покупкуГистограмма Центра гравитации показывает рост (при этом значение индикатора меньше нуля), а значение Average Speed выше порогового (изначально заданного в настройках)
Условия на продажуГистограмма Центра гравитации показывает падение (при этом значение индикатора больше нуля), а значение Average Speed выше порогового (изначально заданного в настройках)
Условия выхода  Тейк-профит/Стоп-лосс

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

Р‌ис.2 Условия входа по трендовой стратегии.

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

Также нужно учесть такие моменты:

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

Для выполнения этих условий создания торгового эксперта введем следующий код:

//+------------------------------------------------------------------+
//| Перечисление режимов работы                                      |
//+------------------------------------------------------------------+
enum Trend_type
  {
   UPTREND = 1,            //Uptrend       
   DOWNTREND,              //Downtrend
   BOTH                    //Both trends
  };

Набор входных параметров выглядит так:

//+------------------------------------------------------------------+
//| Входные параметры эксперта                                       |
//+------------------------------------------------------------------+
input string               Inp_EaComment="Trend Strategy";              //EA Comment
input double               Inp_Lot=0.01;                                //Lot
input MarginMode           Inp_MMode=LOT;                               //MM

input Trend_type           Inp_Trend_type=3;                            //Trend type
//--- Uptrend parameters
input string               Inp_Str_label1="===Uptrend parameters===";   //Label
input int                  Inp_MagicNum1=1111;                          //Magic number
input int                  Inp_StopLoss1=40;                            //Stop Loss(points)
input int                  Inp_TakeProfit1=60;                          //Take Profit(points)

//--- Параметры индикатора CenterOfGravityOSMA
input uint                 Period_1=9;                                  //Averaging period
input uint                 SmoothPeriod1_1=3;                           //Smoothing period1
input ENUM_MA_METHOD       MA_Method_1_1=MODE_SMA;                      //Averaging method1
input uint                 SmoothPeriod2_1=3;                           //Smoothing period2
input ENUM_MA_METHOD       MA_Method_2_1=MODE_SMA;                      //Averaging method2
input Applied_price_       AppliedPrice1=PRICE_OPEN_;                   //Applied price

//--- Параметры индикатора Average Speed
input int                  Inp_Bars1=1;                                 //Days
input ENUM_APPLIED_PRICE   Price1=PRICE_CLOSE;                          //Applied price
input double               Trend_lev1=2;                                //Trend Level

//--- Downtrend parameters
input string               Inp_Str_label2="===Downtrend parameters==="; //Label
input int                  Inp_MagicNum2=2222;                          //Magic number
input int                  Inp_StopLoss2=40;                            //Stop Loss(points)
input int                  Inp_TakeProfit2=60;                          //Take Profit(points)

//--- Параметры индикатора CenterOfGravityOSMA
input uint                 Period_2=9;                                  //Averaging period
input uint                 SmoothPeriod1_2=3;                           //Smoothing period1
input ENUM_MA_METHOD       MA_Method_1_2=MODE_SMA;                      //Averaging method1
input uint                 SmoothPeriod2_2=3;                           //Smoothing period2
input ENUM_MA_METHOD       MA_Method_2_2=MODE_SMA;                      //Averaging method2
input Applied_price_       AppliedPrice2=PRICE_OPEN_;                   //Applied price

//--- Параметры индикатора Average Speed
input int                  Inp_Bars2=1;                                 //Days
input ENUM_APPLIED_PRICE   Price2=PRICE_CLOSE;                          //Applied price
input double               Trend_lev2=2;                                //Trend Level

Как видно из кода переменная Inp_Trend_type отвечает за выбор режима работы торгового эксперта, а входные параметры для режимов Uptrend и Downtrend разделены соответственно на Uptrend parameters и Downtrend parameters. Стоит отметить, что при выборе режима Both входные параметры будут использоваться из обоих разделов.

А основной код реализации логики представлен в следующем листинге:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Получение данных для расчета

   if(!GetIndValue())
      return;

   if(Inp_Trend_type==1 && !Trade.IsOpenedByMagic(Inp_MagicNum1))
     {
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
     }
   else if(Inp_Trend_type==2 && !Trade.IsOpenedByMagic(Inp_MagicNum2))
     {
      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);
     }
   else if(Inp_Trend_type==3)
     {
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal() && !Trade.IsOpenedByMagic(Inp_MagicNum1))
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal() && !Trade.IsOpenedByMagic(Inp_MagicNum2))
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(avr_speed1[0]>Trend_lev1 && cog1[1]<cog1[0] &&(cog1[1]<0 && cog1[0]<0))?true:false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(avr_speed2[0]>Trend_lev2 && cog2[1]>cog2[0] &&(cog2[1]>0 && cog2[0]>0))?true:false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,cog1)<=0 ||
          CopyBuffer(InpInd_Handle2,0,0,2,cog2)<=0 ||
          CopyBuffer(InpInd_Handle3,0,0,2,avr_speed1)<=0 ||
          CopyBuffer(InpInd_Handle4,0,0,2,avr_speed2)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Для режимов Uptrend и Downtrend схема торговли проста: покупка при восходящем и продажа при нисходящем, то есть следование за тенденцией. В режиме Both видно, что обе этим системы работают вместе и независимо друг от друга со своими уникальными входными параметрами — Uptrend+Downtrend.


Тестирование трендовой стратегии

Для тестирования и раздельной оптимизации выбранной стратегии логично выбрать ярко выраженные периоды восходящего тренда для режима Uptrend и нисходящего для режима Downtrend. Поэтому было решено выбрать следующие временные периоды, изображенные на рис.3.

Рис.3 Выбранные временные периоды для тестирования.

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

  • Интервал: Для режима Uptrend 10.04.2017 — 01.02.2018. Для режима Downtrend 08.05.2014 — 13.03.2015.
  • Валютная пара: EURUSD.
  • Режим торговли: Без задержки. Представленные стратегии не относятся к высокочастотным, поэтому влияние задержек было бы очень мало.
  • Тестирование: OHLC на М1. Предварительное тестирование на реальных тиках оказалось почти неотличимо от этого режима. 
  • Начальный депозит: 1000 USD.
  • Плечо: 1:500.
  • Сервер: MetaQuotes-Demo.
  • Котировки: 5-значные.

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

Для восходящего тренда получились следующие результаты оптимизации:


Рис. 4 Результаты тестировании и оптимизации стратегии на восходящем тренде.

Для нисходящего тренда получились такие результаты:


Рис. 5 Результаты тестировании и оптимизации стратегии на нисходящем тренде.

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

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

Рис.6 Выбранный период времени для смешанного тестирования.

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

Рис.7 Результат тестирования оптимизированной трендовой стратегии на неблагоприятном участке.


По результатам тестирования данной трендовой торговой стратегии можно отметить следующие наблюдения:

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

Выбор флэтовой стратегии

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

ПараметрОписание
Используемый индикаторWilliams Percent Range
Используемый индикаторADX
ТаймфреймH1
Условия на покупкуИндикатор WPR находится в зоне перепроданности (ниже -80) и значение ADX ниже установленного порогового.
Условия на продажуИндикатор WPR находится в зоне перекупленности (выше -20) и значение ADX ниже установленного порогового.
Условия выхода  Тейк-профит/Стоп-лосс

На рис.5 представлен визуальный пример входа в рынок по этой стратегии.

Рис.6 Условия входа по флэтовой стратегии.

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

//+------------------------------------------------------------------+
//| Перечисление режимов работы                                      |
//+------------------------------------------------------------------+
enum Trend_type
  {
   UPTREND = 1,            //Buy       
   DOWNTREND,              //Sell
   BOTH                    //Both 
  };

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

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Получение данных для расчета

   if(!GetIndValue())
      return;

   if(Inp_Trend_type==1 && !Trade.IsOpenedByMagic(Inp_MagicNum1))
     {
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
     }
   else if(Inp_Trend_type==2 && !Trade.IsOpenedByMagic(Inp_MagicNum2))
     {
      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);
     }
   else if(Inp_Trend_type==3)
     {
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal() && !Trade.IsOpenedByMagic(Inp_MagicNum1))
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal() && !Trade.IsOpenedByMagic(Inp_MagicNum2))
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(wpr1[0]<-80 && adx1[0]<Inp_FlatLevel1)?true:false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(wpr2[0]>=-20 && adx2[0]<Inp_FlatLevel2)?true:false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,wpr1)<=0  ||
          CopyBuffer(InpInd_Handle2,0,0,2,wpr2)<=0 || 
          CopyBuffer(InpInd_Handle3,0,0,2,adx1)<=0  ||
          CopyBuffer(InpInd_Handle4,0,0,2,adx2)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+


Тестирование флэтовой стратегии

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

Рис.7 Выбранный интервал тестирования для флэтовой стратегии.

Общие условия тестирования выглядят такими:

Для тестирования и оптимизации будут параметры индикаторов и значения Тейк-профит и Стоп-лосс. Результаты раздельной оптимизации в режиме Buy приведены ниже в таблице.


Рис. 7 Результаты тестировании и оптимизации флэтовой стратегии в режиме Buy.

А результаты раздельной оптимизации в режиме Sell получились такими:


Рис. 8 Результаты тестировании и оптимизации флэтовой стратегии в режиме Sell.

Определив наилучшие параметры для обоих режимов с помощью раздельной оптимизации, пора проверить стратегию на неблагоприятном участке и выяснить, насколько хорошо она приживется в новых для себя условиях. В качестве эксперимента выберем временной интервал рынка, который не будет флэтовым, а тот, что уже выбирали для тестирования трендовой стратегии. Имеется ввиду интервал представленный на рис.6. Его мы использовали для смешанного тестирования трендовой стратегии в режиме Both(Uptrend+Downtrend).

Итак, результат получился следующим:

Рис. 9 Результат тестирования оптимизированной флэтовой стратегии на неблагоприятном участке.

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


Комбинированная стратегия

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

После программной реализации стратегии в первую очередь были выставлены оптимизированные параметры двух режимов трендовой стратегии и двух режимов флэтовой стратегии:

//+------------------------------------------------------------------+
//| Входные параметры эксперта                                       |
//+------------------------------------------------------------------+
input string               Inp_EaComment="Universe Strategy";           //EA Comment
input double               Inp_Lot=0.01;                                //Lot
input MarginMode           Inp_MMode=LOT;                               //MM

//--- Uptrend parameters
input string               Inp_Str_label1="===Uptrend parameters===";   //Label
input int                  Inp_MagicNum1=1111;                          //Magic number
input int                  Inp_StopLoss1=50;                            //Stop Loss(points)
input int                  Inp_TakeProfit1=55;                          //Take Profit(points)

//--- Параметры индикатора CenterOfGravityOSMA
input uint                 Period_1=9;                                  //Averaging period
input uint                 SmoothPeriod1_1=3;                           //Smoothing period1
input ENUM_MA_METHOD       MA_Method_1_1=MODE_SMA;                      //Averaging method1
input uint                 SmoothPeriod2_1=3;                           //Smoothing period2
input ENUM_MA_METHOD       MA_Method_2_1=MODE_SMA;                      //Averaging method2
input Applied_price_       AppliedPrice1=PRICE_TRENDFOLLOW1_;           //Applied price

//--- Параметры индикатора Average Speed
input int                  Inp_Bars1=1;                                 //Days
input ENUM_APPLIED_PRICE   Price1=PRICE_LOW;                            //Applied price
input double               Trend_lev1=1.6;                              //Trend Level

//--- Downtrend parameters
input string               Inp_Str_label2="===Downtrend parameters==="; //Label
input int                  Inp_MagicNum2=2222;                          //Magic number
input int                  Inp_StopLoss2=40;                            //Stop Loss(points)
input int                  Inp_TakeProfit2=70;                          //Take Profit(points)

//--- Параметры индикатора CenterOfGravityOSMA
input uint                 Period_2=15;                                 //Averaging period
input uint                 SmoothPeriod1_2=3;                           //Smoothing period1
input ENUM_MA_METHOD       MA_Method_1_2=MODE_SMA;                      //Averaging method1
input uint                 SmoothPeriod2_2=3;                           //Smoothing period2
input ENUM_MA_METHOD       MA_Method_2_2=MODE_SMA;                      //Averaging method2
input Applied_price_       AppliedPrice2=PRICE_HIGH_;                   //Applied price

//--- Параметры индикатора Average Speed
input int                  Inp_Bars2=1;                                 //Days
input ENUM_APPLIED_PRICE   Price2=PRICE_WEIGHTED;                       //Applied price
input double               Trend_lev2=1.0;                              //Trend Level


//--- Buy parameters
input string               Inp_Str_label3="===Buy parameters===";       //Label
input int                  Inp_MagicNum3=3333;                          //Magic number
input int                  Inp_StopLoss3=40;                            //Stop Loss(points)
input int                  Inp_TakeProfit3=60;                          //Take Profit(points)

//--- Параметры индикатора WPR
input int                  Inp_WPRPeriod1=11;                           //Period WPR
//--- Параметры индикатора ADX
input int                  Inp_ADXPeriod1=13;                           //Period ADX
input int                  Inp_FlatLevel1=25;                           //Flat Level ADX

//--- Sell parameters
input string               Inp_Str_label4="===Sell parameters===";      //Label
input int                  Inp_MagicNum4=4444;                          //Magic number
input int                  Inp_StopLoss4=30;                            //Stop Loss(points)
input int                  Inp_TakeProfit4=30;                          //Take Profit(points)

//--- Параметры индикатора WPR
input int                  Inp_WPRPeriod2=7;                            //Period WPR
//--- Параметры индикатора ADX
input int                  Inp_ADXPeriod2=15;                           //Period ADX
input int                  Inp_FlatLevel2=40;                           //Flat Level ADX

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

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Получение данных для расчета

   if(!GetIndValue())
      return;

//--- Открытие ордера при наличии сигнала на покупку(Трендовая стратегия)
   if(BuySignal_1() && !Trade.IsOpenedByMagic(Inp_MagicNum1))
      Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
//--- Открытие ордера при наличии сигнала на продажу(Трендовая стратегия)
   if(SellSignal_1() && !Trade.IsOpenedByMagic(Inp_MagicNum2))
      Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);

//--- Открытие ордера при наличии сигнала на покупку (Флэтовая стратегия)
   if(BuySignal_2() && !Trade.IsOpenedByMagic(Inp_MagicNum3))
      Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss3,Inp_TakeProfit3,Inp_MagicNum3,Inp_EaComment);
//--- Открытие ордера при наличии сигнала на продажу (Флэтовая стратегия)
   if(SellSignal_2() && !Trade.IsOpenedByMagic(Inp_MagicNum4))
      Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss4,Inp_TakeProfit4,Inp_MagicNum4,Inp_EaComment);
  }
//+------------------------------------------------------------------+
//| Условия на покупку (Трендовая стратегия)                         |
//+------------------------------------------------------------------+
bool BuySignal_1()
  {
   return(avr_speed1[0]>Trend_lev1 && cog1[1]<cog1[0] &&(cog1[1]<0 && cog1[0]<0))?true:false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу (Трендовая стратегия)                         |
//+------------------------------------------------------------------+
bool SellSignal_1()
  {
   return(avr_speed2[0]>Trend_lev2 && cog2[1]>cog2[0] &&(cog2[1]>0 && cog2[0]>0))?true:false;
  }
//+------------------------------------------------------------------+
//| Условия на покупку (Флэтовая стратегия)                          |
//+------------------------------------------------------------------+
bool BuySignal_2()
  {
   return(wpr1[0]<-80 && adx1[0]<Inp_FlatLevel1)?true:false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу (Флэтовая стратегия)                          |
//+------------------------------------------------------------------+
bool SellSignal_2()
  {
   return(wpr2[0]>=-20 && adx2[0]<Inp_FlatLevel2)?true:false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,cog1)<=0       ||
          CopyBuffer(InpInd_Handle2,0,0,2,cog2)<=0       ||
          CopyBuffer(InpInd_Handle3,0,0,2,avr_speed1)<=0 ||
          CopyBuffer(InpInd_Handle4,0,0,2,avr_speed2)<=0 ||
          CopyBuffer(InpInd_Handle5,0,0,2,wpr1)<=0       ||
          CopyBuffer(InpInd_Handle6,0,0,2,wpr2)<=0       ||
          CopyBuffer(InpInd_Handle7,0,0,2,adx1)<=0       ||
          CopyBuffer(InpInd_Handle8,0,0,2,adx2)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

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

  • Интервал: 01.01.2015 — 30.11.2018.
  • Валютная пара: EURUSD.
  • Режим торговли: Без задержки. Представленные стратегии не относятся к высокочастотным, поэтому влияние задержек было бы очень мало.
  • Тестирование: OHLC на М1. Предварительное тестирование на реальных тиках оказалось почти неотличимо от этого режима. 
  • Начальный депозит: 1000 USD.
  • Плечо: 1:500.
  • Сервер: MetaQuotes-Demo.
  • Котировки: 5-значные.

После тестирования получились вот такие интересные результаты:

Рис.10 Результаты тестирования комбинированной стратегии.

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


Выводы

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

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


Заключение

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

Программы, используемые в статье:

#
 Имя
Тип
Описание
1
TrendStrategy.mq5Эксперт
 Торговый эксперт, основанный на трендовой стратегии.
2
FlatStrategy.mq5Эксперт Торговый эксперт, основанный на флэтовой стратегии.
 3UniverseStrategy.mql5 Эксперт  Торговый эксперт, основанный на комбинированной стратегии.
4Trade.mqhБиблиотека Класс торговых функций.
5
average_speed.mq5Индикатор Индикатор средней скорости цены. Используется в трендовой стратегии.
6centerofgravityosma.mq5Индикатор Индикатор Центр гравитации Эллерса. Используется в трендовой стратегии.