import streamlit as st import tensorflow as tf import pandas as pd import numpy as np from src.data_fetcher import DataFetcher from src.processor import Processor from src.strategy import get_market_regime st.set_page_config(page_title="Alpha Predict", page_icon="🏹", layout="wide") @st.cache_resource def load_alpha_model(): return tf.keras.models.load_model("models/gru_booster_model.keras") @st.cache_resource def load_processor(): return Processor() def main(): st.title("🏹 Alpha Predict") st.markdown("---") with st.sidebar: st.header("📖 Strategy Logic") st.markdown(""" **Objective:** Directional probability for the next session. - **🟢 GREEN (≥ 57.8%)**: 3x Leverage (SPXL/UPRO) - **🟡 YELLOW (53.0% - 57.7%)**: 1x Exposure (SPY/VOO) - **🔴 RED (< 53.0%)**: Cash (0x) """) st.divider() st.caption("Alpha Predict") fetcher = DataFetcher() processor = load_processor() model = load_alpha_model() if st.button("Generate Today's Signal", type="primary"): with st.spinner("🔭 Analyzing Market Nervous System..."): # 1. Fetch data (Fetch 60 days to allow for the 26-day MACD EMA dropping NaNs) market_df = fetcher.fetch_market_data(days=60) news_df = fetcher.fetch_market_news(days=45) st.warning(f"Earliest news fetched: {news_df['Date'].min()} | Total Headlines: {len(news_df)}") # 2. Process - Now unpacking 4 items (df_features gives us the history!) input_tensor, metrics, df_features, scored_news = processor.process(market_df, news_df) # 3. Predict prediction_prob = float(model.predict(input_tensor)[0][0]) # 4. Get Strategy Regime regime = get_market_regime(prediction_prob) # 5. UI Metrics latest_vix = market_df['VIX'].iloc[-1] prev_vix = market_df['VIX'].iloc[-2] current_price = market_df['Close'].iloc[-1] col1, col2, col3 = st.columns(3) col1.metric("S&P 500 Baseline", f"${current_price:,.2f}") col2.metric("VIX (Fear Gauge)", f"{latest_vix:.2f}", delta=f"{latest_vix - prev_vix:+.2f} Fear", delta_color="inverse") col3.metric("FinBERT Sentiment", f"{metrics['Sent_Mean']:+.2f}", delta=f"{int(metrics['News_Volume'])} Headlines") with st.expander("📊 How to interpret these values?"): c1, c2 = st.columns(2) c1.markdown("**VIX:** <15 Calm, 15-25 Normal, >25 Panic.") c2.markdown("**Sentiment:** >+0.1 Bullish, ±0.1 Neutral, <-0.1 Bearish.") st.divider() # --- REGIME DISPLAY --- st.subheader(f"{regime['icon']} Current Regime: :{regime['color']}[{regime['zone']}]") res1, res2 = st.columns([1, 2]) res1.metric("Bullish Probability", f"{prediction_prob:.2%}") res2.info(f"**Recommended Action:** {regime['action']}") # --- LOGIC BREAKDOWN --- st.write("### 🧠 Logic Breakdown (Last 30 Days)") e_col1, e_col2 = st.columns(2) with e_col1: st.write("**Volatility Regime (VIX)**") vix_trend = market_df['VIX'].tail(30) st.line_chart(vix_trend) vix_slope = vix_trend.iloc[-1] - vix_trend.iloc[0] if vix_slope > 2: st.warning(f"⚠️ Volatility is **trending up** (+{vix_slope:.1f}pts). The AI sees rising instability.") elif vix_slope < -2: st.success(f"✅ Volatility is **cooling off** ({vix_slope:.1f}pts). This supports the bullish case.") else: st.info("⚖️ Volatility is sideways. The model is focused on other factors.") with e_col2: st.write("**Sentiment Momentum (FinBERT)**") # FIX: We now pull the historical trend from df_features! sent_trend = df_features['Sent_Mean'].tail(30) st.area_chart(sent_trend) avg_30d = sent_trend.mean() st.write(f"30-Day Avg Sentiment: **{avg_30d:+.2f}**") if metrics['Sent_Mean'] > avg_30d: st.write("📈 Today's news is **stronger** than the monthly average.") else: st.write("📉 Today's news is **weaker** than the monthly average.") if __name__ == "__main__": main()