preview
Оптимизация и тестирование торговых стратегий (Часть 1): Взгляд на "Red Dragon H4", "BOLT", "YinYang", и "Statistics SAR"

Оптимизация и тестирование торговых стратегий (Часть 1): Взгляд на "Red Dragon H4", "BOLT", "YinYang", и "Statistics SAR"

MetaTrader 5Торговые системы | 23 февраля 2024, 14:30
1 124 0
Roman Poshtar
Roman Poshtar

Введение

Добрый день, уважаемые пользователи, сообщества MQL5. Так как я постоянно занимаюсь, разработкой разного рода торговых систем сегодня хочу поделиться с Вами несколькими из них по стратегиям "Red Dragon H4", "BOLT", "YinYang" и "Statistics SAR". Данные стратегии были найдены на просторах интернета. Привлекли мое внимание своей простотой и использованием в терминале MetaTrader 5. Некоторые позиционируются как классические трендовые стратегии, некоторые как разворотные контртрендовые. Сразу хотелось бы сказать, что итоговый результат разработки советников по данным стратегиям мне неизвестен. Данная статья пишется вместе с разработкой, что придает ей некой загадочности. Тем самым я хотел бы начать новую серию своих статей и постоянно делиться с вами своими достижениями.


Стратегия «Red Dragon H4»

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

Также немаловажным фактором мотивации написания торгового робота сыграл факт «свежести» системы. Стратегию начали использовать в 2022-2023 годах. Изначального применения на самых популярных торговых парах EURUSD и GBPUSD, а также тонкий намек на возможность применения на других валютных парах. То есть стратегия позиционируется как мультивалютная и нуждается в проверке этого утверждения. И так начнем.

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


Рынок, валютная пара, временной интервал:

  • Валютная пара – мультивалютная.
  • Временной интервал – Н4.
  • Рынок - FOREX


Используемые индикаторы:

  • Экспоненциальная скользящая средняя с периодом 120 - EMA120.
  • Exponential Moving Average 14 - EMA14, построенная по ценам Low.
  • Такая же EMA14, построенная по ценам High.
  • Индикатор Parabolic SAR с шагом 0,01 и с максимумом 0,2.
  • Индикатор Accelerator Oscillator.


Условия для покупок по стратегии «Red Dragon H4»:

  1. На закрытии очередной предыдущей свечи индикатор Parabolic SAR перескакивает сверху-вниз и оказывается под текущей свечей.
  2. Именно эта же предыдущая свеча должна быть закрыта выше EMA14 (High).
  3. Так же эта свеча должна быть закрыта выше ЕМА120.
  4. Индикатор Accelerator Oscillator на предыдущей свече находится выше своей нулевой отметки.
  5. Если все условия выполнены, то на открытии следующей свечи заключается сделка на покупку.
  6. Stop Loss устанавливается за ЕМА14 (Low). Если минимум сигнальной свечи находится ниже, то Stop Loss следует устанавливать именно под нее. То есть на Low предыдущей свечи.
  7. После прохождения цены в положительной зоне расстояния равного размеру Stop Loss сделку необходимо перевести в безубыток.
  8. Take Profit устанавливается в размере, двукратно превышающем размер Stop Loss .
  9. Новую позицию в ту же сторону можно открывать, если предыдущая позиция уже переведена в безубыток.

Ниже приведу пару скриншотов с входами на покупку:

Buy1


Buy2


Условия для продаж по стратегии «Red Dragon H4»:

  1. На закрытии очередной предыдущей свечи индикатор Parabolic SAR перескакивает снизу-вверх и располагается над текущей свечей.
  2. Именно эта же предыдущая свеча должна быть закрыта ниже EMA14 (Low).
  3. Так же эта свеча должна быть закрыта ниже ЕМА120.
  4. Индикатор Accelerator Oscillator на предыдущей свече находится ниже своей нулевой отметки.
  5. Если все условия выполнены, то на открытии следующей свечи заключается сделка на продажу.
  6. Stop Loss устанавливается за ЕМА14 (High). Если максимум сигнальной свечи находится выше, то Stop Loss следует устанавливать именно над ней. То есть на High предыдущей свечи.
  7. После прохождения цены в положительной зоне расстояния равного размеру Stop Loss сделку необходимо перевести в безубыток.
  8. Take Profit устанавливается в размере, двукратно превышающем размер Stop Loss, как и в случае с покупками.
  9. Новую позицию в ту же сторону можно открывать, если предыдущая позиция уже переведена в безубыток, как и в случае с покупками.

Ниже приведу пару скриншотов с входами на продажу:

Sell1


Sell2


Пишем код советника по стратегии «Red Dragon H4»:

Для проведения дальнейшей оптимизации выводим параметры индикаторов и множителя Take Profit в переменные:

input group "+++ Indicators +++"
input int Big_MA = 120;
input int Small_MA = 14;
input ENUM_MA_METHOD Method_MA = MODE_EMA;
input double Step_SAR = 0.01;
input double Maximum_SAR = 0.2;

input group "+++ Take profit +++"
input double StoplossMultiplierForTakeprofit = 2.0;

Получаем хендлы и значения наших индикаторов:

   handle_In1=iMA(symbolS1.Name(),PERIOD_CURRENT,Big_MA,0,Method_MA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2=iMA(symbolS1.Name(),PERIOD_CURRENT,Small_MA,0,Method_MA,PRICE_HIGH);
//--- if the handle is not created
   if(handle_In2==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3=iMA(symbolS1.Name(),PERIOD_CURRENT,Small_MA,0,Method_MA,PRICE_LOW);
//--- if the handle is not created
   if(handle_In3==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In4=iSAR(symbolS1.Name(),PERIOD_CURRENT,Step_SAR,Maximum_SAR);
//--- if the handle is not created
   if(handle_In4==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In5=iAO(symbolS1.Name(),PERIOD_CURRENT);
//--- if the handle is not created
   if(handle_In5==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---


         //--- get data from the three buffers of the MA indicator
         ArraySetAsSeries(ind_In1S1,true);
         if(!iGetArray(handle_In1,0,0,5,ind_In1S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the MA indicator
         ArraySetAsSeries(ind_In2S1,true);
         if(!iGetArray(handle_In2,0,0,5,ind_In2S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the MA indicator
         ArraySetAsSeries(ind_In3S1,true);
         if(!iGetArray(handle_In3,0,0,5,ind_In3S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the SAR indicator
         ArraySetAsSeries(ind_In4S1,true);
         if(!iGetArray(handle_In4,0,0,5,ind_In4S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the AO indicator
         ArraySetAsSeries(ind_In5S1,true);
         if(!iGetArray(handle_In5,0,0,5,ind_In5S1))
           {
            return;
           }
         //---

Основной блок логики советника:

         //Sell++++++++++++++++++++++++++++++++++++++++++++++++

         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (SpreadS1<=MaxSpread) && (Triger_Sell!=iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[1]>iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[2]<iClose(symbolS1.Name(),PERIOD_CURRENT,2)) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In1S1[1]) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In3S1[1]) && (ind_In5S1[1]<0))
           {
            double sl = 0;
            double tp = 0;
            if(iHigh(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1])
              {
               sl = iHigh(symbolS1.Name(),PERIOD_CURRENT,1);
              }
            else
              {
               sl = ind_In2S1[1];
              }
            tp = BidS1-((sl-AskS1)*StoplossMultiplierForTakeprofit);
            OpenSell(symbolS1.Name(), LotsXSell, tp, sl, EAComment);
            Triger_Sell=iClose(symbolS1.Name(),PERIOD_CURRENT,1);
           }

         //Buy++++++++++++++++++++++++++++++++++++++++++++++++

         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (SpreadS1<=MaxSpread) && (Triger_Buy!=iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[1]<iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[2]>iClose(symbolS1.Name(),PERIOD_CURRENT,2)) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In1S1[1]) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) && (ind_In5S1[1]>0))
           {
            double sl = 0;
            double tp = 0;
            if(iLow(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In3S1[1])
              {
               sl = iLow(symbolS1.Name(),PERIOD_CURRENT,1);
              }
            else
              {
               sl = ind_In3S1[1];
              }
            tp = AskS1+((BidS1-sl)*StoplossMultiplierForTakeprofit);
            OpenBuy(symbolS1.Name(), LotsXBuy, tp, sl, EAComment);
            Triger_Buy=iClose(symbolS1.Name(),PERIOD_CURRENT,1);
           }

Следует пояснить некоторые моменты, а именно:

  • параметр StoplossMultiplierForTakeprofit отвечает за умножение Take Profit относительно Stop Loss;
  • Triger_Sell и Triger_Buy используются для запоминания цены открытия свечи и в дальнейшем проверяются в условии открытия позиции. Это необходимо для предотвращения получения нескольких входов на одном сигнале;
  • проверки if(iHigh(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) и if(iLow(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In3S1[1]) используются для определения расположения Stop Loss описанного в условиях стратегии.


Тестирование и оптимизация советника по стратегии «Red Dragon H4»:

Проведем тестирование с параметрами по умолчанию по валютных парах EURUSD и GBPUSD в период времени с 2020.02.13 по 2023.02.13 на разных таймфреймах:

Test1

EURUSD H1 StoplossMultiplierForTakeprofit = 1.0

Test2

EURUSD H4 StoplossMultiplierForTakeprofit = 1.0

Test3

EURUSD H1 StoplossMultiplierForTakeprofit = 2.0

Test4

EURUSD H4 StoplossMultiplierForTakeprofit = 2.0

Test5

GBPUSD H1 StoplossMultiplierForTakeprofit = 1.0

Test6

GBPUSD H4 StoplossMultiplierForTakeprofit = 1.0

Test7

GBPUSD H1 StoplossMultiplierForTakeprofit = 2.0

Test8

GBPUSD H4 StoplossMultiplierForTakeprofit = 2.0

Как видно из тестов мы получили неоднозначные результаты. Проведем оптимизацию с параметрами указанными на скриншоте ниже:

Opt1

Результаты оптимизации:

Opt2

Результат тестирования лучшего результата оптимизации:

OptR

 

Заключение по стратегии «Red Dragon H4»:

Как видно из проведенной работы стратегия выдает не очень хорошие результаты и обладает низким профит фактором даже при соотношении 1 к 2 или 1 к 3 Stop Loss к Take Profit. Интересной особенностью является получение сигнала именно в момент переворота индикатора Parabolic SAR. Возможно, это влияет на частоту сделок. Также на результаты может влиять постоянно плавающие значения Stop Loss и соответственно Take Profit.


Стратегия «BOLT»

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


Рынок, валютная пара, временной интервал:

  • Валютная пара – мультивалютная.
  • Временной интервал – Н1.
  • Рынок - FOREX


Используемые индикаторы:

  • Индикатор Bollinger Bands с параметрами Период для расчета средней линии = 30, смещение индикатора по горизонтали = 0, количество стандартных отклонений = 3.
  • Индикатор HLC Trend. Данный индикатор не входит в состав стандартных индикаторов поставляемых с терминалом MetaTrader 5 и его необходимо установить отдельно. Параметры High Price Period = 34, Low Price Period = 13, Close Price Period = 5, Moving Average Method = MODE_SMA.


Условия для продаж по стратегии «BOLT»:

  1. На закрытии очередной предыдущей свечи цена коснулась верхней границы индикатора Bollinger Bands. Таким образом, мы получаем первый сигнал на открытие первого ордера.
  2. После получения первого сигнала ждем схождения индикатора HLC Trend на предыдущем баре относительно пред предыдущего.
  3. Зеленая линия индикатора HLC Trend выше красной линии.
  4. Условием на открытие дополнительного ордера является сохранение условий 1 и 2 а также нахождение цены выше цены открытия предыдущего ордера на продажу. Этот параметр можно менять в настройках советника. Параметр StepOrdersPips.
  5. Закрытие всех позиций на продажу происходит после пересечения красной и зеленой линии индикатора HLC Trend. Зеленая линия индикатора ниже красной линии.
  6. Страховочный Stop Loss используется при желании.

Ниже приведу пару скриншотов с входами на продажу:

Sell1

Sell2


Условия для покупок по стратегии «BOLT»:

  1. На закрытии очередной предыдущей свечи цена коснулась нижней границы индикатора Bollinger Bands. Таким образом, мы получаем первый сигнал на открытие первого ордера.
  2. После получения первого сигнала ждем схождения индикатора HLC Trend на предыдущем баре относительно пред предыдущего.
  3. Зеленая линия индикатора HLC Trend ниже красной линии.
  4. Условием на открытие дополнительного ордера является сохранение условий 1 и 2 а также нахождение цены выше цены открытия предыдущего ордера на продажу. Этот параметр можно менять в настройках советника. Параметр StepOrdersPips.
  5. Закрытие всех позиций на покупку происходит после пересечения красной и зеленой линии индикатора HLC Trend. Зеленая линия индикатора выше красной линии.
  6. Страховочный Stop Loss используется при желании.

Ниже приведу пару скриншотов с входами на покупку:

Buy1


Buy2


Пишем код советника по стратегии «BOLT»:

Для проведения дальнейшей оптимизации выводим параметры индикаторов, шага сетки и Stop Loss в переменные:

input group "+++ Indicators +++"
input int BandsPeriod = 30;
input double BandsDeviation = 3.0;
input int HLCTrend_high_period = 34;
input int HLCTrend_low_period = 13;
input int HLCTrend_close_period = 5;

input group "+++ Grid +++"
input int StepOrdersPips = 200;

input group "+++ Stop loss +++"
input int StopLoss = 9000;

Получаем хендлы и значения наших индикаторов:

   handle_In1=iBands(symbolS1.Name(),PERIOD_CURRENT,BandsPeriod,0,BandsDeviation,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2=iCustom(symbolS1.Name(),PERIOD_CURRENT,"HLC Trend",HLCTrend_high_period,HLCTrend_low_period,HLCTrend_close_period,MODE_SMA);
//--- if the handle is not created
   if(handle_In2==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

         //--- get data from the three buffers of the BB indicator
         ArraySetAsSeries(ind_In1S1,true);
         if(!iGetArray(handle_In1,1,0,5,ind_In1S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the BB indicator
         ArraySetAsSeries(ind_In2S1,true);
         if(!iGetArray(handle_In1,2,0,5,ind_In2S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the HLC Trend indicator
         ArraySetAsSeries(ind_In3S1,true);
         if(!iGetArray(handle_In2,0,0,5,ind_In3S1))
           {
            return;
           }
         //---
      
         //--- get data from the three buffers of the HLC Trend indicator
         ArraySetAsSeries(ind_In4S1,true);
         if(!iGetArray(handle_In2,1,0,5,ind_In4S1))
           {
            return;
           }
         //---

Основной блок логики советника:

         //Sell++++++++++++++++++++++++++++++++++++++++++++++++
         
         if ((iHigh(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In1S1[1]) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0)){Triger_Sell=true;}

         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (SpreadS1<=MaxSpread) && (Triger_Sell==true) && (ind_In3S1[1]>ind_In4S1[1]) && (ind_In3S1[1]<ind_In3S1[2]) && (ind_In4S1[1]>ind_In4S1[2]))
           {
            OpenSell(symbolS1.Name(), LotsXSell, 0, StopLoss, EAComment);
            Triger_Sell=false;
           }
           
         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (SpreadS1<=MaxSpread) && (BidS1>(GetPrice(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(StepOrdersPips*PointS1))) && (ind_In3S1[1]>ind_In4S1[1]) && (ind_In3S1[1]<ind_In3S1[2]) && (ind_In4S1[1]>ind_In4S1[2]))
           {
            OpenSell(symbolS1.Name(), LotsXSell, 0, StopLoss, EAComment);
           }   
           
         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (ind_In3S1[1]<ind_In4S1[1]))
           {
            ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL);
           }      

         //Buy++++++++++++++++++++++++++++++++++++++++++++++++
         
         if ((iLow(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In2S1[1]) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0)){Triger_Buy=true;}

         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (SpreadS1<=MaxSpread) && (Triger_Buy==true) && (ind_In3S1[1]<ind_In4S1[1]) && (ind_In3S1[1]>ind_In3S1[2]) && (ind_In4S1[1]<ind_In4S1[2]))
           {
            OpenBuy(symbolS1.Name(), LotsXBuy, 0, StopLoss, EAComment);
            Triger_Buy=false;
           }
           
         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (SpreadS1<=MaxSpread) && (AskS1<(GetPrice(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)-(StepOrdersPips*PointS1))) && (ind_In3S1[1]<ind_In4S1[1]) && (ind_In3S1[1]>ind_In3S1[2]) && (ind_In4S1[1]<ind_In4S1[2]))
           {
            OpenBuy(symbolS1.Name(), LotsXBuy, 0, StopLoss, EAComment);
           }   
           
         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (ind_In3S1[1]>ind_In4S1[1]))
           {
            ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY);
           }    

Следует пояснить некоторые моменты, а именно:

    • Переменные Triger_Sell и Triger_Buy значения True/False отвечают за запоминание касаний верхней и нижней сторон индикатора Bollinger Bands. По условиям стратегии это первый сигнал.
    • Отслеживания цены последней позиции для выставления сетки ордеров происходит с помощью функции GetPrice, которая возвращает цену открытия в зависимости от типа позиции.
    • В сетке уже не участвуют триггеры касания индикатора Bollinger Bands. Выполняются только условия схождения индикатора HLC Trend.


Тестирование и оптимизация советника по стратегии «BOLT»:

Проведем тестирование с параметрами по умолчанию по валютных парах EURUSD и GBPUSD в период времени с 2020.02.13 по 2023.02.13 на разных таймфреймах. Шаг сетки равен 200 пунктов по пятизнаку:

Test1

EURUSD M30

Test2

EURUSD H1

Test3

EURUSD H4

Test4

GBPUSD M30

Test5

GBPUSD H1

Test6

GBPUSD H4

Как видно из тестов мы получили результаты с большими просадками. Проведем оптимизацию с параметрами указанными на скриншоте ниже:

Opt1

Результаты оптимизации:

Opt2

Результаты тестирования лучшего прохода по максимуму комплексного критерия:

TestOpt


Заключение по стратегии «BOLT»:

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


Стратегия «YinYang»

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


Рынок, валютная пара, временной интервал:

  • Валютная пара – изначально GBPUSD.
  • Временной интервал – M15.
  • Рынок - FOREX


Используемые индикаторы:

  • Индикатор Envelopes с периодом 21 и с отклонением 0,18%.
  • Индикатор Parabolic SAR с шагом 0,02; максимум 0,7.
  • Индикатор Awesome Oscillator.


Условия для продаж по стратегии «YinYang»:

Вариант 1

  1. В прошлом цена касалась верхней линии индикатора Envelopes что является тригером на продажу, но еще не касалась нижней границы.
  2. Индикатор Parabolic SAR меняет свое положение и окажется выше цены на графике.
  3. Индикатор Awesome Oscillator находится выше нуля и окрашен в красный цвет. То есть его значения падают относительно предыдущих значений.
  4. После получения всех сигналов на следующей свече открываем продажу.

 

Вариант 2

  1. Текущая цена находится между верхней и нижней линиями индикатора Envelopes.
  2. Индикатор Parabolic SAR меняет свое положение и окажется выше цены на графике.
  3. Индикатор Awesome Oscillator находится выше нуля и эго значение растет.

 

Для обоих вариантов на продажу

  1. Stop Loss устанавливаем за индикатор Parabolic SAR.
  2. Рекомендуемый Take Profit 500-600 пунктов по пятизнаку.
  3. При получении обратного сигнала в обоих вариантах следует закрыть текущую позицию даже с убытком.

Ниже приведу пару скриншотов с входами на продажу варианта 1:

Sell11


Sell12

Ниже приведу пару скриншотов с входами на продажу варианта 2:

Sell21


Sell22


Условия для покупок по стратегии «YinYang»:

Вариант 1

  1. В прошлом цена касалась нижней линии индикатора Envelopes что является тригером на покупку по первому варианту стратегии, но еще не касалась нижней границы.
  2. Индикатор Parabolic SAR меняет свое положение и окажется ниже цены на графике.
  3. Индикатор Awesome Oscillator находится ниже нуля и окрашен в зеленый цвет. То есть его значения падают относительно предыдущих значений.
  4. После получения всех сигналов на следующей свече открываем покупку.

 

Вариант 2

  1. Текущая цена находится между верхней и нижней линиями индикатора Envelopes.
  2. Индикатор Parabolic SAR меняет свое положение и окажется ниже цены на графике.
  3. Индикатор Awesome Oscillator находится выше нуля и эго значение растет.

 

Для обоих вариантов на покупку

  1. Stop Loss устанавливаем за индикатор Parabolic SAR.
  2. Рекомендуемый Take Profit 500-600 пунктов по пятизнаку.
  3. При получении обратного сигнала в обоих вариантах следует закрыть текущую позицию даже с убытком.

Ниже приведу пару скриншотов с входами на покупку варианта 1:

Buy11


Buy12

Ниже приведу пару скриншотов с входами на покупку варианта 2:

Buy21


Buy22


Пишем код советника по стратегии «YinYang»:

Для проведения дальнейшей оптимизации выводим параметры индикаторов и Take Profit в переменные. Stop Loss мы выставляем по индикатору Parabolic SAR. Также введем 2 параметра типа bool для отключения или включения соответствующей стратегии для управления ими:

input group "+++ Indicators +++"
input int EnvelopesPeriod = 21;
input double EnvelopesDeviation = 0.18;
input double Step_SAR = 0.01;
input double Maximum_SAR = 0.2;

input group "+++ Take profit +++"
input int TakeProfit = 500;

input group "+++ ON/OF Strategies +++"
input bool Strategy1 = true;
input bool Strategy2 = true;

Получаем хендлы и значения наших индикаторов:

   handle_In1=iEnvelopes(symbolS1.Name(),PERIOD_CURRENT,EnvelopesPeriod,0,MODE_SMA,PRICE_CLOSE,EnvelopesDeviation);
//--- if the handle is not created
   if(handle_In1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2=iSAR(symbolS1.Name(),PERIOD_CURRENT,Step_SAR,Maximum_SAR);
//--- if the handle is not created
   if(handle_In2==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In3=iAO(symbolS1.Name(),PERIOD_CURRENT);
//--- if the handle is not created
   if(handle_In3==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

        //--- get data from the three buffers of the Envelopes indicator
         ArraySetAsSeries(ind_In1S1,true);
         if(!iGetArray(handle_In1,0,0,5,ind_In1S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the Envelopes indicator
         ArraySetAsSeries(ind_In2S1,true);
         if(!iGetArray(handle_In1,1,0,5,ind_In2S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the SAR indicator
         ArraySetAsSeries(ind_In3S1,true);
         if(!iGetArray(handle_In2,0,0,5,ind_In3S1))
           {
            return;
           }
         //---
      
         //--- get data from the three buffers of the AO indicator
         ArraySetAsSeries(ind_In4S1,true);
         if(!iGetArray(handle_In3,0,0,5,ind_In4S1))
           {
            return;
           }
         //---

Основной блок логики советника:

//Variant 1 +++++++++++++++++++++++++++++++++++++++++++++++++++

if (Strategy1==true){
         //Sell++++++++++++++++++++++++++++++++++++++++++++++++
         
         if ((iHigh(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In1S1[1]) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST1")==0)){Triger_Sell=true;}

         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST1")==0) && (SpreadS1<=MaxSpread) && (Triger_Sell==true) && (ind_In3S1[1]>iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[1]<ind_In4S1[2]) && (ind_In4S1[1]>0) && (ind_In4S1[2]>0))
           {
            double sl = ind_In3S1[1];
            ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST1");
            OpenSell(symbolS1.Name(), LotsXSell, TakeProfit, sl, EAComment+"ST1");
            Triger_Sell=false;
           }   

         //Buy++++++++++++++++++++++++++++++++++++++++++++++++
         
         if ((iLow(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In2S1[1]) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST1")==0)){Triger_Buy=true;}

         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST1")==0) && (SpreadS1<=MaxSpread) && (Triger_Buy==true) && (ind_In3S1[1]<iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[1]>ind_In4S1[2]) && (ind_In4S1[1]<0) && (ind_In4S1[2]<0))
           {
            double sl = ind_In3S1[1];
            ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST1");
            OpenBuy(symbolS1.Name(), LotsXBuy, TakeProfit, sl, EAComment+"ST1");
            Triger_Buy=false;
           }
}
           
//Variant 2 +++++++++++++++++++++++++++++++++++++++++++++++++++

if (Strategy2==true){
         //Sell++++++++++++++++++++++++++++++++++++++++++++++++
         
         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST2")==0) && (SpreadS1<=MaxSpread) && (ind_In3S1[1]>iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In1S1[1]) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) && (ind_In4S1[1]<0) && (ind_In4S1[2]<0) && (ind_In4S1[1]<ind_In4S1[2]))
           {
            double sl = ind_In3S1[1];
            ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST2");
            OpenSell(symbolS1.Name(), LotsXSell, TakeProfit, sl, EAComment+"ST2");
           }   

         //Buy++++++++++++++++++++++++++++++++++++++++++++++++
         
         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST2")==0) && (SpreadS1<=MaxSpread) && (ind_In3S1[1]<iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In1S1[1]) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) && (ind_In4S1[1]>0) && (ind_In4S1[2]>0) && (ind_In4S1[1]>ind_In4S1[2]))
           {
            double sl = ind_In3S1[1];
            ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST2");
            OpenBuy(symbolS1.Name(), LotsXBuy, TakeProfit, sl, EAComment+"ST2");
           }
}


Тестирование и оптимизация советника по стратегии «YinYang»:

Проведем тестирование с параметрами по умолчанию по валютных парах EURUSD и GBPUSD в период времени с 2020.02.13 по 2023.02.13 на таймфрейме M15:

Вариант 1:

Test1

EURUSD

Test2

GBPUSD

Вариант 2:

Test3

EURUSD

Test4

GBPUSD

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

Opt1

Результаты оптимизации:

Opt2


Заключение по стратегии «YinYang»:

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


Стратегия «Statistics SAR»

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


Рынок, валютная пара, временной интервал:

  • Валютная пара – мультивалютная, проверять будем на EURUSD и GBPUSD.
  • Временной интервал – M15-H1.
  • Рынок - FOREX

 

Используемые индикаторы:

  • Индикатор Parabolic SAR с шагом 0,02; максимум 0,2 по умолчанию. В дальнейшем используется оптимизация этих параметров.
  • Индикатор Moving Average с периодом 1. Используем как значение цены.


Условия для продаж по стратегии «Statistics SAR»:

  1. Собираем статистику расхождения индикатора Moving Average с периодом 1 и индикатора Parabolic SAR для нахождения среднего значения. Используется задаваемое в параметрах количество свечей.
  2. Индикатор Parabolic SAR находится под ценой, в нашем случае Moving Average с периодом 1.
  3. Расстояние в пунктах между ценой и SAR превышает среднее значение, умноженное на некий коэффициент, определенный в параметрах советника.
  4. Stop Loss и Take Profit имеют фиксированные значения. Вынесены в параметры советника.

Ниже приведу пару скриншотов с попыткой отследить такие ситуации на продажу:

Sell1

 

Sell2


Условия для покупок по стратегии «Statistics SAR»:

  1. Собираем статистику расхождения индикатора Moving Average с периодом 1 и индикатора Parabolic SAR для нахождения среднего значения. Используется задаваемое в параметрах количество свечей.
  2. Индикатор Parabolic SAR находится над ценой, в нашем случае Moving Average с периодом 1.
  3. Расстояние в пунктах между SAR и ценой превышает среднее значение, умноженное на некий коэффициент, определенный в параметрах советника.
  4. Stop Loss и Take Profit имеют фиксированные значения. Вынесены в параметры советника.

Ниже приведу пару скриншотов с попыткой отследить такие ситуации на покупку:

Buy1


Buy2


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


На заметку:

  • На таймфрейме H1 30 дней равно 720 свечей.
  • На таймфрейме M30 30 дней равно 1440 свечей.
  • На таймфрейме M15 30 дней равно 2880 свечей.


Пишем код советника по стратегии «Statistics SAR»:

Для проведения дальнейшей оптимизации выводим параметры индикаторов, параметры Take Profit и Stop Loss в переменные. Также выводим количество свечей для сбора статистики – параметр Canbles:

input group "+++ Indicators +++"
input double Step_SAR = 0.02;
input double Maximum_SAR = 0.2;

input group "+++ Take profit/Stop loss +++"
input int TakeProfit = 400;
input int StopLoss = 200;

input group "+++ Statistics +++"
input int Canbles = 720;
input double MultiplyingAverage = 2.0;

Получаем хендлы и значения наших индикаторов:

   handle_In1=iMA(symbolS1.Name(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE);
//--- if the handle is not created
   if(handle_In1==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

   handle_In2=iSAR(symbolS1.Name(),PERIOD_CURRENT,Step_SAR,Maximum_SAR);
//--- if the handle is not created
   if(handle_In2==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
//---

         //--- get data from the three buffers of the MA 1 indicator
         ArraySetAsSeries(ind_In1S1,true);
         if(!iGetArray(handle_In1,0,0,Canbles+5,ind_In1S1))
           {
            return;
           }
         //---

         //--- get data from the three buffers of the SAR indicator
         ArraySetAsSeries(ind_In2S1,true);
         if(!iGetArray(handle_In2,0,0,Canbles+5,ind_In2S1))
           {
            return;
           }
         //---

Код получения статистики:

         //Statistics++++++++++++++++++++++++++++++++++++++++++++++++

         if(isNewBar2()==true)
           {

            //--- get data from the three buffers of the MA 1 indicator
            ArraySetAsSeries(ind_In1S1,true);
            if(!iGetArray(handle_In1,0,0,Candles+5,ind_In1S1))
              {
               return;
              }
            //---

            //--- get data from the three buffers of the SAR indicator
            ArraySetAsSeries(ind_In2S1,true);
            if(!iGetArray(handle_In2,0,0,Candles+5,ind_In2S1))
              {
               return;
              }
            //---

            Sr=0;
            Count=0;

            for(int i=0; i<=Candles; i++)
              {

               if((ind_In1S1[i]!=0) && (ind_In2S1[i]!=0))
                 {
                  Sr = Sr + int(MathAbs((ind_In1S1[i]-ind_In2S1[i])/PointS1));
                  Count++;
                 }

              }

            Sr = Sr/Count;

           }

         //Statistics++++++++++++++++++++++++++++++++++++++++++++++++

Основной блок логики советника:

         //Sell++++++++++++++++++++++++++++++++++++++++++++++++
         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (SpreadS1<=MaxSpread) && (ind_In1S1[1]>ind_In2S1[1]) && (((ind_In1S1[1]-ind_In2S1[1])/PointS1)>=(Sr*MultiplyingAverage)))
           {
            OpenSell(symbolS1.Name(), LotsXSell, TakeProfit, StopLoss, EAComment);
           }   

         //Buy+++++++++++++++++++++++++++++++++++++++++++++++
         if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (SpreadS1<=MaxSpread) && (ind_In1S1[1]<ind_In2S1[1]) && (((ind_In2S1[1]-ind_In1S1[1])/PointS1)>=(Sr*MultiplyingAverage)))
           {
            OpenBuy(symbolS1.Name(), LotsXBuy, TakeProfit, StopLoss, EAComment);
           }

Немного объяснений по коду. Дабы ускорить, советник статистику мы собираем один раз в день. Функция isNewBar2() возвращает признак открытия новой свечи на таймфрейме D1. Также обязательно проверяем, не равно ли среднее значение нулю - (Sr!=0). Среднее и текущее значения считаются в пунктах.


Тестирование и оптимизация советника по стратегии «Statistics SAR»:

Проведем тестирование с параметрами по умолчанию по валютных парах EURUSD и GBPUSD в период времени с 2020.02.13 по 2023.02.13 на разных тайм фреймах. Параметр  MultiplyingAverage = 2.0 :

EURUSDM15

EURUSD M15

EURUSDM30

EURUSD M30

EURUSDH1

EURUSD H1

GBPUSDM15

GBPUSD M15

GBPUSDM30

GBPUSD M30

GBPUSDH1

GBPUSD H1

Как видно из тестов мы получили негативный результат по обеим валютним парам с параметрами по умолчанию. Проведем оптимизацию на тайм фрейме H1 с параметрами указанными на скриншоте ниже:

Opt1

Результаты оптимизации:

Opt2


Opt3

Результат лучшего прохода по комплексному критерию:

OptR


Заключение по стратегии «Statistics SAR»:

Как видно из проведенной оптимизации стратегия вполне пригодна для дальнейшего развития и модернизации. По комплексному критерию результаты не плохие.


Выводы по результатам анализа

  • Стратегия "Red Dragon H4" показывает не очень хорошие результаты и обладает низким профит фактором, но интересна моментом получения сигнала при перевороте индикатора Parabolic SAR.
  • Стратегия "BOLT" может приводить к просадкам и требует дополнительной оптимизации, возможно, с использованием мартингейла, что увеличивает риски.
  • Стратегия "YinYang" абсолютно не применима к выбранным валютным парам и таймфрейму, показывая плохие результаты.
  • Стратегия "Statistics SAR" кажется перспективной для дальнейшего развития и модернизации, показывая комплексно не плохие результаты.

Заключение

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

  • Использование триггеров для определения точки входа.
  • Выставления Stop Loss по индикаторам.
  • Умножение на порядок Take Profit в зависимости от Stop Loss.
  • Рассмотрели простенький вариант использования сетки в торговле.
  • Использование двух сигналов на открытие позиций в одном советнике.
  • Сбор статистических данных для использования в торговле.
Уважаемые читатели, представляю вашему вниманию пробный выпуск статьи в новом формате. Если он вам придется по вкусу и вы проявите интерес к дальнейшему изучению советников по различным стратегиям, буду рад вашим вопросам, предложениям и идеям для будущих разработок. Пожалуйста, делитесь ими через личные сообщения или на форуме. Продолжение серии статей напрямую зависит от вашей реакции на данный материал. Благодарю за участие и до новых встреч!

Прикрепленные файлы |
EA.zip (25.73 KB)
Нейросети — это просто (Часть 78): Детектор объектов на основе Трансформера (DFFT) Нейросети — это просто (Часть 78): Детектор объектов на основе Трансформера (DFFT)
В данной статье я предлагаю посмотреть на вопрос построения торговой стратегии с другой стороны. Мы не будем прогнозировать будущее ценовое движение, а попробуем построить торговую систему на основе анализа исторических данных.
Работаем с датами и временем в MQL5 Работаем с датами и временем в MQL5
Трейдерам и разработчикам торговых инструментов очень важно понимать, как хорошо и эффективно обращаться с датами и временем. В статье я покажу, как мы можем обращаться с датами и временем при создании эффективных торговых инструментов.
Работа с ONNX-моделями в форматах float16 и float8 Работа с ONNX-моделями в форматах float16 и float8
Форматы данных, используемые для представления моделей машинного обучения, играют ключевую роль в их эффективности. В последние годы появилось несколько новых типов данных, разработанных специально для работы с моделями глубокого обучения. В данной статье мы обратим внимание на два новых формата данных, которые стали широко применяться в современных моделях.
Угловые операции для трейдеров Угловые операции для трейдеров
В этой статье будут рассмотрены угловые операции. Мы рассмотрим методы построения углов и способы их применения в трейдинге.