Spaces:
Build error
Build error
| import streamlit as st | |
| import numpy as np | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| import os | |
| # Optional ML imports | |
| try: | |
| import tensorflow as tf | |
| from tensorflow.keras.models import load_model | |
| from sklearn.preprocessing import MinMaxScaler | |
| import joblib | |
| except ImportError: | |
| tf = None | |
| load_model = None | |
| MinMaxScaler = None | |
| joblib = None | |
| # Optional sentiment analysis | |
| try: | |
| from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer | |
| analyzer = SentimentIntensityAnalyzer() | |
| except ImportError: | |
| analyzer = None | |
| st.set_page_config(page_title="PSX Stock Predictor", layout="wide") | |
| st.title("π PSX Stock Predictor β HF Safe + Live Version") | |
| # ------------------------------ | |
| # Load Model & Scaler | |
| # ------------------------------ | |
| MODEL_LOADED = False | |
| if tf and os.path.exists("model.h5"): | |
| try: | |
| model = load_model("model.h5", custom_objects={"mse": tf.keras.metrics.MeanSquaredError()}) | |
| scaler = joblib.load("scaler.pkl") if os.path.exists("scaler.pkl") else MinMaxScaler() | |
| MODEL_LOADED = True | |
| st.success("Model loaded successfully!") | |
| except Exception as e: | |
| st.warning(f"Model found but failed to load: {e}") | |
| else: | |
| st.warning("Model not found. Using dummy predictions.") | |
| # ------------------------------ | |
| # Fetch PSX Data | |
| # ------------------------------ | |
| API_KEY = os.getenv("ALPHAVANTAGE_API_KEY", None) | |
| def get_psx_data(symbol="HBL"): | |
| if API_KEY: | |
| try: | |
| import requests | |
| url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}.PSX&apikey={API_KEY}" | |
| r = requests.get(url).json() | |
| data = r.get("Time Series (Daily)", None) | |
| if data: | |
| df = pd.DataFrame(data).T | |
| df.index = pd.to_datetime(df.index) | |
| df = df.sort_index() | |
| df = df[["4. close"]].rename(columns={"4. close": "Close"}) | |
| return df | |
| except: | |
| pass | |
| # Fallback dummy data | |
| dates = pd.date_range(end=pd.Timestamp.today(), periods=200) | |
| prices = np.linspace(100, 150, 200) + np.random.normal(0, 2, 200) | |
| df = pd.DataFrame({"Close": prices}, index=dates) | |
| return df | |
| # ------------------------------ | |
| # News Sentiment | |
| # ------------------------------ | |
| NEWS_KEY = os.getenv("NEWSAPI_KEY", None) | |
| def get_sentiment(stock="HBL"): | |
| if not analyzer or not NEWS_KEY: | |
| return 0 | |
| try: | |
| import requests | |
| url = f"https://newsapi.org/v2/everything?q={stock}+Pakistan&apiKey={NEWS_KEY}" | |
| r = requests.get(url).json() | |
| articles = r.get("articles", [])[:5] | |
| if not articles: | |
| return 0 | |
| scores = [analyzer.polarity_scores(a["title"])['compound'] for a in articles] | |
| return np.mean(scores) if scores else 0 | |
| except: | |
| return 0 | |
| # ------------------------------ | |
| # Prediction | |
| # ------------------------------ | |
| def predict_next(df): | |
| if MODEL_LOADED: | |
| data = scaler.fit_transform(df[["Close"]]) | |
| last60 = data[-60:].reshape(1, 60, 1) | |
| pred = model.predict(last60, verbose=0)[0][0] | |
| pred_real = scaler.inverse_transform([[pred]])[0][0] | |
| return pred_real | |
| else: | |
| # Dummy prediction: last value + small random change | |
| return df["Close"].iloc[-1] * (1 + np.random.uniform(-0.01, 0.01)) | |
| # ------------------------------ | |
| # Streamlit UI | |
| # ------------------------------ | |
| symbol = st.selectbox("Choose PSX Stock:", ["HBL", "UBL", "ENGRO", "PSO", "OGDC"]) | |
| if st.button("Fetch & Predict"): | |
| with st.spinner("Fetching data and predicting..."): | |
| df = get_psx_data(symbol) | |
| sentiment = get_sentiment(symbol) | |
| prediction = predict_next(df) | |
| # Adjust prediction with sentiment (2% weight) | |
| sentiment_adj = prediction + (prediction * sentiment * 0.02) | |
| # Plot historical + predicted | |
| fig, ax = plt.subplots() | |
| ax.plot(df.index, df["Close"], label="Historical Price") | |
| ax.axhline(sentiment_adj, linestyle="--", color="red", label="Predicted Price") | |
| ax.set_title(f"{symbol} Stock Price Prediction") | |
| ax.legend() | |
| st.pyplot(fig) | |
| # Display results | |
| st.subheader("Prediction Result") | |
| st.write(f"**Predicted Price:** Rs {sentiment_adj:.2f}") | |
| st.write(f"**Sentiment Impact:** {sentiment:.3f}") | |