用于季节性模型的Polyfit

问题描述 投票:0回答:3

我正在尝试分析股票回报的季节性(但实际上可以是任何类型的时间序列): enter image description here

x 轴上是周数,y 轴上是每周的历史平均回报率。为了更好地说明,每个点代表股票在 52 周(x 轴)的每一周内的平均回报(y 轴);平均值考虑了过去 20 年的情况。 我正在尝试使用多项式模型对数据进行降噪并获得更平滑的信号。

我知道我可以使用 numpy.polyfit 获得多项式系数

numpy.polyfit( weeks , return , deg)

问题在于,在上面的示例中,我在第 52 周(红色圆圈)收到的信号与我在下一周收到的信号(绿色圆圈,即第二年的第一周)完全不同。 我试图避免从 12 月最后一周的信号到 1 月第一周的信号的这种跳跃。有没有办法强制 polyfit 找到对于两个给定输入 x 值(在我的例子中为 1 和 52)产生相同函数结果的系数?

否则,我可以用这些数据做些什么来缓解这个问题吗?我尝试过的一件事是在第一个周之前添加“假周”(因此我创建了周 -9 到 0,其与第 43 周到第 52 周具有相同的 Y 值),并在最后一周之后添加其他假周(因此我们有第 53 周)到 62,它们具有相同的第 1 周到第 10 周的 Y 值)。这似乎有帮助,但并不能完全解决问题。 有任何想法吗?谢谢

numpy scipy statistics time-series
3个回答
1
投票

这不是

polyfit
的工作。从根本上讲,您的数据代表一个周期性过程。一种方法是应用真正的 FFT,然后选择性地限制带宽。这将产生一个光谱序列,该序列“知道”Jan 1 和 Dec 31+1 是同一件事。具有较高的带宽,

import matplotlib.pyplot as plt
import numpy as np


ave_return = np.array([
    0.29549823, -0.04327911, -0.28475728,  0.24133149,  0.29175083,
    0.05927994, -0.19481259,  0.0682162 ,  0.12219757,  0.2537674 ,
    0.24648395,  0.15455555,  0.27520195, -0.01664706, -0.47437987,
   -0.01138717, -0.02216335,  0.0930811 ,  0.61556973,  0.30738668,
    0.30734683,  0.21362355,  0.13790445, -0.15041544, -0.37567391,
   -0.06940527, -0.12529933, -0.26046757, -0.34338869, -0.3451905 ,
   -0.02994229, -0.04620011, -0.03362213,  0.16813838,  0.20072505,
   -0.22111894, -0.23910233, -0.29322923, -0.06443125, -0.07527673,
   -0.25189341, -0.16183438, -0.07362219, -0.09708203,  0.00569532,
    0.23257541,  0.07938912,  0.03610597, -0.23765742, -0.32248603,
    0.04504569, -0.01805558,  0.03534886,
])

spectrum = np.fft.rfft(ave_return)
spectrum[30:] = 0

verified = np.fft.irfft(spectrum)

plt.scatter(np.arange(len(ave_return)), ave_return)
plt.plot(verified)
plt.show()

high-bw

将带宽从 30 降低到 6 左右,可以更明显地看出周期序列在同一位置开始和结束: low-bw


0
投票

当我处理季节性数据时,我遇到了类似的问题,但我有每日记录,并且必须找到每周的季节性。

我的解决方案是转换数据,使每年有 52 周。但是,52*7 是 364,因此会多出 1 或 2 天(如果是闰年)。我将这些额外的日子视为上周的一部分。

我使用了这个公式(我有每日数据):

df["Week"] = (df["Date"].dt.dayofyear - 1) // 7
df["Week"] = df["Week"].clip(0, 51)

之后,我将季节性计算为简单平均值:

df.groupby("Week").agg({"ValueName": "mean"})

这是一个简单的解决方案,而且效果很好。

您能否提供更多信息:

  • “周”到底是什么意思?是ISO-week,还是其他什么?
  • 可以获取每日数据吗?

0
投票

您可以在端点处拟合样条曲线和力周期性吗?

from scipy.interpolate import BSpline, splrep
ave_return = np.array([
    0.29549823, -0.04327911, -0.28475728,  0.24133149,  0.29175083,
    0.05927994, -0.19481259,  0.0682162 ,  0.12219757,  0.2537674 ,
    0.24648395,  0.15455555,  0.27520195, -0.01664706, -0.47437987,
   -0.01138717, -0.02216335,  0.0930811 ,  0.61556973,  0.30738668,
    0.30734683,  0.21362355,  0.13790445, -0.15041544, -0.37567391,
   -0.06940527, -0.12529933, -0.26046757, -0.34338869, -0.3451905 ,
   -0.02994229, -0.04620011, -0.03362213,  0.16813838,  0.20072505,
   -0.22111894, -0.23910233, -0.29322923, -0.06443125, -0.07527673,
   -0.25189341, -0.16183438, -0.07362219, -0.09708203,  0.00569532,
    0.23257541,  0.07938912,  0.03610597, -0.23765742, -0.32248603,
    0.04504569, -0.01805558,  0.03534886,
])
N = len(ave_return)
xx = np.linspace(0., 12., N)
t, c, k = splrep(xx, ave_return, s=.3, k=4,per=True)
spline = BSpline(t, c, k, extrapolate=False)

plt.plot(xx, ave_return, 'bo', label='Original points')
plt.plot(xx, spline(xx), 'r', label='BSpline')
plt.grid()
plt.legend(loc='best')
plt.show()


  [1]: https://i.sstatic.net/MiAi5FpB.png
© www.soinside.com 2019 - 2024. All rights reserved.