arjunanand13's picture
Update app.py
8dbdb70 verified
raw
history blame
7.39 kB
import gradio as gr
import yfinance as yf
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')
COMPANIES = {
'Apple (AAPL)': 'AAPL',
'Microsoft (MSFT)': 'MSFT',
'Amazon (AMZN)': 'AMZN',
'Google (GOOGL)': 'GOOGL',
'Meta (META)': 'META',
'Tesla (TSLA)': 'TSLA',
'NVIDIA (NVDA)': 'NVDA',
'JPMorgan Chase (JPM)': 'JPM',
'Johnson & Johnson (JNJ)': 'JNJ',
'Walmart (WMT)': 'WMT',
'Visa (V)': 'V',
'Mastercard (MA)': 'MA',
'Procter & Gamble (PG)': 'PG',
'UnitedHealth (UNH)': 'UNH',
'Home Depot (HD)': 'HD',
'Bank of America (BAC)': 'BAC',
'Coca-Cola (KO)': 'KO',
'Pfizer (PFE)': 'PFE',
'Disney (DIS)': 'DIS',
'Netflix (NFLX)': 'NFLX'
}
def calculate_metrics(data: pd.DataFrame) -> pd.DataFrame:
df = data.copy()
# Basic metrics
df['Returns'] = df['Close'].pct_change()
df['SMA_20'] = df['Close'].rolling(window=20).mean()
df['SMA_50'] = df['Close'].rolling(window=50).mean()
# RSI
delta = df['Close'].diff()
gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
rs = gain / loss
df['RSI'] = 100 - (100 / (1 + rs))
# Bollinger Bands
df['BB_middle'] = df['Close'].rolling(window=20).mean()
bb_std = df['Close'].rolling(window=20).std()
df['BB_upper'] = df['BB_middle'] + (2 * bb_std)
df['BB_lower'] = df['BB_middle'] - (2 * bb_std)
return df
def create_analysis_plots(data: pd.DataFrame) -> list:
# Price and Volume Plot
fig1 = make_subplots(rows=2, cols=1, shared_xaxes=True,
subplot_titles=('Price and Moving Averages', 'Volume'),
row_heights=[0.7, 0.3],
vertical_spacing=0.1)
# Price and SMAs
fig1.add_trace(
go.Scatter(x=data.index, y=data['Close'], name='Close', line=dict(color='blue')),
row=1, col=1
)
fig1.add_trace(
go.Scatter(x=data.index, y=data['SMA_20'], name='SMA 20', line=dict(color='orange', dash='dash')),
row=1, col=1
)
fig1.add_trace(
go.Scatter(x=data.index, y=data['SMA_50'], name='SMA 50', line=dict(color='green', dash='dash')),
row=1, col=1
)
# Volume
fig1.add_trace(
go.Bar(x=data.index, y=data['Volume'], name='Volume', marker_color='lightblue'),
row=2, col=1
)
fig1.update_layout(height=600, title_text="Price Analysis")
# Technical Indicators Plot
fig2 = make_subplots(rows=2, cols=1, shared_xaxes=True,
subplot_titles=('RSI', 'Bollinger Bands'),
row_heights=[0.5, 0.5],
vertical_spacing=0.1)
# RSI
fig2.add_trace(
go.Scatter(x=data.index, y=data['RSI'], name='RSI', line=dict(color='purple')),
row=1, col=1
)
fig2.add_hline(y=70, line_dash="dash", line_color="red", row=1, col=1)
fig2.add_hline(y=30, line_dash="dash", line_color="green", row=1, col=1)
# Bollinger Bands
fig2.add_trace(
go.Scatter(x=data.index, y=data['Close'], name='Close', line=dict(color='blue')),
row=2, col=1
)
fig2.add_trace(
go.Scatter(x=data.index, y=data['BB_upper'], name='Upper BB',
line=dict(color='gray', dash='dash')),
row=2, col=1
)
fig2.add_trace(
go.Scatter(x=data.index, y=data['BB_middle'], name='Middle BB',
line=dict(color='red', dash='dash')),
row=2, col=1
)
fig2.add_trace(
go.Scatter(x=data.index, y=data['BB_lower'], name='Lower BB',
line=dict(color='gray', dash='dash')),
row=2, col=1
)
fig2.update_layout(height=600, title_text="Technical Analysis")
return [fig1, fig2]
def generate_summary(data: pd.DataFrame) -> str:
current_price = data['Close'].iloc[-1]
prev_price = data['Close'].iloc[-2]
daily_return = ((current_price - prev_price) / prev_price) * 100
rsi = data['RSI'].iloc[-1]
sma_20 = data['SMA_20'].iloc[-1]
sma_50 = data['SMA_50'].iloc[-1]
summary = f"""Market Analysis Summary:
• Current Price: ${current_price:.2f}
• Daily Change: {daily_return:+.2f}%
• Trend: {'Bullish' if sma_20 > sma_50 else 'Bearish'} (20-day MA vs 50-day MA)
• RSI: {rsi:.2f} ({'Overbought' if rsi > 70 else 'Oversold' if rsi < 30 else 'Neutral'})
• Volume: {data['Volume'].iloc[-1]:,.0f}
Technical Signals:
• Moving Averages: Price is {'above' if current_price > sma_20 else 'below'} 20-day MA
• Bollinger Bands: Price is {
'near upper band (potential resistance)' if current_price > data['BB_upper'].iloc[-1] * 0.95
else 'near lower band (potential support)' if current_price < data['BB_lower'].iloc[-1] * 1.05
else 'in middle range'}
"""
return summary
def analyze_stock(company: str, lookback_days: int = 180) -> tuple:
try:
symbol = COMPANIES[company]
end_date = datetime.now()
start_date = end_date - timedelta(days=lookback_days)
# Download data
data = yf.download(symbol, start=start_date, end=end_date)
if len(data) == 0:
return "No data available for the selected period.", None, None
# Calculate metrics
data = calculate_metrics(data)
# Generate analysis
summary = generate_summary(data)
plots = create_analysis_plots(data)
return summary, plots[0], plots[1]
except Exception as e:
return f"Error analyzing stock: {str(e)}", None, None
def refresh_analysis(company, lookback_days):
return analyze_stock(company, lookback_days)
def create_gradio_interface():
with gr.Blocks() as interface:
gr.Markdown("# Stock Market Analysis Dashboard")
with gr.Row():
company = gr.Dropdown(
choices=list(COMPANIES.keys()),
label="Select Company",
value="Apple (AAPL)"
)
lookback = gr.Slider(
minimum=30,
maximum=365,
value=180,
step=1,
label="Lookback Period (days)"
)
refresh_btn = gr.Button("Refresh Analysis")
with gr.Row():
summary = gr.Textbox(label="Analysis Summary", lines=10)
with gr.Row():
plot1 = gr.Plot(label="Price Analysis")
plot2 = gr.Plot(label="Technical Analysis")
refresh_btn.click(
fn=refresh_analysis,
inputs=[company, lookback],
outputs=[summary, plot1, plot2]
)
# Also trigger analysis when company or lookback period changes
company.change(
fn=analyze_stock,
inputs=[company, lookback],
outputs=[summary, plot1, plot2]
)
lookback.release(
fn=analyze_stock,
inputs=[company, lookback],
outputs=[summary, plot1, plot2]
)
return interface
if __name__ == "__main__":
interface = create_gradio_interface()
interface.launch(share=True)