专题一(附加)时间序列趋势分析
Prophet模型能够捕获时间序列数据中的各种模式,包括周期性(年度、季度、月度、周度)、季节性和节假日效应等,可以生成模型中的各种组成部分,包括趋势、季节性、节假日效应。这有助于解释时间序列数据的趋势和变化。
seasonal_decompose 是一个传统的时间序列分解工具,适用于简单的季节性和趋势分析。而Prophet是一个更高级的工具,适用于更复杂的时间序列分析,特别是对于包含多种季节性模式和假日效应的数据。
本文分别运用两种时间序列分解的方法,以股票2023-01-01至2023-10-14的时间序列数据为例,进行了数据导入、趋势数据生成、可视化、解释结果。
更多金融、大数据相关案例代码可以关注gzh‘finance褪黑素’回复关键字获取。
一、Prophet时间序列分解
1.数据准备
导入需要的库:baostock与prophet
import pandas as pd
import datetime
from prophet import Prophet
import baostock as bs
import numpy as np
import matplotlib.pyplot as plt
导入股票数据
lg = bs.login()
rs = bs.query_history_k_data_plus("sh.000001", "date,code,open,high,low,close",
start_date='2023-01-01', end_date='2023-10-14',
frequency="d", adjustflag="3")
# 输出结果
data_list = []
while (rs.error_code == '0') & rs.next():
# 获取一条记录,将记录合并在一起
data_list.append(rs.get_row_data())
result = pd.DataFrame(data_list, columns=rs.fields)
# 退出系统
bs.logout()
处理数据:将时间列变为系统认可的时间数据,并提取需要的列生成新的表格。
result['time']= pd.to_datetime(result['date'])
# 创建一个包含日期时间戳和观测值的DataFrame
df = pd.DataFrame({'ds': result['time'],
'y': result['open']})
2.创建模型
# 创建 Prophet 模型
model = Prophet()
model.add_seasonality(name='weekly', period=5, fourier_order=6)
model.add_seasonality(name='monthly', period=20, fourier_order=6)
# 拟合模型
model.fit(df)
上面代码中,model = Prophet()创建了一个Prophet模型的实例。然后才可以在模型中添加季节性成分、假日等。
add_seasonality是Prophet模型中的一个重要参数,它用于添加自定义组件,以更好地捕获时间序列中的自定义模式。
add_seasonality方法的一些主要参数如下:
参数 | 解释 |
---|---|
name | 描述季节性的名称,例如“weekly”、“yearly”等。 |
period | 季节性成分的周期长度。如果想捕捉每周的季节性,则将其设置为7;如果是每年的季节性,则设置为365.25(到闰年) |
fourier_order | 控制用于导出模型的傅立叶级数的阶数。增加这个值可以使模型更加灵活,但也可能导致过度导出。通常,建议从3开始,并根据需要进行调整。 |
prior_scale | 控制某个成分的影响力,用于控制某个成分的平滑程度。增加此值将增加某个成分的影响力。通常,可以从0.1开始,并根据需要进行调整。 |
mode | 这是一个字符串,指定当前成分的模式。可以设置为“additive”(加法模式)或“multiplicative”(乘法模式),具体取决于一个的性质。 |
cap和floor | 这些可选参数,用于处理上限和下限。它们分别表示时间序列的最大上限和最小下限。 |
在上面的代码中,我通过add_seasonality方法向模型添加了两个季节性成分:
“weekly” 季节性,股票数据一周的周期为5天,period参数为5,并使用6阶的傅立叶级数来拟合季节性模式。
“monthly” 季节性,周期为20-22天,并同样使用6阶的傅立叶级数来拟合季节性模式。
这些季节性成分的目的是捕捉时间序列数据中的每周和每月的季节性模式。
拟合模型后结果为一个表格,分别是各个趋势等特征的数据,保存在tt变量中:
tt = model.predict(df)
以下是对生成表格特征的解释,是重要的结果,这些结果在模型预测中非常有用:
-
trend:这是模型捕获的趋势成分,它代表时间序列数据的整体趋势。
trend
列中包含了对未来时间点的趋势预测。 -
yhat_lower 和 yhat_upper:这些是预测结果的下限和上限。它们表示模型对未来值的不确定性范围。
yhat_lower
是预测值的最低估计,yhat_upper
是最高估计。这些范围可以帮助你了解模型的不确定性。 -
additive_terms:这是捕获到的附加季节性成分,通常是季节性模式、假期效应等。
additive_terms
表示附加季节性对预测的影响。 -
monthly 和 weekly:这些是具体季节性成分,例如每月季节性和每周季节性。它们分别表示每月和每周季节性对预测的影响。
-
multiplicative_terms:这是捕获到的乘法季节性成分,它表示季节性成分以乘法方式影响预测值。通常,这将在模型中考虑数据的相对比例效应。
-
yhat:这是Prophet模型的总体预测值,它是趋势、季节性和其他影响因素的组合。
yhat
是你最终的预测结果,它代表了对未来时间点的总体估计。
这些术语和结果一起帮助你理解Prophet模型如何进行时间序列预测,以及每个成分对预测值的影响。可以使用这些结果来解释和可视化预测结果,以便更好地了解时间序列数据的趋势和季节性。
3.可视化结果
model.plot_components(tt)
通过观察每周成分图,可以识别对时间序列数据具有显著影响的周期性效应。如果每周成分图显示出现明显的波动,那么数据可能具有一周的周期性。从Prophet模型的plot_components
方法生成的结果图中,我们可以看到长期趋势、每周季节性和每月周期性都显示明显的波动,这表明时间序列数据包含了复杂的趋势和季节性结构。
如果纵轴变化都很小,大约在零点几,变化不大,因此可以忽略不计,不认为具有明显的每周变动。这种分析有助于我们更好地理解时间序列数据中不同成分的影响和波动。
趋势 (Trend):
明显波动的趋势成分表明数据中存在长期趋势的波动。这可能意味着数据在较长时间内呈现出明显的上升和下降趋势,这些趋势在较长时间内不断变化。趋势波动可能是由各种因素引起的。
4.结果分析
prophet提取季节性对时间序列进行预测,查看模型拟合误差:
result.set_index('time', inplace=True)
float_list = [float(str_num) for str_num in result['open']]
tt2 = tt.copy()
tt2.set_index('ds', inplace=True)
import matplotlib.pyplot as plt
res = float_list - tt2['yhat']
plt.figure(figsize=(12, 6))
ax2 = plt.subplot(2, 1, 2)
ax2.plot(df['ds'], res)
ax2.set_xlabel('date')
ax2.set_title('residuals')
# 调整布局
plt.tight_layout()
# 显示图形
plt.show()
更多相关资料、大数据、金融案例可guanzhu gzh’finance褪黑素’回复关键词获取。
5.节假日效应
如果需要考虑像5月1日、10月1日这样的特殊节假日,则需要进行特殊处理。
首先导入需要考虑的节假日数据,生成表格:
#创建节假日数据框
qingming = pd.DataFrame({
'holiday': 'qingming',
'ds': pd.to_datetime(['2023-04-05','2023-04-06']),
'lower_window': 0,
'upper_window': 1,
})
laodong = pd.DataFrame({
'holiday': 'laodong',
'ds': pd.to_datetime(['2023-04-29', '2023-05-03']),
'lower_window': 0,
'upper_window': 1,
})
duanwu = pd.DataFrame({
'holiday': 'duanwu',
'ds': pd.to_datetime(['2023-06-22', '2023-06-24']),
'lower_window': 0,
'upper_window': 1,
})
guoqing = pd.DataFrame({
'holiday': 'guoqing',
'ds': pd.to_datetime(['2023-09-29', '2023-10-06']),
'lower_window': 0,
'upper_window': 1,
})
holidays = pd.concat([qingming, laodong,duanwu,guoqing])
在创建模型时,和前文差不多,只需要添加holiday参数:
model = Prophet(holidays=holidays)
model.add_seasonality(name='weekly', period=5, fourier_order=6)
model.add_seasonality(name='monthly', period=20, fourier_order=6)
# 拟合模型
model.fit(df)
生成图表:
tt = model.predict(df)
model.plot_components(tt)
图表会多一个关于节假日的描述,说明在清明节、五一劳动节出现了比较大的波动。
二、传统的时间序列分解
股票数据不适合传统的时间序列分解,因为股票数据并不是连续的,每周只有五个交易日。
选择比特币进行分析。
result = pd.read_csv("bitcoin.csv")
result = result[-270:]
处理数据,将行索引设置为标准的日期格式:
result['date']= pd.to_datetime(result['date'])
result.set_index('date', inplace=True)
提取bitcoin_price列进行分解:
result1 = seasonal_decompose(result['bitcoin_price'], model='additive')
可视化原始数据、长期趋势、季节趋势和误差:
# 绘制分解后的系列
plt.figure(figsize=(12, 10))
# 原始数据
plt.subplot(4, 1, 1)
plt.plot(result.index, result['bitcoin_price'], label='open', color='b')
plt.title('Data')
plt.xlabel('Date')
plt.ylabel('Data Value')
plt.grid(False)
plt.legend()
# 趋势分量
plt.subplot(4, 1, 2)
plt.plot(result.index, result1.trend, label='Trend', color='b')
plt.title('Trend Component')
plt.xlabel('Date')
plt.ylabel('Trend Value')
plt.grid(False)
plt.legend()
# 季节效应
plt.subplot(4, 1, 3)
plt.plot(result.index, result1.seasonal, label='Seasonal', color='b')
plt.title('Seasonal Component')
plt.xlabel('Date')
plt.ylabel('Seasonal Value')
plt.grid(False)
plt.legend()
# 残差
plt.subplot(4, 1, 4)
plt.plot(result.index, result1.resid, label='Residual', color='b')
plt.title('Residual Component')
plt.xlabel('Date')
plt.ylabel('Residual Value')
plt.grid(False)
plt.legend()
plt.tight_layout()
plt.show()
本文代码和所用数据可以关注gzh‘finance褪黑素’回复关键词获取。