使用统计模型进行预测

Forecasting with statsmodels

我有一个包含 5 年时间序列的 .csv 文件,具有每小时分辨率(商品价格)。根据历史数据,我想创建第 6 年的价格预测。

我在 www 上阅读了几篇关于此类程序的文章,我的代码基本上基于那里发布的代码,因为我在 Python(尤其是 statsmodels)和统计方面的知识是最多限制。

这些是链接,感兴趣的朋友:

http://www.seanabu.com/2016/03/22/time-series-seasonal-ARIMA-model-in-python/

http://www.johnwittenauer.net/a-simple-time-series-analysis-of-the-sp-500-index/

首先,这是 .csv 文件的示例。在这种情况下,数据以每月分辨率显示,它不是真实数据,只是随机选择数字来举例说明(在这种情况下,我希望一年足以能够制定第二年的预测;如果没有,完整的 csv 文件可用):

              Price
2011-01-31    32.21
2011-02-28    28.32
2011-03-31    27.12
2011-04-30    29.56
2011-05-31    31.98
2011-06-30    26.25
2011-07-31    24.75
2011-08-31    25.56
2011-09-30    26.68
2011-10-31    29.12
2011-11-30    33.87
2011-12-31    35.45

我目前的进度如下:

读取输入文件并将日期列设置为日期时间索引后,使用以下脚本对可用数据进行预测

model = sm.tsa.ARIMA(df['Price'].iloc[1:], order=(1, 0, 0))  
results = model.fit(disp=-1)  
df['Forecast'] = results.fittedvalues  
df[['Price', 'Forecast']].plot(figsize=(16, 12))  

,输出如下:

现在,正如我所说,我没有任何统计技能,我几乎不知道我是如何得到这个输出的(基本上,改变第一行内的顺序属性会改变输出),但是'actual' 预测看起来不错,我想再延长一年 (2016)。

为了做到这一点,在数据框中创建了额外的行,如下所示:

start = datetime.datetime.strptime("2016-01-01", "%Y-%m-%d")
date_list = pd.date_range('2016-01-01', freq='1D', periods=366)
future = pd.DataFrame(index=date_list, columns= df.columns)
data = pd.concat([df, future])

最后,当我使用 statsmodels 的 .predict 函数时:

data['Forecast'] = results.predict(start = 1825, end = 2192, dynamic= True)  
data[['Price', 'Forecast']].plot(figsize=(12, 8))

我得到的预测是一条直线(见下文),这看起来一点也不像预测。此外,如果我将现在从第 1825 天到第 2192 天(2016 年)的范围扩展到整个 6 年的时间跨度,则整个期间(2011-2016)的预测线都是一条直线。

我也尝试过使用 'statsmodels.tsa.statespace.sarimax.SARIMAX.predict' 方法,该方法考虑了季节性变化(在这种情况下有意义),但我得到一些关于 'module' 没有属性 'SARIMAX'。但这是次要问题,如果需要会详细介绍。

我在某个地方失去控制,我不知道在哪里。谢谢阅读。干杯!

听起来您使用的是不支持 SARIMAX 的旧版本 statsmodels。您需要安装最新发布的版本 0.8.0,请参阅 http://statsmodels.sourceforge.net/devel/install.html

我正在使用 Anaconda 并通过 pip 安装。

pip install -U statsmodels

SARIMAX 模型的结果 class 有许多有用的方法,包括预测。

data['Forecast'] = results.forecast(100)

将使用您的模型预测未来 100 步。

ARIMA(1,0,0) 是单周期自回归模型。所以这是一个遵循这个公式的模型:

这意味着时间段t中的值等于某个常数(phi_0)加上通过拟合ARMA模型确定的值(phi_1)乘以时间段中的值前期 r_(t-1),加上白噪声误差项 (a_t)。

你的模型只有1个周期的记忆,所以当前的预测完全由前期的1个值决定。这不是一个非常复杂的模型;它没有对所有先验值做任何花哨的事情。它只是将昨天的价格乘以某个值并加上一个常数。你应该期望它很快达到平衡,然后永远保持在那里。

顶部图片中的预测之所以看起来如此出色,是因为它只向您展示了数百个 1 期预测,这些预测在每个新时期都重新开始。它并没有像您可能认为的那样显示长期预测。

正在查看您发送的link:

http://www.johnwittenauer.net/a-simple-time-series-analysis-of-the-sp-500-index/

阅读他讨论为什么这个模型不能给你你想要的部分。

"So at first glance it seems like this model is doing pretty well. But although it appears like the forecasts are really close (the lines are almost indistinguishable after all), remember that we used the un-differenced series! The index only fluctuates a small percentage day-to-day relative to the total absolute value. What we really want is to predict the first difference, or the day-to-day moves. We can either re-run the model using the differenced series, or add an "我对 ARIMA 模型(产生 (1, 1, 0) 模型)的术语应该完成同样的事情。让我们尝试使用差分系列。"

要完成您正在尝试做的事情,您需要对这些模型进行更多研究并弄清楚如何格式化您的数据,以及哪种模型是合适的。最重要的是了解您认为输入模型的数据中包含哪些信息。您的模型当前正在尝试做的是说,"Today the price is . What will the price be tomorrow?" 就是这样。它没有任何关于动量、波动性等的信息。这没什么好说的。

尝试在预测时设置 dynamic = False