Summary: Gold Apex Trend EA is an MQL4 expert advisor for XAUUSD that uses H4 trend structure confirmation, ATR volatility filtering, and basket profit targeting. Suitable for H1 timeframe stable operation.




Gold Apex Trend EA is engineered specifically for stable gold trading with a focus on structural trend analysis. Unlike aggressive grid systems that ignore market direction, this EA uses multi-timeframe trend confirmation to ensure trades align with the dominant market structure. The EA identifies key swing points on H4, confirms trend strength with ADX, and enters on H1 pullbacks. Each position is protected by ATR-based stops, and a basket profit mechanism locks in gains. Daily loss limits and spread controls provide additional safety layers.

Recommended Timeframe: H1 (for execution) with H4 for trend reference
Trading Logic:
1. Trend Structure: Identify swing highs/lows on H4 over the last 40 candles to determine trend direction.
2. Trend Strength: ADX(14) > 25 to avoid low-volatility chop.
3. Entry Signal: Price pulls back to H1 EMA(20) in the direction of H4 structure, with confirming candlestick pattern.
4. Risk Management: ATR-based stop loss (1.8x ATR), take profit at 3x ATR. Maximum 2 concurrent positions, daily loss limit 5%.

```mql4
//+------------------------------------------------------------------+
//| GoldApexTrendEA.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 H4StructurePeriod = 40; // H4 lookback for swing structure detection
input int H1EntryMAPeriod = 20; // H1 EMA period for pullback entries
input int ADXPeriod = 14; // ADX period for trend strength filter
input int ADXThreshold = 25; // Minimum ADX value to allow entries
input int ATRPeriod = 14; // ATR period for dynamic stops
input double ATRStopMultiplier = 1.8; // Stop loss as multiple of ATR
input double ATRTakeMultiplier = 3.0; // Take profit as multiple of ATR
input int MaxPositions = 2; // Maximum concurrent positions allowed
input double BasketProfitPoints = 200; // Combined profit target in points
input int MagicNumber = 202421; // 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;
int h4TrendDirection = 0; // 1 = bullish, -1 = bearish
datetime trendConfirmedTime = 0;

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

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

//+------------------------------------------------------------------+
//| Detect H4 trend structure using swing points |
//+------------------------------------------------------------------+
int DetectH4TrendStructure()
{
// Find recent swing high and swing low on H4
int swingHighIdx = iHighest(Symbol(), PERIOD_H4, MODE_HIGH, H4StructurePeriod, 1);
int swingLowIdx = iLowest(Symbol(), PERIOD_H4, MODE_LOW, H4StructurePeriod, 1);

if(swingHighIdx < 0 || swingLowIdx < 0) return 0;

double swingHigh = iHigh(Symbol(), PERIOD_H4, swingHighIdx);
double swingLow = iLow(Symbol(), PERIOD_H4, swingLowIdx);
double currentClose = iClose(Symbol(), PERIOD_H4, 1);
double currentHigh = iHigh(Symbol(), PERIOD_H4, 1);
double currentLow = iLow(Symbol(), PERIOD_H4, 1);

// Determine trend based on higher highs and higher lows pattern
bool bullishStructure = (currentHigh > swingHigh && currentLow > swingLow);
bool bearishStructure = (currentLow < swingLow && currentHigh < swingHigh);

// Additional confirmation using 200 EMA on H4
double ema200H4 = iMA(Symbol(), PERIOD_H4, 200, 0, MODE_EMA, PRICE_CLOSE, 1);

if(bullishStructure && currentClose > ema200H4) return 1;
if(bearishStructure && currentClose < ema200H4) 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);
}

//+------------------------------------------------------------------+
//| Check pullback entry on H1 |
//+------------------------------------------------------------------+
bool CheckPullbackEntry(int trendDir, double &entryPrice, double &sl, double &tp, double atr)
{
if(trendDir == 0) return false;

double ema20H1 = iMA(Symbol(), PERIOD_H1, H1EntryMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double close1 = iClose(Symbol(), PERIOD_H1, 1);
double open1 = iOpen(Symbol(), PERIOD_H1, 1);
double low1 = iLow(Symbol(), PERIOD_H1, 1);
double high1 = iHigh(Symbol(), PERIOD_H1, 1);

if(trendDir == 1) // Bullish - look for pullback to EMA20
{
bool pulledToEMA = (low1 <= ema20H1 && close1 > ema20H1);
bool bullishCandle = (close1 > open1);
bool confirmMomentum = (close1 > iClose(Symbol(), PERIOD_H1, 2));

if(pulledToEMA && bullishCandle && confirmMomentum)
{
entryPrice = Ask;
sl = entryPrice - (atr * ATRStopMultiplier);
tp = entryPrice + (atr * ATRTakeMultiplier);
return true;
}
}
else if(trendDir == -1) // Bearish - look for pullback to EMA20
{
bool pulledToEMA = (high1 >= ema20H1 && close1 < ema20H1);
bool bearishCandle = (close1 < open1);
bool confirmMomentum = (close1 < iClose(Symbol(), PERIOD_H1, 2));

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

//+------------------------------------------------------------------+
//| Calculate basket floating profit in points |
//+------------------------------------------------------------------+
double CalculateBasketProfitPoints()
{
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();
}
}
}
// Convert profit to points approximation
double pointValue = LotSize * 100; // Approximate for gold, 0.01 lot = $1 per point
if(pointValue > 0)
return totalProfit / pointValue;
return 0;
}

//+------------------------------------------------------------------+
//| Check and execute basket take profit |
//+------------------------------------------------------------------+
bool CheckBasketTakeProfit()
{
double profitPoints = CalculateBasketProfitPoints();
if(profitPoints >= BasketProfitPoints)
{
CloseAllOrders();
Print("Basket take profit triggered at ", profitPoints, " points");
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Manage existing positions - trail stop and basket TP |
//+------------------------------------------------------------------+
void ManagePositions(double atr)
{
CheckBasketTakeProfit();

// Trail stop for individual positions
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double trailStep = atr * 0.8;
double newSL = 0;

if(OrderType() == OP_BUY)
{
double profit = Bid - OrderOpenPrice();
if(profit > atr * 1.2) // Trail after 1.2x ATR profit
{
newSL = Bid - trailStep;
if(newSL > OrderStopLoss())
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
else if(OrderType() == OP_SELL)
{
double profit = OrderOpenPrice() - Ask;
if(profit > atr * 1.2)
{
newSL = Ask + trailStep;
if(newSL < OrderStopLoss() || OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
}
}
}
}

//+------------------------------------------------------------------+
//| 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);
}
}
}
}

//+------------------------------------------------------------------+
//| 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 for calculations
double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
if(atr > 0) avgATR = (avgATR * 0.95) + (atr * 0.05);

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

// Manage existing positions
int posCount = CountPositions();
if(posCount > 0)
{
ManagePositions(atr);
return;
}

// Check max positions limit
if(posCount >= MaxPositions)
return;

// Detect H4 trend structure (update every 4 hours)
static datetime lastTrendCheck = 0;
if(TimeCurrent() - lastTrendCheck >= 14400)
{
h4TrendDirection = DetectH4TrendStructure();
lastTrendCheck = TimeCurrent();
}

// No clear trend, skip trading
if(h4TrendDirection == 0)
{
Comment("No clear H4 trend structure");
return;
}

// Check ADX trend strength
if(!IsTrendStrong())
{
Comment("ADX below threshold, no strong trend");
return;
}

// Check pullback entry
double entryPrice = 0, sl = 0, tp = 0;
if(CheckPullbackEntry(h4TrendDirection, entryPrice, sl, tp, atr))
{
int cmd = (h4TrendDirection == 1) ? OP_BUY : OP_SELL;
int ticket = OrderSend(Symbol(), cmd, LotSize, entryPrice, 5, sl, tp, "Gold Apex", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
else
Print("Entry opened. Direction: ", cmd==OP_BUY?"BUY":"SELL");
}
}
//+------------------------------------------------------------------+
```
Reference: Original MQL4 code designed based on structural trend analysis principles for XAUUSD gold trading.
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 before live deployment. Past performance does not guarantee future results.