Williams %R in MetaTrader 5 — MQL5 Source Code

A custom Williams %R oscillator for MT5

Williams %R in MetaTrader 5
Williams %R in MetaTrader 5

Williams %R in MQL5 is a compact separate-window oscillator — a nice, short custom indicator. See the explainer for the concept and the negative scale.

What you’ll need

  • MetaTrader 5 with MetaEditor
  • Save as AlgoGen.WilliamsR.mq5 under MQL5/Indicators/

The source

//+------------------------------------------------------------------+
//|                                            AlgoGen.WilliamsR.mq5 |
//|                                          Copyright 2026, AlgoGen |
//|                                           https://www.algogen.io |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, AlgoGen"
#property link      "https://www.algogen.io"
#property version   "1.00"
#property indicator_separate_window
#property indicator_minimum -100
#property indicator_maximum 0
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_label1  "%R"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_width1  2
#property indicator_level1  -20.0
#property indicator_level2  -80.0

input int InpPeriod = 14; // %R period

double WRBuffer[];

int OnInit()
  {
   SetIndexBuffer(0, WRBuffer, INDICATOR_DATA);
   IndicatorSetString(INDICATOR_SHORTNAME, "AlgoGen %R(" + (string)InpPeriod + ")");
   return(INIT_SUCCEEDED);
  }

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[])
  {
   if(rates_total < InpPeriod)
      return(0);

   int start = (prev_calculated > InpPeriod) ? prev_calculated - 1 : InpPeriod - 1;

   for(int i = start; i < rates_total; i++)
     {
      double hh = high[i], ll = low[i];
      for(int j = 1; j < InpPeriod; j++)
        {
         if(high[i - j] > hh) hh = high[i - j];
         if(low[i - j]  < ll) ll = low[i - j];
        }
      double range = hh - ll;
      WRBuffer[i] = (range == 0.0) ? -50.0 : -100.0 * (hh - close[i]) / range;
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

Install & compile

  1. Drop it in MQL5/Indicators/, press F7.
  2. Drag onto a chart — a separate window shows the %R line between −100 and 0 with the −20/−80 level lines, matching the output chart.

Gotchas

  • Fixed scale. indicator_minimum -100 / indicator_maximum 0 pin the sub- window so the levels sit correctly; without them MT5 auto-scales and the −20/−80 guides drift.
  • Flat-range guard. (range == 0.0) ? -50.0 fills a neutral mid-value when the window is perfectly flat instead of dividing by zero.
  • Built-in / MQL4. MT5 has iWPR; MQL4 does too. The custom version is for learning and for exposing the buffer to an EA.
  • Using it in an EA. Read the buffer with CopyBuffer, and consider gating signals on a trend filter (e.g. only buy %R crossing up through −80 when price is above a long moving average) — fading extremes blindly gets punished in trends.
  • Add smoothing. For calmer signals, average the raw %R with a short SMA on a second buffer; %R is unsmoothed and pokes the extremes often.

Same indicator elsewhere: Python, Pine Script, EasyLanguage, NinjaScript. Then test a %R rule in AlgoGen.


This post is educational, not financial advice. Indicators describe the past; they don’t predict the future. Backtest anything before you risk real money on it.

Sources and further reading

  1. Larry Williams' indicator chronology (I Really Trade)
  2. Technical indicator functions (MetaQuotes)

Historical research from the Algogen archive. Not investment advice.

Blog

Have a strategy idea?

Describe it in plain English, preview where your rules fire, then decide whether the evidence is worth a backtest.

Keep me postedHow it works