halme commited on
Commit
95528fd
·
verified ·
1 Parent(s): e2c55d1

Upload 2 files

Browse files
Files changed (2) hide show
  1. DataLoader.py +119 -0
  2. app.py +87 -0
DataLoader.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #Class to fetch news and stock data from the web for a specific ticker and combine them into a dataframe.
2
+
3
+ import pandas as pd
4
+ import numpy as np
5
+ import requests
6
+ import matplotlib.pyplot as plt
7
+ import yfinance as yf
8
+ from datetime import datetime
9
+ from pygooglenews import GoogleNews
10
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
11
+ from transformers import pipeline
12
+ class DataLoader:
13
+ def __init__(self, ticker, time_period_news, time_period_stock, news_decay_rate = 0):
14
+ self.ticker = ticker
15
+ self.time_period_news = time_period_news
16
+ self.time_period_stock = time_period_stock
17
+ self.news_decay_rate = news_decay_rate
18
+
19
+ def get_data(self):
20
+ stock_data = self.get_stock_data()
21
+ news_data = self.get_news_data()
22
+ news_sentiment = self.get_sentiment(news_data)
23
+ combined_data = self.combine_data(stock_data, news_sentiment)
24
+
25
+ if self.news_decay_rate != 0:
26
+ combined_data = self.news_decay(combined_data, self.news_decay_rate)
27
+
28
+ return combined_data
29
+
30
+
31
+ def get_stock_data(self):
32
+ data = yf.download(self.ticker, period = self.time_period_stock)
33
+ df = pd.DataFrame()
34
+ df['Open'] = data['Open']
35
+ df['Close'] = data['Close']
36
+ df['High'] = data['High']
37
+ df['Low'] = data['Low']
38
+
39
+ return df
40
+
41
+ def get_news_data(self):
42
+ googlenews = GoogleNews()
43
+ news_data = googlenews.search(self.ticker, when=self.time_period_news)
44
+ news_data = pd.DataFrame(news_data['entries'])
45
+ return news_data
46
+
47
+ def get_sentiment(self, news_data):
48
+ tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
49
+ model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")
50
+ classifier = pipeline('sentiment-analysis', model=model, tokenizer=tokenizer)
51
+
52
+ news_sentiment = []
53
+ for i in range(len(news_data)):
54
+ sentiment = classifier(news_data['title'][i], top_k=None)
55
+ postive_score = sentiment[0]['score']
56
+ negative_score = sentiment[1]['score']
57
+ neutral_score = sentiment[2]['score']
58
+ reformmated_time_stamp = pd.to_datetime(news_data['published'][i]).date()
59
+ news_sentiment.append({'Date': reformmated_time_stamp, 'positive_score': postive_score, 'negative_score': negative_score, 'neutral_score': neutral_score})
60
+ return pd.DataFrame(news_sentiment)
61
+
62
+ def combine_data(self, stock_data, news_sentiment):
63
+ news_sentiment = (
64
+ news_sentiment
65
+ .groupby('Date')
66
+ .mean()
67
+ .fillna(0)
68
+ .reset_index()
69
+ .set_index('Date')
70
+ .sort_index()
71
+ )
72
+
73
+ common_index = pd.date_range(
74
+ start=pd.Timestamp(min(pd.Timestamp(stock_data.index[0]), pd.Timestamp(news_sentiment.index[0]))),
75
+ end=pd.Timestamp(max(pd.Timestamp(stock_data.index[-1]), pd.Timestamp(news_sentiment.index[-1]))),
76
+ freq='D'
77
+ )
78
+ stock_data = stock_data.reindex(common_index).fillna(-1)
79
+
80
+ news_sentiment = news_sentiment.reindex(common_index).fillna(0)
81
+
82
+ #Ensure stock_data and news_sentiment have combatile indices
83
+ stock_data.index = pd.to_datetime(stock_data.index).normalize()
84
+ news_sentiment.index = pd.to_datetime(news_sentiment.index).normalize()
85
+
86
+ combined_data = pd.merge(
87
+ stock_data,
88
+ news_sentiment,
89
+ how='left',
90
+ left_index=True,
91
+ right_index=True
92
+ )
93
+
94
+ #Drop all close values that are -1
95
+ combined_data = combined_data[combined_data['Close'] != -1]
96
+ #fill all missing values with 0
97
+ combined_data = combined_data.fillna(0)
98
+
99
+ return combined_data
100
+
101
+ def news_decay(self, Combined_data, decay_rate):
102
+ #We have lots of days in the data with no news. We will fill these days with the previous days news * decay_rate
103
+ #This will allow us to have a more continuous news data
104
+ combined_data = Combined_data.copy()
105
+ news_columns = ['positive_score', 'negative_score', 'neutral_score']
106
+ #We want to start from the oldest date and work our way to the newest date
107
+ for i in range(1, len(combined_data)):
108
+ for column in news_columns:
109
+ if combined_data[column][i] == 0:
110
+ combined_data[column][i] = combined_data[column][i-1] * decay_rate
111
+ return combined_data
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
app.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import pipeline
3
+ import yfinance as yf
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+ import hopsworks
7
+ import tensorflow as tf
8
+ from tensorflow.keras.layers import LSTM, Dense
9
+ from tensorflow.keras.models import load_model
10
+ from DataLoader import DataLoader
11
+ from sklearn.preprocessing import MinMaxScaler
12
+
13
+ # Function to generate a sine wave plot
14
+ def predict(index_name="^OMX"):
15
+ # Load the model
16
+ project = hopsworks.login(api_key_value="pwWjyzF8SYsYJGQp.uZRknwAGCDPMe2covG1e4uVY4LsJXhAyKYgUNADOGY3H67mRAzoBtEJGlskTWE8h")
17
+ mr = project.get_model_registry()
18
+ model = mr.get_model("FinanceModel", version=9)
19
+ saved_model_dir = model.download()
20
+ model = load_model(saved_model_dir + "/model.keras")
21
+
22
+ #Fetch the data used to train the model
23
+ time_period_news = '30d'
24
+ time_period_price = '3mo' #Needed to make sure we get 30 days of price data. Stock markets are closed on weekends and holidays
25
+ data_loader = DataLoader(index_name, time_period_news, time_period_price)
26
+ data = data_loader.get_data()
27
+
28
+ #Get the previous closing price
29
+ previous_closing_price = data['Close'].values
30
+ #Remove uneccessary data and scale the data
31
+ #The modell only takes the latest 30 days of data
32
+ data = data[-30:]
33
+
34
+ #Load the input and output scalers used to train the model
35
+ input_scaler = MinMaxScaler()
36
+ output_scaler = MinMaxScaler()
37
+
38
+ #Create a fake output data to fit the scaler
39
+ output_scaler.fit_transform(previous_closing_price.reshape(-1, 1))
40
+
41
+ #Scale the data
42
+ data = input_scaler.fit_transform(data)
43
+
44
+ #Format the data to be used by the model. The model expects the data to be in the shape (1, 30, 7)
45
+ data = data.reshape(1, 30, 7)
46
+ prediction = model.predict(data)
47
+
48
+ #Inverse the scaling
49
+ prediction = output_scaler.inverse_transform(prediction)[0]
50
+ print(prediction)
51
+
52
+ # predicted_value = index_close_price_list[-1] + 10
53
+
54
+ # Create the plot
55
+ fig, ax = plt.subplots(figsize=(8, 4))
56
+ ax.plot(range(len(previous_closing_price)), previous_closing_price, label="True Values", color="blue")
57
+ predicted_indices = np.arange(len(previous_closing_price), len(previous_closing_price) + len(prediction))
58
+ ax.scatter(predicted_indices, prediction, color="red", label="Predicted Value")
59
+ ax.axvline(len(previous_closing_price) - 1, linestyle="--", color="gray", alpha=0.6)
60
+ ax.set_title(f"Prediction for {index_name}")
61
+ ax.set_xlabel("Time")
62
+ ax.set_ylabel("Index Value")
63
+ ax.legend()
64
+
65
+ """ fig, ax = plt.subplots(figsize=(8, 4))
66
+ ax.plot(previous_closing_price, label='Previous Closing Prices', linestyle='--',)
67
+
68
+ # Create an array of indices for the predicted values, right after the last index of prev_closing
69
+ predicted_indices = np.arange(len(previous_closing_price), len(previous_closing_price) + len(prediction))
70
+
71
+ # Plot the predicted closing prices in red, using the correct indices
72
+ ax.plot(predicted_indices, prediction, color='red', label='Predicted Prices',linestyle='--',) """
73
+
74
+ return fig
75
+
76
+ # Create the Gradio interface
77
+ interface = gr.Interface(
78
+ fn=predict,
79
+ inputs=gr.Textbox(label="Financial Index Name", placeholder="Enter the name of the financial index..."),
80
+ outputs=gr.Plot(label="Index Prediction Plot"),
81
+ title="Financial Index Predictor",
82
+ description="Enter the name of a financial index to generate a plot showing true values for the past 30 days and the predicted value."
83
+ )
84
+
85
+ # Launch the app
86
+ if __name__ == "__main__":
87
+ interface.launch()