Skip to main content

RSI Indicator: Relative Strength Index in a JavaScript or React Financial Chart

The RSI (Relative Strength Index) is one of the most widely used technical indicators. This page explains what the RSI indicator is, how it is calculated and how traders read it, and shows how to add an RSI indicator to a JavaScript or React financial chart with SciTrader.js's RSIStudy, with live examples you can edit in CodePen.

info

The RSI is one of the 32 built-in technical indicators and studies in the SciTrader SDK. For the full list, with each one's options and defaults, see Every Built-in Indicator and Study. To add and remove any of them, or build an indicator picker, see Add Technical Indicators to a Financial Chart.

What Is the RSI Indicator?​

The RSI is a momentum oscillator, developed by J. Welles Wilder Jr. It measures how strongly price has been rising compared to how strongly it has been falling over recent candles, on a scale from 0 to 100:

  • Near 100, the recent rises have far outweighed the falls.
  • Near 0, the recent falls have far outweighed the rises.
  • Around 50, rises and falls have been about even.

Because it has its own 0–100 scale, a chart draws the RSI in a pane of its own below the price chart, usually with lines at 70 and 30.

How Is the RSI Calculated?​

The RSI compares the average gain to the average loss over length candles, 14 by default:

  1. Gains and losses. For each candle, the change is its close minus the previous close. A positive change is a gain (and a loss of 0); a negative change is a loss, as a positive number (and a gain of 0).

  2. First averages. The first average gain is the simple average of the first length gains, and the same for losses.

  3. Wilder smoothing. Each later average carries most of the previous one forward:

    averageGaint=averageGaint−1×(n−1)+gaintnaverageLosst=averageLosst−1×(n−1)+losstn\begin{aligned} \text{averageGain}_t &= \frac{\text{averageGain}_{t-1} \times (n - 1) + \text{gain}_t}{n} \\ \text{averageLoss}_t &= \frac{\text{averageLoss}_{t-1} \times (n - 1) + \text{loss}_t}{n} \end{aligned}

    where nn is length.

  4. RS and RSI. RS is the average gain divided by the average loss, and

    RS=averageGainaverageLossRSI=100−1001+RSRS = \frac{\text{averageGain}}{\text{averageLoss}} \qquad RSI = 100 - \frac{100}{1 + RS}

    When there have been no losses at all, RSI is 100.

So the RSI has no value for the first length candles. SciTrader loads that many extra candles to the left of the visible period, so the line starts at the left edge of the chart.

How to Read the RSI​

These are the common readings. They are conventions traders use, not signals that hold every time:

  • Overbought and oversold. Above 70 is commonly read as overbought: price has risen fast and may pause or pull back. Below 30 is read as oversold. In strong trends the RSI can stay overbought or oversold for a long time.
  • The 50 line. An RSI holding above 50 suggests upward momentum; below 50, downward momentum.
  • Divergence. When price makes a new high but the RSI makes a lower high, momentum is fading behind the move. The same applies to lows.

Some traders use 80 and 20 for fewer, stronger readings, or a shorter length, such as 7, for a faster, noisier RSI.

How to Add an RSI Indicator to a JavaScript Financial Chart​

Add an RSIStudy to the chart's studies. The example below is a BTC-USD chart from Coinbase, with a 14-candle RSI in its own pane, overbought and oversold levels at 70 and 30, and the RSI filled where it crosses them.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
OHLCStudy,
RSIStudy,
SciFinanceChartPanel,
VolumeStudy,
} from "scichart-scitrader";

// This example expects this HTML:
// <div id="chart" style="height: 100%"></div>

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

async function createChart() {
// A financial chart is a SciFinanceChartPanel. Its indicators are studies, passed in `studies`
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById("chart"), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [
new OHLCStudy(), // the price series, as candlesticks
new VolumeStudy(), // volume, along the bottom of the price pane
// RSI: an oscillator, so it gets a pane of its own below the price pane, scaled 0 to 100.
// length: candles in the average gain and loss (default 14).
// overbought / oversold: the levels drawn as dashed lines, with the RSI filled beyond them
new RSIStudy({
length: 14,
overbought: 70,
oversold: 30,
renderOptions: { stroke: "#ff9f1c", strokeThickness: 2 }, // the RSI line
}),
],
});

// When the page goes away: financeChartPanel.cleanup();
return financeChartPanel;
}

createChart();

How to Add an RSI Indicator to a React Financial Chart​

In React, pass the same studies in the config of SciFinanceChartView, from scichart-scitrader-react. Create them in a useMemo, once per mounted chart: a study is a live object, bound to one chart.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import * as React from "react";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
ISciFinanceChartPanelConfig,
OHLCStudy,
RSIStudy,
VolumeStudy,
} from "scichart-scitrader";
import { SciFinanceChartView } from "scichart-scitrader-react";

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

export function RsiChart() {
// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [
new OHLCStudy(), // the price series, as candlesticks
new VolumeStudy(), // volume, along the bottom of the price pane
// RSI: an oscillator, so it gets a pane of its own below the price pane, scaled 0 to 100.
// length: candles in the average gain and loss (default 14).
// overbought / oversold: the levels drawn as dashed lines, with the RSI filled beyond them
new RSIStudy({
length: 14,
overbought: 70,
oversold: 30,
renderOptions: { stroke: "#ff9f1c", strokeThickness: 2 }, // the RSI line
}),
],
}),
[]
);

// SciFinanceChartView fills its parent, so give the parent a height
return <SciFinanceChartView config={config} />;
}

Adding and Removing the RSI Indicator at Runtime​

RSIStudy is a study like any other, so you can add it to a chart that is already showing, and remove it again:

import { EStudyType, RSIStudy, studyProvider } from "scichart-scitrader";

const chart = financeChartPanel.financeApi;

// Add one with your own settings...
const study = new RSIStudy();
await chart.attachStudy(study);

// ...or by type, with the default settings, e.g. from an indicator picker
await chart.attachStudy(studyProvider.getStudy(EStudyType.RSI));

// Remove it
chart.detachStudy(study);

See Add Technical Indicators to a Financial Chart for more, including a ready-made indicator picker.

RSIStudy Options and Settings​

OptionDefaultWhat it does
length14Candles in the average gain and loss
overbought70The upper level, drawn as a dashed line
oversold30The lower level, drawn as a dashed line
thresholdFills"show""show" fills the RSI beyond the levels; "hide" doesn't
overboughtFill, oversoldFillThe theme's coloursThe fill colours beyond each level
renderOptionsThe theme's coloursThe RSI line: stroke, strokeThickness, strokeDashArray
paneIdA new paneThe pane to draw in

Users can change the same settings in the Settings Form, and you can change them from code with applyDescriptor. There, length is named period:

StudyInputsStyles
RSIStudyperiod, overbought, oversoldstrokeColor, strokeThickness, strokeStyle, thresholdFills, overboughtFill, oversoldFill
The RSIStudy class, with its TSDoc
class RSIStudy extends StudyBase<number> {
/** Indicator pane — small relative weight (price pane defaults to 3×). */
readonly paneSizeConfig: {
grow: number;
};
length: number;
readonly renderOptions: IFastLineRenderableSeriesOptions;
inputId: DataSourceId;
overbought: number;
oversold: number;
overboughtFill: string;
oversoldFill: string;
thresholdFills: TRsiThresholdFills;
getRequiredWarmup(): number;
constructor(options?: IRsiOptions);
/**
* Re-instantiate options from an edited descriptor — used by the
* studies-edit menu's apply flow via `studyProvider.getStudy`.
*/
static getOptionsFromDescriptor(descriptor: TStudyDescriptor): IRsiOptions;
/** Opts in to the in-place apply pipeline — see {@link onDescriptorApplied}. */
get supportsLiveApply(): boolean;
createInputOutputIds(): void;
createDataSeries(): void;
createAxes(): AxisBase2D[];
/**
* The fills come before the line so they draw behind it: a surface paints its series in
* collection order.
*/
createRenderableSeries(): IRenderableSeries[];
/** The line's stroke. The default reads it only off a study with one series, and RSI has three. */
getLegendColor(_outputId: DataSourceId, _xIndex?: number): string | undefined;
createAnnotation(): void;
}
The IRsiOptions interface, with its TSDoc
type TRsiThresholdFills = "show" | "hide";
interface IRsiOptions extends IStudyOptions {
inputId?: DataSourceId;
length?: number;
renderOptions?: IFastLineRenderableSeriesOptions;
/** Upper reference level. Defaults to 70. */
overbought?: number;
/** Lower reference level. Defaults to 30. */
oversold?: number;
/** Fill between the level and the line where RSI is above {@link overbought}. */
overboughtFill?: string;
/** Fill between the level and the line where RSI is below {@link oversold}. */
oversoldFill?: string;
thresholdFills?: TRsiThresholdFills;
}