perf(metrics): rolling alpha/beta 向量化(O(n²)→O(n),治分钟级卡死)
compute_metrics rolling alpha/beta 原 for 循环每点 iloc[:i+1].cov/var = O(n²)。日线 111 天没事,分钟级 daily_df(万行)卡死(cta_c287f4b5 卡 5min CPU88%)。改 pandas expanding 向量化(cov/var/mean O(n)),数值与原循环一致(beta/alpha diff<1e-15,NaN 位置匹配)。pytest 6 绿。触发:b2c41c7 降级让 compute_metrics 首次在 benchmark 有数据时真跑(此前 benchmark 空被 skip),暴露 rolling O(n²) 性能 bug。
This commit is contained in:
@@ -69,15 +69,13 @@ def compute_metrics(
|
||||
equity = empyrical.cum_returns(s)
|
||||
bench_curve = empyrical.cum_returns(b)
|
||||
# rolling alpha/beta (expanding window 用于画图,口径由 scalars 保证)
|
||||
roll_beta = pd.Series(index=s.index, dtype=float)
|
||||
roll_alpha = pd.Series(index=s.index, dtype=float)
|
||||
for i in range(len(s)):
|
||||
sub = aligned.iloc[: i + 1]
|
||||
if len(sub) >= 2 and sub["b"].var() > 0:
|
||||
beta = sub["s"].cov(sub["b"]) / sub["b"].var()
|
||||
alpha = sub["s"].mean() - beta * sub["b"].mean()
|
||||
roll_beta.iloc[i] = beta
|
||||
roll_alpha.iloc[i] = alpha * period
|
||||
# 向量化 expanding (O(n)) 替代原 for 循环 (O(n²))——分钟级 daily_df(万行)原循环卡死
|
||||
# (cta_c287f4b5 卡 5min CPU88% 根因)。expanding.cov/.var/.mean 数值与原循环一致
|
||||
# (ddof=1);var_b<=0(含单点 NaN)处 beta=NaN,与原 len>=2 且 var>0 守卫等价。
|
||||
cov_sb = aligned["s"].expanding().cov(aligned["b"])
|
||||
var_b = aligned["b"].expanding().var()
|
||||
roll_beta = cov_sb / var_b.where(var_b > 0)
|
||||
roll_alpha = (aligned["s"].expanding().mean() - roll_beta * aligned["b"].expanding().mean()) * period
|
||||
# drawdown: 从峰值回落 (值 <= 0)
|
||||
cummax = equity.cummax()
|
||||
drawdown = (equity - cummax) / cummax
|
||||
|
||||
Reference in New Issue
Block a user