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) |