rahilv commited on
Commit
81fe0bb
·
verified ·
1 Parent(s): b3f1e6e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -186
app.py CHANGED
@@ -1,203 +1,70 @@
1
  import streamlit as st
2
  import pandas as pd
3
- import torch
4
- from transformers import DistilBertTokenizer, DistilBertForSequenceClassification
5
  import feedparser
6
- import requests
7
- import re
8
- from datetime import datetime
9
- import time
10
- from huggingface_hub import notebook_login
11
-
12
- notebook_login()
13
-
14
- # Page configuration
15
- st.set_page_config(
16
- page_title="Stock Market Sentiment Analyzer",
17
- page_icon="📈",
18
- layout="wide"
19
- )
20
-
21
- # Create two columns for the header
22
- col1, col2 = st.columns([0.2, 1])
23
 
24
- with col1:
25
- # You can replace this with your own logo
26
- st.image("https://api.dicebear.com/7.x/shapes/svg?seed=stocks", width=80)
 
27
 
28
- with col2:
29
- st.title("Stock Market Sentiment Analyzer")
30
 
31
- st.markdown("**Analyze real-time market sentiment from news articles using DistilBERT-based deep learning model.**")
 
 
 
 
32
 
33
- # Sidebar content
34
- st.sidebar.subheader("About the App")
35
- st.sidebar.info(
36
- """This app uses 🤗 HuggingFace's DistilBERT model fine-tuned on financial news data
37
- to predict market sentiment in real-time. It processes news from various financial RSS feeds
38
- and classifies sentiment as bullish, bearish, or neutral."""
39
- )
 
 
 
 
 
 
 
 
40
 
41
- st.sidebar.markdown("### Configuration")
42
- st.sidebar.markdown("**Available RSS Feeds:**")
43
- feed_options = {
44
- "Benzinga Large Cap": "https://www.benzinga.com/news/large-cap/feed",
45
- "Market Watch": "http://feeds.marketwatch.com/marketwatch/marketpulse/",
46
- "Yahoo Finance": "https://finance.yahoo.com/news/rssindex"
47
- }
48
- selected_feed = st.sidebar.selectbox("Choose News Source:", list(feed_options.keys()))
49
 
50
- refresh_interval = st.sidebar.slider(
51
- "Refresh Interval (seconds)",
52
- min_value=30,
53
- max_value=300,
54
- value=60,
55
- help="How often to fetch new articles"
56
- )
57
 
58
- # Cache the model loading
59
- @st.cache_resource
60
- def load_model():
61
- """Load the sentiment analysis model and tokenizer"""
62
- try:
63
- model = DistilBertForSequenceClassification.from_pretrained('./sentiment_model')
64
- tokenizer = DistilBertTokenizer.from_pretrained('./sentiment_model')
65
- return model, tokenizer
66
- except Exception as e:
67
- st.error(f"Error loading model: {str(e)}")
68
- return None, None
69
 
70
- def predict_sentiment(text, model, tokenizer):
71
- """Predict sentiment for given text"""
72
- try:
73
- inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
74
- outputs = model(**inputs)
75
- logits = outputs.logits
76
- probabilities = torch.nn.functional.softmax(logits, dim=1)
77
- predicted_class = torch.argmax(logits, dim=1).item()
78
- confidence = probabilities[0][predicted_class].item()
79
-
80
- sentiment_map = {0: 'bearish', 1: 'bullish', 2: 'neutral'}
81
- return sentiment_map[predicted_class], confidence
82
- except Exception as e:
83
- st.error(f"Error in sentiment prediction: {str(e)}")
84
- return "error", 0.0
85
 
86
- def fetch_articles(feed_url):
87
- """Fetch and parse RSS feed"""
88
- try:
89
- headers = {
90
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
91
- }
92
- response = requests.get(feed_url, headers=headers, timeout=10)
93
- feed = feedparser.parse(response.content)
94
-
95
- articles = []
96
- for entry in feed.entries[:10]: # Limit to 10 most recent articles
97
- article = {
98
- 'title': entry.title,
99
- 'link': entry.link,
100
- 'summary': entry.get('summary', entry.title),
101
- 'published': entry.get('published', 'No date'),
102
- 'tickers': re.findall(r'\((\w+)\)', entry.title)
103
- }
104
- articles.append(article)
105
- return articles
106
- except Exception as e:
107
- st.error(f"Error fetching articles: {str(e)}")
108
- return []
109
 
110
- def main():
111
- # Load model
112
- model, tokenizer = load_model()
113
- if model is None or tokenizer is None:
114
- st.error("Could not load the model. Please check if model files exist.")
115
  return
116
 
117
- # Main content area
118
- col1, col2 = st.columns([2, 1])
119
-
120
- with col1:
121
- st.subheader("Latest Market News Analysis")
122
- articles_container = st.empty()
123
-
124
- while True:
125
- try:
126
- with st.spinner('Fetching latest articles...'):
127
- articles = fetch_articles(feed_options[selected_feed])
128
-
129
- if articles:
130
- with articles_container.container():
131
- for article in articles:
132
- sentiment, confidence = predict_sentiment(
133
- article['summary'],
134
- model,
135
- tokenizer
136
- )
137
-
138
- # Create card-like display for each article
139
- with st.expander(f"📰 {article['title']}", expanded=False):
140
- st.write(f"**Published:** {article['published']}")
141
-
142
- # Display tickers if found
143
- if article['tickers']:
144
- st.write(f"**Tickers:** {', '.join(article['tickers'])}")
145
-
146
- # Color-coded sentiment with confidence
147
- sentiment_colors = {
148
- 'bullish': 'green',
149
- 'bearish': 'red',
150
- 'neutral': 'grey'
151
- }
152
- st.markdown(
153
- f"**Sentiment:** :{sentiment_colors[sentiment]}[{sentiment.upper()}] "
154
- f"({confidence:.1%} confidence)"
155
- )
156
-
157
- st.write("**Summary:**")
158
- st.write(article['summary'])
159
- st.write(f"[Read full article]({article['link']})")
160
-
161
- st.caption(f"Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
162
-
163
- # Statistics in the second column
164
- with col2:
165
- st.subheader("Sentiment Overview")
166
-
167
- # Calculate sentiment distribution
168
- sentiments = [predict_sentiment(a['summary'], model, tokenizer)[0]
169
- for a in articles]
170
-
171
- # Create metrics
172
- sentiment_counts = pd.Series(sentiments).value_counts()
173
- total = len(sentiments)
174
-
175
- # Display metrics with gauges
176
- col_a, col_b, col_c = st.columns(3)
177
- with col_a:
178
- bullish_count = sentiment_counts.get('bullish', 0)
179
- st.metric("Bullish", f"{bullish_count}/{total}")
180
- with col_b:
181
- bearish_count = sentiment_counts.get('bearish', 0)
182
- st.metric("Bearish", f"{bearish_count}/{total}")
183
- with col_c:
184
- neutral_count = sentiment_counts.get('neutral', 0)
185
- st.metric("Neutral", f"{neutral_count}/{total}")
186
-
187
- # Display sentiment distribution chart
188
- st.bar_chart(sentiment_counts)
189
-
190
- time.sleep(refresh_interval)
191
-
192
- except Exception as e:
193
- st.error(f"An error occurred: {str(e)}")
194
- time.sleep(refresh_interval)
195
-
196
- # Footer
197
- st.sidebar.divider()
198
- st.sidebar.caption("Made with Streamlit and HuggingFace 🤗")
199
 
200
  if __name__ == "__main__":
201
- main()
202
-
203
- #test
 
1
  import streamlit as st
2
  import pandas as pd
 
 
3
  import feedparser
4
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
5
+ import torch
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ # Load the trained model and tokenizer
8
+ MODEL_NAME = "financial-sentiment-model"
9
+ model = AutoModelForSequenceClassification.from_pretrained(MODEL_NAME)
10
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
11
 
12
+ LABEL_MAP = {0: "bullish", 1: "bearish", 2: "neutral"}
 
13
 
14
+ # RSS Feed URLs
15
+ rss_feeds = {
16
+ "Benzinga": ["https://www.benzinga.com/feeds/news", "https://www.benzinga.com/feeds/analysis"],
17
+ "Yahoo News": ["https://finance.yahoo.com/rss/topstories"]
18
+ }
19
 
20
+ def fetch_rss_feed(url):
21
+ """Fetch articles from an RSS feed."""
22
+ feed = feedparser.parse(url)
23
+ articles = []
24
+ for entry in feed.entries:
25
+ articles.append({"title": entry.title, "link": entry.link})
26
+ return articles
27
+
28
+ def analyze_sentiment(text):
29
+ """Analyze sentiment of a given text."""
30
+ inputs = tokenizer(text, return_tensors="pt", truncation=True, padding="max_length", max_length=128)
31
+ with torch.no_grad():
32
+ outputs = model(**inputs)
33
+ predictions = torch.argmax(outputs.logits, dim=-1).item()
34
+ return LABEL_MAP[predictions]
35
 
36
+ def main():
37
+ st.title("Financial News Sentiment Analysis")
 
 
 
 
 
 
38
 
39
+ # Sidebar: Feed Selection
40
+ st.sidebar.header("Select RSS Feeds")
41
+ selected_feeds = st.sidebar.multiselect("Choose feeds:", options=rss_feeds.keys(), default=list(rss_feeds.keys()))
 
 
 
 
42
 
43
+ if not selected_feeds:
44
+ st.warning("Please select at least one RSS feed.")
45
+ return
 
 
 
 
 
 
 
 
46
 
47
+ st.sidebar.header("About")
48
+ st.sidebar.info(
49
+ "This app fetches financial news from RSS feeds and analyzes sentiment (buy, sell, hold) based on the latest news titles."
50
+ )
 
 
 
 
 
 
 
 
 
 
 
51
 
52
+ # Fetch and Display Articles
53
+ st.header("Latest Financial News")
54
+ articles = []
55
+ for feed_name in selected_feeds:
56
+ for url in rss_feeds[feed_name]:
57
+ articles.extend(fetch_rss_feed(url))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
+ if not articles:
60
+ st.write("No articles found.")
 
 
 
61
  return
62
 
63
+ for article in articles:
64
+ sentiment = analyze_sentiment(article["title"])
65
+ st.subheader(article["title"])
66
+ st.write(f"Sentiment: **{sentiment}**")
67
+ st.write(f"[Read more]({article['link']})")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  if __name__ == "__main__":
70
+ main()