本篇博客将对比特币的走势进行预测,采用的模型是时间序列模型 ARMA,采用的工具是 Python 3.
先来简单介绍一下使用到的模型 ARMA。
ARMA英文全称是 Auto Regressive Moving Average,中文叫做自回归滑动平均模型,也就是 AR 模型和 MA 模型的混合。相比 AR 模型和 MA 模型,它有更准确的估计。同样 ARMA 模型存在 p 和 q 两个阶数,称为 ARMA(p,q) 模型。
接下来具体看看在 Python 中的 ARMA 工具。
引用
from statsmodels.tsa.arima_model import ARMA
构造
ARMA(endog, order, exog = None)
endog
:代表内生变量,由模型决定的,不被外部环境所改变,可以认为是我们想要解释的变量。
order
:代表的是 p 和 q 的值,也就是 ARMA 中的阶数。
exog
:代表外生变量,受外部因素的影响,不是我们模型要研究的变量。
功能函数
fit( )
:拟合函数
predict(start, end)
:预测函数,其中 start 代表预测的起始时间;end 代表预测的终止时间。
AIC准则
也称为赤池信息准则,是衡量统计模型拟合好坏的一个标准。AIC 值越小,代表模型的拟合度越好。
首先导入需要用到的 Python 包。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.arima_model import ARMA
import warnings
from itertools import product
from datetime import datetime
导入数据,数据的类型是.csv。
df = pd.read_csv('./bitcoin_2012-01-01_to_2018-10-31.csv')
接下来对数据进行探索。我们先看看前5行的数据。
df.head(5)
Timestamp : 日期
Open : 开盘价
High : 最高价
Low : 最低价
Close : 收盘价
Volume_(BTC) : 比特币成交量
Volume_(Currency) : 成交金额
Weighted_Price : 比特币平均价格
接下来,我们把 Timestamp 作为 df 的索引。
df.Timestamp = pd.to_datetime(df.Timestamp)
df.index = df.Timestamp
然后,分别按 月、季节 和 年 来进行数据的统计。
df_month = df.resample('M').mean()
df_Q = df.resample('Q-DEC').mean()
df_year = df.resample('A-DEC').mean()
分别以 天、月、季节 和 年 为单位来显示比特币的走势。以下代码是显示比特币的平均价格的走势,其他的统计量的走势同理得出。
fig = plt.figure(figsize=[15, 7])
plt.suptitle('Bitcoin amount $', fontsize=20)
plt.subplot(221)
plt.plot(df.Weighted_Price, '-', label='based on day')
plt.legend()
plt.subplot(222)
plt.plot(df_month.Weighted_Price, '-', label='based on month')
plt.legend()
plt.subplot(223)
plt.plot(df_Q.Weighted_Price, '-', label='based on season')
plt.legend()
plt.subplot(224)
plt.plot(df_year.Weighted_Price, '-', label='based on year')
plt.legend()
plt.show()
比特币成交金额的趋势图
比特币成交量的趋势图
比特币成交平均价格的趋势图
接下来是建模,首先调参,我们需要选择一个不错的超参数。这里的参数指 p 和 q。
# 设置参数范围
ps = range(0,3)
qs = range(0,3)
parameters = product(ps,qs)
parameters_list = list(parameters)
寻找最优ARMA模型参数,即best_aic最小。这里采用的是以月为单位的预测。
其实在一定程度上也给数据进行了降维,同时也会节省模型训练的时间。
results = []
best_aic = float("inf") # 正无穷
for param in parameters_list:
try:
model = ARMA(df_month.Weighted_Price, order=(param[0], param[1])).fit()
except ValueError:
print('参数错误:', param)
continue
aic = model.aic
if aic < best_aic:
best_model = model
best_aic = aic
best_param = param
results.append([param, model.aic])
# 输出最优模型
result_table = pd.DataFrame(results)
result_table.columns = ['parameters', 'aic']
print('最优模型: ', best_model.summary())
运行结果如图所示:
# 比特币预测
df_month2 = df_month[['Weighted_Price']]
date_list = [datetime(2018, 11, 30), datetime(2018, 12, 31), datetime(2019, 1, 31), datetime(2019, 2, 28), datetime(2019, 3, 31),
datetime(2019, 4, 30), datetime(2019, 5, 31), datetime(2019, 6, 30)]
future = pd.DataFrame(index=date_list, columns= df_month.columns)
df_month2 = pd.concat([df_month2, future])
df_month2['forecast'] = best_model.predict(start=0, end=91)
# 比特币预测结果显示
plt.figure(figsize=(20,7))
df_month2.Weighted_Price.plot(label='real amount')
df_month2.forecast.plot(color='r', ls='--', label='predict amount')
plt.legend()
plt.title('Bitcoin amount/month')
plt.xlabel('time')
plt.ylabel('dollar')
plt.show()
总结
从结果中可以看出,在训练阶段,即处于蓝色和红色的线都有的那段时间,我们的模型对训练数据的拟合程度还是不错的。
在预测阶段,即在 2018 年 10 月之后 8 个月的时间里,比特币的平均价格开始不断地下跌,跌破 4000 美金左右。其实实际上,比特币在这个阶段的价格确实降低到了 4000 元美金甚至更低。