Sarat Chandra commited on
Commit
aec0f90
1 Parent(s): 7cbc36b

"Multi Threaded Approach"

Browse files
.DS_Store ADDED
Binary file (6.15 kB). View file
 
Dockerfile CHANGED
@@ -5,8 +5,8 @@ FROM python:3.9-slim
5
  WORKDIR /code
6
 
7
  # Copy the required files to the working directory
8
- COPY app.py .
9
- COPY ./templates/index.html /code/templates/index.html
10
  COPY ./requirements.txt /code/requirements.txt
11
 
12
  # Install the required packages
@@ -27,4 +27,4 @@ COPY --chown=user . $HOME/app
27
  EXPOSE 7860
28
 
29
  # Start the Flask app
30
- CMD ["python", "app.py"]
 
5
  WORKDIR /code
6
 
7
  # Copy the required files to the working directory
8
+ COPY app_socket_multi_threaded.py .
9
+ COPY ./templates/index_socket.html /code/templates/index_socket.html
10
  COPY ./requirements.txt /code/requirements.txt
11
 
12
  # Install the required packages
 
27
  EXPOSE 7860
28
 
29
  # Start the Flask app
30
+ CMD ["python", "app_socket_multi_threaded.py"]
app_graph_test.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, jsonify
2
+ from flask_socketio import SocketIO
3
+ import yfinance as yf
4
+ from datetime import datetime, timedelta
5
+ import plotly.graph_objs as go
6
+
7
+ app = Flask(__name__)
8
+ socketio = SocketIO(app)
9
+
10
+ @app.route("/")
11
+ def index():
12
+ return render_template("test.html")
13
+
14
+ @socketio.on('get_graph')
15
+ def get_graph(ticker):
16
+ # Define the stock ticker symbol and the date range
17
+ ticker_symbol = ticker
18
+ end_date = datetime.today()
19
+ start_date = end_date - timedelta(days=90)
20
+
21
+ # Fetch historical data using yfinance
22
+ data = yf.download(ticker_symbol, start=start_date, end=end_date)
23
+
24
+ # Create a candlestick graph using Plotly
25
+ fig = go.Figure(data=[go.Candlestick(x=data.index.strftime('%Y-%m-%d').tolist(),
26
+ open=data['Open'].tolist(),
27
+ high=data['High'].tolist(),
28
+ low=data['Low'].tolist(),
29
+ close=data['Close'].tolist())])
30
+
31
+ # Customize the layout
32
+ fig.update_layout(title=f'Candlestick Chart for {ticker_symbol} in the Last 90 Days',
33
+ xaxis_title='Date',
34
+ yaxis_title='Price',
35
+ xaxis_rangeslider_visible=False)
36
+
37
+ # # convert the fig to HTML DIV element
38
+ # graph_html = fig.to_html(full_html=False,include_plotlyjs = False)
39
+ # print(len(graph_html))
40
+ # # socketio.emit('graph', fig.to_html(full_html=False,include_plotlyjs = False))
41
+ graph_data = fig.to_plotly_json()
42
+ socketio.emit('graph',graph_data)
43
+ print("Graph is finished")
44
+
45
+ if __name__ == "__main__":
46
+ socketio.run(app, host='0.0.0.0', port=7860)
app_socket_multi_threaded.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template
2
+ from flask_socketio import SocketIO
3
+ from transformers import pipeline
4
+ import yfinance as yf
5
+ import requests
6
+ from newspaper import Article
7
+ from newspaper import Config
8
+ from bs4 import BeautifulSoup
9
+ from datetime import datetime, timedelta
10
+ import plotly.graph_objs as go
11
+ from transformers import BertTokenizer, BertForSequenceClassification
12
+ from transformers import BartForConditionalGeneration, BartTokenizer
13
+ import threading
14
+
15
+ app = Flask(__name__)
16
+ socketio = SocketIO(app)
17
+
18
+ news_data = []
19
+
20
+ # Set up sentiment analysis and summarization pipelines
21
+ finbert = BertForSequenceClassification.from_pretrained('yiyanghkust/finbert-tone', num_labels=3)
22
+ sentiment_tokenizer = BertTokenizer.from_pretrained('yiyanghkust/finbert-tone')
23
+ summarization_model = BartForConditionalGeneration.from_pretrained("facebook/bart-large", forced_bos_token_id=0)
24
+ summarization_tokenizer = BartTokenizer.from_pretrained("facebook/bart-large")
25
+ sentiment_analysis_pipeline = pipeline("sentiment-analysis", model=finbert, tokenizer=sentiment_tokenizer, truncation=True, max_length=512)
26
+ summarization_pipeline = pipeline("summarization", model=summarization_model, tokenizer=summarization_tokenizer, max_length=512, truncation=True)
27
+
28
+ # News API setup
29
+ def get_news_articles_info(ticker_name):
30
+ # URL of the search results page
31
+ url = "https://www.marketwatch.com/search?q=" + ticker_name + "&ts=0&tab=All%20News"
32
+
33
+ # Send an HTTP GET request to the URL
34
+ response = requests.get(url)
35
+
36
+ # Parse the HTML content using BeautifulSoup
37
+ soup = BeautifulSoup(response.content, "html.parser")
38
+
39
+ article_links = []
40
+
41
+ for content in soup.find_all("h3",class_="article__headline"):
42
+ for link in content.find_all("a"):
43
+ if link['href'] != "#":
44
+ article_links.append(link['href'])
45
+
46
+ article_links = article_links[18:36]
47
+ ticker_news_extracted = []
48
+ count = 0
49
+ for link in article_links:
50
+ article_info = {}
51
+ article_info['text'] = ''
52
+ article_info['url'] = link
53
+ try:
54
+ url = article_info['url']
55
+ url = requests.head(url, allow_redirects=True).url
56
+
57
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36'
58
+ config = Config()
59
+ config.browser_user_agent = user_agent
60
+
61
+ article = Article(url, config=config)
62
+ article.download()
63
+ article.parse()
64
+ article_info['title'] = article.title
65
+ article_info['text'] = article.text
66
+ article_info['url'] = url
67
+ count = count + 1
68
+ print(count,url)
69
+ socketio.emit('log',str(count) + " " + url)
70
+ except Exception as error:
71
+ print("Error",url,error)
72
+ continue
73
+ if article_info['text'] == '':
74
+ print('No text',url)
75
+ continue
76
+ if count > 5:
77
+ break
78
+ ticker_news_extracted.append(article_info)
79
+ return ticker_news_extracted
80
+
81
+ @app.route("/")
82
+ def index():
83
+ global news_data
84
+ news_data = []
85
+ socketio.emit('news_data',news_data)
86
+ return render_template("index_socket.html")
87
+
88
+ @socketio.on('get_graph')
89
+ def get_graph(ticker):
90
+ # Define the stock ticker symbol and the date range
91
+
92
+ ticker_symbol = ticker # Example: Apple Inc.
93
+ end_date = datetime.today()
94
+ start_date = end_date - timedelta(days=90)
95
+
96
+ # Fetch historical data using yfinance
97
+ data = yf.download(ticker_symbol, start=start_date, end=end_date)
98
+
99
+ # Create a candlestick graph using Plotly
100
+ fig = go.Figure(data=[go.Candlestick(x=data.index.strftime('%Y-%m-%d').tolist(),
101
+ open=data['Open'].tolist(),
102
+ high=data['High'].tolist(),
103
+ low=data['Low'].tolist(),
104
+ close=data['Close'].tolist())])
105
+
106
+ # Customize the layout
107
+ fig.update_layout(title=f'Candlestick Chart for {ticker_symbol} in the Last 90 Days',
108
+ xaxis_title='Date',
109
+ yaxis_title='Price',
110
+ xaxis_rangeslider_visible=False)
111
+
112
+ # convert the fig to HTML DIV element
113
+ graph_data = fig.to_plotly_json()
114
+ socketio.emit('graph',graph_data)
115
+ print("Graph is finished")
116
+
117
+ def get_sentiment(_index,_content):
118
+ _sentiment = sentiment_analysis_pipeline(_content)[0]
119
+ news_data[_index]['sentiment'] = _sentiment["label"]
120
+ news_data[_index]['sentiment_score'] = round(_sentiment["score"], 3)
121
+ socketio.emit('news_data',news_data)
122
+
123
+ def get_summary(_index,_content):
124
+ _summary = summarization_pipeline(_content, max_length=100, min_length=30, do_sample=False)[0]["summary_text"]
125
+ news_data[_index]['summary'] = _summary
126
+ socketio.emit('news_data', news_data)
127
+
128
+
129
+ @socketio.on('get_news_data')
130
+ def get_news_data(ticker):
131
+
132
+ global news_data
133
+ news_data = []
134
+ socketio.emit('news_data',news_data)
135
+
136
+ # Get top 5 news articles for the given ticker
137
+ search_results = get_news_articles_info(ticker_name=ticker)
138
+ articles = search_results[:5]
139
+
140
+ for article in articles:
141
+ news_data.append({
142
+ "title": article['title'],
143
+ "link": article['url'],
144
+ "sentiment": 'Loading...',
145
+ "sentiment_score": 'Loading...',
146
+ "summary": 'Loading...',
147
+ "Ticker": ticker
148
+ })
149
+
150
+ socketio.emit('news_data',news_data)
151
+
152
+ threads_list = []
153
+
154
+ for i in range(0,len(articles)):
155
+ article = articles[i]
156
+ link = article['url']
157
+ content = article['text']
158
+
159
+ t1 = threading.Thread(target=get_sentiment, args=(i,content))
160
+ t2 = threading.Thread(target=get_summary, args=(i,content))
161
+
162
+ t1.start()
163
+ t2.start()
164
+
165
+ threads_list.append(t1)
166
+ threads_list.append(t2)
167
+
168
+ socketio.emit('log',link + " Analysis started")
169
+
170
+ for thread in threads_list:
171
+ thread.join()
172
+
173
+ socketio.emit('log','Analysis is finished')
174
+
175
+ if __name__ == "__main__":
176
+ socketio.run(app, host='0.0.0.0', port=7860)
static/css/styles.css ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Body styles */
2
+ body {
3
+ font-family: Arial, sans-serif;
4
+ background-color: #f3f3f3;
5
+ margin: 0;
6
+ padding: 0;
7
+ }
8
+
9
+ /* Page container styles */
10
+ .container {
11
+ max-width: 800px;
12
+ margin: 0 auto;
13
+ padding: 20px;
14
+ background-color: #fff;
15
+ border: 1px solid #ccc;
16
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
17
+ }
18
+
19
+ /* Header styles */
20
+ h1 {
21
+ text-align: center;
22
+ color: #333;
23
+ }
24
+
25
+ /* Header styles */
26
+ h2 {
27
+ text-align: center;
28
+ color: #333;
29
+ }
30
+
31
+ /* Form styles */
32
+ form {
33
+ text-align: center;
34
+ margin-top: 20px;
35
+ }
36
+
37
+ label {
38
+ font-weight: bold;
39
+ }
40
+
41
+ input[type="text"] {
42
+ width: 15%; /* Set the width to 25% of the parent container */
43
+ padding: 10px;
44
+ margin: 5px auto; /* Center the input horizontally */
45
+ display: block; /* Make it a block-level element for centering */
46
+ border: 1px solid #ccc;
47
+ border-radius: 4px;
48
+ }
49
+
50
+ button {
51
+ background-color: #007BFF;
52
+ color: #fff;
53
+ border: none;
54
+ padding: 10px 20px;
55
+ cursor: pointer;
56
+ border-radius: 4px;
57
+ }
58
+
59
+ button:hover {
60
+ background-color: #0056b3;
61
+ }
62
+
63
+ /* Log and News Data styles */
64
+ #log, #newsData {
65
+ padding: 20px;
66
+ margin-top: 20px;
67
+ /* background-color: #fff; */
68
+ /* border: 1px solid #ccc; */
69
+ /* box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); */
70
+ }
71
+
72
+ /* Stock Graph styles */
73
+ #stock_graph {
74
+ margin-top: 20px;
75
+ /* background-color: #fff; */
76
+ /* border: 1px solid #ccc; */
77
+ /* box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); */
78
+ padding: 20px;
79
+ }
80
+
81
+ /* Table styles for News Data */
82
+ #newsTable {
83
+ width: 100%;
84
+ border-collapse: collapse;
85
+ }
86
+
87
+ #newsTable th, #newsTable td {
88
+ border: 1px solid #ccc;
89
+ padding: 10px;
90
+ }
91
+
92
+ #newsTable th {
93
+ background-color: #f0f0f0;
94
+ }
95
+
96
+ /* Links in News Data */
97
+ #newsTable a {
98
+ text-decoration: none;
99
+ color: #007BFF;
100
+ }
101
+
102
+ #newsTable a:hover {
103
+ text-decoration: underline;
104
+ }
105
+
106
+ /* No news data message */
107
+ #newsData p {
108
+ text-align: center;
109
+ color: #888;
110
+ }
templates/index_socket.html ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Stock Information App</title>
5
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
6
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
7
+ <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='css/styles.css') }}">
8
+ </head>
9
+ <body>
10
+ <h1>Stock Information App</h1>
11
+
12
+ <form onsubmit="getInformation(); return false;">
13
+ <label for="ticker">Enter Ticker:</label>
14
+ <input type="text" id="ticker" required>
15
+ <button type="submit">Get Information</button>
16
+ </form>
17
+
18
+ <div id = "log">
19
+ <!-- Here the log will be displayed -->
20
+ </div>
21
+
22
+ <div id = "newsData">
23
+ <!-- News data will be displayed here -->
24
+ </div>
25
+
26
+ <div>
27
+ <h2 id = "graph_title"></h2>
28
+ <div id = "stock_graph">
29
+ <!-- The candlestick graph will be displayed here -->
30
+ </div>
31
+ </div>
32
+
33
+ <script>
34
+ var socket = io.connect('http://' + document.domain + ':' + location.port);
35
+
36
+ function getInformation() {
37
+ var ticker = document.getElementById('ticker').value;
38
+ socket.emit('get_graph',ticker);
39
+ socket.emit('get_news_data', ticker);
40
+ }
41
+
42
+ socket.on('log', function(data) {
43
+ var graphDiv = document.getElementById('log');
44
+ graphDiv.innerHTML = "Log: " + data;
45
+ console.log(data)
46
+ });
47
+
48
+ socket.on('graph', function(graphData) {
49
+ document.getElementById("graph_title").innerHTML = '';
50
+ var graphDiv = document.getElementById('stock_graph');
51
+ graphDiv.innerHTML = '';
52
+ console.log(graphData);
53
+ if (graphData != '')
54
+ {
55
+ Plotly.newPlot(graphDiv, graphData.data, graphData.layout);
56
+ document.getElementById("graph_title").innerHTML = "Stock Opening and Closing Data";
57
+ }
58
+ else
59
+ {
60
+ document.getElementById("graph_title").innerHTML = "Stock Opening and Closing Data";
61
+ graphDiv.innerHTML = '<center><p>Not a valid Ticker.</p></center>';
62
+ }
63
+ });
64
+
65
+ socket.on('news_data', function(data) {
66
+ // Handle the received news data and update the DOM
67
+ var newsDataDiv = document.getElementById('newsData');
68
+ newsDataDiv.innerHTML = ''; // Clear previous data
69
+
70
+ if (data.length > 0) {
71
+ var table = document.createElement('table');
72
+ table.id = 'newsTable';
73
+ table.innerHTML = `
74
+ <thead>
75
+ <tr>
76
+ <th>Title</th>
77
+ <th>Sentiment</th>
78
+ <th>Summary</th>
79
+ <th>Full Article</th>
80
+ </tr>
81
+ </thead>
82
+ <tbody>
83
+ </tbody>
84
+ `;
85
+
86
+ var tbody = table.querySelector('tbody');
87
+ data.forEach(function(article) {
88
+ var row = document.createElement('tr');
89
+ row.innerHTML = `
90
+ <td>${article.title}</td>
91
+ <td>${article.sentiment} (Score: ${article.sentiment_score})</td>
92
+ <td>${article.summary}</td>
93
+ <td><a href="${article.link}" target="_blank">Read full article</a></td>
94
+ `;
95
+ tbody.appendChild(row);
96
+ });
97
+
98
+ newsDataDiv.appendChild(table);
99
+ } else {
100
+ newsDataDiv.innerHTML = '<p>No news data available. or still searching for News</p>';
101
+ }
102
+ });
103
+ </script>
104
+ </body>
105
+ </html>
templates/test.html ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Stock Information App Testing</title>
5
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
6
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
7
+ <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='css/styles.css') }}">
8
+ </head>
9
+ <body>
10
+ <h1>Stock Information App</h1>
11
+
12
+ <form onsubmit="getInformation(); return false;">
13
+ <label for="ticker">Enter Ticker:</label>
14
+ <input type="text" id="ticker" required>
15
+ <button type="submit">Get Information</button>
16
+ </form>
17
+
18
+ <div>
19
+ <h2>Stock Opening and Closing Data</h2>
20
+ <div id = "stock_graph">
21
+ <!-- The candlestick graph will be displayed here -->
22
+ </div>
23
+ </div>
24
+
25
+ <script>
26
+ var socket = io.connect('http://' + document.domain + ':' + location.port);
27
+
28
+ function getInformation() {
29
+ var ticker = document.getElementById('ticker').value;
30
+ socket.emit('get_graph',ticker);
31
+ }
32
+
33
+ socket.on('graph', function(graphData) {
34
+ var graphDiv = document.getElementById('stock_graph');
35
+ graphDiv.innerHTML = '';
36
+ Plotly.newPlot(graphDiv, graphData.data, graphData.layout);
37
+ });
38
+ </script>
39
+ </body>
40
+ </html>