第17节 UMP边裁交易决策
2017年10月13日
第19节 数据源
2017年10月13日

第18节 自定义裁判决策交易

作者: 阿布

阿布量化版权所有 未经允许 禁止转载

abu量化系统github地址(欢迎+star)

本节ipython notebook

上一节示例了ump边裁的使用以及回测示例,最后说过对决策效果提升最为重要的是:训练更多交易数据,更多策略来提升裁判的拦截水平及拦截认知范围,给每一个裁判看更多的比赛录像(回测数据),提高比赛录像水准,从多个不同视角录制比赛(回测交易),扩展裁判。

对于ump模块每个裁判类有自己关心的交易特征,使用特定的特征做为决策依据,即:每个裁判有自己在比赛中所特定关心的视角或者行为,之前的章节讲解的都是abupy内置裁判的使用示例,本节将讲解示例自定义裁判,通过不同的视角录制比赛。

对于训练更多交易数据,更多策略来提升裁判的拦截水平及拦截认知范围请阅读之后的章节中的相关全市场回测。

与之前章节一样,本节示例的相关性分析只限制在abupy内置沙盒数据中,和上一节一样首先将内置沙盒中美股,A股,港股, 比特币,莱特币,期货市场中的symbol都列出来,然后组成训练集和测试集,买入卖出因子等相同设置:

us_choice_symbols = ['usTSLA', 'usNOAH', 'usSFUN', 'usBIDU', 'usAAPL', 'usGOOG', 'usWUBA', 'usVIPS']
cn_choice_symbols = ['002230', '300104', '300059', '601766', '600085', '600036', '600809', '000002', '002594']
hk_choice_symbols = ['hk03333', 'hk00700', 'hk02333', 'hk01359', 'hk00656', 'hk03888', 'hk02318']
tc_choice_symbols = ['btc', 'ltc']
# 期货市场的直接从AbuFuturesCn().symbo中读取
ft_choice_symbols = AbuFuturesCn().symbol.tolist()

# 训练集:沙盒中所有美股 + 沙盒中所有A股 + 沙盒中所有港股 + 比特币
train_choice_symbols = us_choice_symbols + cn_choice_symbols +  hk_choice_symbols + tc_choice_symbols[:1]
# 测试集:沙盒中所有期货 + 莱特币
test_choice_symbols = ft_choice_symbols  + tc_choice_symbols[1:]

# 设置初始资金数
read_cash = 1000000
# 买入因子依然延用向上突破因子
buy_factors = [{'xd': 60, 'class': AbuFactorBuyBreak},
               {'xd': 42, 'class': AbuFactorBuyBreak}]

# 卖出因子继续使用上一节使用的因子
sell_factors = [
    {'stop_loss_n': 1.0, 'stop_win_n': 3.0,
     'class': AbuFactorAtrNStop},
    {'class': AbuFactorPreAtrNStop, 'pre_atr_n': 1.5},
    {'class': AbuFactorCloseAtrNStop, 'close_atr_n': 1.5}
]
# 回测生成买入时刻特征
abupy.env.g_enable_ml_feature = True

使用load_abu_result_tuple读取第15节中保存在本地的训练集数据:

abu_result_tuple_train = abu.load_abu_result_tuple(n_folds=2, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                                                   custom_name='lecture_train')
orders_pd_train = abu_result_tuple_train.orders_pd
AbuMetricsBase.show_general(*abu_result_tuple_train, returns_cmp=True, only_info=True)
买入后卖出的交易数量:196
胜率:59.6939%
平均获利期望:18.6899%
平均亏损期望:-7.1235%
盈亏比:4.4972
所有交易收益比例和:16.2396 
所有交易总盈亏和:2717948.4900 

1. 从不同视角训练新的主裁

如下示例编写如何从不同视角组成裁判AbuUmpMainMul,其关心的视角为短线21天趋势角度,长线一年的价格rank,长线波动,以及atr波动如下所示:

class AbuUmpMainMul(AbuUmpMainBase, BuyUmpMixin):
    """从不同视角训练新的主裁示例,AbuUmpMainBase子类,混入BuyUmpMixin,做为买入ump类"""

    class UmpMulFiter(AbuMLPd):
        @ump.ump_main_make_xy
        def make_xy(self, **kwarg):
            # regex='result|buy_deg_ang21|buy_price_rank252|buy_wave_score3|buy_atr_std'
            regex = 'result|{}|{}|{}|{}'.format(feature.AbuFeatureDeg().get_feature_ump_keys(ump_cls=AbuUmpMainMul)[-1],
                                                feature.AbuFeaturePrice().get_feature_ump_keys(ump_cls=AbuUmpMainMul)[-1],
                                                feature.AbuFeatureWave().get_feature_ump_keys(ump_cls=AbuUmpMainMul)[-1],
                                                feature.AbuFeatureAtr().get_feature_ump_keys(ump_cls=AbuUmpMainMul)[-1])
            # noinspection PyUnresolvedReferences
            mul_df = self.order_has_ret.filter(regex=regex)
            return mul_df

    def get_predict_col(self):
        """
        主裁单混特征keys:['buy_deg_ang21', 'buy_price_rank252', 'buy_wave_score3', 'buy_atr_std']
        :return: ['buy_deg_ang21', 'buy_price_rank252', 'buy_wave_score3', 'buy_atr_std']
        """

        return [feature.AbuFeatureDeg().get_feature_ump_keys(ump_cls=AbuUmpMainMul)[-1],
                feature.AbuFeaturePrice().get_feature_ump_keys(ump_cls=AbuUmpMainMul)[-1],
                feature.AbuFeatureWave().get_feature_ump_keys(ump_cls=AbuUmpMainMul)[-1],
                feature.AbuFeatureAtr().get_feature_ump_keys(ump_cls=AbuUmpMainMul)[-1]]

    def get_fiter_class(self):
        """
        主裁单混特征返回的AbuMLPd子类:AbuUmpMainMul.UmpMulFiter
        :return: AbuUmpMainMul.UmpMulFiter
        """
        return AbuUmpMainMul.UmpMulFiter

    @classmethod
    def class_unique_id(cls):
        """
        具体ump类关键字唯一名称,类方法:return 'mul_main'
        主要针对外部user设置自定义ump使用, 需要user自己保证class_unique_id的唯一性,内部不做检测
        具体使用见ABuUmpManager中extend_ump_block方法
        """
        return 'mul_main'

如上所示,即完成一个全新ump主裁的编写:

  1. ump主裁需要继承AbuUmpMainBase,买入ump需要混入BuyUmpMixin
  2. 编写内部类继承自AbuMLPd,实现make_xy,即从训练集数据中筛选自己关心的特征
  3. 实现get_predict_col,返回关心的特征字符串名称
  4. 实现get_fiter_class,返回继承自AbuMLPd的内部类
  5. 实现class_unique_id,为裁判起一个唯一的名称

备注:feature.AbuFeatureDeg()等为abupy中内置的特征类,稍后会讲解自定义特征类

现在有了新的裁判AbuUmpMainMul,接下使用相同的训练集开始训练裁判,和第16节一样使用ump_main_clf_dump:

ump_mul = AbuUmpMainMul.ump_main_clf_dump(orders_pd_train, p_ncs=slice(20, 40, 1))
ump_mul.fiter.df.head()
please wait! dump_pickle....: /Users/Bailey/abu/data/ump/ump_main_umpmulfiter

显示的特征为四个特征即为新的主裁AbuUmpMainMul所关心的决策视角和行为。

下面示例如何使用自定义裁判,如下所示:

# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 把新的裁判AbuUmpMainMul类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpMainMul)

即添加新的裁到系统中流程为:

  1. 打开使用用户自定义裁判开关:ump.manager.g_enable_user_ump = True
  2. 把新的裁判AbuUmpMainMul类名称使用append_user_ump添加到系统中,或者直接将上面训练好的对象ump_mul添加也可以

备注:使用append_user_ump添加的裁判参数可以是类名称,也可以是类对象,但裁判必须是使用ump_main_clf_dump训练好的。

下面使用新的裁判AbuUmpMainMul对测试集交易进行回测,如下:

abu_result_tuple_test_ump_main_user, _ = abu.run_loop_back(read_cash,
                                                   buy_factors,
                                                   sell_factors,
                                                   start='2014-07-26',
                                                   end='2016-07-26',
                                                   choice_symbols=test_choice_symbols)

AbuMetricsBase.show_general(*abu_result_tuple_test_ump_main_user, returns_cmp=True, only_info=True)                                                 
买入后卖出的交易数量:216
胜率:41.6667%
平均获利期望:9.2565%
平均亏损期望:-5.0211%
盈亏比:1.2766
所有交易收益比例和:2.0042 
所有交易总盈亏和:281522.2700 

使用测试集不使用任何主裁拦截情况下进行回测度量对比,如下所示:

# 关闭用户自定义裁判开关
ump.manager.g_enable_user_ump = False
abu_result_tuple_test, _ = abu.run_loop_back(read_cash,
                                                   buy_factors,
                                                   sell_factors,
                                                   start='2014-07-26',
                                                   end='2016-07-26',
                                                   choice_symbols=test_choice_symbols)

AbuMetricsBase.show_general(*abu_result_tuple_test, returns_cmp=True, only_info=True)
买入后卖出的交易数量:247
胜率:41.2955%
平均获利期望:9.7208%
平均亏损期望:-4.8754%
盈亏比:1.3725
所有交易收益比例和:2.8459 
所有交易总盈亏和:428259.7700 

可以看到使用新的裁判胜率和盈亏比都稍微有提高,可以再加上几个内置裁判一起决策,如下示例:

# 开启内置跳空主裁
abupy.env.g_enable_ump_main_jump_block = True
# 开启内置价格主裁
abupy.env.g_enable_ump_main_price_block = True

# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 把新的裁判AbuUmpMainMul类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpMainMul)

abu_result_tuple_test_ump_builtin_and_user, _ = abu.run_loop_back(read_cash,
                                                                   buy_factors,
                                                                   sell_factors,
                                                                   start='2014-07-26',
                                                                   end='2016-07-26',
                                                                   choice_symbols=test_choice_symbols)

AbuMetricsBase.show_general(*abu_result_tuple_test_ump_builtin_and_user, returns_cmp=True, only_info=True)
买入后卖出的交易数量:112
胜率:44.6429%
平均获利期望:11.8156%
平均亏损期望:-4.8241%
盈亏比:1.8417
所有交易收益比例和:2.9169 
所有交易总盈亏和:397637.2700 

2. 从不同视角训练新的边裁

和主裁类似,如下示例编写如何从不同视角组成边裁AbuUmpMainMul,其关心的视角为短线21天趋势角度,长线一年的价格rank,长线波动,以及atr波动如下所示:

class AbuUmpEdgeMul(AbuUmpEdgeBase, BuyUmpMixin):
    """从不同视角训练新的边裁示例,AbuUmpEdgeBase子类,混入BuyUmpMixin,做为买入ump类"""

    class UmpMulFiter(AbuMLPd):
        @ump.ump_edge_make_xy
        def make_xy(self, **kwarg):
            filter_list = ['profit', 'profit_cg']
            # ['profit', 'profit_cg', 'buy_deg_ang21', 'buy_price_rank252', 'buy_wave_score3', 'buy_atr_std']
            filter_list.extend(
                [feature.AbuFeatureDeg().get_feature_ump_keys(ump_cls=AbuUmpEdgeMul)[-1],
                 feature.AbuFeaturePrice().get_feature_ump_keys(ump_cls=AbuUmpEdgeMul)[-1],
                 feature.AbuFeatureWave().get_feature_ump_keys(ump_cls=AbuUmpEdgeMul)[-1],
                 feature.AbuFeatureAtr().get_feature_ump_keys(ump_cls=AbuUmpEdgeMul)[-1]])
            mul_df = self.order_has_ret.filter(filter_list)
            return mul_df

    def get_predict_col(self):
        """
        边裁单混特征keys:['buy_deg_ang21', 'buy_price_rank252', 'buy_wave_score3', 'buy_atr_std']
        :return: ['buy_deg_ang21', 'buy_price_rank252', 'buy_wave_score3', 'buy_atr_std']
        """

        return [feature.AbuFeatureDeg().get_feature_ump_keys(ump_cls=AbuUmpEdgeMul)[-1],
                feature.AbuFeaturePrice().get_feature_ump_keys(ump_cls=AbuUmpEdgeMul)[-1],
                feature.AbuFeatureWave().get_feature_ump_keys(ump_cls=AbuUmpEdgeMul)[-1],
                feature.AbuFeatureAtr().get_feature_ump_keys(ump_cls=AbuUmpEdgeMul)[-1]]

    def get_fiter_class(self):
        """
        边裁单混特征返回的AbuMLPd子类:AbuUmpEdgeMul.UmpMulFiter
        :return: AbuUmpEdgeMul.UmpMulFiter
        """
        return AbuUmpEdgeMul.UmpMulFiter

    @classmethod
    def class_unique_id(cls):
        """
         具体ump类关键字唯一名称,类方法:return 'mul_edge'
         主要针对外部user设置自定义ump使用, 需要user自己保证class_unique_id的唯一性,内部不做检测
         具体使用见ABuUmpManager中extend_ump_block方法
        """
        return 'mul_edge'

如上所示,即完成一个全新ump边裁的编写,与主裁的实现非常类似:

  1. ump边裁需要继承AbuUmpEdgeBase,买入ump需要混入BuyUmpMixin
  2. 编写内部类继承自AbuMLPd,实现make_xy,即从训练集数据中筛选自己关心的特征
  3. 实现get_predict_col,返回关心的特征字符串名称
  4. 实现get_fiter_class,返回继承自AbuMLPd的内部类
  5. 实现class_unique_id,为裁判起一个唯一的名称

备注:feature.AbuFeatureDeg()等为abupy中内置的特征类,稍后会讲解自定义特征类

现在有了新的边裁AbuUmpEdgeMul,接下使用相同的训练集开始训练裁判,和第17节一样使用ump_edge_clf_dump:

edge_mul = AbuUmpEdgeMul.ump_edge_clf_dump(orders_pd_train)
edge_mul.fiter.df.head()
please wait! dump_pickle....: /Users/Bailey/abu/data/ump/ump_edge_umpmulfiter

显示的特征为新的边裁AbuUmpEdgeMul所关心的决策视角和行为。

下面将新的边裁添加到系统中流程为:

  1. 打开使用用户自定义裁判开关:ump.manager.g_enable_user_ump = True
  2. 把新的裁判AbuUmpEdgeMul类名称使用append_user_ump添加到系统中,或者直接将上面训练好的对象edge_mul添加也可以

流程和主裁一致,这里使用ump.manager.clear_user_ump()先把自定义裁判清空一下,即将上面添加到系统中自定义主裁清除。

备注:使用append_user_ump添加的裁判参数可以是类名称,也可以是类对象,但边裁必须是使用ump_edge_clf_dump训练好的。

# 清空用户自定义的裁判
ump.manager.clear_user_ump()

# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 把新的裁判AbuUmpEdgeMul类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpEdgeMul)
abu_result_tuple_test_ump_user_edge, _ = abu.run_loop_back(read_cash,
                                                   buy_factors,
                                                   sell_factors,
                                                   start='2014-07-26',
                                                   end='2016-07-26',
                                                   choice_symbols=test_choice_symbols)

AbuMetricsBase.show_general(*abu_result_tuple_test_ump_user_edge, returns_cmp=True, only_info=True)
买入后卖出的交易数量:109
胜率:44.0367%
平均获利期望:9.4283%
平均亏损期望:-4.5710%
盈亏比:1.5630
所有交易收益比例和:1.7373 
所有交易总盈亏和:252098.5300 

可以看到使用新的边裁胜率和盈亏比并不太理想,可以再加上几个内置边裁一起决策,如下示例:

# 开启内置价格边裁
abupy.env.g_enable_ump_edge_price_block = True
# 开启内置波动边裁
abupy.env.g_enable_ump_edge_wave_block = True

# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 把新的裁判AbuUmpEdgeMul类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpEdgeMul)

abu_result_tuple_test_ump_builtin_and_user_edge, _ = abu.run_loop_back(read_cash,
                                                                       buy_factors,
                                                                       sell_factors,
                                                                       start='2014-07-26',
                                                                       end='2016-07-26',
                                                                       choice_symbols=test_choice_symbols)

AbuMetricsBase.show_general(*abu_result_tuple_test_ump_builtin_and_user_edge, returns_cmp=True, only_info=True)
买入后卖出的交易数量:66
胜率:56.0606%
平均获利期望:10.3395%
平均亏损期望:-4.5154%
盈亏比:2.6907
所有交易收益比例和:2.5161 
所有交易总盈亏和:357671.0300 

上面的完成的裁判都是使用abupy内置的特征类,如果希望能裁判能够从一些新的视角或者行为来进行决策,那么就需要添加新的视角来录制比赛(回测交易),下面的内容将示例讲自定义新的特征类(新的视角),自定义裁判使用这些新的特征类进行训练:

3. 添加新的视角来录制比赛(记录回测特征)

如下示例如何添加新的视角来录制比赛,编写AbuFeatureDegExtend,其与内置的角度主裁使用的特征很像,也是录制买入,卖出时的拟合角度特征 主裁角度记录21,42,60,252日走势拟合角度,本示例记录10,30,50,90,120日走势拟合角度特征,如下所示:

class AbuFeatureDegExtend(AbuFeatureBase, BuyFeatureMixin, SellFeatureMixin):
    """示例添加新的视角来录制比赛,角度特征,支持买入,卖出"""

    def __init__(self):
        """20, 40, 60, 90, 120日走势角度特征"""
        # frozenset包一下,一旦定下来就不能修改,否则特征对不上
        self.deg_keys = frozenset([10, 30, 50, 90, 120])

    def get_feature_keys(self, buy_feature):
        """
        迭代生成所有走势角度特征feature的列名称定, 使用feature_prefix区分买入,卖出前缀key
        :param buy_feature: 是否是买入特征构造(bool)
        :return: 角度特征的键值对字典中的key序列
        """
        return ['{}deg_ang{}'.format(self.feature_prefix(buy_feature=buy_feature), dk) for dk in self.deg_keys]

    def calc_feature(self, kl_pd, combine_kl_pd, day_ind, buy_feature):
        """
        根据买入或者卖出时的金融时间序列,以及交易日信息构造拟合角度特征
        :param kl_pd: 择时阶段金融时间序列
        :param combine_kl_pd: 合并择时阶段之前1年的金融时间序列
        :param day_ind: 交易发生的时间索引,即对应self.kl_pd.key
        :param buy_feature: 是否是买入特征构造(bool)
        :return: 构造角度特征的键值对字典
        """
        # 返回的角度特征键值对字典
        deg_dict = {}
        for dk in self.deg_keys:
            # 迭代预设角度周期,计算构建特征
            if day_ind - dk >= 0:
                # 如果择时时间序列够提取特征,使用kl_pd截取特征交易周期收盘价格
                deg_close = kl_pd[day_ind - dk + 1:day_ind + 1].close
            else:
                # 如果择时时间序列不够提取特征,使用combine_kl_pd截取特征交易周期,首先截取直到day_ind的时间序列
                combine_kl_pd = combine_kl_pd.loc[:kl_pd.index[day_ind]]
                # 如combine_kl_pd长度大于特征周期长度-> 截取combine_kl_pd[-dk:].close,否则取combine_kl_pd所有交易收盘价格
                deg_close = combine_kl_pd[-dk:].close if combine_kl_pd.shape[0] > dk else combine_kl_pd.close

            # 使用截取特征交易周期收盘价格deg_close做为参数,通过calc_regress_deg计算趋势拟合角度
            ang = ABuRegUtil.calc_regress_deg(deg_close, show=False)
            # 标准化拟合角度值
            ang = 0 if np.isnan(ang) else round(ang, 3)
            # 角度特征键值对字典添加拟合角度周期key和对应的拟合角度值
            deg_dict['{}deg_ang{}'.format(self.feature_prefix(buy_feature=buy_feature), dk)] = ang
        return deg_dict

如上所示,即添加完成一个新的视角来录制比赛(回测交易),即用户自定义特征类:

  1. 特征类需要继承AbuFeatureBase,支持买入特征混入BuyFeatureMixin,支持卖出特征混入SellFeatureMixin,本例都支持,都混入
  2. 需要实现get_feature_keys,返回自定义特征列名称
  3. 需要实现calc_feature,根据参数中的金融时间数据计算具体的特征值

备注:更多特征类的编写示例请阅读ABuMLFeature中相关源代码

现在有了新的特征类AbuFeatureDegExtend,首先需要使用feature.append_user_feature将新的特征加入到系统中:

feature.append_user_feature(AbuFeatureDegExtend)

现在新的特征类已经在系统中了,使用第15节回测的相同设置进行回测,如下所示:

# 关闭内置跳空主裁
abupy.env.g_enable_ump_main_jump_block = False
# 关闭内置价格主裁
abupy.env.g_enable_ump_main_price_block = False
# 关闭内置角度主裁
abupy.env.g_enable_ump_main_deg_block = False
# 关闭内置波动主裁
abupy.env.g_enable_ump_main_wave_block = False

# 关闭内置价格边裁
abupy.env.g_enable_ump_edge_price_block = False
# 关闭内置波动边裁
abupy.env.g_enable_ump_edge_wave_block = False
# 关闭内置角度边裁
abupy.env.g_enable_ump_edge_deg_block = False
# 关闭内置综合边裁
abupy.env.g_enable_ump_edge_full_block = False

# 关闭用户自定义裁判开关
ump.manager.g_enable_user_ump = False

abu_result_tuple_train_deg_extend, _ = abu.run_loop_back(read_cash,
                                                       buy_factors,
                                                       sell_factors,
                                                       start='2014-07-26',
                                                       end='2016-07-26',
                                                       choice_symbols=train_choice_symbols)
ABuProgress.clear_output()
orders_pd_train_deg_extend = abu_result_tuple_train_deg_extend.orders_pd
AbuMetricsBase.show_general(*abu_result_tuple_train_deg_extend, returns_cmp=True ,only_info=True)
买入后卖出的交易数量:196
胜率:59.6939%
平均获利期望:18.6899%
平均亏损期望:-7.1235%
盈亏比:4.4972
所有交易收益比例和:16.2396 
所有交易总盈亏和:2717948.4900 

可以发现回测的度量结果和之前是一摸一样的,不同点在于orders_pd_train_deg_extend中有了新的特征,如下筛选出所有拟合角特征:

orders_pd_train_deg_extend.filter(regex='buy_*deg').head()

可以看到除了之前主裁使用的拟合角度21,42,60,252,外还增加了10,30,50,90,120日拟合角度特征值,下面把AbuFeatureDegExtend的特征都筛选出来看看:

orders_pd_train_deg_extend.filter(AbuFeatureDegExtend().get_feature_keys(True) +
                                  AbuFeatureDegExtend().get_feature_keys(False)).head()

可以看到由于AbuFeatureDegExtend混入了BuyFeatureMixin和SellFeatureMixin,所以同时生成了买入趋势角度特征和卖出趋势角度特征,买入特征就是在之前的章节中主裁和边裁使用的特征,之前的章节讲解的都是根据买入特征进行决策拦截,没有涉及过针对卖出的交易进行决策拦截的示例,在之后的章节中会完整示例,请关注公众号的更新提醒。

4. 主裁使用新的视角来决策交易

下面开始编写主裁使用AbuFeatureDegExtend:

class AbuUmpMainDegExtend(AbuUmpMainBase, BuyUmpMixin):
    """主裁使用新的视角来决策交易,AbuUmpMainBase子类,混入BuyUmpMixin,做为买入ump类"""

    class UmpExtendFeatureFiter(AbuMLPd):
        @ump.ump_main_make_xy
        def make_xy(self, **kwarg):
            # 这里使用get_feature_ump_keys,只需要传递当前类名称即可,其根据是买入ump还是卖出ump返回对应特征列
            col = AbuFeatureDegExtend().get_feature_ump_keys(ump_cls=AbuUmpMainDegExtend)
            regex = 'result|{}'.format('|'.join(col))
            extend_deg_df = self.order_has_ret.filter(regex=regex)
            return extend_deg_df

    def get_predict_col(self):
        # 这里使用get_feature_ump_keys,只需要传递当前类名称即可,其根据是买入ump还是卖出ump返回对应特征列
        col = AbuFeatureDegExtend().get_feature_ump_keys(ump_cls=AbuUmpMainDegExtend)
        return col

    def get_fiter_class(self):
        return AbuUmpMainDegExtend.UmpExtendFeatureFiter

    @classmethod
    def class_unique_id(cls):
        return 'extend_main_deg'

AbuUmpMainDegExtend的编写与之前类似,接下来使用AbuUmpMainDegExtend进行测试集回测,仍然不要忘记要先训练裁判,然后使用append_user_ump添加到系统中:

# 首先训练新裁判AbuUmpMainDegExtend,注意这里训练要使用orders_pd_train_deg_extend,不能用之前的orders_pd_train,否则没有特征列
ump_deg_extend = AbuUmpMainDegExtend.ump_main_clf_dump(orders_pd_train_deg_extend, p_ncs=slice(20, 40, 1))
# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 先clear一下
ump.manager.clear_user_ump()
# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpMainDegExtend)

ump_deg_extend.fiter.df.head()
please wait! dump_pickle....: /Users/Bailey/abu/data/ump/ump_main_umpextendfeaturefiter

abu_result_tuple_test_ump_extend_deg, _ = abu.run_loop_back(read_cash,
                                                               buy_factors,
                                                               sell_factors,
                                                               start='2014-07-26',
                                                               end='2016-07-26',
                                                               choice_symbols=test_choice_symbols)
ABuProgress.clear_output()
AbuMetricsBase.show_general(*abu_result_tuple_test_ump_extend_deg, returns_cmp=True ,only_info=True)
买入后卖出的交易数量:232
胜率:42.2414%
平均获利期望:9.3664%
平均亏损期望:-4.8751%
盈亏比:1.3626
所有交易收益比例和:2.6464 
所有交易总盈亏和:382564.7700 
proxy = AbuOrderPdProxy(abu_result_tuple_test.orders_pd)
with proxy.proxy_work(abu_result_tuple_test_ump_extend_deg.orders_pd) as (order1, order2):
     block_order = order1 - order2
print('正确拦截失败的交易数量{}, 错误拦截的交易数量{}'.format(block_order.result.value_counts()[-1], block_order.result.value_counts()[1]))
正确拦截失败的交易数量11, 错误拦截的交易数量4

如上所示拦截了15笔交易,11笔正确,拦截正确率比较高,达到73%正确。

5. 边裁使用新的视角来决策交易

下面开始编写边裁使用AbuFeatureDegExtend:

class AbuUmpEegeDegExtend(AbuUmpEdgeBase, BuyUmpMixin):
    """边裁使用新的视角来决策交易,AbuUmpEdgeBase子类,混入BuyUmpMixin,做为买入ump类"""

    class UmpExtendEdgeFiter(AbuMLPd):
        @ump.ump_edge_make_xy
        def make_xy(self, **kwarg):
            filter_list = ['profit', 'profit_cg']
            col = AbuFeatureDegExtend().get_feature_ump_keys(ump_cls=AbuUmpEegeDegExtend)
            filter_list.extend(col)
            mul_df = self.order_has_ret.filter(filter_list)
            return mul_df

    def get_predict_col(self):
        # 这里使用get_feature_ump_keys,只需要传递当前类名称即可,其根据是买入ump还是卖出ump返回对应特征列
        col = AbuFeatureDegExtend().get_feature_ump_keys(ump_cls=AbuUmpEegeDegExtend)
        return col

    def get_fiter_class(self):
        return AbuUmpEegeDegExtend.UmpExtendEdgeFiter

    @classmethod
    def class_unique_id(cls):
        return 'extend_edge_deg'

# 通过import的方式导入AbuUmpEegeDegExtend, 因为在windows系统上,启动并行后,在ipython notebook中定义的类会在子进程中无法找到
from abupy import AbuUmpEegeDegExtend

AbuUmpEegeDegExtend的编写与之前类似,接下来使用AbuUmpEegeDegExtend进行测试集回测,仍然不要忘记要先训练裁判,然后使用append_user_ump添加到系统中:

# 首先训练新裁判AbuUmpMainDegExtend,注意这里训练要使用orders_pd_train_deg_extend,不能用之前的orders_pd_train,否则没有特征列
ump_deg_edge_extend = AbuUmpEegeDegExtend.ump_edge_clf_dump(orders_pd_train_deg_extend)
# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 先clear一下
ump.manager.clear_user_ump()
# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpEegeDegExtend)

ump_deg_edge_extend.fiter.df.head()
please wait! dump_pickle....: /Users/Bailey/abu/data/ump/ump_edge_umpextendedgefiter

abu_result_tuple_test_ump_edge_extend_deg, _ = abu.run_loop_back(read_cash,
                                                               buy_factors,
                                                               sell_factors,
                                                               start='2014-07-26',
                                                               end='2016-07-26',
                                                               choice_symbols=test_choice_symbols)

AbuMetricsBase.show_general(*abu_result_tuple_test_ump_edge_extend_deg, returns_cmp=True ,only_info=True)
买入后卖出的交易数量:235
胜率:42.1277%
平均获利期望:9.5267%
平均亏损期望:-4.8764%
盈亏比:1.3821
所有交易收益比例和:2.7995 
所有交易总盈亏和:410764.7700 
proxy = AbuOrderPdProxy(abu_result_tuple_test.orders_pd)
with proxy.proxy_work(abu_result_tuple_test_ump_extend_deg.orders_pd) as (order1, order2):
     block_order = order1 - order2
print('正确拦截失败的交易数量{}, 错误拦截的交易数量{}'.format(block_order.result.value_counts()[-1], block_order.result.value_counts()[1]))
正确拦截失败的交易数量9, 错误拦截的交易数量3

如上所示拦截了12笔交易,9笔正确,拦截正确率比较高,达到75%正确。

最后使用新编写的主裁趋势角度扩展类,边裁趋势角度扩展类,和内置的主裁角度,内置的边裁角度共同决进行回测:

# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 先clear一下
ump.manager.clear_user_ump()

# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpEegeDegExtend)
# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpMainDegExtend)

# 打开内置角度边裁
abupy.env.g_enable_ump_edge_deg_block = True
# 打开内置角度主裁
abupy.env.g_enable_ump_main_deg_block = True
abu_result_tuple_test_ump_end, _ = abu.run_loop_back(read_cash,
                                                               buy_factors,
                                                               sell_factors,
                                                               start='2014-07-26',
                                                               end='2016-07-26',
                                                               choice_symbols=test_choice_symbols)
ABuProgress.clear_output()
AbuMetricsBase.show_general(*abu_result_tuple_test_ump_end, returns_cmp=True ,only_info=True)
买入后卖出的交易数量:192
胜率:42.7083%
平均获利期望:9.4539%
平均亏损期望:-4.8478%
盈亏比:1.3774
所有交易收益比例和:2.4196 
所有交易总盈亏和:325569.7700 

小结:

abupy中ump模块的设计目标是:

  1. 不需要在具体策略中硬编码
  2. 不需要人工设定阀值,即且使得代码逻辑清晰
  3. 分离基础策略和策略优化监督模块,提高灵活度和适配性
  4. 发现策略中隐藏的交易策略问题
  5. 可以通过不断的学习新的交易数据

ump的使用和在‘第九节 港股市场的回测’中使用将优化策略的’策略’做为类装饰器进行封装的目的都是:分离基础策略和策略优化监督模块,提高灵活度和适配性, 基础策略追求的就应该是简单, 可以一句话说明你的基础策略

现阶段的量化策略还是通过人来编写代码,未来的发展也许会向着完全由计算机实现整套流程的方向迈进,包括量化策略本身。

abupy的设计目标是:

只需要提供一些基础的简单种子策略代码,计算机在这些简单种子策略基础上不断自我学习、自我完善,创造新的策略,并且紧跟时间序列不断自我调整策略参数。

abu量化文档目录章节

  1. 择时策略的开发
  2. 择时策略的优化
  3. 滑点策略与交易手续费
  4. 多支股票择时回测与仓位管理
  5. 选股策略的开发
  6. 回测结果的度量
  7. 寻找策略最优参数和评分
  8. A股市场的回测
  9. 港股市场的回测
  10. 比特币,莱特币的回测
  11. 期货市场的回测
  12. 机器学习与比特币示例
  13. 量化技术分析应用
  14. 量化相关性分析应用
  15. 量化交易和搜索引擎
  16. UMP主裁交易决策
  17. UMP边裁交易决策
  18. 自定义裁判决策交易
  19. 数据源
  20. A股全市场回测
  21. A股UMP决策
  22. 美股全市场回测
  23. 美股UMP决策

abu量化系统文档教程持续更新中,请关注公众号中的更新提醒。

更多阿布量化量化技术文章

更多关于量化交易相关请阅读《量化交易之路》

更多关于量化交易与机器学习相关请阅读《机器学习之路》

更多关于abu量化系统请关注微信公众号: abu_quant

发表评论

电子邮件地址不会被公开。 必填项已用*标注