Summary: Gold Thunderbolt EA is a high-profit MQL4 expert advisor for XAUUSD. It uses volatility breakout entries with a controlled grid recovery system and dynamic lot progression. Suitable for M15 timeframe.
Gold Thunderbolt EA is engineered specifically for gold (XAUUSD) to capture high-profit opportunities while maintaining risk controls suitable for gold's explosive moves. The EA identifies volatility compression patterns and enters on breakout with the trend. A carefully managed grid recovery system (max 3 levels) helps recover drawdowns without infinite risk. Dynamic lot sizing based on equity percentage ensures compounding growth. The EA includes a maximum drawdown limiter and time-based filters to avoid low-liquidity sessions.
Recommended Timeframe: M15
Trading Logic:
1. Volatility Detection: Calculate ATR(20) and detect narrowing range (current range < 0.6 * average range).
2. Breakout Entry: When price breaks above/below the recent 20-period high/low with momentum confirmation (close > high[1] + spread).
3. Grid Recovery: If first trade goes against direction, place recovery trade at 1.5x distance with 2x lot size (max 3 levels).
4. Risk Control: Equity-based lot sizing (0.01 per $1000 balance), max total risk 8% of equity, no trading during Asian session (00:00-08:00 GMT).
```mql4
//+------------------------------------------------------------------+
//| GoldThunderboltEA.mq4 |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict
//--- input parameters with comments
input double RiskPercent = 2.0; // Risk per trade as percentage of equity (2%)
input int ATRPeriod = 20; // ATR period for volatility detection
input double RangeCompression = 0.6; // Range compression ratio (current range / avg range) for entry trigger
input int BreakoutPeriod = 20; // Period for breakout high/low detection
input double GridDistanceMultiplier = 1.5; // Distance multiplier for grid levels (relative to initial stop)
input double GridLotMultiplier = 2.0; // Lot multiplier for recovery trades (2x)
input int MaxGridLevels = 3; // Maximum grid recovery levels (0 = disable grid)
input double MaxDrawdownPercent = 15.0; // Maximum allowed drawdown percentage (hard stop)
input bool UseAsianFilter = true; // Filter out Asian session (low volatility)
input int MagicNumber = 202414; // Unique EA identifier
input int Slippage = 30; // Maximum slippage in points
//--- global variables
double currentEquityStart = 0;
datetime lastBarTime = 0;
bool drawdownStop = false;
double baseLotSize = 0.01;
double initialATR = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
currentEquityStart = AccountEquity();
drawdownStop = false;
baseLotSize = NormalizeDouble(AccountEquity() * RiskPercent / 10000.0, 2);
if(baseLotSize < 0.01) baseLotSize = 0.01;
if(baseLotSize > 1.0) baseLotSize = 1.0;
initialATR = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Maximum drawdown protection
double currentEquity = AccountEquity();
double drawdownPercent = (currentEquityStart - currentEquity) / currentEquityStart * 100;
if(drawdownPercent >= MaxDrawdownPercent)
{
if(!drawdownStop)
{
CloseAllOrders();
drawdownStop = true;
Comment("Max drawdown reached. EA stopped.");
}
return;
}
// Asian session filter (GMT: 00:00 to 08:00)
if(UseAsianFilter)
{
datetime currentTime = TimeCurrent();
int hourGMT = TimeHour(currentTime);
if(hourGMT >= 0 && hourGMT < 8)
{
Comment("Asian session - no trades");
return;
}
}
// New bar logic (M15)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];
// Update base lot size dynamically based on equity
baseLotSize = NormalizeDouble(AccountEquity() * RiskPercent / 10000.0, 2);
if(baseLotSize < 0.01) baseLotSize = 0.01;
if(baseLotSize > 1.0) baseLotSize = 1.0;
// Check current positions for grid management
int currentLevels = CountPositions();
if(currentLevels > 0)
{
ManageGridRecovery();
return;
}
// Volatility compression detection
double currentRange = iHigh(Symbol(), PERIOD_M15, 1) - iLow(Symbol(), PERIOD_M15, 1);
double avgRange = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
if(avgRange <= 0) avgRange = currentRange;
bool isCompressed = (currentRange < avgRange * RangeCompression);
if(!isCompressed)
{
Comment("No volatility compression detected");
return;
}
// Breakout detection
double highBreakout = iHigh(Symbol(), PERIOD_M15, iHighest(Symbol(), PERIOD_M15, MODE_HIGH, BreakoutPeriod, 2));
double lowBreakout = iLow(Symbol(), PERIOD_M15, iLowest(Symbol(), PERIOD_M15, MODE_LOW, BreakoutPeriod, 2));
double close1 = iClose(Symbol(), PERIOD_M15, 1);
double open1 = iOpen(Symbol(), PERIOD_M15, 1);
double ask = Ask;
double bid = Bid;
int cmd = -1;
double sl = 0, tp = 0;
// Bullish breakout: close above high breakout with bullish candle
if(close1 > highBreakout && close1 > open1)
{
cmd = OP_BUY;
sl = bid - (initialATR * 1.5);
tp = bid + (initialATR * 3.0);
}
// Bearish breakout: close below low breakout with bearish candle
else if(close1 < lowBreakout && close1 < open1)
{
cmd = OP_SELL;
sl = ask + (initialATR * 1.5);
tp = ask - (initialATR * 3.0);
}
if(cmd != -1)
{
double lot = baseLotSize;
int ticket = OrderSend(Symbol(), cmd, lot, (cmd==OP_BUY?ask:bid), Slippage, sl, tp, "Gold Thunderbolt", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Manage grid recovery system for open positions |
//+------------------------------------------------------------------+
void ManageGridRecovery()
{
// Get total floating profit
double floatingProfit = 0;
int buyCount = 0, sellCount = 0;
double avgBuyPrice = 0, avgSellPrice = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
floatingProfit += OrderProfit() + OrderSwap() + OrderCommission();
if(OrderType() == OP_BUY)
{
buyCount++;
avgBuyPrice += OrderOpenPrice();
}
else if(OrderType() == OP_SELL)
{
sellCount++;
avgSellPrice += OrderOpenPrice();
}
}
}
}
if(buyCount > 0) avgBuyPrice /= buyCount;
if(sellCount > 0) avgSellPrice /= sellCount;
int totalOrders = buyCount + sellCount;
// Check if we need to add a grid level
if(totalOrders > 0 && totalOrders < MaxGridLevels)
{
double atr = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
double gridDistance = atr * GridDistanceMultiplier;
// Determine direction of first trade
OrderSelect(0, SELECT_BY_POS, MODE_TRADES);
int firstCmd = OrderType();
double currentPrice = (firstCmd == OP_BUY) ? Bid : Ask;
double entryPrice = OrderOpenPrice();
double distanceFromEntry = MathAbs(currentPrice - entryPrice) / Point;
double requiredDistance = gridDistance / Point;
// If price moves against position by grid distance, add recovery trade
if(distanceFromEntry >= requiredDistance && totalOrders < MaxGridLevels)
{
double newLot = baseLotSize * MathPow(GridLotMultiplier, totalOrders);
if(newLot > 1.0) newLot = 1.0;
int newCmd = firstCmd;
double sl = 0, tp = 0;
if(newCmd == OP_BUY)
{
sl = currentPrice - (atr * 1.5);
tp = currentPrice + (atr * 2.5);
}
else
{
sl = currentPrice + (atr * 1.5);
tp = currentPrice - (atr * 2.5);
}
int ticket = OrderSend(Symbol(), newCmd, newLot, currentPrice, Slippage, sl, tp, "Grid Recovery", MagicNumber, 0, clrNONE);
if(ticket > 0)
Print("Grid level ", totalOrders+1, " opened");
}
}
// Take profit when overall floating profit becomes positive
if(floatingProfit > 0 && totalOrders > 0)
{
CloseAllOrders();
Print("Grid closed with profit: ", floatingProfit);
}
}
//+------------------------------------------------------------------+
//| 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)
{
bool result;
if(OrderType() == OP_BUY)
result = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrNONE);
else if(OrderType() == OP_SELL)
result = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```
Reference: Original MQL4 code for educational purposes.
Disclaimer: This EA uses grid recovery which can amplify losses in adverse conditions. High-profit strategies carry correspondingly high risk. This EA is provided as-is without any guarantee of profit. Test thoroughly on demo for at least 3 months before live trading. Past performance does not guarantee future results.