EURUSD Scalping EA MT5: M5 EMA Example & Test Guide
Inspect a complete educational M5 EMA-crossover EA with broker-server-hour and spread filters. It uses fixed lots and point-based SL/TP, with no ATR filter or trailing stop. The page supplies no verified backtest or optimum settings.
Strategy logic
Entry conditions
Once per available M5 bar, compare completed bars 2 and 1 for a strict 9/21 EMA crossover. Entries require the configured server-hour window and spread limit. The example defaults to 07:00–12:00 broker time; this is not automatically London time or DST-adjusted. Position checks use the symbol and magic number; account mode still matters.
Exit conditions
The default stop and target are 100 and 150 SYMBOL_POINT units. These correspond to 10 and 15 conventional EURUSD pips only for a five-decimal quote. Outside the server-hour window, the EA attempts to close its own symbol/magic positions when ticks arrive. It does not guarantee an exact noon exit, and it has no trailing stop. IOC filling, tick grid, volume steps and stop distances require broker verification.
MQL5 Expert Advisor Code
//+------------------------------------------------------------------+
//| EURUSD Scalping EA - London Session M5 |
//| Pineify.app |
//+------------------------------------------------------------------+
#property copyright "Pineify.app"
#property version "1.00"
input int MagicNumber = 567890;
input double Lots = 0.01;
input int EMA_Fast = 9;
input int EMA_Slow = 21;
input int MaxSpread = 15; // Max spread in points
input double TP_Points = 150;
input double SL_Points = 100;
input int SessionStart = 7;
input int SessionEnd = 12;
int emaFastH=INVALID_HANDLE, emaSlowH=INVALID_HANDLE;
datetime lastSignalBar=0;
double emaFast[], emaSlow[];
int OnInit() {
if(EMA_Fast<1 || EMA_Slow<=EMA_Fast || Lots<=0 || SL_Points<=0 || TP_Points<=0 || MaxSpread<0 || SessionStart<0 || SessionEnd>24 || SessionStart>=SessionEnd) return INIT_PARAMETERS_INCORRECT;
emaFastH = iMA(_Symbol, PERIOD_M5, EMA_Fast, 0, MODE_EMA, PRICE_CLOSE);
emaSlowH = iMA(_Symbol, PERIOD_M5, EMA_Slow, 0, MODE_EMA, PRICE_CLOSE);
if(emaFastH==INVALID_HANDLE || emaSlowH==INVALID_HANDLE) return INIT_FAILED;
ArraySetAsSeries(emaFast, true); ArraySetAsSeries(emaSlow, true);
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason) {
if(emaFastH!=INVALID_HANDLE) IndicatorRelease(emaFastH);
if(emaSlowH!=INVALID_HANDLE) IndicatorRelease(emaSlowH);
}
void OnTick() {
MqlTick tick;
if (!SymbolInfoTick(_Symbol, tick)) return;
MqlDateTime dt; if(!TimeToStruct(tick.time, dt)) return;
if (dt.hour < SessionStart || dt.hour >= SessionEnd) {
CloseAllPositions(MagicNumber); return;
}
double spread = (tick.ask - tick.bid) / _Point;
if (spread > MaxSpread) return;
if (CopyBuffer(emaFastH, 0, 0, 3, emaFast) < 3) return;
if (CopyBuffer(emaSlowH, 0, 0, 3, emaSlow) < 3) return;
datetime bar=iTime(_Symbol,PERIOD_M5,0);
if(bar==0 || bar==lastSignalBar) return;
lastSignalBar=bar;
if (CountPositions(MagicNumber) > 0) return;
bool bullCross = emaFast[2] < emaSlow[2] && emaFast[1] > emaSlow[1];
bool bearCross = emaFast[2] > emaSlow[2] && emaFast[1] < emaSlow[1];
if (bullCross) OpenTrade(ORDER_TYPE_BUY, Lots, SL_Points * _Point, TP_Points * _Point, MagicNumber);
if (bearCross) OpenTrade(ORDER_TYPE_SELL, Lots, SL_Points * _Point, TP_Points * _Point, MagicNumber);
}
void CloseAllPositions(int magic) {
for (int i = PositionsTotal()-1; i >= 0; i--) {
ulong t = PositionGetTicket(i);
if (!PositionSelectByTicket(t)) continue;
if ((int)PositionGetInteger(POSITION_MAGIC) != magic || PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
MqlTradeRequest req={}; MqlTradeResult res={};
req.action=TRADE_ACTION_DEAL; req.position=t; req.symbol=_Symbol;
req.volume=PositionGetDouble(POSITION_VOLUME);
req.type=(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)?ORDER_TYPE_SELL:ORDER_TYPE_BUY;
req.price=(req.type==ORDER_TYPE_SELL)?SymbolInfoDouble(_Symbol,SYMBOL_BID):SymbolInfoDouble(_Symbol,SYMBOL_ASK);
req.type_filling=ORDER_FILLING_IOC;
if(!OrderSend(req,res) || res.retcode!=TRADE_RETCODE_DONE) Print("Close request: ",res.retcode," ",res.comment);
}
}
int CountPositions(int magic) {
int n=0;
for (int i=PositionsTotal()-1;i>=0;i--) {
ulong t=PositionGetTicket(i);
if (PositionSelectByTicket(t)&&PositionGetString(POSITION_SYMBOL)==_Symbol&&
(int)PositionGetInteger(POSITION_MAGIC)==magic) n++;
} return n;
}
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 EURUSD"; req.type_filling=ORDER_FILLING_IOC;
if(!OrderSend(req,res) || res.retcode!=TRADE_RETCODE_DONE) Print("Entry request: ",res.retcode," ",res.comment);
}Copy this code into MetaEditor, save it in the MQL5/Experts folder, and compile with F7.
Generate a custom EURUSD 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
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.