Summary: Gold Thunder EA is a high-profit MQL4 expert advisor for XAUUSD. It uses Asian session breakout, dynamic lot recovery, and trailing stop. Suitable for M15 timeframe.




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:
  • Asian Range Calculation (00:00-06:00 server time): Record high and low of the range.

  • Breakout Entry: When price breaks the Asian high by BreakoutPips (buy) or low (sell) between 07:00-17:00 GMT.

  • Recovery Mode: If first trade hits stop loss, second trade opens at double lot size in same direction, with wider stop.

  • Risk Control: Maximum 2 recovery steps, equity drawdown limit 15%, trailing stop activates after 300 points profit.


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