304 lines
11 KiB
Python
304 lines
11 KiB
Python
|
|
import os
|
||
|
|
import numpy as np
|
||
|
|
import pandas as pd
|
||
|
|
|
||
|
|
from pandas.plotting import autocorrelation_plot
|
||
|
|
from statsmodels.tsa.arima_model import ARIMA
|
||
|
|
|
||
|
|
from keras.models import Sequential
|
||
|
|
from keras.layers import LSTM, Dense
|
||
|
|
|
||
|
|
from sklearn.preprocessing import MinMaxScaler, normalize
|
||
|
|
from sklearn.linear_model import LinearRegression, Ridge
|
||
|
|
from sklearn.metrics import mean_squared_error
|
||
|
|
from sklearn.tree import DecisionTreeRegressor
|
||
|
|
from sklearn.ensemble import (AdaBoostRegressor, BaggingRegressor,
|
||
|
|
ExtraTreesRegressor, GradientBoostingRegressor,
|
||
|
|
RandomForestRegressor)
|
||
|
|
|
||
|
|
import tensorflow as tf
|
||
|
|
from tensorflow.contrib import rnn
|
||
|
|
|
||
|
|
import matplotlib.pyplot as plt
|
||
|
|
|
||
|
|
file = 'history/AUD_JPY_D.csv'
|
||
|
|
folder = 'history/'
|
||
|
|
|
||
|
|
def walk_folder(folder):
|
||
|
|
|
||
|
|
all_files = list()
|
||
|
|
for files in os.walk(folder):
|
||
|
|
for f in files[2]:
|
||
|
|
f = os.path.join(folder, f)
|
||
|
|
all_files.append(f)
|
||
|
|
|
||
|
|
return all_files
|
||
|
|
|
||
|
|
# TODO: test this some more, it works with Keras and sklearn; but had trouble with TF.
|
||
|
|
def split_data(X, y, n, split, o):
|
||
|
|
|
||
|
|
m = int(n * split)
|
||
|
|
X_train, X_test = X[0:m], X[m:n-o]
|
||
|
|
y_train, y_test = y[o:m+o], y[m+o:n]
|
||
|
|
|
||
|
|
return X_train, X_test, y_train, y_test
|
||
|
|
|
||
|
|
def tf_nn_research(file, epochs=10, split=0.6, o=1):
|
||
|
|
# import data and clean it for processing
|
||
|
|
df = pd.read_csv(file)
|
||
|
|
df = df[['Close', 'Open','High', 'Low']]
|
||
|
|
n = df.shape[0]
|
||
|
|
p = df.shape[1]
|
||
|
|
data = df.values
|
||
|
|
# Training and test data; split_data doesn't work too well with TF atm
|
||
|
|
train_start = 0
|
||
|
|
train_end = int(0.6*n)
|
||
|
|
test_start = train_end + 1
|
||
|
|
test_end = n
|
||
|
|
data_train = data[np.arange(train_start, train_end), :]
|
||
|
|
data_test = data[np.arange(test_start, test_end), :]
|
||
|
|
# Scale data
|
||
|
|
scaler = MinMaxScaler(feature_range=(-1, 1))
|
||
|
|
scaler.fit(data_train)
|
||
|
|
data_train = scaler.transform(data_train)
|
||
|
|
data_test = scaler.transform(data_test)
|
||
|
|
# Build X and y
|
||
|
|
X_train = data_train[:, 1:]
|
||
|
|
y_train = data_train[:, 0]
|
||
|
|
X_test = data_test[:, 1:]
|
||
|
|
y_test = data_test[:, 0]
|
||
|
|
# length of training data
|
||
|
|
m = X_train.shape[1]
|
||
|
|
# neurons in each layer
|
||
|
|
neurons_1 = 1024
|
||
|
|
neurons_2 = 512
|
||
|
|
neurons_3 = 256
|
||
|
|
neurons_4 = 128
|
||
|
|
# session
|
||
|
|
sess = tf.InteractiveSession()
|
||
|
|
# Placeholders
|
||
|
|
X = tf.placeholder(dtype=tf.float32, shape=[None, m])
|
||
|
|
Y = tf.placeholder(dtype=tf.float32, shape=[None])
|
||
|
|
# initializers
|
||
|
|
sigma = 1
|
||
|
|
W = tf.variance_scaling_initializer(mode="fan_avg", distribution="uniform", scale=sigma)
|
||
|
|
b = tf.zeros_initializer()
|
||
|
|
# hidden weights
|
||
|
|
W_hidden_1 = tf.Variable(W([m, neurons_1]))
|
||
|
|
b_hidden_1 = tf.Variable(b([neurons_1]))
|
||
|
|
W_hidden_2 = tf.Variable(W([neurons_1, neurons_2]))
|
||
|
|
b_hidden_2 = tf.Variable(b([neurons_2]))
|
||
|
|
W_hidden_3 = tf.Variable(W([neurons_2, neurons_3]))
|
||
|
|
b_hidden_3 = tf.Variable(b([neurons_3]))
|
||
|
|
W_hidden_4 = tf.Variable(W([neurons_3, neurons_4]))
|
||
|
|
b_hidden_4 = tf.Variable(b([neurons_4]))
|
||
|
|
# output weights
|
||
|
|
W_out = tf.Variable(W([neurons_4, 1]))
|
||
|
|
b_out = tf.Variable(b([1]))
|
||
|
|
# hidden layers
|
||
|
|
hidden_1 = tf.nn.relu(tf.add(tf.matmul(X, W_hidden_1), b_hidden_1))
|
||
|
|
hidden_2 = tf.nn.relu(tf.add(tf.matmul(hidden_1, W_hidden_2), b_hidden_2))
|
||
|
|
hidden_3 = tf.nn.relu(tf.add(tf.matmul(hidden_2, W_hidden_3), b_hidden_3))
|
||
|
|
hidden_4 = tf.nn.relu(tf.add(tf.matmul(hidden_3, W_hidden_4), b_hidden_4))
|
||
|
|
# transpose the output layer
|
||
|
|
out = tf.transpose(tf.add(tf.matmul(hidden_4, W_out), b_out))
|
||
|
|
# cost function
|
||
|
|
mse = tf.reduce_mean(tf.squared_difference(out, Y))
|
||
|
|
# optimizer
|
||
|
|
opt = tf.train.AdamOptimizer().minimize(mse)
|
||
|
|
# init
|
||
|
|
sess.run(tf.global_variables_initializer())
|
||
|
|
# start plot
|
||
|
|
plt.ion()
|
||
|
|
fig = plt.figure()
|
||
|
|
ax1 = fig.add_subplot(111)
|
||
|
|
line1, = ax1.plot(y_test)
|
||
|
|
line2, = ax1.plot(y_test * 0.5)
|
||
|
|
plt.show()
|
||
|
|
# fit neural net
|
||
|
|
batch_size = 1
|
||
|
|
mse_train = []
|
||
|
|
mse_test = []
|
||
|
|
# run the network
|
||
|
|
for e in range(epochs):
|
||
|
|
# shuffle training data
|
||
|
|
shuffle_indices = np.random.permutation(np.arange(len(y_train)))
|
||
|
|
X_train = X_train[shuffle_indices]
|
||
|
|
y_train = y_train[shuffle_indices]
|
||
|
|
# Minibatch training
|
||
|
|
for i in range(0, len(y_train) // batch_size):
|
||
|
|
start = i * batch_size
|
||
|
|
batch_x = X_train[start:start + batch_size]
|
||
|
|
batch_y = y_train[start:start + batch_size]
|
||
|
|
# run optimizer with batch
|
||
|
|
sess.run(opt, feed_dict={X: batch_x, Y: batch_y})
|
||
|
|
# show progress
|
||
|
|
if np.mod(i, 50) == 0:
|
||
|
|
# MSE train and test
|
||
|
|
mse_train.append(sess.run(mse, feed_dict={X: X_train, Y: y_train}))
|
||
|
|
mse_test.append(sess.run(mse, feed_dict={X: X_test, Y: y_test}))
|
||
|
|
print('MSE Train: ', mse_train[-1])
|
||
|
|
print('MSE Test: ', mse_test[-1])
|
||
|
|
# prediction
|
||
|
|
pred = sess.run(out, feed_dict={X: X_test})
|
||
|
|
line2.set_ydata(pred)
|
||
|
|
plt.title('Epoch ' + str(e) + ', Batch ' + str(i))
|
||
|
|
plt.pause(0.10)
|
||
|
|
plt.savefig('graphs/%s_%s.png' %(str(e), str(i)))
|
||
|
|
|
||
|
|
# Xcols=20 returns better results than Xcols=1, with o=5
|
||
|
|
# Xcols=20 and o=1 returns 90-95% accuracy for every model
|
||
|
|
def ensemble_research(file, split=0.6, o=5, Xcols=1):
|
||
|
|
"""Xcols == 1 or 20; 1 for 'Open' or 20 for all input values"""
|
||
|
|
# import, split, and prepare data
|
||
|
|
df = pd.read_csv(file)
|
||
|
|
n = len(df)
|
||
|
|
if Xcols == 1:
|
||
|
|
y = df['Close'].values.reshape(n, 1)
|
||
|
|
X = df['Open'].values.reshape(n, 1)
|
||
|
|
X_train, X_test, y_train, y_test = split_data(X, y, n, split, o)
|
||
|
|
elif Xcols == 20:
|
||
|
|
y = df['Close'].values
|
||
|
|
a = df['Close'].mean()
|
||
|
|
df.fillna(a, inplace=True)
|
||
|
|
for col in df.columns:
|
||
|
|
if 'Unnamed' in col:
|
||
|
|
df.drop(col, axis=1, inplace=True)
|
||
|
|
df.drop('Close', axis=1, inplace=True)
|
||
|
|
X = df[df.columns.tolist()].values
|
||
|
|
X_train, X_test, y_train, y_test = split_data(X, y, n, split, o)
|
||
|
|
|
||
|
|
# instantiate the models to be explored
|
||
|
|
models = [AdaBoostRegressor(),
|
||
|
|
BaggingRegressor(),
|
||
|
|
DecisionTreeRegressor(),
|
||
|
|
ExtraTreesRegressor(),
|
||
|
|
GradientBoostingRegressor(),
|
||
|
|
RandomForestRegressor()]
|
||
|
|
|
||
|
|
# set and run models
|
||
|
|
scores = list()
|
||
|
|
for model in models:
|
||
|
|
model.fit(X_train, y_train)
|
||
|
|
yhat = model.predict(X_test)
|
||
|
|
score = model.score(X_test, y_test)
|
||
|
|
scores.append(score)
|
||
|
|
plt.plot(yhat, label='predictions')
|
||
|
|
plt.plot(y_test, label='real data')
|
||
|
|
plt.title(str(score))
|
||
|
|
plt.legend()
|
||
|
|
plt.show()
|
||
|
|
|
||
|
|
# multivariate LSTM in Keras (OHL, plus technical indicators; 20 columns in total)
|
||
|
|
def LSTMulti_research(file, o=5, split=0.6, show_loss=False):
|
||
|
|
# import and clean the dataframe as needed, filling in any missing data
|
||
|
|
df = pd.read_csv(file)
|
||
|
|
n = len(df)
|
||
|
|
y = df['Close'].values
|
||
|
|
a = df['Close'].mean()
|
||
|
|
df.fillna(a, inplace=True)
|
||
|
|
for col in df.columns:
|
||
|
|
if "Unnamed" in col:
|
||
|
|
df.drop(col, axis=1, inplace=True)
|
||
|
|
df.drop('Close', axis=1, inplace=True)
|
||
|
|
X = df[df.columns.tolist()].values
|
||
|
|
# split data and reshape input values
|
||
|
|
X_train, X_test, y_train, y_test = split_data(X,y,n,split,o)
|
||
|
|
X_train = np.reshape(X_train, (X_train.shape[0], 1, X_train.shape[1]))
|
||
|
|
X_test = np.reshape(X_test, (X_test.shape[0], 1, X_test.shape[1]))
|
||
|
|
|
||
|
|
model = Sequential()
|
||
|
|
model.add(LSTM(20, input_shape=(1,20,), activation='linear'))
|
||
|
|
model.add(Dense(1))
|
||
|
|
model.compile(loss='mse', optimizer='adam')
|
||
|
|
history = model.fit(X_train, y_train, epochs=50, batch_size=1,
|
||
|
|
validation_data=(X_test, y_test), verbose=2, shuffle=False)
|
||
|
|
score = model.evaluate(X_test, y_test)#history['']
|
||
|
|
if show_loss == True:
|
||
|
|
plt.plot(history.history['loss'], label='train')
|
||
|
|
plt.plot(history.history['val_loss'], label='test')
|
||
|
|
plt.title('LSTMulti Score' + str(score))
|
||
|
|
plt.legend()
|
||
|
|
plt.show()
|
||
|
|
else:
|
||
|
|
plt.plot(y_test, label='prices')
|
||
|
|
plt.plot(model.predict(X_test), label='predictions')
|
||
|
|
plt.title('LSTMulti Score ' + str(score))
|
||
|
|
plt.legend()
|
||
|
|
plt.show()
|
||
|
|
|
||
|
|
def plot_Ridge(file, o=5, split=0.6):
|
||
|
|
df = pd.read_csv(file)
|
||
|
|
n = len(df)
|
||
|
|
X = df['Open'].values.reshape(n,1)
|
||
|
|
y = df['Close'].values.reshape(n,1)
|
||
|
|
X_train, X_test, y_train, y_test = split_data(X, y, n, split, o)
|
||
|
|
|
||
|
|
model = Ridge()
|
||
|
|
model.fit(X_train, y_train)
|
||
|
|
predictions = model.predict(X_test)
|
||
|
|
score = model.score(X_test, y_test)
|
||
|
|
print("Model score: %.2f" % score)
|
||
|
|
|
||
|
|
plt.plot([x for x in range(len(X_test))], predictions, label='predictions')
|
||
|
|
plt.plot([x for x in range(len(X_test))], y_test, label='actual data')
|
||
|
|
plt.legend()
|
||
|
|
plt.show()
|
||
|
|
|
||
|
|
def plot_LinearRegression(file, o=5, split=0.6):
|
||
|
|
# o == offset, how far away is the prediction we want to make?
|
||
|
|
# changing o from 5 to 1 improves prediction accuract from 81% to 94%
|
||
|
|
df = pd.read_csv(file)
|
||
|
|
n = len(df)
|
||
|
|
# convert pd.Series to np.ndarrays now for manipulation
|
||
|
|
X = df['Open'].values.reshape(n,1)
|
||
|
|
y = df['Close'].values.reshape(n,1)
|
||
|
|
|
||
|
|
# slight offset, X[t] is used to 'predict' y[t+o]
|
||
|
|
X_train, X_test, y_train, y_test = split_data(X,y,n,split,o)
|
||
|
|
|
||
|
|
# check to make sure the two sets of arrays match in length
|
||
|
|
print("Training sizes: X: %.2f, y: %.2f" % (X_train.shape[0], y_train.shape[0]))
|
||
|
|
print("Test sizes: X: %.2f, y: %.2f" % (X_test.shape[0], y_test.shape[0]))
|
||
|
|
|
||
|
|
model = LinearRegression()
|
||
|
|
model.fit(X_train, y_train)
|
||
|
|
predictions = model.predict(X_test)
|
||
|
|
score = model.score(X_test, y_test)
|
||
|
|
print("Model score: ", score)
|
||
|
|
plt.plot([x for x in range(len(X_test))], predictions, label='predictions')
|
||
|
|
plt.plot([y for y in range(len(y_test))], y_test, label='real data')
|
||
|
|
plt.legend()
|
||
|
|
plt.show()
|
||
|
|
|
||
|
|
#arima_research(file, 'Close', 5, 1, 1) # best fit
|
||
|
|
def arima_research(file, series, p, d, q):
|
||
|
|
# prepare data
|
||
|
|
df = pd.read_csv(file)
|
||
|
|
X = df[series].values
|
||
|
|
size = int(len(X) * 0.6)
|
||
|
|
train, test = X[:size], X[size:]
|
||
|
|
history = [x for x in train]
|
||
|
|
predictions = list()
|
||
|
|
|
||
|
|
# fit the model and make predictions
|
||
|
|
for t in range(len(test)):
|
||
|
|
model = ARIMA(history, order=(p,d,q))
|
||
|
|
model_fit = model.fit(disp=0)
|
||
|
|
#print(model_fit.summary())
|
||
|
|
output = model_fit.forecast()
|
||
|
|
yhat = output[0]
|
||
|
|
predictions.append(yhat)
|
||
|
|
obs = test[t]
|
||
|
|
history.append(obs)
|
||
|
|
err = abs(yhat - obs)
|
||
|
|
print("Predicted: %.3f, Expected: %.3f, Error: %.3f" % (yhat, obs, err))
|
||
|
|
|
||
|
|
# print summary and graph results
|
||
|
|
error = mean_squared_error(test, predictions)
|
||
|
|
print("Test MSE: %.3f" % (error))
|
||
|
|
plt.plot(test, label='actual prices')
|
||
|
|
plt.plot(predictions, label='predicted prices')
|
||
|
|
plt.legend()
|
||
|
|
plt.show()
|