之前分享过系列的代码:
行业指数轮动:一个可实盘策略的“魔改”历程,十年年化15%(策略+代码+数据下载)
我们下载29个A股主要行业指数。
下面是etf与指数的对应关系:
etfs_indexes = {
'159870.SZ':'000813.CSI',
'512400.SH':'000819.SH',
'515220.SH':'399998.SZ',
'515210.SH': '930606.CSI',
'516950.SH': '930608.CSI',
'562800.SH': '930632.CSI',
'515170.SH': '000815.CSI',
'512690.SH': '399987.SZ',
'159996.SZ': '930697.CSI',
'159865.SZ': '930707.CSI',
'159766.SZ': '930633.CSI',
'515950.SH': '931140.CSI',
'159992.SZ': '931152.CSI',
'159839.SZ': '399441.SZ',
'512170.SH': '399989.SZ',
'159883.SZ': 'h30217.CSI',
'512980.SH': '399971.CSI',
'159869.SZ': '930901.CSI',
'515050.SH': '931079.CSI',
'515000.SH': '931087.CSI',
'515880.SH': '931160.CSI', '512480.SH': 'h30184.CSI', '515230.SH': 'h30202.CSI', '512670.SH': '399973.SZ', '515790.SH': '931151.CSI', '159757.SZ': '980032.CNI', '516110.SH': 'h30015.CSI', '512800.SH': '399986.SZ', '512200.SH': '931775.CSI', }
使用指数数据的好处在于,可回测周期比较长。
数据我已经帮大家下载好,并完成格式统一化:
准备因子集——由于机器学习需要的因子比较多,不像传统量化,可能就几条规则几个因子,我们直接手写就好了。
from abc import abstractmethod class AlphaBase: # 返回因子集的fields, names @abstractmethod def get_factors(self): pass def get_field_by_name(self, name): fields, names = self.get_factors() for f,n in zip(fields, names): if n == name: return f def get_labels(self): return ["label(shift(close, -1)/close - 1,0)"], ['label'] def get_ic_labels(self): days = [1, 5, 10, 20] fields = ['shift(close, -{})/close - 1'.format(d) for d in days] names = ['return_{}'.format(d) for d in days] return fields, names def get_all_fields_names(self, b_ic=False): fields, names = self.get_factors() if not b_ic: label_fields, label_names = self.get_labels() else: label_fields, label_names = self.get_ic_labels() fields.extend(label_fields) names.extend(label_names) return fields, names class AlphaLit: def get_all_features_names(self): fields,names = self.get_fields_names() label_field, label_name = self.get_label() all_fields = fields.copy() all_fields.append(label_field) all_names = names.copy() all_names.append(label_name) return all_fields, all_names def get_fields_names(self): fields = [] names = [] windows = [2, 5, 10, 20] fields += ['close/shift(close,%d) - 1' % d for d in windows] names += ['roc_%d' % d for d in windows] fields += ['avg(volume,1)/avg(volume,5)'] names += ['avg_amount_1_avg_amount_5'] fields += ['avg(volume,5)/avg(volume,20)'] names += ['avg_amount_5_avg_amount_20'] fields += ['rank(avg(volume,1))/rank(avg(volume,5))'] names += ['rank_avg_amount_1_avg_amount_5'] fields += ['avg(volume,5)/avg(volume,20)'] names += ['rank_avg_amount_5_avg_amount_20'] windows = [2, 5, 10] fields += ['rank(roc_%d)' % d for d in windows] names += ['rank_roc_%d' % d for d in windows] fields += ['rank(roc_2)/rank(roc_5)'] names += ['rank_roc_2_rank_roc_5'] fields += ['rank(roc_5)/rank(roc_10)'] names += ['rank_roc_5_rank_roc_10'] return fields, names def get_label(self): return "shift(close, -10)/close - 1,0)", 'label'
dataloader支持截面函数:
df_all.set_index([df_all.index,'symbol'],inplace=True) for rank_field, rank_name in rank_exprs: #支持截面rank,逻辑加在这里 se = calc_expr(df_all, rank_field) se.name = rank_name df_all[rank_name] = se #df_all['symbol'] = df_all.index. #df_all = df_all.set_index(df_all.index.l) # todo groupby('date').rank(pct=True) df_all = df_all.loc[self.start_date: self.end_date] return df_all
支持截面函数rank(时间序列排序是ts_rank):
def rank(se: pd.Series): ret = se.groupby(level=1).rank(pct=True) return ret
吾日三省吾身
今早悟到几句话,与大家分享。
作为普通人,进攻才是最好的防守。
守正很重要,出奇更重要。
普通人就是没有特别的家世,没有耀眼的资源加持,光着脚或者刚穿上鞋。一味地守正,患得患失,抵御风险能力有限。
守正,注意风险底限,不碰触法律,以及不做带来不可逆风险的决策。建立系统,做时间的朋友。
但还不够多,这个时代,最焦虑的就是中产。
经济形势风吹草动都带来影响。
中考分流,行业裁员,房价波动。。。
刚装上的鞋子怕掉了。
出奇——是反脆弱,是杠铃配置。追热点,高赔率的投资,顶级的人脉圈。
可遇而不可求,但这些才是人生安全感的来源。
——游泳的时候,如何不掉下去?——往前游就是了。
时间会解释一切,因为长期来看,我们都会死,历史长河不过沧海一粟。
——人生没有意义,人生只是一场体验。
有些人小心翼翼一辈子,却没有真正活过。
在守正的基础上,大胆去尝试,去折腾。
生命在于体验,允许一切发生,体验而已。
发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/103553
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!