Summary: Gold High Yield EA is a high-profit potential MQL4 expert advisor for XAUUSD. It uses volatility breakout with grid recovery zones. Suitable for M15 timeframe with strict drawdown controls.




Gold High Yield EA is designed specifically for gold (XAUUSD) to capture high-profit opportunities while maintaining structured risk controls. The EA employs a volatility breakout strategy on M15 timeframe, entering trades when price breaks recent high/low with sufficient ATR confirmation. A unique layered grid recovery system adds positions at predefined intervals when the market moves against the initial position, but only up to a maximum of 3 layers to control drawdown. The EA uses dynamic take profit levels based on volatility and includes a hard stop loss on the first position. Daily profit target and maximum drawdown limits protect the account from excessive losses.

Recommended Timeframe: M15
Trading Logic:
  • Breakout Detection: Price closes above recent 20-bar high (buy) or below 20-bar low (sell) on M15.

  • Volatility Confirmation: ATR(14) value must be above threshold (not in ultra-low volatility).

  • Grid Recovery: If position moves against by GridStepPoints, add a second layer (same direction). Maximum 3 layers.

  • Exit: All positions close when cumulative profit reaches TakeProfitPoints from average entry. Hard stop loss on first position at StopLossPoints.

  • Risk Control: Maximum daily loss 10%, maximum spread 40 points, no trading during news hours (optional).


  • ``mql4
    //+------------------------------------------------------------------+
    //| GoldHighYieldEA.mq4 |
    //+------------------------------------------------------------------+
    #property copyright ""
    #property link ""
    #property version "1.00"
    #property strict

    //--- input parameters with comments
    input double BaseLotSize = 0.01; // Base lot size for first position
    input double LotMultiplier = 1.5; // Lot multiplier for each grid layer (1.5x, 2.0x, etc.)
    input int BreakoutPeriod = 20; // Period for breakout high/low (bars)
    input int ATRPeriod = 14; // ATR period for volatility filter
    input double ATRMinThreshold = 1.2; // Minimum ATR multiplier (relative to 150 points base)
    input int GridStepPoints = 250; // Grid step in points between layers (250 points = 250 pips for gold)
    input int MaxLayers = 3; // Maximum number of grid layers (1 to 5 recommended)
    input int TakeProfitPoints = 400; // Take profit from average entry price (points)
    input int StopLossPoints = 800; // Hard stop loss on first position (points)
    input int MagicNumber = 202414; // Unique EA identifier
    input int MaxSpread = 40; // Maximum allowed spread (in points for gold)
    input double DailyProfitTarget = 15.0; // Daily profit target in percentage (close all trades)
    input double DailyLossLimit = 10.0; // Daily loss limit in percentage (stop trading)
    input bool UseNewsFilter = true; // Skip trading 30min before/after high impact news

    //--- global variables
    double dailyStartBalance = 0;
    datetime lastBarTime = 0;
    bool isDailyTargetHit = false;
    string newsTimes[] = {"13:30","15:00","18:00"}; // Example news hours (US session)

    //+------------------------------------------------------------------+
    //| Expert initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    dailyStartBalance = AccountBalance();
    lastBarTime = 0;
    isDailyTargetHit = false;
    return(INIT_SUCCEEDED);
    }

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

    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    // Daily profit target & loss limit
    double currentEquity = AccountEquity();
    double profitPercent = (currentEquity - dailyStartBalance) / dailyStartBalance 100;
    double lossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance
    100;

    if(profitPercent >= DailyProfitTarget && !isDailyTargetHit)
    {
    CloseAllOrders();
    isDailyTargetHit = true;
    Comment("Daily profit target reached. Closed all trades.");
    return;
    }
    if(lossPercent >= DailyLossLimit)
    {
    Comment("Daily loss limit reached. No new trades.");
    return;
    }

    // Reset daily balance at new day
    if(TimeDayOfYear(TimeCurrent()) != TimeDayOfYear(TimeCurrent() - PeriodSeconds(PERIOD_D1)))
    {
    dailyStartBalance = AccountBalance();
    isDailyTargetHit = false;
    }

    // News filter
    if(UseNewsFilter && IsNewsTime())
    {
    Comment("News time - no new trades");
    return;
    }

    // Spread filter
    if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
    {
    Comment("Spread too high: ", MarketInfo(Symbol(), MODE_SPREAD));
    return;
    }

    // New bar logic (M15)
    if(Time[0] == lastBarTime)
    return;
    lastBarTime = Time[0];

    // Manage existing grid positions - check for take profit
    if(CountPositions() > 0)
    {
    CheckGridTakeProfit();
    CheckAddGridLayer();
    return;
    }

    // ATR volatility filter
    double atr = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
    double atrMin = ATRMinThreshold 150; // 150 points base for gold on M15
    if(atr < atrMin)
    {
    Comment("Volatility too low, ATR: ", atr);
    return;
    }

    // Breakout detection
    double high20 = iHigh(Symbol(), PERIOD_M15, iHighest(Symbol(), PERIOD_M15, MODE_HIGH, BreakoutPeriod, 1));
    double low20 = iLow(Symbol(), PERIOD_M15, iLowest(Symbol(), PERIOD_M15, MODE_LOW, BreakoutPeriod, 1));
    double close1 = iClose(Symbol(), PERIOD_M15, 1);

    int cmd = -1;
    double sl = 0, tp = 0;

    if(close1 > high20)
    {
    cmd = OP_BUY;
    sl = SymbolInfoDouble(Symbol(), SYMBOL_BID) - StopLossPoints
    Point;
    tp = SymbolInfoDouble(Symbol(), SYMBOL_BID) + TakeProfitPoints Point;
    }
    else if(close1 < low20)
    {
    cmd = OP_SELL;
    sl = SymbolInfoDouble(Symbol(), SYMBOL_ASK) + StopLossPoints
    Point;
    tp = SymbolInfoDouble(Symbol(), SYMBOL_ASK) - TakeProfitPoints Point;
    }

    if(cmd != -1)
    {
    int ticket = OrderSend(Symbol(), cmd, BaseLotSize, (cmd==OP_BUY?Ask:Bid), 3, sl, tp, "Gold HighYield", MagicNumber, 0, clrNONE);
    if(ticket < 0)
    Print("OrderSend failed: ", GetLastError());
    }
    }

    //+------------------------------------------------------------------+
    //| Check if grid take profit condition is met |
    //+------------------------------------------------------------------+
    void CheckGridTakeProfit()
    {
    double totalProfit = 0;
    double totalLots = 0;
    double avgPrice = 0;
    double weightedPrice = 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();
    totalLots += OrderLots();
    weightedPrice += OrderOpenPrice()
    OrderLots();
    }
    }
    }

    if(totalLots > 0)
    avgPrice = weightedPrice / totalLots;

    double currentPrice = (OrderSelect(0, SELECT_BY_POS, MODE_TRADES) && OrderType() == OP_BUY) ? Bid : Ask;
    double profitPoints = 0;

    if(OrderSelect(0, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderType() == OP_BUY)
    profitPoints = (currentPrice - avgPrice) / Point;
    else
    profitPoints = (avgPrice - currentPrice) / Point;
    }

    if(profitPoints >= TakeProfitPoints)
    {
    CloseAllOrders();
    Print("Grid take profit achieved: ", profitPoints, " points");
    }
    }

    //+------------------------------------------------------------------+
    //| Check and add next grid layer if needed |
    //+------------------------------------------------------------------+
    void CheckAddGridLayer()
    {
    int positions = CountPositions();
    if(positions >= MaxLayers)
    return;

    double avgPrice = 0;
    double totalLots = 0;
    double weightedPrice = 0;
    int orderType = -1;

    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    {
    orderType = OrderType();
    totalLots += OrderLots();
    weightedPrice += OrderOpenPrice() OrderLots();
    }
    }
    }

    if(totalLots > 0)
    avgPrice = weightedPrice / totalLots;

    double currentPrice = (orderType == OP_BUY) ? Bid : Ask;
    double distance = 0;

    if(orderType == OP_BUY)
    distance = (avgPrice - currentPrice) / Point;
    else
    distance = (currentPrice - avgPrice) / Point;

    if(distance >= GridStepPoints)
    {
    double newLotSize = BaseLotSize
    MathPow(LotMultiplier, positions);
    if(newLotSize < 0.01) newLotSize = 0.01;

    int cmd = orderType;
    double sl = 0, tp = 0;

    if(cmd == OP_BUY)
    {
    sl = SymbolInfoDouble(Symbol(), SYMBOL_BID) - StopLossPoints Point;
    tp = SymbolInfoDouble(Symbol(), SYMBOL_BID) + TakeProfitPoints
    Point;
    int ticket = OrderSend(Symbol(), OP_BUY, newLotSize, Ask, 3, sl, tp, "Gold HighYield L" + IntegerToString(positions+1), MagicNumber, 0, clrNONE);
    if(ticket > 0)
    Print("Added grid layer ", positions+1, " Buy at ", Ask);
    else
    Print("Add layer failed: ", GetLastError());
    }
    else if(cmd == OP_SELL)
    {
    sl = SymbolInfoDouble(Symbol(), SYMBOL_ASK) + StopLossPoints Point;
    tp = SymbolInfoDouble(Symbol(), SYMBOL_ASK) - TakeProfitPoints
    Point;
    int ticket = OrderSend(Symbol(), OP_SELL, newLotSize, Bid, 3, sl, tp, "Gold HighYield L" + IntegerToString(positions+1), MagicNumber, 0, clrNONE);
    if(ticket > 0)
    Print("Added grid layer ", positions+1, " Sell at ", Bid);
    else
    Print("Add layer failed: ", GetLastError());
    }
    }
    }

    //+------------------------------------------------------------------+
    //| Check if current time is within news periods |
    //+------------------------------------------------------------------+
    bool IsNewsTime()
    {
    datetime currentTime = TimeCurrent();
    string currentHourMin = TimeToString(currentTime, TIME_MINUTES);

    for(int i = 0; i < ArraySize(newsTimes); i++)
    {
    datetime newsTime = StringToTime(TimeToString(currentTime, TIME_DATE) + " " + newsTimes[i]);
    if(MathAbs(currentTime - newsTime) < 1800) // 30 minutes before/after
    return true;
    }
    return false;
    }

    //+------------------------------------------------------------------+
    //| 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, 3, clrNONE);
    else if(OrderType() == OP_SELL)
    OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrNONE);
    }
    }
    }
    }
    //+------------------------------------------------------------------+
    ``
    Reference: Original MQL4 code for educational purposes.
    Disclaimer: High-profit strategies like grid trading involve significant risk of large drawdowns. This EA is provided as-is without any guarantee of profit. The term "high profit" refers to potential, not certainty. Test thoroughly on demo for at least 3 months before live trading. Past performance does not guarantee future results.