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.
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
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
| 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.