阿布量化界面操作视频教程 第一节 量化交易

第30节 趋势跟踪与均值回复的长短线搭配
2017年10月25日
第31节 资金仓位管理与买入策略的搭配
2017年11月8日

第1-2节 择时策略的开发与优化

作者: 阿布

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

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

本节ipython notebook

本节界面操作教程视频播放地址

量化系统一般分为回测模块、实盘模块。

  • 回测模块:首先交易者编写实现一个交易策略,它基于一段历史的交易数据,根据交易策略进行模拟买入卖出,策略中可以涉及买入规则、卖出规则、选股规则、仓位控制及滑点策略等等,回测的目的是验证交易策略是否可行。
  • 实盘模块:将回测通过的策略应用于每天的实时交易数据,根据策略发出买入信号、卖出信号,进行实际的买入、卖出操作。

回测模块最重要的组成部份是择时、选股:

  • 择时(什么时候投资)
  • 选股(投资什么股票)

只有在对的时间买入对的股票才能获利,就像下面张小娴的名言一样,可以把‘股票’ 代替 ‘人’完全合乎逻辑。

在对的时间,遇见对的人(股票),是一种幸福

在对的时间,遇见错的人(股票),是一种悲伤

在错的时间,遇见对的人(股票),是一声叹息

在错的时间,遇见错的人(股票),是一种无奈

本节首先讲解择时(什么时候投资), 后面的小节将讲解选股

1. 买入择时因子的编写

海龟交易法则是量化经典书籍中的经典作品,它里面介绍过一种趋势跟踪策略:N日趋势突破策略

趋势突破定义为当天收盘价格超过N天内的最高价或最低价,超过最高价格作为买入信号买入股票持有,超过最低价格作为卖出信号。

下面将用abupy来实现海龟交易法则作为一个买入因子的实现代码,向经典致敬:

class AbuFactorBuyBreak(AbuFactorBuyXD, BuyCallMixin):
    """示例继承AbuFactorBuyXD完成正向突破买入择时类, 混入BuyCallMixin,即向上突破触发买入event"""
    def fit_day(self, today):
        """
        针对每一个交易日拟合买入交易策略,寻找向上突破买入机会
        :param today: 当前驱动的交易日金融时间序列数据
        :return:
        """
        # 今天的收盘价格达到xd天内最高价格则符合买入条件
        if today.close == self.xd_kl.close.max():
            # 生成买入订单, 由于使用了今天的收盘价格做为策略信号判断,所以信号发出后,只能明天买
            return self.buy_tomorrow()
        return None

上AbuFactorBuyBreak即是完成了海龟突破策略的代码实现:

  1. 买入因子需要继承AbuFactorBuyXD或者更复杂的策略继承AbuFactorBuyBase
  2. 买入因子混入BuyCallMixin,即做为正向策略,股票相关的策略全部是正向策略,即买涨,后续章节示例期货,期权会使用BuyPutMixin
  3. 买入因子需要实现fit_day,即每一个交易日如何执行交易策略,当符合买入条件后,使用buy_tomorrow或者buy_today生成订单

更多买入因子实现代码请阅读AbuFactorBuyBase

2. 分解模式一步一步对策略进行回测

本节首先通过分解流程方式一步一步实现使用AbuFactorBuyBreak进行回测,目的是为了更清晰的说明内部操作流程,
编码过程会显的有些复杂臃肿,但实际上在编写完成一个策略后只需要使用一行代码即可以完成回测,在后面的小节中会进行讲解。

通过字典形式初始化买入buy_factors,首先实现针对一支股票的择时操作:

  • benchmark的意义为基准参考,基准默认使用回测股票对应市场的大盘指数
  • 默认参数下回测过去两年的交易数据,传递AbuBenchmark(n_folds=2)参数修改回测周期
  • AbuCapital为资金主类,参数需要初始资金设定,这里初始设定1000000(100万),另一个参数为刚刚介绍过的benchmark(基准参考)对象
  • buy_factors由两个买入因子组成,进行择时的时候两个因子同时并行生效
# buy_factors 60日向上突破,42日向上突破两个因子
buy_factors = [{'xd': 60, 'class': AbuFactorBuyBreak}, 
               {'xd': 42, 'class': AbuFactorBuyBreak}]
benchmark = AbuBenchmark()
capital = AbuCapital(1000000, benchmark)

择时ABuPickTimeExecute主要驱动方式为时间驱动,即通过时间序列一天一天递进,通过买入因子卖出因子的fit来查询是否有事件生成(买入卖出行为),另外也有框架使用事件驱动,它们分别有各自的优点,原始的abu框架就是时间驱动+事件驱动的,它最大的优点是执行效率比时间驱动高,但是灵活性及扩展性要比时间驱动差。

下面使用ABuPickTimeExecute开始进行择时交易回测,ABuPickTimeExecute实际上不是最简洁的回测接口,更简单的接口可以使用abu.run_loop_back()函数,在后面的章节将会示例使用,本节目的是为了更清晰的说明内部操作流程。

由回测结果图可看出由于AbuPickTimeWorker没有设置sell_factors,所以所有的交易单子都一直保留没有卖出:

  • orders_pd:所有交易的相关数据(之后会有内容展示)
  • action_pd:所有交易的行为数据(之后会有内容展示)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(['usTSLA'],
                                                                            benchmark,
                                                                            buy_factors,
                                                                            None,
                                                                            capital, show=True)

png

3. 卖出择时因子的实现

上面所有单子都没有成交的原因是没有卖出因子,下面首先实现类似买入策略的N日趋势突破策略AbuFactorSellBreak,当股价向下突破N日最低价格时卖出股票,即当天收盘价格低于N天内最低价格作为卖出信号,认为下跌趋势成立卖出股票:

class AbuFactorSellBreak(AbuFactorSellXD):
    """示例继承AbuFactorBuyXD, 向下突破卖出择时因子"""
    def support_direction(self):
        """支持的方向,只支持正向"""
        return [ESupportDirection.DIRECTION_CAll.value]

    def fit_day(self, today, orders):
        """
        寻找向下突破作为策略卖出驱动event
        :param today: 当前驱动的交易日金融时间序列数据
        :param orders: 买入择时策略中生成的订单序列
        """
        # 今天的收盘价格达到xd天内最低价格则符合条件
        if today.close == self.xd_kl.close.min():
            for order in orders:
                self.sell_tomorrow(order)

上AbuFactorSellBreak即是完成了卖出突破策略的代码实现:

  1. 卖出因子需要继承AbuFactorSellXD或者更复杂的策略继承AbuFactorSellBase
  2. 卖出因子需要实现support_direction方法,确定策略支持的买入策略方向,本例中[ESupportDirection.DIRECTION_CAll.value]即只支持正向买入策略,即买涨
  3. 卖出因子需要实现fit_day,看有没有符合卖出条件的交易单子

更多具体卖出因子实现代码请阅读AbuFactorSellBase

备注:之后章节的期货示例讲讲解如何使用ESupportDirection做反向交易,buy put

4. 买入因子和卖出因子在回测中同时生效

同理使用字典组装卖出因子:

# 使用120天向下突破为卖出信号
sell_factor1 = {'xd': 120, 'class': AbuFactorSellBreak}

# buy_factors 60日向上突破,42日向上突破两个因子
buy_factors = [{'xd': 60, 'class': AbuFactorBuyBreak}, 
               {'xd': 42, 'class': AbuFactorBuyBreak}]

# 只使用120天向下突破为卖出因子
sell_factors = [sell_factor1]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(['usTSLA'],
                                                                            benchmark,
                                                                            buy_factors,
                                                                            sell_factors,
                                                                            capital, show=True)

png

从上图可以看到,大多数的交易卖出因子都生效了,但效果很不好, 下将继续通过增加多个卖出因子同时作用于策略上来提高策略的效果。

5. 基本止盈止损策略

上策略大多数的交易卖出因子都生效了,但效果很不好,量化交易系统一般都会有止盈策略和止损策略。

下面使用abupy中内置的基本止盈止损策略AbuFactorAtrNStop做回测,即使用AbuFactorAtrNStop和AbuFactorSellBreak两个卖出因子策略并行同时生效, 交易结果如下所示

备注:

AbuFactorAtrNStop是真实波幅atr作为最大止盈和最大止损的常数值:

  • 当stop_loss_n 乘以 当日atr > 买入价格 - 当日收盘价格:止损卖出,如下止损n = 0.5
  • 当stop_win_n 乘以 当日atr < 当日收盘价格 -买入价格:止盈卖出,如下止盈n = 3.0

更多详情请阅读abupy中AbuFactorAtrNStop代码实现

from abupy import AbuFactorAtrNStop
from abupy import ABuPickTimeExecute, AbuBenchmark, AbuCapital

# 趋势跟踪策略止盈要大于止损设置值,这里0.5,3.0
sell_factor2 = {'stop_loss_n': 0.5, 'stop_win_n': 3.0,
                'class': AbuFactorAtrNStop}

# 两个卖出因子策略并行同时生效
sell_factors = [sell_factor1, sell_factor2]
benchmark = AbuBenchmark()
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(['usTSLA'],
                                                                            benchmark,
                                                                            buy_factors,
                                                                            sell_factors,
                                                                            capital, show=True)

6. 风险控制止损策略

可以看到效果比之前好多了,下面再加入一些其它卖出策略,量化交易系统中一般都会有风险控制策略,比如当股票今天价格开始剧烈下跌,采取果断平仓措施。

可以使用abupy中内置的风险控制止损策略AbuFactorPreAtrNStop

  • 策略中继续使用真实波幅atr作为常数值: 当今日价格下跌幅度 > 当日atr 乘以 pre_atr_n(下跌止损倍数)卖出股票, 本例使用pre_atr_n=1.0

更多详情请阅读abupy中AbuFactorPreAtrNStop代码实现

sell_factors中加入AbuFactorPreAtrNStop卖出因子,三个卖出因子策略并行同时生效:

from abupy import AbuFactorPreAtrNStop

# 暴跌止损卖出因子形成dict
sell_factor3 = {'class': AbuFactorPreAtrNStop, 'pre_atr_n': 1.0}
# 三个卖出因子同时生效,组成sell_factors
sell_factors = [sell_factor1, sell_factor2, sell_factor3]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(['usTSLA'],
                                                                            benchmark,
                                                                            buy_factors,
                                                                            sell_factors,
                                                                            capital,
                                                                            show=True)

如上所示由于使用AbuFactorPreAtrNStop,效果继续变好,有两笔交易通过AbuFactorPreAtrNStop进行卖出,阻止了进一步的交易损失:


7. 利润保护止盈策略

接下来注意下图这笔交易,读者会发现本来有很多盈利的,但是由于止盈没有达到,所以最后变成了亏损

下面通过添加abupy内置的保护盈利的卖出因子AbuFactorCloseAtrNStop来使上图那笔交易获利:

  • AbuFactorCloseAtrNStop atr移动止盈策略,当买入股票有一定收益后,如果股价下跌幅度超过close_atr_n乘以当日atr:则保护止盈卖出,如下示例使用close_atr_n=1.5

更多详情请阅读abupy中AbuFactorCloseAtrNStop代码实现

sell_factors加入AbuFactorCloseAtrNStop卖出因子,四个卖出因子策略并行同时生效

from abupy import AbuFactorCloseAtrNStop

# 保护止盈卖出因子组成dict
sell_factor4 = {'class': AbuFactorCloseAtrNStop, 'close_atr_n': 1.5}
# 四个卖出因子同时并行生效
sell_factors = [sell_factor1, sell_factor2, sell_factor3,
                sell_factor4]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(['usTSLA'],
                                                                            benchmark,
                                                                            buy_factors,
                                                                            sell_factors,
                                                                            capital,
                                                                            show=True)

png

从上图交易结果可以看到最终那笔失败的交易也盈利卖出了。

注意:

  1. 上面的很多拟合优化操作在实际应用中是不可取的,比如最后的那个使用AbuFactorCloseAtrNStop使交易盈利以及我之后即将讲解的另一些手段使整体交易变好的做法,不应该因为某些特定股票或者特定交易修改参数或者添加因子等方式使结果变好,这样就是过拟合择时交易系统,将会在下一章节来示例如何挑选参数及因子的选择问题,本节内容主要是为了讲解择时系统的示例。

  2. 读者可能注意到我在多个卖出因子,还有即将讲到的仓位控制都使用了atr,但请不要误会我不是强调atr有多重要多好,只不过是我想尽量使用一个概念来完成尽可能多的任务,不必反复引入过多的交易概念,因为篇幅有限,且容易引发阅读困难

  3. 本节只是示例卖出策略的使用,更多个性化的卖出策略可根据自己的交易买入策略与交易风格自行编写。

发表评论

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