signal, period] = ic[period][signal].mean() / ic[period][signal].std() factor_list = ['Factor1', 'Factor7', 'Factor9'] period = 20 from jaqs_fxdayu.research.signaldigger import process factor_dict = dict() index_member = id_member for name in factor_list: signal = dv.get_ts(name) # 调整符号 print(name) signal = process.winsorize(factor_df=signal, alpha=0.05, index_member=index_member) # 去极值 # print(signal.shape) signal = process.standardize(signal, index_member) # z-score标准化 保留排序信息和分布信息 # print(signal.shape) # signal = process.neutralize(signal,group=dv.get_ts("sw1"),float_mv = dv.get_ts("float_mv")) #行业中性化 print(signal.shape) factor_dict[name] = signal for name in factor_list: dv.append_df(factor_dict[name], name + '_J') # rollback_period代表滚动窗口所用到的天数,即用前多少期的数据来计算现阶段的因子权重。 通常建议设置时间在半年以上,可以获得相对稳定的预期结果
# In[94]: from jaqs_fxdayu.research.signaldigger import process negative = ['alpha206','alpha197','alpha195','alpha211','alpha194','alpha64_','alpha56_','alpha42_','pb','pe'] factor_dict = dict() for name in factor_lis: print(name) if name in negative: signal = -1*dv.get_ts(name) # 调整符号 else: signal = dv.get_ts(name) signal = process.winsorize(factor_df=signal,alpha=0.05)#去极值 # 行业市值中性化 signal = process.neutralize(signal, group=dv.get_ts("sw1"),# 行业分类标准 ) signal = process.standardize(signal) #z-score标准化 保留排序信息和分布信息 factor_dict[name] = signal import pickle with open('Neutralized_Postive_Data.pkl','wb') as f: pickle.dump(factor_dict,f) import pickle
ir_table.plot(kind="barh", figsize=(15, 5)) #3_因子预处理 #根据之前的分析,可知momentum、ps、pe、pb这4个因子在几个持有期下与股票收益的关系(ic)都是负的,故需进一步分析这4个人因子 #先统一调整成正相关关系,并且需要完成以下几个步骤 #去极值 #标准化 -- z-score/rank; z-score标准化,也称为标准化分数,这种方法根据原始数据的均值和标准差进行标准化(会保留因子原有的基本分布信息), #经过处理后的数据符合标准正态分布,即均值为0,标准差为1(根据下面的转化函数很容易证明),转化函数为:(X-均值)/标准差.而rank标准化会保留因子的排序信息,但会删除因子的分布信息. #行业市值中性化(这一步是为了防止所选股票的因子在行业或市值上有过多的暴露,(例如:所选股票全是某一行业或全是小市值的股票)) from jaqs_fxdayu.research.signaldigger import process factor_dict = dict() #处理后的因子factor_dict index_member = dv.get_ts("index_member") for name in ["pb", "pe", "ps", "momentum"]: signal = -1 * dv.get_ts(name) # 调整符号 这里表示统一调整成正相关关系 process.winsorize(factor_df=signal, alpha=0.05, index_member=index_member ) #factor_df=signal是输入的因子值,alpha=0.05表示去掉因子值左右两端5%的数值, #index_member=index_member表示需要传入的是否是指数成分的一个dataframe,传入后仅会处理指数成分股,对非指数成分股则不会进行处理 signal = process.standardize(signal, index_member) #z-score标准化 保留排序信息和分布信息 # signal = process.rank_standardize(signal,index_member) #rank标准化 因子在截面排序并归一化到0-1(只保留排序信息) # # 行业市值中性化(这步可以做也可以不做,其作用是在横截面上把行业风格与市值风格给剔除掉) # signal = process.neutralize(signal, # group=dv.get_ts("sw1"),# 行业分类标准 # float_mv = dv.get_ts("float_mv"), #流通市值 可为None 则不进行市值中性化 # index_member=index_member,# 是否只处理时只考虑指数成份股 # ) factor_dict[name] = signal #输出结果,结果为字典 #4_施密特正交化 ''' 对筛选后的因子进行组合,一般有以下常规处理: 1:因子间存在较强同质性时,可以使用施密特正交化方法对因子做正交化处理,用得到的正交化残差作为因子,这样可以剔除同质化部分. 但是这也有一个弊端:由于正交化会破坏因子的经济学逻辑,并剔除一些原有的信息(包括原因子之间的联系,这可能导致不好的影响),造成与原因子差别太大,固也可以不使用或谨慎使用.
def test_multi_factor(): from jaqs_fxdayu.research.signaldigger import multi_factor, process dv = DataView() dv.load_dataview(dataview_folder) dv.add_formula("momentum", "Return(close_adj, 20)", is_quarterly=False, add_data=True) mask = mask_index_member(dv) can_enter, can_exit = limit_up_down(dv) ic = dict() factors_dict = { signal: dv.get_ts(signal) for signal in ["pb", "pe", "ps", "momentum"] } for period in [5, 15]: ic[period] = multi_factor.get_factors_ic_df( factors_dict, price=dv.get_ts("close_adj"), high=dv.get_ts("high_adj"), # 可为空 low=dv.get_ts("low_adj"), # 可为空 n_quantiles=5, # quantile分类数 mask=mask, # 过滤条件 can_enter=can_enter, # 是否能进场 can_exit=can_exit, # 是否能出场 period=period, # 持有期 benchmark_price=dv. data_benchmark, # 基准价格 可不传入,持有期收益(return)计算为绝对收益 commission=0.0008, ) factor_dict = dict() index_member = dv.get_ts("index_member") for name in ["pb", "pe", "ps", "momentum"]: signal = -1 * dv.get_ts(name) # 调整符号 process.winsorize(factor_df=signal, alpha=0.05, index_member=index_member) # 去极值 signal = process.rank_standardize( signal, index_member) # 因子在截面排序并归一化到0-1(只保留排序信息) signal = process.standardize(signal, index_member) # z-score标准化 保留排序信息和分布信息 # 行业市值中性化 signal = process.neutralize( signal, group=dv.get_ts("sw1"), float_mv=dv.get_ts("float_mv"), index_member=index_member, # 是否只处理时只考虑指数成份股 ) factor_dict[name] = signal # 因子间存在较强同质性时,使用施密特正交化方法对因子做正交化处理,用得到的正交化残差作为因子 new_factors = multi_factor.orthogonalize( factors_dict=factor_dict, standardize_type="rank", # 输入因子标准化方法,有"rank"(排序标准化),"z_score"(z-score标准化)两种("rank"/"z_score") winsorization=False, # 是否对输入因子去极值 index_member=index_member) # 是否只处理指数成分股 # 多因子组合-动态加权参数配置 props = { 'price': dv.get_ts("close_adj"), 'high': dv.get_ts("high_adj"), # 可为空 'low': dv.get_ts("low_adj"), # 可为空 'ret_type': 'return', # 可选参数还有upside_ret/downside_ret 则组合因子将以优化潜在上行、下行空间为目标 'benchmark_price': dv.data_benchmark, # 为空计算的是绝对收益 不为空计算相对收益 'period': 30, # 30天的持有期 'mask': mask, 'can_enter': can_enter, 'can_exit': can_exit, 'forward': True, 'commission': 0.0008, "covariance_type": "shrink", # 协方差矩阵估算方法 还可以为"simple" "rollback_period": 120 } # 滚动窗口天数 comb_factors = dict() for method in [ "equal_weight", "ic_weight", "ir_weight", "max_IR", "max_IC", "factors_ret_weight" ]: comb_factors[method] = multi_factor.combine_factors( factor_dict, standardize_type="rank", winsorization=False, weighted_method=method, props=props)