English 中文 Español Deutsch 日本語 Português
preview
Реализация советника Deus: Автоматическая торговля с RSI и скользящими средними в MQL5

Реализация советника Deus: Автоматическая торговля с RSI и скользящими средними в MQL5

MetaTrader 5Трейдинг |
1 031 5
Duke825
[Удален]

Введение

В статье рассматриваются основные компоненты советника Deus, включая его торговую логику, настройки параметров и код MQL5, необходимый для его реализации. Цель статьи — снабдить вас знаниями и инструментами, необходимыми для разработки и улучшения вашего торгового алгоритма. Используя советник Deus, вы сможете исследовать мир автоматизированной торговли и открыть новые возможности для своего трейдинга.      

Мы рассмотрим функционал советника Deus — автоматизированной торговой методики, созданной с использованием MQL5. В ходе обсуждения основное внимание будет уделено тому, как советник Deus использует скользящие средние и индекс относительной силы (RSI) для принятия торговых решений. Анализируя эти индикаторы, советник определяет наилучшие точки входа и выхода на рынке, чтобы максимизировать прибыльность торговли и минимизировать риск.

Советник Deus — это автоматизированная торговая система, разработанная для платформы MetaTrader 5, которая генерирует сигналы на покупку и продажу на основе скользящих средних и индекса относительной силы (RSI). Определяя рыночные тренды и выявляя состояния перекупленности или перепроданности, он стремится улучшить торговые решения. Более того, советник включает в себя инструменты управления рисками, такие как стоп-лосс, тейк-профит и трейлинг-стопы. 


Обзор советника Deus 

Советник Deus использует индекс относительной силы (RSI) и скользящие средние для автоматизации торговых решений. Целью советника является повышение эффективности торговли и эффективное управление рисками путем использования этих индикаторов для выработки действенных рекомендаций по покупке и продаже.

Ниже приведены ключевые элементы советника Deus:

  1. Технические индикаторы:
  • Relative Strength Index (RSI) - этот импульсный осциллятор измеряет, насколько быстро и как движутся цены. Это помогает определить, когда рынок перекуплен или перепродан, и быстро реагировать на движения рынка. В нашем случае советник будет использовать короткий 7-дневный таймфрейм RSI с пороговыми значениями 35 для перекупленности и 15 для перепроданности.
  • Moving Averages (MA) - скользящая средняя выравнивает ценовые данные, чтобы выявить тренды за определенный период. Мы будем использовать 25-периодную простую скользящую среднюю (SMA) в советнике Deus для фильтрации торговых сигналов и определения общего направления рынка. 


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

    • Сигнал на продажу: Если цена ниже скользящей средней и RSI, это указывает на состояние перекупленности (выше 35), что предполагает возможный нисходящий тренд, и размещается ордер на продажу.


         3. Управление рисками:
    • Стоп-лосс и тейк-профит: в нашем советнике мы включаем настраиваемые параметры для уровней стоп-лосса и тейк-профита, установленные на 50 пунктов каждый, чтобы помочь управлять рисками и фиксировать прибыль.
    • Трейлинг-стоп: мы используем трейлинг-стоп в 25 пунктов для корректировки уровней стоп-лосса по мере благоприятного движения цены, стремясь обеспечить прибыль, при этом позволяя сделке оставаться открытой до тех пор, пока рынок движется в желаемом направлении.

          4. Управление ордерами:

    • Управление позициями: Одновременно может быть открыта только одна позиция, все существующие позиции закрываются перед открытием новой на основе торговых сигналов.

    Советник Deus имеет функции инициализации, обработки тиков, открытия и закрытия позиций, а также настройки трейлинг-стопа. Он реализован на языке скриптов MQL5, используемом в MetaTrader 5. Программирование необходимо для соблюдения рекомендаций по управлению рисками и эффективной обработки торговых сигналов.

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


      Реализация средствами MQL5

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

      #include <Trade\Trade.mqh>
      CTrade trade;

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

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

      Входные параметры следующие:

      input double Lots = 0.1;                     // Lot size
      input double StopLoss = 50;                  // Stop loss in points
      input double TakeProfit = 50;                // Take profit in points
      input double TrailingStop = 25;              // Trailing stop in points
      

      1. Lots (торговый объем)

      input double Lots = 0.1;                     // Lot size

      Размер каждой сделки определяется параметром Lots. В данном случае советник настроен на торговлю 0,1 лота в каждой сделке. Трейдеры могут управлять уровнем риска, изменяя размер лота. Меньший размер лота снижает как возможные риски, так и прибыль, в то время как больший размер лота не только увеличивает возможную прибыль, но и увеличивает риски. Чтобы сбалансировать риски и выгоды, важно выбрать правильный лот. 

             2. StopLoss (стоп-лосс в пунктах)

      input double StopLoss = 50;                  // Stop loss in points         

      Максимально допустимый убыток за сделку определяется опцией StopLoss и в нашем случае установлен на уровне 50 пунктов. Чтобы предотвратить будущие убытки, позиция автоматически закроется, если рынок пойдет против сделки за пределами этой точки. Это защитит ваш торговый счет от крупных потерь.  

             3. TakeProfit (тейк-профит в пунктах)

      input double TakeProfit = 50;                // Take profit in points

      Мы устанавливаем целевой показатель прибыли для каждой сделки в размере 50 пунктов с помощью параметра TakeProfit. Для обеспечения прибыли позиция автоматически закроется, когда рынок изменится на определенную величину в пользу сделки. Это обеспечит прибыль до возможного изменения рыночных условий и, следовательно, повысит прибыльность.

             4. TrailingStop (точки срабатывания трейлинг-стопа)

      input double TrailingStop = 25;              // Trailing stop in points

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

      Параметры индикатора RSI:

      input int RSI_Period = 7;                   // RSI period
      input double RSI_Overbought = 35.0;         // RSI overbought level
      input double RSI_Oversold = 15.0;           // RSI oversold level

              5. RSI_Period (период расчета RSI)

      input int RSI_Period = 7;                   // RSI period
            

      Количество периодов, используемых для генерации индекса относительной силы (RSI), задается параметром RSI_period. В нашем случае он равен 7. RSI - осциллятор импульса, который измеряет скорости и колебания цен. RSI более чувствителен к недавним ценовым колебаниям за короткий период, например, 7, что полезно для быстрого определения ситуаций перекупленности или перепроданности.

             6. RSI_Overbought (уровень перекупленности RSI)

      input double RSI_Overbought = 35.0;  

      Порог определения состояния перекупленности определяется параметром RSI_Overbought, который установлен на уровне 35.0. Обычно уровень перекупленности может быть равен 70, но при использовании этой методики значение 35,0 обозначает более агрессивную позицию продажи. Советник активирует продажу, когда RSI превышает этот порог, указывая на высокую вероятность разворота рынка вниз.  

               7. RSI_Oversold (уровни перепроданности RSI) 

      input double RSI_Oversold = 15.0;           // RSI oversold level
      

      Пороговое значение состояния перепроданности определяется параметром RSI_Oversold, который равен 15,0. Хотя этот подход использует более консервативный уровень для обозначения возможности покупки, типичный уровень перепроданности может быть равен тридцать. Советник активирует покупку, когда RSI падает ниже этого порога, поскольку это воспринимается как возможный разворот рынка вверх.

      Параметры Moving average

      input int MA_Period = 25;                   // Moving Average period
      input ENUM_MA_METHOD MA_Method = MODE_SMA// Moving Average method
      input ENUM_APPLIED_PRICE MA_Price = PRICE_CLOSE; // Applied price for MA

             8. MA_Period (период скользящей средней)

      input int MA_Period = 25;                   // Moving Average period

       Период расчета скользящей средней (MA) определяется параметром MA_Period, который равен 25. Ценовые данные сглаживаются скользящей средней для выявления тренда. 25-периодное окно обеспечит всесторонний обзор рыночных трендов, оно не только устранит краткосрочный шум, но и отреагирует на заметные изменения цен.    

             9. MA_Method (метод скользящей средней)

      Moving Average period
      input ENUM_MA_METHOD MA_Method = MODE_SMA// Moving Average method

         Тип скользящей средней, используемой в данном случае, простая скользящая средняя (SMA), определяется параметром MA_Method option. SMA — это простой трендовый индикатор, который вычисляет среднее значение цен закрытия за определенный период. Для различной чувствительности можно использовать альтернативные методы, такие как экспоненциальная скользящая средняя (EMA), но простая скользящая средняя (SMA) является надежным и устойчивым индикатором тренда.

            10. MA_Price (цена, применимая к скользящей средней)

      input ENUM_APPLIED_PRICE MA_Price = PRICE_CLOSE; // Applied price for MA
      

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

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

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

      //--- Variables
      double rsiValue;  // RSI value
      double maValue;   // Moving Average value
      double Ask;
      double Bid;
      double Close; // Initializing Close array with two elements

      Значение RSI:

      double rsiValue;                            // RSI value

      Текущее значение индекса относительной силы (RSI) сохраняется в переменной rsiValue. Будучи импульсным осциллятором, RSI помогает определить, когда рынок перекуплен или перепродан, рассчитывая скорость и дисперсию изменения цен.

      Для определения значения RSI используются тип цены и указанный период RSI. Для расчета RSI советник Deus использует заданные пользователем параметры и последние ценовые данные.

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

      С другой стороны, если значение RSI пересекает уровень RSI_Overbought снизу вверх, это сигнал к продаже. Это означает, что рынок перекуплен и может откатиться вниз. 

      Значение скользящей средней:

      double maValue;                             // Moving Average value

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

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

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

      Сигнал на вход: формирование торговых сигналов зависит от соотношения между значениями RSI и скользящей средней. Например, если предыдущая цена закрытия была выше значения скользящей средней, а RSI находится ниже уровня RSI_Oversold, то сигнал на покупку считается подтвержденным. Значения RSI и скользящей средней объединены в советнике Deus, что помогает ему принимать обоснованные торговые решения.

      double Ask;

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

      double Bid;

      Текущая цена bid актива устанавливается переменной Bid. Это цена продажи актива для трейдеров. Она устанавливает цену входа для ордеров на продажу в функции OpenPosition. Лучшая цена, которую можно получить за продажу актива, отражается в цене bid.

      double Close[];

      Цена закрытия актива за определенный период хранится в массиве Close. В этом советнике он расширен для хранения значений для текущего использования. Массив используется для формирования торговых сигналов и анализа движения цен. Чтобы решить, активировать ли сигнал на покупку или продажу, значение сравнивается с ценами закрытия предыдущего периода (Close[1]) и самого последнего периода (Close[0]). Это сравнение поможет нам определить, растет цена или падает. 

      void ApplyTrailingStop();

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

      void OpenPosition(CTrade trade, int orderType);

      В зависимости от типа ордера данный метод предназначен для открытия новых торговых позиций. Функция определяет тейк-профит, стоп-лосс и цену входа в зависимости от типа ордера. Сделка осуществляется с использованием вычисляемых параметров с использованием объекта CTrade. Это поможет советнику генерировать сигналы, которые могут оказаться крайне важными для начала торговли.

      void ClosePositions(int orderType);

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

      //--- Function prototypes
      void ApplyTrailingStop();
      void OpenPosition(CTrade trade, int orderType);

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

      Теперь перейдем к функции OnInit. Советник Deus использует функцию OnInit для начала торговли. Он предназначен для совершения сделок на основе индикаторов скользящей средней и RSI. 

      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
         Print("Deus  EA initialized successfully.");
         return(INIT_SUCCEEDED);
        }

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

       
         Print("Deus  EA initialized successfully.");

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

      return(INIT_SUCCEEDED);
        }

      Оператор return (INIT_SUCCEEDED); служит для уведомления платформы MetaTrader о завершении процесса инициализации. Советнику необходимо вернуть INIT_SUCCEEDED, чтобы перейти к следующим этапам, таким как функция OnTick, где выполняется основная торговая логика. Функция может вернуть INIT_FAILED, останавливая работу советника и предотвращая потенциальные сбои во время работы, если инициализация по какой-либо причине не удалась. 

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

      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
         Print("Deus  EA deinitialized. Reason: ", reason);
        }

      Обоснование деинициализации приводится в параметре reason функции OnDeinit. Это может помочь в отладке и выяснении причин деинициализации EA. Для регистрации этой причины мы используем функцию Print в советнике Deus.

      void OnDeinit(const int reason)
        {
         Print("Deus  EA deinitialized. Reason: ", reason);
        }

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

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

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

      • Получение рыночной информации; 

      При первом запуске функция OnTick помогает получить максимум рыночных данных.

          Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
          Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
          ArrayResize(Close, 2);
          Close[0] = iClose(_Symbol, _Period, 0);
          Close[1] = iClose(_Symbol, _Period, 1);

        Код сохраняет последние цены закрытия и получает цены ask и bid. Чтобы гарантировать, что в массиве Close достаточно места для хранения последней цены закрытия, используется ArrayResize.

        • Расчет технического индикатора; 

        Скользящая средняя и индекс относительной силы рассчитываются по алгоритму.

         //--- Calculate RSI value
           rsiValue = iRSI(_Symbol, _Period, RSI_Period, PRICE_CLOSE, 0);
           if (rsiValue == WRONG_VALUE)
             {
              Print("Error calculating RSI");
              return;
             }
           
           //--- Calculate Moving Average value
           maValue = iMA(_Symbol, _Period, MA_Period, 0, MA_Method, MA_Price, 0);
           if (maValue == WRONG_VALUE)
             {
              Print("Error calculating Moving Average");
              return;
             }

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

          • Формирование торгового сигнала; После расчета индикаторов функция ищет сигналы на покупку и продажу:
            //--- Check for Buy Signal
             if(rsiValue < RSI_Oversold && Close[1] > maValue)
               {
                if(PositionsTotal() == 0)
                  {
                   ClosePositions(ORDER_TYPE_SELL);
                   OpenPosition(ORDER_TYPE_BUY);
                  }
               }
             
             //--- Check for Sell Signal
             if(rsiValue > RSI_Overbought && Close[1] < maValue)
               {
                if(PositionsTotal() == 0)
                  {
                   ClosePositions(ORDER_TYPE_BUY);
                   OpenPosition(ORDER_TYPE_SELL);
                  }
             }

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

            Сигнал на продажу подается, когда цена закрытия ниже скользящей средней, а RSI выше порога перекупленности. Это указывает на возможный разворот в сторону понижения.

            • Применение трейлинг-стопа. Чтобы минимизировать убытки и защитить прибыль, функция OnTick содержит логику применения трейлинг-стопа.
               //--- Apply trailing stop if specified
               if (TrailingStop > 0)
                 {
                  ApplyTrailingStop();
                 }

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

              • Открытие и закрытие позиций: Функция OpenPosition пытается открыть позицию после определения цены входа, уровней стоп-лосса и тейк-профита. Закрытие позиции: Все позиции перебираются функцией ClosePositions, которая закрывает те из них, которые соответствуют заданному типу ордера.

              Это объясняет, как советник Deus динамически адаптируется к рыночным ситуациям, используя функцию OnTick. Эта функция использует индикаторы RSI и MA для генерации торговых сигналов и скользящих стопов для защиты прибыли. Благодаря этой стратегии советник гарантированно сохранит прибыль, а также отреагирует на изменения рынка. Ниже представлен полный код функции OnTick:

              //+------------------------------------------------------------------+
              //| Expert tick function                                             |
              //+------------------------------------------------------------------+
              void OnTick()
                {
                  Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
                  Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
                  ArrayResize(Close, 2);
                  Close[0] = iClose(_Symbol, _Period, 0);
                  Close[1] = iClose(_Symbol, _Period, 1);
                  
                  
                 //--- Calculate RSI value
                 rsiValue = iRSI(_Symbol, _Period, RSI_Period, PRICE_CLOSE, 0);
                 if (rsiValue == WRONG_VALUE)
                   {
                    Print("Error calculating RSI");
                    return;
                   }
                 
                 //--- Calculate Moving Average value
                 maValue = iMA(_Symbol, _Period, MA_Period, 0, MA_Method, MA_Price, 0);
                 if (maValue == WRONG_VALUE)
                   {
                    Print("Error calculating Moving Average");
                    return;
                   }
              
                 //--- Check for Buy Signal
                 if(rsiValue < RSI_Oversold && Close[1] > maValue)
                   {
                    if(PositionsTotal() == 0)
                      {
                       ClosePositions(ORDER_TYPE_SELL);
                       OpenPosition(ORDER_TYPE_BUY);
                      }
                   }
                 
                 //--- Check for Sell Signal
                 if(rsiValue > RSI_Overbought && Close[1] < maValue)
                   {
                    if(PositionsTotal() == 0)
                      {
                       ClosePositions(ORDER_TYPE_BUY);
                       OpenPosition(ORDER_TYPE_SELL);
                      }
                 }
                 
                 //--- Apply trailing stop if specified
                 if (TrailingStop > 0)
                   {
                    ApplyTrailingStop();
                   }

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

              void OpenPosition(int orderType)

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

              double price = (orderType == ORDER_TYPE_BUY) ? Ask : Bid;

              Цена {Ask} используется для ордера на покупку, а цена {Bid} - для ордера на продажу.

              Для контроля риска и обеспечения прибыли определяются пороговые значения стоп-лосса (SL) и тейк-профита (TP): 

              double sl = (orderType == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point;
              double tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point;

              Для ордеров на покупку тейк-профит устанавливается выше цены ордера, а стоп-лосс — ниже. Тейк-профит и стоп-лосс для ордеров на продажу размещаются ниже и выше цены ордера соответственно. Функция PositionOpen класса CTrade{ используется для открытия реальной позиции:

              bool result = trade.PositionOpen(_Symbol, orderType, Lots, price, sl, tp, "Deus  EA");
                 

              Такой подход требует несколько параметров: 

              • -{ Symbol} - торговый символ, например EURUSD.
              • -{ orderType} - тип ордера (продажа или покупка).
              • -"Lots" - размер лота ордера.
              • -{price} - цена bid и ask ордера.
              • -{sI} - уровень расчета стоп-лосса. 
              • -{tp} - расчетный порог тейк-профита.
              • -"Deus EA" - оператор ордера.

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

              if(result)
                   {
                    Print("Order opened successfully. Type: ", orderType, ", Price: ", price);
                   }
                 else
                   {
                    Print("Failed to open order. Error code: ", GetLastError());
                   }
                }

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

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

              //+------------------------------------------------------------------+
              //| Function to open a position                                      |
              //+------------------------------------------------------------------+
              void OpenPosition(int orderType)
                {
                 double price = (orderType == ORDER_TYPE_BUY) ? Ask : Bid;
                 double sl = (orderType == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point;
                 double tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point;
                 
                 bool result = trade.PositionOpen(_Symbol, orderType, Lots, price, sl, tp, "Deus  EA");
                 
                 if(result)
                   {
                    Print("Order opened successfully. Type: ", orderType, ", Price: ", price);
                   }
                 else
                   {
                    Print("Failed to open order. Error code: ", GetLastError());
                   }
                }  
               )    

              Мы закончили с одной из служебных функций, теперь давайте рассмотрим другую — функцию закрытия позиций. Функция ClosePositions советника Deus необходима для того, чтобы гарантировать закрытие нежелательных позиций в соответствии с параметрами торговой стратегии. При выполнении определенных условий функция управляет логикой закрытия позиций определенного типа (покупка или продажа). Давайте рассмотрим работу этой функции и ее значение для всей стратегии. 

              void OpenPosition(int orderType)

              Тип закрываемой позиции указывается одним аргументом orderType, который принимается функцией Closepositions. Возможные значения этого параметра — ORDER_TYPE_SELL или ORDER_TYPE_BUY. Функция перебирает все открытые позиции в этот момент и закрывает соответствующие.  

              for(int i = PositionsTotal() - 1; i >= 0; i--)
                   {
                    if(PositionSelectByIndex(i))
                      {
                       if(PositionGetInteger(POSITION_TYPE) == orderType)
                         {
                          if(!trade.PositionClose(ticket)
                            {
                             Print("Failed to close position. Error code: ", GetLastError());
                            }
                        }
                   }
                }

              Цикл движется назад, начиная с последней точки. Поскольку закрытие позиции снижает общее количество позиций, прямой цикл итерации может быть нарушен, что потребует обратной итерации. PositionSelectByIndex(i) используется для выбора позиции по заданному индексу {i}.

              Функция проверяет, соответствует ли выбранное местоположение заданному {orderType} внутри цикла.

              if(PositionGetInteger(POSITION_TYPE) == orderType)

              Если {orderType} не равен этому значению, позиция не должна быть закрыта. Функция пытается закрыть позицию, если тип совпадает.

              if(!trade.PositionClose(ticket)
                            {
                             Print("Failed to close position. Error code: ", GetLastError());
                            }
                        }
                   }
                }

              Позиция закрывается путем попытки идентифицировать ее по номеру тикета {trade.PositionClose(ticket)}). Если позиция не закрывается, выводится сообщение об ошибке с кодом ошибки, полученным с помощью GetLastError(). Это помогает определить причину невозможности закрыть позицию и облегчает устранение неполадок.

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

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

              //+------------------------------------------------------------------+
              //| Function to close positions                                      |
              //+------------------------------------------------------------------+
              void ClosePositions(int orderType)
                {
                 for(int i = PositionsTotal() - 1; i >= 0; i--)
                   {
                    if(PositionSelectByIndex(i))
                      {
                       if(PositionGetInteger(POSITION_TYPE) == orderType)
                         {
                          if(!trade.PositionClose(ticket)
                            {
                             Print("Failed to close position. Error code: ", GetLastError());
                            }
                        }
                   }
                }
              

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

              void ApplyTrailingStop()

              Поскольку он применим ко всем открытым позициям по текущему символу, метод ApplyTrailingStop не требует никаких параметров. Как и ClosePositions, функция начинается с перебора всех открытых позиций: 

              for (int i = PositionsTotal() - 1; i >= 0; i--)
                   {
                    if (PositionSelectByIndex(i) && PositionGetSymbol() == _Symbol)

              Цикл продвигается назад, начиная с последней позиции. 

              -{PositionSelectByIndex(i)}: функция выбирает запись с индексом {i}. Проверяет, связана ли позиция с активным торговым символом, с помощью {PositionGetSymbol()==_Symbol}.

              Функция использует расстояние трейлинг-стопа и текущую рыночную цену для определения нового уровня стопа:

               double price = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? Bid : Ask;
               double sl = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? price - TrailingStop * _Point : price + TrailingStop * _Point;
                       

              Трейлинг-стоп для позиций на покупку устанавливается ниже цены {bid}. Трейлинг-стоп размещается выше цены {Ask} для сделок на продажу. Затем функция использует PositionModify для применения нового уровня стоп-лосса после определения его целесообразности: 

              if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY && PositionGetDouble(POSITION_SL) < sl)
                         {
                          if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP)))
                            {
                             Print("Failed to modify position. Error code: ", GetLastError());
                            }
                         }
                       else if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_SELL && PositionGetDouble(POSITION_SL) > sl)
                         {
                          if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP)))
                            {
                             Print("Failed to modify position. Error code: ", GetLastError());
                            }
                         }
                      }

              Только когда новый уровень стоп-лосса ({sI)} превышает существующий, стоп-лосс позиций изменяется. Также, если новый уровень стоп-лосса меньше существующего, стоп-лосс обновляется для позиций на продажу.

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

              Полный код функции применения трейлинг-стопа выглядит следующим образом:

              //+------------------------------------------------------------------+
              //| Function to apply trailing stop                                  |
              //+------------------------------------------------------------------+
              void ApplyTrailingStop()
                {
                 for (int i = PositionsTotal() - 1; i >= 0; i--)
                   {
                    if (PositionSelectByIndex(i) && PositionGetSymbol() == _Symbol)
                      {
                       double price = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? Bid : Ask;
                       double sl = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? price - TrailingStop * _Point : price + TrailingStop * _Point;
                       
                       if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY && PositionGetDouble(POSITION_SL) < sl)
                         {
                          if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP)))
                            {
                             Print("Failed to modify position. Error code: ", GetLastError());
                            }
                         }
                       else if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_SELL && PositionGetDouble(POSITION_SL) > sl)
                         {
                          if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP)))
                            {
                             Print("Failed to modify position. Error code: ", GetLastError());
                            }
                         }
                      }

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

              //+------------------------------------------------------------------+
              //|                     Deus  EA                                     |
              //|     Copyright 2024, MetaQuotes Ltd.                              |
              //|                    https://www.mql5.com                          |
              //+------------------------------------------------------------------+
              #include <Trade\Trade.mqh>
              CTrade trade;
              
              //--- Input parameters
              input double Lots = 0.1;                 // Lot size
              input double StopLoss = 50;              // Stop loss in points
              input double TakeProfit = 50;            // Take profit in points
              input double TrailingStop = 25;          // Trailing stop in points
              
              //--- RSI parameters
              input int RSI_Period = 7;                // RSI period
              input double RSI_Overbought = 35.0;      // RSI overbought level
              input double RSI_Oversold = 15.0;        // RSI oversold level
              
              //--- Moving Average parameters
              input int MA_Period = 25;                // Moving Average period
              input ENUM_MA_METHOD MA_Method = MODE_SMA;  // Moving Average method
              input ENUM_APPLIED_PRICE MA_Price = PRICE_CLOSE; // Applied price for MA
              
              //--- Variables
              double rsiValue;  // RSI value
              double maValue;   // Moving Average value
              double Ask;
              double Bid;
              double Close[2];  // Initializing Close array with two elements
              
              //--- Function prototypes
              void ApplyTrailingStop();
              void OpenPosition(CTrade &trade, int orderType); // Pass CTrade by reference
              void ClosePositions(int orderType);           // pass orderType directly
               
              //+------------------------------------------------------------------+
              //| Expert initialization function                                   |
              //+------------------------------------------------------------------+
              int OnInit()
                {
                 Print("Deus  EA initialized successfully.");
                 return(INIT_SUCCEEDED);
                }
               
              //+------------------------------------------------------------------+
              //| Expert deinitialization function                                 |
              //+------------------------------------------------------------------+
              void OnDeinit(const int reason)
                {
                 Print("Deus  EA deinitialized. Reason: ", reason);
                }
              
              //+------------------------------------------------------------------+
              //| Expert tick function                                             |
              //+------------------------------------------------------------------+
              void OnTick()
                {
                //--- Update current prices
                  Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
                  Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
                  ArrayResize(Close, 2);
                   Close[0] = iClose(_Symbol, Period(), 0);
                  Close[1] = iClose(_Symbol, Period(), 1);
                 
                  
                 //--- Calculate RSI value
                 rsiValue = iRSI(_Symbol, _Period, RSI_Period, PRICE_CLOSE, 0);
                 if (rsiValue == WRONG_VALUE)
                   {
                    Print("Error calculating RSI");
                    return;
                   
                 //--- Calculate Moving Average value
                 maValue = iMA(_Symbol, _Period, MA_Period, 0, MA_Method, MA_Price, 0);
                 if (maValue == WRONG_VALUE)
                   {
                    Print("Error calculating Moving Average");
                    return;
                   }
              
                 //--- Check for Buy Signal
                 if(rsiValue < RSI_Oversold && Close[1] > maValue)
                   {
                    if(PositionsTotal() == 0)
                      {
                       ClosePositions(ORDER_TYPE_SELL);
                       OpenPosition(ORDER_TYPE_BUY);
                      }
                   }
                 
                 //--- Check for Sell Signal
                 if(rsiValue > RSI_Overbought && Close[1] < maValue)
                   {
                    if(PositionsTotal() == 0)
                      {
                       ClosePositions(ORDER_TYPE_BUY);
                       OpenPosition(ORDER_TYPE_SELL);
                      }
                    }
                 
                 //--- Apply trailing stop if specified
                 if(TrailingStop > 0)
                   {
                    ApplyTrailingStop();
                   }
                 }
                 
              //+------------------------------------------------------------------+
              //| Function to open a position                                      |
              //+------------------------------------------------------------------+
              void OpenPosition(int orderType)
                {
                 //--- Determine price stop loss, and take profit levels 
                 double price = (orderType == ORDER_TYPE_BUY) ? Ask : Bid;
                 double sl = (orderType == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point;
                 double tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point;
                 
                 
                 bool result = trade.PositionOpen(_Symbol, orderType, Lots, price, sl, tp, "Deus  EA");
                 
                 if(result)
                   {
                    Print("Order opened successfully. Type: ", orderType, ", Price: ", price);
                   }
                 else
                   {
                    Print("Failed to open order. Error code: ", GetLastError());
                   }
                }
              
              //+------------------------------------------------------------------+
              //| Function to close positions                                      |
              //+------------------------------------------------------------------+
              void ClosePositions(int orderType)
                {
                 for(int i = PositionsTotal() - 1; i >= 0; i--)
                   {
                    if(PositionSelectByIndex(i))
                      {
                      //--- Check if the positions type matches the order type to be closed
                       if(PositionGetInteger(POSITION_TYPE) == orderType)
                         {
                         ulong ticket = PositionGetInteger(POSITION_TICKET);
                          if(!trade.PositionClose(ticket)
                            {
                             Print("Failed to close position. Error code: ", GetLastError());
                            }
                          }
                        }
                     }
                   }
              
              
              //+------------------------------------------------------------------+
              //| Function to apply trailing stop                                  |
              //+------------------------------------------------------------------+
              void ApplyTrailingStop()
                {
                 for (int i = PositionsTotal() - 1; i >= 0; i--)
                   {
                    if (PositionSelectByIndex(i) && PositionGetSymbol() == _Symbol)
                      {
                       double price = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? Bid : Ask;
                       double sl = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? price - TrailingStop * _Point : price + TrailingStop * _Point;
                       
                       //--- Trailing  stop logic for buy positions 
                       if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY && PositionGetDouble(POSITION_SL) < sl)
                         {
                          if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP)))
                            {
                             Print("Failed to modify position. Error code: ", GetLastError());
                            }
                         }
                      
                       //--- Trailing stop logic for sell positions
                       else if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_SELL && PositionGetDouble(POSITION_SL) > sl)
                         {
                          if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP)))
                            {
                             Print("Failed to modify position. Error code: ", GetLastError());
                            }
                         }
                      }
                    }
                     

              Поздравляю! Мы внедрили советник Deus для автоматизации торговли.

              Вот результаты тестов:



              Отчет:


              Тест проводился на USDJPY с 10.07.2024 по 06.08.2024 на H1. Используемые параметры те же, что мы использовали при изучении реализации.  

              Этот тип стратегии лучше всего подходит для валютных пар EURUSD и USDJPY, но только если вам не нужен высокий процент выигрышей. Ниже приведены параметры тестирования советника:


              Заключение

              Советник Deus использует скользящие средние и индекс относительной силы (RSI) для генерации торговых сигналов, объединяя технические индикаторы для управления и извлечения прибыли из рыночных возможностей. В статье подробно описаны торговая логика, контроль рисков и код MQL5, лежащий в основе советника, который автоматизирует торговые решения для повышения согласованности и снижения влияния эмоций.

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

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


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

              Прикрепленные файлы |
              Deus_EA.mq5 (9.28 KB)
              Последние комментарии | Перейти к обсуждению на форуме трейдеров (5)
              Cristian-bogdan Buzatu
              Cristian-bogdan Buzatu | 8 авг. 2024 в 15:58
              Он выдает ошибку компиляции.
              Lucas Damien Lafon
              Lucas Damien Lafon | 8 авг. 2024 в 17:59

              Не могли бы вы объяснить, почему вы используете 15 и 35 в качестве предельных значений для RSI?

              Мне кажется, что это не имеет смысла, это похоже на трюк, чтобы заставить ваш бэктест работать только в течение 1 месяца, который вы показываете...

              Cornelis Cornelius
              Cornelis Cornelius | 14 авг. 2024 в 13:57
              Cristian-bogdan Buzatu #:
              Он выдает ошибку компиляции.

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

              Cornelis Cornelius
              Cornelis Cornelius | 14 авг. 2024 в 13:58
              Lucas Damien Lafon бэктест работать только в течение 1 месяца, который вы показываете...

              Я согласен, если вы используете 15 в качестве уровня перепроданности, то уровень перекупленности должен быть 85, а не 35.

              mbaas
              mbaas | 17 авг. 2024 в 11:25
              Кто-нибудь тестирует эти материалы перед публикацией? Отсутствие родительного падежа, вызов функций с неправильной подписью - удручающе много ошибок!
              От начального до среднего уровня: Оператор SWITCH От начального до среднего уровня: Оператор SWITCH
              В данной статье мы узнаем, как использовать оператор SWITCH в ее самой простой и базовой форме. Представленные здесь материалы предназначены только для обучения. Ни в коем случае не рассматривайте это приложение как окончательное, цели которого будут иные, кроме изучения представленных концепций.
              Разработка системы репликации (Часть 64): Нажатие кнопки воспроизведения в сервисе (V) Разработка системы репликации (Часть 64): Нажатие кнопки воспроизведения в сервисе (V)
              В данной статье мы рассмотрим, как исправить две ошибки в коде. Однако я постараюсь объяснить их так, чтобы вы, начинающие программисты, поняли, что не всегда всё происходит так, как вы предполагали. Но это не повод отчаиваться, это возможность учиться. Представленные здесь материалы предназначены только для обучения. Ни в коем случае не рассматривайте это приложение как окончательное, цели которого иные, кроме изучения представленных концепций.
              Биологический нейрон для прогнозирования финансовых временных рядов Биологический нейрон для прогнозирования финансовых временных рядов
              Выстраиваем биологически верную систему нейронов для прогнозирования временных рядов. Внедрение плазмоподобной среды в архитектуру нейронной сети создало своеобразный "коллективный разум", где каждый нейрон влияет на работу системы не только через прямые связи, но и посредством дальнодействующих электромагнитных взаимодействий. Как покажет себя нейронная система моделирования мозга на рынке?
              Индикатор прогноза волатильности при помощи Python Индикатор прогноза волатильности при помощи Python
              Прогнозируем будущую экстремальную волатильность при помощи бинарной классификации. Создаем индикатор прогноза экстремальной волатильности с использованием машинного обучения.