使用Prophet替代statsmodels的简单ARIMA,进行时间序列预测和交叉验证
没有任何物理、数学、统计学专业背景,从零开始的民间量化之路。
第一次测试结果在交叉检验测试中 13.65%的 MAPE(平均绝对百分比误差)和 40%的覆盖率下,2024 年的 8 月 8 日,btc/usd 价格下限(80%的不确定宽度)是 12000?当然这是“潜在的最坏情况”。
从简单的参数选择来看,考虑到 1 年的覆盖误差(Coverage Error)过大,而且不追求精准度,只想覆盖现实的不确定性情况(95%)选择保守(一般来说覆盖率越接近不确定性宽度模型误差越小),模型设置 95%的不确定性区间。
from prophet import Prophet
df_p = df.reset_index()[["date", "lnprice"]].rename(
columns={"date": "ds", "lnprice": "y"}
)
model = Prophet(uncertainty_samples = 1000, mcmc_samples=0,seasonality_mode="multiplicative", interval_width= 0.95)
# multiplicative
# Fit the model
model.fit(df_p)
# create date to predict
future_dates = model.make_future_dataframe(periods=180)
# Make predictions
predictions = model.predict(future_dates)
model.plot(predictions)
model.plot_components(predictions)
目前 2023 年 8 月 14 日,btc/usd 是 29300,而模型显示目前严重高估,预测 2023 年 11 月 6 日的预测收盘价是 e^9.7122653758=16518.98,然后用 90/180 进行数据划分进行交叉验证。
from prophet.diagnostics import cross_validation, performance_metrics
# 评估 180 天范围内的预测性能,从第一个截止点的 365.25 天训练数据开始,然后每 60 天进行一次预测
df_cv = cross_validation(model, initial='365.25 days', period='90 days', horizon = '180 days')
# Calculate evaluation metrics
res = performance_metrics(df_cv)
res
非常诱人的结果:MAPE 随着时间缓慢增长,到 180 天后仍然不超过 15%,覆盖率达到 70%,说明该模型适合被用作时间序列分析。
为何选择 MAPE 和 Coverage 来评估?
季节性分析
对于周期性的结果是符合预期的,“黑色星期四”和“春节行情”。
Yt=Tt+St+Ct+ItTi: 时趋势性项
St:t 时季节性项
Ci:t 时周期性项
It:无关(随机)项
选择乘性季节性,因为季节性周期的宽度或高度随着时间的推移而变化,尤其是在 2021 年 defi summer,btc 的周期性振幅超乎很多人的想象,但当时相当多的人仍然是线性思维判断。
为什么取对数仍然需要相乘模型?
在 Tradingview 社区中会发现很多人认为在坐标系上取对数,然后再进行线性的技术分析就能解决非线性问题,特别是在长达两三年的周期性图表上,总是结果低估相对波动率和振幅。
Yt=Tt∗St∗Ct∗It其中三种不确定性来源:
季节性和噪声在比特币价格运作中影响较少,主要是趋势的不确定性,趋势受到外界美元利率、通胀指数、纳斯达克指数、高风险股票收益率的影响,内部有矿工费、区块大小、地址增长速度,这里边必然存在多重共线性。
为什么不能使用简单的 ARIMA 模型?
以后还会尝试进一步的模型选择和参数调优,尤其别是尝试 LSTM。
对当下的反思和批判
作者槐序
2023 August 15th发布