Complete .mq5 source code

Stochastic H4 Swing Trading MQL5: Oscillator Reversal Entry System

An H4-only custom indicator showing Stochastic K/D and completed-bar cross markers. The sample adds H4 ADX and a time-aligned completed D1 close-versus-EMA filter. It has no order execution, multi-day holding policy or verified trade performance.

How the indicator signal works

Calculation and signal conditions

The up condition is a K-over-D cross with both current completed values below the oversold threshold; the down condition reverses the cross with both above the overbought threshold. ADX must exceed its threshold. For each historical candidate, the next available H4 open identifies the decision time; the prior completed D1 close must be above its EMA for up or below it for down. Price versus EMA is a level comparison, not EMA slope.

Interpretation and limitations

There are no positions, ATR stops, opposite-signal closes or ADX exits in this indicator. Markers are observations for a separately defined strategy. Source data unavailable at a candidate time withholds its marker; it never substitutes the latest daily filter into historical bars. Forming lines, corrected history and newly loaded history can change displayed values.

MQL5 Custom Indicator Code

#property strict
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots 4
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_label1 "%K"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrangeRed
#property indicator_label2 "%D"
#property indicator_type3 DRAW_ARROW
#property indicator_color3 clrLimeGreen
#property indicator_label3 "Up signal"
#property indicator_type4 DRAW_ARROW
#property indicator_color4 clrTomato
#property indicator_label4 "Down signal"
input int InpKPeriod=5;
input int InpDPeriod=3;
input int InpSlowing=3;
input int InpOverbought=80;
input int InpOversold=20;
input int InpAdxPeriod=14;
input double InpAdxThreshold=20;
input int InpEmaPeriod=200;
input bool InpShowAlerts=true;
double kLine[],dLine[],up[],down[];
int hs=INVALID_HANDLE,ha=INVALID_HANDLE,he=INVALID_HANDLE;
datetime lastClosed=0;
int OnInit()
{
   if(_Period!=PERIOD_H4 || InpKPeriod<2 || InpDPeriod<1 || InpSlowing<1 || InpAdxPeriod<1 || InpEmaPeriod<1 ||
      InpOversold<0 || InpOverbought>100 || InpOversold>=InpOverbought || InpAdxThreshold<0 || InpAdxThreshold>100)
      return INIT_PARAMETERS_INCORRECT;
   SetIndexBuffer(0,kLine,INDICATOR_DATA); SetIndexBuffer(1,dLine,INDICATOR_DATA);
   SetIndexBuffer(2,up,INDICATOR_DATA); SetIndexBuffer(3,down,INDICATOR_DATA);
   ArraySetAsSeries(kLine,false); ArraySetAsSeries(dLine,false); ArraySetAsSeries(up,false); ArraySetAsSeries(down,false);
   for(int p=0;p<4;p++) { PlotIndexSetInteger(p,PLOT_DRAW_BEGIN,InpKPeriod+InpDPeriod+InpSlowing); PlotIndexSetDouble(p,PLOT_EMPTY_VALUE,EMPTY_VALUE); }
   PlotIndexSetInteger(2,PLOT_ARROW,233); PlotIndexSetInteger(3,PLOT_ARROW,234);
   IndicatorSetInteger(INDICATOR_LEVELS,2); IndicatorSetDouble(INDICATOR_LEVELVALUE,0,InpOversold); IndicatorSetDouble(INDICATOR_LEVELVALUE,1,InpOverbought);
   hs=iStochastic(_Symbol,PERIOD_H4,InpKPeriod,InpDPeriod,InpSlowing,MODE_SMA,STO_LOWHIGH);
   ha=iADX(_Symbol,PERIOD_H4,InpAdxPeriod);
   he=iMA(_Symbol,PERIOD_D1,InpEmaPeriod,0,MODE_EMA,PRICE_CLOSE);
   return hs==INVALID_HANDLE || ha==INVALID_HANDLE || he==INVALID_HANDLE?INIT_FAILED:INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
   if(hs!=INVALID_HANDLE) IndicatorRelease(hs); if(ha!=INVALID_HANDLE) IndicatorRelease(ha); if(he!=INVALID_HANDLE) IndicatorRelease(he);
}
int OnCalculate(const int rates_total,const int prev_calculated,const datetime &time[],
 const double &open[],const double &high[],const double &low[],const double &close[],
 const long &tick_volume[],const long &volume[],const int &spread[])
{
   int begin=(int)MathMax(InpKPeriod+InpDPeriod+InpSlowing,2*InpAdxPeriod+1);
   if(rates_total<begin+3) return 0;
   ArraySetAsSeries(time,false);
   double k[],d[],adx[];
   if(CopyBuffer(hs,MAIN_LINE,0,rates_total,k)!=rates_total || CopyBuffer(hs,SIGNAL_LINE,0,rates_total,d)!=rates_total ||
      CopyBuffer(ha,0,0,rates_total,adx)!=rates_total) return prev_calculated;
   ArrayInitialize(up,EMPTY_VALUE); ArrayInitialize(down,EMPTY_VALUE);
   for(int i=0;i<rates_total;i++) { kLine[i]=i>=begin?k[i]:EMPTY_VALUE; dLine[i]=i>=begin?d[i]:EMPTY_VALUE; }
   bool newestReady=true;
   for(int i=begin;i<rates_total-1;i++)
   {
      bool bull=k[i-1]<=d[i-1] && k[i]>d[i] && k[i]<InpOversold && d[i]<InpOversold;
      bool bear=k[i-1]>=d[i-1] && k[i]<d[i] && k[i]>InpOverbought && d[i]>InpOverbought;
      if((!bull && !bear) || adx[i]<=InpAdxThreshold) continue;
      int containing=iBarShift(_Symbol,PERIOD_D1,time[i+1],false);
      int shift=containing+1;
      double ema[1],dailyClose[1];
      if(containing<0 || BarsCalculated(he)<=shift+InpEmaPeriod || CopyBuffer(he,0,shift,1,ema)!=1 ||
         CopyClose(_Symbol,PERIOD_D1,shift,1,dailyClose)!=1)
      { if(i==rates_total-2) newestReady=false; continue; }
      if(bull && dailyClose[0]>ema[0]) up[i]=k[i];
      if(bear && dailyClose[0]<ema[0]) down[i]=k[i];
   }
   int i=rates_total-2;
   if(prev_calculated==0 || lastClosed==0) lastClosed=time[i];
   else if(newestReady && time[i]!=lastClosed)
   {
      lastClosed=time[i];
      if(InpShowAlerts && (up[i]!=EMPTY_VALUE || down[i]!=EMPTY_VALUE))
         Alert(StringFormat("%s H4 Stochastic completed-bar %s",_Symbol,up[i]!=EMPTY_VALUE?"up signal":"down signal"));
   }
   return rates_total;
}

Copy this code into MetaEditor, save it in the MQL5/Indicators folder, and compile with F7.

Change the settings or add your own signal filter

Describe the inputs, buffers, alerts, visual style, or confirmation filter you want. Pineify generates editable MQL5 source code that you can inspect and compile in MetaEditor.

Frequently Asked Questions

Related MQL5 pages

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.