Calculate RSI
This example demonstrates how to fetch stock price data from Yahoo Finance using a URL endpoint that returns JSON data. We then parse the JSON data to extract the stock's timestamp and closing prices. Finally, we convert this data into a pandas DataFrame for further analysis. The timestamps are converted to human-readable datetime format.
Here we are using the %5ENSEI index, which represents NIFTY50.
import micropip import asyncio asyncio.ensure_future(micropip.install(['pandas','matplotlib']))
Fetch Data
To begin the analysis, we fetch real-time stock data from Yahoo Finance using a public API endpoint that returns data in JSON format. This endpoint provides detailed stock chart data including timestamps and various price indicators such as open, high, low, and close prices. After retrieving the JSON response, we parse it to extract the relevant fields. Specifically, we extract the list of UNIX timestamps and corresponding price values from the "quote" section. We then create a structured pandas DataFrame from this data, assigning appropriate column labels. To make the timestamps human-readable, we convert them from UNIX format to standard datetime format using pandas.to_datetime(). This cleaned and structured DataFrame serves as the foundation for subsequent financial analysis such as calculating indicators like the Relative Strength Index (RSI).
from pyodide.http import open_url import pandas as pd import json # Define dynamic parameters symbol = "%5ENSEI" # You can replace with other indices like ^NSEBANK, etc. interval = "1d" # Options: 1m, 2m, 5m, 15m, 1d, etc. range = "6mo" # Options: 1d, 5d, 1mo, 6mo, 1y, etc. # Construct the dynamic URL base_url = "https://query1.finance.yahoo.com/v8/finance/chart/" url = f"/fetch?url=https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?interval={interval}%26range={range}" # Step 2: Fetch and parse data response = open_url(url) data = response.read() parsed = json.loads(data) # Step 3: Extract time and price data chart = parsed['chart']['result'][0] timestamps = chart['timestamp'] quote = chart['indicators']['quote'][0] df = pd.DataFrame({ 'timestamp': timestamps, 'close': quote['close'], 'open': quote['open'], 'low': quote['low'], 'high': quote['high'], 'volume': quote['volume'] }) # Step 4: Convert timestamp df['timestamp'] = pd.to_datetime(df['timestamp'], unit='s') df
Calculate RSI (Relative Strength Index) Using Python
The Relative Strength Index (RSI) is a popular momentum oscillator that measures the speed and change of price movements. It ranges from 0 to 100 and helps identify overbought or oversold conditions in a stock. Values above 70 typically indicate overbought conditions, while values below 30 indicate oversold.
In the following code block, we calculate RSI using the closing prices from the DataFrame we created earlier. We calculate the price difference, separate gains and losses, compute exponential moving averages, and then apply the RSI formula.
# Calculate RSI from closing prices def calculate_rsi(prices, period=14): delta = prices.diff() gain = delta.where(delta > 0, 0) loss = -delta.where(delta < 0, 0) avg_gain = gain.rolling(window=period).mean() avg_loss = loss.rolling(window=period).mean() rs = avg_gain / avg_loss rsi = 100 - (100 / (1 + rs)) return rsi # Add RSI column to the DataFrame df['RSI'] = calculate_rsi(df['close']) # Show the DataFrame with RSI df[['timestamp', 'close', 'RSI']]
Chart
Chart with close price and rsi
import matplotlib.pyplot as plt # Create a figure with two vertically stacked subplots fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(10, 6), sharex=True) # Plot Close Price (Top) ax1.plot(df['timestamp'], df['close'], color='blue', label='Close Price') ax1.set_title('NIFTY 50 - Close Price') ax1.set_ylabel('Price') ax1.grid(True) ax1.legend(loc='upper left') # Plot RSI (Bottom) ax2.plot(df['timestamp'], df['RSI'], color='green', linestyle='--', label='RSI') ax2.axhline(70, color='red', linestyle=':', label='Overbought (70)') ax2.axhline(30, color='purple', linestyle=':', label='Oversold (30)') ax2.set_title('RSI (Relative Strength Index)') ax2.set_ylabel('RSI') ax2.set_xlabel('Time') ax2.set_ylim(0, 100) ax2.grid(True) ax2.legend(loc='upper left') # Improve layout and rotate x-axis labels plt.xticks(rotation=45) plt.tight_layout() plt