Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import yfinance as yf | |
| import numpy as np | |
| import pandas as pd | |
| from keras.models import load_model | |
| import joblib | |
| import os | |
| # Load the saved components | |
| MODEL_PATH = 'stock_model.keras' | |
| SCALER_PATH = 'scaler.gz' | |
| if os.path.exists(MODEL_PATH) and os.path.exists(SCALER_PATH): | |
| model = load_model(MODEL_PATH) | |
| scaler = joblib.load(SCALER_PATH) | |
| else: | |
| model = None | |
| scaler = None | |
| def predict_next_day(ticker): | |
| if model is None or scaler is None: | |
| return "Error: Model or Scaler files not found." | |
| try: | |
| # 1. Fetch more data (120d) to accommodate MA50 and RSI calculations | |
| df = yf.download(ticker, period='120d', interval='1d', multi_level_index=False) | |
| if df.empty: return f"Error: No data for '{ticker}'." | |
| # 2. Re-create all 9 features from your notebook | |
| # Moving Averages | |
| df['MA7'] = df['Close'].rolling(window=7).mean() | |
| df['MA21'] = df['Close'].rolling(window=21).mean() | |
| df['MA50'] = df['Close'].rolling(window=50).mean() | |
| # Volatility & Returns | |
| df['Volatility'] = df['Close'].rolling(window=7).std() | |
| df['Daily_Return'] = df['Close'].pct_change() | |
| # Price Range & Volume Trend | |
| df['Price_Range'] = df['High'] - df['Low'] | |
| df['Volume_MA7'] = df['Volume'].rolling(window=7).mean() | |
| # RSI (Relative Strength Index) | |
| delta = df['Close'].diff() | |
| gain = (delta.where(delta > 0, 0)).rolling(window=14).mean() | |
| loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean() | |
| rs = gain / loss | |
| df['RSI'] = 100 - (100 / (1 + rs)) | |
| df.dropna(inplace=True) | |
| # 3. Check if we have enough data left | |
| if len(df) < 60: | |
| return "Error: Not enough data for a 60-day prediction window." | |
| # 4. Prepare features in the EXACT order used in training | |
| feature_cols = ['Close', 'MA7', 'MA21', 'MA50', 'RSI', | |
| 'Volatility', 'Price_Range', 'Daily_Return', 'Volume_MA7'] | |
| last_60_days = df[feature_cols].tail(60).values | |
| # 5. Scale and Predict | |
| scaled_data = scaler.transform(last_60_days) | |
| # Reshape to (1 sample, 60 time steps, 9 features) | |
| input_data = np.reshape(scaled_data, (1, 60, 9)) | |
| prediction_scaled = model.predict(input_data, verbose=0) | |
| # 6. Inverse Transform (using 9-column dummy) | |
| dummy = np.zeros((1, 9)) | |
| dummy[0, 0] = prediction_scaled.flatten()[0] | |
| prediction_final = scaler.inverse_transform(dummy)[0, 0] | |
| return f"Predicted Next Closing Price for {ticker}: ₹{prediction_final:.2f}" | |
| except Exception as e: | |
| return f"Technical Error: {str(e)}" | |
| # Interface | |
| interface = gr.Interface( | |
| fn=predict_next_day, | |
| inputs=gr.Textbox(label="Stock Ticker", placeholder="e.g., TCS.NS, RELIANCE.NS, AAPL"), | |
| outputs=gr.Textbox(label="Forecasted Price"), | |
| title="📈 StockPulse Predictor", | |
| description="LSTM model predicting stock price using 9 technical indicators.", | |
| theme="soft" | |
| ) | |
| if __name__ == "__main__": | |
| interface.launch() |