Akshayram1 commited on
Commit
a7d0af8
1 Parent(s): 1d4fc4e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -66
app.py CHANGED
@@ -10,8 +10,8 @@ from transformers import BertTokenizer, BertForSequenceClassification, pipeline
10
 
11
  st.set_page_config(page_title="Stock News Sentiment Analyzer", layout="wide")
12
 
13
- # Initialize FinBERT (yiyanghkust/finbert-tone) pipeline
14
- @st.cache_resource
15
  def load_model():
16
  model = BertForSequenceClassification.from_pretrained('yiyanghkust/finbert-tone', num_labels=3)
17
  tokenizer = BertTokenizer.from_pretrained('yiyanghkust/finbert-tone')
@@ -30,13 +30,17 @@ def verify_link(url, timeout=10, retries=3):
30
  return False
31
 
32
  def get_news(ticker):
33
- finviz_url = 'https://finviz.com/quote.ashx?t='
34
- url = finviz_url + ticker
35
- req = Request(url=url, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0'})
36
- response = urlopen(req)
37
- html = BeautifulSoup(response, 'html.parser')
38
- news_table = html.find(id='news-table')
39
- return news_table
 
 
 
 
40
 
41
  def parse_news(news_table):
42
  parsed_news = []
@@ -71,34 +75,35 @@ def parse_news(news_table):
71
  return parsed_news_df
72
 
73
  def score_news(parsed_news_df):
74
- # Get FinBERT predictions
75
- predictions = finbert(parsed_news_df['headline'].tolist())
76
-
77
- # Convert predictions to sentiment scores
78
  sentiment_scores = []
79
- for pred in predictions:
80
- label = pred['label']
81
- score = pred['score']
 
82
 
83
- # Map 'LABEL_0' (neutral), 'LABEL_1' (positive), and 'LABEL_2' (negative)
84
- if label == 'LABEL_1':
85
- sentiment_score = score
86
- elif label == 'LABEL_2':
87
- sentiment_score = -score
88
- else: # neutral
89
- sentiment_score = 0
90
 
91
- sentiment_scores.append({
92
- 'sentiment_score': sentiment_score,
93
- 'label': label,
94
- 'confidence': score
95
- })
96
-
97
- # Convert to DataFrame
 
 
 
 
 
 
 
98
  scores_df = pd.DataFrame(sentiment_scores)
99
-
100
- # Join with original news DataFrame
101
- parsed_and_scored_news = parsed_news_df.join(scores_df)
102
  parsed_and_scored_news = parsed_and_scored_news.set_index('datetime')
103
 
104
  return parsed_and_scored_news
@@ -154,43 +159,47 @@ ticker = st.text_input('Enter Stock Ticker', '').upper()
154
  try:
155
  st.subheader(f"Sentiment Analysis and Recommendation for {ticker} Stock")
156
  news_table = get_news(ticker)
157
- parsed_news_df = parse_news(news_table)
158
- parsed_and_scored_news = score_news(parsed_news_df)
159
-
160
- # Generate and display recommendation
161
- recommendation = get_recommendation(parsed_and_scored_news)
162
- st.write(recommendation)
163
-
164
- # Display a disclaimer
165
- st.warning("Disclaimer: This recommendation is based solely on recent news sentiment and should not be considered as financial advice. Always do your own research and consult with a qualified financial advisor before making investment decisions.")
166
-
167
- fig_hourly = plot_hourly_sentiment(parsed_and_scored_news, ticker)
168
- fig_daily = plot_daily_sentiment(parsed_and_scored_news, ticker)
169
-
170
- st.plotly_chart(fig_hourly)
171
- st.plotly_chart(fig_daily)
172
-
173
- description = f"""
174
- The above charts average the sentiment scores of {ticker} stock hourly and daily.
175
- The table below shows recent headlines with their sentiment scores and classifications.
176
- The news headlines are obtained from the FinViz website.
177
- Sentiments are analyzed using the yiyanghkust/finbert-tone model, which is specifically trained for financial text.
178
- Links have been verified for validity.
179
- """
180
 
181
- st.write(description)
182
-
183
- parsed_and_scored_news['link'] = parsed_and_scored_news.apply(
184
- lambda row: f'<a href="{row["link"]}" target="_blank">{"Valid✅" if row["is_valid"] else "Invalid❌"} Link</a>',
185
- axis=1
186
- )
187
-
188
- display_df = parsed_and_scored_news.drop(columns=['is_valid'])
189
- st.write(display_df.to_html(escape=False), unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  except Exception as e:
192
  print(str(e))
193
- st.write("Enter a correct stock ticker, e.g. 'AAPL' above and hit Enter.")
194
 
195
  hide_streamlit_style = """
196
  <style>
 
10
 
11
  st.set_page_config(page_title="Stock News Sentiment Analyzer", layout="wide")
12
 
13
+ # Initialize FinBERT (yiyanghkust/finbert-tone) pipeline only once and cache
14
+ @st.cache_resource(show_spinner=False)
15
  def load_model():
16
  model = BertForSequenceClassification.from_pretrained('yiyanghkust/finbert-tone', num_labels=3)
17
  tokenizer = BertTokenizer.from_pretrained('yiyanghkust/finbert-tone')
 
30
  return False
31
 
32
  def get_news(ticker):
33
+ try:
34
+ finviz_url = 'https://finviz.com/quote.ashx?t='
35
+ url = finviz_url + ticker
36
+ req = Request(url=url, headers={'User-Agent': 'Mozilla/5.0'})
37
+ response = urlopen(req)
38
+ html = BeautifulSoup(response, 'html.parser')
39
+ news_table = html.find(id='news-table')
40
+ return news_table
41
+ except Exception as e:
42
+ st.write("Error fetching news:", str(e))
43
+ return None
44
 
45
  def parse_news(news_table):
46
  parsed_news = []
 
75
  return parsed_news_df
76
 
77
  def score_news(parsed_news_df):
78
+ # Send headlines in smaller batches to speed up processing
79
+ batch_size = 10
80
+ parsed_news_df = parsed_news_df.reset_index(drop=True)
 
81
  sentiment_scores = []
82
+
83
+ for i in range(0, len(parsed_news_df), batch_size):
84
+ batch_headlines = parsed_news_df['headline'][i:i+batch_size].tolist()
85
+ predictions = finbert(batch_headlines)
86
 
87
+ for pred in predictions:
88
+ label = pred['label']
89
+ score = pred['score']
 
 
 
 
90
 
91
+ # Map 'LABEL_0' (neutral), 'LABEL_1' (positive), and 'LABEL_2' (negative)
92
+ if label == 'LABEL_1':
93
+ sentiment_score = score
94
+ elif label == 'LABEL_2':
95
+ sentiment_score = -score
96
+ else: # neutral
97
+ sentiment_score = 0
98
+
99
+ sentiment_scores.append({
100
+ 'sentiment_score': sentiment_score,
101
+ 'label': label,
102
+ 'confidence': score
103
+ })
104
+
105
  scores_df = pd.DataFrame(sentiment_scores)
106
+ parsed_and_scored_news = pd.concat([parsed_news_df, scores_df], axis=1)
 
 
107
  parsed_and_scored_news = parsed_and_scored_news.set_index('datetime')
108
 
109
  return parsed_and_scored_news
 
159
  try:
160
  st.subheader(f"Sentiment Analysis and Recommendation for {ticker} Stock")
161
  news_table = get_news(ticker)
162
+ if news_table:
163
+ parsed_news_df = parse_news(news_table)
164
+ parsed_and_scored_news = score_news(parsed_news_df)
165
+
166
+ # Generate and display recommendation
167
+ recommendation = get_recommendation(parsed_and_scored_news)
168
+ st.write(recommendation)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
+ # Display a disclaimer
171
+ st.warning("Disclaimer: This recommendation is based solely on recent news sentiment and should not be considered as financial advice. Always do your own research and consult with a qualified financial advisor before making investment decisions.")
172
+
173
+ fig_hourly = plot_hourly_sentiment(parsed_and_scored_news, ticker)
174
+ fig_daily = plot_daily_sentiment(parsed_and_scored_news, ticker)
175
+
176
+ st.plotly_chart(fig_hourly)
177
+ st.plotly_chart(fig_daily)
178
+
179
+ description = f"""
180
+ The above charts average the sentiment scores of {ticker} stock hourly and daily.
181
+ The table below shows recent headlines with their sentiment scores and classifications.
182
+ The news headlines are obtained from the FinViz website.
183
+ Sentiments are analyzed using the ProsusAI/finbert model, which is specifically trained for financial text.
184
+ Links have been verified for validity.
185
+ """
186
+
187
+ st.write(description)
188
+
189
+ parsed_and_scored_news['link'] = parsed_and_scored_news.apply(
190
+ lambda row: f'<a href="{row["link"]}" target="_blank">{"Valid✅" if row["is_valid"] else "Invalid❌"} Link</a>',
191
+ axis=1
192
+ )
193
+
194
+ display_df = parsed_and_scored_news.drop(columns=['is_valid'])
195
+ st.write(display_df.to_html(escape=False), unsafe_allow_html=True)
196
+
197
+ else:
198
+ st.write("No news available or invalid ticker symbol.")
199
 
200
  except Exception as e:
201
  print(str(e))
202
+ st.write("Enter a correct stock ticker, e.g. 'AAPL' above and hit Enter.")
203
 
204
  hide_streamlit_style = """
205
  <style>