Summary: Golden Horizon EA is a stable MQL4 expert advisor for XAUUSD. It uses dual EMA crossover with RSI filter and ATR volatility protection. Suitable for H1 timeframe.




Golden Horizon EA is specifically designed for gold (XAUUSD) with a stable operational approach, respecting gold's tendency for strong trends and sudden reversals. The EA employs a dual EMA crossover system (fast 20, slow 50) combined with RSI(14) confirmation to filter false signals. ATR(14) acts as a volatility gate, preventing entries during extreme market noise. Each trade carries a fixed stop loss and a trailing stop that locks in profits as the trend extends. The EA also includes a daily loss limit and maximum spread control.

Recommended Timeframe: H1
Trading Logic:
  • Trend Detection: Fast EMA20 crosses above Slow EMA50 → potential uptrend; opposite for downtrend.

  • Signal Confirmation: RSI(14) must be above 50 (uptrend) or below 50 (downtrend) to align with trend.

  • Volatility Gate: ATR(14) must be below the ATR threshold (ATR < ATRMaxLimit × 200-point reference) to avoid erratic moves.

  • Exit Strategy: Fixed take profit (600 points) or trailing stop activation after 300-point profit (trailing step 200 points).


  • ``mql4
    //+------------------------------------------------------------------+
    //| GoldenHorizonEA.mq4 |
    //+------------------------------------------------------------------+
    #property copyright ""
    #property link ""
    #property version "1.00"
    #property strict

    //--- input parameters with comments
    input double LotSize = 0.01; // Fixed lot size (0.01 lot for gold)
    input int FastMAPeriod = 20; // Fast moving average period (EMA)
    input int SlowMAPeriod = 50; // Slow moving average period (EMA)
    input int RSIPeriod = 14; // RSI period for confirmation
    input int ATRPeriod = 14; // ATR period for volatility filter
    input double ATRMaxLimit = 1.2; // Maximum ATR multiplier (ATR > ATRMaxLimit200 points = no trade)
    input int StopLossPoints = 300; // Fixed stop loss in points (300 points)
    input int TakeProfitPoints = 600; // Fixed take profit in points (2:1 risk-reward)
    input int TrailingStart = 300; // Points profit needed to start trailing
    input int TrailingStep = 200; // Trailing stop distance in points
    input int MagicNumber = 202415; // Unique EA identifier
    input int MaxSpread = 35; // Maximum allowed spread (in points)
    input double DailyLossLimit = 5.0; // Daily loss limit in percentage of balance
    input bool UseFridayClose = true; // Close all trades before Friday 20:00 GMT

    //--- global variables
    double dailyStartBalance = 0;
    datetime lastBarTime = 0;
    bool fridayCloseExecuted = false;

    //+------------------------------------------------------------------+
    //| Expert initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    dailyStartBalance = AccountBalance();
    lastBarTime = 0;
    fridayCloseExecuted = false;
    return(INIT_SUCCEEDED);
    }

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

    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    // Daily equity protection
    double currentEquity = AccountEquity();
    double lossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance
    100;
    if(lossPercent >= DailyLossLimit)
    {
    Comment("Daily loss limit reached. No new trades.");
    return;
    }

    // Friday close before weekend (20:00 GMT)
    if(UseFridayClose && !fridayCloseExecuted)
    {
    datetime currentTime = TimeCurrent();
    int hourGMT = TimeHour(currentTime);
    if(TimeDayOfWeek(currentTime) == 5 && hourGMT >= 20)
    {
    CloseAllOrders();
    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];

    // Check for existing position
    int positions = CountPositions();
    if(positions > 0)
    {
    ManageTrailingStop();
    return;
    }

    // Get indicator values on previous closed bar
    double fastEMA = iMA(Symbol(), PERIOD_H1, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
    double slowEMA = iMA(Symbol(), PERIOD_H1, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
    double rsi = iRSI(Symbol(), PERIOD_H1, RSIPeriod, PRICE_CLOSE, 1);
    double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);

    // Volatility filter
    double atrThreshold = ATRMaxLimit 200; // 200 points reference for gold
    if(atr > atrThreshold)
    {
    Comment("Volatility too high. ATR: ", atr);
    return;
    }

    int cmd = -1;
    double sl = 0, tp = 0;

    // Bullish condition: EMA crossover + RSI > 50
    if(fastEMA > slowEMA && rsi > 50)
    {
    // Confirm crossover occurred on previous bar
    double fastEMA_prev = iMA(Symbol(), PERIOD_H1, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 2);
    double slowEMA_prev = iMA(Symbol(), PERIOD_H1, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 2);

    if(fastEMA_prev <= slowEMA_prev)
    {
    cmd = OP_BUY;
    sl = SymbolInfoDouble(Symbol(), SYMBOL_BID) - StopLossPoints
    Point;
    tp = SymbolInfoDouble(Symbol(), SYMBOL_BID) + TakeProfitPoints Point;
    }
    }
    // Bearish condition: EMA crossover + RSI < 50
    else if(fastEMA < slowEMA && rsi < 50)
    {
    double fastEMA_prev = iMA(Symbol(), PERIOD_H1, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 2);
    double slowEMA_prev = iMA(Symbol(), PERIOD_H1, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 2);

    if(fastEMA_prev >= slowEMA_prev)
    {
    cmd = OP_SELL;
    sl = SymbolInfoDouble(Symbol(), SYMBOL_ASK) + StopLossPoints
    Point;
    tp = SymbolInfoDouble(Symbol(), SYMBOL_ASK) - TakeProfitPoints Point;
    }
    }

    if(cmd != -1)
    {
    double price = (cmd == OP_BUY) ? Ask : Bid;
    int ticket = OrderSend(Symbol(), cmd, LotSize, price, 3, sl, tp, "Golden Horizon", MagicNumber, 0, clrNONE);
    if(ticket < 0)
    Print("OrderSend failed: ", GetLastError());
    }
    }

    //+------------------------------------------------------------------+
    //| 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 newSL = 0;
    double currentStopLoss = OrderStopLoss();

    if(OrderType() == OP_BUY)
    {
    double profitPoints = (Bid - OrderOpenPrice()) / Point;
    if(profitPoints >= TrailingStart)
    {
    newSL = Bid - TrailingStep
    Point;
    if(newSL > currentStopLoss)
    {
    if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
    Print("Trailing stop updated for BUY #", OrderTicket());
    }
    }
    }
    else if(OrderType() == OP_SELL)
    {
    double profitPoints = (OrderOpenPrice() - Ask) / Point;
    if(profitPoints >= TrailingStart)
    {
    newSL = Ask + TrailingStep * Point;
    if(newSL < currentStopLoss || currentStopLoss == 0)
    {
    if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
    Print("Trailing stop updated for SELL #", OrderTicket());
    }
    }
    }
    break;
    }
    }
    }
    }

    //+------------------------------------------------------------------+
    //| 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: Forex and gold trading involve substantial risk of loss. This EA is provided as-is without any guarantee of profit. Always test on a demo account before live deployment. Past performance does not guarantee future results.