File size: 4,453 Bytes
b302b27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45c8e0e
b302b27
45c8e0e
 
 
 
b302b27
 
45c8e0e
 
 
 
 
b302b27
 
 
 
 
 
45c8e0e
 
 
b302b27
 
 
 
 
 
45c8e0e
b302b27
 
 
 
 
3312cc4
b302b27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45c8e0e
 
 
 
 
 
 
b302b27
 
45c8e0e
b302b27
 
 
 
a9d6d3f
b302b27
a9d6d3f
b302b27
 
 
 
 
 
 
45c8e0e
b302b27
 
 
 
 
 
 
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
import streamlit as st
from func import (
    get_sentiment_pipeline,
    get_ner_pipeline,
    fetch_news,
    analyze_sentiment,
    extract_org_entities,
)
import time

# ----------- Page Config -----------
st.set_page_config(
    page_title="EquiPulse: Stock Sentiment Tracker",
    layout="centered",
    initial_sidebar_state="collapsed"
)

# ----------- Custom Styling -----------
st.markdown("""
    <style>
        body { background-color: #ffffff; }
        /* Title styling */
        .main-title      { font-size: 32px; font-weight: 700; font-family: 'Segoe UI', sans-serif;
                           color: #002b45; margin-bottom: 1.2rem; white-space: nowrap; overflow-x: auto; }
        .main-title::-webkit-scrollbar        { height: 4px; }
        .main-title::-webkit-scrollbar-thumb  { background-color: #ccc; border-radius: 2px; }
        /* Input + Button styling */
        .stTextInput > div > div > input,
        .stTextArea textarea                  { font-size: 16px; }
        .stButton > button                    { background-color: #002b45; color: white; font-size: 16px;
                                                padding: 0.4rem 1rem; border-radius: 6px; }
        .stButton > button:hover              { background-color: #004b78; }
        .stMarkdown                           { font-size: 16px; }
    </style>
""", unsafe_allow_html=True)

# ----------- Header Title (Centered + Bold + Large + Professional) -----------
st.markdown("""
    <style>
        .centered-title { text-align: center; font-size: 36px; font-weight: 800;
                          font-family: 'Segoe UI', sans-serif; color: #002b45;
                          margin-top: 20px; margin-bottom: 20px; }
    </style>
    <div class="centered-title">πŸ“Š EquiPulse: Stock Sentiment Tracker</div>
""", unsafe_allow_html=True)

# ----------- Description Section -----------
st.markdown("""
<div style='font-size:16px; line-height:1.6; color:#333; margin-bottom:1rem;'>
    Analyze real-time financial sentiment from news headlines related to companies you're interested in.
</div>
""", unsafe_allow_html=True)

# ----------- Input Area -----------
st.markdown("#### 🎯 Enter Your Target Company Tickers (Up to 5 Tickers)")
free_text = st.text_area("Example: AAPL, NVDA, TSLA", height=90)

# ----------- Ticker Extraction -----------
ner_pipeline = get_ner_pipeline()
tickers = extract_org_entities(free_text, ner_pipeline)

if tickers:
    st.markdown(f"βœ… **Recognized Tickers:** `{', '.join(tickers)}`")
else:
    tickers = []

# ----------- Action Button -----------
if st.button("πŸ” Get News and Sentiment"):
    if not tickers:
        st.warning("⚠️ Please enter at least one recognizable company name or ticker.")
    else:
        sentiment_pipeline = get_sentiment_pipeline()
        progress_bar = st.progress(0)
        total_stocks = len(tickers)

        for idx, ticker in enumerate(tickers):
            st.markdown(f"---\n#### πŸ” Analyzing `{ticker}`")

            news_list = fetch_news(ticker)

            if news_list:
                # ------------------------------------------------------
                sentiments = [
                    analyze_sentiment(news["title"], pipe=sentiment_pipeline) 
                    for news in news_list
                ]
                # ------------------------------------------------------

                pos_count = sentiments.count("Positive")
                neg_count = sentiments.count("Negative")
                total     = len(sentiments)
                pos_ratio = pos_count / total if total else 0
                neg_ratio = neg_count / total if total else 0

                # Simple heuristic for overall sentiment
                if pos_ratio >= 0.5:
                    overall = "Positive"
                elif neg_ratio >= 0.5:
                    overall = "Negative"
                else:
                    overall = "Neutral"

                # Display news
                st.markdown(f"**πŸ“° Top News for `{ticker}`:**")
                for i, news in enumerate(news_list[:3]):
                    st.markdown(f"{i + 1}. [{news['title']}]({news['link']}) β€” **{sentiments[i]}**")

                st.success(f"πŸ“ˆ **Overall Sentiment for `{ticker}`: {overall}**")
            else:
                st.info(f"No recent news found for `{ticker}`.")

            progress_bar.progress((idx + 1) / total_stocks)
            time.sleep(0.1)