Akshayram1 commited on
Commit
aa04d75
·
verified ·
1 Parent(s): 580a5c5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -20
app.py CHANGED
@@ -4,14 +4,19 @@ from bs4 import BeautifulSoup
4
  import pandas as pd
5
  import plotly.express as px
6
  from dateutil import parser
7
- import nltk
8
- nltk.downloader.download('vader_lexicon')
9
- from nltk.sentiment.vader import SentimentIntensityAnalyzer
10
  import datetime
11
  import requests
 
12
 
13
  st.set_page_config(page_title="Stock News Sentiment Analyzer", layout="wide")
14
 
 
 
 
 
 
 
 
15
  def verify_link(url, timeout=10, retries=3):
16
  for _ in range(retries):
17
  try:
@@ -64,19 +69,40 @@ def parse_news(news_table):
64
  return parsed_news_df
65
 
66
  def score_news(parsed_news_df):
67
- vader = SentimentIntensityAnalyzer()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
- scores = parsed_news_df['headline'].apply(vader.polarity_scores).tolist()
70
- scores_df = pd.DataFrame(scores)
71
- parsed_and_scored_news = parsed_news_df.join(scores_df, rsuffix='_right')
72
- parsed_and_scored_news = parsed_and_scored_news.set_index('datetime')
73
- parsed_and_scored_news = parsed_and_scored_news.rename(columns={"compound": "sentiment_score"})
74
-
75
  return parsed_and_scored_news
76
 
77
  def plot_hourly_sentiment(parsed_and_scored_news, ticker):
78
- numeric_cols = parsed_and_scored_news.select_dtypes(include=['float64', 'int64'])
79
- mean_scores = numeric_cols.resample('h').mean()
80
 
81
  fig = px.bar(mean_scores, x=mean_scores.index, y='sentiment_score',
82
  title=f'{ticker} Hourly Sentiment Scores',
@@ -93,8 +119,7 @@ def plot_hourly_sentiment(parsed_and_scored_news, ticker):
93
  return fig
94
 
95
  def plot_daily_sentiment(parsed_and_scored_news, ticker):
96
- numeric_cols = parsed_and_scored_news.select_dtypes(include=['float64', 'int64'])
97
- mean_scores = numeric_cols.resample('D').mean()
98
 
99
  fig = px.bar(mean_scores, x=mean_scores.index, y='sentiment_score',
100
  title=f'{ticker} Daily Sentiment Scores',
@@ -113,14 +138,14 @@ def plot_daily_sentiment(parsed_and_scored_news, ticker):
113
  def get_recommendation(sentiment_scores):
114
  avg_sentiment = sentiment_scores['sentiment_score'].mean()
115
 
116
- if avg_sentiment >= 0.05:
117
  return f"Positive sentiment (Score: {avg_sentiment:.2f}). The recent news suggests a favorable outlook for this stock. Consider buying or holding if you already own it."
118
- elif avg_sentiment <= -0.05:
119
  return f"Negative sentiment (Score: {avg_sentiment:.2f}). The recent news suggests caution. Consider selling or avoiding this stock for now."
120
  else:
121
  return f"Neutral sentiment (Score: {avg_sentiment:.2f}). The recent news doesn't show a strong bias. Consider holding if you own the stock, or watch for more definitive trends before making a decision."
122
 
123
- st.header("Stock News Sentiment Analyzer")
124
 
125
  ticker = st.text_input('Enter Stock Ticker', '').upper()
126
 
@@ -145,9 +170,9 @@ try:
145
 
146
  description = f"""
147
  The above charts average the sentiment scores of {ticker} stock hourly and daily.
148
- The table below gives each of the most recent headlines of the stock and the negative, neutral, positive and an aggregated sentiment score.
149
  The news headlines are obtained from the FinViz website.
150
- Sentiments are given by the nltk.sentiment.vader Python library.
151
  Links have been verified for validity.
152
  """
153
 
@@ -158,7 +183,8 @@ try:
158
  axis=1
159
  )
160
 
161
- st.write(parsed_and_scored_news.drop(columns=['is_valid']).to_html(escape=False), unsafe_allow_html=True)
 
162
 
163
  except Exception as e:
164
  print(str(e))
 
4
  import pandas as pd
5
  import plotly.express as px
6
  from dateutil import parser
 
 
 
7
  import datetime
8
  import requests
9
+ from transformers import pipeline
10
 
11
  st.set_page_config(page_title="Stock News Sentiment Analyzer", layout="wide")
12
 
13
+ # Initialize FinBERT pipeline
14
+ @st.cache_resource
15
+ def load_model():
16
+ return pipeline("text-classification", model="ProsusAI/finbert")
17
+
18
+ finbert = load_model()
19
+
20
  def verify_link(url, timeout=10, retries=3):
21
  for _ in range(retries):
22
  try:
 
69
  return parsed_news_df
70
 
71
  def score_news(parsed_news_df):
72
+ # Get FinBERT predictions
73
+ predictions = finbert(parsed_news_df['headline'].tolist())
74
+
75
+ # Convert predictions to sentiment scores
76
+ sentiment_scores = []
77
+ for pred in predictions:
78
+ label = pred['label']
79
+ score = pred['score']
80
+
81
+ # Convert to -1 to 1 scale
82
+ if label == 'positive':
83
+ sentiment_score = score
84
+ elif label == 'negative':
85
+ sentiment_score = -score
86
+ else: # neutral
87
+ sentiment_score = 0
88
+
89
+ sentiment_scores.append({
90
+ 'sentiment_score': sentiment_score,
91
+ 'label': label,
92
+ 'confidence': score
93
+ })
94
+
95
+ # Convert to DataFrame
96
+ scores_df = pd.DataFrame(sentiment_scores)
97
+
98
+ # Join with original news DataFrame
99
+ parsed_and_scored_news = parsed_news_df.join(scores_df)
100
+ parsed_and_scored_news = parsed_and_scored_news.set_index('datetime')
101
 
 
 
 
 
 
 
102
  return parsed_and_scored_news
103
 
104
  def plot_hourly_sentiment(parsed_and_scored_news, ticker):
105
+ mean_scores = parsed_and_scored_news['sentiment_score'].resample('h').mean()
 
106
 
107
  fig = px.bar(mean_scores, x=mean_scores.index, y='sentiment_score',
108
  title=f'{ticker} Hourly Sentiment Scores',
 
119
  return fig
120
 
121
  def plot_daily_sentiment(parsed_and_scored_news, ticker):
122
+ mean_scores = parsed_and_scored_news['sentiment_score'].resample('D').mean()
 
123
 
124
  fig = px.bar(mean_scores, x=mean_scores.index, y='sentiment_score',
125
  title=f'{ticker} Daily Sentiment Scores',
 
138
  def get_recommendation(sentiment_scores):
139
  avg_sentiment = sentiment_scores['sentiment_score'].mean()
140
 
141
+ if avg_sentiment >= 0.3:
142
  return f"Positive sentiment (Score: {avg_sentiment:.2f}). The recent news suggests a favorable outlook for this stock. Consider buying or holding if you already own it."
143
+ elif avg_sentiment <= -0.3:
144
  return f"Negative sentiment (Score: {avg_sentiment:.2f}). The recent news suggests caution. Consider selling or avoiding this stock for now."
145
  else:
146
  return f"Neutral sentiment (Score: {avg_sentiment:.2f}). The recent news doesn't show a strong bias. Consider holding if you own the stock, or watch for more definitive trends before making a decision."
147
 
148
+ st.header("Stock News Sentiment Analyzer (FinBERT)")
149
 
150
  ticker = st.text_input('Enter Stock Ticker', '').upper()
151
 
 
170
 
171
  description = f"""
172
  The above charts average the sentiment scores of {ticker} stock hourly and daily.
173
+ The table below shows recent headlines with their sentiment scores and classifications.
174
  The news headlines are obtained from the FinViz website.
175
+ Sentiments are analyzed using the ProsusAI/finbert model, which is specifically trained for financial text.
176
  Links have been verified for validity.
177
  """
178
 
 
183
  axis=1
184
  )
185
 
186
+ display_df = parsed_and_scored_news.drop(columns=['is_valid'])
187
+ st.write(display_df.to_html(escape=False), unsafe_allow_html=True)
188
 
189
  except Exception as e:
190
  print(str(e))