Торговый робот VR Rsi Robot: мультитаймфреймовая стратегия на RSI в MQL5

Торговый робот VR Rsi Robot: мультитаймфреймовая стратегия на RSI в MQL5

12 марта 2026, 11:54
Vladimir Pastushak
0
15

1. Введение

Индикатор Relative Strength Index (RSI) знаком практически каждому трейдеру. Его сигналы о перекупленности (80+) и перепроданности (20-) кажутся простыми и понятными. Однако на практике вход по этим уровням на одном таймфрейме часто приводит к убыткам: цена может долго оставаться в экстремальных зонах или разворачиваться слишком поздно. Причина — рыночный шум и отсутствие подтверждения от старших периодов.

Эффективным решением является мультитаймфреймовый анализ. Если сигнал на младшем таймфрейме совпадает с направлением движения на старшем, вероятность успешной сделки значительно возрастает. Именно этот принцип заложен в основу эксперта VR Rsi Robot, написанного на MQL5. В этой статье мы подробно разберём его логику, код и возможности доработки.

2. Описание стратегии

VR Rsi Robot использует значения RSI на двух таймфреймах — H1 и D1. Торговый сигнал формируется только при выполнении следующих условий:

  • Для покупки (BUY):
    • Текущее значение RSI на H1 (по завершённому бару) выше уровня перепроданности (20) и при этом больше предыдущего значения (индикатор растёт).
    • Аналогичная картина на D1: RSI выше 20 и растёт.
  • Для продажи (SELL):
    • Текущее значение RSI на H1 ниже уровня перекупленности (80) и при этом меньше предыдущего (индикатор падает).
    • D1 подтверждает: RSI ниже 80 и падает.

Важно, что все значения берутся только с закрытых баров (индексы 1 и 2 в терминологии MQL5). Это исключает перерисовку и гарантирует, что сигнал не изменится на следующем тике.

Управление позициями

Робот поддерживает только одну открытую позицию по символу. Если приходит сигнал на покупку, а уже открыта продажа, эксперт сначала закрывает продажу, затем открывает покупку. Аналогично при сигнале на продажу. Таким образом, система всегда «едет» в направлении последнего подтверждённого сигнала.

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

3. Разбор кода

Код написан на MQL5 с использованием стандартных библиотек Trade и PositionInfo . Рассмотрим его ключевые блоки.

Подключение библиотек и входные параметры

#include <Trade\Trade.mqh>        CTrade        trade;
#include <Trade\PositionInfo.mqh> CPositionInfo posit;

input double          iLots             = 0.01;
input int             iRSI_Period_H1    = 12;
input ENUM_TIMEFRAMES iRSI_TimeFrame_H1 = PERIOD_H1;
input int             iRSI_Period_D1    = 18;
input ENUM_TIMEFRAMES iRSI_TimeFrame_D1 = PERIOD_D1;
input double          iRSI_Level_UP     = 80.0;
input double          iRSI_Level_DW     = 20.0;
input int             iMagicNumber      = 227;
input int             iSlippage         = 30; 

Здесь задаются все настраиваемые параметры: объём лота, периоды RSI для двух таймфреймов, уровни перекупленности/перепроданности, магический номер и проскальзывание. Благодаря этому советника можно гибко адаптировать под разные инструменты и рыночные условия.

Глобальные переменные и инициализация

double lt = 0;
int    handle_0 = -1;
int    handle_1 = -1;
double rsi_mass_h1[];
double rsi_mass_d1[];

int OnInit()
  {
   trade.SetExpertMagicNumber(iMagicNumber);
   trade.SetDeviationInPoints(iSlippage);
   trade.SetTypeFillingBySymbol(_Symbol);
   trade.SetMarginMode();

   double stepvol = ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   if(stepvol > 0)
      lt = stepvol * (int)(iLots / stepvol);
   if(lt < ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN))
      lt = ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);

   handle_0 = ::iRSI(_Symbol, iRSI_TimeFrame_H1, iRSI_Period_H1, PRICE_CLOSE);
   handle_1 = ::iRSI(_Symbol, iRSI_TimeFrame_D1, iRSI_Period_D1, PRICE_CLOSE);

   return(INIT_SUCCEEDED);
  } 

lt — скорректированный лот с учётом шага объёма и минимальных ограничений брокера. handle_0 и handle_1 — хендлы индикаторов RSI для H1 и D1. Массивы rsi_mass_h1 и rsi_mass_d1 будут использоваться для получения значений индикатора.

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

Основная логика в OnTick

void OnTick()
  {
   double Bid = ::SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double Ask = ::SymbolInfoDouble(_Symbol, SYMBOL_ASK);

   int total = ::PositionsTotal();
   ulong b_ticket = 0, s_ticket = 0;
   for(int i = 0; i < total; i++)
      if(posit.SelectByIndex(i))
         if(posit.Symbol() == _Symbol && posit.Magic() == iMagicNumber)
         {
            if(posit.PositionType() == POSITION_TYPE_BUY) b_ticket = posit.Ticket();
            if(posit.PositionType() == POSITION_TYPE_SELL) s_ticket = posit.Ticket();
         }

   bool signal_up = false, signal_dw = false;

   if(b_ticket == 0)
     {
      if(::CopyBuffer(handle_0, 0, 1, 2, rsi_mass_h1) != -1) ArraySetAsSeries(rsi_mass_h1, true);
      if(::CopyBuffer(handle_1, 0, 1, 2, rsi_mass_d1) != -1) ArraySetAsSeries(rsi_mass_d1, true);
      if(::ArraySize(rsi_mass_h1) >= 2 && ::ArraySize(rsi_mass_d1) >= 2)
         if(rsi_mass_h1[0] >= iRSI_Level_DW && rsi_mass_h1[0] > rsi_mass_h1[1])
            if(rsi_mass_d1[0] >= iRSI_Level_DW && rsi_mass_d1[0] > rsi_mass_d1[1])
               signal_up = true;
     }

   if(s_ticket == 0)
     {
      if(::CopyBuffer(handle_0, 0, 1, 2, rsi_mass_h1) != -1) ArraySetAsSeries(rsi_mass_h1, true);
      if(::CopyBuffer(handle_1, 0, 1, 2, rsi_mass_d1) != -1) ArraySetAsSeries(rsi_mass_d1, true);
      if(::ArraySize(rsi_mass_h1) >= 2 && ::ArraySize(rsi_mass_d1) >= 2)
         if(rsi_mass_h1[0] <= iRSI_Level_UP && rsi_mass_h1[0] < rsi_mass_h1[1])
            if(rsi_mass_d1[0] <= iRSI_Level_UP && rsi_mass_d1[0] < rsi_mass_d1[1])
               signal_dw = true;
     }

   if(signal_up)
     {
      if(s_ticket > 0) trade.PositionClose(s_ticket);
      if(CheckMargin(ORDER_TYPE_BUY, lt) && trade.CheckVolume(_Symbol, lt, Ask, ORDER_TYPE_BUY))
         if(trade.Buy(lt)) return;
     }

   if(signal_dw)
     {
      if(b_ticket > 0) trade.PositionClose(b_ticket);
      if(CheckMargin(ORDER_TYPE_SELL, lt) && trade.CheckVolume(_Symbol, lt, Bid, ORDER_TYPE_SELL))
         if(trade.Sell(lt)) return;
     }
  } 

В обработчике новых тиков сначала получаем цены, затем определяем наличие позиций нашего эксперта. Далее копируем значения RSI с закрытых баров (индексы 1 и 2 в CopyBuffer означают пропуск текущего формирующегося бара). При выполнении условий формируется сигнал, после чего закрывается противоположная позиция (если есть), проверяется маржа и допустимость объёма, и отправляется рыночный ордер.

Вспомогательные функции

bool CheckMargin(ENUM_ORDER_TYPE aType, double aLot)
  {
   double Bid = ::SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double Ask = ::SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double fMargin = 0;
   if(Ask > 0 && Bid > 0)
      if(::OrderCalcMargin(aType, _Symbol, aLot, aType == 0 ? Ask : Bid, fMargin))
         return(fMargin < ::AccountInfoDouble(ACCOUNT_MARGIN_FREE));
   return false;
  }

bool CheckSL_TP(ENUM_POSITION_TYPE type, double aSL, double aTP)
  {
   int stops_level = (int)::SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
   double ask = ::SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = ::SymbolInfoDouble(_Symbol, SYMBOL_BID);
   switch(type)
     {
      case POSITION_TYPE_BUY:
        return((bid - aSL > stops_level * _Point) && (aTP - bid > stops_level * _Point));
      case POSITION_TYPE_SELL:
        return((ask - aTP > stops_level * _Point) && (aSL - ask > stops_level * _Point));
     }
   return false;
  } 

CheckMargin вычисляет требуемую маржу с помощью OrderCalcMargin и сравнивает её со свободной маржей. CheckSL_TP может использоваться для проверки корректности стоп-лосса и тейк-профита перед их установкой, но в текущей версии она не задействована.

4. Преимущества и ограничения стратегии

Плюсы:

  • Простота и прозрачность логики.
  • Фильтрация ложных сигналов за счёт подтверждения от D1.
  • Отсутствие перерисовки благодаря работе по закрытым барам.
  • Наличие базовых проверок (лот, маржа) делает код более надёжным.

Минусы:

  • Отсутствие стоп-лоссов и тейк-профитов может приводить к глубоким просадкам.
  • Во флэте RSI может долго колебаться возле уровней, генерируя ложные входы (хотя фильтр по D1 частично решает проблему).
  • Стратегия не адаптируется под изменение волатильности.

5. Возможные улучшения

VR Rsi Robot — отличная основа для дальнейшей доработки. Вот несколько идей:

  • Добавление защитных ордеров. Используя функцию CheckSL_TP , можно выставлять стоп-лосс и тейк-профит, например, на основе ATR или фиксированных пунктов.
  • Трейлинг-стоп. Позволит фиксировать прибыль при движении цены в нужную сторону.
  • Фильтр по тренду. Например, проверять, что цена выше скользящей средней на D1 для длинных позиций.
  • Временные фильтры. Отключать торговлю в определённые часы или перед важными новостями.
  • Адаптивный лот. Рассчитывать объём позиции как процент от текущего депозита с учётом риска.

6. Заключение

Мы подробно разобрали код торгового робота VR Rsi Robot, реализующего мультитаймфреймовую стратегию на RSI. Этот пример показывает, как с помощью стандартных средств MQL5 можно создать вполне работоспособного советника, который учитывает риск-менеджмент (проверка маржи, корректировка лота) и использует простую, но эффективную логику входа.

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

 Исходник для MetaTrader 4: https://www.mql5.com/ru/code/70467

 Исходник для MetaTrader 5: https://www.mql5.com/ru/code/70465