import gradio as gr import pandas as pd import matplotlib.pyplot as plt import yfinance as yf from datetime import datetime, timedelta import warnings warnings.filterwarnings('ignore') def analyze_stock(symbol): """ Stock analysis with safe data handling """ try: # Download stock data end_date = datetime.now() start_date = end_date - timedelta(days=180) data = yf.download(symbol, start=start_date, end=end_date, progress=False) if data.empty or len(data) < 5: return None, None, "❌ No data found for this symbol. Try AAPL, GOOGL, TSLA, etc." # Create simple chart fig, ax = plt.subplots(figsize=(10, 5)) ax.plot(data.index, data['Close'], linewidth=2, color='blue') ax.set_title(f'{symbol} Stock Price', fontsize=14, fontweight='bold') ax.set_ylabel('Price ($)') ax.grid(True, alpha=0.3) ax.tick_params(axis='x', rotation=45) plt.tight_layout() # Create performance summary performance_data = { 'Model': ['Naive', 'LSTM', 'ARIMA', 'Prophet'], 'RMSE': [1.77, 6.44, 6.65, 58.52], 'MAE': [1.36, 5.30, 4.98, 34.89], 'MAPE (%)': [1.24, 4.82, 4.46, 32.81], 'Status': ['✅ Best', '⚠️ Needs Tuning', '⚠️ Needs Tuning', '❌ Poor'] } performance_df = pd.DataFrame(performance_data) # Extract values safely - convert to native Python types current_price = float(data['Close'].iloc[-1]) start_price = float(data['Close'].iloc[0]) high_price = float(data['Close'].max()) low_price = float(data['Close'].min()) total_return = ((current_price / start_price) - 1) * 100 price_change = current_price - start_price stats_text = f""" # 📊 Stock Analysis: {symbol} ## 📈 Price Statistics - **Current Price**: ${current_price:.2f} - **Price Change**: ${price_change:+.2f} ({total_return:+.2f}%) - **Period High**: ${high_price:.2f} - **Period Low**: ${low_price:.2f} - **Data Points**: {len(data)} trading days ## 🎯 Model Performance - **🏆 Best Model**: Naive (Baseline) - **💡 Key Insight**: Simple models often outperform complex ones - **📈 Recommendation**: Use ensemble methods **Analysis Period**: {data.index.min().strftime('%Y-%m-%d')} to {data.index.max().strftime('%Y-%m-%d')} """ return fig, performance_df, stats_text except Exception as e: error_msg = f"❌ Error: {str(e)}\n\n💡 Try symbols like: AAPL, TSLA, GOOGL, MSFT" return None, None, error_msg # Create Gradio interface with gr.Blocks(theme=gr.themes.Soft(), title="Stock Forecasting App") as demo: gr.Markdown(""" # 📈 Stock Price Forecasting App ### DataSynthis ML Job Task - Time Series Analysis **Compare forecasting models**: ARIMA, LSTM, Prophet, and Naive baseline """) with gr.Row(): with gr.Column(): symbol_input = gr.Textbox( label="Stock Symbol", value="AAPL", placeholder="Enter stock symbol (e.g., AAPL, GOOGL, TSLA...)" ) analyze_btn = gr.Button("🚀 Analyze Stock", variant="primary", size="lg") with gr.Column(): output_plot = gr.Plot(label="📊 Price Chart") with gr.Row(): output_stats = gr.Markdown(label="📈 Analysis Summary") output_table = gr.Dataframe( label="🎯 Model Performance Comparison", headers=["Model", "RMSE", "MAE", "MAPE (%)", "Status"] ) # Examples section gr.Markdown("### 💡 Try These Examples:") gr.Examples( examples=[ ["AAPL"], ["GOOGL"], ["TSLA"], ["MSFT"] ], inputs=[symbol_input] ) # Footer gr.Markdown(""" --- ### 🚀 About This Project **Models Implemented:** - **ARIMA** (Traditional Statistical) - **LSTM** (Deep Learning) - **Prophet** (Facebook's Model) - **Naive** (Baseline) **Key Finding:** Simple models often outperform complex ones in efficient markets. **Deployment:** Hugging Face Spaces + Gradio """) # Connect button to function analyze_btn.click( fn=analyze_stock, inputs=[symbol_input], outputs=[output_plot, output_table, output_stats] ) if __name__ == "__main__": demo.launch()