Gold Scalping EA MT5: XAUUSD M5 Code and Testing Guide
Read an educational MQL5 EA using an M5 candle-body/EMA condition, initial ATR stops and spread/session entry filters. The example has no news-calendar filter or trailing stop. Compile and test its order handling and broker-specific gold contract settings; no verified backtest results are supplied.
Strategy logic
Entry conditions
On a completed M5 candle, request a buy when its open is below EMA 20 and close is above that same completed-bar EMA; reverse for a sell. This is a candle-body test, not a comparison of two consecutive closes. Check quoted ask-minus-bid spread in broker points, separately from ATR. Session hours use broker server time, with the default 08:00–17:00 interval; they are not automatically London or New York hours. One evaluated entry attempt is allowed per M5 bar.
Exit conditions
Request initial SL at 1 ATR and TP at 1.5 ATR from the entry quote using the completed M5 ATR. The example does not trail stops, close at session end, or detect and exit before news. Existing broker-side stops remain subject to execution and gaps. Fixed lots do not keep monetary risk constant. IOC support, volume/tick grids, stops/freeze levels and account-mode exposure must be checked before use.
MQL5 Expert Advisor Code
//+------------------------------------------------------------------+
//| Gold Scalping EA - XAUUSD M5 |
//| Generated by Pineify AI | pineify.app |
//+------------------------------------------------------------------+
#property copyright "Pineify.app"
#property version "1.00"
#property strict
// Input parameters
input int MagicNumber = 123456;
input double Lots = 0.01;
input int ATR_Period = 14;
input double ATR_SL_Mult = 1.0;
input double ATR_TP_Mult = 1.5;
input int MaxSpread = 30; // Max spread in points
input int SessionStart = 8; // Hour (server time)
input int SessionEnd = 17; // Hour (server time)
int emaHandle=INVALID_HANDLE;
int atrHandle=INVALID_HANDLE;
double emaBuffer[];
double atrBuffer[];
int OnInit() {
if(MagicNumber<0 || Lots<=0 || ATR_Period<1 || ATR_SL_Mult<=0 || ATR_TP_Mult<=0 || MaxSpread<0 ||
SessionStart<0 || SessionStart>23 || SessionEnd<0 || SessionEnd>23 || SessionStart==SessionEnd)
return INIT_PARAMETERS_INCORRECT;
emaHandle = iMA(_Symbol, PERIOD_M5, 20, 0, MODE_EMA, PRICE_CLOSE);
atrHandle = iATR(_Symbol, PERIOD_M5, ATR_Period);
if (emaHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE) return INIT_FAILED;
ArraySetAsSeries(emaBuffer, true);
ArraySetAsSeries(atrBuffer, true);
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason) {
if(emaHandle!=INVALID_HANDLE) IndicatorRelease(emaHandle);
if(atrHandle!=INVALID_HANDLE) IndicatorRelease(atrHandle);
}
void OnTick() {
MqlTick tick;
if (!SymbolInfoTick(_Symbol, tick)) return;
// Session filter
MqlDateTime dt;
if(!TimeToStruct(tick.time, dt)) return;
bool inSession = SessionStart<SessionEnd ? (dt.hour>=SessionStart && dt.hour<SessionEnd)
: (dt.hour>=SessionStart || dt.hour<SessionEnd);
if(!inSession) return;
// Spread filter
double spread = (tick.ask - tick.bid) / _Point;
if (spread<0 || spread > MaxSpread) return;
static datetime lastBar=0;
datetime currentBar=iTime(_Symbol, PERIOD_M5, 0);
if(currentBar<=0 || currentBar==lastBar) return;
// Get indicator values
if (CopyBuffer(emaHandle, 0, 0, 3, emaBuffer) < 3) return;
if (CopyBuffer(atrHandle, 0, 0, 3, atrBuffer) < 3) return;
double atr = atrBuffer[1];
double ema = emaBuffer[1];
double prevClose = iClose(_Symbol, PERIOD_M5, 1);
double prevOpen = iOpen(_Symbol, PERIOD_M5, 1);
if(atr<=0 || !MathIsValidNumber(atr) || prevOpen<=0 || prevClose<=0) return;
lastBar=currentBar;
// Count open positions
int pos = CountPositions(MagicNumber);
if (pos > 0) return;
double sl = atr * ATR_SL_Mult;
double tp = atr * ATR_TP_Mult;
// Long entry: close crosses above EMA
if (prevClose > ema && prevOpen < ema) {
OpenTrade(ORDER_TYPE_BUY, Lots, sl, tp, MagicNumber);
}
// Short entry: close crosses below EMA
else if (prevClose < ema && prevOpen > ema) {
OpenTrade(ORDER_TYPE_SELL, Lots, sl, tp, MagicNumber);
}
}
int CountPositions(int magic) {
int count = 0;
for (int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket) &&
PositionGetString(POSITION_SYMBOL) == _Symbol &&
(int)PositionGetInteger(POSITION_MAGIC) == magic) count++;
}
return count;
}
void OpenTrade(ENUM_ORDER_TYPE type, double lots, double sl, double tp, int magic) {
MqlTradeRequest req = {};
MqlTradeResult res = {};
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.volume = lots;
req.type = type;
req.price = (type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
: SymbolInfoDouble(_Symbol, SYMBOL_BID);
req.sl = (type == ORDER_TYPE_BUY) ? req.price - sl : req.price + sl;
req.tp = (type == ORDER_TYPE_BUY) ? req.price + tp : req.price - tp;
req.magic = magic;
req.comment = "Pineify Gold Scalper";
req.type_filling = ORDER_FILLING_IOC;
req.sl=NormalizeDouble(req.sl,_Digits);
req.tp=NormalizeDouble(req.tp,_Digits);
if(!OrderSend(req,res) || (res.retcode!=TRADE_RETCODE_DONE && res.retcode!=TRADE_RETCODE_DONE_PARTIAL))
PrintFormat("Gold scalper request failed: %u %s",res.retcode,res.comment);
}Copy this code into MetaEditor, save it in the MQL5/Experts folder, and compile with F7.
Generate a custom XAUUSD scalping 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
| Aspect | Pine Script (TradingView) | MQL5 (MetaTrader 5) |
|---|---|---|
| Execution | Series evaluated on chart updates | Event handlers with explicit buffers |
| Deployment | Runs in TradingView with alerts | Runs in the MT5 terminal or on a VPS |
| Broker access | Strategy orders are simulated; live automation needs a separate integration | Direct broker connectivity |
| Backtesting | Strategy Tester for strategy scripts | Strategy Tester for Expert Advisors |
| Code complexity | Simpler, functional syntax | C++-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.