JBond07's picture
Update app.py
9640339 verified
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()