-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathapp.py
264 lines (214 loc) · 8.87 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
import os
import sys
import json
import gym
import argparse
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
import tqdm
# Get prediction model
from core.model import Model
from GA.ga import GeneticNetworks
from keras.backend.tensorflow_backend import set_session
from keras.utils import to_categorical
from core.market_env_v0 import MarketEnvironmentV0
from core.utils import *
from misc.networks import get_session
import datetime # For datetime objects
import os.path # To manage paths
import sys # To find out the script name (in argv[0])
import pathlib
import pandas as pd
# CNN
from cnn_prediction.cnn_data_loader import CNNDataLoader
from cnn_prediction.cnn_data_loader_buy_sell import CNNDataLoaderBuySell
from cnn_prediction.cnn_model import CNNModel
from core.technical_analysis import add_technical_indicators_with_intervals
import keras_metrics
import tensorflow.keras.backend as K
from flask import Flask
from flask import request
from flask import jsonify
app = Flask(__name__)
def f1_score(y_true, y_pred): #taken from old keras source code
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
precision = true_positives / (predicted_positives + K.epsilon())
recall = true_positives / (possible_positives + K.epsilon())
f1_val = 2*(precision*recall)/(precision+recall+K.epsilon())
return f1_val
class InvalidUsage(Exception):
status_code = 400
def __init__(self, message, status_code=None, payload=None):
Exception.__init__(self)
self.message = message
if status_code is not None:
self.status_code = status_code
self.payload = payload
def to_dict(self):
rv = dict(self.payload or ())
rv['message'] = self.message
return rv
class CNNModel:
def __init__(self, model_folder):
self.session = tf.Session()
self.graph = tf.get_default_graph()
self.model_folder = model_folder
self.model = None
# for some reason in a flask app the graph/session needs to be used in the init else it hangs on other threads
with self.graph.as_default():
with self.session.as_default():
print("neural network initialised")
def load(self, file_name=None):
"""
:param file_name: [model_file_name, weights_file_name]
:return:
"""
with self.graph.as_default():
with self.session.as_default():
try:
model_name = file_name[0]
weights_name = file_name[1]
if model_name is not None:
# load the model
filepath = os.path.join(self.model_folder, model_name)
self.model = tf.keras.models.load_model(filepath, custom_objects={
"f1_score": f1_score,
"binary_precision": keras_metrics.precision(),
"binary_recall": keras_metrics.recall(),
})
if weights_name is not None:
# load the weights
weights_path = os.path.join(self.model_folder, weights_name)
self.model.load_weights(weights_path)
print("Neural Network loaded: ")
print('\t' + "Neural Network model: " + model_name)
print('\t' + "Neural Network weights: " + weights_name)
return True
except Exception as e:
print(e)
return False
def predict(self, x):
with self.graph.as_default():
with self.session.as_default():
y = self.model.predict(x)
return y
## Variables
configs = None
action_size = None
state_size = None
size = None
agent = None
cnn_cols = None
cols = None
model = None
graph = None
def load_config():
global configs
configs = json.load(open('config-EURUSD-30M_v3.0141.json', 'r'))
def load_hyperparameters():
print(">>>>>>>>>>>>>>> ...Loading hyperparameters")
global action_size
global state_size
global size
action_size = 3 # 3 possible actions: sit, buy, sell
state_size = 15
size = 347
print(">>>>>>>>>>>>>>> Hyperparameters loaded")
def load_ga_agent():
print(">>>>>>>>>>>>>>> ...Loading agent")
global agent
ga = GeneticNetworks(architecture=(state_size, ) + tuple(configs['agent']['layers']) + (action_size,),
population_size=configs['agent']['params']['population_size'],
generations=configs['agent']['params']['generations'],
episodes=configs['agent']['params']['episodes'],
mutation_variance=configs['agent']['params']['mutation_variance'],
render_env=False,
survival_ratio=configs['agent']['params']['survival_ratio'],
verbose=True)
ga.load_weights(configs['agent']['best_agent'])
agent = ga.best_network
print(">>>>>>>>>>>>>>> Agent loaded")
def load_cnn():
print(">>>>>>>>>>>>>>> ...Loading CNN")
global cnn_cols
global cols
global model
model = CNNModel('saved_models')
model.load([configs['model']['pre_trained_model'], configs['model']['pre_trained_weights']])
# Get CNN cols
cnn_cols = []
for indicator in configs['model']['inputs']['technical_indicators']:
for interval in configs['model']['inputs']['intervals']:
cnn_cols.append(indicator + '_' + str(interval))
img_size = len(configs['model']['inputs']['technical_indicators'])
# Get cols
cols = []
# Add detrend OHLC
for col in [a for a in configs['agent']['cols'] if configs['agent']['cols'][a]["detrend"]]:
cols.append(col + '_detrend')
for col in [a for a in configs['agent']['cols'] if not configs['agent']['cols'][a]["detrend"]]:
cols.append(col)
# Add technical indicators
for indicator in configs['agent']['technical_indicators']:
for interval in configs['agent']['intervals']:
cols.append(indicator + '_' + str(interval))
print(">>>>>>>>>>>>>>> CNN loaded")
@app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
response = jsonify(error.to_dict())
response.status_code = error.status_code
return response
@app.route('/')
def hello_world():
return 'Hello, World!'
@app.route('/action/<market_code>', methods = ['POST'])
def signal(market_code):
data = request.json
if market_code == "EURUSD":
# Check input
if (not 'Close' in data) or (not 'Open' in data) or (not 'High' in data) or (not 'Low' in data):
raise InvalidUsage('The request must have a valid Open, High, Low, Close values', status_code=400)
if (len(data['Close']) < size) or (len(data['Open']) < size) or (len(data['High']) < size) or (len(data['Low']) < size):
raise InvalidUsage('We only accept request if more than ' + str(size) + ' candles', status_code=400)
df_ohlc = pd.DataFrame(data)
# Adding info detrend
for col in [a for a in configs['agent']['cols'] if configs['agent']['cols'][a]["detrend"]]:
df_ohlc[col + '_detrend'] = df_ohlc.get([col]) - df_ohlc.get([col]).shift()
# Get CNN prediction
dataloader = CNNDataLoaderBuySell(
df_ohlc,
indicators=configs['model']['inputs']['technical_indicators'],
intervals=configs['model']['inputs']['intervals'],
window_size=10
)
x, _ = dataloader.get_train_data(cnn_cols, window_size=15, class_unbalacing=False)
pred = model.predict(x)[-1]
print("Got CNN prediction ", pred.shape)
# Adding TA
df_ohlc = add_technical_indicators_with_intervals(
df_ohlc,
indicators=configs['agent']['technical_indicators'],
intervals=configs['agent']['intervals']
)
df_ohlc["CNNClassifier_hold"], df_ohlc["CNNClassifier_buy"], df_ohlc["CNNClassifier_sell"] = np.nan, np.nan, np.nan
df_ohlc["CNNClassifier_hold"].iloc[-1] = pred[0]
df_ohlc["CNNClassifier_buy"].iloc[-1] = pred[1]
df_ohlc["CNNClassifier_sell"].iloc[-1] = pred[2]
df_ohlc = df_ohlc.dropna()
print(df_ohlc)
state = df_ohlc.get(cols).values[-1]
action = agent.act(state)
print("Action ", action)
return jsonify({ 'action': str(action) })
else:
raise InvalidUsage('Not valid market code', status_code=400)
if __name__ == '__main__':
load_config()
load_hyperparameters()
load_ga_agent()
load_cnn()
app.run(debug=False, host='0.0.0.0')