File size: 4,573 Bytes
29e42d5 78c1fff 6af8332 908b282 72f2309 908b282 47ffeb1 908b282 47ffeb1 908b282 72f2309 78c1fff 47ffeb1 78c1fff ef3e3f0 78c1fff 72f2309 78c1fff 29e42d5 47ffeb1 29e42d5 78c1fff 47ffeb1 822643b 47ffeb1 78c1fff 47ffeb1 78c1fff 47ffeb1 72f2309 47ffeb1 |
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 117 118 |
import streamlit as st
import requests
from bs4 import BeautifulSoup
from transformers import pipeline
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import time
# ----------- Page Layout & Custom Styling -----------
st.set_page_config(page_title="Stock News Sentiment Analysis", layout="centered")
st.markdown("""
<style>
.main { background-color: #f9fbfc; }
.stTextInput>div>div>input {
font-size: 16px;
padding: 0.5rem;
}
.stButton>button {
background-color: #4CAF50;
color: white;
font-size: 16px;
padding: 0.5rem 1rem;
border-radius: 8px;
}
.stButton>button:hover {
background-color: #45a049;
}
</style>
""", unsafe_allow_html=True)
# ----------- Model Setup -----------
model_id = "LinkLinkWu/Boss_Stock_News_Analysis"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSequenceClassification.from_pretrained(model_id)
sentiment_pipeline = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer)
# ----------- Function Definitions -----------
def fetch_news(ticker):
try:
url = f"https://finviz.com/quote.ashx?t={ticker}"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
news_table = soup.find(id='news-table')
news = []
for row in news_table.findAll('tr')[:50]: # Fetch up to 50 articles
title = row.a.get_text()
link = row.a['href']
news.append({'title': title, 'link': link})
return news
except Exception as e:
st.error(f"Failed to fetch news for {ticker}: {e}")
return []
def analyze_sentiment(text):
try:
result = sentiment_pipeline(text)[0]
return "Positive" if result['label'] == 'POSITIVE' else "Negative"
except Exception as e:
st.error(f"Sentiment analysis failed: {e}")
return "Unknown"
# ----------- Streamlit UI -----------
st.title("📊 Stock News Sentiment Analysis")
st.markdown("""
This tool parses stock tickers and analyzes the sentiment of related news articles.
💡 *Example input:* `META, NVDA, AAPL, NTES, NCTY`
""")
# Input field for stock tickers
tickers_input = st.text_input("Enter stock tickers separated by commas:", "META, NVDA, AAPL, NTES, NCTY")
# Parse and display cleaned tickers in real-time
if tickers_input:
tickers = [ticker.strip().upper() for ticker in tickers_input.split(",") if ticker.strip()]
cleaned_input = ", ".join(tickers)
st.markdown(f"🔎 **Parsed Tickers:** `{cleaned_input}`")
else:
tickers = []
# Button to trigger sentiment analysis
if st.button("Get News and Sentiment"):
if not tickers:
st.warning("Please enter at least one stock ticker.")
else:
progress_bar = st.progress(0)
total_stocks = len(tickers)
for idx, ticker in enumerate(tickers):
st.subheader(f"Analyzing {ticker}...")
news_list = fetch_news(ticker)
if news_list:
# Analyze sentiment for all news articles (up to 50)
sentiments = []
for news in news_list:
sentiment = analyze_sentiment(news['title'])
sentiments.append(sentiment)
# Determine overall sentiment based on majority
positive_count = sentiments.count("Positive")
negative_count = sentiments.count("Negative")
overall_sentiment = "Positive" if positive_count > negative_count else "Negative"
# Display top 3 news articles with sentiment
st.write(f"**Top 3 News Articles for {ticker}**")
for i, news in enumerate(news_list[:3], 1):
sentiment = sentiments[i-1]
st.markdown(f"{i}. [{news['title']}]({news['link']}) - **{sentiment}**")
# Display overall sentiment
st.write(f"**Overall Sentiment for {ticker}: {overall_sentiment}**")
else:
st.write(f"No news available for {ticker}.")
# Update progress bar
progress_bar.progress((idx + 1) / total_stocks)
time.sleep(0.1) # Simulate processing time |