我正在尝试分析股票回报的季节性(但实际上可以是任何类型的时间序列):
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 值)。这似乎有帮助,但并不能完全解决问题。 有任何想法吗?谢谢
这不是
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()
当我处理季节性数据时,我遇到了类似的问题,但我有每日记录,并且必须找到每周的季节性。
我的解决方案是转换数据,使每年有 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"})
这是一个简单的解决方案,而且效果很好。
您能否提供更多信息:
您可以在端点处拟合样条曲线和力周期性吗?
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