Complete .mq5 source code

Williams %R MQL5 Indicator: Overbought/Oversold System & EA Integration

Williams %R is a bounded oscillator from -100 to 0. This custom MQL5 indicator calculates its lookback range, plots an EMA of the oscillator and optionally notifies threshold crossings on completed bars. It contains no Expert Advisor, orders or verified performance results. The source is intended for inspection and independent testing.

How the indicator signal works

Calculation and signal conditions

Each bar uses its own close and the highest high and lowest low of a window ending at that bar. The first period minus one bars remain empty; a zero-width range is undefined and also remains empty. An alert can occur when the latest completed value crosses above the oversold input or below the overbought input. These are zone-exit observations, not evidence that a reversal must follow. The EMA signal line is plotted but not used by the alert conditions.

Interpretation and limitations

There are no position exits, ATR stops, take-profit, trailing rules or 50 EMA price filter in this indicator. Popup and push settings are independent. At initialization or a history reset, the latest completed bar is recorded without replaying its old alert; subsequent evaluations inspect each new completed bar once. Full-history recalculation favors clarity over speed. Current-bar values can change, and revised price history can change historical values.

MQL5 Custom Indicator Code

// Educational custom indicator. No orders or verified performance.
#property indicator_separate_window
#property indicator_minimum -100
#property indicator_maximum 0
#property indicator_buffers 2
#property indicator_plots 2
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_label1 "Williams %R"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrange
#property indicator_label2 "WPR EMA"
#property indicator_level1 -20
#property indicator_level2 -80
input int WPRPeriod=14;
input int SignalPeriod=3;
input double Overbought=-20;
input double Oversold=-80;
input bool PopupAlerts=true;
input bool PushAlerts=false;
double WPR[],Signal[];
datetime lastCompleted=0;
int OnInit()
{
   if(WPRPeriod<2 || SignalPeriod<1 || Oversold<=-100 || Overbought>=0 || Oversold>=Overbought) return INIT_PARAMETERS_INCORRECT;
   SetIndexBuffer(0,WPR,INDICATOR_DATA); SetIndexBuffer(1,Signal,INDICATOR_DATA);
   ArraySetAsSeries(WPR,false); ArraySetAsSeries(Signal,false);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,Overbought);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,Oversold);
   IndicatorSetString(INDICATOR_SHORTNAME,"Williams %R + EMA");
   for(int p=0;p<2;p++) { PlotIndexSetDouble(p,PLOT_EMPTY_VALUE,EMPTY_VALUE); PlotIndexSetInteger(p,PLOT_DRAW_BEGIN,WPRPeriod-1); }
   return INIT_SUCCEEDED;
}
int OnCalculate(const int n,const int prev,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[])
{
   ArraySetAsSeries(time,false); ArraySetAsSeries(high,false); ArraySetAsSeries(low,false); ArraySetAsSeries(close,false);
   ArrayInitialize(WPR,EMPTY_VALUE); ArrayInitialize(Signal,EMPTY_VALUE);
   double alpha=2.0/(SignalPeriod+1.0);
   for(int i=WPRPeriod-1;i<n && !IsStopped();i++)
   {
      int h=ArrayMaximum(high,i-WPRPeriod+1,WPRPeriod),l=ArrayMinimum(low,i-WPRPeriod+1,WPRPeriod);
      if(h<0 || l<0 || high[h]<=low[l]) continue;
      WPR[i]=-100.0*(high[h]-close[i])/(high[h]-low[l]);
      Signal[i]=(i==0 || Signal[i-1]==EMPTY_VALUE)?WPR[i]:alpha*WPR[i]+(1-alpha)*Signal[i-1];
   }
   if(n<3) return n;
   int c=n-2,p=n-3;
   if(prev==0 || lastCompleted==0) { lastCompleted=time[c]; return n; }
   if(time[c]==lastCompleted) return n;
   lastCompleted=time[c];
   if(WPR[c]==EMPTY_VALUE || WPR[p]==EMPTY_VALUE) return n;
   string event="";
   if(WPR[p]<=Oversold && WPR[c]>Oversold) event="crossed above oversold";
   else if(WPR[p]>=Overbought && WPR[c]<Overbought) event="crossed below overbought";
   if(event!="")
   {
      string msg=_Symbol+" WPR "+event+" on completed bar "+TimeToString(time[c]);
      if(PopupAlerts) Alert(msg);
      if(PushAlerts && !SendNotification(msg)) Print("Push failed: ",GetLastError());
   }
   return n;
}

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.