|
|
|
|
|
|
|
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 |
|
|
|
|
|
st.title('Indian Stock Data Downloader and Volume Analyzer') |
|
|
|
|
|
st.sidebar.header('Select Stocks and Options') |
|
|
|
|
|
csv_file_path = 'ind_nifty500list.csv' |
|
|
|
|
|
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: |
|
|
|
stock_df = pd.read_csv(csv_file_path) |
|
|
|
|
|
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: |
|
|
|
stock_dict = pd.Series(stock_df['Symbol'].values, index=stock_df['Company Name']).to_dict() |
|
|
|
|
|
selected_stocks = st.sidebar.multiselect('Select Stocks:', list(stock_dict.keys())) |
|
|
|
|
|
start_date = st.sidebar.date_input('Start Date', date(2021, 1, 1)) |
|
end_date = st.sidebar.date_input('End Date', date.today()) |
|
|
|
|
|
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'] |
|
) |
|
|
|
|
|
st.sidebar.header('Technical Indicators') |
|
indicators = st.sidebar.multiselect( |
|
'Select Technical Indicators to Calculate:', |
|
['OBV (Amount)', 'RSI', 'MACD'] |
|
) |
|
|
|
|
|
if st.sidebar.button('Download Data'): |
|
if selected_stocks: |
|
for company_name in selected_stocks: |
|
ticker = stock_dict[company_name] |
|
|
|
if not ticker.endswith('.NS') and not ticker.endswith('.BO'): |
|
ticker += '.NS' |
|
|
|
try: |
|
stock_data = yf.download(ticker, start=start_date, end=end_date) |
|
|
|
if stock_data.empty: |
|
st.warning(f"No data found for {company_name} ({ticker}) in the selected date range.") |
|
continue |
|
|
|
stock_data = stock_data[data_options] |
|
st.write(f"**Data for {company_name} ({ticker}):**") |
|
st.dataframe(stock_data) |
|
|
|
|
|
stock_data = stock_data.reset_index() |
|
|
|
|
|
stock_data['Amount'] = stock_data['Close'] * stock_data['Volume'] |
|
|
|
|
|
if 'OBV (Amount)' in indicators: |
|
|
|
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() |
|
|
|
|
|
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) |
|
|
|
|
|
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)) |
|
|
|
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) |
|
|
|
|
|
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'] |
|
|
|
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) |
|
|
|
|
|
stock_data['Volume_MA_5'] = stock_data['Volume'].rolling(window=5).mean() |
|
stock_data['Volume_MA_20'] = stock_data['Volume'].rolling(window=20).mean() |
|
|
|
|
|
fig, ax1 = plt.subplots(figsize=(12, 6)) |
|
|
|
|
|
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') |
|
|
|
|
|
ax2 = ax1.twinx() |
|
ax2.bar(stock_data['Date'], stock_data['Volume'], color='gray', alpha=0.3, label='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') |
|
|
|
|
|
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) |
|
|
|
|
|
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}.**") |
|
|
|
|
|
csv = stock_data.to_csv(index=False).encode('utf-8') |
|
|
|
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.") |
|
|