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:
  • Mean Reversion: Price touches lower Bollinger Band (20,2) → potential buy; touches upper band → potential sell.

  • Confirmation: RSI(14) < 30 for buy, RSI > 70 for sell.

  • Volatility Guard: ATR(14) checks market calmness.

  • 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.