Торговый робот VR Rsi Robot: мультитаймфреймовая стратегия на RSI в MQL5
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


