Summary: Gold Apex EA is an MQL4 expert advisor for XAUUSD that combines ADX trend strength detection, RSI momentum filtering, and a structured contrarian grid layer with dynamic ATR stops. Suitable for H1 stable operation.




Gold Apex EA is engineered specifically for gold (XAUUSD) based on analysis of professional commercial EAs released in early 2026 . Unlike pure martingale or simple trend-following systems, this EA uses a hybrid approach: it first identifies trend direction using ADX (trend strength) and RSI (momentum), then enters a primary trend trade. A controlled, limited-layer contrarian grid mechanism is activated only when certain drawdown conditions are met, but strictly capped to prevent runaway losses. All positions are protected by ATR-based dynamic stop losses and a basket take profit system. Daily equity protection, spread control, and Friday close mechanisms are included.

Recommended Timeframe: H1
Trading Logic:
1. Primary Trend Filter: ADX(14) > 25 confirms trending market. EMA(50) determines direction.
2. Momentum Confirmation: RSI(14) must be above 55 for longs or below 45 for shorts.
3. Primary Entry: Price pulls back to EMA(50) with a confirming candlestick pattern.
4. Controlled Grid Layer (Contrarian): Maximum 2 additional positions, placed at 1.5x and 2.0x ATR distance from average entry. Lot sizes are fixed (no progression). Activated only after primary position reaches -1.2x ATR.
5. Risk Management: ATR-based stop loss (1.8x ATR), basket take profit at 2.5x ATR across all open positions, trailing stop after 1.0x ATR profit.

```mql4
//+------------------------------------------------------------------+
//| GoldApexEA.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 TrendEMAPeriod = 50; // EMA period for trend direction
input int ADXPeriod = 14; // ADX period for trend strength
input int ADXThreshold = 25; // Minimum ADX for trending market
input int RSIPeriod = 14; // RSI period for momentum filter
input int RSIUpperThreshold = 55; // RSI minimum for long entry
input int RSILowerThreshold = 45; // RSI maximum for short entry
input int ATRPeriod = 14; // ATR period for volatility
input double ATRStopMultiplier = 1.8; // Stop loss as multiple of ATR
input double ATRTakeMultiplier = 2.5; // Take profit as multiple of ATR
input double GridTriggerATR = 1.2; // Grid activation at -x ATR from entry
input double GridDistanceATR = 1.5; // Grid position distance in ATR multiples
input int MaxGridLevels = 2; // Maximum contrarian grid positions
input double TrailingStartATR = 1.0; // Trailing activates at profit (x ATR)
input double TrailingStepATR = 0.5; // Trailing step (x ATR)
input int MagicNumber = 202423; // 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 avgEntryPrice = 0;
int primaryDirection = 0;
datetime gridActivationTime = 0;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
fridayCloseExecuted = false;
avgATR = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
if(avgATR <= 0) avgATR = 250 * Point;
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}

//+------------------------------------------------------------------+
//| Check if market is trending using ADX |
//+------------------------------------------------------------------+
bool IsTrending()
{
double adx = iADX(Symbol(), PERIOD_H1, ADXPeriod, PRICE_CLOSE, MODE_MAIN, 1);
return (adx >= ADXThreshold);
}

//+------------------------------------------------------------------+
//| Get trend direction using EMA |
//+------------------------------------------------------------------+
int GetTrendDirection()
{
double close1 = iClose(Symbol(), PERIOD_H1, 1);
double ema = iMA(Symbol(), PERIOD_H1, TrendEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
if(close1 > ema) return 1;
if(close1 < ema) return -1;
return 0;
}

//+------------------------------------------------------------------+
//| Calculate average entry price of all open positions |
//+------------------------------------------------------------------+
double CalculateAvgEntryPrice()
{
double totalPrice = 0;
int totalOrders = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
totalPrice += OrderOpenPrice();
totalOrders++;
}
}
}
if(totalOrders == 0) return 0;
return totalPrice / totalOrders;
}

//+------------------------------------------------------------------+
//| Calculate current floating drawdown in ATR units |
//+------------------------------------------------------------------+
double CalculateDrawdownATR(double atr)
{
if(atr <= 0) return 0;
double avgPrice = CalculateAvgEntryPrice();
if(avgPrice == 0) return 0;

double currentPrice = (primaryDirection == 1) ? Bid : Ask;
double drawdown = 0;

if(primaryDirection == 1 && currentPrice < avgPrice)
drawdown = (avgPrice - currentPrice) / atr;
else if(primaryDirection == -1 && currentPrice > avgPrice)
drawdown = (currentPrice - avgPrice) / atr;

return drawdown;
}

//+------------------------------------------------------------------+
//| Check primary entry condition (trend pullback) |
//+------------------------------------------------------------------+
bool CheckPrimaryEntry(int direction, double &entryPrice, double &sl, double &tp, double atr)
{
if(direction == 0) return false;

double ema = iMA(Symbol(), PERIOD_H1, TrendEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double close1 = iClose(Symbol(), PERIOD_H1, 1);
double low1 = iLow(Symbol(), PERIOD_H1, 1);
double high1 = iHigh(Symbol(), PERIOD_H1, 1);
double open1 = iOpen(Symbol(), PERIOD_H1, 1);
double rsi = iRSI(Symbol(), PERIOD_H1, RSIPeriod, PRICE_CLOSE, 1);

if(direction == 1) // Long
{
bool pulledToEMA = (low1 <= ema && close1 > ema);
bool bullishCandle = (close1 > open1);
bool rsiOk = (rsi >= RSIUpperThreshold);

if(pulledToEMA && bullishCandle && rsiOk)
{
entryPrice = Ask;
sl = entryPrice - (atr * ATRStopMultiplier);
tp = entryPrice + (atr * ATRTakeMultiplier);
return true;
}
}
else if(direction == -1) // Short
{
bool pulledToEMA = (high1 >= ema && close1 < ema);
bool bearishCandle = (close1 < open1);
bool rsiOk = (rsi <= RSILowerThreshold);

if(pulledToEMA && bearishCandle && rsiOk)
{
entryPrice = Bid;
sl = entryPrice + (atr * ATRStopMultiplier);
tp = entryPrice - (atr * ATRTakeMultiplier);
return true;
}
}
return false;
}

//+------------------------------------------------------------------+
//| Check grid entry condition (counter-trend recovery) |
//+------------------------------------------------------------------+
bool CheckGridEntry(int direction, double &entryPrice, double &sl, double &tp, double atr)
{
if(direction == 0) return false;
if(CalculateAvgEntryPrice() == 0) return false;

double avgPrice = CalculateAvgEntryPrice();
double currentPrice = (direction == 1) ? Ask : Bid;
double priceDiff = MathAbs(currentPrice - avgPrice);
double requiredDiff = atr * GridDistanceATR;

// Only add grid position if drawdown exceeds threshold and max levels not reached
double drawdownATR = CalculateDrawdownATR(atr);
if(drawdownATR >= GridTriggerATR)
{
if(direction == 1 && currentPrice < avgPrice - requiredDiff)
{
entryPrice = Ask;
sl = entryPrice - (atr * ATRStopMultiplier);
tp = entryPrice + (atr * ATRTakeMultiplier);
return true;
}
else if(direction == -1 && currentPrice > avgPrice + requiredDiff)
{
entryPrice = Bid;
sl = entryPrice + (atr * ATRStopMultiplier);
tp = entryPrice - (atr * ATRTakeMultiplier);
return true;
}
}
return false;
}

//+------------------------------------------------------------------+
//| 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 - close all if total profit positive |
//+------------------------------------------------------------------+
bool CheckBasketTakeProfit(double atr)
{
double basketProfit = CalculateBasketProfit();
double avgPrice = CalculateAvgEntryPrice();
if(avgPrice == 0) return false;

double currentPrice = (primaryDirection == 1) ? Bid : Ask;
double move = MathAbs(currentPrice - avgPrice);
double targetMove = atr * ATRTakeMultiplier;

if(basketProfit > 0 && move >= targetMove * 0.6) // Early take profit
{
CloseAllOrders();
Print("Basket take profit triggered. Profit: ", basketProfit);
return true;
}
else if(basketProfit > 5.0) // Minimum profit threshold
{
CloseAllOrders();
Print("Basket take profit (positive). Profit: ", basketProfit);
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Manage trailing stop for all 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);
}
}
}
}
}
}

//+------------------------------------------------------------------+
//| Update average ATR and primary direction tracking |
//+------------------------------------------------------------------+
void UpdateTracking(double atr)
{
if(atr > 0) avgATR = (avgATR * 0.95) + (atr * 0.05);

int posCount = CountPositions();
if(posCount > 0 && primaryDirection == 0)
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
primaryDirection = (OrderType() == OP_BUY) ? 1 : -1;
break;
}
}
}
}
else if(posCount == 0)
{
primaryDirection = 0;
}
}

//+------------------------------------------------------------------+
//| 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 (H1)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];

// Get ATR
double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
if(atr <= 0) atr = avgATR;

// Update tracking variables
UpdateTracking(atr);

// Manage existing positions
int posCount = CountPositions();
if(posCount > 0)
{
// Check basket take profit
if(CheckBasketTakeProfit(atr))
return;

// Manage trailing stop
ManageTrailingStop(atr);

// Check for grid entry (additional positions)
if(posCount < MaxGridLevels + 1 && primaryDirection != 0)
{
double entryPrice = 0, sl = 0, tp = 0;
if(CheckGridEntry(primaryDirection, entryPrice, sl, tp, atr))
{
int cmd = (primaryDirection == 1) ? OP_BUY : OP_SELL;
int ticket = OrderSend(Symbol(), cmd, LotSize, entryPrice, 5, sl, tp, "Apex Grid", MagicNumber, 0, clrNONE);
if(ticket > 0)
Print("Grid layer added. Direction: ", cmd==OP_BUY?"BUY":"SELL");
}
}
return;
}

// --- No open positions - check for primary entry ---

// Check trending market
if(!IsTrending())
{
Comment("ADX below threshold. No strong trend.");
return;
}

// Get trend direction
int trendDir = GetTrendDirection();
if(trendDir == 0)
{
Comment("No clear trend direction.");
return;
}

// Volatility guard
if(atr > avgATR * 2.0 && avgATR > 0)
{
Comment("Volatility too high. ATR: ", atr);
return;
}

// Check primary entry
double entryPrice = 0, sl = 0, tp = 0;
if(CheckPrimaryEntry(trendDir, entryPrice, sl, tp, atr))
{
int cmd = (trendDir == 1) ? OP_BUY : OP_SELL;
int ticket = OrderSend(Symbol(), cmd, LotSize, entryPrice, 5, sl, tp, "Apex Primary", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
else
{
Print("Primary entry opened. Direction: ", cmd==OP_BUY?"BUY":"SELL");
primaryDirection = trendDir;
}
}
}

//+------------------------------------------------------------------+
//| 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 Gold Signal Swing Pro , Quant MT4 Gold , and Golden tut Super Trend commercial EA logic structures observed in early-to-mid 2026.
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.