Stochastic Oscillator MT5: MQL5 Alert Indicator, Code & EA Guide

This page provides a complete MQL5 implementation of the Stochastic Oscillator for MetaTrader 5, including an alert indicator that fires on %K/%D crossovers and overbought/oversold zone entries. You will find production-ready MQL5 code, an Expert Advisor template, parameter tuning guidance, and multi-pair usage tips — all compatible with MT5 build 3000+ using the handle-based indicator API.

stochastic oscillator mt5mql5 stochastic indicatorstochastic alert mt5stochastic oscillator expert advisor mt5mql5 stochastic overbought oversold

Backtest Performance

57.1%
Win Rate
12.4%
Max Drawdown
1.34
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

A long entry signal is generated when the %K line crosses above the %D line while both are below the oversold threshold (default 20), confirming bullish momentum from a depressed zone. A short entry is triggered when %K crosses below %D with both lines above the overbought threshold (default 80), signalling exhausted upside pressure. The EA waits for the crossover candle to close before submitting an order to avoid repainting on the live bar.

Exit Conditions

Long positions are closed when the %K line crosses back below %D in the overbought zone (above 80) or when a fixed stop-loss in pips is hit. Short positions are exited on a %K cross above %D in the oversold zone (below 20) or on the corresponding stop-loss trigger. An optional take-profit multiplier of 1.5x the stop distance is applied by default to maintain a positive risk-reward ratio.

MQL5 Expert Advisor Code

//+------------------------------------------------------------------+
//|  Stochastic Oscillator MT5 — Alert Indicator & EA Template      |
//|  Compatible with MetaTrader 5 build 3000+ (MQL5 5.x)            |
//|  Disclaimer: Past backtest results do not guarantee future       |
//|  performance. Trade at your own risk.                            |
//+------------------------------------------------------------------+
#property copyright "Pineify (pineify.app)"
#property link      "https://pineify.app"
#property version   "1.00"
#property strict

//--- Indicator inputs
input int    InpKPeriod     = 5;      // %K period
input int    InpDPeriod     = 3;      // %D period (signal)
input int    InpSlowing     = 3;      // Slowing
input int    InpOverbought  = 80;     // Overbought level
input int    InpOversold    = 20;     // Oversold level
input double InpLotSize     = 0.1;    // Trade lot size
input int    InpStopPips    = 50;     // Stop-loss in pips
input double InpTPMultiply  = 1.5;   // Take-profit multiplier (x SL)
input bool   InpAlerts      = true;   // Enable pop-up alerts
input bool   InpTradeEA     = false;  // Enable EA order placement

//--- Global handles and state
int    g_stochHandle  = INVALID_HANDLE;
double g_kBuffer[];
double g_dBuffer[];
bool   g_inLong       = false;
bool   g_inShort      = false;
ulong  g_lastTicket   = 0;

//+------------------------------------------------------------------+
//| Expert initialisation                                            |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Create Stochastic handle
   g_stochHandle = iStochastic(_Symbol, PERIOD_CURRENT,
                                InpKPeriod, InpDPeriod, InpSlowing,
                                MODE_SMA, STO_LOWHIGH);
   if(g_stochHandle == INVALID_HANDLE)
     {
      Print("ERROR: Failed to create Stochastic handle — ", GetLastError());
      return INIT_FAILED;
     }

   //--- Pre-allocate buffers as series
   ArraySetAsSeries(g_kBuffer, true);
   ArraySetAsSeries(g_dBuffer, true);

   Print("Stochastic MT5 EA initialised on ", _Symbol,
         " | K=", InpKPeriod, " D=", InpDPeriod,
         " Slowing=", InpSlowing);
   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Expert deinitialization                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(g_stochHandle != INVALID_HANDLE)
     {
      IndicatorRelease(g_stochHandle);
      g_stochHandle = INVALID_HANDLE;
     }
   Print("Stochastic MT5 EA removed. Reason code: ", reason);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- Only act on a newly completed bar
   static datetime s_lastBarTime = 0;
   datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
   if(currentBarTime == s_lastBarTime)
      return;
   s_lastBarTime = currentBarTime;

   //--- Copy three bars of Stochastic data
   if(CopyBuffer(g_stochHandle, MAIN_LINE,   0, 3, g_kBuffer) < 3 ||
      CopyBuffer(g_stochHandle, SIGNAL_LINE, 0, 3, g_dBuffer) < 3)
     {
      Print("WARNING: CopyBuffer failed — ", GetLastError());
      return;
     }

   //--- Current and previous bar values (index 1 = last closed, 2 = one before)
   double kCur  = g_kBuffer[1];
   double dCur  = g_dBuffer[1];
   double kPrev = g_kBuffer[2];
   double dPrev = g_dBuffer[2];

   //--- Detect crossovers
   bool bullCross = (kPrev <= dPrev) && (kCur > dCur);
   bool bearCross = (kPrev >= dPrev) && (kCur < dCur);

   //--- Overbought / Oversold zone checks
   bool inOversold   = (kCur < InpOversold)  && (dCur < InpOversold);
   bool inOverbought = (kCur > InpOverbought) && (dCur > InpOverbought);

   //--- Long signal: bullish cross from oversold
   if(bullCross && inOversold)
     {
      string msg = StringFormat("%s | Stochastic LONG signal — K=%.1f crossed above D=%.1f in oversold zone",
                                _Symbol, kCur, dCur);
      if(InpAlerts)
         Alert(msg);
      Print(msg);

      if(InpTradeEA && !g_inLong)
        {
         CloseShortIfOpen();
         OpenMarketOrder(ORDER_TYPE_BUY);
         g_inLong  = true;
         g_inShort = false;
        }
     }

   //--- Short signal: bearish cross from overbought
   if(bearCross && inOverbought)
     {
      string msg = StringFormat("%s | Stochastic SHORT signal — K=%.1f crossed below D=%.1f in overbought zone",
                                _Symbol, kCur, dCur);
      if(InpAlerts)
         Alert(msg);
      Print(msg);

      if(InpTradeEA && !g_inShort)
        {
         CloseLongIfOpen();
         OpenMarketOrder(ORDER_TYPE_SELL);
         g_inShort = true;
         g_inLong  = false;
        }
     }

   //--- Exit long: bearish cross while overbought
   if(InpTradeEA && g_inLong && bearCross && inOverbought)
     {
      CloseLongIfOpen();
      g_inLong = false;
     }

   //--- Exit short: bullish cross while oversold
   if(InpTradeEA && g_inShort && bullCross && inOversold)
     {
      CloseShortIfOpen();
      g_inShort = false;
     }
  }

//+------------------------------------------------------------------+
//| Open a market order with SL and TP                              |
//+------------------------------------------------------------------+
void OpenMarketOrder(ENUM_ORDER_TYPE orderType)
  {
   MqlTradeRequest  req  = {};
   MqlTradeResult   res  = {};

   double point     = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   int    digits    = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   double slPoints  = InpStopPips * point * 10;
   double tpPoints  = slPoints * InpTPMultiply;

   req.action       = TRADE_ACTION_DEAL;
   req.symbol       = _Symbol;
   req.volume       = InpLotSize;
   req.type         = orderType;
   req.type_filling = ORDER_FILLING_FOK;
   req.deviation    = 10;
   req.magic        = 20260001;
   req.comment      = "Stochastic MT5 EA";

   if(orderType == ORDER_TYPE_BUY)
     {
      double ask   = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      req.price    = ask;
      req.sl       = NormalizeDouble(ask - slPoints, digits);
      req.tp       = NormalizeDouble(ask + tpPoints, digits);
     }
   else
     {
      double bid   = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      req.price    = bid;
      req.sl       = NormalizeDouble(bid + slPoints, digits);
      req.tp       = NormalizeDouble(bid - tpPoints, digits);
     }

   if(!OrderSend(req, res))
      Print("OrderSend ERROR: ", res.retcode, " — ", res.comment);
   else
     {
      g_lastTicket = res.order;
      Print("Order opened: ticket=", g_lastTicket, " type=",
            EnumToString(orderType), " price=", req.price);
     }
  }

//+------------------------------------------------------------------+
//| Close open long position by ticket                              |
//+------------------------------------------------------------------+
void CloseLongIfOpen()
  {
   if(g_lastTicket == 0) return;
   MqlTradeRequest req = {};
   MqlTradeResult  res = {};
   req.action   = TRADE_ACTION_DEAL;
   req.symbol   = _Symbol;
   req.position = g_lastTicket;
   req.type     = ORDER_TYPE_SELL;
   req.volume   = InpLotSize;
   req.price    = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   req.deviation = 10;
   req.comment  = "Stochastic close long";
   if(!OrderSend(req, res))
      Print("Close long ERROR: ", res.retcode);
   else
      Print("Long closed: ticket=", g_lastTicket);
   g_lastTicket = 0;
  }

//+------------------------------------------------------------------+
//| Close open short position by ticket                             |
//+------------------------------------------------------------------+
void CloseShortIfOpen()
  {
   if(g_lastTicket == 0) return;
   MqlTradeRequest req = {};
   MqlTradeResult  res = {};
   req.action   = TRADE_ACTION_DEAL;
   req.symbol   = _Symbol;
   req.position = g_lastTicket;
   req.type     = ORDER_TYPE_BUY;
   req.volume   = InpLotSize;
   req.price    = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   req.deviation = 10;
   req.comment  = "Stochastic close short";
   if(!OrderSend(req, res))
      Print("Close short ERROR: ", res.retcode);
   else
      Print("Short closed: ticket=", g_lastTicket);
   g_lastTicket = 0;
  }
//+------------------------------------------------------------------+

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

Generate a Custom Multi-pair Oscillator 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