我正在尝试使用 EWMA(指数加权移动平均线)计算波动性。
这是我开发的功能:
def ewm_std(x, param=0.99):
n = len(x)
coefs = param ** np.arange(n)[::-1]
mean_x = np.mean(x)
squared_diff = (x - mean_x) ** 2
res = np.sqrt(np.dot(squared_diff, coefs) / np.sum(coefs))
return res
权重参数始终设置为0.99,窗口大小为255。
我将该函数应用到我的 DataFrame(每列是一个场景,每行一个日期),如下所示:
df.rolling(window=255).apply(ewm_std, raw=True)
问题是速度很慢,而且我没能优化它。我希望最终得到相同的结果。
如何提高性能?
假设“col”是您感兴趣的列,您可以使用纯 numpy 和
sliding_window_view
:
from numpy.lib.stride_tricks import sliding_window_view as swv
# test input
np.random.seed(0)
df = pd.DataFrame({'col': np.random.random(1000)})
window = 255
param = 0.99
coefs = param ** np.arange(window)[::-1]
x = swv(df['col'], window)
mean_x = x.mean(axis=1)[:, None]
squared_diff = (x - mean_x) ** 2
res = np.sqrt(np.dot(squared_diff, coefs) / np.sum(coefs))
df['out'] = pd.Series(res, index=df.index[window-1:])
# validation
df['expected'] = df.rolling(window=window)['col'].apply(ewm_std, raw=True)
np.allclose(df.loc[window-1:, 'expected'], df.loc[window-1:, 'out'])
# True