Spaces:
Running
Running
| 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") | |
| def load_alpha_model(): | |
| return tf.keras.models.load_model("models/gru_booster_model.keras") | |
| 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() |