Сравнительный анализ 10 флэтовых стратегий

Alexander Fedosov | 29 мая, 2018

Содержание

Введение

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

П‌остановка задачи при создании флэтовой стратегии

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

Рис. 1. Пример бокового движения (флэта).

Задача №1. Определение наличия флэта.

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

Задача №2. Цели открытой позиции.

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

Рис. 2. Торговля при отскоке цены от границ канала.

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

Флэтовые стратегии

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

‌С‌тратегия №1: Индикатор Envelopes с фильтром в виде MFI

 Для определения границ канала будет применяться Envelopes, а сигнал отфильтрует MFI.

Параметр Описание
Используемый индикатор Envelopes
Используемый индикатор MFI
Таймфрейм H1
Условия на покупку Достижение ценой нижней границы канала и нахождение MFI в зоне перепроданности (ниже 20)
Условия на продажу Достижение ценой верхней границы канала и нахождение MFI в зоне перекупленности (выше 80)
Условия выхода   Достижение противоположной границы канала

На рис.3 показаны условия входа в рынок по стратегии №1.

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

Код торгового советника по этой стратегии выглядит так:

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(mfi[0]<20 && env_low[0]>close[0])
     {
      tp=env_high[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(mfi[0]>80 && env_high[0]<close[0])
     {
      tp=env_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,mfi)<=0  ||
          CopyBuffer(InpInd_Handle2,1,0,2,env_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,env_high)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Тейк-профит устанавливается автоматически, исходя из заданных условий, а стоп-лосс — вручную, в зависимости от таймфрейма.

Стратегия №2: Индикатор Bollinger Bands и две Moving Average

Для определения границ канала используется индикатор Bollinger Bands, а в качестве фильтра — положение медленной и быстрой МА относительно друг друга.

Параметр Описание
Используемый индикатор Bollinger Bands
Используемый индикатор Moving Average
Таймфрейм H1
Условия на покупку Достижение ценой нижней границы канала, быстрая МА выше медленной
Условия на продажу Достижение ценой верхней границы канала, быстрая МА ниже медленной
Условия выхода   Достижение противоположной границы канала

На рис.4 показаны условия входа в рынок. Период двух SMA по умолчанию небольшой: 4 и 8. В советнике можно настраивать периоды и методы сглаживания, изменяя таким образом чувствительность фильтрации сигнала от Bollinger Bands.

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

За исключением условий входа в рынок, стратегия №2 очень похожа на стратегию №1. 

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(ma_slow[0]>ma_fast[0] && bb_low[0]>close[0])
     {
      tp=bb_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(ma_slow[0]<ma_fast[0] && bb_up[0]<close[0])
     {
      tp=bb_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,1,0,2,bb_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,bb_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,ma_slow)<=0 ||
          CopyBuffer(InpInd_Handle3,0,0,2,ma_fast)<=0 ||
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Стратегия №3. WSO & WRO Channel и Fractal Dimension Ehlers

Основным сигнальным индикатором станет WSO & WRO Channel — канал, построенный на основе значений двух осцилляторов: WSO (Widner Support Oscillator) и WRO (Widner Resistance Oscillator). Идея индикатора основана на статье Мэла Уиднера  "Automated Support And Resistance". В качестве фильтра возьмем индикатор фрактальной размерности, описанный в статье Джона Эйлерса и Рика Уэйса "Fractal Dimension As A Market Mode Sensor". 

Параметр Описание
Используемый индикатор WSO & WRO Channel
Используемый индикатор Fractal Dimension Ehlers
Таймфрейм Любой
Условия на покупку Достижение ценой нижней границы канала и значение Fractal Dimension ниже целевого порога
Условия на продажу Достижение ценой верхней границы канала и значение Fractal Dimension ниже целевого порога
Условия выхода   Достижение противоположной границы канала

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


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

Код советника по этой стратегии выглядит вот так:

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(wwc_low[0]>close[0] && fdi[0]<Inp_FdiThreshold)
     {
      tp=wwc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(wwc_up[0]<close[0] && fdi[0]<Inp_FdiThreshold)
     {
      tp=wwc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,3,0,2,wwc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,wwc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,fdi)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Стратегия №4. Индикатор Percentage Crossover Channel и TrendRange в качестве фильтра

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

Параметр Описание
Используемый индикатор Percentage Crossover Channel
Используемый индикатор Trend Range
Таймфрейм Любой
Условия на покупку Достижение ценой нижней границы канала и цвет гистограммы Trend Range серого цвета
Условия на продажу Достижение ценой верхней границы канала и цвет гистограммы Trend Range серого цвета
Условия выхода   Достижение противоположной границы канала

Условия входа в рынок показаны на рис.6. Работа индикатора Percentage Crossover имеет некоторые особенности. Параметр Percent, отражающий предельную дистанцию, по пробою которой начинается построение нового уровня, зависит от таймфрейма. Чем он меньше, тем меньший процент нужно устанавливать. К примеру, на часовом таймфрейме рекомендуемое значение 20 — 30. Более высокие значения приведут к излишней избирательности индикатора.

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

Стратегия реализуется в коде так:

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(pcc_low[0]>close[0] && tr_flat[0]>tr_range[0])
     {
      tp=pcc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(pcc_up[0]<close[0] && tr_flat[0]>tr_range[0])
     {
      tp=pcc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,pcc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,pcc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,1,0,2,tr_flat)<=0 ||
          CopyBuffer(InpInd_Handle2,2,0,2,tr_range)<=0 ||
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Стратегия №5. Индикатор Price Channel и RBVI в качестве фильтра

Индикатор Price Channel строит канал, верхние и нижние границы которого определяются максимумом и минимумом цены за период. Фильтровать ложные сигналы будет RBVI, определяющий флэт на рынке. 

Параметр Описание
Используемый индикатор Price Channel
Используемый индикатор RBVI
Таймфрейм Любой
Условия на покупку Достижение ценой нижней границы канала и значение RBVI ниже порогового для флэта
Условия на продажу Достижение ценой верхней границы канала и значение RBVI ниже порогового для флэта
Условия выхода   Достижение противоположной границы канала

На рис.7 представлены условия входа. Пороговое значение индикатора RBVI — 40. Но в параметрах советника можно будет изменить это значение.

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

Реализация этой стратегии в коде выглядит так:

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;

      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(pc_low[0]>close[0] && rbvi[0]<=Inp_level)
     {
      tp=pc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(pc_up[0]<close[0] && rbvi[0]<=Inp_level)
     {
      tp=pc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,pc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,1,0,2,pc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,rbvi)<=0 ||
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Стратегия №6. Индикатор Williams Percent Range и ADX в качестве фильтра

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

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

Как видно на рис.8, зона флэта на индикаторе ADX по умолчанию установлена на значение 30. Но в коде советника предусмотрена возможность его пользовательской настройки.

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

На листинге ниже приведена реализации этой стратегии. Здесь переменная Inp_FlatLevel отвечает за пороговое значение ADX, о котором говорилось выше.

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;

      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(wpr[0]<-80 && adx[0]<Inp_FlatLevel)?true:false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(wpr[0]>=-20 && adx[0]<Inp_FlatLevel)?true:false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,wpr)<=0  ||
          CopyBuffer(InpInd_Handle2,0,0,2,adx)<=0)?false:true;
  }
//+------------------------------------------------------------------+

Стратегия №7. Модифицированный канал Келтнера и индикатор Magic Trend в качестве фильтра

Здесь отскок цены от границ канала Келтнера будем проверять с помощью трендового индикатора Magic Trend в моменты, когда он будет идентифицировать флэт.

Параметр Описание
Используемый индикатор Модифицированный канал Келтнера
Используемый индикатор Magic Trend
Таймфрейм Любой
Условия на покупку Достижение ценой нижней границы канала и серый цвет линии Magic Trend
Условия на продажу Достижение ценой верхней границы канала и серый цвет линии Magic Trend
Условия выхода   Достижение противоположной границы канала

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

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

В коде это учитывается в функциях, проверяющих условия на продажу/покупку:

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;

      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(kc_low[0]>close[0] && mt[0]==mt[1])
     {
      tp=kc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(kc_up[0]<close[0] && mt[0]==mt[1])
     {
      tp=kc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,kc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,kc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,mt)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Стратегия №8. Канал Дончиана с подтверждением индикатором Trinity Impulse

В этой стратегии попробуем отловить моменты отскока от границ канала Дончиана, подтвердая его импульсным индикатором Trinity Impulse в состоянии бокового движения. 

Параметр Описание
Используемый индикатор Канал Дончиана
Используемый индикатор Trinity Impulse
Таймфрейм Младшие таймфреймы
Условия на покупку Достижение ценой нижней границы канала и нулевое значение Trinity Impulse
Условия на продажу Достижение ценой верхней границы канала и нулевое значение Trinity Impulse
Условия выхода   Достижение противоположной границы канала

Входы в рынок представлены на рис.10. Стратегию нежелательно использовать на старших таймфреймах, потому что фильтр Trinity Impusle показывает пилообразное поведение, и зоны флэта отображаются с задержкой. При этом их ширина очень мала, а это делает стратегию слишком избирательной. Оптимально использовать 5 — 30-минутные таймфреймы.

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

Реализация торгового советника по стратегии:.

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;
         
      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(dc_low[0]>close[0] && ti[0]==0)
     {
      tp=dc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(dc_up[0]<close[0] && ti[0]==0)
     {
      tp=dc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,dc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,1,0,2,dc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,ti)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Стратегия №9. Индикатор ATR Channel и CCI Color Levels в качестве фильтра

ATR Channel основан на отклонениях индикатора ATR от скользящей средней. CCI Color Levels — это CCI, отображающийся в виде гистограммы пороговых значений, которые являются признаками ценового движения. Мы же будем использовать его как фильтр канала во флэтовом состоянии (когда CCI находится в диапазоне между пороговыми значениями).

Параметр Описание
Используемый индикатор ATR Channel
Используемый индикатор CCI Color Levels
Таймфрейм Любой
Условия на покупку Достижение ценой нижней границы канала и значение CCI Color Levels находится в диапазоне между пороговыми значениями
Условия на продажу Достижение ценой верхней границы канала и значение CCI Color Levels находится в диапазоне между пороговыми значениями
Условия выхода   Достижение противоположной границы канала

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


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

Код советника по этой стратегии:

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;

      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(atr_low[0]>close[0] && cci[0]<Inp_CCI_LevelUP && cci[0]>Inp_CCI_LevelDOWN)
     {
      tp=atr_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(atr_up[0]<close[0] && cci[0]<Inp_CCI_LevelUP && cci[0]>Inp_CCI_LevelDOWN)
     {
      tp=atr_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,1,0,2,atr_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,atr_low)<=0 || 
          CopyBuffer(InpInd_Handle2,2,0,2,cci)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

Стратегия №10. RSI в виде гистограммы и индикатор Flat в качестве фильтра

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

Параметр Описание
Используемый индикатор RSI_Histogram
Используемый индикатор Flat
Таймфрейм любой
Условия на покупку Нахождение RSI в зоне перепроданности(ниже порогового значения) и Flat находится в зоне флэта.
Условия на продажу Нахождение RSI в зоне перекупленности(выше порогового значения) и Flat находится в зоне флэта.
Условия выхода   Тейк-профит/Стоп-лосс

На рис.12 наглядно показаны точки входа. Отображение RSI в виде гистограммы делает более удобным отслеживание зон перекупленности/перепроданности, а также флэтовой зоны фильтра Flat.

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

Реализация торгового советника по стратегии представлена в листинге ниже.

void OnTick()
  {
//--- Проверка ранее открытых экcпертом ордеров
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;

      //--- Открытие ордера при наличии сигнала на покупку
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment);

      //--- Открытие ордера при наличии сигнала на продажу
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| Условия на покупку                                               |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(rsi[0]<Inp_LowLevel && fl[0]<Inp_FLowLevel)?true:false;
  }
//+------------------------------------------------------------------+
//| Условия на продажу                                               |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(rsi[0]>Inp_HighLevel && fl[0]<Inp_FLowLevel)?true:false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,rsi)<=0  ||
          CopyBuffer(InpInd_Handle2,0,0,2,fl)<=0)?false:true;
  }
//+------------------------------------------------------------------+

Тестирование

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

Т‌ест Стратегии №1 (Индикатор Envelopes с фильтром в виде MFI)

Предустановка:

input int                  Inp_StopLoss=500;                            //Stop Loss(points)

//--- Параметры индикатора MFI
input ENUM_APPLIED_VOLUME  Inp_applied_volume=VOLUME_TICK;              // тип объема MFI
input int                  Inp_MFI_period=10;                           // период MFI
//--- Параметры индикатора Envelopes
input int                  Inp_ma_period=10;                            // период скользящей Envelopes 
input ENUM_MA_METHOD       Inp_ma_method=MODE_SMA;                      // тип сглаживания Envelopes
input double               Inp_deviation=0.1;                           // отклонение границ от скользящей Envelopes

Результат тестирования:

Рис. 13. Результаты тестирования флэтовой стратегии №1.

Т‌ест Стратегии №2 (Индикатор Bollinger Bands и две Moving Average)

Предустановка:

input int                  Inp_StopLoss=450;                            //Stop Loss(points)

//--- Параметры индикатора Bollinger Bands
input int                  Inp_BBPeriod=14;                             //BB период
input double               Inp_deviation=2.0;                           //Отклонение
//--- Параметры индикатора MA slow
input int                  Inp_ma_period1=12;                           //Период MA slow
input ENUM_MA_METHOD       Inp_ma_method1=MODE_SMMA;                    //Метод сглаживания MA slow
//--- Параметры индикатора MA fast
input int                  Inp_ma_period2=2;                            //Период MA fast
input ENUM_MA_METHOD       Inp_ma_method2=MODE_LWMA;                    //Метод сглаживания MA fast

Результат тестирования:

Рис. 14. Результаты тестирования флэтовой стратегии №2.

Т‌ест Стратегии №3 (WSO & WRO Channel с фильтром в виде Fractal Dimension Ehlers)

Предустановка:

input int                  Inp_StopLoss=500;                            //Stop Loss(points)

//--- Параметры индикатора WSO & WRO Channel
input int                  Inp_WsoWroPeriod=16;                         //Период Wso & Wro Channel
//--- Параметры индикатора Fractal Dimension Ehlers
input int                  Inp_FdiPeriod    =  18;                      //Период Fractal dimension 
input double               Inp_FdiThreshold =  1.4;                     //Порог Fractal dimension 
input ENUM_APPLIED_PRICE   Inp_Price        = PRICE_CLOSE;              //Применяемая цена 

Результат тестирования:

Рис. 15. Результаты тестирования флэтовой стратегии №3.

Т‌ест Стратегии №4 (Индикатор Percentage Crossover Channel и TrendRange в качестве фильтра)

Предустановка:

input int                  Inp_StopLoss=500;                            //Stop Loss(points)

//--- Параметры индикатора Percentage_Crossover_Channel
input double               Inp_Percent=26.0;                            //Процент предельной дистанции
input ENUM_APPLIED_PRICE   Inp_Price=PRICE_CLOSE;                       //Применяемая цена
//--- Параметры индикатора Trend Range
input uint                 Inp_PeriodTR    =  14;                       //Период Trend Range
input ENUM_MA_METHOD       Inp_Method      =  MODE_EMA;                 //Метод сглаживания
input double               Inp_Deviation   =  1.0;                      //Отклонение

Результат тестирования:

Рис.16. Результаты тестирования флэтовой стратегии №4.

Т‌ест Стратегии №5 (Индикатор Price Channel и RBVI в качестве фильтра)

Предустановка:

input int                  Inp_StopLoss=450;                            //Stop Loss(points)

//--- Параметры индикатора Price Channel
input int                  Inp_ChannelPeriod=12;                        //Period
//--- Параметры индикатора RBVI
input int                  Inp_RBVIPeriod=5;                            //период RBVI
input ENUM_APPLIED_VOLUME  Inp_VolumeType=VOLUME_TICK;                  //объём
input double               Inp_level=40;                                //уровень флэта

Результат тестирования:

Рис. 17. Результаты тестирования флэтовой стратегии №5.

Т‌ест Стратегии №6 (Индикатор Williams Percent Range и ADX в качестве фильтра)

Предустановка:

input int                  Inp_StopLoss=50;                             //Stop Loss(points)
input int                  Inp_TakeProfit=50;                           //Take Profit(points)

//--- Параметры индикатора WPR
input int                  Inp_WPRPeriod=10;                            //Period WPR
//--- Параметры индикатора ADX
input int                  Inp_ADXPeriod=14;                            //Period ADX
input int                  Inp_FlatLevel=40;                            //Flat Level ADX

Результат тестирования:

Рис. 18. Результаты тестирования флэтовой стратегии №6.

Т‌ест Стратегии №7 (Модифицированный канал Келтнера и индикатор Magic Trend в качестве фильтра)

Предустановка:

input int                     Inp_SmoothCenter      =  11;              // Number of the periods to smooth the center line
input int                     Inp_SmoothDeviation   =  12;              // Number of periods to smooth deviation
input double                  Inp_F                 =  1.0;             // Factor which is used to apply the deviation
input ENUM_APPLIED_PRICE      Inp_AppliedPrice      =  PRICE_CLOSE;     // The center line applied price:
input ENUM_MA_METHOD          Inp_MethodSmoothing   =  MODE_SMA;        // The center line smoothing method
input ENUM_METHOD_VARIATION   Inp_MethodVariation   =  METHOD_HL;       // Variation Method
//--- Параметры индикатора Magic Trend
input uint                    Inp_PeriodCCI   =  60;                    // CCI period
input uint                    Inp_PeriodATR   =  5;                     // ATR period

Результат тестирования:

Рис. 19. Результаты тестирования флэтовой стратегии №7.

Т‌ест Стратегии №8 (Канал Дончиана с подтверждением индикатором Trinity Impulse)

Предустановка:

input int                  Inp_StopLoss=500;                            //Stop Loss(points)

//--- Параметры индикатора канала Дончиана
input int                  Inp_ChannelPeriod=12;                        //Doncian period
//--- Параметры индикатора Trinity Impulse
input int                  Inp_Period= 5;                               //Indicator period
input int                  Inp_Level= 34;                               //Smoothing level
input ENUM_MA_METHOD       Inp_Type=MODE_LWMA;                          //Averaging type
input ENUM_APPLIED_PRICE   Inp_Price=PRICE_WEIGHTED;                    //Price
input ENUM_APPLIED_VOLUME  Inp_Volume=VOLUME_TICK;                      //Volume type

Результат тестирования:

Рис. 20. Результаты тестирования флэтовой стратегии №8.

Т‌ест Стратегии №9 (Индикатор ATR Channel и CCI Color Levels в качестве фильтра)

Предустановка:

//--- Параметры индикатора ATR Channel
input ENUM_MA_METHOD       Inp_MA_Method=MODE_SMA;                      //MA smoothing method
input uint                 Inp_MA_Period=10;                            //MA period
input uint                 Inp_ATR_Period=12;                           //ATR period
input double               Inp_Factor=1.5;                              //Number of deviations
input ENUM_APPLIED_PRICE   Inp_IPC=PRICE_LOW;                           //Applied price
input int                  Inp_Shift=0;                                 //Horizontal shift of the indicator in bars
//--- Параметры индикатора CCI Color Levels
input int                  Inp_CCI_ma_period = 14;                      // Averaging period 
input double               Inp_CCI_LevelUP   = 90;                      // Level UP
input double               Inp_CCI_LevelDOWN =-90;                      // Level DOWN

Результат тестирования:

Рис. 21. Результаты тестирования флэтовой стратегии №9.

Т‌ест Стратегии №10 (RSI в виде гистограммы и индикатор Flat в качестве фильтра)

Предустановка:

//--- Параметры индикатора RSI Histogram
input uint                 Inp_RSIPeriod=12;                            // период индикатора
input ENUM_APPLIED_PRICE   Inp_RSIPrice=PRICE_CLOSE;                    // цена
input uint                 Inp_HighLevel=60;                            // уровень перекупленности
input uint                 Inp_LowLevel=40;                             // уровень перепроданности
input int                  Inp_Shift=0;                                 // сдвиг индикатора по горизонтали в барах
//--- Параметры индикатора Flat
input uint                 Inp_Smooth=10;                               // Smoothing period
input ENUM_MA_METHOD       Inp_ma_method=MODE_SMA;                      // Smoothing type
input ENUM_APPLIED_PRICE   Inp_applied_price=PRICE_CLOSE;               // Price type
input uint                 Inp_HLRef=100;
input int                  Inp_FShift=0;                                // Horizontal shift of the indicator in bars
input uint                 Inp_ExtraHighLevel=70;                       // Maximum trend level
input uint                 Inp_FHighLevel=50;                           // Strong trend level
input uint                 Inp_FLowLevel=30;                            // Weak trend level

Результат тестирования:

Рис. 22. Результаты тестирования флэтовой стратегии №10.

Выводы

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

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

Заключение

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

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

#
 Имя
Тип
Описание
1
Strategy_1.mq5
Эксперт
 Стратегия №1. Индикатор Envelopes с фильтром в виде MFI.
2
Strategy_2.mql5
Эксперт
 Стратегия №2. Индикатор Bollinger Bands и две Moving Average.
3
Strategy_3.mq5
Эксперт  Стратегия №3. WSO & WRO Channel с фильтром в виде Fractal Dimension Ehlers.
4
Strategy_4.mq5
Эксперт
 Стратегия №4. Индикатор Percentage Crossover Channel и TrendRange в качестве фильтра. 
5
Strategy_5.mq5 Эксперт  Стратегия №5. Индикатор Price Channel и RBVI в качестве фильтра.
6
Strategy_6.mq5
Эксперт
 Стратегия №6. Индикатор Williams Percent Range и ADX в качестве фильтра.
7 Strategy_7.mq5 
Эксперт
 Стратегия №7. Модифицированный канал Келтнера и индикатор Magic Trend в качестве фильтра.
 8 Strategy_8.mq5 Эксперт  Стратегия №8. Канал Дончиана с подтверждением индикатором Trinity Impulse.
 9 Strategy_9.mq5 Эксперт  Стратегия №9. Индикатор ATR Channel и CCI Color Levels в качестве фильтра.
 10 Strategy_10.mq5 Эксперт  Стратегия №10. RSI в виде гистограммы и индикатор Flat в качестве фильтра. 
 11 Trade.mqh Библиотека  Класс торговых функций.
 13 wwc.mq5 Индикатор  Используется в Стратегии №3.
 14 fdi.mq5 Индикатор  Используется в Стратегии №3.
 15 pcc.mq5 Индикатор  Используется в Стратегии №4.
 16 trend_range.mq5  Индикатор  Используется в Стратегии №4.
 17 price_channel.mq5 Индикатор  Используется в Стратегии №5.
 18 rbvi.mq5 Индикатор  Используется в Стратегии №5.
 19 customizable _keltner.mq5 Индикатор  Используется в Стратегии №7.
 20 magic_trend.mq5 Индикатор  Используется в Стратегии №7.
 21 donchian_channel.mq5 Индикатор  Используется в Стратегии №8.
 22 trinity_impulse.mq5 Индикатор  Используется в Стратегии №8.
 23 atr_channel.mq5 Индикатор   Используется в Стратегии №9.
 24 cci_color_levels.mq5 Индикатор  Используется в Стратегии №9.
 25 rsi_histogram.mq5 Индикатор  Используется в Стратегии №10.
 26 flat.mq5 Индикатор  Используется в Стратегии №10.