English 中文 Español Deutsch 日本語 Português
preview
Тестирование и оптимизация стратегий для бинарных опционов в MetaTrader 5

Тестирование и оптимизация стратегий для бинарных опционов в MetaTrader 5

MetaTrader 5Тестер | 10 февраля 2023, 12:20
1 240 6
Roman Poshtar
Roman Poshtar

Введение

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


Теория

Бинарный опцион - цифровой контракт, предметом которого служит прогноз направления цены aктивa в выбpaнный пpoмeжутoк вpeмeни. Kaк paбoтaть нa бинapныx oпциoнax? Зaдaчa cвoдитcя к тoму, чтoбы пpaвильнo oпpeдeлить oдин из двуx вepoятныx вapиaнтoв paзвития pынoчнoй cитуaции: будeт актив pacти или пaдaть. Ceгoдня пpeдcтaвлeн шиpoкий выбop oнлaйн oпций нa вaлюты, цeнныe бумaги, биpжeвыe тoвapы. Aктивoм в тaкoгo poдa пpoцeдуpax мoжeт быть вce чтo угoднo, как выяснилось дaжe пpoгнoз пoгoды. Чтобы начать торговлю нe тpeбуeтся oгpoмныx влoжeний и глубoкиx финaнcoвo-экoнoмичecкиx знaний в cфepe pынoчныx биpжeвыx пpoцeccoв.


Виды бинарных опционов

«Bышe/Hижe» - caмый пpocтoй и понятный вид бинарных опционов - для пoлучeния пpибыли  тpeйдepу дocтaтoчнo oпpeдeлить в кaкую cтopoну пoйдeт цeнa, вверх или вниз. Ha бычьeм тренде цeлecooбpaзнo покупать «Bвepx» (Call). Oпциoн «Bниз» (Put) пpиoбpeтaeтcя, ecли oжидaeтcя нисходящее движение актива. Профит опционов «Bышe/Hижe» вapьиpуeт oт 10% дo 80% oт cтaвки.

«Oднo кacaниe» (One touch) - пpeдcтaвляют coбoй дoгoвopeннocть, в кoтopoй тpeбуeтcя определить дocтижeниe ценой нужнoгo цeнoвoгo уpoвня. Гдe будут нaxoдитьcя кoтиpoвки пpи зaкpытии нe имeeт знaчeния; oпpeдeляющим будeт caм фaкт кacaния зaдaннoгo уровня. Дoxoднocть «One touch» вышe oбычныx, тaк кaк иx в большинстве случаев очень трудно предугадать, и дocтигaeт 95%, а вот потерять можно все 100%.

«Гpaницa» («Диaпaзoн») - oпpeдeляют цeнoвoй кopидop, внутpи кoтopoгo будeт нaxoдитьcя цeннocть aктивa нa мoмeнт экспирации. Также является сложным в понимании и прогнозировании. Доходность до 95%.

Ниже в статье мы будем проводить тестирование и оптимизацию стратегий для опционов «Bышe/Hижe» как самый популярный на мой взгляд.


Плюсы и минусы

К плюсам можно отнести:

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

Из недостатков:

  • Большая рискованность и oтpицaтeльнoe матожидание. Для компенсации одного проигрыша нужно два выигрыша. Дoxoднaя эффeктивнocть дo 80%. Неудачная oпepaция обойдется дopoжe, чeм выигpышнaя.
  • Peжим «Казино» нa диcтaнции пpинocит нeудaчи. Heкoтopыe пpoбуют пpимeнить пpиeмы из кaзинo пpи тopгax или методы усреднения например «Мартингейл», чтo кaтeгopичecки пpoтивopeчит правилам правильного тpeйдинга. Этo как я считаю 100% cлив дeпoзитa на дистанции.
  • Достаточно кpупныe кoмиccиoнныe которые взимaютcя пpи любoм удoбнoм cлучae пpи торговле.

    Валютная пара. Диапазон оптимизации и форвард тестирования. Настройки

    Тут я предоставлю, все параметры для оптимизации и тестирования что бы дальше в тексте не повторятся:

    • Рынок Forex;
    • Валютная пара EURUSD;
    • Период M5, M15, M30, H1;
    • Время экспирации 5, 15, 30 минут и 1 час.
    • Диапазон оптимизации 1 год. С 2021.01.28 по 2022.01.28.
    • Диапазон форвард тестирования 1 год. С 2022.01.28 по 2023.01.28;
    • Начальный депозит 10000;
    • Ставка 10;
    • Процент вознаграждения 80%.

      Технические аспекты

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

      1. StartDepo  - стартовый депозит;
      2. OptionRate - ставка;
      3. ExpirationTime - время экспирации;
      4. ProfitPercent - процент прибыльности;
      5. TimeFrame - таймфрейм индикаторов;
      6. Optimization -переключатель оптимизации;
      7. OptimizationFileName – имя файла для хранения результатов оптимизации.
      input string N0 = "------------Open settings----------------";
      input double StartDepo = 10000;
      input int OptionRate = 10;
      input string N1 = "------------Close settings---------------";
      input int ExpirationTime = 1; //ExpirationTime 1=5 min, 2=15 min, 3=30 min, 4=60 min
      input double ProfitPercent = 80;
      input string N2 = "------------Optimization settings--------";
      input int TimeFrame = 1; //TimeFrame 1=5 min, 2=15 min, 3=30 min, 4=60 min
      input bool Optimization = false;
      input string OptimizationFileName = "Optimization.csv";
      input string N3 = "------------Other settings---------------";
      input int Slippage = 10;
      input int Magic = 111111;
      input string EAComment = "2Ma+RSI+Stochastic Oscillator";

      Также понадобятся переменные для хранения и отслеживания изменения депозита и количества прибыльных и убыточных покупок опционов:

      1. XStartDepo - для хранения текущего депозита;
      2. Profit - для хранения количества прибыльных покупок опционов;
      3. Loss - для хранения количества убыточных покупок опционов;
      double XStartDepo = StartDepo;
      int Profit=0;
      int Loss=0;

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

      //+------------------------------------------------------------------+
      //| Get open time in positions                                             |
      //+------------------------------------------------------------------+
      datetime GetTime(string symb="0", int type=-1, int mg=-1,int index=0) {
       datetime p[];
       int c=-1, pr=0;
        if(symb=="0") { symb=Symbol();}
         for(int i=PositionsTotal()-1;i>=0;i--){
            if(position.SelectByIndex(i)) {
           if(position.PositionType()==POSITION_TYPE_BUY || position.PositionType()==POSITION_TYPE_SELL) {
            if((position.Symbol()==symb||symb=="")&&(type<0||position.PositionType()==type)&&(mg<0||position.Magic()==mg)) {
             c++;
             ArrayResize(p, c+1);
             p[c]=position.Time();
             pr=c>=index?index:c;
             
       }}}}
        return(c==-1?0:p[pr]);
       }

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

      //+------------------------------------------------------------------+
      //| Get profit in positions                                             |
      //+------------------------------------------------------------------+
      double GetProfit(string symb="0", int type=-1, int mg=-1,int index=0) {
       double p[];
       int c=-1, pr=0;
        if(symb=="0") { symb=Symbol();}
         for(int i=PositionsTotal()-1;i>=0;i--){
            if(position.SelectByIndex(i)) {
           if(position.PositionType()==POSITION_TYPE_BUY || position.PositionType()==POSITION_TYPE_SELL) {
            if((position.Symbol()==symb||symb=="")&&(type<0||position.PositionType()==type)&&(mg<0||position.Magic()==mg)) {
             c++;
             ArrayResize(p, c+1);
             p[c]=position.Profit();
             pr=c>=index?index:c;
             
       }}}}
        return(c==-1?0:p[pr]);
       }

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

      1. TrigerSell - покупка Put опциона;
      2. TrigerBuy - покупка Call опциона;
      int TrigerSell=0;
      int TrigerBuy=0;

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

      //Sell (Put)
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Для оптимизации используем переменные для определения нужного таймфрейма и времени экспирации. Режим оптимизации включается переменной Optimization. Суть оптимизации сводится к использованию файлов типа CSV. После завершения тестирования в OnDeinit записываем в файл все необходимые переменные. При оптимизации наши советники создают файл CSV с результатом по пути «C:\Users\Ваше имя пользователя\AppData\Roaming\MetaQuotes\Terminal\Common\Files».

      1. Конечный депозит;
      2. Количество прибыльных сделок;
      3. Количество убыточных сделок;
      4. Таймфрейм;
      5. Время экспирации.
      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      
      if (Optimization==true){
       if (FileIsExist(OptimizationFileName)==false){
         filehandle = FileOpen(OptimizationFileName,FILE_WRITE|FILE_READ|FILE_CSV|FILE_COMMON|FILE_ANSI, ";");
          if(filehandle!=INVALID_HANDLE)
           {
            FileSeek(filehandle, 0, SEEK_END);
            FileWrite(filehandle,DoubleToString(XStartDepo),IntegerToString(Profit),IntegerToString(Loss),IntegerToString(XTimeFrame),IntegerToString(XExpirationTime));
            FileClose(filehandle);
           }
       }
      }
      
        }

      Наблюдать за тестированием можно в режиме визуализации. С помощью Comment() для простоты выведем текущий результат.

      Текущий результат


      Стратегии

      Стратегия «2Ma+RSI+Stochastic Oscillator»

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

      Индикаторы:

      1. Пара экспоненциальных скользящих средних с периодами 5 и 10;
      2. Индекс относительной силы (RSI), настройки используются по умолчанию;
      3. «Стохастик» (Stochastic Oscillator) со значениями настроек 14, 3, 3.

      Сигнал «вверх», или покупка Call опциона, появляется при выполнении ряда условий:

      1. Скользящая красного цвета пересекла синюю скользящую снизу вверх;
      2. Индекс относительной силы располагается над уровнем 50;
      3. Быстрая линия «Стохастика» пересекла медленную (пунктирную) снизу вверх.

      Вверх стратегия 1

      Сигнал «вниз», или покупка Put опциона, образуется также при наличии определенных факторов:
      1. Красный «мувинг» пересек синий сверху вниз;
      2. RSI располагается ниже уровня 50;
      3. Быстрая линия стохастического осциллятора пересекает медленную сверху вниз.

      Вниз стратегия 1

      Триггером в данной стратегии для нового сигнала я выбрал пересечение MA в обратную сторону. Ниже приведу код стратегии.

      //Sell (Put)
      
      if((ind_In1S1[1]>ind_In2S1[1]) && (ind_In1S1[2]>ind_In2S1[2])){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (ind_In1S1[1]<ind_In2S1[1]) && (ind_In1S1[0]<ind_In2S1[0]) && (ind_In4S1[1]<50) && (ind_In4S1[0]<50) && (ind_In3S1_1[1]<ind_In3S1_2[1])){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if((ind_In1S1[1]<ind_In2S1[1]) && (ind_In1S1[2]<ind_In2S1[2])){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (ind_In1S1[1]>ind_In2S1[1]) && (ind_In1S1[0]>ind_In2S1[0]) && (ind_In4S1[1]>50) && (ind_In4S1[0]>50) && (ind_In3S1_1[1]>ind_In3S1_2[1])){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

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

      • Конечный депозит 1964;
      • Прибыльных трейдов 1273;
      • Убыточных трейдов 1822.

      Результат

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

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


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

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

      Индикаторы:

      1. Индикатор Bollinger Bands с параметрами 20 и StDev (стандартное отклонение) 2;
      2. Индикатор RSI. Параметры RSI – 4, с границами 80 и 20.

      Прогноз роста. Покупка Call опциона:

      После того как линия индикатора RSI вышла в зону перепроданности, ниже отметки 20, а линия цены касается или выходит за рамки полос Боллинджера – ждем первую бычью свечу и открываем сделку ВВЕРХ.

      Покупка вверх

      Прогноз падения. Покупка Put опциона:

      После того как линия индикатора RSI вышла в зону перекупленности, выше отметки 80, а ценовая линия вышла за верхние границы Боллинджера – ждем первую медвежью свечу и открываем сделку ВНИЗ.

      Покупка вниз

      Триггером в данной стратегии для нового сигнала я выбрал закрытие предыдущей свечи внутри канала индикатора Боллинджер. Ниже приведу код стратегии.

      //Sell (Put)
      
      if(iClose(symbolS1.Name(),XTimeFrame,1)<ind_In1S1_1[1]){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (iClose(symbolS1.Name(),XTimeFrame,2)>ind_In1S1_1[2]) && (ind_In2S1[2]>80) && (iClose(symbolS1.Name(),XTimeFrame,1)<iOpen(symbolS1.Name(),XTimeFrame,1))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if(iClose(symbolS1.Name(),XTimeFrame,1)>ind_In1S1_2[1]){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (iClose(symbolS1.Name(),XTimeFrame,2)<ind_In1S1_2[2]) && (ind_In2S1[2]<20) && (iClose(symbolS1.Name(),XTimeFrame,1)>iOpen(symbolS1.Name(),XTimeFrame,1))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Приступим к проверке. Проведем тестирование на таймфрейме M5. Получаем результат:

      • Конечный депозит 3312;
      • Прибыльных трейдов 1589;
      • Убыточных трейдов 1940.

      Результат

      Что же мы получили убыток. Хотя и результат немного лучше, чем в предыдущей стратегии. Проведем оптимизацию в надежде на положительные значения депозита. Но увы стратегия не работает:

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


      Стратегия «Vortex+TSI»

      Стратегия для бинарных опционов называется Вортекс благодаря использованию одноименного индикатора. На деле в стратегии участвуют два индикатора – основной и второй в качестве фильтра. Предлагаемый таймфрейм 1-5 минут.

      Индикаторы:

      1. Vortex с параметром 14;
      2. True Strength Indicator (TSI) c параметрами 25, 13, 5, Exponential.

      Для покупки опциона на рост цены:

      1. Дожидаемся одновременного пересечения линий обоих индикаторов, когда синие линии окажутся вверху, а красные пойдут вниз;
      2. Линии индикатора Vortex должны расходиться.

      Рост

      Для покупки опциона на падение цены:

      1. Дожидаемся одновременного пересечения линий обоих индикаторов, когда красные линии окажутся вверху, а синие пойдут вниз;
      2. Линии индикатора Vortex должны расходиться.

      Падение

      Триггером для нового сигнала выступает обратное пересечение индикатора True Strength Indicator. Ниже приведу код стратегии.
      //Sell (Put)
      
      if(ind_In1S1_1[1]>ind_In1S1_2[1]){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (ind_In1S1_1[0]<ind_In1S1_2[0]) && (ind_In1S1_1[1]<ind_In1S1_2[1]) && (ind_In2S1_1[0]<ind_In2S1_2[0]) && (ind_In2S1_1[1]<ind_In2S1_2[1]) && (ind_In2S1_1[0]<ind_In2S1_1[1]) && (ind_In2S1_2[0]>ind_In2S1_2[1]) && (ind_In2S1_1[1]<ind_In2S1_1[2]) && (ind_In2S1_2[1]>ind_In2S1_2[2])){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if(ind_In1S1_1[1]<ind_In1S1_2[1]){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (ind_In1S1_1[0]>ind_In1S1_2[0]) && (ind_In1S1_1[1]>ind_In1S1_2[1]) && (ind_In2S1_1[0]>ind_In2S1_2[0]) && (ind_In2S1_1[1]>ind_In2S1_2[1]) && (ind_In2S1_1[0]>ind_In2S1_1[1]) && (ind_In2S1_2[0]<ind_In2S1_2[1]) && (ind_In2S1_1[1]>ind_In2S1_1[2]) && (ind_In2S1_2[1]<ind_In2S1_2[2])){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Приступим к проверке нашей индикаторной стратегии. Проведем тестирование на таймфрейме M5. Получаем результат:

      • Конечный депозит -3118;
      • Прибыльных трейдов 1914;
      • Убыточных трейдов 2843.

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

      Результат

      Результаты проведенной оптимизации говорят сами за себя:

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


      Проверив еще около 10 различных стратегий и не получив желаемого результата, мною было принято решение разработать собственную стратегию. Отталкиваясь от полученного опыта, что сами индикаторы не работают, решил попробовать другой подход. Стратегию решил назвать незамысловатым названием «New».

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

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

      Индикаторы:

      Один индикатор Envelopes со стандартными настройками 14, 0, 0,1 метод Simole применить к Close.

      Сигнал «вверх», или покупка Call опциона:

      1. Цена Ask меньше нижней линии индикатора Envelopes;
      2. Расстояние в пунктах от нижней линии индикатора Envelopes до цены Ask больше значения Distance.

      Вверх

      Сигнал «вниз», или покупка Put опциона:

      1. Цена Bid больше верхней линии индикатора Envelopes;
      2. Расстояние в пунктах от цены Bid до линии индикатора Envelopes больше значения Distance.

      Вниз

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

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Проведем тестирование на таймфрейме 5 минут. Параметр Distance=150. Результат тестирования без использования усреднения на скриншоте ниже:

      Результат 1

      Конечный депозит 8952; Прибыльных трейдов 874;

      Убыточных трейдов 804.

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

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

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

      Добавим усреднение. Количество усредняющих входов было решено ограничить. Для этого ввели, новый параметр Averaging, по умолчанию равен 4. Ниже код стратегии с усреднением:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+(((XOptionRate*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-(XOptionRate*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+(((XOptionRate*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-(XOptionRate*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Результаты тестирования с усреднением. Ура, мы добились успеха:

      Усреднение 1

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

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

      Результаты более интересного варианта с умножением ставки после убыточных сделок. Ниже представлен код:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((((XOptionRate*LossIn)*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-((XOptionRate*LossIn)*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((((XOptionRate*LossIn)*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-((XOptionRate*LossIn)*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

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

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


      Заключение

      Какие выводы можно сделать из всей проделанной работы? То, что 99% всех индикаторных стратегий практически не работают. Изменив немного подход, возможно, разработать неплохую стратегию, которая будет приносить прибыль. Проверять необходимо все перед использованием на рынке, в этом, как всегда, нам поможет MetaTrader 5. Кстати, сейчас уже есть опционы с 100% прибыльностью, что дает дополнительную пищу для размышлений. Все представленные здесь стратегии в виде советников вы можете скачать в приложенном архиве. Спасибо за внимание друзья и до встречи.


      Прикрепленные файлы |
      MQL5.zip (25.52 KB)
      Последние комментарии | Перейти к обсуждению на форуме трейдеров (6)
      sydiya63
      sydiya63 | 20 сент. 2023 в 11:02
      Очень интересно. Я на бинарках сижу лет 10. Каких только стратегий я не придумывал. Любые стандартные индикаторы не работают ИМХО. Мне кажется нужно копать в свечной анализ, тело свечи, тени. Пока в минусах.
      HeAic
      HeAic | 3 февр. 2024 в 19:29

      Для бинарных опционов (3мин. время экспирации) когда то успешно !!! использовал стандартный индикатор OsMA.

      Единственная проблема  - точности входа не хватало из-за отсутствия 30сек. таймфрейма в МТ4 :)

      Ищите в сторону рыночного дисбаланса - поиск начала движения к балансу, этот сигнал всегда выполняется ;)

      maxvoronin74
      maxvoronin74 | 15 апр. 2024 в 09:07

      Попробовал вашу конкатенацию

         int         total            = PositionsTotal();
         for(int i=total-1; i>=0; i--)
         {
            int    position_magic        = position.Magic();
            string position_symbol       = position.Symbol(); /*PositionGetString(POSITION_SYMBOL)*/;
            ulong  position_ticket       = position.SelectByIndex(i);

      MetaEditor не пропускает: 'position' - undeclared identifier

      MrBrooklin
      MrBrooklin | 15 апр. 2024 в 09:50

      Эта часть кода у Вас есть?

      #include <Trade\PositionInfo.mqh>
      CPositionInfo  position;

      Если нет, то вставьте сразу после

      #property version   "1.000"

      С уважением, Владимир.

      maxvoronin74
      maxvoronin74 | 15 апр. 2024 в 15:33
      MrBrooklin #:

      Эта часть кода у Вас есть?

      Если нет, то вставьте сразу после

      С уважением, Владимир.

      Спасибо. Получилось.
      Пример создания комплекcной торговой стратегии Owl Пример создания комплекcной торговой стратегии Owl
      Моя стратегия базируется на классических основах трейдинга и доработке индикаторов, широко применяемых на всех видах рынков. Фактически — это уже готовый инструмент, используя который, можно во всей полноте работать по предлагаемой новой прибыльной торговой стратегии.
      Моральное ожидание в трейдинге Моральное ожидание в трейдинге
      Эта статья посвящена моральному ожиданию. Мы рассмотрим несколько примеров его применения в трейдинге, и каких результатов можно добиться с его помощью.
      Популяционные алгоритмы оптимизации: Алгоритм гравитационного поиска (Gravitational Search Algorithm - GSA) Популяционные алгоритмы оптимизации: Алгоритм гравитационного поиска (Gravitational Search Algorithm - GSA)
      GSA — популяционный алгоритм оптимизации, инспирированный неживой природой. Высокая достоверность моделирования взаимодействия физических тел, благодаря закону гравитации Ньютона в алгоритме, позволяет наблюдать феерический танец планетарных систем и галактических скоплений, который завораживает своим представлением на анимации. Сегодня рассмотрим один из самых интересных и оригинальных алгоритмов оптимизации. Симулятор движения космических объектов прилагается.
      Как построить советник, работающий автоматически (Часть 05): Ручные триггеры (II) Как построить советник, работающий автоматически (Часть 05): Ручные триггеры (II)
      Сегодня мы рассмотрим, как создать советник, который просто и безопасно работает в автоматическом режиме. В конце предыдущей статьи я подумал, что было бы уместно разрешить использование советника вручную хотя бы на время.