如何从技术上成功预测比特币价格?

点击上方“CSDN”,选择“置顶公众号”

关键时刻,第一时间送达!

许多论证声称,通过深度学习网络可以准确预测加密货币的价格波动。本文则用实际数据打脸:别被玩弄了!这种所谓的“准确预测”存在很多坑。

640?wx_fmt=jpeg

以下为译文:

我试着建了个深度神经网络来预测比特币的价格,结果准得不可思议。

想知道什么情况吗?先看看我的预测结果吧。

640?wx_fmt=png

貌似很准确,是不是?

不用你问,我直接告诉你答案:没错,上面的测试是在没遇到过的数据上做的,模型训练时只用到了之前的数据(稍后解释细节)。

看来这是个发家致富的摇钱树!对吧?其实我都可以给你上面模型的代码,然后这样你就可以自己用了......

好了正经点,千万别这么干!别在交易中使用这种模型,虽然这些看似准确的结果相当有迷惑性,但是千万不要被骗了。

下面我来具体解释。

事出反常必有妖

前几周甚至前几个月,我看了太多文章,它们采用和上面类似的途径显示了加密货币价格的预测图。

但是,这些准确得令人难以置信的价格预测,应该立刻引起你的警觉。“如果一件事情好得难以置信,那通常就是假的。——Emmy Rossum”

下面我想演示下为何事情会如此。

不过不要误会——我不是要否定那些文章做出的努力。那些文章真的很好,值得人们为其鼓掌。实际上,许多方法在理论上来说确实非常准确。而本文的目的主要就是要揭示,为何在实践中那些模型是不合理的?为何其预测不一定适合实际的交易?

利用LSTM预测比特币的价格

为了便于说明,首先介绍一个利用多维LSTM(长短期记忆)神经网络来预测比特币价格,并生成上面的预测结果的例子。

LSTM是一种特殊的RNN(递归神经网络),十分适合带有时间序列的问题。因此,在预测加密货币价格和股市方面LSTM十分流行。

想深入了解LSTM可以读一读这两篇文章:

  • http://colah.github.io/posts/2015-08-Understanding-LSTMs/

  • http://blog.echen.me/2017/05/30/exploring-lstms/

下面的LSTM实现采用了Python和Keras(https://keras.io/)。

相应的Jupyter Notebook请参见我的Github:

  • https://github.com/neocortex/lstm-bitcoin-prediction

获取数据

首先,我下载了比特币的历史价格数据(你也可以下载其他任何加密货币的数据)。利用cryptocompare(http://www.cryptocompare.com/)的API可以做到这一点:

import json
import requests
import pandas as pd
endpoint = 'https://min-api.cryptocompare.com/data/histoday'
res = requests.get(endpoint + '?fsym=BTC&tsym=USD&limit=2000')
hist = pd.DataFrame(json.loads(res.content)['Data'])
hist = hist.set_index('time')
hist.index = pd.to_datetime(hist.index, unit='s')
hist.head()

640?wx_fmt=png

图注:比特币的历史价格数据的一部分

这样我们就有了过去2000日的BTC数据,从2012/10/10直到2018/4/4。

分割训练集和测试集

接下来,我将数据分割成了训练集和测试集。使用最后的10%数据作为测试,这样分割线位于2017/9/14。所有在该日期之前的数据被用于训练,该日期之后的数据用于测试训练好的模型。下面,我画出了DataFrame的close列,这就是我们要预测的每日收盘价格。

def train_test_split(df, test_size=0.1):
   split_row = len(df) - int(test_size * len(df))
   train_data = df.iloc[:split_row]
   test_data = df.iloc[split_row:]
   return train_data, test_data
def line_plot(line1, line2, label1=None, label2=None, title=''):
   fig, ax = plt.subplots(1, figsize=(16, 9))
   ax.plot(line1, label=label1, linewidth=2)
   ax.plot(line2, label=label2, linewidth=2)
   ax.set_ylabel('price [USD]', fontsize=14)
   ax.set_title(title, fontsize=18)
   ax.legend(loc='best', fontsize=18)
train, test = train_test_split(hist, test_size=0.1)
line_plot(train.close, test.close, 'training', 'test', 'BTC')

640?wx_fmt=png

图注:比特币历史价格数据分割成训练集和测试集

构建模型

为了训练LSTM,我们将数据按照7天的时间段分割(时间长度可以人选,我只是简单地以一周为时间段),每个时间段内以零为基础(zero base)将数据正规化(normalize),即每个时间段内的第一条数据为0,其他值表示与第一条数据之间的相对变化。因此,这里预测的是价格变动,而不是绝对的价格。

def normalise_zero_base(df):
   """ Normalise dataframe column-wise to reflect changes with
       respect to first entry.
   """

   return df / df.iloc[0] - 1
def extract_window_data(df, window=7, zero_base=True):
   """ Convert dataframe to overlapping sequences/windows of
       length `window`.
   """

   window_data = []
   for idx in range(len(df) - window):
       tmp = df[idx: (idx + window)].copy()
       if zero_base:
           tmp = normalise_zero_base(tmp)
       window_data.append(tmp.values)
   return np.array(window_data)
def prepare_data(df, window=7, zero_base=True, test_size=0.1):
   """ Prepare data for LSTM. """
   # train test split
   train_data, test_data = train_test_split(df, test_size)
   # extract window data
   X_train = extract_window_data(train_data, window, zero_base)
   X_test = extract_window_data(test_data, window, zero_base)
   # extract targets
   y_train = train_data.close[window:].values
   y_test = test_data.close[window:].values
   if zero_base:
       y_train = y_train / train_data.close[:-window].values - 1
       y_test = y_test / test_data.close[:-window].values - 1
   return train_data, test_data, X_train, X_test, y_train, y_test
train, test, X_train, X_test, y_train, y_test = prepare_data(hist)

这里采用了一个简单的神经网络,包含一个由20个神经元组成的LSTM层,dropout率为0.25,还有一个密集层(Dense),激活函数为简单的线性函数。此外,损失函数用的是MAE(Mean Absolute Error,平均绝对误差),优化器用的是Adam。

我将该网络训练了50个epoch,batch大小为4。

注意:网络架构和所有参数都可以任意选择,这里我没有做任何优化,因为这不是本文的中点。

def build_lstm_model(input_data, output_size, neurons=20,
                    activ_func='linear', dropout=0.25,
                    loss='mae', optimizer='adam'
):
   model
= Sequential()
   model.add(LSTM(neurons, input_shape=(
             input_data.shape[1], input_data.shape[2])))
   model.add(Dropout(dropout))
   model.add(Dense(units=output_size))
   model.add(Activation(activ_func))
   model.compile(loss=loss, optimizer=optimizer)
   return model
model = build_lstm_model(X_train, output_size=1)
history = model.fit(X_train, y_train, epochs=50, batch_size=4)

结果

使用训练好的模型预测剩下的测试集,得到本文开头的那张图。

640?wx_fmt=png

那么究竟这些结果有什么问题?仔细看看并放大图像到最近30日。

targets = test[target_col][window:]
preds = model.predict(X_test).squeeze()
# convert change predictions back to actual price
preds = test.close.values[:-window] * (preds + 1)
preds = pd.Series(index=targets.index, data=preds)
n = 30
line_plot(targets[-n:], preds[-n:], 'actual', 'prediction')

640?wx_fmt=png

看到了吗?

可能你已经猜到了,这个模型最根本的问题在于,对于给定某天的预测,它几乎与前一天的实际结果相同。

预测曲线看起来只不过是把实际曲线平移了一天而已。

实际上,如果把预测曲线平移一天,这个结论就更明显了。

line_plot(targets[-n:][:-1], preds[-n:].shift(-1))

640?wx_fmt=png

如上图所示,预测曲线和实际曲线完美地匹配在一起,这说明模型实际上在学习前一天的价格。

该结果与我在许多使用LSTM做单点预测的例子中看到的一样。

为了更明确地说明这一点,我们来计算下模型预测的返回结果和实际的返回结果:

actual_returns = targets.pct_change()[1:]
predicted_returns = preds.pct_change()[1:]

观察实际和预测的返回结果,一个是原始形式,一个是平移了一天的形式,可以得到相同的结论。

640?wx_fmt=png

实际和预测的返回结果,左侧的图形中预测结果调整了一天。

实际上,如果计算下实际和预测返回结果之间的关联度,可以发现以下结论:

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 9))
# actual correlation
corr = np.corrcoef(actual_returns, predicted_returns)[0][1]
ax1.scatter(actual_returns, predicted_returns, color='k')
ax1.set_title('r = {:.2f}'.format(corr), fontsize=18)
# shifted correlation
shifted_actual = actual_returns[:-1]
shifted_predicted = predicted_returns.shift(-1).dropna()
corr = np.corrcoef(shifted_actual, shifted_predicted)[0][1]
ax2.scatter(shifted_actual, shifted_predicted, color='k')
ax2.set_title('r = {:.2f}'.format(corr));

640?wx_fmt=png

从上面的图形中可见,实际和预测的返回结果实际上没有相关性。但将预测返回结果偏移一天之后,就能观察到极强的相关性,说明预测结果在重复实际的比特币数据。

总结

本文的目的是讨论我这几个月看到的许多关于利用深度神经网络预测加密货币和股市价格的例子。这些文章用的方法与这里类似:利用历史价格数据实现一个LSTM,并预测未来的走势。

而本文演示了为何这些模型无法在实际交易中使用。

没错,网络在学习方面很有效。但学习到的策略却是预测一个尽量接近于前一天的数值,因为这样能获得最小的平均绝对误差。但是,无论这种预测在损失函数上的结果多么精确,在实际中,仅基于历史价格数据的单点预测模型的结果依然很难准确,在实际交易中几乎没有任何用处。

当然,可能存在更复杂的方式,在价格预测方面实现更有用的LSTM。可以从使用更多的数据,同时优化网络结构和超参数开始。但是我认为,更可能的是采用历史价格数据之外的数据和特征。毕竟,投资的世界中已有共识——“过去的业绩不代表未来的产出”。

同样的结论对于加密货币应该也成立。

免责声明:本文不是投资建议。本文和展示的模型仅用于教育用途。请不要用于交易或市场投资决策。

原文:https://hackernoon.com/dont-be-fooled-deceptive-cryptocurrency-price-predictions-using-deep-learning-bf27e4837151

作者:Rafael Schultze-Kraft

译者:弯月,责编:郭芮

  征稿啦!

CSDN 公众号秉持着「与千万技术人共成长」理念,不仅以「极客头条」、「畅言」栏目在第一时间以技术人的独特视角描述技术人关心的行业焦点事件,更有「技术头条」专栏,深度解读行业内的热门技术与场景应用,让所有的开发者紧跟技术潮流,保持警醒的技术嗅觉,对行业趋势、技术有更为全面的认知。
如果你有优质的文章,或是行业热点事件、技术趋势的真知灼见,或是深度的应用实践、场景方案等的新见解,欢迎联系 CSDN 投稿,联系方式:微信(guorui_1118,请备注投稿+姓名+公司职位),邮箱(guorui@csdn.net)。

————— 推荐阅读 —————

点击图片即可阅读

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png640?wx_fmt=png

640?wx_fmt=gif

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭