What is the Relative Strength Index?
The Relative Strength Index (RSI) on a stock is a technical indicator.
The relative strength index (RSI) is a momentum indicator used in technical analysis that measures the magnitude of recent price changes to evaluate overbought or oversold conditions in the price of a stock or other asset.https://www.investopedia.com/terms/r/rsi.asp
A technical indicator is a mathematical calculation based on past prices and volumes of a stock. The RSI has a value between 0 and 100. It is said to be overbought if above 70, and oversold if below 30.
Step 1: How to calculate the RSI
- If previous price is lower than current price, then set the values.
- U = close_now – close_previous
- D = 0
- While if the previous price is higher than current price, then set the values
- U = 0
- D = close_previous – close_now
- Calculate the Smoothed or modified moving average (SMMA) or the exponential moving average (EMA) of D and U. To be aligned with the Yahoo! Finance, I have chosen to use the (EMA).
- Calculate the relative strength (RS)
- RS = EMA(U)/EMA(D)
- Then we end with the final calculation of the Relative Strength Index (RSI).
- RSI = 100 – (100 / (1 + RSI))
Notice that the U are the price difference if positive otherwise 0, while D is the absolute value of the the price difference if negative.
Step 2: Get a stock and calculate the RSI
In this tutorial we will use Twitter as an examples, which has the TWTR ticker. It you want to do it on some other stock, then you can look up the ticker on Yahoo! Finance here.
Then below we have the following calculations.
import pandas_datareader as pdr from datetime import datetime ticker = pdr.get_data_yahoo("TWTR", datetime(2020, 1, 1)) delta = ticker['Close'].diff() up = delta.clip(lower=0) down = -1*delta.clip(upper=0) ema_up = up.ewm(com=13, adjust=False).mean() ema_down = down.ewm(com=13, adjust=False).mean() rs = ema_up/ema_down print(ticker)
To have a naming that is close to the definition and also aligned with Python, we use up for U and down for D.
This results in the following output.
High Low Open Close Volume Adj Close Date 2020-01-02 32.500000 31.959999 32.310001 32.299999 10721100 32.299999 2020-01-03 32.099998 31.260000 31.709999 31.520000 14429500 31.520000 2020-01-06 31.709999 31.160000 31.230000 31.639999 12582500 31.639999 2020-01-07 32.700001 31.719999 31.799999 32.540001 13712900 32.540001 2020-01-08 33.400002 32.349998 32.349998 33.049999 14632400 33.049999 ... ... ... ... ... ... ... 2021-10-08 64.339996 63.310001 64.250000 63.680000 8094900 63.680000 2021-10-11 63.509998 62.070000 62.990002 62.099998 9020400 62.099998 2021-10-12 62.799999 60.790001 61.680000 61.450001 9952100 61.450001 2021-10-13 62.740002 61.509998 61.959999 62.200001 9423500 62.200001 2021-10-14 63.779999 62.759998 63.009998 63.130001 3455733 63.130001
This tutorial was written 2020-08-18 (updated in 2021-10-14), and comparing with the RSI for twitter on Yahoo! Finance.
As you can see in the lower left corner, the RSI for the same ending day was 51.56 (it was measured in trading hours, so the end-of-day number is different), which fits the calculated value. Further checks reveal that they also fit the values of Yahoo.
Step 3: Visualize the RSI with the daily stock price
We will use the matplotlib library to visualize the RSI with the stock price. In this tutorial we will have two rows of graphs by using the subplots function. The function returns an array of axis (along with a figure, which we will not use).
The axis can be parsed to the Pandas DataFrame plot function.
import pandas_datareader as pdr from datetime import datetime import matplotlib.pyplot as plt ticker = pdr.get_data_yahoo("TWTR", datetime(2020, 1, 1)) delta = ticker['Close'].diff() up = delta.clip(lower=0) down = -1*delta.clip(upper=0) ema_up = up.ewm(com=13, adjust=False).mean() ema_down = down.ewm(com=13, adjust=False).mean() rs = ema_up/ema_down ticker['RSI'] = 100 - (100/(1 + rs)) # Skip first 14 days to have real values ticker = ticker.iloc[14:] print(ticker) fig, (ax1, ax2) = plt.subplots(2) ax1.get_xaxis().set_visible(False) fig.suptitle('Twitter') ticker['Close'].plot(ax=ax1) ax1.set_ylabel('Price ($)') ticker['RSI'].plot(ax=ax2) ax2.set_ylim(0,100) ax2.axhline(30, color='r', linestyle='--') ax2.axhline(70, color='r', linestyle='--') ax2.set_ylabel('RSI') plt.show()
Also, we we remove the x-axis of the first graph (ax1). Adjust the y-axis of the second graph (ax2). Also, we have set two horizontal lines to indicate overbought and oversold at 70 and 30, respectively. Notice, that Yahoo! Finance use 80 and 20 as indicators by default.