import gradio as gr import torch import logging import warnings import os import yfinance as yf import pandas as pd from neuralprophet import NeuralProphet import plotly.graph_objs as go # --- STEP 1: CONFIGURATION & PATCHES --- # Suppress messy logs logging.getLogger("neuralprophet").setLevel(logging.ERROR) logging.getLogger("pytorch_lightning").setLevel(logging.ERROR) warnings.filterwarnings("ignore") os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # Fix for PyTorch 2.6+ security check original_load = torch.load def patched_load(*args, **kwargs): if 'weights_only' not in kwargs: kwargs['weights_only'] = False return original_load(*args, **kwargs) torch.load = patched_load # --- STEP 2: PREDICTION LOGIC --- def predict_stock(ticker): """ Takes a ticker symbol, trains a NeuralProphet model, and returns a textual report and two Plotly figures. """ ticker = ticker.strip().upper() if not ticker: return "â ī¸ Please enter a ticker symbol.", None, None print(f"Processing {ticker}...") try: # 1. Get Data data = yf.download(ticker, period="3y", interval="1d", progress=False) if data.empty: return f"â Could not find data for ticker '{ticker}'. Please check the symbol.", None, None # Flatten MultiIndex if present if isinstance(data.columns, pd.MultiIndex): try: # Attempt to extract just the Close column for the specific ticker df = data.xs(ticker, axis=1, level=1) if 'Close' in df.columns: df = df[['Close']].reset_index() else: df = data['Close'].reset_index() except: # Brute force flatten df = data.copy() df.columns = ['_'.join(col).strip() for col in df.columns.values] close_col = [c for c in df.columns if "Close" in c][0] df = df[[close_col]].reset_index() else: df = data[['Close']].reset_index() # Rename for NeuralProphet df.columns = ['ds', 'y'] df['ds'] = df['ds'].dt.tz_localize(None) if len(df) < 100: return f"â Not enough historical data found for {ticker} (Need > 100 days).", None, None # 2. Train Model m = NeuralProphet( yearly_seasonality=True, weekly_seasonality=True, daily_seasonality=False, learning_rate=0.01 ) m.fit(df, freq="D") # 3. Predict 90 Days out future = m.make_future_dataframe(df, periods=90) forecast = m.predict(future) # 4. Extract Metrics current_price = df['y'].iloc[-1] predicted_price = forecast['yhat1'].iloc[-1] # Calculate ROI roi = ((predicted_price - current_price) / current_price) * 100 # Generate Verdict & Colors if roi > 10: verdict = "STRONG BUY đ" color = "#10B981" # Green bg_color = "#D1FAE5" elif roi > 2: verdict = "BUY đĸ" color = "#10B981" # Green bg_color = "#D1FAE5" elif roi > -5: verdict = "HOLD đĄ" color = "#F59E0B" # Yellow bg_color = "#FEF3C7" else: verdict = "SELL đ´" color = "#EF4444" # Red bg_color = "#FEE2E2" # 5. Format Output HTML (Pretty Dashboard) # Using inline CSS to ensure it looks good in Gradio html_report = f"""
Forecast Horizon: 90 Days