|
|
import os |
|
|
import io |
|
|
import requests |
|
|
import joblib |
|
|
import pandas as pd |
|
|
import streamlit as st |
|
|
import plotly.graph_objects as go |
|
|
from datetime import datetime |
|
|
from supabase import create_client, Client |
|
|
import yfinance as yf |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MODEL_URL = "https://huggingface.co/shaikfakruddin18/stock-predictor-model/resolve/main/rf_model.joblib" |
|
|
|
|
|
ALPHA_VANTAGE_API_KEY = " IY2HMVXFHXE83LB5" |
|
|
SUPABASE_URL = "https://rrvsbizwikocatkdhyfs.supabase.co" |
|
|
SUPABASE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJydnNiaXp3aWtvY2F0a2RoeWZzIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTI5NjExNDAsImV4cCI6MjA2ODUzNzE0MH0.YWP65KQvwna1yQlhjksyT9Rhpyn5bBw5MDlMVHTF62Q" |
|
|
|
|
|
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) |
|
|
|
|
|
|
|
|
@st.cache_resource |
|
|
def load_model_from_hf(): |
|
|
"""Download model from Hugging Face and load it""" |
|
|
model_path = "rf_model.joblib" |
|
|
if not os.path.exists(model_path): |
|
|
st.info("π₯ Downloading ML model from Hugging Face...") |
|
|
r = requests.get(MODEL_URL) |
|
|
with open(model_path, "wb") as f: |
|
|
f.write(r.content) |
|
|
return joblib.load(model_path) |
|
|
|
|
|
model = load_model_from_hf() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fetch_yahoo_data(ticker, period="3mo"): |
|
|
"""Fetch historical daily data from Yahoo Finance""" |
|
|
df = yf.download(ticker, period=period, interval="1d") |
|
|
if df.empty: |
|
|
return None |
|
|
df.reset_index(inplace=True) |
|
|
return df |
|
|
|
|
|
def fetch_alpha_vantage_intraday(ticker, interval="5min"): |
|
|
"""Fetch intraday data from Alpha Vantage""" |
|
|
url = ( |
|
|
f"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY" |
|
|
f"&symbol={ticker}&interval={interval}&apikey={ALPHA_VANTAGE_API_KEY}&datatype=json" |
|
|
) |
|
|
r = requests.get(url).json() |
|
|
key = f"Time Series ({interval})" |
|
|
if key not in r: |
|
|
return None |
|
|
df = pd.DataFrame(r[key]).T |
|
|
df.columns = ["Open", "High", "Low", "Close", "Volume"] |
|
|
df.index = pd.to_datetime(df.index) |
|
|
df = df.sort_index() |
|
|
df.reset_index(inplace=True) |
|
|
df.rename(columns={"index": "Datetime"}, inplace=True) |
|
|
df[["Open", "High", "Low", "Close", "Volume"]] = df[["Open", "High", "Low", "Close", "Volume"]].astype(float) |
|
|
return df |
|
|
|
|
|
def fetch_supabase_csv(ticker): |
|
|
"""Fetch saved stock CSV from Supabase storage""" |
|
|
try: |
|
|
base_url = "https://rrvsbizwikocatkdhyfs.supabase.co/storage/v1/object/public/prediction/stock_data_with_indicators" |
|
|
csv_url = f"{base_url}/{ticker}.csv" |
|
|
df = pd.read_csv(csv_url) |
|
|
return df |
|
|
except: |
|
|
return None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def predict_stock(df): |
|
|
"""Predict UP/DOWN using the loaded ML model""" |
|
|
if df is None or df.empty: |
|
|
return None, None |
|
|
|
|
|
features = df[["Open", "High", "Low", "Close", "Volume"]].tail(1) |
|
|
pred = model.predict(features)[0] |
|
|
confidence = model.predict_proba(features).max() * 100 |
|
|
prediction = "UP" if pred == 1 else "DOWN" |
|
|
return prediction, confidence |
|
|
|
|
|
def plot_candlestick(df, title="Stock Price"): |
|
|
fig = go.Figure( |
|
|
data=[ |
|
|
go.Candlestick( |
|
|
x=df[df.columns[0]], |
|
|
open=df["Open"], |
|
|
high=df["High"], |
|
|
low=df["Low"], |
|
|
close=df["Close"], |
|
|
) |
|
|
] |
|
|
) |
|
|
fig.update_layout(title=title, xaxis_rangeslider_visible=False, height=400) |
|
|
return fig |
|
|
|
|
|
def save_prediction_to_supabase(stock, prediction, confidence, source): |
|
|
"""Save prediction to Supabase DB""" |
|
|
try: |
|
|
created_at = datetime.utcnow().isoformat() |
|
|
data = { |
|
|
"created_at": created_at, |
|
|
"stock": stock, |
|
|
"prediction": prediction, |
|
|
"confidence": f"{confidence:.2f}%", |
|
|
"source": source |
|
|
} |
|
|
response = supabase.table("predictions").insert(data).execute() |
|
|
if response.data: |
|
|
st.success("β
Prediction saved to Supabase!") |
|
|
else: |
|
|
st.error(f"β Failed to save prediction: {response}") |
|
|
except Exception as e: |
|
|
st.error(f"β Supabase error: {e}") |
|
|
|
|
|
def load_prediction_history_supabase(): |
|
|
"""Load previous predictions""" |
|
|
try: |
|
|
response = supabase.table("predictions").select("*").order("created_at", desc=True).execute() |
|
|
return pd.DataFrame(response.data) if response.data else pd.DataFrame() |
|
|
except Exception as e: |
|
|
st.error(f"β Failed to load history: {e}") |
|
|
return pd.DataFrame() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
st.set_page_config(page_title="AI Stock Predictor", layout="wide") |
|
|
st.sidebar.title("π Navigation") |
|
|
|
|
|
st.sidebar.subheader("Select Data Source") |
|
|
data_source = st.sidebar.radio( |
|
|
"Fetch data from:", |
|
|
["Yahoo Finance (Daily)", "Alpha Vantage (Intraday)", "Supabase CSV"] |
|
|
) |
|
|
|
|
|
ticker = st.sidebar.text_input("Enter Stock Ticker (e.g. AAPL, RELIANCE.BSE)", "AAPL") |
|
|
|
|
|
if data_source == "Yahoo Finance (Daily)": |
|
|
period = st.sidebar.selectbox("Select Period", ["1mo", "3mo", "6mo", "1y", "2y"], index=1) |
|
|
elif data_source == "Alpha Vantage (Intraday)": |
|
|
interval = st.sidebar.selectbox("Intraday Interval", ["1min", "5min", "15min", "30min", "60min"], index=1) |
|
|
|
|
|
st.title("π AI Stock Predictor Dashboard") |
|
|
|
|
|
if st.sidebar.button("Fetch Data & Predict"): |
|
|
if data_source == "Yahoo Finance (Daily)": |
|
|
df = fetch_yahoo_data(ticker, period) |
|
|
source_name = "YahooFinance" |
|
|
elif data_source == "Alpha Vantage (Intraday)": |
|
|
df = fetch_alpha_vantage_intraday(ticker, interval) |
|
|
source_name = "AlphaVantage" |
|
|
else: |
|
|
df = fetch_supabase_csv(ticker) |
|
|
source_name = "Supabase CSV" |
|
|
|
|
|
if df is None or df.empty: |
|
|
st.error("β No data returned. Check ticker or date range.") |
|
|
else: |
|
|
st.subheader(f"Stock Data: {ticker} ({source_name})") |
|
|
st.plotly_chart(plot_candlestick(df, f"{ticker} Price Chart"), use_container_width=True) |
|
|
|
|
|
prediction, confidence = predict_stock(df) |
|
|
if prediction: |
|
|
st.markdown(f"### Prediction: **{prediction}**") |
|
|
st.markdown(f"### Confidence: **{confidence:.2f}%**") |
|
|
save_prediction_to_supabase(ticker, prediction, confidence, source_name) |
|
|
else: |
|
|
st.warning("β οΈ Could not generate prediction.") |
|
|
|
|
|
|
|
|
st.subheader("π Prediction History (Cloud)") |
|
|
history_df = load_prediction_history_supabase() |
|
|
if not history_df.empty: |
|
|
st.dataframe(history_df[["created_at", "stock", "prediction", "confidence", "source"]]) |
|
|
else: |
|
|
st.info("No prediction history yet.") |
|
|
|