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:
1. Breakout Detection: Price closes above recent 20-bar high (buy) or below 20-bar low (sell) on M15.
2. Volatility Confirmation: ATR(14) value must be above threshold (not in ultra-low volatility).
3. Grid Recovery: If position moves against by GridStepPoints, add a second layer (same direction). Maximum 3 layers.
4. Exit: All positions close when cumulative profit reaches TakeProfitPoints from average entry. Hard stop loss on first position at StopLossPoints.
5. 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.