Summary: Golden Phoenix EA is an MQL4 expert advisor for gold (XAUUSD) using adaptive trend following with dual EMA crossover, ATR volatility filter, and daily loss limit. Suitable for H1 timeframe.
Golden Phoenix EA is a robust MQL4 expert advisor designed specifically for gold (XAUUSD) trading. It employs an adaptive trend-following strategy using dual exponential moving averages (EMA) crossover with dynamic confirmation. The EA incorporates ATR-based volatility filtering to avoid whipsaws during low volatility ranging markets. A built-in daily equity protection mechanism and maximum spread control ensure stable operation. Each trade is protected by a trailing stop that locks in profits as the trend extends.
Recommended Timeframe: H1
Trading Logic:
1. Trend Detection: Fast EMA (12) crosses above Slow EMA (26) for uptrend; opposite for downtrend.
2. Entry Confirmation: Price must close beyond the crossover point and ATR(14) > 150 points (minimum volatility).
3. Volatility Filter: ATR value must be below 3x average ATR to avoid extreme volatility spikes.
4. Risk Management: Fixed stop loss (350 points), take profit (700 points), trailing stop activates after 400 points profit.
5. Position Management: Maximum 1 open position, daily loss limit 5% of balance, maximum spread 35 points.
```mql4
//+------------------------------------------------------------------+
//| GoldenPhoenixEA.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 XAUUSD)
input int FastEMAPeriod = 12; // Fast EMA period for trend detection
input int SlowEMAPeriod = 26; // Slow EMA period for trend detection
input int ATRPeriod = 14; // ATR period for volatility filtering
input int StopLossPoints = 350; // Stop loss in points (350 points for gold)
input int TakeProfitPoints = 700; // Take profit in points (2:1 risk-reward)
input int TrailingStart = 400; // Trailing stop activation threshold (points)
input int TrailingStep = 150; // Trailing stop step (points)
input int MinVolatility = 150; // Minimum ATR value required to trade (points)
input double MaxVolatilityMult = 3.0; // Maximum ATR multiplier relative to average
input int MagicNumber = 202415; // Unique EA identifier
input int MaxSpread = 35; // Maximum allowed spread (points)
input double DailyLossLimit = 5.0; // Daily loss limit as 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;
double avgATR = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
isFridayCloseExecuted = false;
avgATR = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
if(avgATR <= 0) avgATR = 200;
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 (H1)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];
// Check for existing position
if(CountPositions() > 0)
{
ManageTrailingStop();
return;
}
// Get indicator values
double fastEMA = iMA(Symbol(), PERIOD_H1, FastEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double slowEMA = iMA(Symbol(), PERIOD_H1, SlowEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double fastEMA_prev = iMA(Symbol(), PERIOD_H1, FastEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 2);
double slowEMA_prev = iMA(Symbol(), PERIOD_H1, SlowEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 2);
double close1 = iClose(Symbol(), PERIOD_H1, 1);
// ATR volatility filter
double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
double atrThreshold = avgATR * MaxVolatilityMult;
if(atr < MinVolatility)
{
Comment("Volatility too low for trend: ", atr);
return;
}
if(atr > atrThreshold && atrThreshold > 0)
{
Comment("Volatility spike detected: ", atr);
return;
}
avgATR = (avgATR * 0.9) + (atr * 0.1);
int cmd = -1;
double sl = 0, tp = 0;
double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
// Bullish crossover: fast EMA crosses above slow EMA
if(fastEMA_prev <= slowEMA_prev && fastEMA > slowEMA)
{
cmd = OP_BUY;
sl = bid - StopLossPoints * Point;
tp = bid + TakeProfitPoints * Point;
}
// Bearish crossover: fast EMA crosses below slow EMA
else if(fastEMA_prev >= slowEMA_prev && fastEMA < slowEMA)
{
cmd = OP_SELL;
sl = ask + StopLossPoints * Point;
tp = ask - TakeProfitPoints * Point;
}
if(cmd != -1)
{
int ticket = OrderSend(Symbol(), cmd, LotSize, (cmd==OP_BUY?ask:bid), 3, sl, tp, "Golden Phoenix", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed. Error: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Manage trailing stop for open position |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double currentStop = OrderStopLoss();
double newStop = 0;
double profitPoints = 0;
if(OrderType() == OP_BUY)
{
profitPoints = (Bid - OrderOpenPrice()) / Point;
if(profitPoints >= TrailingStart)
{
newStop = Bid - (TrailingStep * Point);
if(newStop > currentStop || currentStop == 0)
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newStop, OrderTakeProfit(), 0, clrNONE))
Print("Trailing stop updated for BUY #", OrderTicket());
}
}
}
else if(OrderType() == OP_SELL)
{
profitPoints = (OrderOpenPrice() - Ask) / Point;
if(profitPoints >= TrailingStart)
{
newStop = Ask + (TrailingStep * Point);
if(newStop < currentStop || currentStop == 0)
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newStop, OrderTakeProfit(), 0, clrNONE))
Print("Trailing stop updated for SELL #", OrderTicket());
}
}
}
break;
}
}
}
}
//+------------------------------------------------------------------+
//| 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: Forex and gold trading involve substantial risk of loss. This EA is provided "as is" without any warranty of profitability. Always backtest and forward test on a demo account before using live funds. Past performance does not guarantee future results.