滚动rank_ic函数思路

在求一个时序的rank_ic 尤其是滚动rank_ic中。原理是 对特征的每个滚动窗口内排序,然后对收益率的每个滚动窗口内排序,再求corr。
如果正常的滚动ic。 是 data[name].rolling(1000).corr(data['pf']) 其中 name是特征名称,'pf'是收益率名称,1000为滚动窗口。
而rank_ic涉及到2列数据,使用pandas的rolling().apply() 支持1列,使用 engine='numba' 没搞定,总是出错。

最后用两个方式实现,
1 使用列表推导式

from scipy.stats import spearmanr
def rolling_rank_ic(df,x_name='',y_name='',window=2):
    a=df[[x_name,y_name]].to_numpy()   
    b=[np.nan]*window+[spearmanr(a[x-window:x,0],a[x-window:x,1])[0] for x in range(window,len(a))]
    return b

t0=datetime.datetime.now()
data['rank_ic']=rolling_rank_ic(data,name,'pf',window=100)
print(datetime.datetime.now()-t0)

6000行结果用时:0:00:02.009037

2 使用np.lib.stride_tricks.as_strided

import numpy as np
def rolling_window(a, window_size):
    shape = (a.shape[0] - window_size + 1, window_size,2)
    strides=a.itemsize*(np.array([1,1,a.shape[0]]))
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

t0=datetime.datetime.now()
a=data[[name,'pf']].iloc[0:].to_numpy(copy=True)   
aa1=rolling_window(a,100)
data['rank_ic']=[np.nan]*(100-1)+[spearmanr(x[:,0],x[:,1])[0] for x in aa1]
print(datetime.datetime.now()-t0)

6000行结果用时:0:00:01.976891

这里注意的是 strides的设置。网上说是按照行计数,但我感觉是按照列计数。还有一点就是 to_numpy 必须要带 copy=True,
猜测可能是根据内存连续地址找的,如果copy=False,可能得到的是 dataframe的地址,还有其他列的存在,程序就会出错。

posted @ 2025-07-19 09:47  远方_2408  阅读(38)  评论(0)    收藏  举报