Summary: Gold Trend Grid EA is an MQL4 expert advisor for XAUUSD that integrates trend filtering with a controlled grid recovery system. Grid only expands in trend direction. Suitable for H1.




Gold Trend Grid EA uniquely combines trend following with a disciplined grid approach. Unlike traditional grid EAs that trade both directions, this EA first determines the major trend using EMA(50) and ADX(14). Once the trend is established, it opens a base position and sets a grid of pending orders only in the trend direction. Grid spacing and lot progression are dynamically adjusted based on ATR volatility. The EA includes maximum grid levels, equity-based drawdown protection, and a take-profit target that scales with grid size.

Recommended Timeframe: H1
Trading Logic:
  • Trend Detection: EMA(50) slope + price position. ADX > 25 confirms trending market.

  • Base Entry: After trend confirmation, enter at market with 0.01 lot.

  • Trend Grid Placement: Place buy limit orders above current price (uptrend) or sell limit below (downtrend) at ATR-based spacing.

  • Grid Progression: Each level increases lot size by GridLotMultiplier (e.g., 1.5x). Maximum 5 levels.

  • Grid Exit: Close entire grid when total floating profit reaches TargetProfitPoints or breakeven after 3 levels.


  • ``mql4
    //+------------------------------------------------------------------+
    //| GoldTrendGridEA.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 int TrendEMAPeriod = 50; // EMA period for trend direction
    input int ADXPeriod = 14; // ADX period for trend strength
    input int ADXThreshold = 25; // Minimum ADX value for trend market
    input double GridSpacingATR = 1.5; // Grid spacing as multiple of ATR
    input double GridLotMultiplier = 1.5; // Lot multiplier for each grid level (1.5x)
    input int MaxGridLevels = 5; // Maximum number of grid levels
    input int TargetProfitPoints = 800; // Target profit in points for grid exit
    input double EquityDrawdownLimit = 12.0; // Max equity drawdown percentage to stop
    input int MagicNumber = 202418; // Unique EA identifier
    input int MaxSpread = 35; // Maximum allowed spread in points
    input bool UseFridayClose = true; // Close grid before Friday 20:00 GMT

    //--- global variables
    datetime lastBarTime = 0;
    bool fridayCloseExecuted = false;
    double currentTrend = 0; // 1 = bullish, -1 = bearish, 0 = no trend
    double lastATR = 0;
    double gridStartPrice = 0;
    int currentGridLevel = 0;
    double equityStart = 0;

    //+------------------------------------------------------------------+
    //| Expert initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    lastBarTime = 0;
    fridayCloseExecuted = false;
    equityStart = AccountEquity();
    currentTrend = 0;
    currentGridLevel = 0;
    return(INIT_SUCCEEDED);
    }

    //+------------------------------------------------------------------+
    //| Expert deinitialization function |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
    Comment("");
    }

    //+------------------------------------------------------------------+
    //| Determine trend direction |
    //+------------------------------------------------------------------+
    int GetTrend()
    {
    double ema = iMA(Symbol(), PERIOD_H1, TrendEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
    double close1 = iClose(Symbol(), PERIOD_H1, 1);
    double adx = iADX(Symbol(), PERIOD_H1, ADXPeriod, PRICE_CLOSE, MODE_MAIN, 1);
    double diPlus = iADX(Symbol(), PERIOD_H1, ADXPeriod, PRICE_CLOSE, MODE_PLUSDI, 1);
    double diMinus = iADX(Symbol(), PERIOD_H1, ADXPeriod, PRICE_CLOSE, MODE_MINUSDI, 1);

    if(adx < ADXThreshold) return 0;

    // Bullish: price above EMA and DI+ > DI-
    if(close1 > ema && diPlus > diMinus)
    return 1;
    // Bearish: price below EMA and DI- > DI+
    else if(close1 < ema && diMinus > diPlus)
    return -1;

    return 0;
    }

    //+------------------------------------------------------------------+
    //| Calculate dynamic grid spacing based on ATR |
    //+------------------------------------------------------------------+
    double GetGridSpacing()
    {
    double atr = iATR(Symbol(), PERIOD_H1, 14, 1);
    if(atr <= 0) atr = 200 Point;
    lastATR = atr;
    return atr
    GridSpacingATR;
    }

    //+------------------------------------------------------------------+
    //| Get current grid order count |
    //+------------------------------------------------------------------+
    int CountGridOrders()
    {
    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++;
    }
    }
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_PENDING))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    count++;
    }
    }
    return count;
    }

    //+------------------------------------------------------------------+
    //| Close all grid orders (market and pending) |
    //+------------------------------------------------------------------+
    void CloseAllGridOrders()
    {
    // Close market orders
    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);
    }
    }
    }
    // Delete pending orders
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_PENDING))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    OrderDelete(OrderTicket());
    }
    }
    }

    //+------------------------------------------------------------------+
    //| Calculate total floating profit of grid |
    //+------------------------------------------------------------------+
    double GetGridFloatingProfit()
    {
    double profit = 0;
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    profit += OrderProfit() + OrderSwap() + OrderCommission();
    }
    }
    return profit;
    }

    //+------------------------------------------------------------------+
    //| Create pending grid orders in trend direction |
    //+------------------------------------------------------------------+
    void CreateGridOrders()
    {
    if(currentTrend == 0) return;

    double spacing = GetGridSpacing();
    double currentPrice = (currentTrend == 1) ? Ask : Bid;
    double lot = BaseLotSize;

    for(int level = 1; level <= MaxGridLevels; level++)
    {
    double orderPrice;
    if(currentTrend == 1) // Bullish: buy limit above current price
    orderPrice = currentPrice + (spacing level);
    else // Bearish: sell limit below current price
    orderPrice = currentPrice - (spacing
    level);

    double lotSize = BaseLotSize MathPow(GridLotMultiplier, level - 1);
    if(lotSize > 1.0) lotSize = 1.0;

    int cmd = (currentTrend == 1) ? OP_BUYLIMIT : OP_SELLLIMIT;

    int ticket = OrderSend(Symbol(), cmd, lotSize, orderPrice, 3, 0, 0, "Trend Grid", MagicNumber, 0, clrNONE);
    if(ticket < 0)
    Print("Failed to create grid order level ", level, " error: ", GetLastError());
    else
    Print("Grid level ", level, " created at ", orderPrice);
    }
    }

    //+------------------------------------------------------------------+
    //| Check if grid should be closed based on profit target |
    //+------------------------------------------------------------------+
    bool ShouldCloseGrid()
    {
    double profit = GetGridFloatingProfit();
    double targetProfit = TargetProfitPoints
    Point (CountGridOrders() BaseLotSize 10); // rough estimate
    if(profit >= targetProfit)
    return true;

    // Emergency close if drawdown too high
    double equityDrawdown = (equityStart - AccountEquity()) / equityStart
    100;
    if(equityDrawdown >= EquityDrawdownLimit)
    return true;

    return false;
    }

    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    // Friday close protection
    if(UseFridayClose && !fridayCloseExecuted)
    {
    datetime currentTime = TimeCurrent();
    if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 20)
    {
    CloseAllGridOrders();
    fridayCloseExecuted = true;
    return;
    }
    if(TimeDayOfWeek(currentTime) != 5)
    fridayCloseExecuted = false;
    }

    // Spread filter
    if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
    {
    Comment("Spread too high: ", MarketInfo(Symbol(), MODE_SPREAD));
    return;
    }

    // New bar logic (H1)
    if(Time[0] == lastBarTime)
    return;
    lastBarTime = Time[0];

    // Update equity start daily
    if(TimeDayOfYear(TimeCurrent()) != TimeDayOfYear(TimeCurrent() - 86400))
    equityStart = AccountEquity();

    // Check if grid should close
    if(CountGridOrders() > 0 && ShouldCloseGrid())
    {
    CloseAllGridOrders();
    currentGridLevel = 0;
    Comment("Grid closed by profit target or drawdown limit");
    return;
    }

    // Determine trend
    int newTrend = GetTrend();
    currentTrend = newTrend;

    // If no existing grid and trend is valid, start new grid
    if(CountGridOrders() == 0 && currentTrend != 0)
    {
    // Open base market position
    double lot = BaseLotSize;
    double sl = 0, tp = 0;
    int cmd = (currentTrend == 1) ? OP_BUY : OP_SELL;
    double price = (cmd == OP_BUY) ? Ask : Bid;

    int ticket = OrderSend(Symbol(), cmd, lot, price, 3, sl, tp, "Base Grid", MagicNumber, 0, clrNONE);
    if(ticket > 0)
    {
    Print("Base position opened in trend direction");
    CreateGridOrders();
    }
    }
    else if(CountGridOrders() > 0 && currentTrend == 0)
    {
    // Trend weakened, close grid
    CloseAllGridOrders();
    Comment("Trend weakened, grid closed");
    }

    // Update comment with status
    double profit = GetGridFloatingProfit();
    Comment("Trend: ", currentTrend==1?"BULLISH":(currentTrend==-1?"BEARISH":"NEUTRAL"),
    " | Grid Orders: ", CountGridOrders(),
    " | Floating: ", DoubleToStr(profit, 2),
    " | ATR: ", DoubleToStr(lastATR/Point, 1));
    }

    //+------------------------------------------------------------------+
    //| Expert tick function end |
    //+------------------------------------------------------------------+
    ``
    Reference: Original MQL4 code for educational purposes.
    Disclaimer: Grid trading carries risk of significant drawdown in strong trending or ranging markets. This EA is provided as-is without any guarantee of profit. Test thoroughly on a demo account for at least 3 months before live deployment. Past performance does not guarantee future results.