Summary: EURUSD Stable Scalper EA is a low-risk MQL4 expert advisor for EURUSD. It uses Bollinger Bands mean reversion, RSI filter, fixed stop loss and take profit. Suitable for M15 timeframe.




EURUSD Stable Scalper EA is designed specifically for EURUSD with a low-risk, stable operational approach. It utilizes Bollinger Bands mean reversion strategy with RSI overbought/oversold confirmation, suitable for EURUSD's typical range-bound characteristics. Each trade has a tight stop loss and take profit, with daily equity protection and spread filter.

Recommended Timeframe: M15
Trading Logic:
1. Mean Reversion: Price touches lower Bollinger Band (20,2) → potential buy; touches upper band → potential sell.
2. Confirmation: RSI(14) < 30 for buy, RSI > 70 for sell.
3. Volatility Guard: ATR(14) checks market calmness.
4. Risk Control: Fixed SL (20 points), TP (30 points), max 1 trade at a time, daily loss limit 5%.

```mql4
//+------------------------------------------------------------------+
//| EURUSDStableScalper.mq4 |
//| |
//| |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict

//--- input parameters with comments
input double LotSize = 0.01; // Fixed lot size (0.01 for EURUSD)
input int StopLossPoints = 20; // Stop loss in points (20 pips)
input int TakeProfitPoints = 30; // Take profit in points (1:1.5 risk-reward)
input int BandsPeriod = 20; // Bollinger Bands period
input double BandsDeviation = 2.0; // Bollinger Bands deviation
input int RSIPeriod = 14; // RSI period
input int RSIOversold = 30; // RSI oversold level (buy signal)
input int RSIOverbought = 70; // RSI overbought level (sell signal)
input int ATRPeriod = 14; // ATR period for volatility filter
input double MaxATRPoints = 15.0; // Maximum ATR value in points (avoid high volatility)
input int MagicNumber = 202412; // Unique EA identifier
input int MaxSpread = 15; // Maximum allowed spread (in points)
input double DailyLossLimit = 5.0; // Daily loss limit in percentage of balance
input bool UseCloseOnFriday = true; // Close all trades before Friday 21:00

//--- global variables
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool isFridayCloseExecuted = false;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
isFridayCloseExecuted = false;
return(INIT_SUCCEEDED);
}

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

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Daily equity protection
double currentEquity = AccountEquity();
double lossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance * 100;
if(lossPercent >= DailyLossLimit)
{
Comment("Daily loss limit reached. No new trades.");
return;
}

// Friday close before weekend
if(UseCloseOnFriday && !isFridayCloseExecuted)
{
datetime currentTime = TimeCurrent();
if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 21)
{
CloseAllOrders();
isFridayCloseExecuted = true;
return;
}
if(TimeDayOfWeek(currentTime) != 5)
isFridayCloseExecuted = false;
}

// Spread filter
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("Spread too high: ", MarketInfo(Symbol(), MODE_SPREAD));
return;
}

// New bar logic (M15)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];

// Check for existing position
if(CountPositions() > 0)
return;

// ATR volatility filter - avoid high volatility
double atr = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
if(atr / Point > MaxATRPoints)
{
Comment("High volatility, ATR: ", atr/Point);
return;
}

// Bollinger Bands values
double upperBand = iBands(Symbol(), PERIOD_M15, BandsPeriod, BandsDeviation, 0, PRICE_CLOSE, MODE_UPPER, 1);
double lowerBand = iBands(Symbol(), PERIOD_M15, BandsPeriod, BandsDeviation, 0, PRICE_CLOSE, MODE_LOWER, 1);
double close1 = iClose(Symbol(), PERIOD_M15, 1);

// RSI value
double rsi = iRSI(Symbol(), PERIOD_M15, RSIPeriod, PRICE_CLOSE, 1);

double sl = 0, tp = 0;
int cmd = -1;

// Buy condition: price touches lower band AND RSI oversold
if(close1 <= lowerBand && rsi < RSIOversold)
{
cmd = OP_BUY;
sl = SymbolInfoDouble(Symbol(), SYMBOL_BID) - StopLossPoints * Point;
tp = SymbolInfoDouble(Symbol(), SYMBOL_BID) + TakeProfitPoints * Point;
}
// Sell condition: price touches upper band AND RSI overbought
else if(close1 >= upperBand && rsi > RSIOverbought)
{
cmd = OP_SELL;
sl = SymbolInfoDouble(Symbol(), SYMBOL_ASK) + StopLossPoints * Point;
tp = SymbolInfoDouble(Symbol(), SYMBOL_ASK) - TakeProfitPoints * Point;
}

if(cmd != -1)
{
int ticket = OrderSend(Symbol(), cmd, LotSize, (cmd==OP_BUY?Ask:Bid), 3, sl, tp, "EURUSD Scalper", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
}
}

//+------------------------------------------------------------------+
//| Count open positions with this MagicNumber |
//+------------------------------------------------------------------+
int CountPositions()
{
int count = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
count++;
}
}
return count;
}

//+------------------------------------------------------------------+
//| Close all orders for this symbol and magic |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```
Reference: Original MQL4 code for educational purposes.
Disclaimer: Trading Forex involves high risk. This EA is provided as-is without any guarantee of profit. Test thoroughly on demo before live trading. Past performance does not guarantee future results.