Python应用seasonal_decompose对金融时间序列进行分解。

3

我正在尝试对金融数据执行时间序列数据分析,并且想要进行季节性分解。

from statsmodels.tsa.seasonal import seasonal_decompose
import pandas as pd
import datetime
import pandas_datareader as data
df = data.get_data_yahoo('UGA', start=everSince, end=today)
df_close = df[['Close']]
result = seasonal_decompose(df_close, model='multiplicative')

我以这种方式得到的错误

您必须指定一个周期,或者x必须是具有PeriodIndex或DatetimeIndex且freq未设置为None的pandas对象

我知道我可以通过df.asfreq()指定频率,但金融数据没有每日频率(即,我没有每天的记录),因为它们是从星期一到星期五,并且有时会有假期。

如何将seasonal_decompose应用于这种类型的数据?我还尝试过df_close.index = df_close.index.to_period('B'),但没有起作用。

df的示例:

                Close
Date                 
2008-02-28  49.790001
2008-02-29  49.610001
2008-03-03  49.810001
2008-03-04  47.450001
2008-03-05  49.049999
2008-03-06  49.369999
2008-03-07  50.230000
2008-03-10  50.610001
2008-03-11  50.700001
2008-03-12  50.919998
2008-03-13  49.939999
2008-03-14  50.049999
2008-03-17  46.869999
2008-03-18  48.980000
2008-03-19  47.540001
2008-03-20  48.070000
2008-03-24  48.459999
2008-03-25  49.490002
2008-03-26  50.320000
2008-03-27  50.110001
2008-03-28  50.009998
2008-03-31  48.509998
2008-04-01  48.840000
2008-04-02  51.130001
2008-04-03  50.419998
2008-04-04  50.900002
2008-04-07  51.430000
2008-04-08  50.959999
2008-04-09  51.290001
2008-04-10  51.540001

其中索引的类型为pandas.core.indexes.datetimes.DatetimeIndex


你能提供一个输入数据的例子吗? - luigigi
1
我看到了问题,但我认为你必须操纵数据以符合seasonal_decompose的要求。例如,您可以重新采样数据并通过插值替换nan值:result = seasonal_decompose(df_close.resample('1D').asfreq().interpolate(), model='multiplicative') - luigigi
或者,如果您同意的话,您可以将其重新采样为每周数据。 - luigigi
1
我想保持每天的时间框架。我希望有一些方法来管理这些财务数据,但到目前为止,你的方式是最好的选择。 - roschach
1
@Mario 我记得有一些问题,现在无法告诉你具体是哪些问题。我记得当时我使用的是雅虎金融数据。 - undefined
显示剩余7条评论
1个回答

2

你的问题可以通过以下方法解决:

  • 如果你没有每日的数据,可以通过填补数据框中缺失的日期间隔并用 0 替换相关值来解决。
  • 为目标属性设置周期/频率以制造季节性效果:
# import libraries
import numpy as np
import pandas as pd
import datetime as dt
import statsmodels.api as sm
from statsmodels.tsa.seasonal import seasonal_decompose
print(sm.__version__)

# Generate some data
TODAY = dt.date.today()
ONE_WEEK = dt.timedelta(days=107)
ONE_DAY = dt.timedelta(days=1)

# Create pandas dataframe 
df = pd.DataFrame({'Date': [TODAY-ONE_WEEK, TODAY-3*ONE_DAY, TODAY], 'Close': [42, 45,127]})

#      Date    Close
#0  2021-09-02  42
#1  2021-12-15  45
#2  2021-12-18  127

# Fill the missing dates and relative attribute with 0
r = pd.date_range(start=df.Date.min(), end=df.Date.max())
df = df.set_index('Date').reindex(r).fillna(0).rename_axis('Date').reset_index().dropna()

# Set period/frequency using set_index() dates
df['Date'] = pd.to_datetime(df['Date'])
df = df.set_index('Date').asfreq('D').dropna()

#            Close
#Date   
#2021-09-02 42.0
#2021-09-03 0.0
#2021-09-04 0.0
#2021-09-05 0.0
#2021-09-06 0.0
#...    ...
#2021-12-14 0.0
#2021-12-15 45.0
#2021-12-16 0.0
#2021-12-17 0.0
#2021-12-18 127.0
# 108 rows × 1 columns

最后,现在我们可以使用函数seasonal_decompose()将时间序列数据分解为其他组件:
# inspect frequency attribute
print(df.index.freq)  #<Day>

# Reproduce the example for OP and plot output
seasonal_decompose(df, model='additive').plot()

输出:

img

如果您愿意,可以通过我的另一个答案实现另一个输出图:

img

注意:由于以下原因,分解无法适用于model='multiplicative'
ValueError: Multiplicative seasonality is not appropriate for zero and negative values

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接