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:
1. Trend Detection: Fast EMA20 crosses above Slow EMA50 → potential uptrend; opposite for downtrend.
2. Signal Confirmation: RSI(14) must be above 50 (uptrend) or below 50 (downtrend) to align with trend.
3. Volatility Gate: ATR(14) must be below the ATR threshold (ATR < ATRMaxLimit × 200-point reference) to avoid erratic moves.
4. 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 > ATRMaxLimit*200 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.