下面通过BollChannelStrategy策略示例,来展示策略开发的具体步骤:

    定义策略参数并且初始化策略变量。策略参数为策略类的公有属性,用户可以通过创建新的实例来调用或者改变策略参数。

    如针对rb1905品种,用户可以创建基于BollChannelStrategy的策略示例,如RB_BollChannelStrategy,boll_window可以由18改成30。

    类的初始化

    初始化分3步:

    • 通过super( )的方法继承CTA策略模板,在init( )函数传入CTA引擎、策略名称、vt_symbol、参数设置。
    • 调用K线生成模块:通过时间切片来把Tick数据合成1分钟K线数据,然后更大的时间周期数据,如15分钟K线。
    • 调用K线时间序列管理模块:基于K线数据,如1分钟、15分钟,来生成相应的技术指标。
    1. def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
    2. """"""
    3. super(BollChannelStrategy, self).__init__(
    4. cta_engine, strategy_name, vt_symbol, setting
    5. )
    6.  
    7. self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar)
    8. self.am = ArrayManager()

    通过“CTA策略”组件的相关功能按钮实现。

    注意:函数load_bar(10),代表策略初始化需要载入10个交易日的历史数据。该历史数据可以是Tick数据,也可以是K线数据。

    Tick数据回报

    由于BollChannelStrategy是基于15分钟K线来生成交易信号的,故收到Tick数据后,需要用到K线生成模块里面的update_tick函数,通过时间切片的方法,聚合成1分钟K线数据,并且推送到on_bar函数。

    1. def on_tick(self, tick: TickData):
    2. """
    3. """
    4. self.bg.update_tick(tick)

    收到推送过来的1分钟K线数据后,通过K线生成模块里面的update_bar函数,以分钟切片的方法,合成15分钟K线数据,并且推送到on_15min_bar函数。

    15分钟K线数据回报

    负责CTA信号的生成,由3部分组成:

    • 清空未成交委托:为了防止之前下的单子在上一个15分钟没有成交,但是下一个15分钟可能已经调整了价格,就用cancel_all()方法立刻撤销之前未成交的所有委托,保证策略在当前这15分钟开始时的整个状态是清晰和唯一的。
    • 调用K线时间序列管理模块:基于最新的15分钟K线数据来计算相应计算指标,如布林带通道上下轨、CCI指标、ATR指标
    • 信号计算:通过持仓的判断以及结合CCI指标、布林带通道、ATR指标在通道突破点挂出停止单委托(buy/sell),同时设置离场点(short/cover)。注意:CTA策略具有低胜率和高盈亏比的特定:在难以提升胜率的情况下,研究提高策略盈亏比有利于策略盈利水平的上升。
    1. def on_15min_bar(self, bar: BarData):
    2. """"""
    3. self.cancel_all()
    4.  
    5. am = self.am
    6. am.update_bar(bar)
    7. if not am.inited:
    8. return
    9.  
    10. self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev)
    11. self.cci_value = am.cci(self.cci_window)
    12. self.atr_value = am.atr(self.atr_window)
    13.  
    14. if self.pos == 0:
    15. self.intra_trade_high = bar.high_price
    16.  
    17. if self.cci_value > 0:
    18. self.buy(self.boll_up, self.fixed_size, True)
    19. elif self.cci_value < 0:
    20. self.short(self.boll_down, self.fixed_size, True)
    21.  
    22. elif self.pos > 0:
    23. self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
    24. self.intra_trade_low = bar.low_price
    25.  
    26. self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier
    27. self.sell(self.long_stop, abs(self.pos), True)
    28.  
    29. elif self.pos < 0:
    30. self.intra_trade_high = bar.high_price
    31. self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
    32.  
    33. self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier
    34. self.cover(self.short_stop, abs(self.pos), True)
    35.