Complete .mq5 source code

Gold SMC EA MT5: Smart Money Concept Expert Advisor for XAUUSD

Examine an educational XAUUSD EA that defines a candle-based order-block heuristic, a completed-bar sweep condition and an H4 EMA filter. These chart patterns do not identify institutional orders or prove market-maker intent. The source has no verified backtest, and its broker execution and risk assumptions need separate testing.

Strategy logic

Entry conditions

On each new H1 bar, compare the completed H1 close with the last completed H4 EMA 200. A bullish zone is the nearest bearish candle within three bars before a bullish impulse whose body exceeds 1.5 times its H1 ATR; bearish zones reverse this definition. The most recent completed H1 bar must sweep and close back beyond the preceding 20-bar extreme. At evaluation time, ask for a buy or bid for a sell must be inside the zone. This uses a live quote, not a guaranteed next-open fill or a required close inside the zone. No break-of-structure or institutional-order detector is implemented.

Exit conditions

Request a stop five broker points beyond the zone edge and a target at 1.8 times the quoted entry-to-stop distance. The target is arithmetic, not a detected liquidity pool. On subsequent ticks, if price reaches the current entry-to-stop distance in favor, request a stop one point beyond entry. That adjustment does not cover costs or guarantee no loss. Fixed lots, IOC filling, stop/tick grids and netting ownership require broker-specific checks; no maximum account loss or news filter is included.

MQL5 Expert Advisor Code

//+------------------------------------------------------------------+
//|  Gold SMC EA — Smart Money Concept Expert Advisor for XAUUSD     |
//|  Platform : MetaTrader 5 (MQL5 5.x)                              |
//|  Symbol   : XAUUSD  |  Timeframe: H1                             |
//|  Educational price-pattern example; no verified backtest record. |
//+------------------------------------------------------------------+
#property copyright "Pineify.app"
#property version   "1.00"
#property strict

//--- Input parameters
input double InpLotSize        = 0.10;   // Fixed lot size
input int    InpOBLookback     = 5;      // Order-block lookback (bars)
input int    InpLiqLookback    = 20;     // Liquidity sweep lookback (bars)
input double InpRR             = 1.8;    // Take-profit R:R multiplier
input int    InpH4EMAPeriod    = 200;    // H4 trend EMA period
input int    InpMagicNumber    = 202501; // EA magic number
input double InpSlippage       = 3.0;   // Max slippage in points

//--- Global handles & state
int      g_h4EmaHandle  = INVALID_HANDLE;
datetime g_lastBarTime  = 0;
int      g_atrHandle    = INVALID_HANDLE;

//+------------------------------------------------------------------+
//| Helper: get H4 200-EMA value                                     |
//+------------------------------------------------------------------+
double GetH4EMA()
  {
   double buf[];
   ArraySetAsSeries(buf, true);
   if(CopyBuffer(g_h4EmaHandle, 0, 1, 1, buf) < 1)
      return 0.0;
   return buf[0];
  }

// Candle-zone heuristic, not evidence of institutional order flow.
int FindOrderBlock(bool bullish, int lookback)
  {
   double atr[];
   ArraySetAsSeries(atr,true);
   if(CopyBuffer(g_atrHandle,0,1,lookback,atr)!=lookback) return -1;
   for(int i=1;i<=lookback;i++)
     {
      double open=iOpen(_Symbol,PERIOD_H1,i), close=iClose(_Symbol,PERIOD_H1,i);
      if(open<=0 || close<=0 || atr[i-1]<=0) continue;
      bool impulse=bullish ? close>open : close<open;
      if(!impulse || MathAbs(close-open)<=1.5*atr[i-1]) continue;
      for(int j=i+1;j<=i+3;j++)
        {
         double o=iOpen(_Symbol,PERIOD_H1,j), c=iClose(_Symbol,PERIOD_H1,j);
         if(o>0 && c>0 && (bullish ? c<o : c>o)) return j;
        }
     }
   return -1;
  }

bool LiquiditySweepDetected(bool bullish,int lookback)
  {
   // Bar 1 is compared only with older bars 2 through lookback+1.
   int idx=bullish ? iLowest(_Symbol,PERIOD_H1,MODE_LOW,lookback,2)
                   : iHighest(_Symbol,PERIOD_H1,MODE_HIGH,lookback,2);
   if(idx<0) return false;
   double level=bullish ? iLow(_Symbol,PERIOD_H1,idx) : iHigh(_Symbol,PERIOD_H1,idx);
   double lo=iLow(_Symbol,PERIOD_H1,1), hi=iHigh(_Symbol,PERIOD_H1,1);
   double cl=iClose(_Symbol,PERIOD_H1,1);
   if(level<=0 || lo<=0 || hi<=0 || cl<=0) return false;
   return bullish ? lo<level && cl>level : hi>level && cl<level;
  }

//+------------------------------------------------------------------+
//| Helper: check for open EA position                               |
//+------------------------------------------------------------------+
bool HasOpenPosition()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
         if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
            (long)PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
            return true;
     }
   return false;
  }

//+------------------------------------------------------------------+
//| Helper: apply break-even once 1.0 R reached                     |
//+------------------------------------------------------------------+
void ManageBreakEven()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(!PositionSelectByTicket(ticket)) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if((long)PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;

      double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
      double sl        = PositionGetDouble(POSITION_SL);
      double tp        = PositionGetDouble(POSITION_TP);
      double bid       = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double ask       = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

      double riskPts   = MathAbs(openPrice - sl);
      if(sl<=0 || riskPts<=0) continue;

      if(posType == POSITION_TYPE_BUY && sl < openPrice)
        {
         if(bid >= openPrice + riskPts)  // 1R profit reached
           {
            MqlTradeRequest req = {};
            MqlTradeResult  res = {};
            req.action   = TRADE_ACTION_SLTP;
            req.symbol   = _Symbol;
            req.sl       = openPrice + _Point;
            req.tp       = tp;
            req.position = ticket;
            if(!OrderSend(req,res) || res.retcode!=TRADE_RETCODE_DONE)
               PrintFormat("Break-even modification failed: %u %s",res.retcode,res.comment);
           }
        }
      else if(posType == POSITION_TYPE_SELL && sl > openPrice)
        {
         if(ask <= openPrice - riskPts)
           {
            MqlTradeRequest req = {};
            MqlTradeResult  res = {};
            req.action   = TRADE_ACTION_SLTP;
            req.symbol   = _Symbol;
            req.sl       = openPrice - _Point;
            req.tp       = tp;
            req.position = ticket;
            if(!OrderSend(req,res) || res.retcode!=TRADE_RETCODE_DONE)
               PrintFormat("Break-even modification failed: %u %s",res.retcode,res.comment);
           }
        }
     }
  }

//+------------------------------------------------------------------+
//| OnInit                                                           |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(InpLotSize<=0 || InpOBLookback<1 || InpLiqLookback<1 || InpH4EMAPeriod<1 || InpRR<=0 || InpMagicNumber<0 || InpSlippage<0)
      return INIT_PARAMETERS_INCORRECT;
   g_atrHandle=iATR(_Symbol,PERIOD_H1,14);
   g_h4EmaHandle = iMA(_Symbol, PERIOD_H4, InpH4EMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
   if(g_h4EmaHandle == INVALID_HANDLE || g_atrHandle==INVALID_HANDLE)
     {
      Print("Failed to create H4 EMA handle");
      return INIT_FAILED;
     }
   Print("Gold SMC EA initialised. Magic=", InpMagicNumber);
   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| OnTick                                                           |
//+------------------------------------------------------------------+
void OnTick()
  {
   ManageBreakEven();
   // Run entry logic once per new H1 bar after data is available
   datetime currentBarTime = iTime(_Symbol, PERIOD_H1, 0);
   if(currentBarTime<=0 || currentBarTime==g_lastBarTime) return;
   if(Bars(_Symbol,PERIOD_H1)<MathMax(InpOBLookback+4,InpLiqLookback+2) ||
      BarsCalculated(g_atrHandle)<InpOBLookback+1) return;

   double h4Ema  = GetH4EMA();
   double h1Close = iClose(_Symbol, PERIOD_H1, 1);
   if(h4Ema<=0 || h1Close<=0) return;
   g_lastBarTime=currentBarTime;
   if(HasOpenPosition()) return;

   bool bullTrend = h1Close > h4Ema;
   bool bearTrend = h1Close < h4Ema;

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double pt  = _Point;

   //--- Bullish SMC setup
   if(bullTrend)
     {
      int obIdx = FindOrderBlock(true,InpOBLookback);
      if(obIdx > 0 && LiquiditySweepDetected(true, InpLiqLookback))
        {
         double obHigh = iHigh(_Symbol, PERIOD_H1, obIdx);
         double obLow  = iLow(_Symbol,  PERIOD_H1, obIdx);
         // Price must be retracing into OB zone
         if(ask >= obLow && ask <= obHigh)
           {
            double sl = obLow - 5 * pt;
            double tp = ask + InpRR * (ask - sl);

            MqlTradeRequest req = {};
            MqlTradeResult  res = {};
            req.action    = TRADE_ACTION_DEAL;
            req.symbol    = _Symbol;
            req.volume    = InpLotSize;
            req.type      = ORDER_TYPE_BUY;
            req.price     = ask;
            req.sl        = NormalizeDouble(sl,_Digits);
            req.tp        = NormalizeDouble(tp,_Digits);
            req.magic     = InpMagicNumber;
            req.deviation = (ulong)InpSlippage;
            req.comment   = "GoldSMC_BUY";
            req.type_filling = ORDER_FILLING_IOC;
            if(!OrderSend(req,res) || (res.retcode!=TRADE_RETCODE_DONE && res.retcode!=TRADE_RETCODE_DONE_PARTIAL))
               Print("BUY order failed: ", GetLastError(), " retcode=", res.retcode);
           }
        }
     }

   //--- Bearish SMC setup
   if(bearTrend)
     {
      int obIdx = FindOrderBlock(false,InpOBLookback);
      if(obIdx > 0 && LiquiditySweepDetected(false, InpLiqLookback))
        {
         double obHigh = iHigh(_Symbol, PERIOD_H1, obIdx);
         double obLow  = iLow(_Symbol,  PERIOD_H1, obIdx);
         if(bid >= obLow && bid <= obHigh)
           {
            double sl = obHigh + 5 * pt;
            double tp = bid - InpRR * (sl - bid);

            MqlTradeRequest req = {};
            MqlTradeResult  res = {};
            req.action    = TRADE_ACTION_DEAL;
            req.symbol    = _Symbol;
            req.volume    = InpLotSize;
            req.type      = ORDER_TYPE_SELL;
            req.price     = bid;
            req.sl        = NormalizeDouble(sl,_Digits);
            req.tp        = NormalizeDouble(tp,_Digits);
            req.magic     = InpMagicNumber;
            req.deviation = (ulong)InpSlippage;
            req.comment   = "GoldSMC_SELL";
            req.type_filling = ORDER_FILLING_IOC;
            if(!OrderSend(req,res) || (res.retcode!=TRADE_RETCODE_DONE && res.retcode!=TRADE_RETCODE_DONE_PARTIAL))
               Print("SELL order failed: ", GetLastError(), " retcode=", res.retcode);
           }
        }
     }
  }

//+------------------------------------------------------------------+
//| OnDeinit                                                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(g_h4EmaHandle != INVALID_HANDLE)
      IndicatorRelease(g_h4EmaHandle);
   if(g_atrHandle!=INVALID_HANDLE) IndicatorRelease(g_atrHandle);
   Print("Gold SMC EA removed. Reason code: ", reason);
  }
//+------------------------------------------------------------------+

Copy this code into MetaEditor, save it in the MQL5/Experts folder, and compile with F7.

Generate a custom XAUUSD SMC EA

Describe the entry, exit, position, order, and risk rules you want. Pineify generates editable MQL5 source code that you can inspect and compile in MetaEditor.

Pine Script vs MQL5: Same Strategy, Different Platforms

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionSeries evaluated on chart updatesEvent handlers with explicit buffers
DeploymentRuns in TradingView with alertsRuns in the MT5 terminal or on a VPS
Broker accessStrategy orders are simulated; live automation needs a separate integrationDirect broker connectivity
BacktestingStrategy Tester for strategy scriptsStrategy Tester for Expert Advisors
Code complexitySimpler, functional syntaxC++-like, more powerful

The calculation can be implemented on either platform, but the runtime model and buffer APIs differ.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.