File size: 4,752 Bytes
4cb21eb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bf96dc6
4cb21eb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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()