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:
``
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.