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