Indicator · Pine Script v6 · Own pane

RSI = Relative Strength Index

by piecioshka

Calculates the Relative Strength Index oscillator in a separate pane with configurable overbought and oversold thresholds.

View on GitHub

GitHub stars2on the repository
Pine versionv6current
Lines of code165
Settings14inputs
LicenceMIT
Last update10 days ago18 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

165 lines of Pine Script v6 from indicators/oscillators/rsi/rsi.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

rsi.pine
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Piotr Kowalski "piecioshka"
// Docs (EN): https://github.com/piecioshka/tradingview-pine-scripts/blob/main/indicators/oscillators/rsi/rsi.md
// Docs (PL): https://github.com/piecioshka/tradingview-pine-scripts/blob/main/indicators/oscillators/rsi/rsi.pl.md

//@version=6
// No "timeframe" argument (MTF): Pine forbids it in scripts that create
// drawings - and the price markers, threshold-cross labels, and the status
// table here are all label/table objects.
indicator('RSI = Relative Strength Index', overlay=false, precision=2, max_lines_count=100, max_labels_count=100)

// --- Color palette (single place for the theme) ---
cRsi = color.rgb(255, 245, 157)  // RSI line
cOb  = color.red                 // overbought / upper zone
cOs  = color.green               // oversold / lower zone
cMid = color.gray                // midline and neutral elements
cMa  = color.yellow              // smoothing MA
cBb  = color.green               // Bollinger Bands

// --- Inputs ---
gCalc = 'Calculation'
rsiSource = input.source(close, 'Source', group=gCalc, tooltip='Price the RSI is calculated from (candle close by default).')
rsiLength = input.int(14, 'Length', minval=1, group=gCalc, tooltip='Number of candles in the RSI window. Fewer = more sensitive, more = smoother.')

gLevels = 'Levels'
obLevel  = input.int(70, 'Overbought', minval=50, maxval=100, group=gLevels, tooltip='Above this level the market is considered overbought.')
osLevel  = input.int(30, 'Oversold',   minval=0,  maxval=50,  group=gLevels, tooltip='Below this level the market is considered oversold.')
midLevel = 50  // deliberately NOT an input - 50 is the RSI's definitional axis of symmetry

gSmooth = 'Smoothing'
TT_BB = 'Applies only to the "SMA + Bollinger Bands" variant. Sets the distance of the bands from the SMA.'
maTypeInput = input.string('SMA', 'Type', options=['None', 'SMA', 'SMA + Bollinger Bands', 'EMA', 'SMMA (RMA)', 'WMA', 'VWMA'], group=gSmooth, display=display.none, tooltip='Moving average calculated from the RSI. "None" disables smoothing.')
var isBB = maTypeInput == 'SMA + Bollinger Bands'
maLengthInput = input.int(14, 'Length', minval=1, group=gSmooth, display=display.none, active=maTypeInput != 'None')
bbMultInput = input.float(2.0, 'BB StdDev', minval=0.001, maxval=50, step=0.5, tooltip=TT_BB, group=gSmooth, display=display.none, active=isBB)
var enableMA = maTypeInput != 'None'

gDiv = 'Divergences'
calculateDivergence = input.bool(false, 'Calculate divergences', group=gDiv, display=display.none, tooltip='Regular bull/bear divergences (RSI pivots vs price). Required for divergence alerts to work.')

gView = 'Display'
showZones   = input.bool(true, 'Zone gradient',                 group=gView, tooltip='Vertical gradient in the overbought/oversold zone (between the RSI line and the threshold).')
showSignals = input.bool(true, 'Signals (markers on price)',    group=gView, tooltip='Markers on the price panel (mean reversion): green below the candle when the RSI drops below the oversold level, red above the candle when it rises above the overbought level. Shape and size in the Appearance group.')
showLabels  = input.bool(false, 'BUY CLOSE / BUY OPEN markers', group=gView, tooltip='Markers on the RSI panel where the threshold is crossed. Off by default.')
showTable   = input.bool(true,  'Status table',                 group=gView, tooltip='Small corner panel with the current RSI value and state.')

gA = 'Appearance'
shapeName = input.string('Triangle', 'Marker shape', options=['Triangle', 'Arrow', 'Label arrow', 'Circle', 'Diamond'], group=gA, tooltip='Triangle - solid triangle.\nArrow - small thin arrow.\nLabel arrow - arrow-shaped label bubble.\nCircle / Diamond - neutral dot markers.')
sizeName  = input.string('Small', 'Marker size', options=['Tiny', 'Small', 'Normal', 'Large'], group=gA)

// Markers as labels - the shape is picked from an input, which plotshape() cannot do (its style must be a constant).
upStyle    = shapeName == 'Arrow' ? label.style_arrowup : shapeName == 'Label arrow' ? label.style_label_up : shapeName == 'Circle' ? label.style_circle : shapeName == 'Diamond' ? label.style_diamond : label.style_triangleup
downStyle  = shapeName == 'Arrow' ? label.style_arrowdown : shapeName == 'Label arrow' ? label.style_label_down : shapeName == 'Circle' ? label.style_circle : shapeName == 'Diamond' ? label.style_diamond : label.style_triangledown
markerSize = sizeName == 'Tiny' ? size.tiny : sizeName == 'Normal' ? size.normal : sizeName == 'Large' ? size.large : size.small

// --- Calculations ---
rsi     = ta.rsi(rsiSource, rsiLength)
crossOb = ta.crossover(rsi, obLevel)    // entering the overbought zone
crossOs = ta.crossunder(rsi, osLevel)   // entering the oversold zone

// --- RSI line and hidden thresholds (fill boundaries) ---
rsiPlot = plot(rsi, 'RSI', color=cRsi, linewidth=1)
pOb = plot(obLevel, 'Overbought threshold', color=na, display=display.none, editable=false)
pOs = plot(osLevel, 'Oversold threshold',   color=na, display=display.none, editable=false)

// --- Reference levels ---
hline(obLevel,  'Overbought', color=cOb,  linestyle=hline.style_dotted)
hline(osLevel,  'Oversold',   color=cOs,  linestyle=hline.style_dotted)
hline(midLevel, 'Midline',    color=cMid, linestyle=hline.style_dotted)

// --- Vertical zone gradient (bottom->top), only while RSI is in the zone ---
// Red: pale at the overbought threshold, strong toward 100
fill(rsiPlot, pOb, top_value=100, bottom_value=obLevel, top_color = showZones and rsi > obLevel ? color.new(cOb, 20) : na, bottom_color = showZones and rsi > obLevel ? color.new(cOb, 90) : na, title='Overbought zone')
// Green: pale at the oversold threshold, strong toward 0
fill(rsiPlot, pOs, top_value=osLevel, bottom_value=0, top_color = showZones and rsi < osLevel ? color.new(cOs, 90) : na, bottom_color = showZones and rsi < osLevel ? color.new(cOs, 20) : na, title='Oversold zone')

// --- Smoothing (MA of the RSI, optionally Bollinger Bands) ---
ma(source, length, MAtype) =>
    switch MAtype
        'SMA'                   => ta.sma(source, length)
        'SMA + Bollinger Bands' => ta.sma(source, length)
        'EMA'                   => ta.ema(source, length)
        'SMMA (RMA)'            => ta.rma(source, length)
        'WMA'                   => ta.wma(source, length)
        'VWMA'                  => ta.vwma(source, length)

smoothingMA    = enableMA ? ma(rsi, maLengthInput, maTypeInput) : na
smoothingStDev = isBB ? ta.stdev(rsi, maLengthInput) * bbMultInput : na
plot(smoothingMA, 'RSI-based MA', color=cMa, display = enableMA ? display.all : display.none, editable=enableMA)
bbUpperBand = plot(smoothingMA + smoothingStDev, 'Upper Bollinger Band', color=cBb, display = isBB ? display.all : display.none, editable=isBB)
bbLowerBand = plot(smoothingMA - smoothingStDev, 'Lower Bollinger Band', color=cBb, display = isBB ? display.all : display.none, editable=isBB)
fill(bbUpperBand, bbLowerBand, color = isBB ? color.new(cBb, 90) : na, title='Bollinger Bands background', display = isBB ? display.all : display.none, editable=isBB)

// --- Signals (markers as labels - the shape comes from the Appearance inputs) ---
// Marker positions clipped to the 0..100 scale so they stay inside the panel at RSI extremes
obLabelY = math.min(rsi + 5, 100)
osLabelY = math.max(rsi - 5, 0)

// Markers on the price panel (force_overlay): overbought = red above the candle, oversold = green below
if showSignals and crossOb
    label.new(bar_index, na, '', yloc=yloc.abovebar, style=downStyle, color=cOb, size=markerSize, force_overlay=true)
if showSignals and crossOs
    label.new(bar_index, na, '', yloc=yloc.belowbar, style=upStyle, color=cOs, size=markerSize, force_overlay=true)

// Markers on the RSI panel where the threshold is crossed (BUY CLOSE above, BUY OPEN below)
if showLabels and crossOb
    label.new(bar_index, obLabelY, '', style=downStyle, color=cOb, size=markerSize)
if showLabels and crossOs
    label.new(bar_index, osLabelY, '', style=upStyle, color=cOs, size=markerSize)

// --- Divergences (regular, on RSI pivots vs price) ---
lookbackRight = 5
lookbackLeft  = 5
rangeUpper    = 60
rangeLower    = 5
noneColor     = color.new(color.white, 100)

_inRange(bool cond) =>
    bars = ta.barssince(cond)
    rangeLower <= bars and bars <= rangeUpper

plFound  = false
phFound  = false
bullCond = false
bearCond = false

rsiLBR = rsi[lookbackRight]

if calculateDivergence
    // Bull: RSI makes a higher low, price a lower low
    plFound := not na(ta.pivotlow(rsi, lookbackLeft, lookbackRight))
    rsiHL   = rsiLBR > ta.valuewhen(plFound, rsiLBR, 1) and _inRange(plFound[1])
    lowLBR  = low[lookbackRight]
    priceLL = lowLBR < ta.valuewhen(plFound, lowLBR, 1)
    bullCond := priceLL and rsiHL and plFound

    // Bear: RSI makes a lower high, price a higher high
    phFound := not na(ta.pivothigh(rsi, lookbackLeft, lookbackRight))
    rsiLH   = rsiLBR < ta.valuewhen(phFound, rsiLBR, 1) and _inRange(phFound[1])
    highLBR = high[lookbackRight]
    priceHH = highLBR > ta.valuewhen(phFound, highLBR, 1)
    bearCond := priceHH and rsiLH and phFound

plot(plFound ? rsiLBR : na, offset=-lookbackRight, title='Bullish divergence', linewidth=2, color = bullCond ? cOs : noneColor, display=display.pane, editable=calculateDivergence)
plotshape(bullCond ? rsiLBR : na, offset=-lookbackRight, title='Bullish divergence label', text=' Bull ', style=shape.labelup, location=location.absolute, color=cOs, textcolor=color.white, display=display.pane, editable=calculateDivergence)

plot(phFound ? rsiLBR : na, offset=-lookbackRight, title='Bearish divergence', linewidth=2, color = bearCond ? cOb : noneColor, display=display.pane, editable=calculateDivergence)
plotshape(bearCond ? rsiLBR : na, offset=-lookbackRight, title='Bearish divergence label', text=' Bear ', style=shape.labeldown, location=location.absolute, color=cOb, textcolor=color.white, display=display.pane, editable=calculateDivergence)

// --- Alerts ---
alertcondition(crossOb, 'RSI: Overbought', 'RSI crossed the overbought threshold up')
alertcondition(crossOs, 'RSI: Oversold',   'RSI crossed the oversold threshold down')
alertcondition(bullCond, 'RSI: Bullish divergence', 'Regular bullish divergence - "Pivot Lookback Right" candles to the left of the current candle')
alertcondition(bearCond, 'RSI: Bearish divergence', 'Regular bearish divergence - "Pivot Lookback Right" candles to the left of the current candle')

// --- Status table (top-right corner) ---
status      = rsi >= obLevel ? 'Overbought' : rsi <= osLevel ? 'Oversold' : 'Neutral'
statusColor = rsi >= obLevel ? cOb : rsi <= osLevel ? cOs : cMid

var table infoTable = table.new(position.top_right, 2, 2, border_width=1, border_color=color.new(cMid, 70))
if showTable and barstate.islast
    table.cell(infoTable, 0, 0, 'RSI',    text_color=cMid,        text_size=size.small)
    table.cell(infoTable, 1, 0, str.tostring(rsi, '#.##'), text_color=color.white, text_size=size.small)
    table.cell(infoTable, 0, 1, 'Status', text_color=cMid,        text_size=size.small)
    table.cell(infoTable, 1, 1, status,   text_color=statusColor, text_size=size.small)

Overview

Includes options for smoothing the RSI line using various moving averages or Bollinger Bands, gradient fill zones, and regular divergence detection. The indicator plots optional buy and sell signal markers directly on the price chart or RSI pane and features a status table summarizing current conditions.

Details

Published by

piecioshka on GitHub

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

Oscillators & momentum, Volatility & bands, Divergence, Screeners & dashboards

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Topics

pinescriptpinescript-indicatorspinescript-strategiestradingtradingview

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
SourcesourceclosersiSource
Lengthint14rsiLength
Overboughtint70obLevel
Oversoldint30osLevel
TypestringSMAmaTypeInput
Lengthint14maLengthInput
BB StdDevfloat2.0bbMultInput
Calculate divergencesboolfalsecalculateDivergence
Zone gradientbooltrueshowZones
Signals (markers on price)booltrueshowSignals
BUY CLOSE / BUY OPEN markersboolfalseshowLabels
Status tablebooltrueshowTable
Show all 14 settings
SettingTypeDefaultVariable
Marker shapestringTriangleshapeName
Marker sizestringSmallsizeName
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

GEKO HYBRID MASTER

by grzegorzkowalskigk-jpg
1 stars

GEKO HYBRID MASTER is a custom oscillator indicator that merges RSI, Stochastic, MFI, MACD, and SATS volatility filters for signal confirmation. It calculates composite momentum with normalized MACD, body-proportional CVD, divergences, HTF EMA slope and ADX tr

Indicator v6 Oscillators & momentumVolatility & bands
Updated 3 months ago · Custom licence GitHub repository of GEKO HYBRID MASTER

This indicator projects a dual-asset momentum matrix visualizer directly onto the price chart overlay. It calculates normalized momentum for the chart symbol using either RSI or Stochastic inputs adjusted by ATR volatility, and compares it against a benchmark

Indicator v6 Oscillators & momentumVolatility & bands Repaints
Updated 3 months ago · None stated GitHub repository of Pro Grid Elite: Advanced Dual-Asset Momentum Matrix

This indicator scans a pasted list of symbols for RSI directional momentum and shows matching long and short signals in a table in a separate pane. The user chooses continuous break, continuous retracement, flip break, flip retracement, divergence, or hidden d

Indicator v6 Oscillators & momentumDivergence
Updated 1 year ago · MPL-2.0 GitHub repository of Momentum Setup - RSI Directional Momentum Scanner
330 stars

This indicator plots a TTM Squeeze momentum oscillator and a MACD line in a separate pane. It builds the squeeze oscillator from a linear regression of price against a high-low and simple moving average midpoint, and colors the area by slope and sign. Circles

Indicator v5 Oscillators & momentumVolatility & bands
Updated 2 months ago · None stated GitHub repository of TTM Squeeze + MACD line [Alorse]

Test 009 Stat Mining

by ricardosantos79
261 stars

This statistical analysis tool mines historical relationships between RSI values and candle volatility. It calculates a 14-period RSI from the previous bar and normalizes absolute price change using a 14-period Average True Range (ATR). Based on the normalized

Indicator v4 Oscillators & momentumVolatility & bands
Updated 4 years ago · None stated GitHub repository of Test 009 Stat Mining

Market Speedometer

by TradersPost
218 stars

Market Speedometer plots a 0-100 market speed reading in a separate pane. It measures movement by bar-to-bar change, true range, or a short average of recent bars, then ranks that movement against ATR and a percentile lookback. An EMA smooths the reading, and

Indicator v6 Volatility & bandsOscillators & momentum
Updated 3 months ago · None stated GitHub repository of Market Speedometer

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers