Edgoro
Momentum indicator

Williams %R: formula, levels and Pine Script v6 code

How Williams %R places the close within the recent high-low range, how traders read the -20 and -80 levels, settings, and a free %R script for TradingView.

What it measures

Williams %R measures where the close sits within the high-low range of the last N bars, on a scale from 0 to −100. A reading near 0 means the bar closed near the top of the range; near −100, near the bottom.

Larry Williams introduced it in the 1970s. It is the stochastic oscillator's raw %K turned upside down: %R = %K − 100. The information is the same, the scale is different, and %R is usually shown without smoothing or a signal line, so it reacts quickly.

The formula in words

  1. Find the highest high and lowest low of the last N bars (14 by default).
  2. %R = (highest high − close) ÷ (highest high − lowest low) × −100.

The result runs from 0 (close at the highest high) to −100 (close at the lowest low). The negative scale is a convention from the original; some platforms show %R from 0 to 100 instead. Pine Script's ta.wpr(length) uses the negative scale. If the window's high equals its low, the value is undefined for that bar.

How traders read it

  • Zones. Above −20 is called overbought and below −80 oversold. In a trend %R can stay in a zone for a long time, so being in a zone isn't a signal by itself.
  • Leaving a zone. A more specific event is %R crossing back below −20 or back above −80: the close has moved away from the edge of the range. The script marks those crosses.
  • Momentum confirmation. During a strong rally %R keeps returning to near 0. %R failing to reach −20 on a later push is read as momentum fading.
  • Trend filter. Taking oversold exits only when price is above a long moving average (and overbought exits only below it) cuts signals against the trend. The script includes this as an option.

Common settings

SettingTypical valueNotes
Length1410 is also common. Shorter lengths reach the extremes more often.
Levels−20 / −80−10 / −90 for fewer, more extreme readings.
Trend filter200 EMAOptional, off by default in the script.

Because %R isn't smoothed, it's noisier than a slow stochastic of the same length.

Pine Script v6 code

The complete, self-contained script is below. Copy it into a new indicator in TradingView's Pine Editor, or download the .pine file.

Pine Script v6
//@version=6
indicator("Williams %R", shorttitle = "%R", format = format.price, precision = 2)

len      = input.int(14, "Length", minval = 1, group = "Calculation")
obLevel  = input.int(-20, "Overbought level", minval = -50, maxval = 0, group = "Levels")
osLevel  = input.int(-80, "Oversold level", minval = -100, maxval = -50, group = "Levels")
useTrend = input.bool(false, "Only mark signals in the direction of the trend EMA", group = "Filter")
trendLen = input.int(200, "Trend EMA length", minval = 2, group = "Filter")

wr    = ta.wpr(len)
trend = ta.ema(close, trendLen)

// %R leaving a zone: crossing back above oversold, or back below overbought.
leavesOversold   = ta.crossover(wr, osLevel)
leavesOverbought = ta.crossunder(wr, obLevel)
bullSignal = leavesOversold and (not useTrend or close > trend)
bearSignal = leavesOverbought and (not useTrend or close < trend)

plot(wr, "%R", color = color.new(color.blue, 0), linewidth = 2)
obLine = hline(obLevel, "Overbought", color = color.gray, linestyle = hline.style_dashed)
hline(-50, "Midline", color = color.new(color.gray, 60), linestyle = hline.style_dotted)
osLine = hline(osLevel, "Oversold", color = color.gray, linestyle = hline.style_dashed)
fill(obLine, osLine, color = color.new(color.blue, 93), title = "Range")

plotshape(bullSignal, "Leaves oversold", shape.triangleup, location.bottom, color.new(color.teal, 0), size = size.tiny)
plotshape(bearSignal, "Leaves overbought", shape.triangledown, location.top, color.new(color.red, 0), size = size.tiny)

alertcondition(bullSignal, "%R leaves oversold", "Williams %R crossed back above the oversold level on {{ticker}} ({{interval}})")
alertcondition(bearSignal, "%R leaves overbought", "Williams %R crossed back below the overbought level on {{ticker}} ({{interval}})")

The script plots %R in its own pane with the zone between the levels shaded, and marks the bar where %R crosses back out of a zone. An optional 200 EMA filter keeps bullish marks only above the EMA and bearish marks only below it.

Both events are available as alert conditions. Choose Once per bar close: on the live bar %R moves with every tick.

Add it to your chart

  1. Open any chart on TradingView and open the Pine Editor.
  2. Create a new indicator, delete the template code and paste the script.
  3. Click Save, then Add to chart. Change lengths and levels from the indicator's settings.

Stuck on an error? See how to add a Pine Script indicator to TradingView.

Pitfalls

  • Selling every reading above −20. In strong uptrends %R lives near 0. Use the zones in ranges or with a trend filter.
  • Expecting new information next to a stochastic. %R is the unsmoothed stochastic %K on another scale. Adding both to a chart doesn't add a second opinion.
  • Scale confusion. Some platforms show %R from 0 to 100. Check the scale before copying levels from another source.
  • Live-bar crosses. The close isn't final until the bar closes.

The script is an educational example: test it on your own markets before relying on it. Indicators describe the past; they don't predict the future. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.

Make it yours with Edgoro

Describe the change in plain English and Edgoro writes the Pine Script v6 for you, ready to paste. For example:

“Plot Williams %R(14) with -20/-80 levels, mark when it crosses back above -80 while the close is above the 50 EMA, and alert once per bar close.”

Build your Williams %R indicator