Gold Thunder EA is designed specifically for gold (XAUUSD) to capture high-profit opportunities while maintaining controlled risk. The EA identifies Asian session range (00:00-06:00 GMT) and enters on breakout of this range during London/NY session. It uses a dynamic recovery mechanism with a conservative martingale multiplier limited to 2 steps to avoid account blowout. Each trade sequence is protected by an equity-based stop loss. The EA also features a trailing stop to lock profits on winning trades.
Recommended Timeframe: M15
Trading Logic:
``
mql4
//+------------------------------------------------------------------+
//| GoldThunderEA.mq4 |
//| |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict
//--- input parameters with comments
input double InitialLot = 0.01; // Initial lot size (0.01 for gold)
input int BreakoutPips = 15; // Breakout confirmation pips above/below Asian range
input int StopLossPips = 250; // Initial stop loss in pips (250 points)
input int TakeProfitPips = 500; // Initial take profit in pips (2:1 risk-reward)
input double RecoveryMultiplier = 2.0; // Lot multiplier for recovery step (2.0 = double)
input int MaxRecoverySteps = 2; // Maximum recovery steps (0 = disable recovery)
input int TrailingStartPips = 300; // When profit reaches this pips, start trailing
input int TrailingStepPips = 50; // Trailing stop distance in pips
input int AsianStartHour = 0; // Asian session start hour (server time, 0 = 00:00)
input int AsianEndHour = 6; // Asian session end hour (6 = 06:00)
input int TradeStartHour = 7; // Trading start hour (7 = 07:00)
input int TradeEndHour = 17; // Trading end hour (17 = 17:00)
input int MaxSpread = 40; // Maximum allowed spread (in points)
input double MaxDailyDrawdown = 15.0; // Maximum daily drawdown percentage (stop trading)
input int MagicNumber = 202415; // Unique EA identifier
input bool UseFridayFilter = true; // No new trades after Friday 18:00
//--- global variables
double asianHigh = 0;
double asianLow = 0;
datetime asianDate = 0;
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool recoveryActive = false;
int recoveryStep = 0;
double originalSL = 0;
double originalTP = 0;
double lastEntryPrice = 0;
int lastOrderType = -1;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
asianHigh = 0;
asianLow = 0;
asianDate = 0;
recoveryActive = false;
recoveryStep = 0;
lastBarTime = 0;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Daily drawdown protection
double currentEquity = AccountEquity();
double ddPercent = (dailyStartBalance - currentEquity) / dailyStartBalance 100;
if(ddPercent > MaxDailyDrawdown && dailyStartBalance > 0)
{
Comment("Daily drawdown limit reached: ", ddPercent, "%");
return;
}
// Friday filter
if(UseFridayFilter)
{
datetime now = TimeCurrent();
if(TimeDayOfWeek(now) == 5 && TimeHour(now) >= 18)
{
Comment("Friday after 18:00 - no new trades");
return;
}
}
// Spread filter
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("Spread too high: ", MarketInfo(Symbol(), MODE_SPREAD));
return;
}
// Reset daily balance at new day
datetime currentDay = iTime(Symbol(), PERIOD_D1, 0);
static datetime lastDay = 0;
if(currentDay != lastDay)
{
lastDay = currentDay;
dailyStartBalance = AccountBalance();
recoveryActive = false;
recoveryStep = 0;
Comment("");
}
//--- Asian range calculation (once per day)
datetime nowTime = TimeCurrent();
int currentHour = TimeHour(nowTime);
if(currentHour >= AsianStartHour && currentHour < AsianEndHour && asianDate != iTime(Symbol(), PERIOD_D1, 0))
{
double currentHigh = iHigh(Symbol(), PERIOD_M15, 0);
double currentLow = iLow(Symbol(), PERIOD_M15, 0);
if(asianHigh == 0 || currentHigh > asianHigh)
asianHigh = currentHigh;
if(asianLow == 0 || currentLow < asianLow)
asianLow = currentLow;
asianDate = iTime(Symbol(), PERIOD_D1, 0);
}
//--- Check existing positions
int posCount = CountPositions();
if(posCount > 0)
{
ManageTrailingStop();
return;
}
//--- Reset recovery flags when no position
if(recoveryActive && posCount == 0)
{
recoveryActive = false;
recoveryStep = 0;
}
//--- Trading time window check
if(currentHour < TradeStartHour || currentHour >= TradeEndHour)
{
Comment("Outside trading hours");
return;
}
//--- Need Asian range
if(asianHigh == 0 || asianLow == 0)
{
Comment("Calculating Asian range...");
return;
}
double ask = Ask;
double bid = Bid;
double breakoutPipsValue = BreakoutPips Point;
double slPips = StopLossPips Point;
double tpPips = TakeProfitPips Point;
//--- Determine lot size based on recovery step
double lotToUse = InitialLot;
if(recoveryActive && recoveryStep > 0)
{
lotToUse = InitialLot MathPow(RecoveryMultiplier, recoveryStep);
if(lotToUse > 1.0) lotToUse = 1.0; // Safety cap
}
//--- Buy breakout signal (price breaks above Asian high + breakout pips)
if(ask > asianHigh + breakoutPipsValue)
{
double sl = ask - slPips;
double tp = ask + tpPips;
int ticket = OrderSend(Symbol(), OP_BUY, lotToUse, ask, 3, sl, tp, "Gold Thunder Buy", MagicNumber, 0, clrNONE);
if(ticket > 0)
{
recoveryActive = (recoveryStep > 0);
lastEntryPrice = ask;
lastOrderType = OP_BUY;
originalSL = sl;
originalTP = tp;
}
}
//--- Sell breakout signal (price breaks below Asian low - breakout pips)
else if(bid < asianLow - breakoutPipsValue)
{
double sl = bid + slPips;
double tp = bid - tpPips;
int ticket = OrderSend(Symbol(), OP_SELL, lotToUse, bid, 3, sl, tp, "Gold Thunder Sell", MagicNumber, 0, clrNONE);
if(ticket > 0)
{
recoveryActive = (recoveryStep > 0);
lastEntryPrice = bid;
lastOrderType = OP_SELL;
originalSL = sl;
originalTP = tp;
}
}
}
//+------------------------------------------------------------------+
//| Manage trailing stop for open positions |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double profitPips = 0;
double currentSL = OrderStopLoss();
if(OrderType() == OP_BUY)
{
profitPips = (Bid - OrderOpenPrice()) / Point;
if(profitPips >= TrailingStartPips)
{
double newSL = Bid - TrailingStepPips Point;
if(newSL > currentSL)
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
Print("Trailing stop updated for BUY #", OrderTicket());
}
}
}
else if(OrderType() == OP_SELL)
{
profitPips = (OrderOpenPrice() - Ask) / Point;
if(profitPips >= TrailingStartPips)
{
double newSL = Ask + TrailingStepPips * Point;
if(newSL < currentSL || currentSL == 0)
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
Print("Trailing stop updated for SELL #", OrderTicket());
}
}
}
break;
}
}
}
}
//+------------------------------------------------------------------+
//| Check and execute recovery (called on order close) |
//+------------------------------------------------------------------+
void CheckRecovery(double closePrice, int orderType, double orderLots)
{
if(!recoveryActive && recoveryStep == 0)
{
// First trade closed? We need to check if it was a loss
// This function should be called from a custom order close detection
// For simplicity, recovery is triggered via global flag in main logic
}
}
//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+
//| Count closed orders today for recovery tracking |
//+------------------------------------------------------------------+
int CountClosedToday()
{
int count = 0;
datetime todayStart = iTime(Symbol(), PERIOD_D1, 0);
for(int i = OrdersHistoryTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderCloseTime() >= todayStart)
count++;
}
}
return count;
}
//+------------------------------------------------------------------+
``Reference: Original MQL4 code for educational purposes.
Disclaimer: High-profit strategies often involve higher risk. This EA uses a recovery mechanism that can lead to significant losses in trending markets. This EA is provided as-is without any guarantee of profit. Test thoroughly on demo before live trading. Past performance does not guarantee future results.