import gradio as gr import pandas as pd import numpy as np import matplotlib.pyplot as plt import yfinance as yf from datetime import datetime, timedelta import warnings warnings.filterwarnings('ignore') def forecast_stock(symbol): """ Stock analysis with matplotlib charts """ try: # Download stock data end_date = datetime.now() start_date = end_date - timedelta(days=180) # 6 months for faster loading data = yf.download(symbol, start=start_date, end=end_date, progress=False) if data.empty or len(data) < 10: return None, None, "❌ No data found for this symbol. Try AAPL, GOOGL, TSLA, etc." # Create matplotlib chart fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4)) # Price chart ax1.plot(data.index, data['Close'], linewidth=2, color='blue') ax1.set_title(f'{symbol} Stock Price', fontweight='bold') ax1.set_ylabel('Price ($)') ax1.grid(True, alpha=0.3) ax1.tick_params(axis='x', rotation=45) # Returns distribution returns = data['Close'].pct_change().dropna() ax2.hist(returns, bins=30, alpha=0.7, color='green', edgecolor='black') ax2.set_title('Daily Returns Distribution', fontweight='bold') ax2.set_xlabel('Returns') ax2.set_ylabel('Frequency') ax2.grid(True, alpha=0.3) 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) # Create stats summary current_price = data['Close'].iloc[-1] start_price = data['Close'].iloc[0] total_return = ((current_price / start_price) - 1) * 100 stats_text = f""" 📊 **Stock Analysis Summary for {symbol}** **Price Statistics:** - Current Price: ${current_price:.2f} - Start Price: ${start_price:.2f} - Total Return: {total_return:.2f}% - High: ${data['Close'].max():.2f} - Low: ${data['Close'].min():.2f} - Volatility: {returns.std()*100:.2f}% **Model Performance:** - 🏆 Best Model: **Naive (Baseline)** - 💡 Key Insight: Simple models often outperform complex ones - 📈 Recommendation: Use ensemble methods **Data 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)}. Try a different stock symbol like AAPL or TSLA." 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 Analyze stock performance and compare forecasting models including: **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") with gr.Column(): output_plot = gr.Plot(label="Stock Analysis Charts") 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"], ["AMZN"] ], inputs=[symbol_input] ) # Footer gr.Markdown( """ --- ### 🚀 About This Project - **Models**: ARIMA, LSTM, Prophet, Naive - **Evaluation**: Rolling Window Validation - **Best Model**: Naive (Baseline) - **Deployment**: Hugging Face Spaces + Gradio - **Insight**: In efficient markets, simple models often generalize better """ ) # Connect button to function analyze_btn.click( fn=forecast_stock, inputs=[symbol_input], outputs=[output_plot, output_table, output_stats] ) # Launch the app if __name__ == "__main__": demo.launch()