Hamza012bce21 commited on
Commit
be1c8d5
Β·
verified Β·
1 Parent(s): ce57f27

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -123
app.py CHANGED
@@ -1,128 +1,117 @@
1
  import streamlit as st
 
 
2
  import numpy as np
3
  import pandas as pd
4
- import matplotlib.pyplot as plt
5
- import os
6
 
7
- # Optional ML imports
8
- try:
9
- import tensorflow as tf
10
- from tensorflow.keras.models import load_model
11
- from sklearn.preprocessing import MinMaxScaler
12
- import joblib
13
- except ImportError:
14
- tf = None
15
- load_model = None
16
- MinMaxScaler = None
17
- joblib = None
18
-
19
- # Optional sentiment analysis
 
 
 
 
20
  try:
21
- from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
22
- analyzer = SentimentIntensityAnalyzer()
23
- except ImportError:
24
- analyzer = None
25
-
26
- st.set_page_config(page_title="PSX Stock Predictor", layout="wide")
27
- st.title("πŸ“ˆ PSX Stock Predictor – HF Safe + Live Version")
28
-
29
- # ------------------------------
30
- # Load Model & Scaler
31
- # ------------------------------
32
- MODEL_LOADED = False
33
- if tf and os.path.exists("model.h5"):
34
- try:
35
- model = load_model("model.h5", custom_objects={"mse": tf.keras.metrics.MeanSquaredError()})
36
- scaler = joblib.load("scaler.pkl") if os.path.exists("scaler.pkl") else MinMaxScaler()
37
- MODEL_LOADED = True
38
- st.success("Model loaded successfully!")
39
- except Exception as e:
40
- st.warning(f"Model found but failed to load: {e}")
41
- else:
42
- st.warning("Model not found. Using dummy predictions.")
43
-
44
- # ------------------------------
45
- # Fetch PSX Data
46
- # ------------------------------
47
- API_KEY = os.getenv("ALPHAVANTAGE_API_KEY", None)
48
-
49
- def get_psx_data(symbol="HBL"):
50
- if API_KEY:
51
- try:
52
- import requests
53
- url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}.PSX&apikey={API_KEY}"
54
- r = requests.get(url).json()
55
- data = r.get("Time Series (Daily)", None)
56
- if data:
57
- df = pd.DataFrame(data).T
58
- df.index = pd.to_datetime(df.index)
59
- df = df.sort_index()
60
- df = df[["4. close"]].rename(columns={"4. close": "Close"})
61
- return df
62
- except:
63
- pass
64
- # Fallback dummy data
65
- dates = pd.date_range(end=pd.Timestamp.today(), periods=200)
66
- prices = np.linspace(100, 150, 200) + np.random.normal(0, 2, 200)
67
- df = pd.DataFrame({"Close": prices}, index=dates)
68
- return df
69
-
70
- # ------------------------------
71
- # News Sentiment
72
- # ------------------------------
73
- NEWS_KEY = os.getenv("NEWSAPI_KEY", None)
74
-
75
- def get_sentiment(stock="HBL"):
76
- if not analyzer or not NEWS_KEY:
77
- return 0
78
- try:
79
- import requests
80
- url = f"https://newsapi.org/v2/everything?q={stock}+Pakistan&apiKey={NEWS_KEY}"
81
- r = requests.get(url).json()
82
- articles = r.get("articles", [])[:5]
83
- if not articles:
84
- return 0
85
- scores = [analyzer.polarity_scores(a["title"])['compound'] for a in articles]
86
- return np.mean(scores) if scores else 0
87
- except:
88
- return 0
89
-
90
- # ------------------------------
91
- # Prediction
92
- # ------------------------------
93
- def predict_next(df):
94
- if MODEL_LOADED:
95
- data = scaler.fit_transform(df[["Close"]])
96
- last60 = data[-60:].reshape(1, 60, 1)
97
- pred = model.predict(last60, verbose=0)[0][0]
98
- pred_real = scaler.inverse_transform([[pred]])[0][0]
99
- return pred_real
100
- else:
101
- # Dummy prediction: last value + small random change
102
- return df["Close"].iloc[-1] * (1 + np.random.uniform(-0.01, 0.01))
103
-
104
- # ------------------------------
105
- # Streamlit UI
106
- # ------------------------------
107
- symbol = st.selectbox("Choose PSX Stock:", ["HBL", "UBL", "ENGRO", "PSO", "OGDC"])
108
-
109
- if st.button("Fetch & Predict"):
110
- with st.spinner("Fetching data and predicting..."):
111
- df = get_psx_data(symbol)
112
- sentiment = get_sentiment(symbol)
113
- prediction = predict_next(df)
114
- # Adjust prediction with sentiment (2% weight)
115
- sentiment_adj = prediction + (prediction * sentiment * 0.02)
116
-
117
- # Plot historical + predicted
118
- fig, ax = plt.subplots()
119
- ax.plot(df.index, df["Close"], label="Historical Price")
120
- ax.axhline(sentiment_adj, linestyle="--", color="red", label="Predicted Price")
121
- ax.set_title(f"{symbol} Stock Price Prediction")
122
- ax.legend()
123
- st.pyplot(fig)
124
-
125
- # Display results
126
- st.subheader("Prediction Result")
127
- st.write(f"**Predicted Price:** Rs {sentiment_adj:.2f}")
128
- st.write(f"**Sentiment Impact:** {sentiment:.3f}")
 
1
  import streamlit as st
2
+ import plotly.graph_objects as go
3
+ from groq import Groq
4
  import numpy as np
5
  import pandas as pd
6
+ import yfinance as yf
 
7
 
8
+ # prediction module
9
+ from predict_live import predict_next_price, get_live_data
10
+ # Streamlit Setup
11
+
12
+ st.set_page_config(page_title="πŸ“Š PSX Investment Advisor", layout="wide", page_icon="πŸ“ˆ")
13
+ st.title("πŸ“Š PSX Investment Dashboard")
14
+ st.write("GenAI-powered stock insights with LIVE LSTM predictions")
15
+
16
+ # Sidebar Inputs
17
+ st.sidebar.header("Investment Options")
18
+ investment_type = st.sidebar.radio("Investment Type:", ["Short Term", "Long Term"])
19
+ sector = st.sidebar.selectbox("Sector:", ["Banking", "Energy"])
20
+ stock = st.sidebar.text_input("Stock Symbol:", "HBL") # user enters HBL
21
+
22
+ #PSX ticker format
23
+ ticker = stock.upper() + ".KA"
24
+ # LIVE Prediction
25
  try:
26
+ close_prices = get_live_data(ticker)
27
+ predicted_price = predict_next_price(ticker)
28
+
29
+ except Exception as e:
30
+ st.error(f"Error fetching live data: {e}")
31
+ st.stop()
32
+ # Dummy sentiment
33
+ sentiment_score = 0.10
34
+ sentiment_adjusted_pred = predicted_price + (predicted_price * sentiment_score * 0.02)
35
+
36
+ # Dashboard
37
+ col1, col2, col3 = st.columns(3)
38
+ col1.metric("Selected Stock", stock)
39
+ col2.metric("Live Last Price", f"Rs {close_prices[-1]:.2f}")
40
+ col3.metric("LSTM Prediction", f"Rs {sentiment_adjusted_pred:.2f}")
41
+
42
+ #Plot
43
+ def plot_stock(close_prices, predicted_price):
44
+ fig = go.Figure()
45
+
46
+ # Plot live historical
47
+ fig.add_trace(go.Scatter(
48
+ y=close_prices,
49
+ x=list(range(len(close_prices))),
50
+ mode='lines',
51
+ name='Live Prices'
52
+ ))
53
+
54
+ # Plot prediction
55
+ fig.add_trace(go.Scatter(
56
+ x=[len(close_prices)],
57
+ y=[predicted_price],
58
+ mode='markers',
59
+ name='Predicted Next Price',
60
+ marker=dict(size=12)
61
+ ))
62
+
63
+ fig.update_layout(
64
+ title=f"{stock} Live Price + Prediction",
65
+ xaxis_title="Time",
66
+ yaxis_title="Price (Rs)",
67
+ template="plotly_dark"
68
+ )
69
+ return fig
70
+
71
+ st.subheader("Live Price Chart")
72
+ st.plotly_chart(plot_stock(close_prices, sentiment_adjusted_pred), use_container_width=True)
73
+
74
+ st.subheader("Prediction Result")
75
+ st.write(f"**LSTM Next Price Prediction:** Rs {sentiment_adjusted_pred:.2f}")
76
+ st.write(f"**Sentiment Impact:** {sentiment_score:.2f}")
77
+
78
+ # AI Chatbox via Groq
79
+
80
+ st.subheader("πŸ’¬ Ask Your Investment Advisor")
81
+
82
+ user_input = st.text_input(
83
+ "Your question to AI:",
84
+ f"Should I invest in {stock} for {investment_type.lower()}?"
85
+ )
86
+
87
+ if st.button("Ask AI"):
88
+ if user_input:
89
+ with st.spinner("Thinking..."):
90
+
91
+ client = Groq(api_key=st.secrets["GROQ_API_KEY"])
92
+
93
+ advisor_prompt = f"""
94
+ You are a financial advisor AI.
95
+
96
+ Use the following data:
97
+ Current Price: {close_prices[-1]}
98
+ Predicted Next Price: {sentiment_adjusted_pred}
99
+ User Question: {user_input}
100
+
101
+ Respond MUST:
102
+ - Give a clear BUY / SELL / HOLD
103
+ - Explain in 2–3 simple lines
104
+ - Mention risk in simple terms
105
+ - 1 friendly tip
106
+ - No complex financial jargon
107
+ """
108
+ response = client.chat.completions.create(
109
+ model="openai/gpt-oss-120b",
110
+ messages=[
111
+ {"role": "system", "content": "You are a professional stock advisor."},
112
+ {"role": "user", "content": advisor_prompt}
113
+ ]
114
+ )
115
+
116
+ answer = response.choices[0].message.content
117
+ st.markdown(f"**AI:** {answer}")