English 中文 Español Deutsch 日本語
preview
Создание самооптимизирующихся советников на MQL5 (Часть 5): Самоадаптирующиеся торговые правила

Создание самооптимизирующихся советников на MQL5 (Часть 5): Самоадаптирующиеся торговые правила

MetaTrader 5Примеры |
635 0
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana

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

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

На рис. 1 ниже мы применили 20-периодный RSI к дневной цене золота в долларах США. Читатель может заметить, что ни одно из ожидаемых показаний не наблюдалось в течение длительного периода в 3 месяца. Глядя на линию тренда, проведенную на графике, можно заметить, что с сентября по декабрь 2019 года цена на золото находилась в сильном нисходящем тренде.

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

Скриншот 1

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

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

Кроме того, читателям, торгующим только на одном рынке одновременно, следует помнить, что увеличение периода RSI усугубит проблему. Аналогично, уменьшение периода RSI увеличивает уровень шума на рынке и снижает общее качество торговых сигналов.

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


Обзор методологии

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

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


Начало работы с MQL5

Наше исследование начинается с установления базового уровня производительности с помощью тестера стратегий MetaTrader 5. Наша стратегия будет использоваться в качестве основы, которую читатель должен будет заменить собственными торговыми стратегиями. Мы построим стратегию на MQL5, которая торгует на пробоях ключевых уровней поддержки или сопротивления. RSI даст нам подтверждение того, что уровень успешно преодолен. Мы зафиксируем размер стоп-лосса и тейк-профита во всех версиях приложения, чтобы гарантировать, что изменения в прибыльности напрямую зависят от принятия нами более правильных решений. 

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

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

Наши уровни поддержки и сопротивления будут найдены путем сравнения текущих уровней цен с соответствующими уровнями 5 дней назад. 

Скриншот 2

Рис. 2. Визуализация уровней поддержки и сопротивления на XAGUSD

Некоторые параметры останутся неизменными. Поэтому, чтобы избежать ненужного повторения одной и той же информации, мы обсудим здесь эти фиксированные параметры. Целью нашего обсуждения будет торговля на прорывах уровней поддержки и сопротивления по дневной цене серебра в USD (XAGUSD). Мы протестируем нашу стратегию на исторических данных M15 с 1 января 2017 года по 28 января 2025 года.

Скриншот 3

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

Кроме того, во время нашего тестирования на истории мы будем использовать настройки "Случайной задержки" (Random delay), поскольку это похоже на опыт реальной торговли. Также мы выбрали "Каждый тик на основе реальных тиков" для проведения наших тестов на реальных рыночных данных, полученных от нашего брокера.

Скриншот 4

Рис. 4: Вторая группа фиксированных настроек в нашем сегодняшнем тесте

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

//+------------------------------------------------------------------+
//|                                  Self Adapting Trading Rules.mq5 |
//|                                               Gamuchirai Ndawana |
//|                    https://www.mql5.com/en/users/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Ndawana"
#property link      "https://www.mql5.com/en/users/gamuchiraindawa"
#property version   "1.00"

//+------------------------------------------------------------------+
//| System constants                                                 |
//+------------------------------------------------------------------+
#define RSI_PERIOD 10              //The period for our RSI indicator
#define RSI_PRICE  PRICE_CLOSE     //The price level our RSI should be applied to
#define ATR_SIZE   1.5             //How wide should our Stop loss be?
#define ATR_PERIOD 14              //The period of calculation for our ATR indicator
#define TF_1       PERIOD_D1       //The primary time frame for our trading application
#define TF_2       PERIOD_M15      //The secondary time frame for our trading application
#define VOL        0.1             //Our trading volume   

Теперь нам нужно импортировать торговую библиотеку, которая поможет нам управлять нашими позициями.

//+------------------------------------------------------------------+
//| Libraries we need                                                |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
CTrade Trade;

Далее нам необходимо определить несколько важных глобальных переменных.

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int rsi_handler,atr_handler;
double rsi[],atr[];
double support,resistance;

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

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   setup();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   release();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   update();
  }
//+------------------------------------------------------------------+

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

//+------------------------------------------------------------------+
//| User defined methods                                             |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Initialize our system variables                                  |
//+------------------------------------------------------------------+
void setup(void)
  {
//Load our technical indicators
   atr_handler = iATR(Symbol(),TF_1,ATR_PERIOD);
   rsi_handler = iRSI(Symbol(),TF_2,RSI_PERIOD,RSI_PRICE);
   resistance  = iHigh(Symbol(),TF_1,5);
   support     = iLow(Symbol(),TF_1,5);
  }

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

//+------------------------------------------------------------------+
//| Let go of resources we are no longer consuming                   |
//+------------------------------------------------------------------+
void release(void)
  {
//Free up resources we are not using
   IndicatorRelease(atr_handler);
   IndicatorRelease(rsi_handler);
  }

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

//+------------------------------------------------------------------+
//| Update our system variables and look for trading setups          |
//+------------------------------------------------------------------+
void update(void)
  {
//Update our system variables
//Some duties must be performed periodically on the higher time frame
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_1,0);

      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;

         //Update indicator readings
         CopyBuffer(rsi_handler,0,0,1,rsi);
         CopyBuffer(atr_handler,0,0,1,atr);

         //Update our support and resistance levels
         support    = iLow(Symbol(),TF_1,5);
         resistance = iHigh(Symbol(),TF_1,5);
         ObjectDelete(0,"Support");
         ObjectDelete(0,"Resistance");
         ObjectCreate(0,"Suppoprt",OBJ_HLINE,0,0,support);
         ObjectCreate(0,"Resistance",OBJ_HLINE,0,0,resistance);
        }
     }

//While other duties need more attention, and must be handled on lower time frames.
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_2,0);
      double bid,ask;   
                  
      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;
         bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
         ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
         
         //Check if we have broken either extreme
         if(PositionsTotal() == 0)
            {
               //We are looking for opportunities to sell
               if(iLow(Symbol(),TF_2,0) > resistance)
                  {
                     if(rsi[0] > 70) Trade.Sell(VOL,Symbol(),bid,(ask + (ATR_SIZE * atr[0])),(ask - (ATR_SIZE * atr[0])));
                  }
              
              //We are looking for opportunities to buy
              if(iHigh(Symbol(),TF_2,0) < support)
                  {
                     if(rsi[0] < 30) Trade.Buy(VOL,Symbol(),ask,(bid - (ATR_SIZE * atr[0])),(bid + (ATR_SIZE * atr[0])));
                  }
            }
         }      
        }
     }

Наконец, мы должны отменить определение системных констант, которые мы определили в начале приложения.

//+------------------------------------------------------------------+
//| Undefine the system constants                                    |
//+------------------------------------------------------------------+
#undef RSI_PERIOD
#undef RSI_PRICE
#undef ATR_PERIOD
#undef ATR_SIZE
#undef TF_1
#undef TF_2
#undef VOL
//+------------------------------------------------------------------+

Вот как выглядит наша текущая база кодов.

//+------------------------------------------------------------------+
//|                                  Self Adapting Trading Rules.mq5 |
//|                                               Gamuchirai Ndawana |
//|                    https://www.mql5.com/en/users/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Ndawana"
#property link      "https://www.mql5.com/en/users/gamuchiraindawa"
#property version   "1.00"

//+------------------------------------------------------------------+
//| System constants                                                 |
//+------------------------------------------------------------------+
#define RSI_PERIOD 10            //The period for our RSI indicator
#define RSI_PRICE  PRICE_CLOSE   //The price level our RSI should be applied to
#define ATR_SIZE   1.5             //How wide should our Stop loss be?
#define ATR_PERIOD 14            //The period of calculation for our ATR indicator
#define TF_1       PERIOD_D1     //The primary time frame for our trading application
#define TF_2       PERIOD_M15    //The secondary time frame for our trading application
#define VOL        0.1           //Our trading volume   

//+------------------------------------------------------------------+
//| Libraries we need                                                |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
CTrade Trade;

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int rsi_handler,atr_handler;
double rsi[],atr[];
double support,resistance;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   setup();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   release();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   update();
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| User defined methods                                             |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Initialize our system variables                                  |
//+------------------------------------------------------------------+
void setup(void)
  {
//Load our technical indicators
   atr_handler = iATR(Symbol(),TF_1,ATR_PERIOD);
   rsi_handler = iRSI(Symbol(),TF_2,RSI_PERIOD,RSI_PRICE);
   resistance  = iHigh(Symbol(),TF_1,5);
   support     = iLow(Symbol(),TF_1,5);
  }

//+------------------------------------------------------------------+
//| Let go of resources we are no longer consuming                   |
//+------------------------------------------------------------------+
void release(void)
  {
//Free up resources we are not using
   IndicatorRelease(atr_handler);
   IndicatorRelease(rsi_handler);
  }

//+------------------------------------------------------------------+
//| Update our system variables and look for trading setups          |
//+------------------------------------------------------------------+
void update(void)
  {
//Update our system variables
//Some duties must be performed periodically on the higher time frame
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_1,0);

      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;

         //Update indicator readings
         CopyBuffer(rsi_handler,0,0,1,rsi);
         CopyBuffer(atr_handler,0,0,1,atr);

         //Update our support and resistance levels
         support    = iLow(Symbol(),TF_1,5);
         resistance = iHigh(Symbol(),TF_1,5);
         ObjectDelete(0,"Support");
         ObjectDelete(0,"Resistance");
         ObjectCreate(0,"Suppoprt",OBJ_HLINE,0,0,support);
         ObjectCreate(0,"Resistance",OBJ_HLINE,0,0,resistance);
        }
     }

//While other duties need more attention, and must be handled on lower time frames.
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_2,0);
      double bid,ask;

      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;
         bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
         ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

         //Check if we have broken either extreme
         if(PositionsTotal() == 0)
           {
            //We are looking for opportunities to sell
            if(iLow(Symbol(),TF_2,0) > resistance)
              {
               if(rsi[0] > 70)
                  Trade.Sell(VOL,Symbol(),bid,(ask + (ATR_SIZE * atr[0])),(ask - (ATR_SIZE * atr[0])));
              }

            //We are looking for opportunities to buy
            if(iHigh(Symbol(),TF_2,0) < support)
              {
               if(rsi[0] < 30)
                  Trade.Buy(VOL,Symbol(),ask,(bid - (ATR_SIZE * atr[0])),(bid + (ATR_SIZE * atr[0])));
              }
           }
        }
     }
  }

//+------------------------------------------------------------------+
//| Undefine the system constants                                    |
//+------------------------------------------------------------------+
#undef RSI_PERIOD
#undef RSI_PRICE
#undef ATR_PERIOD
#undef ATR_SIZE
#undef TF_1
#undef TF_2
#undef VOL
//+------------------------------------------------------------------+

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

Скриншот 5

Рис. 5. Начало нашего тестирования на истории в MetaTrader 5

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

Скриншот 6

Рис. 6. Кривая эквити, полученная с помощью классической торговой стратегии RSI

На рис. 7 представлен подробный обзор того, как наше торговое приложение на основе RSI показало себя в первом тесте. Наша общая чистая прибыль составила USD 588,60 при коэффициенте Шарпа 0,85. На данный момент эти результаты обнадеживают. Нашей целью будет превзойти их в следующей версии нашего торгового приложения.

Скриншот 7

Рис. 7. Подробный обзор результатов, полученных в ходе нашего тестирования на истории



Улучшаем наши первоначальные результаты

Теперь мы пришли к предлагаемому решению, которое устраняет потенциальные проблемы, вызванные нестандартными результатами использования индикатора. Чтобы заменить классические уровни 70 и 30 оптимальными уровнями, выбранными непосредственно из исторических показателей рынка, мы должны сначала рассмотреть диапазон выходных данных, которые индикатор генерирует на данном рынке. После этого мы разделим пополам две параллельные линии, которые отмечают максимальный и минимальный выходные данные индикатора. Это разделение станет нашей новой средней точкой. Обратите внимание, что изначально средней точкой индикатора RSI является уровень 50.

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

Чтобы реализовать эти изменения в нашем приложении, нам необходимо внести следующие изменения:

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

Для начала давайте создадим необходимые нам новые системные константы. Нам необходимо динамически решать, сколько баров следует использовать в вычислениях, которые мы хотим выполнить. За это будет отвечать новая системная константа под названием BARS. Она вернет целое число, близкое к половине общего числа доступных баров. Кроме того, мы также решили, что нас интересуют только те изменения RSI, которые в 2 раза превышают среднее значение. Поэтому мы создали новую константу под названием BIG SIZE (большой размер), которая фиксирует предполагаемую силу, которую мы хотим наблюдать в наших ходах.

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

//+---------------------------------------------------------------+
//| System constants                                              |
//+---------------------------------------------------------------+
#define RSI_PERIOD     10                                          //The period for our RSI indicator
#define RSI_PRICE      PRICE_CLOSE                                 //The price level our RSI should be applied to
#define ATR_SIZE       1.5                                         //How wide should our Stop loss be?
#define ATR_PERIOD     14                                          //The period of calculation for our ATR indicator
#define TF_1           PERIOD_D1                                   //The primary time frame for our trading application
#define TF_2           PERIOD_M15                                  //The secondary time frame for our trading application
#define VOL            0.1                                         //Our trading volume   
#define BARS           (int) MathFloor((iBars(Symbol(),TF_2) / 2)) //How many bars should we use for our calculation?
#define BIG_SIZE       2                                           //How many times bigger than the average move should the observed change be?
#define SUPPORT_PERIOD 5                                           //How far back into the past should we look to find our support and resistance levels?

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

//While other duties need more attention, and must be handled on lower time frames.
     {
      static datetime time_stamp;
      datetime current_time = iTime(Symbol(),TF_2,0);
      double bid,ask;

      //Update the time
      if(time_stamp != current_time)
        {
         time_stamp = current_time;
         bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
         ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

         //Copy the rsi readings into a vector
         vector rsi_vector   = vector::Zeros(BARS);
         rsi_vector.CopyIndicatorBuffer(rsi_handler,0,1,BARS);

         //Let's see how far the RSI tends to deviate from its centre
         double rsi_midpoint = ((rsi_vector.Max() + rsi_vector.Min()) / 2);
         vector rsi_growth   = MathAbs(rsi_vector - rsi_midpoint);

         //Check if we have broken either extreme
         if(PositionsTotal() == 0)
           {
            //We are looking for opportunities to sell
            if(iLow(Symbol(),TF_2,0) > resistance)
              {
               if((rsi[0] - rsi_midpoint) > (rsi_growth.Mean() * BIG_SIZE))
                  Trade.Sell(VOL,Symbol(),bid,(ask + (ATR_SIZE * atr[0])),(ask - (ATR_SIZE * atr[0])));
              }

            //We are looking for opportunities to buy
            if(iHigh(Symbol(),TF_2,0) < support)
              {
               if((rsi[0] - rsi_midpoint) < (-(rsi_growth.Mean() * BIG_SIZE)))
                  Trade.Buy(VOL,Symbol(),ask,(bid - (ATR_SIZE * atr[0])),(bid + (ATR_SIZE * atr[0])));
              }
           }
        }
     }

Наконец, нам необходимо отменить определение новых системных констант, которые мы создали.

//+------------------------------------------------------------------+
//| Undefine the system constants                                    |
//+------------------------------------------------------------------+
#undef RSI_PERIOD
#undef RSI_PRICE
#undef ATR_PERIOD
#undef ATR_SIZE
#undef TF_1
#undef TF_2
#undef VOL
#undef BARS
#undef BIG_SIZE
#undef SUPPORT_PERIOD
//+------------------------------------------------------------------+

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

Скриншот 8

Рис. 8. Выберем правильную версию торгового приложения для нашего теста

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

Скриншот 9

Рис. 9. Кривая эквити, полученная с помощью нашей версии алгоритма торговли с динамическими правилами

В нашем первоначальном тесте общая чистая прибыль составила USD 588,60 за 136 сделок. Наша новая стратегия принесла прибыль в размере USD 703,20 за 121 сделку. Таким образом, наша прибыльность выросла примерно на 19,5%, в то время как общее количество заключенных нами сделок сократилось примерно на 11%. Очевидно, что наша новая система дает нам явное конкурентное преимущество по сравнению с классическими правилами, определяющими, как мы обычно должны использовать индикатор. 

Скриншот 10

Рис. 10: Подробные результаты, суммирующие эффективность нашей новой торговой стратегии



Заключение

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

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

Прикрепленный файл Описание
Self Adapting Trading Rules Тестовая версия нашего торгового приложения со статическими и фиксированными правилами.
Self Adapting Trading Rules V2 Усовершенствованная версия нашего торгового приложения, которая адаптирует свои правила на основе доступных рыночных данных.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/17049

Прикрепленные файлы |
Автоматизация торговых стратегий на MQL5 (Часть 12): Реализация стратегии смягчения ордер-блоков (MOB) Автоматизация торговых стратегий на MQL5 (Часть 12): Реализация стратегии смягчения ордер-блоков (MOB)
В настоящей статье нами будет создана торговая система на MQL5, которая автоматизирует обнаружение ордер-блоков для для торговли по концепции Smart Money. Мы опишем правила стратегии, реализуем логику средствами MQL5 и интегрируем управление рисками для эффективного совершения сделок. Наконец, проведём тестирование системы на истории, чтобы оценить ее эффективность и доработать для получения оптимальных результатов.
Нейросети в трейдинге: Обучение глубоких спайкинговых моделей (Окончание) Нейросети в трейдинге: Обучение глубоких спайкинговых моделей (Окончание)
В данной статье показана практическая реализация фреймворка SEW ResNet средствами MQL5 с акцентом на прикладное применение в торговле. Двойной Bottleneck даёт возможность одновременно анализировать унитарные потоки и межканальные зависимости, не теряя градиентов при обучении. Спайковые активации с адаптивными порогами и гейты повышают устойчивость к шуму и чувствительность к новизне рынка. В тексте приведены детали реализации и результаты тестов.
Автоматизация торговых стратегий на MQL5 (Часть 4): Построение многоуровневой системы зонального восстановления Автоматизация торговых стратегий на MQL5 (Часть 4): Построение многоуровневой системы зонального восстановления
В этой статье мы разработаем многоуровневую систему зонального восстановления в MQL5, которая использует RSI для генерации торговых сигналов. Каждый сигнал динамически добавляется в массив, что позволяет системе одновременно управлять несколькими сигналами в рамках логики зонального восстановления. Данный подход демонстрирует эффективную обработку сложных сценариев управления торговлей, сохраняя при этом масштабируемый и надежный дизайн кода.
Разработка инструментария для анализа движения цен (Часть 10): Внешние библиотеки (II) VWAP Разработка инструментария для анализа движения цен (Часть 10): Внешние библиотеки (II) VWAP
Освойте возможности VWAP с помощью нашего подробного руководства! Узнайте, как интегрировать анализ VWAP в вашу торговую стратегию, используя MQL5 и Python. Получите максимально полное представление о рынке и улучшите свои торговые решения уже сегодня.