← Back to Home
Technical Indicators Relative Strength Index

Technical Indicators Relative Strength Index

Developed by J. Welles Wilder Jr., the Relative Strength Index (RSI) is a widely respected momentum oscillator that measures the speed and change of price movements. It operates by comparing the magnitude of recent gains to recent losses over a specified time period, typically 14 periods, to evaluate whether an asset is overbought or oversold. The RSI oscillates on a scale from 0 to 100.

The calculation of RSI involves a few steps:

  1. Calculate Average Gain and Average Loss: Over a chosen period (N), typically 14 days:

    • Identify all periods with a price increase (gain) and all periods with a price decrease (loss) compared to the previous period.
    • The initial Average Gain is the sum of all gains over the N periods divided by N.
    • The initial Average Loss is the sum of all losses over the N periods divided by N (losses are taken as positive values).
    • Subsequent calculations typically use a smoothed average:
      • Average Gain = [(Previous Average Gain) * (N-1) + Current Gain] / N
      • Average Loss = [(Previous Average Loss) * (N-1) + Current Loss] / N
  2. Calculate Relative Strength (RS): The RS is the ratio of the Average Gain to the Average Loss. RS = \frac{\text{Average Gain over N periods}}{\text{Average Loss over N periods}} Note: Wilder initially smoothed RS using a Wilder’s smoothing method, which is similar to an exponential moving average.

  3. Calculate RSI: The RSI is then normalized to oscillate between 0 and 100 using the following formula: RSI = 100 - \frac{100}{1 + RS} If the Average Loss is zero (meaning prices only went up or stayed flat for N periods), RS becomes infinite, and RSI is 100. Conversely, if the Average Gain is zero, RS is zero, and RSI is 0.

Usage: The RSI provides several ways to interpret market momentum:

TA-Lib Function: The Technical Analysis Library (TA-Lib) provides a convenient function for calculating RSI:

talib.RSI(close_prices, timeperiod=14)

Code Example (Calculation & Plot with yfinance Data):

The following Python code demonstrates how to fetch stock data using yfinance, calculate the RSI, and then plot the price along with the RSI indicator, including the typical overbought, oversold, and midpoint lines.

import yfinance as yf
import talib
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# --- 1. Data Fetching using yfinance ---
ticker_symbol = "AAPL" # Example: Apple Inc.
data = yf.download(ticker_symbol, start="2023-01-01", end="2024-05-01", auto_adjust=False, progress=False)

if data.empty:
    print(f"No data found for {ticker_symbol}. Exiting.")
else:
    # Complying with user preference for droplevel
    if isinstance(data.columns, pd.MultiIndex):
        data.columns = data.columns.droplevel(level=1)

    close_prices = data['Close'].dropna()
    date_index = close_prices.index

    # --- 2. RSI Calculation ---
    time_period_rsi = 14 # Standard period for RSI

    # RSI needs N periods + initial data for smoothing.
    # TA-Lib handles the initial NaN values.
    if len(close_prices) > time_period_rsi:
        rsi_values = talib.RSI(close_prices, timeperiod=time_period_rsi)
        indicator_name = f"RSI({time_period_rsi})"
        print(f"\n--- {indicator_name} - Relative Strength Index for {ticker_symbol} ---")

        valid_rsi = rsi_values[~np.isnan(rsi_values)]
        if len(valid_rsi) >= 5:
            print(f"Output {indicator_name} (last 5 valid): {valid_rsi[-5:].round(2)}")
        elif len(valid_rsi) > 0:
            print(f"Output {indicator_name} (all valid): {valid_rsi.round(2)}")
        else:
            print(f"Output {indicator_name}: No valid RSI values calculated.")

        # --- 3. Plotting ---
        fig, axes = plt.subplots(2, 1, figsize=(14, 10), sharex=True,
                                 gridspec_kw={'height_ratios': [3, 1]}) # Price chart 3x taller

        # Plot Price
        axes[0].plot(date_index, close_prices, label='Close Price', color='blue')
        axes[0].set_title(f'{ticker_symbol} Price and {indicator_name}')
        axes[0].set_ylabel('Price')
        axes[0].legend(loc='upper left')
        axes[0].grid(True)

        # Plot RSI
        axes[1].plot(date_index, rsi_values, label=indicator_name, color='purple')
        axes[1].axhline(70, color='red', linestyle='--', linewidth=0.8, label='Overbought (70)')
        axes[1].axhline(50, color='gray', linestyle='--', linewidth=0.8, label='Midpoint (50)')
        axes[1].axhline(30, color='green', linestyle='--', linewidth=0.8, label='Oversold (30)')
        axes[1].set_ylim(0, 100) # RSI oscillates between 0 and 100
        axes[1].set_ylabel('RSI Value')
        axes[1].set_xlabel('Date')
        axes[1].legend(loc='upper left')
        axes[1].grid(True)

        plt.tight_layout() # Adjust layout to prevent overlap
        plt.show()

    else:
        print(f"\nSkipping RSI plot for {ticker_symbol}: Insufficient data (need > {time_period_rsi} points).")
        if not data.empty:
             print(f"Data available from {data.index.min().date()} to {data.index.max().date()}.")
Pasted image 20250602193552.png

Explanation of the Code:

  1. Import Libraries: Essential libraries like yfinance, talib, numpy, matplotlib.pyplot, and pandas are imported.
  2. Data Fetching:
    • yf.download() fetches historical data for the specified ticker_symbol (e.g., “AAPL”). User preferences auto_adjust=False and droplevel are applied.
    • close_prices are extracted.
  3. RSI Calculation:
    • time_period_rsi is set (typically 14).
    • talib.RSI() calculates the RSI values. TA-Lib will output NaN for the initial periods where there’s not enough data.
    • The last few valid RSI values are printed.
  4. Plotting:
    • plt.subplots(2, 1, ...) creates a figure with two subplots stacked vertically (2 rows, 1 column). sharex=True links the x-axes. gridspec_kw allows resizing the subplots.
    • Price Plot (axes[0]): The top subplot displays the closing prices.
    • RSI Plot (axes[1]): The bottom subplot displays the RSI.
      • axhline() is used to draw horizontal lines at the 70 (overbought), 50 (midpoint), and 30 (oversold) levels, making it easier to identify these key thresholds.
      • set_ylim(0, 100) ensures the y-axis for RSI is scaled correctly.
    • Titles, labels, and legends are added for clarity.
    • plt.tight_layout() adjusts subplot parameters for a tight layout.
    • plt.show() displays the chart.
  5. Insufficient Data Handling: If data is insufficient, a message is printed.

The RSI is a versatile indicator that, when used correctly and often in conjunction with other analytical tools, can provide valuable insights into market psychology and potential price movements.