English Español Deutsch 日本語
preview
Построение модели для ограничения диапазона сигналов по тренду (Часть 9): Советник с несколькими стратегиями (I)

Построение модели для ограничения диапазона сигналов по тренду (Часть 9): Советник с несколькими стратегиями (I)

MetaTrader 5Торговые системы | 30 апреля 2025, 11:01
558 0
Clemence Benjamin
Clemence Benjamin

Содержание:



Введение

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

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

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

 Условие бычьей свечи в MQL5:

void OnTick()
{
    // Determine current daily trend (bullish )
    double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
    double daily_close = iClose(_Symbol, PERIOD_D1, 0);

    bool is_bullish = daily_close > daily_open;
}

Условие медвежьей свечи в MQL5:

void OnTick()
{
    // Determine current daily trend (bearish)
    double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
    double daily_close = iClose(_Symbol, PERIOD_D1, 0);

    
    bool is_bearish = daily_close < daily_open;
}

В приведенном выше коде ограничивающим фактором служит настроение на более крупном таймфрейме. В данном случае мы выбрали таймфрейм D1.

Реализация условия ограничения:

Теперь, когда мы определили медвежьи и бычьи настроения нашей дневной свечи, мы можем использовать функцию ''if()'' вместе с нашей логикой условий входа. 

Для бычьего дня:

 if (is_bullish)
    {
        // Logic for bullish trend
        Print("The daily trend is bullish.");

   // You can add your trading logic here, for example:
        // if (OrderSelect(...)) { /* Place buy order */ }
    }

Для медвежьего дня:

 if (is_bearish)
    {
        // Logic for bearish trend
        Print("The daily trend is bearish.");
        // You can add your trading logic here, for example:
        // if (OrderSelect(...)) { /* Place sell order */ }
    }

К концу этого обсуждения вы, возможно, сможете лучше понимать:

1. Другие стратегии и людей, стоящих за ними.

2. Внедрение новой стратегии в модули существующего советника.

3. Реализация магического числа.

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

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

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

Предупреждение об ошибке

Предупреждение при компиляции

Эта ошибка была в строке 78 и столбце 28:

предупреждение

Предупреждение в строке 78, столбце 28

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

long position_type = PositionGetInteger(POSITION_TYPE);

Исправление выше включало замену int на long.

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

//+------------------------------------------------------------------+
//|                                      Trend Constraint Expert.mq5 |
//|                                Copyright 2024, Clemence Benjamin |
//|             https://www.mql5.com/en/users/billionaire2024/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Clemence Benjamin"
#property link      "https://www.mql5.com/en/users/billionaire2024/seller"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>  // Include the trade library

// Input parameters
input int    RSI_Period = 14;            // RSI period
input double RSI_Overbought = 70.0;      // RSI overbought level
input double RSI_Oversold = 30.0;        // RSI oversold level
input double Lots = 0.1;                 // Lot size
input double StopLoss = 100;             // Stop Loss in points
input double TakeProfit = 200;           // Take Profit in points
input double TrailingStop = 50;          // Trailing Stop in points

// Global variables
double rsi_value;
int rsi_handle;
CTrade trade;  // Declare an instance of the CTrade class

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Create an RSI indicator handle
   rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
   if (rsi_handle == INVALID_HANDLE)
     {
      Print("Failed to create RSI indicator handle");
      return(INIT_FAILED);
     }

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // Release the RSI indicator handle
   IndicatorRelease(rsi_handle);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Determine current daily trend (bullish or bearish)
   double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
   double daily_close = iClose(_Symbol, PERIOD_D1, 0);

   bool is_bullish = daily_close > daily_open;
   bool is_bearish = daily_close < daily_open;

   // Get the RSI value for the current bar
   double rsi_values[];
   if (CopyBuffer(rsi_handle, 0, 0, 1, rsi_values) <= 0)
     {
      Print("Failed to get RSI value");
      return;
     }
   rsi_value = rsi_values[0];

   // Close open positions if the trend changes
   for (int i = PositionsTotal() - 1; i >= 0; i--)
     {
      if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
        {
         long position_type = PositionGetInteger(POSITION_TYPE);
         ulong ticket = PositionGetInteger(POSITION_TICKET);  // Get the position ticket

         if ((position_type == POSITION_TYPE_BUY && is_bearish) ||
             (position_type == POSITION_TYPE_SELL && is_bullish))
           {
            trade.PositionClose(ticket);  // Use the ulong variable directly
           }
        }
     }

   // Check for buy condition (bullish trend + RSI oversold)
   if (is_bullish && rsi_value < RSI_Oversold)
     {
      // No open positions? Place a buy order
      if (PositionsTotal() == 0)
        {
         double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         double sl = price - StopLoss * _Point;
         double tp = price + TakeProfit * _Point;

         // Open a buy order
         trade.Buy(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Buy");
        }
     }

   // Check for sell condition (bearish trend + RSI overbought)
   if (is_bearish && rsi_value > RSI_Overbought)
     {
      // No open positions? Place a sell order
      if (PositionsTotal() == 0)
        {
         double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double sl = price + StopLoss * _Point;
         double tp = price - TakeProfit * _Point;

         // Open a sell order
         trade.Sell(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Sell");
        }
     }

   // Apply trailing stop
   for (int i = PositionsTotal() - 1; i >= 0; i--)
     {
      if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
        {
         double price = PositionGetDouble(POSITION_PRICE_OPEN);
         double stopLoss = PositionGetDouble(POSITION_SL);
         double current_price;

         if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
           {
            current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            if (current_price - price > TrailingStop * _Point)
              {
               if (stopLoss < current_price - TrailingStop * _Point)
                 {
                  trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price - TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                 }
              }
           }
         else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
           {
            current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            if (price - current_price > TrailingStop * _Point)
              {
               if (stopLoss > current_price + TrailingStop * _Point || stopLoss == 0)
                 {
                  trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price + TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+


Семь избранных стратегий

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

(i) Стратегия следования за трендом

Стратегия следования за трендом основана на принципах Чарльза Доу, который сформулировал теорию Доу в 1896 году. Доу считал, что рынки движутся в соответствии с трендами, и выявление этих трендов может предоставить существенные торговые возможности. Математика, лежащая в основе следования за трендом, часто использует скользящие средние, где трейдеры используют простую скользящую среднюю (SMA) для сглаживания колебаний цен.

Фактическая формула для простой скользящей средней (SMA) выглядит так:

SMA

где:

  • - это количество периодов (или точек данных).
  • (P_i) - цена в (i-м) периоде.

Эта формула рассчитывает среднюю цену за N периодов. Сопутствующие исследования, в частности работы Ричарда Денниса о "стратегии черепах", опубликованные в 1980-е, показал, что следование тренду может принести значительную прибыль, особенно на рынках с сильными трендами.

(ii) Торговля в диапазоне

Торговля в диапазоне основана на концепциях уровней поддержки и сопротивления, имеющих решающее значение для технического анализа. Эти концепции были хорошо описаны в книге Джона Уэллеса Уайлдера (J. Welles Wilder) в его книге "Новые концепции в технических торговых системах" (New Concepts in Technical Trading Systems), вышедшей в 1978 году. Трейдеры определяют поддержку как уровень цен, при котором покупательский интерес предотвращает падение, а сопротивление сдерживает рост цен. Математическая основа для расчета точек разворота (pivot points), общепринятый метод определения этих уровней, задается следующим образом:

Формула для расчета точки разворота выглядит так:

расчет точки разворота

где:

  • High - максимальная цена предыдущего торгового периода.
  • Low - минимальная цена предыдущего торгового периода.
  • Close - цена закрытия предыдущего торгового периода.

Эта формула вычисляет центральную точку разворота, используемую в техническом анализе для определения потенциальных уровней поддержки и сопротивления на предстоящий торговый период. Исследования, такие как работа Джона Мерфи "Технический анализ финансовых рынков" (1986), подчеркивают, что уровни поддержки и сопротивления часто служат психологическими индикаторами, которые могут помочь трейдерам принимать обоснованные решения.

(iii) Торговля на прорывах

Торговля на прорывах основана на убеждении, что существенные ценовые движения происходят, когда цены прорываются через установленные уровни поддержки или сопротивления. Ричард Дончян (Дончиан) представил эту стратегию в 1950-х годах. Работа с каналами Дончиана подчеркивает использование волатильности для определения точек прорыва. Трейдеры рассчитывают каналы Дончяна, используя самый высокий максимум (highest high, HH) и самый низкий минимум (lowest low, LL) за указанный период:

(Верхняя полоса = HH)

(Нижняя полоса = LL)

Каналы Дончяна (Дончиана)

Канал Дончяна (Дончиана)

Исследования в области поведенческих финансов подтверждают идею о том, что трейдеры часто следуют за прорывами из-за стадного поведения, которое усиливает импульс в направлении прорыва. В статье Даниэля Канемана и Амоса Тверски "Теория перспектив: анализ принятия решений в условиях риска" (Prospect Theory: An Analysis of Decision under Risk) подчеркивается, как психологические факторы влияют на поведение трейдеров во время прорывов.

(iv) Кэрри-трейд

В основе стратегии лежит разница в процентных ставках между двумя валютами на основе теории паритета процентных ставок (Interest Rate Parity, IRP). Этот принцип исходит из экономических теорий, сформулированных Полом Самуэльсоном в работе "Основания экономического анализа" (Foundations of Economic Analysis), вышедшей в 1947 году, и другими исследователями первой половины двадцатого века

Основная формула для расчета ожидаемой доходности от сделки керри-трейд выглядит так:

ER

где:

  • (i_high) и (i_low) - процентные ставки по высокодоходным и низкодоходным валютам соответственно.
  • (Delta S) - ожидаемое изменение обменного курса. 
 Кеннет Рогофф в своей статье 1998 года подчеркивает, как отклонения от паритета процентных ставок могут создавать торговые возможности.

(v) Скальпинг

Скальпинг — это высокочастотная торговая стратегия, использующая небольшие ценовые колебания и основанная на теории микроструктуры рынка (Market Microstructure Theory, ММТ). Эта теория развивалась различными исследователями, включая Лоуренса Харриса, в частности его работу 1998 года "Формирование рынка и финансовые результаты компаний Nasdaq" (Market Making and the Financial Performance of Nasdaq Firms). Скальперы совершают множество сделок в течение коротких промежутков времени, стремясь получить прибыль от малейших изменений цен.

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

прибыль

где:

  • (Selling Price) - цена продажи актива.

  • (Buying Price) - цена изначальной покупки актива.

  • (Transaction Costs) - любые комиссии или расходы, связанные с процессом купли-продажи (например, брокерские комиссии, налоги).

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

(vi) Фундаментальный анализ

Фундаментальный анализ включает изучение экономических показателей и геополитических факторов, влияющих на стоимость валют. Основы впервые были изложены в работе Бенджамина Грэма и Дэвида Додда "Анализ ценных бумаг" (Security Analysis) 1934 года. Этот подход подчеркивает важность оценки внутренней стоимости валют. Трейдеры используют различные показатели, такие как рост валового внутреннего продукта (ВВП) и уровень безработицы, для принятия обоснованных решений. Также можно адаптировать математические методы, такие как коэффициент цены к прибыли (Price-to-Earnings, P/E) для акций;

P^E

где:

  • (Market Price per share) - текущая цена одной акции компании.

  • Earnings per Share (EPS) - прибыль компании, распределенная на каждую размещенную акцию обыкновенных акций.

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


(vii) Технические индикаторы

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

RSI

где:

  • (RS) - средние прибыли и убытки за определенный период.

RS

Различные исследования, включая работу Томаса Булковски "Полная энциклопедия графических ценовых моделей" (Encyclopedia of Candlestick Charts) 2008 года, показывают, что определенные модели и индикаторы могут повысить точность торговли, позволяя трейдерам предвидеть движения рынка на основе исторического ценового поведения. Каждая из этих стратегий подкреплена фундаментальными теориями, математическими принципами и обширными исследованиями, которые помогают трейдерам принимать решения на рынке Форекс. Понимание тонкостей этих стратегий может значительно повысить способность трейдера ориентироваться в сложностях торговли на рынке Форекс, что в конечном итоге приведет к более обоснованным и прибыльным результатам торговли. Продуманно применяя эти стратегии, трейдеры могут разработать надежный торговый подход, соответствующий их индивидуальным предпочтениям и уровню риска.


Включение магического числа

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

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

Функция PositionGetInteger(POSITION_MAGIC) извлекает магическое число, прикрепленное к каждой сделке, что позволяет советнику принять решение о следующем шаге - изменить, отслеживать или закрыть позицию. Для трейдера или разработчика это означает меньше беспокойства о случайном взаимодействии различных стратегий и более простую отладку, поскольку каждую сделку можно отследить до ее исходной стратегии. Таким образом, эффективное использование и управление магическими числами гарантирует, что ваши торговые стратегии на финансовых рынках останутся точными и хорошо организованными.

Ниже фрагмент кода, демонстрирующий включение:

input int MagicNumber = 12345678; // Define a unique magic number for the EA

// Within the OnTick() or relevant function
for (int i = 0; i < PositionsTotal(); i++) {
    if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i))) {
        long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);

        if (currentMagicNumber == MagicNumber) { // Check if the position belongs to this EA
            // Perform actions on this position, like closing or modifying
        }
    }
}

// When opening a new trade
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double sl = price - StopLoss * _Point;
double tp = price + TakeProfit * _Point;

if (trade.Buy(Lots, _Symbol, price, sl, tp, "TrendFollowing Buy")) {
    Print("Buy order placed with Magic Number: ", MagicNumber);
} else {
    Print("Error placing buy order: ", GetLastError());


Реализация стратегии следования тренду

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

Следование тренду — это подход, который определяет устойчивую рыночную тенденцию и торгует в ее направлении, используя такие методы, как скользящие средние, для подтверждения направления тренда. Код нашего советника уже использует RSI для оценки условий перекупленности или перепроданности, но интеграция скользящих средних может дополнительно усовершенствовать процесс принятия решений. Здесь мы используем краткосрочную (50-периодную) скользящую среднюю и долгосрочную (200-периодную) скользящую среднюю для определения направления тренда. Если краткосрочная средняя пересекает долгосрочную среднюю снизу вверх, это сигнал восходящего тренда; и наоборот, пересечение сверху вниз указывает на нисходящий тренд. Интеграция этого метода помогает подтверждать бычьи или медвежьи тренды, повышая точность торговых входов в условиях RSI.

 Вот наш фрагмент кода для расчета скользящих средних перед интеграцией в основную программу.

//Calculate moving averages
double ma_short = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE, 0);
double ma_long = iMA(_Symbol, PERIOD_CURRENT, 200, 0, MODE_EMA, PRICE_CLOSE, 0);

//Determine the trend  direction
bool is_uptrend = ma_short > ma_long;
bool is_downtrend = ma_short < ma_long;

if (is_bullish && is_uptrend && rsi_value < RSI_Oversold)
{
   // Implement buy order logic here
}

if (is_bearish && is_downtrend && rsi_value > RSI_Overbought)
{
   // Implement sell order logic here
}

Чтобы эффективно внедрить стратегию следования за трендом в существующий советник, мы начинаем с улучшения логики инициализации и обработки в его модулях. Начиная с функции OnInit(), мы вводим расчет двух критических экспоненциальных скользящих средних (EMA), обычно 50-периодных для краткосрочных трендов и 200-периодных - для долгосрочных.

По мере продвижения к методу OnTick() эти EMA пересчитываются с каждым новым рыночным тиком, что позволяет советнику определять текущее направление рыночного тренда. Пересечение, при котором краткосрочная EMA поднимается выше долгосрочной, сигнализирует о восходящем тренде, тогда как пересечение, при котором она опускается ниже, указывает на нисходящий тренд.

Интегрируя эти трендовые сигналы с существующим анализом RSI, мы создаем условия, при которых алгоритм открывает ордера на покупку во время подтвержденного восходящего тренда, когда RSI перепродан, и ордера на продажу во время нисходящего тренда, когда RSI перекуплен.

Использование класса CTrade для исполнения, мы тщательно устанавливаем параметры стоп-лосса, тейк-профита и трейлинг-стопа, обеспечивая надежное управление рисками. Кроме того, в том же цикле OnTick() реализована система, позволяющая плавно закрыть любые существующие позиции в случае разворота выявленного тренда, тем самым согласовывая каждую сделку с проверенным направлением рынка. Благодаря этим стратегическим обновлениям советник умело адаптирован для использования стратегии следования за трендом, легко интегрируя ее с текущими функциональными возможностями и повышая общую эффективность торговли.

Ниже представлена полностью интегрированная программа:

//+------------------------------------------------------------------+
//|                                      Trend Constraint Expert.mq5 |
//|                                Copyright 2024, Clemence Benjamin |
//|             https://www.mql5.com/en/users/billionaire2024/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Clemence Benjamin"
#property link      "https://www.mql5.com/en/users/billionaire2024/seller"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>  // Include the trade library

// Input parameters
input int    RSI_Period = 14;            // RSI period
input double RSI_Overbought = 70.0;      // RSI overbought level
input double RSI_Oversold = 30.0;        // RSI oversold level
input double Lots = 0.1;                 // Lot size
input double StopLoss = 100;             // Stop Loss in points
input double TakeProfit = 200;           // Take Profit in points
input double TrailingStop = 50;          // Trailing Stop in points
input int    MagicNumber = 12345678;     // Magic number for this EA

// Global variables
double rsi_value;
int rsi_handle;
CTrade trade;  // Declare an instance of the CTrade class

// Variables for moving averages
double ma_short;
double ma_long;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Create an RSI indicator handle
   rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
   if (rsi_handle == INVALID_HANDLE)
     {
      Print("Failed to create RSI indicator handle");
      return(INIT_FAILED);
     }

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // Release the RSI indicator handle
   IndicatorRelease(rsi_handle);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Calculate moving averages
   ma_short = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE);
   ma_long  = iMA(_Symbol, PERIOD_CURRENT, 200, 0, MODE_EMA, PRICE_CLOSE);

   // Determine trend direction
   bool is_uptrend = ma_short > ma_long;
   bool is_downtrend = ma_short < ma_long;

   // Get the RSI value for the current bar
   double rsi_values[];
   if (CopyBuffer(rsi_handle, 0, 0, 1, rsi_values) <= 0)
     {
      Print("Failed to get RSI value");
      return;
     }
   rsi_value = rsi_values[0];

   // Close open positions if the trend changes
   for (int i = 0; i < PositionsTotal(); i++) // Correct loop initialization
     {
      if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i)))  // Select position by symbol
        {
         long position_type = PositionGetInteger(POSITION_TYPE);
         long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);
         ulong ticket = PositionGetInteger(POSITION_TICKET);

         if (currentMagicNumber == MagicNumber) // Ensure only this EA's orders are checked
           {
            if ((position_type == POSITION_TYPE_BUY && is_downtrend) ||
                (position_type == POSITION_TYPE_SELL && is_uptrend))
              {
               trade.PositionClose(ticket);
              }
           }
        }
     }

   // Check for buy condition (uptrend + RSI oversold)
   if (is_uptrend && rsi_value < RSI_Oversold)
     {
      // No open positions? Place a buy order
      bool open_position = false;

      for (int i = 0; i < PositionsTotal(); i++) // Correct loop initialization
        {
         if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i)))
           {
            long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);

            if (currentMagicNumber == MagicNumber)
              {
               open_position = true;
               break;
              }
           }
        }

      if (!open_position)
        {
         double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         double sl = price - StopLoss * _Point;
         double tp = price + TakeProfit * _Point;

         // Open a buy order
         if (trade.Buy(Lots, _Symbol, price, sl, tp, "TrendFollowing Buy"))
            Print("Buy order placed with Magic Number: ", MagicNumber);
         else
            Print("Error placing buy order: ", GetLastError());
        }
     }

   // Check for sell condition (downtrend + RSI overbought)
   if (is_downtrend && rsi_value > RSI_Overbought)
     {
      // No open positions? Place a sell order
      bool open_position = false;

      for (int i = 0; i < PositionsTotal(); i++) // Correct loop initialization
        {
         if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i)))
           {
            long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);

            if (currentMagicNumber == MagicNumber)
              {
               open_position = true;
               break;
              }
           }
        }

      if (!open_position)
        {
         double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double sl = price + StopLoss * _Point;
         double tp = price - TakeProfit * _Point;

         // Open a sell order
         if (trade.Sell(Lots, _Symbol, price, sl, tp, "TrendFollowing Sell"))
            Print("Sell order placed with Magic Number: ", MagicNumber);
         else
            Print("Error placing sell order: ", GetLastError());
        }
     }

   // Apply trailing stop
   for (int i = 0; i < PositionsTotal(); i++) // Correct loop initialization
     {
      if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i))) // Select position by symbol
        {
         long currentMagicNumber = PositionGetInteger(POSITION_MAGIC);

         if (currentMagicNumber == MagicNumber) // Apply trailing stop only to this EA's positions
           {
            double price = PositionGetDouble(POSITION_PRICE_OPEN);
            double stopLoss = PositionGetDouble(POSITION_SL);
            double current_price;

            if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
              {
               current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
               if (current_price - price > TrailingStop * _Point)
                 {
                  if (stopLoss < current_price - TrailingStop * _Point)
                    {
                     trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price - TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                    }
                 }
              }
            else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
              {
               current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
               if (price - current_price > TrailingStop * _Point)
                 {
                  if (stopLoss > current_price + TrailingStop * _Point || stopLoss == 0)
                    {
                     trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price + TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                    }
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+


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

Я протестировал советника на индексе B00M 500 и наблюдал за ордерами. Однако еще многое предстоит сделать, чтобы предотвратить одновременное размещение нескольких ордеров. Результаты на демо-счете в размере USD 10 000 показывают положительные результаты, но результаты могут быть иными при использовании реальных счетов с меньшим объемом финансирования. Важно отметить, что эта система не гарантирует прибыли. Она предназначена для образовательных целей, экспериментов и исследований.

Запуск советника

Запуск советника по индексу Boom 500

тестер

Результат теста индекса Boom 500 за 2019 год


Заключение

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

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

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

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

Прикрепленные файлы |
Прогнозируем Ренко — бары при помощи ИИ CatBoost Прогнозируем Ренко — бары при помощи ИИ CatBoost
Как использовать Ренко-бары вместе с ИИ? Рассмотрим Ренко-трейдинг на Форекс с точностью прогнозов до 59.27%. Исследуем преимущества Ренко-баров для фильтрации рыночного шума, узнаем, почему объемные показатели важнее ценовых паттернов, и как настроить оптимальный размер блока Ренко для EURUSD. Пошаговое руководство по интеграции CatBoost, Python и MetaTrader 5 для создания собственной системы прогнозирования Ренко Форекс. Идеально для трейдеров, стремящихся выйти за рамки традиционного технического анализа.
Нейросети в трейдинге: Оптимизация LSTM для целей прогнозирования многомерных временных рядов (Окончание) Нейросети в трейдинге: Оптимизация LSTM для целей прогнозирования многомерных временных рядов (Окончание)
Мы продолжаем реализацию фреймворка DA-CG-LSTM, который предлагает инновационные методы анализа и прогнозирования временных рядов. Использование CG-LSTM и двойного внимания позволяет более точно выявлять как долгосрочные, так и краткосрочные зависимости в данных, что особенно полезно для работы с финансовыми рынками.
Скальпинг по потоку ордеров (Order Flow Scalping) с MQL5 Скальпинг по потоку ордеров (Order Flow Scalping) с MQL5
Данный советник для MetaTrader 5 реализует стратегию Scalping OrderFlow (стратегия скальпирования потока ордеров) с расширенным управлением рисками. В нем используется множество технических индикаторов для определения торговых возможностей на основе дисбалансов в потоке ордеров. Бэк-тестирование показывает потенциальную прибыльность, но подчеркивает необходимость дальнейшей оптимизации, особенно в области управления рисками и соотношения результатов торговли. Он подходит для опытных трейдеров и требует тщательного тестирования и понимания перед практическим применением.
Алгоритм хаотической оптимизации  — Chaos optimization algorithm (COA) Алгоритм хаотической оптимизации — Chaos optimization algorithm (COA)
Усовершенствованный алгоритм хаотической оптимизации (COA), объединяющий воздействие хаоса с адаптивными механизмами поиска. Алгоритм использует множество хаотических отображений и инерционные компоненты для исследования пространства поиска. Статья раскрывает теоретические основы хаотических методов финансовой оптимизации.