Complete MQL5 guide & code

RSI MQL5 Indicator: Custom Alert, Multi-Timeframe & EA Integration

Use the MQL5 iRSI handle inside a complete Expert Advisor with current-chart and higher-timeframe readings. The example defaults to alerts only; optional order execution uses fixed lots and initial stops. Save it under MQL5/Experts, not Indicators: it has OnTick and no custom plot buffers.

Implementation details & mechanics

Core implementation pattern

Once per current-chart bar, read RSI from the two completed chart bars and the latest completed higher-timeframe bar. The sample up condition is an oversold rebound while higher-timeframe RSI is below 50; the down condition is an overbought reversal while higher-timeframe RSI is above 50. These are explicitly contrarian level filters, not proof of trend confirmation. HTF must be longer than the chart period.

Error handling & safety rules

When enabled, trading exits matching longs at a completed RSI reading at or above the overbought level, and shorts at or below the oversold level. These exit tests are levels, not crossing events. Failed closes are retried on subsequent ticks while attached; new entries are blocked until matching positions are gone. Initial SL/TP are broker requests; there is no ATR trailing stop. Fixed lots, FX-style pip conversion, FOK filling and nonpersistent retry state require broker-specific testing.

MQL5 Code Implementation

#property copyright "Pineify.app"
#property version   "1.00"
#property strict

//--- Input parameters
input int    RSI_Period       = 14;          // RSI period
input double OverboughtLevel  = 70.0;        // Overbought threshold
input double OversoldLevel    = 30.0;        // Oversold threshold
input ENUM_TIMEFRAMES HTF     = PERIOD_H4;   // Higher timeframe for confluence
input double LotSize          = 0.1;         // Trade lot size
input int    StopLossPips     = 50;          // Stop loss in pips
input int    TakeProfitPips   = 100;         // Take profit in pips
input bool   EnableAlerts     = true;        // Enable push/sound alerts
input bool   EnableTrading    = false;       // Enable automated order execution
input ulong  MagicNumber      = 20240101;    // EA magic number

//--- Global handles
int    g_rsiHandle    = INVALID_HANDLE;
int    g_rsiHTFHandle = INVALID_HANDLE;
double g_point        = 0.0;
datetime lastBarTime=0;
bool closeLongPending=false,closeShortPending=false;

//+------------------------------------------------------------------+
//| Expert initialisation                                            |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Validate inputs
   if(RSI_Period < 2 || OversoldLevel<0 || OverboughtLevel>100 || OversoldLevel>=OverboughtLevel || LotSize<=0 || StopLossPips<=0 || TakeProfitPips<=0 || PeriodSeconds(HTF)<=PeriodSeconds(_Period))
     {
      Print("ERROR: RSI_Period must be >= 2");
      return INIT_PARAMETERS_INCORRECT;
     }

   //--- Create RSI handles
   g_rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
   if(g_rsiHandle == INVALID_HANDLE)
     {
      Print("ERROR: Failed to create RSI handle on current TF, error=", GetLastError());
      return INIT_FAILED;
     }

   g_rsiHTFHandle = iRSI(_Symbol, HTF, RSI_Period, PRICE_CLOSE);
   if(g_rsiHTFHandle == INVALID_HANDLE)
     {
      Print("ERROR: Failed to create RSI handle on HTF=", EnumToString(HTF), ", error=", GetLastError());
      return INIT_FAILED;
     }

   //--- Cache point value
   g_point = _Point;
   if(_Digits == 3 || _Digits == 5)
      g_point *= 10;

   Print("RSI MTF EA initialised | Symbol=", _Symbol,
         " | Period=", RSI_Period,
         " | HTF=", EnumToString(HTF));
   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Expert deinitialization                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(g_rsiHandle != INVALID_HANDLE)
      IndicatorRelease(g_rsiHandle);
   if(g_rsiHTFHandle != INVALID_HANDLE)
      IndicatorRelease(g_rsiHTFHandle);

   Print("RSI MTF EA removed. Deinit reason=", reason);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(EnableTrading)
   {
      if(closeLongPending) { ClosePositions(POSITION_TYPE_BUY); closeLongPending=HasType(POSITION_TYPE_BUY); }
      if(closeShortPending) { ClosePositions(POSITION_TYPE_SELL); closeShortPending=HasType(POSITION_TYPE_SELL); }
   }
   datetime currentBarTime=iTime(_Symbol,_Period,0);
   if(currentBarTime==0 || currentBarTime==lastBarTime) return;
   double rsiCurrent[2],rsiHTF[1];
   if(CopyBuffer(g_rsiHandle,0,1,2,rsiCurrent)!=2 || CopyBuffer(g_rsiHTFHandle,0,1,1,rsiHTF)!=1) return;
   if(currentBarTime!=iTime(_Symbol,_Period,0)) return;
   lastBarTime=currentBarTime;
   // Static arrays store oldest copied value first: shift 2 then shift 1.
   double rsiPrev=rsiCurrent[0],rsiNow=rsiCurrent[1],htfNow=rsiHTF[0];
   bool buy=rsiPrev<=OversoldLevel && rsiNow>OversoldLevel && htfNow<50;
   bool sell=rsiPrev>=OverboughtLevel && rsiNow<OverboughtLevel && htfNow>50;
   if(EnableAlerts && (buy || sell))
   {
      string msg=StringFormat("%s completed RSI %s, RSI=%.2f HTF=%.2f",_Symbol,buy?"up signal":"down signal",rsiNow,htfNow);
      Alert(msg); if(!SendNotification(msg)) Print("Push failed: ",GetLastError());
   }
   if(!EnableTrading) return;
   if(rsiNow>=OverboughtLevel && HasType(POSITION_TYPE_BUY))
   { ClosePositions(POSITION_TYPE_BUY); closeLongPending=HasType(POSITION_TYPE_BUY); }
   if(rsiNow<=OversoldLevel && HasType(POSITION_TYPE_SELL))
   { ClosePositions(POSITION_TYPE_SELL); closeShortPending=HasType(POSITION_TYPE_SELL); }
   if(closeLongPending || closeShortPending || HasType(POSITION_TYPE_BUY) || HasType(POSITION_TYPE_SELL)) return;
   if(buy) OpenOrder(ORDER_TYPE_BUY);
   if(sell) OpenOrder(ORDER_TYPE_SELL);
  }
bool HasType(const ENUM_POSITION_TYPE type)
{
   for(int i=PositionsTotal()-1;i>=0;i--)
      if(PositionGetTicket(i)>0 && PositionGetString(POSITION_SYMBOL)==_Symbol &&
         PositionGetInteger(POSITION_MAGIC)==(long)MagicNumber && PositionGetInteger(POSITION_TYPE)==type) return true;
   return false;
}

//+------------------------------------------------------------------+
//| Open a market order                                              |
//+------------------------------------------------------------------+
bool OpenOrder(ENUM_ORDER_TYPE orderType)
  {
   MqlTradeRequest request = {};
   MqlTradeResult  result  = {};

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double price = (orderType == ORDER_TYPE_BUY) ? ask : bid;
   double sl, tp;

   if(orderType == ORDER_TYPE_BUY)
     {
      sl = price - StopLossPips  * g_point;
      tp = price + TakeProfitPips * g_point;
     }
   else
     {
      sl = price + StopLossPips  * g_point;
      tp = price - TakeProfitPips * g_point;
     }

   request.action   = TRADE_ACTION_DEAL;
   request.symbol   = _Symbol;
   request.volume   = LotSize;
   request.type     = orderType;
   request.price    = price;
   request.sl       = NormalizeDouble(sl,_Digits);
   request.tp       = NormalizeDouble(tp,_Digits);
   request.magic    = MagicNumber;
   request.comment  = "RSI_MTF";
   request.type_filling = ORDER_FILLING_FOK;

   if(!OrderSend(request, result) || result.retcode!=TRADE_RETCODE_DONE)
     {
      Print("OrderSend failed: retcode=", result.retcode, " | ", result.comment);
      return false;
     }
   Print("Order opened: type=", EnumToString(orderType),
         " price=", price, " SL=", sl, " TP=", tp);
   return true;
  }

//+------------------------------------------------------------------+
//| Close all positions of a given type                              |
//+------------------------------------------------------------------+
void ClosePositions(ENUM_POSITION_TYPE posType)
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(!PositionSelectByTicket(ticket))
         continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol)
         continue;
      if(PositionGetInteger(POSITION_MAGIC) != (long)MagicNumber)
         continue;
      if(PositionGetInteger(POSITION_TYPE) != posType)
         continue;

      MqlTradeRequest request = {};
      MqlTradeResult  result  = {};
      request.action = TRADE_ACTION_DEAL;
      request.symbol = _Symbol;
      request.volume = PositionGetDouble(POSITION_VOLUME);
      request.type   = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
      request.price  = (posType == POSITION_TYPE_BUY)
                       ? SymbolInfoDouble(_Symbol, SYMBOL_BID)
                       : SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      request.position      = ticket;
      request.magic         = MagicNumber;
      request.comment       = "RSI_MTF_Close";
      request.type_filling  = ORDER_FILLING_FOK;

      if(!OrderSend(request, result) || result.retcode!=TRADE_RETCODE_DONE)
         Print("Close failed: ticket=", ticket, " retcode=", result.retcode);
      else
         Print("Position closed: ticket=", ticket);
     }
  }
//+------------------------------------------------------------------+

Copy this code into MetaEditor, save it in your MQL5 folder (Experts, Scripts, or Include), and compile with F7.

Generate custom MQL5 code with Pineify AI

Describe the trade execution, indicator calculations, risk management, or data processing logic you need. Pineify generates editable MQL5 source code. Review its logic, request a syntax check, and compile and test the final file in MetaEditor.

Pine Script vs MQL5: Same Strategy, Different Platforms

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionSeries evaluated on chart updatesEvent handlers with explicit buffers
DeploymentRuns in TradingView with alertsRuns in the MT5 terminal or on a VPS
Broker accessStrategy orders are simulated; live automation needs a separate integrationDirect broker connectivity
BacktestingStrategy Tester for strategy scriptsStrategy Tester for Expert Advisors
Code complexitySimpler, functional syntaxC++-like, more powerful

The calculation can be implemented on either platform, but the runtime model and buffer APIs differ. Read the Pine Script reference guide before porting logic between them.

Frequently Asked Questions

Related MQL5 pages

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.