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