riteshcp's picture
Update app.py
88b1a24 verified
# app.py
# Import required libraries
import streamlit as st
import yfinance as yf
from datetime import date, timedelta
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import io
# Optional: Install 'ta' library for technical indicators (uncomment if needed)
# !pip install ta
# Set Streamlit page configuration
st.set_page_config(
page_title='📈 Indian Stock Data Downloader and Volume Analyzer',
layout='wide',
initial_sidebar_state='expanded'
)
# Set the title of the app
st.title('📈 Indian Stock Data Downloader and Volume Analyzer')
# Sidebar for user inputs
st.sidebar.header('🔧 Configuration')
# File uploader for 'stock_list.csv'
uploaded_file = st.sidebar.file_uploader(
"📂 Upload your stock list CSV",
type=["csv"],
help="The CSV file should contain 'Symbol' and 'Company Name' columns."
)
if uploaded_file is not None:
try:
# Read the uploaded CSV file into a DataFrame
stock_df = pd.read_csv(uploaded_file)
# 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: {', '.join(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:',
options=list(stock_dict.keys()),
default=list(stock_dict.keys())[:5] # Select first 5 stocks by default
)
# Date input widgets for date range selection
default_start_date = date.today() - timedelta(days=365) # Past year
start_date = st.sidebar.date_input('📅 Start Date', default_start_date)
end_date = st.sidebar.date_input('📅 End Date', date.today())
# Ensure that start_date is before end_date
if start_date > end_date:
st.sidebar.error("❌ Start Date must be before End Date.")
# 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 and Analyze Data button
if st.sidebar.button('📥 Download and Analyze Data'):
if selected_stocks:
for company_name in selected_stocks:
ticker = stock_dict[company_name]
# Append '.NS' or '.BO' for NSE or BSE stocks if not already present
if not (ticker.endswith('.NS') or ticker.endswith('.BO')):
# Default to NSE; modify as needed
ticker += '.NS'
# Fetch data from Yahoo Finance
try:
with st.spinner(f"⏳ Fetching data for {company_name} ({ticker})..."):
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
available_options = [option for option in data_options if option in stock_data.columns]
if not available_options:
st.warning(f"No selected data options available for **{company_name}** ({ticker}).")
continue
stock_data = stock_data[available_options]
st.subheader(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) if 'Close' and 'Volume' are selected
if 'Close' in stock_data.columns and 'Volume' in stock_data.columns:
stock_data['Amount'] = stock_data['Close'] * stock_data['Volume']
else:
stock_data['Amount'] = np.nan
# OBV in terms of Amount
if 'OBV (Amount)' in indicators and 'Amount' in stock_data.columns:
# 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 and 'Close' in stock_data.columns:
delta = stock_data['Close'].diff()
up = delta.clip(lower=0)
down = -1 * delta.clip(upper=0)
roll_up = up.rolling(window=14).mean()
roll_down = down.rolling(window=14).mean()
RS = roll_up / roll_down
stock_data['RSI'] = 100.0 - (100.0 / (1.0 + RS))
# 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 and 'Close' in stock_data.columns:
exp1 = stock_data['Close'].ewm(span=12, adjust=False).mean()
exp2 = stock_data['Close'].ewm(span=26, adjust=False).mean()
stock_data['MACD'] = exp1 - exp2
stock_data['MACD_Signal'] = stock_data['MACD'].ewm(span=9, adjust=False).mean()
stock_data['MACD_Hist'] = stock_data['MACD'] - stock_data['MACD_Signal']
# Plot MACD
fig_macd, ax = plt.subplots(figsize=(12, 4))
ax.plot(stock_data['Date'], stock_data['MACD'], label='MACD', color='purple')
ax.plot(stock_data['Date'], stock_data['MACD_Signal'], label='Signal', color='red')
ax.bar(stock_data['Date'], stock_data['MACD_Hist'], 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 for Volume if 'Volume' is selected
if 'Volume' in stock_data.columns:
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'
)
else:
st.warning("⚠️ Please select at least one stock.")
except Exception as e:
st.error(f"❌ Error processing the uploaded file: {e}")
else:
st.info("🔍 Please upload your `stock_list.csv` file to get started.")
st.markdown("""
**Sample `stock_list.csv` Format:**
```csv
Symbol,Company Name
TCS,Tata Consultancy Services
INFY,Infosys Limited
RELIANCE,Reliance Industries
HDFCBANK,HDFC Bank
ICICIBANK,ICICI Bank
```
You can create your own CSV file following the above format. Ensure that the CSV has headers `Symbol` and `Company Name`.
**Sample CSV Download:**
[Download Sample `stock_list.csv`](https://huggingface.co/spaces/riteshcp/Indian_Futures_OBV_Downloader/resolve/main/sample_stock_list.csv)
""")