Spaces:
Sleeping
Sleeping
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') | |
# List of companies with their symbols | |
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(df): | |
"""Calculate technical indicators""" | |
data = df.copy() | |
# Basic metrics | |
data['Returns'] = data['Close'].pct_change() | |
data['SMA_20'] = data['Close'].rolling(window=20).mean() | |
data['SMA_50'] = data['Close'].rolling(window=50).mean() | |
# RSI | |
delta = data['Close'].diff() | |
gain = delta.clip(lower=0) | |
loss = -delta.clip(upper=0) | |
avg_gain = gain.rolling(window=14).mean() | |
avg_loss = loss.rolling(window=14).mean() | |
rs = avg_gain / avg_loss | |
data['RSI'] = 100 - (100 / (1 + rs)) | |
# Bollinger Bands | |
data['BB_middle'] = data['Close'].rolling(window=20).mean() | |
bb_std = data['Close'].rolling(window=20).std() | |
data['BB_upper'] = data['BB_middle'] + (2 * bb_std) | |
data['BB_lower'] = data['BB_middle'] - (2 * bb_std) | |
return data | |
def create_plots(data): | |
"""Create analysis plots""" | |
# Price and Volume Plot | |
fig1 = make_subplots( | |
rows=2, cols=1, | |
shared_xaxes=True, | |
vertical_spacing=0.1, | |
subplot_titles=('Price and Moving Averages', 'Volume'), | |
row_heights=[0.7, 0.3] | |
) | |
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 | |
) | |
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 Analysis Plot | |
fig2 = make_subplots( | |
rows=2, cols=1, | |
shared_xaxes=True, | |
vertical_spacing=0.1, | |
subplot_titles=('RSI', 'Bollinger Bands'), | |
row_heights=[0.5, 0.5] | |
) | |
# 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 | |
) | |
for band, color in [('BB_upper', 'gray'), ('BB_middle', 'red'), ('BB_lower', 'gray')]: | |
fig2.add_trace( | |
go.Scatter(x=data.index, y=data[band], name=band, line=dict(color=color, dash='dash')), | |
row=2, col=1 | |
) | |
fig2.update_layout(height=600, title_text="Technical Analysis") | |
return [fig1, fig2] | |
def generate_summary(data, symbol): | |
"""Generate analysis summary""" | |
try: | |
current_price = float(data['Close'].iloc[-1]) | |
prev_price = float(data['Close'].iloc[-2]) | |
daily_return = ((current_price - prev_price) / prev_price) * 100 | |
rsi = float(data['RSI'].iloc[-1]) | |
sma_20 = float(data['SMA_20'].iloc[-1]) | |
sma_50 = float(data['SMA_50'].iloc[-1]) | |
volume = float(data['Volume'].iloc[-1]) | |
bb_position = "in middle range" | |
if current_price > float(data['BB_upper'].iloc[-1] * 0.95): | |
bb_position = "near upper band (potential resistance)" | |
elif current_price < float(data['BB_lower'].iloc[-1] * 1.05): | |
bb_position = "near lower band (potential support)" | |
summary = f"""Analysis Summary for {symbol}: | |
• 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: {volume:,.0f} | |
Technical Signals: | |
• Moving Averages: Price is {"above" if current_price > sma_20 else "below"} 20-day MA | |
• Bollinger Bands: Price is {bb_position} | |
""" | |
return summary | |
except Exception as e: | |
return f"Error generating summary: {str(e)}" | |
def analyze_stock(company, lookback_days=180): | |
"""Main analysis function""" | |
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 and create analysis | |
data = calculate_metrics(data) | |
summary = generate_summary(data, symbol) | |
plots = create_plots(data) | |
return summary, plots[0], plots[1] | |
except Exception as e: | |
return f"Error analyzing stock: {str(e)}", None, None | |
def create_interface(): | |
"""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") | |
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") | |
# Event handlers | |
refresh_btn.click( | |
fn=analyze_stock, | |
inputs=[company, lookback], | |
outputs=[summary, plot1, plot2] | |
) | |
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_interface() | |
interface.launch(share=True) |