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="Market-Pulse: 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">📊 EuqiPulse: 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)