Summary: Gold Apex Tracker EA is an MQL4 expert advisor for XAUUSD that combines multi-timeframe EMA trend filters, ADX strength validation, ATR volatility guard, and controlled layering with basket take profit. Suitable for H4 stable operation.
Gold Apex Tracker EA is engineered specifically for gold (XAUUSD) using a disciplined trend-following approach with multiple validation layers. Unlike aggressive grid or martingale systems that randomly accumulate positions, this EA waits for structural alignment across H1 and H4 timeframes, requiring both EMA confirmation and ADX trend strength validation before entry. Once a trend is confirmed, the EA enters with a fixed initial lot and may add up to two additional layers (controlled layering, no martingale progression) if the trend continues favorably. The EA includes ATR-based volatility filtering to avoid extreme market conditions, a basket take profit mechanism that closes all positions when a combined profit target is reached, daily equity protection, and Friday close safeguards. This design prioritizes stability and capital preservation over aggressive returns.
Recommended Timeframe: H4
Trading Logic:
1. Multi-Timeframe Alignment: H4 EMA(100) defines primary trend; H1 EMA(50) must align with same direction.
2. Trend Strength Validation: ADX(14) must exceed 25 to ensure trending market conditions.
3. Entry Trigger: Price closes beyond the recent 20-bar swing high (bullish) or swing low (bearish) with momentum confirmation.
4. Controlled Layering: Maximum 2 additional positions (3 total) allowed only when price moves favorably by 1.2x ATR from previous entry.
5. Volatility Guard: Current ATR(14) must not exceed 1.8x the 50-period average ATR.
6. Risk Management: Fixed ATR-based stop loss (1.5x ATR), take profit at 2.5x ATR, basket profit target of 150 points, daily loss limit 5%.
```mql4
//+------------------------------------------------------------------+
//| GoldApexTrackerEA.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 H4TrendPeriod = 100; // H4 EMA period for primary trend
input int H1TrendPeriod = 50; // H1 EMA period for trend alignment
input int StructureLookback = 20; // Bars for swing high/low detection
input int ADXPeriod = 14; // ADX period for trend strength
input int ADXThreshold = 25; // Minimum ADX value for trending market
input int ATRPeriod = 14; // ATR period for volatility
input double ATRMaxMultiplier = 1.8; // Max ATR vs average ATR (volatility guard)
input double ATRStopMultiplier = 1.5; // Stop loss as multiple of ATR
input double ATRTakeMultiplier = 2.5; // Take profit as multiple of ATR
input double LayerDistanceATR = 1.2; // Distance for adding layers (x ATR)
input int MaxLayers = 3; // Maximum position layers (including first)
input double BasketProfitPoints = 150; // Basket profit target in points
input double TrailingStartATR = 1.0; // Trailing activates at profit (x ATR)
input double TrailingStepATR = 0.5; // Trailing step (x ATR)
input int MagicNumber = 202422; // Unique EA identifier
input int MaxSpread = 35; // Maximum allowed spread in points
input double DailyLossLimit = 5.0; // Daily loss limit as percentage
input bool UseFridayClose = true; // Close trades before Friday 21:00 GMT
//--- global variables
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool fridayCloseExecuted = false;
double avgATR = 0;
double structureHigh = 0;
double structureLow = 0;
int lastDirection = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
fridayCloseExecuted = false;
avgATR = iATR(Symbol(), PERIOD_H4, ATRPeriod, 1);
if(avgATR <= 0) avgATR = 300 * Point;
lastDirection = 0;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Detect structural swing levels |
//+------------------------------------------------------------------+
void DetectStructureLevels()
{
int highestIdx = iHighest(Symbol(), PERIOD_H4, MODE_HIGH, StructureLookback, 1);
int lowestIdx = iLowest(Symbol(), PERIOD_H4, MODE_LOW, StructureLookback, 1);
if(highestIdx > 0)
structureHigh = iHigh(Symbol(), PERIOD_H4, highestIdx);
if(lowestIdx > 0)
structureLow = iLow(Symbol(), PERIOD_H4, lowestIdx);
}
//+------------------------------------------------------------------+
//| Get multi-timeframe trend alignment |
//+------------------------------------------------------------------+
int GetTrendAlignment()
{
double closeH4 = iClose(Symbol(), PERIOD_H4, 1);
double emaH4 = iMA(Symbol(), PERIOD_H4, H4TrendPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double closeH1 = iClose(Symbol(), PERIOD_H1, 1);
double emaH1 = iMA(Symbol(), PERIOD_H1, H1TrendPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
bool h4Bullish = (closeH4 > emaH4);
bool h4Bearish = (closeH4 < emaH4);
bool h1Bullish = (closeH1 > emaH1);
bool h1Bearish = (closeH1 < emaH1);
if(h4Bullish && h1Bullish) return 1;
if(h4Bearish && h1Bearish) return -1;
return 0;
}
//+------------------------------------------------------------------+
//| Check ADX trend strength |
//+------------------------------------------------------------------+
bool IsTrendStrong()
{
double adx = iADX(Symbol(), PERIOD_H4, ADXPeriod, PRICE_CLOSE, MODE_MAIN, 1);
return (adx >= ADXThreshold);
}
//+------------------------------------------------------------------+
//| Calculate basket floating profit/loss |
//+------------------------------------------------------------------+
double CalculateBasketProfit()
{
double totalProfit = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
}
}
}
return totalProfit;
}
//+------------------------------------------------------------------+
//| Check basket take profit condition |
//+------------------------------------------------------------------+
bool CheckBasketTakeProfit()
{
double basketProfit = CalculateBasketProfit();
double targetAmount = BasketProfitPoints * Point * LotSize * 100;
if(targetAmount <= 0) targetAmount = 15.0;
if(basketProfit >= targetAmount)
{
CloseAllOrders();
Print("Basket take profit triggered. Profit: ", basketProfit);
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Manage controlled position layering |
//+------------------------------------------------------------------+
void ManagePositionLayering(double atr)
{
int posCount = CountPositions();
if(posCount >= MaxLayers || posCount == 0) return;
// Get first order direction and price
int firstDirection = 0;
double firstOpenPrice = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
firstDirection = (OrderType() == OP_BUY) ? 1 : -1;
firstOpenPrice = OrderOpenPrice();
break;
}
}
}
if(firstDirection == 0) return;
double addDistance = atr * LayerDistanceATR;
double currentPrice = (firstDirection == 1) ? Bid : Ask;
double priceDiff = MathAbs(currentPrice - firstOpenPrice);
// Add layer if price moved favorably enough and within max layers
if(priceDiff >= addDistance && posCount < MaxLayers)
{
double sl = 0, tp = 0;
int cmd = firstDirection;
if(cmd == OP_BUY)
{
sl = currentPrice - (atr * ATRStopMultiplier);
tp = currentPrice + (atr * ATRTakeMultiplier);
}
else
{
sl = currentPrice + (atr * ATRStopMultiplier);
tp = currentPrice - (atr * ATRTakeMultiplier);
}
int ticket = OrderSend(Symbol(), cmd, LotSize, currentPrice, 5, sl, tp, "Apex Layer", MagicNumber, 0, clrNONE);
if(ticket > 0)
Print("Layer ", posCount+1, " added. Direction: ", cmd==OP_BUY?"BUY":"SELL");
}
}
//+------------------------------------------------------------------+
//| Manage trailing stop for open positions |
//+------------------------------------------------------------------+
void ManageTrailingStop(double atr)
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double activate = atr * TrailingStartATR;
double step = atr * TrailingStepATR;
double newSL = 0;
if(OrderType() == OP_BUY)
{
double profit = Bid - OrderOpenPrice();
if(profit >= activate)
{
newSL = Bid - step;
if(newSL > OrderStopLoss())
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
else if(OrderType() == OP_SELL)
{
double profit = OrderOpenPrice() - Ask;
if(profit >= activate)
{
newSL = Ask + step;
if(newSL < OrderStopLoss() || OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
break;
}
}
}
}
//+------------------------------------------------------------------+
//| Check structural breakout entry |
//+------------------------------------------------------------------+
bool CheckStructuralBreakout(int direction, double &entryPrice, double &sl, double &tp, double atr)
{
if(direction == 0) return false;
double close1 = iClose(Symbol(), PERIOD_H4, 1);
if(direction == 1 && structureHigh > 0)
{
if(close1 > structureHigh)
{
entryPrice = Ask;
sl = entryPrice - (atr * ATRStopMultiplier);
tp = entryPrice + (atr * ATRTakeMultiplier);
return true;
}
}
else if(direction == -1 && structureLow > 0)
{
if(close1 < structureLow)
{
entryPrice = Bid;
sl = entryPrice + (atr * ATRStopMultiplier);
tp = entryPrice - (atr * ATRTakeMultiplier);
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| 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(UseFridayClose && !fridayCloseExecuted)
{
datetime currentTime = TimeCurrent();
if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 21)
{
CloseAllOrders();
fridayCloseExecuted = true;
return;
}
if(TimeDayOfWeek(currentTime) != 5)
fridayCloseExecuted = false;
}
// Spread filter
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("Spread too high: ", MarketInfo(Symbol(), MODE_SPREAD));
return;
}
// New bar logic (H4)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];
// Update structure levels
DetectStructureLevels();
// Get ATR for volatility filtering
double atr = iATR(Symbol(), PERIOD_H4, ATRPeriod, 1);
if(atr > 0) avgATR = (avgATR * 0.95) + (atr * 0.05);
// Volatility guard
if(atr > avgATR * ATRMaxMultiplier && avgATR > 0)
{
Comment("Volatility too high. ATR: ", atr);
return;
}
// Manage existing positions
int posCount = CountPositions();
if(posCount > 0)
{
CheckBasketTakeProfit();
ManagePositionLayering(atr);
ManageTrailingStop(atr);
return;
}
// Check trend alignment
int trendDirection = GetTrendAlignment();
if(trendDirection == 0)
{
Comment("H4 and H1 trends not aligned");
return;
}
// Check ADX trend strength
if(!IsTrendStrong())
{
Comment("ADX below threshold. No strong trend.");
return;
}
// Check structural breakout entry
double entryPrice = 0, sl = 0, tp = 0;
if(CheckStructuralBreakout(trendDirection, entryPrice, sl, tp, atr))
{
int cmd = (trendDirection == 1) ? OP_BUY : OP_SELL;
int ticket = OrderSend(Symbol(), cmd, LotSize, entryPrice, 5, sl, tp, "Apex Entry", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
else
Print("Structural breakout entry opened. Direction: ", cmd==OP_BUY?"BUY":"SELL");
}
}
//+------------------------------------------------------------------+
//| 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, 5, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, 5, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```
Reference: Original MQL4 code inspired by recent structural trend-following principles for XAUUSD as seen in institutional-grade gold EAs.
Disclaimer: Gold trading involves significant risk due to high volatility and leverage. This EA is provided as-is without any guarantee of profit. Test thoroughly on a demo account for at least 3 months before live deployment. Past performance does not guarantee future results.