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:
  • Multi-Timeframe Alignment: H4 EMA(100) defines primary trend; H1 EMA(50) must align with same direction.

  • Trend Strength Validation: ADX(14) must exceed 25 to ensure trending market conditions.

  • Entry Trigger: Price closes beyond the recent 20-bar swing high (bullish) or swing low (bearish) with momentum confirmation.

  • Controlled Layering: Maximum 2 additional positions (3 total) allowed only when price moves favorably by 1.2x ATR from previous entry.

  • Volatility Guard: Current ATR(14) must not exceed 1.8x the 50-period average ATR.

  • 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.