File size: 9,890 Bytes
8b9d246 aec6489 8b9d246 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# app.py
# Import required libraries
import streamlit as st
import yfinance as yf
from datetime import date
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
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
csv_file_path = 'ind_nifty500list.csv' # Ensure this file is uploaded to your Hugging Face Space
# Check if the file exists
if not os.path.isfile(csv_file_path):
st.error("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:
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:
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
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.")
|