Esempio n. 1
0
class BollVix(CtaTemplate):
    """"""
    author = "yunya"

    open_window = 15
    boll_window = 80
    fixed_size = 1

    boll_mid_current = 0
    boll_mid_last = 0
    boll_up_current = 0
    boll_up_last = 0
    boll_down_current = 0
    boll_down_last = 0
    target_pos = 0
    pos_inited = 0

    parameters = [
        "open_window",
        "boll_window",
        "fixed_size",
    ]

    variables = [
        "boll_mid_current",
        "boll_mid_last",
        "boll_up_current",
        "boll_up_last",
        "boll_down_current",
        "boll_down_last",
        "pos_inited",
        "target_pos"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_minute_bar, interval=Interval.MINUTE)
        self.am = ArrayManager(self.boll_window * 2)

        self.up_array: np.ndarray = np.zeros(5)
        self.down_array: np.ndarray = np.zeros(5)
        self.boll_inited = False
        self.boll_count = 0

        self.engine_type = self.get_engine_type()
        self.vt_orderids = []
        self.order_price = 0

        self.pos_inited = 0

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(12)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")
        self.put_event()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

        # 只有实盘交易才使用BestLimit算法
        if self.engine_type != EngineType.LIVE:
            return

        #  当前没有仓位
        order_volume_open = self.target_pos - self.pos

        if not order_volume_open:
            return

        if order_volume_open > 0:
            if not self.vt_orderids:
                self.order_price = tick.bid_price_1
                vt_orderids = self.buy(self.order_price, abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.bid_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

        elif order_volume_open < 0:
            if not self.vt_orderids:
                self.order_price = tick.ask_price_1
                vt_orderids = self.short(self.order_price, abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.ask_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_minute_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        # 计算布林
        self.boll_calculate()
        if not self.boll_inited:
            return

        boll_mid_array = self.am.sma(self.boll_window, True)

        # 计算数组
        self.boll_mid = boll_mid_array[-2]
        self.boll_up_current = self.up_array[-1]
        self.boll_up_last = self.up_array[-2]
        self.boll_down_current = self.down_array[-1]
        self.boll_down_last = self.down_array[-2]

        if not self.pos:
            self.pos_inited = 0

            if self.am.close[-1] > self.boll_up_current and self.am.close[-2] <= self.boll_up_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.buy(self.boll_up_current, self.fixed_size)
                else:
                    self.target_pos = self.fixed_size
                    print("没有仓位,我开多")

            elif self.am.close[-1] < self.boll_down_current and self.am.close[-2] >= self.boll_down_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.short(self.boll_down_current, self.fixed_size)
                else:
                    self.target_pos = -self.fixed_size
                    print("没有仓位,我开空")

        elif self.pos > 0:
            self.sell(self.boll_mid, abs(self.pos), True)

        elif self.pos < 0:
            self.cover(self.boll_mid, abs(self.pos), True)

        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        self.put_event()
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        pass

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass

    def boll_calculate(self):
        """
        计算布林
        :return:
        """

        if not self.boll_inited:
            self.boll_count += 1
            if self.boll_count >= 6:
                self.boll_inited = True

        self.up_array[:-1] = self.up_array[1:]
        self.down_array[:-1] = self.down_array[1:]

        sma_array = self.am.sma(self.boll_window, True)
        std_array = self.am.std(self.boll_window, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_window:].max()
        up = sma_array[-1] + std_array[-1] * dev_max
        down = sma_array[-1] - std_array[-1] * dev_max

        self.up_array[-1] = up
        self.down_array[-1] = down
Esempio n. 2
0
class BollingerBotStrategy(CtaTemplate):
    """基于布林通道的交易策略"""
    className = 'BollingerBotStrategy'
    author = u'ForwardCapital'

    # 策略参数
    bollWindow = 28  # 通道窗口数
    entryDev = 3.2  # 开仓偏差
    exitDev = 1.2  # 平仓偏差
    trailingPrcnt = 0.4  # 移动止损百分比
    maWindow = 10  # 过滤用均线窗口
    initDays = 10  # 初始化数据所用的天数
    fixedSize = 1  # 每次交易的数量

    # 策略变量
    bollMid = 0  # 布林带中轨
    bollStd = 0  # 布林带宽度
    entryUp = 0  # 开仓上轨
    exitUp = 0  # 平仓上轨

    maFilter = 0  # 均线过滤
    maFilter1 = 0  # 上一期均线

    intraTradeHigh = 0  # 持仓期内的最高点
    longEntry = 0  # 多头开仓
    longExit = 0  # 多头平仓

    orderList = []  # 保存委托代码的列表
    buyOrderID = None
    sellOrderID = None

    # 参数列表,保存了参数的名称
    paramList = [
        'name', 'className', 'author', 'vtSymbol', 'bollWindow', 'entryDev',
        'exitDev', 'trailingPrcnt', 'maWindow', 'initDays', 'fixedSize'
    ]

    # 变量列表,保存了变量的名称
    varList = [
        'inited', 'trading', 'pos', 'bollMid', 'bollStd', 'entryUp', 'exitUp',
        'intraTradeHigh', 'longEntry', 'longExit'
    ]

    # 同步列表
    syncList = ['pos', 'intraTradeHigh']

    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(BollingerBotStrategy, self).__init__(ctaEngine, setting)

        self.bm = BarGenerator(self.on_bar, 15, self.onFiveBar)
        self.am = ArrayManager()

    #----------------------------------------------------------------------
    def on_init(self):
        """初始化策略(必须由用户继承实现)"""
        self.write_log(u'策略初始化')

        # 载入历史数据,并采用回放计算的方式初始化策略数值
        self.load_bar(self.initDays)

        self.put_event()

    #----------------------------------------------------------------------
    def on_start(self):
        """启动策略(必须由用户继承实现)"""
        self.write_log(u'策略启动')
        self.put_event()

    #----------------------------------------------------------------------
    def on_stop(self):
        """停止策略(必须由用户继承实现)"""
        self.write_log(u'策略停止')
        self.put_event()

    #----------------------------------------------------------------------
    def on_tick(self, tick):
        """收到行情TICK推送(必须由用户继承实现)"""
        self.bm.update_tick(tick)

    #----------------------------------------------------------------------
    def on_bar(self, bar):
        """收到Bar推送(必须由用户继承实现)"""
        self.bm.update_bar(bar)

    #----------------------------------------------------------------------
    def orderIDConvert(self, orderList):
        if not orderList:
            return []
        else:
            return orderList[0]

    #----------------------------------------------------------------------
    def onFiveBar(self, bar):
        """收到5分钟K线"""
        # 保存K线数据
        self.am.update_bar(bar)
        if not self.am.inited or not self.trading:
            return

        # 撤销之前发出的尚未成交的委托(包括限价单和停止单)
        # 计算指标数值
        self.bollMid = self.am.sma(self.bollWindow)
        self.bollStd = self.am.std(self.bollWindow)
        self.entryUp = self.bollMid + self.bollStd * self.entryDev
        self.exitUp = self.bollMid + self.bollStd * self.exitDev

        maArray = self.am.sma(self.maWindow, True)
        self.maFilter = maArray[-1]
        self.maFilter1 = maArray[-2]

        # 判断是否要进行交易
        if not self.buyOrderID:
            if self.pos == 0:
                self.intraTradeHigh = bar.high
                # 下开仓单
                if bar.close > self.maFilter and self.maFilter > self.maFilter1:
                    self.longEntry = self.entryUp
                    self.buyOrderID = self.buy(self.longEntry, self.fixedSize,
                                               True)
                    self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                    print('order None!!!buyOrderID is : %s ' % self.buyOrderID)
                    self.orderList.append(self.buyOrderID)
                    # 下平仓单
                    self.longExit = self.intraTradeHigh * (
                        1 - self.trailingPrcnt / 100)
                    self.longExit = min(self.longExit, self.exitUp)

                    self.sellOrderID = self.sell(self.longExit, abs(self.pos),
                                                 True)
                    self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                    print('order None!!!ellOrderID is : %s ' %
                          self.sellOrderID)
                    self.orderList.append(self.sellOrderID)
            elif self.pos > 0:
                self.intraTradeHigh = max(self.intraTradeHigh, bar.high)
                # 下平仓单
                self.longExit = self.intraTradeHigh * (
                    1 - self.trailingPrcnt / 100)
                self.longExit = min(self.longExit, self.exitUp)

                self.sellOrderID = self.sell(self.longExit, abs(self.pos),
                                             True)
                self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                print('order None!!!sellOrderID is : %s ' % self.sellOrderID)
                self.orderList.append(self.sellOrderID)

        else:
            if self.buyOrderID in self.orderList:
                self.intraTradeHigh = bar.high
                self.cancel_all()
                # 下开仓单
                if bar.close > self.maFilter and self.maFilter > self.maFilter1:
                    self.longEntry = self.entryUp
                    self.buyOrderID = self.buy(self.longEntry, self.fixedSize,
                                               True)
                    print('buyOrderID is : %s ' % self.buyOrderID)
                    self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                    self.orderList.append(self.buyOrderID)
                    # 下平仓单
                    self.longExit = self.intraTradeHigh * (
                        1 - self.trailingPrcnt / 100)
                    self.longExit = min(self.longExit, self.exitUp)

                    self.sellOrderID = self.sell(self.longExit, abs(self.pos),
                                                 True)
                    self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                    print('sellOrderID is : %s ' % self.sellOrderID)
                    self.orderList.append(self.sellOrderID)
            else:
                if self.sellOrderID in self.orderList:
                    self.intraTradeHigh = max(self.intraTradeHigh, bar.high)
                    self.cancel_order(self.sellOrderID)
                    # 下平仓单
                    self.longExit = self.intraTradeHigh * (
                        1 - self.trailingPrcnt / 100)
                    self.longExit = min(self.longExit, self.exitUp)

                    self.sellOrderID = self.sell(self.longExit, abs(self.pos),
                                                 True)
                    self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                    print('sellOrderID is : %s ' % self.sellOrderID)
                    self.orderList.append(self.sellOrderID)
                else:
                    self.intraTradeHigh = bar.high
                    # 下开仓单
                    if bar.close > self.maFilter and self.maFilter > self.maFilter1:
                        self.longEntry = self.entryUp
                        self.buyOrderID = self.buy(self.longEntry,
                                                   self.fixedSize, True)
                        self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                        print('buyOrderID is : %s ' % self.buyOrderID)
                        self.orderList.append(self.buyOrderID)
                        # 下平仓单
                        self.longExit = self.intraTradeHigh * (
                            1 - self.trailingPrcnt / 100)
                        self.longExit = min(self.longExit, self.exitUp)

                        self.sellOrderID = self.sell(self.longExit,
                                                     abs(self.pos), True)
                        self.sellOrderID = self.orderIDConvert(
                            self.sellOrderID)
                        print('sellOrderID is : %s ' % self.sellOrderID)
                        self.orderList.append(self.sellOrderID)

        # 发出状态更新事件
        # self.putEvent()

    #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委托变化推送(必须由用户继承实现)"""
        pass

    #----------------------------------------------------------------------
    def onTrade(self, trade):
        # 发出状态更新事件
        self.put_event()

    #----------------------------------------------------------------------
    def onStopOrder(self, so):
        """停止单推送"""
        print(u'StopOrder回报,stopOrderID:%s, status:%s' %
              (so.stopOrderID, so.status))
        if so.status == StopOrderStatus.CANCELLED or so.status == StopOrderStatus.TRIGGERED:
            self.orderList.remove(so.stopOrderID)
        pass
Esempio n. 3
0
class BollVix(CtaTemplate):
    """"""
    author = "yunya"

    open_window = 15
    boll_length = 530
    fixed_size = 1

    boll_mid_current = 0
    boll_mid_last = 0
    boll_up_current = 0
    boll_up_last = 0
    boll_down_current = 0
    boll_down_last = 0
    target_pos = 0
    pos_inited = 0
    boll_mid = 0

    # 画图专用
    time_list = []
    open_list = []
    high_list = []
    low_list = []
    close_list = []
    volume_list = []
    up_list = []
    down_list = []
    mid_list = []
    mid_new_list = []
    bias_value_list = []
    bias_list = []
    singnal_plot = []
    singnal_list = None
    singnal = None

    plot_echarts = {}

    parameters = [
        "open_window",
        "boll_length",
        "fixed_size",
    ]

    variables = [
        "boll_mid_current", "boll_mid_last", "boll_up_current", "boll_up_last",
        "boll_down_current", "boll_down_last", "pos_inited", "target_pos"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.bg = NewBarGenerator(self.on_bar,
                                  self.open_window,
                                  self.on_minute_bar,
                                  interval=Interval.MINUTE)
        self.am = ArrayManager(self.boll_length * 2)

        self.up_array: np.ndarray = np.zeros(5)
        self.down_array: np.ndarray = np.zeros(5)
        self.boll_inited = False
        self.boll_count = 0

        self.engine_type = self.get_engine_type()
        self.vt_orderids = []
        self.order_price = 0

        self.pos_inited = 0

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(12)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")
        self.put_event()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

        # 只有实盘交易才使用BestLimit算法
        if self.engine_type != EngineType.LIVE:
            return

        #  当前没有仓位
        order_volume_open = self.target_pos - self.pos

        if not order_volume_open:
            return

        if order_volume_open > 0:
            if not self.vt_orderids:
                self.order_price = tick.bid_price_1
                vt_orderids = self.buy(self.order_price,
                                       abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.bid_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

        elif order_volume_open < 0:
            if not self.vt_orderids:
                self.order_price = tick.ask_price_1
                vt_orderids = self.short(self.order_price,
                                         abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.ask_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_minute_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        # 计算布林
        sma_array = self.am.sma(self.boll_length, True)
        std_array = self.am.std(self.boll_length, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_length:].max()
        up = sma_array + std_array * dev_max
        down = sma_array - std_array * dev_max

        boll_mid_array = self.am.sma(self.boll_length, True)

        # 计算数组
        self.boll_mid = boll_mid_array[-2]
        self.boll_up_current = up[-1]
        self.boll_up_last = up[-2]
        self.boll_down_current = down[-1]
        self.boll_down_last = down[-2]

        if not self.pos:
            self.pos_inited = 0

            if self.am.close[-1] > self.boll_up_current and self.am.close[
                    -2] <= self.boll_up_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.buy(bar.close_price, self.fixed_size)
                else:
                    self.target_pos = self.fixed_size
                    print("没有仓位,我开多")

            elif self.am.close[-1] < self.boll_down_current and self.am.close[
                    -2] >= self.boll_down_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.short(bar.close_price, self.fixed_size)
                else:
                    self.target_pos = -self.fixed_size
                    print("没有仓位,我开空")

        elif self.pos > 0:
            self.sell(self.boll_mid, abs(self.pos), True)

        elif self.pos < 0:
            self.cover(self.boll_mid, abs(self.pos), True)

        # 画图专用
        if self.singnal != self.singnal_list:
            plot = self.singnal
        else:
            plot = None

        self.time_list.append(bar.datetime)
        self.open_list.append(bar.open_price)
        self.high_list.append(bar.high_price)
        self.low_list.append(bar.low_price)
        self.close_list.append(bar.close_price)
        self.volume_list.append(bar.volume)
        self.up_list.append(self.boll_up_current)
        self.down_list.append(self.boll_down_current)
        self.mid_list.append(self.boll_mid)
        self.singnal_plot.append(plot)

        self.plot_echarts = {
            "datetime": self.time_list,
            "open": self.open_list,
            "high": self.high_list,
            "low": self.low_list,
            "close": self.close_list,
            "volume": self.low_list,
            "boll_up": self.up_list,
            "boll_down": self.down_list,
            "boll_mid": self.mid_list,
            "signal": self.singnal_plot
        }
        self.singnal_list = self.singnal

        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        self.put_event()
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction.value == Direction.LONG.value:
            if trade.offset.value == Offset.OPEN.value:
                self.singnal = 1

            elif trade.offset.value == Offset.CLOSE.value:
                self.singnal = 0

            else:
                self.singnal = None

        elif trade.direction.value == Direction.SHORT.value:
            if trade.offset.value == Offset.OPEN.value:
                self.singnal = -1

            elif trade.offset.value == Offset.CLOSE.value:
                self.singnal = 0

            else:
                self.singnal = None

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass

    def boll_calculate(self):
        """
        计算布林
        :return:
        """

        if not self.boll_inited:
            self.boll_count += 1
            if self.boll_count >= 6:
                self.boll_inited = True

        self.up_array[:-1] = self.up_array[1:]
        self.down_array[:-1] = self.down_array[1:]

        sma_array = self.am.sma(self.boll_length, True)
        std_array = self.am.std(self.boll_length, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_length:].max()
        up = sma_array[-1] + std_array[-1] * dev_max
        down = sma_array[-1] - std_array[-1] * dev_max

        self.up_array[-1] = up
        self.down_array[-1] = down