Skip to content

Commit 3d2dde6

Browse files
authored
Safe to demo (and awesome B)) Merge pull request #78 from ShaynAli/dev
The awesome update B)
2 parents a3696e4 + 7349c6f commit 3d2dde6

File tree

13 files changed

+162
-46
lines changed

13 files changed

+162
-46
lines changed

src/activities/stock_prediction/stock_arena.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
from arena.arena import MachineLearningArena
2-
from activities.stock_prediction.stock_prediction import FrankfurtStockPrediction
3-
from activities.stock_prediction.stock_prediction_models import RandomRangePredictor
2+
from activities.stock_prediction.stock_prediction_models import *
43
import pprint
54

65
if __name__ == '__main__':
76

8-
arena = MachineLearningArena(model_pool=[RandomRangePredictor], activity=FrankfurtStockPrediction)
7+
arena = MachineLearningArena(model_pool=[ShallowNeuralNetworkPredictor], activity=FrankfurtStockPrediction)
98
printer = pprint.PrettyPrinter()
109
for _ in range(10):
1110
arena.auto_compete()

src/activities/stock_prediction/stock_prediction.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from activities.activities import MachineLearningActivity
22
import quandl
3-
from _datetime import date, timedelta
4-
import pdb
53
import numpy as np
64
from datetime import date
75
from dateutil.relativedelta import relativedelta
@@ -196,6 +194,8 @@ class FrankfurtStockPrediction(MachineLearningActivity):
196194

197195
default_guess_tickers = ['CON_X']
198196

197+
n_days = 20
198+
199199
def __init__(self, tickers=default_tickers, guess_tickers=default_guess_tickers):
200200
quandl.ApiConfig.api_key = 'z3rsXS2rz9ZXCe76xozE'
201201
self.code = 'FSE'
@@ -204,11 +204,11 @@ def __init__(self, tickers=default_tickers, guess_tickers=default_guess_tickers)
204204

205205
@property
206206
def x_shape(self):
207-
return len(self.tickers), None
207+
return FrankfurtStockPrediction.n_days, len(self.tickers)
208208

209209
@property
210210
def y_shape(self):
211-
return len(self.guess_tickers), None
211+
return FrankfurtStockPrediction.n_days, len(self.guess_tickers)
212212

213213
def next_data(self):
214214
from random import choice
@@ -237,13 +237,18 @@ def next_data(self):
237237
except ValueError:
238238
return self.next_data()
239239

240-
return tickers, guess_tickers
240+
x = np.transpose(tickers)[:FrankfurtStockPrediction.n_days, :]
241+
y = np.transpose(guess_tickers)[:FrankfurtStockPrediction.n_days, :]
242+
243+
return x, y
241244

242245
def get_ticker(self, ticker, start_date, end_date, field='Open'):
243246
return quandl.get(f'{self.code}/{ticker}', returns='numpy', start_date=start_date, end_date=end_date)[field]
244247

245248

246249
if __name__ == '__main__':
247250
activity = FrankfurtStockPrediction()
248-
data = [activity.next_data() for _ in range(3)]
249-
pdb.set_trace()
251+
while True:
252+
x, y = activity.next_data()
253+
from pdb import set_trace
254+
set_trace()

src/activities/stock_prediction/stock_prediction_models.py

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from activities.stock_prediction.stock_prediction import FrankfurtStockPrediction
22
import numpy as np
3+
from keras import Sequential
4+
from keras.layers import Dense, Activation
5+
from random import randint
36

47

58
class RandomRangePredictor(FrankfurtStockPrediction.Model):
@@ -18,4 +21,88 @@ def predict(self, x):
1821

1922
@staticmethod
2023
def description():
21-
return '''Predicts within a range range, which is updated base on y data.'''
24+
return '''Predicts within a random range. The max and min of the range are updated based on y data.'''
25+
26+
27+
class MeanPredictor(FrankfurtStockPrediction.Model):
28+
29+
def __init__(self, activity):
30+
super().__init__(activity)
31+
32+
def train(self, x, y):
33+
pass
34+
35+
def predict(self, x):
36+
return np.full(shape=(self.y_shape[0], x.shape[1]), fill_value=np.mean(x))
37+
38+
@staticmethod
39+
def description():
40+
return '''Predicts that every stock will have the same mean price overall.'''
41+
42+
43+
class MeanRowPredictor(FrankfurtStockPrediction.Model):
44+
45+
def __init__(self, activity):
46+
super().__init__(activity)
47+
48+
def train(self, x, y):
49+
pass
50+
51+
def predict(self, x):
52+
n_y_cols = self.y_shape[1]
53+
prediction = np.empty(shape=self.y_shape)
54+
for row_i in range(x.shape[0]):
55+
row_mean = np.mean(x[row_i, :])
56+
prediction[:, row_i] = [row_mean] * n_y_cols
57+
return prediction
58+
59+
@staticmethod
60+
def description():
61+
return '''Predicts that every stock will have the same mean price at every time interval.'''
62+
63+
64+
class ShallowNeuralNetworkPredictor(FrankfurtStockPrediction.Model):
65+
66+
def __init__(self, activity):
67+
super().__init__(activity)
68+
self.neural_network = Sequential([
69+
Dense(32, input_shape=(self.x_shape[1],)),
70+
Dense(self.y_shape[1])
71+
])
72+
self.neural_network.compile(
73+
optimizer='nadam',
74+
loss='mse'
75+
)
76+
77+
def train(self, x, y):
78+
self.neural_network.fit(x=x, y=y)
79+
80+
def predict(self, x):
81+
return self.neural_network.predict(x)
82+
83+
@staticmethod
84+
def description():
85+
return '''Uses a shallow, wide neural network.'''
86+
87+
88+
class RandomDepthNeuralNetworkPredictor(FrankfurtStockPrediction.Model):
89+
90+
def __init__(self, activity):
91+
super().__init__(activity)
92+
self.neural_network = Sequential([Dense(8, input_shape=(self.x_shape[1],))] +
93+
[Dense(8) for _ in range(randint(0, 8))] +
94+
[Dense(self.y_shape[1])])
95+
self.neural_network.compile(
96+
optimizer='nadam',
97+
loss='mse'
98+
)
99+
100+
def train(self, x, y):
101+
self.neural_network.fit(x=x, y=y)
102+
103+
def predict(self, x):
104+
return self.neural_network.predict(x)
105+
106+
@staticmethod
107+
def description():
108+
return '''Creates a neural network of depth from 2-10.'''

src/arena/arena.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
""" arena.py - Where ML and AI bots go to face off """
21
import evaluation
32
from random import choice
4-
3+
from pandas import isnull
54

65
class MachineLearningArena:
76

8-
def __init__(self, model_pool, activity, generation_size=10):
7+
def __init__(self, model_pool, activity, score_function=evaluation.DEFAULT_SCORE_FUNCTION, generation_size=10):
98
self.model_pool = model_pool
109
self.activity = activity()
10+
self.score_function = score_function
1111
self.models = list(self.new_models(n_models=generation_size))
1212
self.score_history = []
1313

@@ -17,8 +17,8 @@ def new_model(self):
1717
def new_models(self, n_models):
1818
return (self.new_model() for _ in range(n_models))
1919

20-
def compete(self, x, y, live_ratio=0.5, score_function=evaluation.DEFAULT_SCORE_FUNCTION):
21-
model_score = {m: evaluation.score(m, x, y, score_function=score_function) for m in self.models}
20+
def compete(self, x, y, live_ratio=0.5):
21+
model_score = {m: evaluation.score(m, x, y, score_function=self.score_function) for m in self.models}
2222
self.score_history.append(model_score)
2323
score_ranking = sorted(model_score.keys(), key=lambda model: model_score[model], reverse=True)
2424
from utilities import partition_indices
@@ -27,5 +27,6 @@ def compete(self, x, y, live_ratio=0.5, score_function=evaluation.DEFAULT_SCORE_
2727

2828
def auto_compete(self, live_ratio=0.5):
2929
x, y = self.activity.next_data()
30-
self.compete(x=x, y=y, live_ratio=live_ratio, score_function=evaluation.DEFAULT_SCORE_FUNCTION)
31-
30+
while isnull(x).any() or isnull(y).any():
31+
x, y = self.activity.next_data()
32+
self.compete(x=x, y=y, live_ratio=live_ratio)

src/data_utils/visualization.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import bokeh
22
from bokeh.plotting import figure, output_file, show
3-
import pdb
3+
from random import choice
44

55
plot_dimensions = (1225, 600)
66

7+
colors = {}
8+
9+
10+
def random_color(k):
11+
if k in colors:
12+
return colors[k]
13+
digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
14+
new_color = f'#{choice(digits)}{choice(digits)}{choice(digits)}{choice(digits)}{choice(digits)}{choice(digits)}'
15+
colors[k] = new_color
16+
return new_color
17+
718

819
def plot_line(data_class, x_label, y_label):
920
# Use hover tool
@@ -60,19 +71,19 @@ def multi_line(data, x_label="X", y_label="Y"):
6071
for k, v in data.items():
6172
generations = [e[0] for e in v]
6273
scores = [e[1] for e in v]
63-
p.line(generations, scores, line_width=2, legend=k[:8])
74+
p.line(generations, scores, line_width=2, legend=k, line_color=random_color(k))
6475
p.legend.click_policy = "hide"
6576

6677
p.plot_width, p.plot_height = plot_dimensions
6778
p.toolbar.logo = "grey"
6879
p.toolbar.autohide = True
80+
p.legend.location = "top_left"
6981
p.background_fill_color = "#dddddd"
7082
p.hover.tooltips = [
7183
(x_label, "@x"),
7284
(y_label, "@y")
7385
]
7486

75-
# Return the plot for display purposes
7687
return p
7788

7889

src/evaluation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def complement_mean_pct_error(predicted, actual):
7070

7171
# region Model scoring
7272

73-
DEFAULT_SCORE_FUNCTION = inv_norm_err
73+
DEFAULT_SCORE_FUNCTION = complement_mean_pct_error
7474
DEFAULT_ERROR_FUNCTION = rms_error
7575
DEFAULT_TRACK_FUNCTION = rms_error
7676

src/requirements.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
numpy
1+
numpy==1.16
2+
flask
23
bokeh
3-
quandl
44
scikit-learn
5-
flask
5+
keras
6+
tensorflow
7+
quandl
8+
pandas

src/server/assets/favicon.ico

98.5 KB
Binary file not shown.

src/server/assets/favicon.png

137 Bytes
Loading

src/server/assets/style.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ table tr:nth-child(even) {
8989
background: #23283C;
9090
}
9191

92+
#leader-board table td {
93+
font-size: 90%;
94+
}
95+
96+
option {
97+
font-size: 120%;
98+
}
99+
92100
.preview {
93101
background-color: #23283C;
94102
font-family: 'Ubuntu Mono', monospace;

0 commit comments

Comments
 (0)