Summary: Gold Stabilizer EA is a robust MQL4 robot for XAUUSD. It uses EMA trend filter, ATR-based stops, and volatility-adjusted lot sizing to reduce risk and ensure stable operation on gold.
Gold Stabilizer EA is designed specifically for the high-volatility gold market (XAUUSD). It employs a trend-following logic with a slow EMA filter, ATR-based stop loss and take profit, and a time-restricted trading session to avoid major rollover risks. Lot sizing adapts to current volatility to keep risk per trade consistent.
Load Period Recommendation: H1 (1 Hour). The strategy is optimized for the H1 timeframe to balance signal reliability and trade frequency.
Trading Logic:
1. Trend Filter: Uses EMA(200) on H1 to determine the long-term direction. Only long signals when price > EMA200; only short signals when price < EMA200.
2. Entry Signal: Uses a fast SMA crossover (SMA5 and SMA20) smoothed by an additional filter. Confirmation requires the crossing to hold for 1 bar.
3. Risk Management:
- Stop Loss = ATR(14) * ATR_Multiplier (default 2.0)
- Take Profit = Stop Loss * RiskRewardRatio (default 1.5)
- Lot size = RiskPercent * AccountBalance() / (StopLoss in pips * TickValuePerLot)
4. Time Filter: Trades only between 08:00-20:00 broker time to avoid low liquidity periods.
5. Max Spread Control: Aborts trade if spread exceeds MaxSpread.
Disclaimer: Trading foreign exchange and gold carries a high level of risk. Past performance does not guarantee future results. This EA is for educational purposes only. Test thoroughly on a demo account before live use. The author assumes no responsibility for financial losses.
```mql4
//+------------------------------------------------------------------+
//| GoldStabilizerEA_v1.mq4 |
//| |
//| |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Input Parameters |
//+------------------------------------------------------------------+
input double LotSizeFixed = 0.01; // Fixed lot size (if UseRiskPercent=false)
input bool UseRiskPercent = true; // Use dynamic risk percentage (true=use RiskPercentPerTrade)
input double RiskPercentPerTrade = 1.0; // Risk % per trade (1% of balance, dynamic lot)
input double ATR_Multiplier = 2.0; // ATR multiplier for Stop Loss (higher = wider SL)
input double RiskRewardRatio = 1.5; // Reward:Risk ratio (TP = SL * this)
input int FastMAPeriod = 5; // Fast SMA period for entry signal
input int SlowMAPeriod = 20; // Slow SMA period for entry signal
input int TrendEMAPeriod = 200; // EMA period for trend filter
input int ATRPeriod = 14; // ATR period for volatility measurement
input int StartHour = 8; // Trading start hour (broker time)
input int EndHour = 20; // Trading end hour (broker time)
input double MaxSpread = 35.0; // Maximum allowed spread (in points)
input int Slippage = 30; // Slippage in points
input bool UseCloseSignals = true; // Enable exit when opposite crossover occurs
input long MagicNumber = 20241115; // Unique EA identifier
//+------------------------------------------------------------------+
//| Global variables |
//+------------------------------------------------------------------+
double lastBarTime = 0;
bool tradeAllowed = true;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(UseRiskPercent && RiskPercentPerTrade <= 0)
{
Print("Error: RiskPercentPerTrade must be >0 when UseRiskPercent=true");
return(INIT_PARAMETERS_INCORRECT);
}
if(ATR_Multiplier <= 0 || RiskRewardRatio <= 0)
{
Print("Error: Multipliers must be positive");
return(INIT_PARAMETERS_INCORRECT);
}
lastBarTime = Time[0];
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check new bar
if(lastBarTime == Time[0]) return;
lastBarTime = Time[0];
// Refresh rates
RefreshRates();
// Check time and spread conditions
if(!IsTradeTime()) return;
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread) return;
// Manage existing orders (trailing not used for low-risk simplicity)
ManageOrders();
// Generate new signal
int signal = GetSignal();
if(signal != 0)
ExecuteTrade(signal);
}
//+------------------------------------------------------------------+
//| Check if current time is within allowed trading window |
//+------------------------------------------------------------------+
bool IsTradeTime()
{
datetime now = TimeCurrent();
int hour = TimeHour(now);
return (hour >= StartHour && hour < EndHour);
}
//+------------------------------------------------------------------+
//| Get trading signal: 1 = Buy, -1 = Sell, 0 = No signal |
//+------------------------------------------------------------------+
int GetSignal()
{
double emaTrend = iMA(Symbol(), PERIOD_H1, TrendEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double fastMA = iMA(Symbol(), 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double slowMA = iMA(Symbol(), 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double prevFast = iMA(Symbol(), 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);
double prevSlow = iMA(Symbol(), 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);
if(emaTrend == 0 || fastMA == 0 || slowMA == 0) return 0;
bool trendUp = Close[1] > emaTrend;
bool trendDown = Close[1] < emaTrend;
// Bullish crossover with confirmation
if(prevFast <= prevSlow && fastMA > slowMA && trendUp)
return 1;
// Bearish crossover with confirmation
if(prevFast >= prevSlow && fastMA < slowMA && trendDown)
return -1;
return 0;
}
//+------------------------------------------------------------------+
//| Execute buy or sell order |
//+------------------------------------------------------------------+
void ExecuteTrade(int signal)
{
// Close opposite orders first
CloseOrders(-signal);
// Check if same direction order already exists
if(CountOrders(signal) > 0) return;
double atr = iATR(Symbol(), 0, ATRPeriod, 1);
if(atr <= 0) return;
double slDistance = atr * ATR_Multiplier;
double tpDistance = slDistance * RiskRewardRatio;
double entryPrice, slPrice, tpPrice;
int cmd;
double point = Point;
if(Digits == 3 || Digits == 5) point = Point * 10;
if(signal == 1) // Buy
{
entryPrice = Ask;
slPrice = entryPrice - slDistance;
tpPrice = entryPrice + tpDistance;
cmd = OP_BUY;
}
else // Sell
{
entryPrice = Bid;
slPrice = entryPrice + slDistance;
tpPrice = entryPrice - tpDistance;
cmd = OP_SELL;
}
// Normalize prices
slPrice = NormalizeDouble(slPrice, Digits);
tpPrice = NormalizeDouble(tpPrice, Digits);
entryPrice = NormalizeDouble(entryPrice, Digits);
double lot = CalculateLotSize(slDistance, signal);
if(lot <= 0) return;
int ticket = OrderSend(Symbol(), cmd, lot, entryPrice, Slippage, slPrice, tpPrice, "Gold Stabilizer", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
}
//+------------------------------------------------------------------+
//| Calculate lot size based on risk percent or fixed lot |
//+------------------------------------------------------------------+
double CalculateLotSize(double slDistanceInPoints, int signal)
{
if(!UseRiskPercent)
return LotSizeFixed;
double balance = AccountBalance();
double riskAmount = balance * RiskPercentPerTrade / 100.0;
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
if(tickValue <= 0) return 0;
// slDistanceInPoints is in price units, convert to points
double point = Point;
if(Digits == 3 || Digits == 5) point = Point * 10;
double slPoints = slDistanceInPoints / point;
if(slPoints <= 0) return 0;
double lot = riskAmount / (slPoints * tickValue);
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double stepLot = MarketInfo(Symbol(), MODE_LOTSTEP);
lot = MathFloor(lot / stepLot) * stepLot;
lot = MathMax(minLot, MathMin(maxLot, lot));
return lot;
}
//+------------------------------------------------------------------+
//| Count orders with given signal direction |
//+------------------------------------------------------------------+
int CountOrders(int signal)
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if((signal == 1 && OrderType() == OP_BUY) || (signal == -1 && OrderType() == OP_SELL))
count++;
}
}
}
return count;
}
//+------------------------------------------------------------------+
//| Close orders opposite to given signal |
//+------------------------------------------------------------------+
void CloseOrders(int oppositeSignal)
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
bool opposite = (oppositeSignal == 1 && OrderType() == OP_SELL) ||
(oppositeSignal == -1 && OrderType() == OP_BUY);
if(opposite)
{
if(OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNONE);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Manage existing orders: optional opposite crossover exit |
//+------------------------------------------------------------------+
void ManageOrders()
{
if(!UseCloseSignals) return;
double fastMA = iMA(Symbol(), 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double slowMA = iMA(Symbol(), 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double prevFast = iMA(Symbol(), 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);
double prevSlow = iMA(Symbol(), 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);
bool bearCross = (prevFast > prevSlow && fastMA <= slowMA);
bool bullCross = (prevFast < prevSlow && fastMA >= slowMA);
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 && bearCross)
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrNONE);
else if(OrderType() == OP_SELL && bullCross)
OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```
Reference: Based on common low-risk trend-following principles for gold. Adapted for MQL4 stability and XAUUSD volatility.