rahilv commited on
Commit
5cc4bb6
·
verified ·
1 Parent(s): 53aa61b

Create app.py

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