GBPJPY Expert Advisor MQL5: High-Volatility Scalping Strategy
Study a GBPJPY M5 Expert Advisor using RSI threshold crossings, an EMA quote filter and ATR-based initial and trailing stops. This example provides inspectable rules and risk-sizing mechanics. No verified trade count, backtest, daily range ranking or optimal parameter study supports this page.
Strategy logic
Entry conditions
On a new M5 bar, request a buy when completed RSI 5 moves from below 30 to at least 30 and the current ask exceeds the completed EMA 20. A sell reverses this at 70 with bid below EMA. The optional weekday window is 07:00–22:00 broker-server time, not the London/New York overlap or a GMT/DST conversion. A spread cap of 30 broker points filters entries; it cannot prevent slippage or identify news events. Periods and thresholds are illustrative.
Exit conditions
Initial requested SL and TP are 1.5 and 3 times completed ATR from the entry quote. At each new M5 bar, matching positions are managed before session and spread entry filters: trailing activates at one current ATR in favor and requests a stop one ATR behind price, only tightening. There is no automatic 22:00 close, news calendar, pre-session pause or ATR-spike gate. Position size estimates a balance risk percentage and rounds down; stops, costs and fills can still exceed that estimate. Account-mode ownership and broker grids require testing.
MQL5 Expert Advisor Code
//+------------------------------------------------------------------+
//| GBPJPY Scalping Expert Advisor for MetaTrader 5 |
//| Strategy: RSI (5) Crossover + 20 EMA Trend Filter |
//| + ATR (14) Risk Management on M5 Timeframe |
//| DISCLAIMER: For educational purposes only. Past performance |
//| does not guarantee future results. Trade at your own risk. |
//+------------------------------------------------------------------+
#property copyright "Pineify MQL5 Example"
#property version "1.00"
//--- Input parameters
input int RSI_Period = 5; // RSI period
input double RSI_Overbought = 70.0; // RSI overbought threshold
input double RSI_Oversold = 30.0; // RSI oversold threshold
input int EMA_Period = 20; // EMA trend filter 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 = 3.0; // Take profit ATR multiplier
input double TrailATRMult = 1.0; // Trailing stop ATR activation
input double MaxSpreadPoints = 30.0; // Max allowed spread (points)
input bool UseSessionFilter = true; // Limit new entries to 07-22 broker hours
input int MagicNumber = 20260617; // EA magic number
input string TradeComment = "GBPJPY_Scalp"; // Trade comment
//--- Global indicator handles
int hRSI = INVALID_HANDLE;
int hEMA = INVALID_HANDLE;
int hATR = INVALID_HANDLE;
//--- Trade object
#include <Trade/Trade.mqh>
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(RSI_Period<1 || EMA_Period<1 || ATR_Period<1 || RSI_Oversold<0 || RSI_Overbought>100 ||
RSI_Oversold>=RSI_Overbought || RiskPercent<=0 || SL_ATR_Mult<=0 || TP_ATR_Mult<=0 ||
TrailATRMult<=0 || MaxSpreadPoints<0 || MagicNumber<0) return INIT_PARAMETERS_INCORRECT;
//--- Validate symbol
string sym = _Symbol;
if(StringFind(sym, "GBPJPY") < 0 && StringFind(sym, "GBP/JPY") < 0)
Print("Example labeled GBPJPY; inspect contract for ", sym);
//--- Create indicator handles
hRSI = iRSI(_Symbol, PERIOD_M5, RSI_Period, PRICE_CLOSE);
hEMA = iMA(_Symbol, PERIOD_M5, EMA_Period, 0, MODE_EMA, PRICE_CLOSE);
hATR = iATR(_Symbol, PERIOD_M5, ATR_Period);
if(hRSI == INVALID_HANDLE || hEMA == INVALID_HANDLE || hATR == INVALID_HANDLE)
{
Print("Error: Failed to create indicator handles. Code: ", GetLastError());
return INIT_FAILED;
}
//--- Configure trade object
trade.SetExpertMagicNumber(MagicNumber);
trade.SetDeviationInPoints(20);
if(!trade.SetTypeFillingBySymbol(_Symbol)) return INIT_FAILED;
Print("GBPJPY Scalping EA initialized. Magic: ", MagicNumber);
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(hRSI != INVALID_HANDLE) IndicatorRelease(hRSI);
if(hEMA != INVALID_HANDLE) IndicatorRelease(hEMA);
if(hATR != INVALID_HANDLE) IndicatorRelease(hATR);
Print("GBPJPY Scalping EA deinitialized. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| Helper: fetch a single indicator buffer value |
//+------------------------------------------------------------------+
double GetIndiValue(int handle, int shift = 0)
{
double buf[];
ArraySetAsSeries(buf, true);
if(CopyBuffer(handle, 0, shift, 1, buf) != 1) return EMPTY_VALUE;
return buf[0];
}
//+------------------------------------------------------------------+
//| Helper: count open positions for this EA's magic number |
//+------------------------------------------------------------------+
int CountPositions()
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == (long)MagicNumber)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| Helper: calculate lot size from risk percentage |
//+------------------------------------------------------------------+
double CalcLotSize(double slPoints)
{
if(slPoints <= 0) return 0;
double tickVal = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double riskAmt = balance * RiskPercent / 100.0;
double stepLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
if(tickSize<=0 || tickVal<=0 || stepLot<=0 || minLot<=0 || maxLot<minLot || riskAmt<=0) return 0;
double lots = riskAmt / ((slPoints / tickSize) * tickVal);
lots = NormalizeDouble(MathFloor(MathMin(lots,maxLot) / stepLot) * stepLot,8);
return lots>=minLot ? lots : 0;
}
//+------------------------------------------------------------------+
//| Helper: check if current server time is in active session |
//+------------------------------------------------------------------+
bool IsSessionActive()
{
if(!UseSessionFilter) return true;
MqlDateTime dt;
if(!TimeToStruct(TimeCurrent(), dt)) return false;
// Skip weekends
if(dt.day_of_week == 0 || dt.day_of_week == 6) return false;
int hour = dt.hour;
// Illustrative server-time window; no timezone or DST conversion
return (hour >= 7 && hour < 22);
}
//+------------------------------------------------------------------+
//| Helper: check spread is within acceptable range |
//+------------------------------------------------------------------+
bool IsSpreadOK()
{
double spread = (double)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
return (spread <= MaxSpreadPoints);
}
//+------------------------------------------------------------------+
//| Helper: manage trailing stop on open positions |
//+------------------------------------------------------------------+
void ManageTrailingStop(double atrValue)
{
double trailDist = TrailATRMult * atrValue;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
double currentTP = PositionGetDouble(POSITION_TP);
long posType = PositionGetInteger(POSITION_TYPE);
if(posType == POSITION_TYPE_BUY)
{
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(bid < openPrice + trailDist) continue;
double newSL = NormalizeDouble(bid - trailDist, _Digits);
if(newSL > currentSL)
if(!trade.PositionModify(ticket,newSL,currentTP) || trade.ResultRetcode()!=TRADE_RETCODE_DONE)
Print("Trailing failed: ",trade.ResultRetcode()," ",trade.ResultRetcodeDescription());
}
else if(posType == POSITION_TYPE_SELL)
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(ask > openPrice - trailDist) continue;
double newSL = NormalizeDouble(ask + trailDist, _Digits);
if(currentSL == 0.0 || newSL < currentSL)
if(!trade.PositionModify(ticket,newSL,currentTP) || trade.ResultRetcode()!=TRADE_RETCODE_DONE)
Print("Trailing failed: ",trade.ResultRetcode()," ",trade.ResultRetcodeDescription());
}
}
}
//+------------------------------------------------------------------+
//| Main tick handler |
//+------------------------------------------------------------------+
void OnTick()
{
//--- New bar detection on M5 (only process once per bar)
static datetime lastBarTime = 0;
datetime currentBarTime = iTime(_Symbol, PERIOD_M5, 0);
if(currentBarTime<=0 || currentBarTime == lastBarTime) return;
//--- Fetch indicator values from the last completed bar (shift 1)
double rsiCurr = GetIndiValue(hRSI, 1);
double rsiPrev = GetIndiValue(hRSI, 2);
double emaCurr = GetIndiValue(hEMA, 1);
double atrCurr = GetIndiValue(hATR, 1);
if(rsiCurr==EMPTY_VALUE || rsiPrev==EMPTY_VALUE || emaCurr==EMPTY_VALUE || atrCurr==EMPTY_VALUE || atrCurr<=0) return;
lastBarTime=currentBarTime;
//--- Manage trailing stops for existing positions
if(CountPositions() > 0)
{
ManageTrailingStop(atrCurr);
return; // One trade at a time for this EA
}
if(!IsSessionActive() || !IsSpreadOK()) return;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
//--- LONG entry: RSI crosses above 30 from below, price above EMA
if(rsiPrev < RSI_Oversold && rsiCurr >= RSI_Oversold && ask > emaCurr)
{
double sl = NormalizeDouble(ask - SL_ATR_Mult * atrCurr, _Digits);
double tp = NormalizeDouble(ask + TP_ATR_Mult * atrCurr, _Digits);
double lots = CalcLotSize(ask - sl);
if(lots > 0.0)
{
if(trade.Buy(lots, _Symbol, ask, sl, tp, TradeComment) &&
(trade.ResultRetcode()==TRADE_RETCODE_DONE || trade.ResultRetcode()==TRADE_RETCODE_DONE_PARTIAL))
Print("BUY placed | Lots: ", lots, " | SL: ", sl, " | TP: ", tp);
else
Print("BUY failed | Retcode: ", trade.ResultRetcode());
}
}
//--- SHORT entry: RSI crosses below 70 from above, price below EMA
if(rsiPrev > RSI_Overbought && rsiCurr <= RSI_Overbought && bid < emaCurr)
{
double sl = NormalizeDouble(bid + SL_ATR_Mult * atrCurr, _Digits);
double tp = NormalizeDouble(bid - TP_ATR_Mult * atrCurr, _Digits);
double lots = CalcLotSize(sl - bid);
if(lots > 0.0)
{
if(trade.Sell(lots, _Symbol, bid, sl, tp, TradeComment) &&
(trade.ResultRetcode()==TRADE_RETCODE_DONE || trade.ResultRetcode()==TRADE_RETCODE_DONE_PARTIAL))
Print("SELL placed | Lots: ", lots, " | SL: ", sl, " | TP: ", tp);
else
Print("SELL failed | Retcode: ", trade.ResultRetcode());
}
}
}
//+------------------------------------------------------------------+Copy this code into MetaEditor, save it in the MQL5/Experts folder, and compile with F7.
Generate a custom GBPJPY 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.
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.