How to Code RSI in Pine Script: A Comprehensive Guide

As experienced Pine Script developers, we understand the importance of reliable indicators in trading. The Relative Strength Index (RSI) is a cornerstone for many technical analysts, providing insights into momentum and potential reversals. Coding it effectively in Pine Script is essential for building robust trading tools.

Introduction to RSI and Pine Script

What is RSI (Relative Strength Index)?

RSI is a momentum oscillator developed by J. Welles Wilder Jr. It measures the speed and change of price movements. It oscillates between zero and 100. Traditionally, an asset is considered overbought when the RSI is above 70 and oversold when it is below 30. These levels can vary depending on the market and specific asset.

Why Code RSI in Pine Script?

TradingView’s Pine Script is a powerful language specifically designed for writing custom indicators and strategies. Coding RSI allows you to:

  • Customize its parameters (period, overbought/oversold levels).
  • Integrate it with other indicators.
  • Build automated trading strategies based on RSI signals.
  • Visualize RSI data in unique ways on your chart.

Pine Script Environment Setup

To write Pine Script, you only need a TradingView account (free or paid). The Pine Editor is integrated directly into the platform, accessible from the chart layout. You can start writing, testing, and saving your scripts there.

Basic RSI Implementation in Pine Script

Understanding the RSI Formula

The standard RSI formula is:

RSI = 100 – [100 / (1 + RS)]

Where RS (Relative Strength) = Average Gain / Average Loss.

The average gain and average loss are typically calculated over a specified period (e.g., 14 periods) using exponential smoothing (Wilder’s smoothing). The core idea is to compare the magnitude of recent gains to recent losses.

Coding the Basic RSI Calculation

Ping Script provides built-in functions for common technical indicators, including RSI. This is the most efficient and recommended way to calculate RSI.

//@version=5
indicator("Basic RSI", shorttitle="RSI", format=format.price, precision=2, overlay=false)

// Define the RSI length as an input
rsiLength = input.int(14, title="RSI Length", minval=1)

// Calculate RSI using the built-in function
rsiValue = ta.rsi(close, rsiLength)

// Plot the RSI value on the indicator pane
plot(rsiValue, title="RSI", color=color.blue)

// Add horizontal lines for overbought and oversold levels
hline(70, title="Overbought", color=color.red, linestyle=hline.style_dashed)
hline(30, title="Oversold", color=color.green, linestyle=hline.style_dashed)
  • //@version=5: Specifies the Pine Script language version.
  • indicator(...): Declares the script as an indicator, sets its properties (name, precision, overlay). overlay=false ensures it plots in a separate pane.
  • input.int(...): Creates a numerical input control in the indicator’s settings, allowing users to easily change the RSI period.
  • ta.rsi(close, rsiLength): This is the core function call. close is the source series (current bar’s closing price), and rsiLength is the lookback period.
  • plot(...): Draws the calculated rsiValue on the chart.
  • hline(...): Adds static horizontal lines for standard overbought (70) and oversold (30) levels.

Adding RSI to Your TradingView Chart

Once you’ve written or copied the code into the Pine Editor, click “Add to Chart”. The indicator will appear in a new pane below the price chart.

Displaying RSI Values

The plot function automatically displays the line. You can also use plotchar or plotshape to mark specific conditions or label.new to add text to the chart, though for the RSI value itself, plot is standard.

Customizing Your RSI Indicator

Adjusting RSI Length/Period

Using input.int as shown in the basic example makes the length adjustable directly from the indicator’s settings panel on the chart.

// ... (previous code)

rsiLength = input.int(14, title="RSI Length", minval=1)

rsiValue = ta.rsi(close, rsiLength)

// ... (plot and hline code)

Overbought and Oversold Levels

You can make the overbought and oversold levels configurable inputs as well.

//@version=5
indicator("Customizable RSI", shorttitle="RSI Custom", format=format.price, precision=2, overlay=false)

rsiLength = input.int(14, title="RSI Length", minval=1)
ovbLevel = input.int(70, title="Overbought Level", minval=50, maxval=100)
oslLevel = input.int(30, title="Oversold Level", minval=0, maxval=50)

rsiValue = ta.rsi(close, rsiLength)

plot(rsiValue, title="RSI", color=color.blue)

hline(ovbLevel, title="Overbought", color=color.red, linestyle=hline.style_dashed)
hline(oslLevel, title="Oversold", color=color.green, linestyle=hline.style_dashed)

Adding Visual Cues (Coloring, Alerts)

You can change the plot color based on RSI value or trigger alerts.

//@version=5
indicator("RSI with Visuals", shorttitle="RSI Visual", format=format.price, precision=2, overlay=false)

rsiLength = input.int(14, title="RSI Length", minval=1)
ovbLevel = input.int(70, title="Overbought Level", minval=50, maxval=100)
oslLevel = input.int(30, title="Oversold Level", minval=0, maxval=50)

rsiValue = ta.rsi(close, rsiLength)

// Determine plot color based on levels
rsiColor = if rsiValue > ovbLevel
    color.red
else if rsiValue < oslLevel
    color.green
else
    color.blue

plot(rsiValue, title="RSI", color=rsiColor)

hline(ovbLevel, title="Overbought", color=color.red, linestyle=hline.style_dashed)
hline(oslLevel, title="Oversold", color=color.green, linestyle=hline.style_dashed)

// Example Alert Conditions
buySignal = ta.cross(rsiValue, oslLevel)
sellSignal = ta.cross(rsiValue, ovbLevel)

// Trigger alerts (requires adding the alert manually in TradingView)
alertcondition(buySignal, title="RSI Oversold Cross", message="RSI crossed below {{plot("Oversold Level")}}!") // Corrected cross logic for oversold/buy
alertcondition(sellSignal, title="RSI Overbought Cross", message="RSI crossed above {{plot("Overbought Level")}}!") // Corrected cross logic for overbought/sell

Note: ta.cross(series1, series2) returns true when series1 crosses series2. For overbought/oversold levels, you might use ta.crossunder and ta.crossover or simple comparisons (rsiValue < oslLevel[1] and rsiValue > oslLevel) depending on desired trigger.

Advanced RSI Techniques in Pine Script

RSI Divergence Detection

Detecting divergence (price making a new high/low while RSI makes a lower high/higher low) is a more advanced topic. It typically involves:

  1. Identifying potential pivot points (local highs/lows) on both price and RSI.
  2. Comparing the values and times of corresponding pivots.
  3. Confirming the divergence based on your specific criteria.

Coding this requires storing historical pivot information and implementing comparison logic. The complexity often warrants dedicated functions or modules, and handling lookback periods correctly is crucial to avoid repainting.

Smoothing RSI Values (e.g., using moving averages)

Applying a moving average to the RSI line can smooth its movement and generate signals when RSI crosses its moving average.

//@version=5
indicator("RSI Smoothed", shorttitle="RSI MA", format=format.price, precision=2, overlay=false)

rsiLength = input.int(14, title="RSI Length", minval=1)
smoothingLength = input.int(5, title="Smoothing Length", minval=1)

rsiValue = ta.rsi(close, rsiLength)
smoothedRSI = ta.sma(rsiValue, smoothingLength) // Or ta.ema(rsiValue, smoothingLength)

plot(rsiValue, title="RSI", color=color.blue, display=display.none) // Plot RSI but hide it if preferred
plot(smoothedRSI, title="Smoothed RSI", color=color.orange)

hline(70, title="Overbought", color=color.red, linestyle=hline.style_dashed)
hline(30, title="Oversold", color=color.green, linestyle=hline.style_dashed)

Combining RSI with Other Indicators

Integrating RSI with other indicators is straightforward. For example, you might require RSI to be below 30 and price to be above a long-term moving average before considering a buy signal. Simply calculate the other indicator(s) and combine the conditions using logical operators (and, or).

Troubleshooting and Best Practices

Common Errors and How to Fix Them

  • NaN values at the start: This is normal for indicators requiring historical data (like RSI). The values are undefined until enough bars have passed for the calculation period. Pine Script handles this gracefully; plots won’t appear until valid data exists.
  • Index out of bounds: Occurs when trying to access historical data that doesn’t exist (e.g., close[20] on the first bar). Ensure your code handles the initial bars correctly or uses built-in functions that manage this.
  • Repainting: This happens in scripts that use future data or non-standard lookback periods. Ensure logic relies only on completed bar data (close, high[1], etc.) or use var and if barstate.islast cautiously.

Optimizing Your Code for Performance

  • Use built-in functions: ta.rsi, ta.sma, etc., are highly optimized. Avoid reimplementing standard calculations manually with complex loops.
  • Use input.const() for static values: If an input value never changes during execution (e.g., a fixed length not intended for optimization), use input.const() for minor performance gains and clearer intent.
  • Avoid excessive loops or recursion: Pine Script is optimized for vectorized operations. Complex iterative calculations can be slow.

Backtesting and Validation

To backtest strategies based on RSI, convert your script type from indicator to strategy. Use strategy.entry, strategy.exit, strategy.close, etc., to define trading actions based on your RSI conditions.

//@version=5
strategy("RSI Simple Strategy", shorttitle="RSI Strat", overlay=true)

rsiLength = input.int(14, title="RSI Length", minval=1)
ovbLevel = input.int(70, title="Overbought Level", minval=50, maxval=100)
oslLevel = input.int(30, title="Oversold Level", minval=0, maxval=50)

rsiValue = ta.rsi(close, rsiLength)

// Strategy logic (simple crossover)
longCondition = ta.crossunder(rsiValue, oslLevel)
shortCondition = ta.crossover(rsiValue, ovbLevel)

if longCondition
    strategy.entry("Buy", strategy.long)

if shortCondition
    strategy.entry("Sell", strategy.short)

// You might add strategy.close or strategy.exit conditions here

// Plot RSI on a separate pane for visualization during backtesting
plot(rsiValue, title="RSI", color=color.blue, display=display.pane[0])

hline(ovbLevel, title="Overbought", color=color.red, linestyle=hline.style_dashed, display=display.pane[0])
hline(oslLevel, title="Oversold", color=color.green, linestyle=hline.style_dashed, display=display.pane[0])

Thorough validation is crucial. Don’t rely solely on backtest results; test your logic across different assets, timeframes, and market conditions. Consider commission, slippage, and other real-world trading costs.

Mastering RSI in Pine Script involves understanding the indicator’s mechanics, leveraging Pine Script’s built-in capabilities, and applying programming best practices to create reliable, customizable, and testable trading tools.


Leave a Reply