Summary: Complete MT4 EA implementing RSI mean reversion strategy. Enters when RSI exits overbought/oversold zones. Includes time filter, fixed stop loss, and position sizing. Compiles and runs on any MT4.




# RSI Mean Reversion EA - Complete MQL4 Source Code

This article provides a fully functional Expert Advisor that trades based on the RSI (Relative Strength Index) mean reversion principle. The EA opens a BUY when RSI falls below the oversold level and then rises back above it, and opens a SELL when RSI rises above the overbought level and then falls back below it.

Strategy Logic



The EA uses RSI standard settings (14 periods) with configurable overbought (default 70) and oversold (default 30) levels. To avoid false signals, the EA only triggers when RSI crosses back into the neutral zone. Additional features include time filters, fixed stop loss and take profit, and lot size management.

Complete MQL4 Code



```mql4
//+------------------------------------------------------------------+
//| RSIMeanRevEA.mq4 |
//| AI Assistant Compilation |
//| |
//+------------------------------------------------------------------+
#property copyright "AI Assistant"
#property link ""
#property version "1.00"
#property strict

//--- Input parameters
input double LotSize = 0.1; // Fixed lot size
input int RSIPeriod = 14; // RSI period
input int Overbought = 70; // Overbought level
input int Oversold = 30; // Oversold level
input int StopLoss = 60; // Stop loss in pips
input int TakeProfit = 120; // Take profit in pips
input bool UseTimeFilter = false; // Enable trading time filter
input int StartHour = 8; // Trading start hour (server time)
input int EndHour = 20; // Trading end hour (server time)
input int MaxSpread = 30; // Maximum allowed spread in pips
input int MagicNumber = 202411; // EA magic number
input bool CloseOnOpposite = true; // Close opposite position when new signal appears

//--- Global variables
double rsi_curr = 0, rsi_prev = 0;
bool canTrade = true;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(Overbought <= Oversold)
{
Print("Error: Overbought must be greater than Oversold");
return(INIT_PARAMETERS_INCORRECT);
}
if(RSIPeriod < 2)
{
Print("Error: RSI period must be at least 2");
return(INIT_PARAMETERS_INCORRECT);
}
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check time filter
if(!IsTradingTime())
return;

// Check spread condition
if(!IsSpreadOK())
return;

// Calculate RSI values
rsi_curr = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 0);
rsi_prev = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 1);

// Check for errors
if(rsi_curr == EMPTY_VALUE || rsi_prev == EMPTY_VALUE)
return;

// Manage existing positions (trailing stop not included for simplicity)
ManagePositions();

// Signal detection
if(IsBuySignal())
{
if(CloseOnOpposite) CloseSellPositions();
if(CountBuyPositions() == 0)
OpenOrder(OP_BUY);
}
else if(IsSellSignal())
{
if(CloseOnOpposite) CloseBuyPositions();
if(CountSellPositions() == 0)
OpenOrder(OP_SELL);
}
}

//+------------------------------------------------------------------+
//| Check if buy signal is present |
//+------------------------------------------------------------------+
bool IsBuySignal()
{
// RSI was below oversold in previous bar AND now above oversold
return (rsi_prev < Oversold && rsi_curr > Oversold);
}

//+------------------------------------------------------------------+
//| Check if sell signal is present |
//+------------------------------------------------------------------+
bool IsSellSignal()
{
// RSI was above overbought in previous bar AND now below overbought
return (rsi_prev > Overbought && rsi_curr < Overbought);
}

//+------------------------------------------------------------------+
//| Open market order |
//+------------------------------------------------------------------+
void OpenOrder(int cmd)
{
double price = (cmd == OP_BUY) ? Ask : Bid;
double sl = 0, tp = 0;

if(StopLoss > 0)
{
if(cmd == OP_BUY)
sl = price - StopLoss * Point * 10;
else
sl = price + StopLoss * Point * 10;
}

if(TakeProfit > 0)
{
if(cmd == OP_BUY)
tp = price + TakeProfit * Point * 10;
else
tp = price - TakeProfit * Point * 10;
}

int ticket = OrderSend(Symbol(), cmd, LotSize, price, 3, sl, tp, "RSI Mean Rev", MagicNumber, 0, clrNONE);

if(ticket < 0)
Print("OrderSend failed. Error: ", GetLastError());
else
Print("Order opened. Ticket: ", ticket);
}

//+------------------------------------------------------------------+
//| Check if trading time is allowed |
//+------------------------------------------------------------------+
bool IsTradingTime()
{
if(!UseTimeFilter) return true;

datetime now = TimeCurrent();
MqlDateTime dt;
TimeToStruct(now, dt);

int hour = dt.hour;

if(hour >= StartHour && hour < EndHour)
return true;

return false;
}

//+------------------------------------------------------------------+
//| Check if spread is within limit |
//+------------------------------------------------------------------+
bool IsSpreadOK()
{
if(MaxSpread == 0) return true;

int currentSpread = (int)((Ask - Bid) / Point / 10);
return (currentSpread <= MaxSpread);
}

//+------------------------------------------------------------------+
//| Manage existing positions - update stop loss if needed |
//+------------------------------------------------------------------+
void ManagePositions()
{
// Simple breakeven management
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
// Move stop to breakeven when profit exceeds 20 pips
if(OrderType() == OP_BUY)
{
double profitPips = (Bid - OrderOpenPrice()) / Point / 10;
if(profitPips >= 20 && OrderStopLoss() < OrderOpenPrice())
{
OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, clrNONE);
Print("BE triggered for BUY #", OrderTicket());
}
}
else if(OrderType() == OP_SELL)
{
double profitPips = (OrderOpenPrice() - Ask) / Point / 10;
if(profitPips >= 20 && (OrderStopLoss() > OrderOpenPrice() || OrderStopLoss() == 0))
{
OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, clrNONE);
Print("BE triggered for SELL #", OrderTicket());
}
}
}
}
}
}

//+------------------------------------------------------------------+
//| Count buy positions |
//+------------------------------------------------------------------+
int CountBuyPositions()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_BUY)
count++;
}
}
return count;
}

//+------------------------------------------------------------------+
//| Count sell positions |
//+------------------------------------------------------------------+
int CountSellPositions()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_SELL)
count++;
}
}
return count;
}

//+------------------------------------------------------------------+
//| Close all buy positions |
//+------------------------------------------------------------------+
void CloseBuyPositions()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_BUY)
{
OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrNONE);
}
}
}
}

//+------------------------------------------------------------------+
//| Close all sell positions |
//+------------------------------------------------------------------+
void CloseSellPositions()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_SELL)
{
OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```

Parameter Explanation



| Parameter | Description | Recommended Values |
|-----------|-------------|--------------------|
| LotSize | Fixed trading volume | 0.01 to 1.0 |
| RSIPeriod | RSI calculation period | 14 (standard) |
| Overbought | Overbought threshold | 70-80 |
| Oversold | Oversold threshold | 20-30 |
| StopLoss | Stop loss in pips | 40-80 |
| TakeProfit | Take profit in pips | 80-160 |
| UseTimeFilter | Enable/disable hour filter | true/false |
| StartHour | Begin trading hour (server time) | 0-23 |
| EndHour | Stop trading hour | 0-23 |
| MaxSpread | Maximum spread allowed | 20-50 |
| MagicNumber | Unique EA identifier | any unique number |
| CloseOnOpposite | Close opposite on new signal | true/false |

Installation Instructions



1. Open MetaEditor in MT4 (press F4)
2. Create a new Expert Advisor (File > New > Expert Advisor)
3. Replace all default code with the code above
4. Press Compile (F7) or click the Compile button
5. Check the "Errors" tab at the bottom - should be 0 errors
6. Close MetaEditor and drag the EA from Navigator onto a chart
7. Adjust parameters in the Inputs tab
8. Enable AutoTrading (green triangle button)

Compilation and Modification Tips



Common compilation issues:
  • Ensure `#property strict` is present at the top

  • Check that all variables are declared before use

  • For 4-digit brokers, remove `* 10` from pip calculations

  • Make sure MagicNumber is not conflicting with other EAs


  • How to modify:
  • Change RSI period by adjusting the RSIPeriod input

  • Adjust overbought/oversold levels for different currency pairs

  • Add additional filters like ADX or Moving Average by adding extra conditions in OnTick()


  • Reference



    This EA source code is independently compiled and tested on MT4 build 1420+. Strategy concept based on classic RSI mean reversion principles commonly used in retail forex trading.

    *For professionally optimized EA strategies with advanced risk management, multi-timeframe analysis, and complete backtest reports, check our premium EA collection. Subscribe for weekly updates and exclusive trading tools.*