GBPUSD Expert Advisor MT5: MQL5 EA Code, Settings & Backtest
This page provides a complete MQL5 Expert Advisor for scalping the GBPUSD currency pair on MetaTrader 5, including full source code, optimized input parameters, and a verified backtest covering 2021–2025. GBPUSD is one of the most liquid forex pairs during London and New York session overlaps, making it ideal for short-term scalping strategies that capture frequent small moves with tight risk control.
Backtest Performance
Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.
Strategy Logic
Entry Conditions
The EA enters long positions when a fast EMA (9-period) crosses above a slow EMA (21-period) on the M15 timeframe, confirmed by RSI rising above 50 and price trading above the 50-period SMA acting as a trend filter. Short entries are triggered on the inverse crossover when RSI falls below 50, ensuring trades align with short-term momentum. An ATR-based spread filter prevents entries during abnormally wide spreads common during off-hours or news events.
Exit Conditions
Each trade uses a fixed risk-reward structure with a stop loss set at 1.5x the 14-period ATR below (long) or above (short) the entry candle, protecting capital during sudden GBP volatility spikes. The take profit target is set at 2.0x ATR from entry, targeting a minimum 1:1.33 reward-to-risk ratio per trade. A trailing stop activates once price moves 1x ATR in the trade direction, locking in partial gains and allowing profitable trades to extend during strong momentum.
MQL5 Expert Advisor Code
//+------------------------------------------------------------------+
//| GBPUSD Scalping Expert Advisor for MetaTrader 5 |
//| Strategy: EMA Crossover + RSI Filter + ATR Risk Management |
//| Timeframe: M15 | Symbol: GBPUSD |
//| DISCLAIMER: For educational purposes only. Past backtest |
//| results do not guarantee future performance. Trade at your |
//| own risk. Always test thoroughly before live deployment. |
//+------------------------------------------------------------------+
#property copyright "Pineify MQL5 Example"
#property version "1.00"
#property strict
//--- Input parameters
input int FastEMA_Period = 9; // Fast EMA period
input int SlowEMA_Period = 21; // Slow EMA period
input int TrendSMA_Period = 50; // Trend SMA period
input int RSI_Period = 14; // RSI period
input int ATR_Period = 14; // ATR period
input double RiskPercent = 1.0; // Risk per trade (% of balance)
input double SL_ATR_Mult = 1.5; // Stop loss ATR multiplier
input double TP_ATR_Mult = 2.0; // Take profit ATR multiplier
input double Trail_ATR_Mult = 1.0; // Trailing stop ATR multiplier
input double MaxSpreadPoints = 20.0; // Max allowed spread (points)
input int MagicNumber = 202201; // EA magic number
input string TradeComment = "GBPUSD_Scalp"; // Trade comment
//--- Global handles
int hFastEMA = INVALID_HANDLE;
int hSlowEMA = INVALID_HANDLE;
int hTrendSMA = INVALID_HANDLE;
int hRSI = INVALID_HANDLE;
int hATR = INVALID_HANDLE;
//--- Trade object
#include <Trade\Trade.mqh>
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Validate symbol
if(Symbol() != "GBPUSD" && Symbol() != "GBPUSDm")
Print("Warning: EA optimized for GBPUSD but running on ", Symbol());
//--- Create indicator handles
hFastEMA = iMA(_Symbol, PERIOD_M15, FastEMA_Period, 0, MODE_EMA, PRICE_CLOSE);
hSlowEMA = iMA(_Symbol, PERIOD_M15, SlowEMA_Period, 0, MODE_EMA, PRICE_CLOSE);
hTrendSMA = iMA(_Symbol, PERIOD_M15, TrendSMA_Period, 0, MODE_SMA, PRICE_CLOSE);
hRSI = iRSI(_Symbol, PERIOD_M15, RSI_Period, PRICE_CLOSE);
hATR = iATR(_Symbol, PERIOD_M15, ATR_Period);
if(hFastEMA == INVALID_HANDLE || hSlowEMA == INVALID_HANDLE ||
hTrendSMA == INVALID_HANDLE || hRSI == INVALID_HANDLE || hATR == INVALID_HANDLE)
{
Print("Error: Failed to create indicator handles. Error code: ", GetLastError());
return(INIT_FAILED);
}
//--- Configure trade object
trade.SetExpertMagicNumber(MagicNumber);
trade.SetDeviationInPoints(10);
trade.SetTypeFilling(ORDER_FILLING_IOC);
Print("GBPUSD Scalping EA initialized successfully.");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Release indicator handles
if(hFastEMA != INVALID_HANDLE) IndicatorRelease(hFastEMA);
if(hSlowEMA != INVALID_HANDLE) IndicatorRelease(hSlowEMA);
if(hTrendSMA != INVALID_HANDLE) IndicatorRelease(hTrendSMA);
if(hRSI != INVALID_HANDLE) IndicatorRelease(hRSI);
if(hATR != INVALID_HANDLE) IndicatorRelease(hATR);
Print("GBPUSD Scalping EA deinitialized. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Only process on new M15 bar
static datetime lastBarTime = 0;
datetime currentBarTime = iTime(_Symbol, PERIOD_M15, 0);
if(currentBarTime == lastBarTime) return;
lastBarTime = currentBarTime;
//--- Check spread filter
double spreadPoints = (double)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spreadPoints > MaxSpreadPoints)
{
Print("Spread too wide: ", spreadPoints, " points. Skipping.");
return;
}
//--- Fetch indicator buffers (index 1 = previous closed bar)
double fastEMA_curr[2], slowEMA_curr[2], trendSMA[2], rsi[2], atr[2];
if(CopyBuffer(hFastEMA, 0, 0, 2, fastEMA_curr) < 2) return;
if(CopyBuffer(hSlowEMA, 0, 0, 2, slowEMA_curr) < 2) return;
if(CopyBuffer(hTrendSMA, 0, 0, 2, trendSMA) < 2) return;
if(CopyBuffer(hRSI, 0, 0, 2, rsi) < 2) return;
if(CopyBuffer(hATR, 0, 0, 2, atr) < 2) return;
double fastPrev = fastEMA_curr[0];
double slowPrev = slowEMA_curr[0];
double fastCurr = fastEMA_curr[1];
double slowCurr = slowEMA_curr[1];
double smaCurr = trendSMA[1];
double rsiCurr = rsi[1];
double atrCurr = atr[1];
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
//--- Manage trailing stops on open positions
ManageTrailingStop(atrCurr);
//--- Skip if position already open for this EA
if(PositionExistsForMagic()) return;
//--- Detect EMA crossover signals
bool bullishCross = (fastPrev <= slowPrev) && (fastCurr > slowCurr);
bool bearishCross = (fastPrev >= slowPrev) && (fastCurr < slowCurr);
//--- Long entry conditions
if(bullishCross && rsiCurr > 50 && ask > smaCurr)
{
double sl = NormalizeDouble(ask - SL_ATR_Mult * atrCurr, _Digits);
double tp = NormalizeDouble(ask + TP_ATR_Mult * atrCurr, _Digits);
double lots = CalculateLotSize(ask - sl);
if(lots > 0)
{
trade.Buy(lots, _Symbol, ask, sl, tp, TradeComment);
Print("BUY order placed | Lots: ", lots, " | SL: ", sl, " | TP: ", tp);
}
}
//--- Short entry conditions
if(bearishCross && rsiCurr < 50 && bid < smaCurr)
{
double sl = NormalizeDouble(bid + SL_ATR_Mult * atrCurr, _Digits);
double tp = NormalizeDouble(bid - TP_ATR_Mult * atrCurr, _Digits);
double lots = CalculateLotSize(sl - bid);
if(lots > 0)
{
trade.Sell(lots, _Symbol, bid, sl, tp, TradeComment);
Print("SELL order placed | Lots: ", lots, " | SL: ", sl, " | TP: ", tp);
}
}
}
//+------------------------------------------------------------------+
//| Calculate lot size based on risk percentage |
//+------------------------------------------------------------------+
double CalculateLotSize(double slDistance)
{
if(slDistance <= 0) return 0;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double riskAmount = balance * RiskPercent / 100.0;
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
if(tickSize == 0 || tickValue == 0) return minLot;
double slTicks = slDistance / tickSize;
double lots = riskAmount / (slTicks * tickValue);
lots = MathFloor(lots / lotStep) * lotStep;
lots = MathMax(minLot, MathMin(maxLot, lots));
return NormalizeDouble(lots, 2);
}
//+------------------------------------------------------------------+
//| Manage trailing stop for open positions |
//+------------------------------------------------------------------+
void ManageTrailingStop(double atrValue)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(!PositionSelectByTicket(PositionGetTicket(i))) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
double trailDist = Trail_ATR_Mult * atrValue;
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
long posType = PositionGetInteger(POSITION_TYPE);
if(posType == POSITION_TYPE_BUY)
{
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double newSL = NormalizeDouble(bid - trailDist, _Digits);
double minProfit = NormalizeDouble(openPrice + trailDist, _Digits);
if(bid >= minProfit && newSL > currentSL)
trade.PositionModify(PositionGetTicket(i), newSL, PositionGetDouble(POSITION_TP));
}
else if(posType == POSITION_TYPE_SELL)
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double newSL = NormalizeDouble(ask + trailDist, _Digits);
double minProfit = NormalizeDouble(openPrice - trailDist, _Digits);
if(ask <= minProfit && (currentSL == 0 || newSL < currentSL))
trade.PositionModify(PositionGetTicket(i), newSL, PositionGetDouble(POSITION_TP));
}
}
}
//+------------------------------------------------------------------+
//| Check if a position exists for this EA's magic number |
//+------------------------------------------------------------------+
bool PositionExistsForMagic()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(!PositionSelectByTicket(PositionGetTicket(i))) continue;
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber &&
PositionGetString(POSITION_SYMBOL) == _Symbol)
return true;
}
return false;
}
//+------------------------------------------------------------------+Copy this code into MetaEditor (F4 in MT5), save in the Experts folder, and compile with F7.
Generate a Custom GBPUSD Scalping EA →
Pineify AI generates syntactically validated MQL5 Expert Advisors from plain English descriptions. Customize entry logic, risk management, and trading sessions — no coding required.
Pine Script vs MQL5: Same Strategy, Different Platforms
| Aspect | Pine Script (TradingView) | MQL5 (MetaTrader 5) |
|---|---|---|
| Execution | Bar-based, backtesting only | Tick-based, live trading |
| Deployment | TradingView alerts | Runs 24/5 on VPS/MT5 |
| Broker access | Via TradingView broker integration | Direct broker connectivity |
| Backtesting | Built-in, no data download needed | Strategy Tester, tick data required |
| Code complexity | Simpler, functional syntax | C++-like, more powerful |
Pineify supports both platforms. Prototype your strategy visually in TradingView Pine Script, then generate the equivalent MQL5 EA for live MT5 trading.