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
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
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