使用循环神经模型预测比特币(BTC)价格

虽然主观观点对于预测加密货币的未来很有价值,但我们的预测方法从一个不同的角度来处理这个问题,尤其是从算法交易的角度。我们只是计划使用数字历史数据来训练一个循环神经网络(RNN)来预测比特币的价格。

获取历史比特币价格

我们可能会有相当多的资源来获取历史比特币价格数据。虽然其中一些资源允许用户手动下载CSV文件,但其他资源提供的API可以连接到代码。因为当我们使用时间序列数据训练模型时,我们希望它能够进行最新的预测,我更喜欢使用API​​,这样我们可以在运行程序时始终获得最新的数据。我决定使用CoinRanking.com的API,它提供了我们可以使用的最新coin价格。

循环神经网络

由于我们使用的是时间序列数据集,因此使用仅前馈神经网络是不可行的,因为明天的BTC价格与今天的价格最相关,而不是一个月前。

循环神经网络(RNN)是一类人工神经网络,其中节点之间的连接形成沿序列的有向图。

RNN显示时间序列的时间动态行为,并且它可以使用其内部状态来处理序列。实际上,这可以通过LSTM和GRU层来实现。

在这里,您可以看到常规仅前馈神经网络和递归神经网络(RNN)之间的区别:

实现步骤

为了能够创建一个训练历史BTC价格并预测明天的BTC价格的程序,我们需要完成以下几项任务:

  • 1 - 获取,清理和归一化历史BTC价格
  • 2 - 使用LSTM构建RNN
  • 3 - 训练RNN并保存训练神经网络模型
  • 4 - 预测明天的BTC价格和“反序列化”它

其他:反序列化X_Test预测并创建Plot.ly图表

使用循环神经模型预测比特币(BTC)价格

获取BTC数据

如上所述,我们将使用CoinRanking.com的API作为BTC数据集,并使用以下Python代码将其转换为pandas dataframe:

import requests,json,numpy as np,pandas as pd
#https://api.coinranking.com/v1/public/coin/:coin_id/history/:timeframe
#https://docs.coinranking.com/
def hist_price_dl(coin_id=1335,timeframe = "5y",currency = "USD"):
 '''It accepts coin_id, timeframe, and currency parameters to clean the historic coin data taken from COINRANKING.COM
 It returns a Pandas Series with daily mean values of the selected coin in which the date is set as the index'''
 r = requests.get("https://api.coinranking.com/v1/public/coin/"+str(coin_id)+"/history/"+timeframe+"?base="+currency)
 coin = json.loads(r.text)['data']['history'] #Reading in json and cleaning the irrelevant parts
 df = pd.DataFrame(coin)
 df['price'] = pd.to_numeric(df['price'])
 df['timestamp'] = pd.to_datetime(df['timestamp'],unit='ms').dt.date
 return df.groupby('timestamp').mean()['price']

使用循环神经模型预测比特币(BTC)价格

默认情况下,此函数会根据5年BTC / USD价格进行调整。但是,您可以通过传入不同的参数值来更改这些值。

使用自定义函数清理数据

在获得数据并将其转换为pandas dataframe之后,我们可以定义自定义函数来清理我们的数据,将其归一化为神经网络,因为它是获得准确结果的必要条件,并应用自定义训练测试拆分。我们创建了一个自定义训练测试拆分函数(不是scikit-learn),因为我们需要保持时间序列顺序以正确训练我们的RNN。我们可以使用以下Python代码实现此目的,您可以在下面的代码片段中找到更多函数说明:

def price_matrix_creator(data, seq_len=30):
 '''
 It converts the series into a nested list where every item of the list contains historic prices of 30 days
 '''
 price_matrix = []
 for index in range(len(data)-seq_len+1):
 price_matrix.append(data[index:index+seq_len])
 return price_matrix
def normalize_windows(window_data):
 '''
 It normalizes each value to reflect the percentage changes from starting point
 '''
 normalised_data = []
 for window in window_data:
 normalised_window = [((float(p) / float(window[0])) - 1) for p in window]
 normalised_data.append(normalised_window)
 return normalised_data
def train_test_split_(price_matrix, train_size=0.9, shuffle=False, return_row=True):
 '''
 It makes a custom train test split where the last part is kept as the training set.
 '''
 price_matrix = np.array(price_matrix)
 #print(price_matrix.shape)
 row = int(round(train_size * len(price_matrix)))
 train = price_matrix[:row, :]
 if shuffle==True:
 np.random.shuffle(train)
 X_train, y_train = train[:row,:-1], train[:row,-1]
 X_test, y_test = price_matrix[row:,:-1], price_matrix[row:,-1]
 X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
 X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
 if return_row:
 return row, X_train, y_train, X_test, y_test
 else:
 X_train, y_train, X_test, y_test

使用循环神经模型预测比特币(BTC)价格

定义这些函数后,我们可以使用以下Python代码调用它们:

# Not passing any argument since they are set by default
ser = hist_price_dl()
# Creating a matrix using the dataframe
price_matrix = price_matrix_creator(ser) 
# Normalizing its values to fit to RNN
price_matrix = normalize_windows(price_matrix)
# Applying train-test splitting, also returning the splitting-point
row, X_train, y_train, X_test, y_test = train_test_split_(price_matrix)

使用LSTM构建RNN

在准备好我们的数据之后,是时候构建我们​​的机器学习模型了,我们稍后将使用清理和归一化的数据进行训练。我们将从导入Keras组件开始,并使用以下Python代码设置一些参数:

from keras.models import Sequential
from keras.layers import LSTM, Dense, Activation
import time
# LSTM Model parameters, I chose
batch_size = 2 # Batch size (you may try different values)
epochs = 15 # Epoch (you may try different values)
seq_len = 30 # 30 sequence data (Representing the last 30 days)
loss='mean_squared_error' # Since the metric is MSE/RMSE
optimizer = 'rmsprop' # Recommended optimizer for RNN
activation = 'linear' # Linear activation
input_shape=(None,1) # Input dimension
output_dim = 30 # Output dimension

然后,我们将使用以下Python代码创建具有两个LSTM和两个Dense层的Sequential模型:

model = Sequential()
model.add(LSTM(units=output_dim, return_sequences=True, input_shape=input_shape))
model.add(Dense(units=32,activation=activation))
model.add(LSTM(units=output_dim, return_sequences=False))
model.add(Dense(units=1,activation=activation))
model.compile(optimizer=optimizer,loss=loss)

训练RNN并保存训练模型

现在是时候用清理过的数据训练我们的机器学习模型了。您还可以测量训练期间所花费的时间。请遵循以下代码:

start_time = time.time()
model.fit(x=X_train,
 y=y_train,
 batch_size=batch_size,
 epochs=epochs,
 validation_split=0.05)
end_time = time.time()
processing_time = end_time - start_time

别忘了保存它:

model.save('coin_predictor.h5')

预测明天的BTC价格并“反序化”它

在我们训练模型之后,我们需要获得当前的预测数据,并且由于我们将数据归一化,因此预测也将被归一化。因此,我们需要将其反归一化到其原始值。首先,我们将通过以下代码以相似的、部分不同的方式获取数据:

import requests,json,numpy as np,pandas as pd
#We need ser, preds, row
ser = hist_price_dl(timeframe='30d')[1:31]
price_matrix = price_matrix_creator(ser)
X_test = normalize_windows(price_matrix)
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))

我们将只有预测的标准化数据:没有训练测试拆分。我们还将手动reshape数据,以便能够在我们保存的模型中使用它。

在清理和准备我们的数据后,我们将加载经过训练的RNN模型进行预测并预测明天的价格。

from keras.models import load_model
model = load_model('coin_predictor.h5')
preds = model.predict(X_test, batch_size=2)

但是,我们的结果将介于-1和1之间,这没有多大意义。因此,我们需要将它们反归一化回原始值。我们可以通过自定义函数实现这一目标:

def deserializer(preds, data, train_size=0.9, train_phase=False):
 '''
 Arguments:
 preds : Predictions to be converted back to their original values
 data : It takes the data into account because the normalization was made based on the full historic data
 train_size : Only applicable when used in train_phase
 train_phase : When a train-test split is made, this should be set to True so that a cut point (row) is calculated based on the train_size argument, otherwise cut point is set to 0
 
 Returns:
 A list of deserialized prediction values, original true values, and date values for plotting
 '''
 price_matrix = np.array(price_matrix_creator(ser))
 if train_phase:
 row = int(round(train_size * len(price_matrix)))
 else:
 row=0
 date = ser.index[row+29:]
 date = np.reshape(date, (date.shape[0]))
 X_test = price_matrix[row:,:-1]
 y_test = price_matrix[row:,-1]
 preds_original = []
 preds = np.reshape(preds, (preds.shape[0]))
 for index in range(0, len(preds)):
 pred = (preds[index]+1)* X_test[index][0]
 preds_original.append(pred)
 preds_original = np.array(preds_original)
 if train_phase:
 return [date, y_test, preds_original]
 else:
 import datetime
 return [date+datetime.timedelta(days=1),y_test]

使用循环神经模型预测比特币(BTC)价格

定义自定义函数后,我们将调用这些函数并使用以下代码提取明天的BTC价格:

final_pred = deserializer(preds, ser, train_size=0.9, train_phase=False)
final_pred[1][0]

使用上面的Python代码,您实际上可以获得机器学习模型对明天BTC价格的预测。

反序列化X_Test预测并创建Plot.ly图表

您可能还对RNN模型的整体结果感兴趣,并希望将其视为图表。我们也可以通过使用本教程训练部分的X_test数据来实现这些目标。

我们将首先加载我们的神经网络模型(将其视为单个预测案例的替代方案)并对X_test数据进行预测,以便我们可以使用以下代码对适当的天数进行预测:

from keras.models import load_model
model = load_model('coin_predictor.h5')
preds = model.predict(X_test, batch_size=2)
plotlist = deserializer(preds, ser, train_phase=True)

接下来,我们将导入Plotly并设置属性以获得良好的绘图体验。我们将使用以下代码实现此目的:

from plotly import __version__
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.graph_objs as go
import cufflinks as cf
init_notebook_mode(connected=True)

设置完所有属性后,我们最终可以使用以下代码绘制预测值和观察值:

prices = pd.DataFrame({'Predictions':plotlist[1], 'Real Prices':plotlist[2]},index=plotlist[0])
iplot(prices.iplot(asFigure=True,
 kind='scatter',
 xTitle='Date',
 yTitle='BTC Price',
 title='BTC Price Predictions'))

运行此代码时,您将获得以下图表的最新版本:

使用循环神经模型预测比特币(BTC)价格

正如你所看到的,它看起来一点都不差。但是,您需要知道,即使模式非常接近,但是如果您每天查看结果,结果仍然是危险的。因此,必须进一步开发代码以获得更好的结果。

最后

您已经成功创建并训练了可以预测BTC价格的RNN模型,您甚至保存了经过训练的模型供以后使用。您可以通过切换到面向对象编程在Web或移动应用程序中使用此训练模型。

相关推荐