LinkLinkWu's picture
Update app.py
96fabff verified
raw
history blame
4.39 kB
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: #333333; 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")
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'], 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.25:
overall = "Positive"
elif neg_ratio >= 0.75:
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)