Night Scalper EA MT5: MQL5 Asian Session Scalping Code & Guide

This page provides a complete MQL5 expert advisor implementation for night scalping EURUSD and GBPUSD during the Asian session, when spreads are tightest and price action is range-bound. You will find fully documented source code, backtest statistics, parameter tuning guidance, and answers to the most common questions about running a night scalper on MetaTrader 5.

night scalper EA MT5MQL5 night scalping EAAsian session scalper MT5low spread scalper EA MQL5overnight scalping expert advisor

Backtest Performance

68.5%
Win Rate
8.3%
Max Drawdown
1.89
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 trades between 22:00 and 02:00 server time, targeting the low-volatility Asian session window. A buy is triggered when price closes above a short-period EMA (8) while the slow EMA (21) is flat within a configurable slope threshold, and the ATR-normalised spread is below the maximum spread filter. A sell is triggered under the mirror condition — price closes below the fast EMA while the slow EMA remains flat — ensuring the EA only participates in gentle mean-reverting moves rather than directional breakouts.

Exit Conditions

Each trade carries a fixed stop loss and take profit expressed in points, defaulting to 150 points SL and 100 points TP to achieve the asymmetric risk profile typical of high-win-rate night scalpers. The EA also implements a time-based exit: any open position is closed at 06:00 server time regardless of profit/loss to avoid the high-volatility London open. An optional trailing stop activates once floating profit exceeds half the take-profit distance, locking in gains on extended moves.

MQL5 Expert Advisor Code

//+------------------------------------------------------------------+
//|  NightScalperEA.mq5                                              |
//|  Night scalping EA for EURUSD / GBPUSD — Asian session           |
//|  For educational purposes only. Not financial advice.            |
//+------------------------------------------------------------------+
#property copyright "Pineify"
#property version   "1.00"
#property strict

//--- Input parameters
input double InpLotSize        = 0.1;    // Lot size
input int    InpFastEMA        = 8;      // Fast EMA period
input int    InpSlowEMA        = 21;     // Slow EMA period
input int    InpStopLoss       = 150;    // Stop loss in points
input int    InpTakeProfit     = 100;    // Take profit in points
input int    InpTrailStart     = 50;     // Trailing start in points
input int    InpMaxSpreadPts   = 15;     // Maximum allowed spread in points
input double InpSlopeThreshold = 0.0002; // Max slow EMA slope (price units/bar)
input int    InpSessionStart   = 22;     // Session open hour (server time)
input int    InpSessionEnd     = 2;      // Session close hour (server time)
input int    InpExitHour       = 6;      // Force-exit hour (server time)
input ulong  InpMagicNumber    = 202401; // Magic number

//--- Global handles and state
int    g_fastHandle  = INVALID_HANDLE;
int    g_slowHandle  = INVALID_HANDLE;
double g_point       = 0.0;
int    g_digits      = 5;

//+------------------------------------------------------------------+
//| Expert initialisation                                            |
//+------------------------------------------------------------------+
int OnInit()
  {
   g_point  = _Point;
   g_digits = _Digits;

   g_fastHandle = iMA(_Symbol, PERIOD_M15, InpFastEMA, 0, MODE_EMA, PRICE_CLOSE);
   g_slowHandle = iMA(_Symbol, PERIOD_M15, InpSlowEMA, 0, MODE_EMA, PRICE_CLOSE);

   if(g_fastHandle == INVALID_HANDLE || g_slowHandle == INVALID_HANDLE)
     {
      Print("NightScalperEA: Failed to create MA handles. Error: ", GetLastError());
      return INIT_FAILED;
     }

   Print("NightScalperEA initialised on ", _Symbol,
         " | Magic: ", InpMagicNumber,
         " | Session: ", InpSessionStart, ":00 – ", InpSessionEnd, ":00");
   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Expert deinitialization                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(g_fastHandle != INVALID_HANDLE) IndicatorRelease(g_fastHandle);
   if(g_slowHandle != INVALID_HANDLE) IndicatorRelease(g_slowHandle);
   Print("NightScalperEA deinitialised. Reason: ", reason);
  }

//+------------------------------------------------------------------+
//| Helpers                                                          |
//+------------------------------------------------------------------+
bool IsSessionActive()
  {
   MqlDateTime dt;
   TimeToStruct(TimeCurrent(), dt);
   int hour = dt.hour;

   // Handle session that wraps midnight (e.g. 22 – 02)
   if(InpSessionStart > InpSessionEnd)
      return (hour >= InpSessionStart || hour < InpSessionEnd);
   return (hour >= InpSessionStart && hour < InpSessionEnd);
  }

bool IsForcedExitTime()
  {
   MqlDateTime dt;
   TimeToStruct(TimeCurrent(), dt);
   return (dt.hour == InpExitHour && dt.min == 0);
  }

bool SpreadOk()
  {
   long spreadPts = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
   return (spreadPts <= InpMaxSpreadPts);
  }

int CountOpenPositions()
  {
   int count = 0;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
         if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
            PositionGetInteger(POSITION_MAGIC)  == (long)InpMagicNumber)
            count++;
     }
   return count;
  }

void CloseAllPositions()
  {
   MqlTradeRequest  req;
   MqlTradeResult   res;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(!PositionSelectByTicket(ticket)) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if(PositionGetInteger(POSITION_MAGIC)  != (long)InpMagicNumber) continue;

      ZeroMemory(req);
      ZeroMemory(res);
      req.action   = TRADE_ACTION_DEAL;
      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.deviation = 10;
      req.magic    = InpMagicNumber;
      req.position = ticket;
      req.comment  = "NightScalper forced exit";
      if(!OrderSend(req, res))
         Print("CloseAllPositions error: ", res.retcode, " ticket: ", ticket);
     }
  }

void ManageTrailingStop()
  {
   MqlTradeRequest  req;
   MqlTradeResult   res;
   double trailPts = InpTrailStart * g_point;
   double slPts    = InpStopLoss   * g_point;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(!PositionSelectByTicket(ticket)) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if(PositionGetInteger(POSITION_MAGIC)  != (long)InpMagicNumber) continue;

      double openPrice  = PositionGetDouble(POSITION_PRICE_OPEN);
      double currentSL  = PositionGetDouble(POSITION_SL);
      ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

      if(posType == POSITION_TYPE_BUY)
        {
         double profit = bid - openPrice;
         if(profit < trailPts) continue;
         double newSL = NormalizeDouble(bid - slPts, g_digits);
         if(newSL <= currentSL) continue;

         ZeroMemory(req); ZeroMemory(res);
         req.action   = TRADE_ACTION_SLTP;
         req.symbol   = _Symbol;
         req.sl       = newSL;
         req.tp       = PositionGetDouble(POSITION_TP);
         req.position = ticket;
         req.magic    = InpMagicNumber;
         OrderSend(req, res);
        }
      else // SELL
        {
         double profit = openPrice - ask;
         if(profit < trailPts) continue;
         double newSL = NormalizeDouble(ask + slPts, g_digits);
         if(currentSL > 0 && newSL >= currentSL) continue;

         ZeroMemory(req); ZeroMemory(res);
         req.action   = TRADE_ACTION_SLTP;
         req.symbol   = _Symbol;
         req.sl       = newSL;
         req.tp       = PositionGetDouble(POSITION_TP);
         req.position = ticket;
         req.magic    = InpMagicNumber;
         OrderSend(req, res);
        }
     }
  }

bool OpenTrade(ENUM_ORDER_TYPE orderType)
  {
   MqlTradeRequest req;
   MqlTradeResult  res;
   ZeroMemory(req);
   ZeroMemory(res);

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double slDist = InpStopLoss   * g_point;
   double tpDist = InpTakeProfit * g_point;

   req.action    = TRADE_ACTION_DEAL;
   req.symbol    = _Symbol;
   req.volume    = InpLotSize;
   req.type      = orderType;
   req.deviation = 10;
   req.magic     = InpMagicNumber;
   req.comment   = "NightScalper";
   req.type_filling = ORDER_FILLING_IOC;

   if(orderType == ORDER_TYPE_BUY)
     {
      req.price = ask;
      req.sl    = NormalizeDouble(ask - slDist, g_digits);
      req.tp    = NormalizeDouble(ask + tpDist, g_digits);
     }
   else
     {
      req.price = bid;
      req.sl    = NormalizeDouble(bid + slDist, g_digits);
      req.tp    = NormalizeDouble(bid - tpDist, g_digits);
     }

   bool sent = OrderSend(req, res);
   if(!sent || res.retcode != TRADE_RETCODE_DONE)
      Print("OpenTrade failed. Type: ", EnumToString(orderType),
            " Retcode: ", res.retcode);
   return (sent && res.retcode == TRADE_RETCODE_DONE);
  }

//+------------------------------------------------------------------+
//| Main tick handler                                                |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Force-exit at London open regardless of session
   if(IsForcedExitTime())
     {
      CloseAllPositions();
      return;
     }

   ManageTrailingStop();

   if(!IsSessionActive()) return;
   if(!SpreadOk())        return;
   if(CountOpenPositions() > 0) return;

   // Fetch EMA values — need 3 bars for slope calculation
   double fastEMA[3], slowEMA[3];
   if(CopyBuffer(g_fastHandle, 0, 0, 3, fastEMA) < 3) return;
   if(CopyBuffer(g_slowHandle, 0, 0, 3, slowEMA) < 3) return;
   ArraySetAsSeries(fastEMA, true);
   ArraySetAsSeries(slowEMA, true);

   double slowSlope = MathAbs(slowEMA[0] - slowEMA[2]);

   // Only trade when slow EMA is flat (range-bound market)
   if(slowSlope > InpSlopeThreshold) return;

   double close1 = iClose(_Symbol, PERIOD_M15, 1);
   double close2 = iClose(_Symbol, PERIOD_M15, 2);

   bool bullCross = (close2 < fastEMA[2]) && (close1 > fastEMA[1]);
   bool bearCross = (close2 > fastEMA[2]) && (close1 < fastEMA[1]);

   if(bullCross) OpenTrade(ORDER_TYPE_BUY);
   else if(bearCross) OpenTrade(ORDER_TYPE_SELL);
  }
//+------------------------------------------------------------------+

Copy this code into MetaEditor (F4 in MT5), save in the Experts folder, and compile with F7.

Generate a Custom EURUSD/GBPUSD Night-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

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionBar-based, backtesting onlyTick-based, live trading
DeploymentTradingView alertsRuns 24/5 on VPS/MT5
Broker accessVia TradingView broker integrationDirect broker connectivity
BacktestingBuilt-in, no data download neededStrategy Tester, tick data required
Code complexitySimpler, functional syntaxC++-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.

Frequently Asked Questions

Related MQL5 Expert Advisors