Spaces:
Sleeping
Sleeping
Download app.py from JaagYS/Stock_Prediction: direct link, hf CLI and curl.
- Browser
- Download file 7.08 kB
-
https://huggingface.co/spaces/JaagYS/Stock_Prediction/resolve/main/app.py
- Command line
-
hf download hf://spaces/JaagYS/Stock_Prediction/app.py
-
curl -L -o app.py https://huggingface.co/spaces/JaagYS/Stock_Prediction/resolve/main/app.py
7.08 kB
| import gradio as gr | |
| import numpy as np | |
| import tensorflow as tf | |
| from tensorflow import keras | |
| import yfinance as yf | |
| import pandas as pd | |
| from datetime import datetime, timedelta | |
| # Load the model | |
| model = keras.models.load_model('gru_model.h5') | |
| def prepare_data(df): | |
| """ | |
| Prepare stock data for the model - using percentage changes | |
| Expected features: Open, High, Low, Close, Volume | |
| """ | |
| # Select required columns | |
| features = ['Open', 'High', 'Low', 'Close', 'Volume'] | |
| data = df[features].copy() | |
| # Calculate percentage changes for prices (more stable normalization) | |
| price_cols = ['Open', 'High', 'Low', 'Close'] | |
| for col in price_cols: | |
| data[col] = data[col].pct_change().fillna(0) | |
| # Normalize volume using rolling window | |
| data['Volume'] = (data['Volume'] - data['Volume'].rolling(20, min_periods=1).mean()) / data['Volume'].rolling(20, min_periods=1).std() | |
| data['Volume'] = data['Volume'].fillna(0) | |
| # Clip extreme values to prevent outliers | |
| data = data.clip(-3, 3) | |
| return data.values, df['Close'].values | |
| def predict_stock_symbol(symbol, days_to_predict=10): | |
| """ | |
| Fetch stock data and make prediction with proper price conversion | |
| """ | |
| try: | |
| # Clean symbol | |
| symbol = symbol.strip().upper() | |
| # Fetch stock data (get more than 60 days to ensure we have enough) | |
| end_date = datetime.now() | |
| start_date = end_date - timedelta(days=120) # Get 120 days to be safe | |
| stock = yf.Ticker(symbol) | |
| df = stock.history(start=start_date, end=end_date) | |
| if df.empty: | |
| return f"❌ Error: No data found for symbol '{symbol}'. Please check the symbol." | |
| if len(df) < 65: # Need extra days for percentage change calculation | |
| return f"❌ Error: Not enough data. Found {len(df)} days, need at least 65 days." | |
| # Prepare data | |
| normalized_data, close_prices = prepare_data(df) | |
| # Get last 60 days for prediction | |
| last_60_days = normalized_data[-60:] | |
| # Reshape for model input (1, 60, 5) | |
| input_data = last_60_days.reshape(1, 60, 5) | |
| # Make prediction | |
| prediction = model.predict(input_data, verbose=0) | |
| predicted_values = prediction[0] | |
| # Get context for interpretation | |
| last_close = close_prices[-1] | |
| recent_closes = close_prices[-10:] # Last 10 closes for trend | |
| avg_recent_change = np.mean(np.diff(recent_closes) / recent_closes[:-1]) * 100 | |
| # Interpret predictions as potential future close prices | |
| # Assume predictions represent relative price movements | |
| interpreted_prices = [] | |
| current_price = last_close | |
| for i, pred_val in enumerate(predicted_values): | |
| # Convert normalized prediction to price change | |
| # Adjust this scaling based on your model's training | |
| price_change_pct = (pred_val - 1.0) * 5 # Scale factor - adjust as needed | |
| new_price = current_price * (1 + price_change_pct / 100) | |
| interpreted_prices.append(new_price) | |
| current_price = new_price # Use for next prediction | |
| # Format results | |
| result = f"📊 **Prediction for {symbol}**\n\n" | |
| result += f"📈 Current Close Price: **${last_close:.2f}**\n" | |
| result += f"📊 Recent Trend: {avg_recent_change:+.2f}% avg daily change\n" | |
| result += f"📅 Data Period: {df.index[0].strftime('%Y-%m-%d')} to {df.index[-1].strftime('%Y-%m-%d')}\n" | |
| result += f"📊 Total Days Used: {len(df)}\n\n" | |
| result += f"🔮 **Price Predictions (Next 10 periods):**\n" | |
| for i, (raw_val, price) in enumerate(zip(predicted_values, interpreted_prices), 1): | |
| change_pct = ((price - last_close) / last_close) * 100 | |
| result += f" Day {i}: **${price:.2f}** ({change_pct:+.1f}%) [raw: {raw_val:.3f}]\n" | |
| # Summary statistics | |
| avg_predicted = np.mean(interpreted_prices) | |
| total_change = ((interpreted_prices[-1] - last_close) / last_close) * 100 | |
| result += f"\n📈 **Summary:**\n" | |
| result += f"• Average Predicted Price: **${avg_predicted:.2f}**\n" | |
| result += f"• Total 10-Day Change: **{total_change:+.1f}%**\n" | |
| result += f"• Prediction Range: ${min(interpreted_prices):.2f} - ${max(interpreted_prices):.2f}\n" | |
| result += f"\n⚠️ **Disclaimer:** Model predictions are experimental. Scaling factor may need adjustment based on training data." | |
| return result | |
| except Exception as e: | |
| return f"❌ Error: {str(e)}" | |
| def get_stock_info(symbol): | |
| """ | |
| Get basic stock information | |
| """ | |
| try: | |
| symbol = symbol.strip().upper() | |
| stock = yf.Ticker(symbol) | |
| info = stock.info | |
| name = info.get('longName', 'N/A') | |
| sector = info.get('sector', 'N/A') | |
| country = info.get('country', 'N/A') | |
| return f"📋 **Stock Info:**\n• Name: {name}\n• Sector: {sector}\n• Country: {country}" | |
| except: | |
| return "ℹ️ Stock info not available" | |
| # Create Gradio interface | |
| with gr.Blocks(title="Stock Symbol GRU Predictor", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("# 📈 Stock Symbol GRU Predictor") | |
| gr.Markdown("Enter a stock symbol to fetch historical data and get GRU model predictions.") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| symbol_input = gr.Textbox( | |
| label="Stock Symbol", | |
| placeholder="e.g., AAPL, RNO.PA, TSLA, MSFT", | |
| value="RNO.PA" | |
| ) | |
| predict_btn = gr.Button("🔮 Predict", variant="primary", size="lg") | |
| info_btn = gr.Button("ℹ️ Get Stock Info", variant="secondary") | |
| with gr.Column(scale=3): | |
| output = gr.Textbox( | |
| label="Prediction Results", | |
| lines=15, | |
| max_lines=20 | |
| ) | |
| info_output = gr.Textbox( | |
| label="Stock Information", | |
| lines=4 | |
| ) | |
| # Event handlers | |
| predict_btn.click(predict_stock_symbol, inputs=symbol_input, outputs=output) | |
| info_btn.click(get_stock_info, inputs=symbol_input, outputs=info_output) | |
| # Example symbols | |
| gr.Markdown(""" | |
| ### 📋 Example Symbols: | |
| • **US Stocks**: AAPL, MSFT, GOOGL, TSLA, AMZN | |
| • **European**: RNO.PA (Renault), AIR.PA (Airbus), SAP (SAP SE) | |
| • **Indices**: ^GSPC (S&P 500), ^IXIC (NASDAQ) | |
| ### 🔧 How it works: | |
| 1. Fetches last 90 days of stock data | |
| 2. Uses last 60 days as model input | |
| 3. Normalizes data (prices relative to first close, volume min-max) | |
| 4. Generates 10 prediction values using your GRU model | |
| ### ⚠️ Disclaimer: | |
| This is for educational purposes only. Not financial advice. | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch() |