Summary: EuroStable EA is a low-risk MQL4 expert advisor for EURUSD. It uses Bollinger Bands mean reversion strategy with ATR volatility filter and daily loss limit. Suitable for H1 timeframe.




EuroStable EA is designed specifically for EURUSD with a low-risk, stable operational approach. It employs a mean reversion strategy using Bollinger Bands, as EURUSD tends to revert to the mean after extreme moves. The EA trades only when price touches the outer bands, confirms with ATR low volatility, and uses fixed stop loss/take profit. Each trade has a daily equity protection and maximum spread filter.

Recommended Timeframe: H1
Trading Logic:
1. Setup: Bollinger Bands (20,2) on H1. ATR (14) for volatility filter.
2. Entry: Price touches lower band + ATR < threshold -> BUY. Price touches upper band + ATR < threshold -> SELL.
3. Filter: Maximum spread 25 points, daily loss limit 5%, only one trade at a time.
4. Exit: Fixed SL 200 points, TP 400 points (2:1 risk-reward). Also close if price crosses middle band.

```mql4
//+------------------------------------------------------------------+
//| EuroStableEA.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 ~$1 per pip)
input int StopLossPoints = 200; // Stop loss in points (200 pips for EURUSD)
input int TakeProfitPoints = 400; // Take profit in points (2:1 risk-reward ratio)
input int BandsPeriod = 20; // Bollinger Bands period
input double BandsDeviation = 2.0; // Bollinger Bands standard deviation multiplier
input int ATRPeriod = 14; // Period for ATR volatility indicator
input double ATRMax = 150; // Maximum ATR value allowed (points) - lower = fewer trades
input int MagicNumber = 202412; // Unique EA identifier
input int MaxSpread = 25; // Maximum allowed spread (in points)
input double DailyLossLimit = 5.0; // Daily loss limit in percentage of balance (5%)
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");
return;
}

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

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

// Bollinger Bands calculation on H1
double upperBand = iBands(Symbol(), PERIOD_H1, BandsPeriod, BandsDeviation, 0, PRICE_CLOSE, MODE_UPPER, 1);
double lowerBand = iBands(Symbol(), PERIOD_H1, BandsPeriod, BandsDeviation, 0, PRICE_CLOSE, MODE_LOWER, 1);
double middleBand = iBands(Symbol(), PERIOD_H1, BandsPeriod, BandsDeviation, 0, PRICE_CLOSE, MODE_MAIN, 1);
double close1 = iClose(Symbol(), PERIOD_H1, 1);
double open1 = iOpen(Symbol(), PERIOD_H1, 1);

// ATR volatility filter
double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
if(atr > ATRMax)
{
Comment("ATR too high, no trade");
return;
}

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

// Mean reversion: price touches lower band and closed up (bullish reversal)
if(close1 <= lowerBand + 5 * Point && close1 > open1)
{
cmd = OP_BUY;
sl = SymbolInfoDouble(Symbol(), SYMBOL_BID) - StopLossPoints * Point;
tp = SymbolInfoDouble(Symbol(), SYMBOL_BID) + TakeProfitPoints * Point;
}
// Mean reversion: price touches upper band and closed down (bearish reversal)
else if(close1 >= upperBand - 5 * Point && close1 < open1)
{
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, "EuroStable EA", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
}

// Check for middle band exit on existing positions (additional logic)
CheckAndExitAtMiddleBand(middleBand);
}

//+------------------------------------------------------------------+
//| 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)
{
bool result;
if(OrderType() == OP_BUY)
result = OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrNONE);
else if(OrderType() == OP_SELL)
result = OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrNONE);
}
}
}
}

//+------------------------------------------------------------------+
//| Check and close if price crosses middle band |
//+------------------------------------------------------------------+
void CheckAndExitAtMiddleBand(double middleBand)
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double currentBid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
double currentAsk = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
if(OrderType() == OP_BUY && currentBid >= middleBand)
{
OrderClose(OrderTicket(), OrderLots(), currentBid, 3, clrNONE);
}
else if(OrderType() == OP_SELL && currentAsk <= middleBand)
{
OrderClose(OrderTicket(), OrderLots(), currentAsk, 3, clrNONE);
}
}
}
}
}
//+------------------------------------------------------------------+
```
Reference: Original MQL4 code for educational purposes.
Disclaimer: Trading Forex and Gold 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.