在本文中,将介绍如何开发一个能够处理比特币数据的时间序列预测器和异常检测器。尽管将以比特币为例,但学到的概念和方法可以应用于任何类似性质的数据类型。为了充分利用本系列文章,应该具备一些Python、机器学习和Keras技能。整个项目可以在GitHub仓库中找到。还可以在这里和这里查看完全交互式的笔记本。
在之前的文章中,已经开发了处理时间序列数据的模型。创建了比特币价格预测器和异常检测器。在本文中,将这两个模型结合起来,以便在未来检测异常。
还有什么比通过API获取当前数据更好的方法呢?将使用Poloniex API获取最近的过去数据。希望获取过去24小时的比特币价格,然后预测下一个小时的价值。
让从获取昨天和今天的Unix格式日期开始,使用UTC时区:
import datetime
import pytz
from datetime import timedelta
past = datetime.datetime.now(pytz.timezone('UTC')) - timedelta(days=1)
# 昨天的日期
past = past.strftime('%s')
# 重塑为Unix格式
current = datetime.datetime.now(pytz.timezone('UTC')).strftime('%s')
# 今天的日期
现在,让将这些日期传递给Poloniex API,并将结果转换为JSON格式,以确保得到一个不错的Pandas DataFrame:
import requests
import pandas as pd
url = 'https://poloniex.com/public?command=returnChartData¤cyPair=USDT_BTC&start=' + str(past) + '&end=' + str(current) + '.=300'
result = requests.get(url)
result = result.json()
last_data = pd.DataFrame(result)
这个数据收集包括一些不需要的列和格式,所以让稍微清理一下:
last_data = last_data[['date', 'weightedAverage']]
last_data = last_data.resample('H', on='date')['weightedAverage'].mean()
last_data = last_data[-24:]
unscaled = last_data.copy()
在用这些数据进行预测之前,让使用之前训练过的缩放器,以使两个模型兼容这些值:
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
last_data_scaled = scaler.fit_transform(last_data)
现在已经整理了从Poloniex获得的数据,让预测并检测其中的异常:
from keras.models import load_model
regressor = load_model('regressor.h5')
detector = load_model('detector.h5')
predictions = regressor.predict(last_data_scaled.values.reshape(1, 24, 1))
unscaled = unscaled.iloc[1:]
unscaled = unscaled.append(pd.DataFrame(scaler.inverse_transform(predictions)[0], index=[unscaled.index[len(unscaled)-1] + timedelta(hours=1)], columns=['weightedAverage']))
future_scaled = scaler.transform(unscaled.copy())
future_scaled_pred = detector.predict(future_scaled.values.reshape(1, 24, 1))
future_loss = np.mean(np.abs(future_scaled_pred - future_scaled.values.reshape(1, 24, 1)), axis=1)
unscaled['threshold'] = threshold
unscaled['loss'] = future_loss[0][0]
unscaled['anomaly'] = unscaled.loss > threshold
应该得到一个类似于这样的DataFrame:
print(unscaled.head())
最后,让绘制结果:
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=unscaled.index, y=unscaled.weightedAverage.values, mode='lines', name='BTC Price'))
fig.add_trace(go.Scatter(x=unscaled.index, y=unscaled[unscaled.anomaly == True]['weightedAverage'].values, mode='markers', marker_symbol='x', marker_size=10, name='Anomaly'))
fig.add_vrect(x0=unscaled.index[-2], x1=unscaled.index[-1], fillcolor='LightSalmon', opacity=1, layer='below', line_width=0)
fig.update_layout(showlegend=True, title='BTC price predictions and anomalies', xaxis_title='Time (UTC)', yaxis_title='Prices', font=dict(family='Courier New, monospace'))
fig.show()
正如所看到的,预测值与之前的相比非常低。如果检查历史数据,不会看到这样一系列高值。这是因为当前的比特币价格是一个异常,以前没有发生过,实际模型没有看到过这样的数据。即使异常检测器可以识别观察结果为异常,预测器也不准确。它应该对以前见过的数据值准确。为了缓解这个问题,需要收集一些包含更近期价格值的当前数据。