riteshcp's picture
Update app.py
7274f0a verified
raw
history blame
9.32 kB
# app.py
# Import required libraries
import streamlit as st
import yfinance as yf
from datetime import date
import pandas as pd
import matplotlib.pyplot as plt
import pandas_ta as ta # For technical indicators
import os
# Set the title of the app
st.title('Indian Stock Data Downloader and Volume Analyzer')
# Sidebar for user inputs
st.sidebar.header('Select Stocks and Options')
# Path to your CSV file (adjusted for HF)
csv_file_path = 'stock_list.csv' # Ensure this file is uploaded to HF
# Check if the file exists
if not os.path.isfile(csv_file_path):
st.error(f"The stock list file was not found. Please upload 'stock_list.csv' to your app.")
else:
# Read the CSV file into a DataFrame
stock_df = pd.read_csv(csv_file_path)
# Ensure that the required columns are present
required_columns = {'Symbol', 'Company Name'}
if not required_columns.issubset(stock_df.columns):
st.error(f"The CSV file must contain the following columns: {required_columns}")
else:
# Create a dictionary mapping company names to stock symbols
stock_dict = pd.Series(stock_df['Symbol'].values, index=stock_df['Company Name']).to_dict()
# Multiselect widget for stock selection
selected_stocks = st.sidebar.multiselect('Select Stocks:', list(stock_dict.keys()))
# Date input widgets for date range selection
start_date = st.sidebar.date_input('Start Date', date(2021, 1, 1))
end_date = st.sidebar.date_input('End Date', date.today())
# Checkbox for selecting data options
st.sidebar.header('Data Options')
data_options = st.sidebar.multiselect(
'Select Data to Download:',
['Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'],
default=['Open', 'High', 'Low', 'Close', 'Volume']
)
# Technical Indicators selection
st.sidebar.header('Technical Indicators')
indicators = st.sidebar.multiselect(
'Select Technical Indicators to Calculate:',
['OBV (Amount)', 'RSI', 'MACD']
)
# Download button
if st.sidebar.button('Download Data'):
if selected_stocks:
for company_name in selected_stocks:
ticker = stock_dict[company_name]
# Append '.NS' if not already present for NSE stocks
if not ticker.endswith('.NS') and not ticker.endswith('.BO'):
ticker += '.NS'
# Fetch data from Yahoo Finance
try:
stock_data = yf.download(ticker, start=start_date, end=end_date)
# Check if data is returned
if stock_data.empty:
st.warning(f"No data found for {company_name} ({ticker}) in the selected date range.")
continue
# Filter data based on selected options
stock_data = stock_data[data_options]
st.write(f"**Data for {company_name} ({ticker}):**")
st.dataframe(stock_data)
# Reset index to get 'Date' as a column
stock_data = stock_data.reset_index()
# Calculate Amount (Close * Volume)
stock_data['Amount'] = stock_data['Close'] * stock_data['Volume']
# OBV in terms of Amount
if 'OBV (Amount)' in indicators:
# Calculate direction
stock_data['Daily_Return'] = stock_data['Close'].pct_change()
stock_data['Direction'] = stock_data['Daily_Return'].apply(lambda x: 1 if x > 0 else (-1 if x < 0 else 0))
stock_data['OBV_Amount'] = (stock_data['Amount'] * stock_data['Direction']).cumsum()
# Plot OBV in Amount
fig_obv_amount, ax = plt.subplots(figsize=(12, 4))
ax.plot(stock_data['Date'], stock_data['OBV_Amount'], label='OBV (Amount)', color='orange')
ax.set_xlabel('Date')
ax.set_ylabel('On-Balance Volume (Amount)')
ax.set_title(f"{company_name} OBV (Amount)")
ax.legend()
st.pyplot(fig_obv_amount)
# RSI
if 'RSI' in indicators:
stock_data['RSI'] = ta.rsi(stock_data['Close'], length=14)
# Plot RSI
fig_rsi, ax = plt.subplots(figsize=(12, 4))
ax.plot(stock_data['Date'], stock_data['RSI'], label='RSI', color='green')
ax.set_xlabel('Date')
ax.set_ylabel('RSI')
ax.set_title(f"{company_name} RSI")
ax.axhline(70, color='red', linestyle='--')
ax.axhline(30, color='blue', linestyle='--')
ax.legend()
st.pyplot(fig_rsi)
# MACD
if 'MACD' in indicators:
macd = ta.macd(stock_data['Close'])
stock_data = pd.concat([stock_data, macd], axis=1)
# Plot MACD
fig_macd, ax = plt.subplots(figsize=(12, 4))
ax.plot(stock_data['Date'], stock_data['MACD_12_26_9'], label='MACD', color='purple')
ax.plot(stock_data['Date'], stock_data['MACDs_12_26_9'], label='Signal', color='red')
ax.bar(stock_data['Date'], stock_data['MACDh_12_26_9'], label='Histogram', color='grey')
ax.set_xlabel('Date')
ax.set_ylabel('MACD')
ax.set_title(f"{company_name} MACD")
ax.legend()
st.pyplot(fig_macd)
# Calculate moving averages
stock_data['Volume_MA_5'] = stock_data['Volume'].rolling(window=5).mean()
stock_data['Volume_MA_20'] = stock_data['Volume'].rolling(window=20).mean()
# Plotting price and volume
fig, ax1 = plt.subplots(figsize=(12, 6))
# Plot the closing price
ax1.plot(stock_data['Date'], stock_data['Close'], color='blue', label='Close Price')
ax1.set_xlabel('Date')
ax1.set_ylabel('Close Price', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
# Create a second y-axis for volume
ax2 = ax1.twinx()
ax2.bar(stock_data['Date'], stock_data['Volume'], color='gray', alpha=0.3, label='Volume')
# Plot moving averages of volume
ax2.plot(stock_data['Date'], stock_data['Volume_MA_5'], color='red', label='5-Day MA')
ax2.plot(stock_data['Date'], stock_data['Volume_MA_20'], color='green', label='20-Day MA')
ax2.set_ylabel('Volume', color='gray')
ax2.tick_params(axis='y', labelcolor='gray')
# Add legends and title
fig.legend(loc='upper left', bbox_to_anchor=(0.15, 0.85))
plt.title(f"{company_name} Price and Volume Chart with Moving Averages")
fig.tight_layout()
st.pyplot(fig)
# Volume analysis
stock_data['Volume_Pct_Change'] = stock_data['Volume'].pct_change() * 100
average_volume = stock_data['Volume'].mean()
current_volume = stock_data['Volume'].iloc[-1]
volume_trend = 'increasing' if current_volume > average_volume else 'decreasing'
st.subheader(f"Volume Analysis for {company_name}")
st.write(f"- **Average Volume:** {average_volume:,.0f}")
st.write(f"- **Current Volume:** {current_volume:,.0f}")
st.write(f"- **Volume is currently {volume_trend}.**")
# Convert data to CSV
csv = stock_data.to_csv(index=False).encode('utf-8')
# Download button for CSV
st.download_button(
label=f"Download {company_name} Data as CSV",
data=csv,
file_name=f"{ticker}_{start_date}_{end_date}.csv",
mime='text/csv'
)
except Exception as e:
st.error(f"Error fetching data for {company_name} ({ticker}): {e}")
else:
st.warning("Please select at least one stock.")