Complete .mq5 source code

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.

Historical test results

60.2%
Win Rate
13.7%
Max Drawdown
1.41
Sharpe Ratio
2021–2025
Test Period

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, save it in the MQL5/Experts folder, and compile with F7.

Generate a custom GBPUSD scalping EA

Describe the ATR inputs, alert rules, visual style, or confirmation filter 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 accessVia TradingView broker 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. Read the Pine Script Supertrend reference before porting logic between them.

Frequently Asked Questions

Related MQL5 pages

Risk and testing note

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.