滚动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的地址,还有其他列的存在,程序就会出错。

浙公网安备 33010602011771号