class MaSignal(CtaSignal): """""" def __init__(self, fast_window: int, slow_window: int): """""" super(MaSignal, self).__init__() self.fast_window = fast_window self.slow_window = slow_window self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.am.update_bar(bar) if not self.am.inited: self.set_signal_pos(0) fast_ma = self.am.sma(self.fast_window) slow_ma = self.am.sma(self.slow_window) if fast_ma > slow_ma: self.set_signal_pos(1) elif fast_ma < slow_ma: self.set_signal_pos(-1) else: self.set_signal_pos(0)
class KingKeltnerStrategy(CtaTemplate): """""" author = '用Python的交易员' kk_length = 11 kk_dev = 1.6 trailing_percent = 0.8 fixed_size = 1 kk_up = 0 kk_down = 0 intra_trade_high = 0 intra_trade_low = 0 long_vt_orderids = [] short_vt_orderids = [] vt_orderids = [] parameters = ['kk_length', 'kk_dev', 'fixed_size'] variables = ['kk_up', 'kk_down'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(KingKeltnerStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" for orderid in self.vt_orderids: self.cancel_order(orderid) self.vt_orderids.clear() am = self.am am.update_bar(bar) if not am.inited: return self.kk_up, self.kk_down = am.keltner(self.kk_length, self.kk_dev) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.send_oco_order(self.kk_up, self.kk_down, self.fixed_size) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price vt_orderid = self.sell(self.intra_trade_high * (1 - self.trailing_percent / 100), abs(self.pos), True) self.vt_orderids.append(vt_orderid) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) vt_orderid = self.cover(self.intra_trade_low * (1 + self.trailing_percent / 100), abs(self.pos), True) self.vt_orderids.append(vt_orderid) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if self.pos != 0: if self.pos > 0: for short_orderid in self.short_vt_orderids: self.cancel_order(short_orderid) elif self.pos < 0: for buy_orderid in self.long_vt_orderids: self.cancel_order(buy_orderid) for orderid in (self.long_vt_orderids + self.short_vt_orderids): if orderid in self.vt_orderids: self.vt_orderids.remove(orderid) self.put_event() def send_oco_order(self, buy_price, short_price, volume): """""" self.long_vt_orderids = self.buy(buy_price, volume, True) self.short_vt_orderids = self.short(short_price, volume, True) self.vt_orderids.extend(self.long_vt_orderids) self.vt_orderids.extend(self.short_vt_orderids) def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class CtaTemplate_6(CtaTemplate_5): """ add bar manager """ className = 'CtaTemplate_6' author = u'rxg' # 基本变量 initDays = 20 # 初始化数据所用的天数 kLineCycle = 6 #Bar line cycle KLineSeconds = 60 #生成X秒的K线 marketTradeValue = 0 #策略的交易市值 arraySize = 100 parameters = CtaTemplate_5.parameters + \ [ 'className', 'author', 'kLineCycle', 'initDays', 'debugMode', 'KLineSeconds', 'arraySize' ] varList = CtaTemplate_5.variables + \ [ ] #---------------------------------------------------------------------- def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) print("-----") print(self.kLineCycle) self.bm = BarGenerator(self.on_bar, self.kLineCycle, self.onXminBar) # 创建K线合成器对象 self.bm.xsec = self.KLineSeconds #按指定X秒生成K线 self.am = ArrayManager(size=self.arraySize) # self.am = getSharedArrayManager(self.vt_symbol, self.kLineCycle, # self.KLineSeconds, self.arraySize) self.bm60 = BarGenerator(self.on_bar, 60, self.on60MinBar) self.am60 = ArrayManager(size=100) # self.am60 = getSharedArrayManager(self.vt_symbol, 60, # self.KLineSeconds, 100) #---------------------------------------------------------------------- # @timeit def on_init(self): """初始化策略(必须由用户继承实现)""" self.write_log(u'策略初始化') # 载入历史数据,并采用回放计算的方式初始化策略数值 self.load_bar(self.initDays) if hasattr(self, 'signal'): if hasattr(self.signal, 'am'): if not self.signal.am.inited: self.write_log(u'%s策略信号加载初始数据不足' % self.strategy_name) print(u'%s策略信号加载初始数据不足 ' % self.strategy_name, self.initDays) if not self.am.inited: print(u'%s策略加载初始数据不足 ' % self.strategy_name, self.kLineCycle, self.initDays) if not self.am60.inited: print(u'%s策略加载60 Min Bar 初始数据不足 ' % self.strategy_name, self.initDays) self.put_event() #---------------------------------------------------------------------- def on_start(self): """启动策略(必须由用户继承实现)""" self.write_log(u'策略启动') self.put_event() #---------------------------------------------------------------------- def on_stop(self): """停止策略(必须由用户继承实现)""" self.cancel_all() self.write_log(u'停止') self.put_event() #---------------------------------------------------------------------- def on_tick(self, tick: TickData): """收到行情TICK推送(必须由用户继承实现)""" super(CtaTemplate_6, self).on_tick(tick) self.bm.update_tick(tick) #---------------------------------------------------------------------- def on_bar(self, bar: BarData): '''处理分钟数据''' super(CtaTemplate_6, self).on_bar(bar) self.bm.update_bar(bar) self.bm60.update_bar(bar) #---------------------------------------------------------------------- def onXminBar(self, bar): """收到X分钟K线""" # 保存K线数据 am = self.am am.update_bar(bar) if not am.inited: return def on60MinBar(self, bar): """收到X分钟K线""" self.am60.update_bar(bar) if not self.am60.inited: return #---------------------------------------------------------------------- def getVolatility(self, volatilityTime=60): """收到X分钟K线""" # 保存K线数据 return (self.am.atr(50) / self.lastPrice) * ( (volatilityTime / self.kLineCycle)**0.5)
class TSMyoCLFXCStrategy(CtaTemplate): """""" author = "TheSuperMyo" # 日内交易 exit_time = time(hour=14, minute=56) # 针对不同交易时间的市场 open_time_night = time(hour=21, minute=0) # 商品夜盘 open_time_day_1 = time(hour=9, minute=0) # 商品 open_time_day_2 = time(hour=9, minute=30) # 股指 close_time_day = time(hour=15, minute=0) # 商品/股指(除了利率期货) close_time_night_1 = time(hour=23, minute=0) # 其他夜盘商品 close_time_night_2 = time(hour=1, minute=0) # 工业金属 close_time_night_3 = time(hour=2, minute=30) # 黄金/白银/原油 break_time_start_1 = time(hour=10, minute=15) # 商品茶歇 break_time_start_2 = time(hour=11, minute=30) # 全体午休 break_time_end_1 = time(hour=10, minute=30) # 商品茶歇 break_time_end_2 = time(hour=13, minute=0) # 股指下午 break_time_end_3 = time(hour=13, minute=30) # 商品下午 fit_bar = 15 # K线周期 clfx_len = 15 # 计算上下轨的周期 rsi_filter = 25 rsi_len = 10 trailing_stop = 0.45 # 跟踪止损 fixed_size = 1 # 固定手数 SAR_stop_long = 0 SAR_stop_short = 0 AF = 0 long_entry = 0 short_entry = 0 long_exit = 0 short_exit = 0 hold_high = 0 hold_low = 0 parameters = ['rsi_len', 'rsi_filter', 'fit_bar', 'fixed_size'] variables = [ 'SAR_stop_long', 'SAR_stop_short', 'AF', 'hold_high', 'hold_low' ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TSMyoCLFXCStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.fit_bar, self.on_fit_bar) self.am = TSMArrayManager() # 策略自身订单管理 self.active_orderids = [] self.bars = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def tick_filter(self, tick: TickData): """ 过滤异常时间的tick """ tick_time = tick.datetime.time() if tick_time < self.open_time_day_2: return False if tick_time > self.break_time_start_2 and tick_time < self.break_time_end_2: return False if tick_time > self.close_time_day: return False return True def on_tick(self, tick: TickData): """ Callback of new tick data update. """ if not self.tick_filter(tick): return self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ 1.根据信号挂单 2.计算SAR系统止损点位 """ self.bg.update_bar(bar) self.cancel_all() if self.pos == 0: if self.long_entry: # 入场开多,收盘价 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.buy(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.short_entry: # 入场开空,收盘价 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.short(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.pos > 0: old_high = self.hold_high self.hold_high = max(self.hold_high, bar.high_price) if old_high - self.hold_high != 0: self.AF += 0.01 self.AF = min(self.AF, 0.1) self.SAR_stop_long = self.SAR_stop_long + ( self.hold_high - self.SAR_stop_long) * self.AF #self.stop_long = self.hold_high*(1-self.trailing_stop/100) # 停止单平多 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(self.SAR_stop_long, self.fixed_size, True, True) self.active_orderids.extend(orderids) if self.pos < 0: old_low = self.hold_low self.hold_low = min(self.hold_low, bar.low_price) if old_low - self.hold_low != 0: self.AF += 0.01 self.AF = min(self.AF, 0.1) self.SAR_stop_short = self.SAR_stop_short - ( self.SAR_stop_short - self.hold_low) * self.AF # 停止单平空 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(self.SAR_stop_short, self.fixed_size, True, True) self.active_orderids.extend(orderids) def on_fit_bar(self, bar: BarData): """ 1.计算分型通道上下轨并产生信号 """ # self.cta_engine.output(f"{bar.datetime.time()}") # self.write_log(f"{bar.datetime.time()}") am = self.am am.update_bar(bar) if not am.inited: return up, down = am.clfxc(self.clfx_len, False) rsi_value = am.rsi(self.rsi_len, False) rsi_flag = 0 if abs(rsi_value - 50) > self.rsi_filter: rsi_flag = 1 if self.pos == 0 and rsi_flag == 1: if bar.close_price > up: # 向上突破,开多信号 self.long_entry = 1 self.short_entry = 0 self.long_exit = 0 self.short_exit = 0 # 抛物线初始止损点 self.SAR_stop_long = bar.low_price if bar.close_price < down: # 向下突破,开空信号 self.long_entry = 0 self.short_entry = 1 self.long_exit = 0 self.short_exit = 0 # 抛物线初始止损点 self.SAR_stop_short = bar.high_price def on_order(self, order: OrderData): """ Callback of new order data update. """ # 移除已成交或已撤销的订单 if not order.is_active() and order.vt_orderid in self.active_orderids: self.active_orderids.remove(order.vt_orderid) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # 邮寄提醒 self.send_email( f"{trade.vt_symbol}在{trade.time}成交,价格{trade.price},方向{trade.direction}{trade.offset},数量{trade.volume}" ) self.long_entry = 0 self.short_entry = 0 self.long_exit = 0 self.short_exit = 0 if self.pos == 0: self.SAR_stop_long = 0 self.SAR_stop_short = 0 self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ # 刚刚生成的本地停止单 if stop_order.status == StopOrderStatus.WAITING: return # 撤销的本地停止单,从活跃列表移除 if stop_order.status == StopOrderStatus.CANCELLED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) # 触发的本地停止单,停止单移除,限价单加入 if stop_order.status == StopOrderStatus.TRIGGERED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) self.active_orderids.extend(stop_order.vt_orderids) # 撤掉其他停止单 for other_orderids in self.active_orderids: if other_orderids.startswith(STOPORDER_PREFIX): self.cancel_order(other_orderids)
class CincoYStrategy(CtaTemplate): """""" author = "tonywang_efun" fixed_size = 2 bar_window = 13 boll_window = 38 boll_dev = 2.2 rsi_window = 8 rsi_long = 76 rsi_short = 18 trailing_long = 2.8 trailing_short = 2.6 stop_long_percent = 3.0 stop_short_percent = 3.0 boll_up = 0 boll_down = 0 rsi_value = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 short_percent_stop = 0 long_percent_stop = 0 parameters = [ "fixed_size", "bar_window", "boll_window", "boll_dev", "rsi_window", "rsi_long", "rsi_short", "trailing_long", "trailing_short", "stop_long_percent", "stop_short_percent" ] variables = [ "boll_up", "boll_down", "rsi_value", "trading_size", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__( self, cta_engine, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.bar_window, self.on_xmin_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) self.rsi_value = self.am.rsi(self.rsi_window) boll_width = self.boll_up - self.boll_down if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 self.long_percent_stop = 0 self.short_percent_stop = 0 # print(self.boll_up, self.boll_down, self.intra_trade_high, self.intra_trade_low) if self.rsi_value >= self.rsi_long: self.buy(self.boll_up, self.fixed_size, stop=True) if self.rsi_value <= self.rsi_short: self.short(self.boll_down, self.fixed_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.long_percent_stop = self.intra_trade_high * ( 1 - self.stop_long_percent / 100) self.sell(max(self.long_stop, self.long_percent_stop), abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.short_percent_stop = self.intra_trade_low * ( 1 + self.stop_short_percent / 100) self.cover(min(self.short_stop, self.short_percent_stop), abs(self.pos), stop=True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class FixedHedgeStrategy(CtaTemplate): """""" author = "option underlying Fixed hedge" nick_name = 'fixed_hedge' is_log = False base_price = 0 entry_range = 0.05 hedge_range_param = 100 hedge_multiple_param = 50 hedge_range = 0.0 hedge_multiple = 0.0 hedge_size = 10 last_trade_dt = None parameters = ['hedge_range_param', 'hedge_multiple_param', 'hedge_size'] variables = [] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am5 = ArrayManager(size=20) self.hedge_range = self.hedge_range_param / 1000 self.hedge_multiple = self.hedge_multiple_param / 100 self.hedge_size = round(self.hedge_range / 0.1 * 30) setting['hedge_size'] = self.hedge_size print("params:", self.hedge_range, self.hedge_multiple, self.hedge_size, self.strategy_name) def on_init(self): self.write_log("策略初始化") self.load_bar(10) def on_start(self): self.write_log("策略启动") def on_stop(self): self.write_log("策略停止") def on_tick(self, tick: TickData): pass def on_bar(self, bar: BarData): self.bg5.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.log(bar.datetime, bar.open_price, bar.high_price, bar.low_price, bar.close_price) self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return if not self.base_price: self.base_price = round(bar.open_price, 2) else: up = self.base_price + self.hedge_range down = self.base_price - self.hedge_range self.log('base:', self.base_price, 'up:', up, 'down:', down, 'pos:', self.pos) if self.pos == 0: self.buy(up, self.hedge_size * self.hedge_multiple, True) self.short(down, self.hedge_size * self.hedge_multiple, True) elif self.pos > 0: # 条件触发用本地单 self.sell(down, self.hedge_size * self.hedge_multiple, True) # self.short(down, self.hedge_size * self.hedge_multiple, True) self.buy(up, self.hedge_size * self.hedge_multiple, True) # 多单止盈用限价单 self.sell(up, self.hedge_size * self.hedge_multiple, False) elif self.pos < 0: # 条件触发用本地单 self.cover(up, self.hedge_size * self.hedge_multiple, True) # self.buy(up, self.hedge_size * self.hedge_multiple, True) self.short(down, self.hedge_size * self.hedge_multiple, True) # 空单止盈用限价单 self.cover(down, self.hedge_size * self.hedge_multiple, False) def on_order(self, order: OrderData): pass def on_trade(self, trade: TradeData): self.log("Trade:", trade.datetime, trade.direction, trade.offset, trade.price, trade.volume) if trade.datetime != self.last_trade_dt: if trade.direction == Direction.LONG: self.base_price += self.hedge_range * self.hedge_multiple elif trade.direction == Direction.SHORT: self.base_price -= self.hedge_range * self.hedge_multiple else: # 如果平仓后跟着开仓,说明前一次基线调错了,补回来后还要相应移动1档 # self.log('trades at the same time') if trade.direction == Direction.LONG and trade.offset == Offset.OPEN: self.base_price += self.hedge_range * self.hedge_multiple * 2 elif trade.direction == Direction.SHORT and trade.offset == Offset.OPEN: self.base_price -= self.hedge_range * self.hedge_multiple * 2 self.last_trade_dt = trade.datetime def on_stop_order(self, stop_order: StopOrder): pass def log(self, *arg, **kwargs): if self.is_log: print(*arg, **kwargs)
class TrendModelDoubleRsi(CtaTemplate): """""" author = "yiran" s_window = 5 l_window = 15 rsi_window = 11 long_threshold_l_window = 50 long_threshold_s_window = 80 fixed_size = 1 fast_ma_macd = 9 slow_ma_macd = 26 signal_macd = 4 true_range_window = 4 true_range_influence_multiplier = 0.5 cross_over_record_max_num = 50 cross_over_slice_window = 4 trail_bar_window = 6 mdif = 0 cross_above_0 = False cross_under_0 = False cross_over_record_array = np.zeros(shape=(4, cross_over_record_max_num)) cross_over_slice_window_highest = 0 cross_over_slice_window_lowest = 0 last_cross_over_interval = 0 last_cross_over_side = 0 bar_num = 0 bar_num_after_crossover = 0 start_time = time(hour=10) exit_time = time(hour=14, minute=55) long_order_record = [] short_order_record = [] rsi_value_l_window = -9999 rsi_value_s_window = -9999 exit_return = 0.02 exit_loss = 0.02 long_entered = False short_entered = False intra_trade_high = 0 intra_trade_low = 0 trailing_percent = 0.8 parameters = [ 's_window', 'l_window', "rsi_window", "long_threshold_l_window", "long_threshold_s_window", 'exit_return', 'exit_loss', "fixed_size" ] variables = ["rsi_value_l_window ", "rsi_value_s_window", "ma_trend"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long_l = self.long_threshold_l_window self.rsi_long_s = self.long_threshold_s_window self.rsi_short_l = 100 - self.long_threshold_l_window self.rsi_short_s = 100 - self.long_threshold_s_window self.bg5 = BarGenerator(self.on_bar, self.s_window, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, self.l_window, self.on_15min_bar) self.am15 = ArrayManager() self.long_order_record = [] self.short_order_record = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return self.rsi_value_s_window = self.am5.rsi(self.rsi_window) if self.long_threshold_l_window != -9999: self.long_entered = (self.rsi_value_s_window > self.rsi_long_s) and (self.rsi_value_l_window > self.rsi_long_l) self.short_entered = ( self.rsi_value_s_window < self.rsi_short_s) and ( self.rsi_value_l_window < self.rsi_short_l) else: return if self.start_time <= bar.datetime.time() < self.exit_time: time_constraint = self.last_cross_over_interval <= self.cross_over_record_max_num if self.pos == 0 and time_constraint: if self.long_entered: self.buy(bar.close_price + 5, self.fixed_size) self.long_order_record.append(bar.close_price + 5) elif self.short_entered: self.short(bar.close_price - 5, self.fixed_size) self.short_order_record.append(bar.close_price - 5) elif self.pos > 0: buy_order_price = self.long_order_record[-1] if bar.close_price >= buy_order_price * (1 + self.exit_return): self.sell(bar.close_price * 0.99, abs(self.pos)) elif bar.close_price <= buy_order_price * (1 - self.exit_loss): self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: sell_order_price = self.short_order_record[-1] if bar.close_price >= sell_order_price * (1 + self.exit_loss): self.cover(bar.close_price * 1.01, abs(self.pos)) elif bar.close_price <= sell_order_price * (1 - self.exit_return): self.cover(bar.close_price * 1.01, abs(self.pos)) elif bar.datetime.time() > self.exit_time: if self.pos > 0: self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.cover(bar.close_price * 1.01, abs(self.pos)) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) self.bar_num += 1 if not self.am15.inited: return self.rsi_value_l_window = self.am15.rsi(self.rsi_window) am = self.am15 self.mdif, signal, hist = am.macd(self.fast_ma_macd, self.slow_ma_macd, self.signal_macd, array=True) self.long_close_stop_order_price = am.low[-self.trail_bar_window:].min( ) self.short_close_stop_order_price = am.high[-self. trail_bar_window:].max() if self.mdif[-2] < 0 < self.mdif[-1]: self.cross_above_0 = True elif self.mdif[-2] > 0 > self.mdif[-1]: self.cross_under_0 = True if self.cross_under_0 or self.cross_above_0: # bar_num self.cross_over_record_array[ 0, :-1] = self.cross_over_record_array[0, 1:] # high self.cross_over_record_array[ 1, :-1] = self.cross_over_record_array[1, 1:] # low self.cross_over_record_array[ 2, :-1] = self.cross_over_record_array[2, 1:] # cross_over_side self.cross_over_record_array[ 3, :-1] = self.cross_over_record_array[3, 1:] self.cross_over_record_array[0, -1] = self.bar_num self.cross_over_record_array[1, -1] = am.high[-1] self.cross_over_record_array[2, -1] = am.low[-1] if self.cross_above_0: side = 1 elif self.cross_under_0: side = -1 self.cross_over_record_array[3, -1] = side self.cross_above_0, self.cross_under_0 = False, False self.cross_over_slice_window_highest = np.max( self.cross_over_record_array[1, -self.cross_over_slice_window:]) self.cross_over_slice_window_lowest = np.min( self.cross_over_record_array[2, -self.cross_over_slice_window:]) self.last_cross_over_interval = self.bar_num - \ self.cross_over_record_array[0, -1] self.last_cross_over_side = self.cross_over_record_array[3, -1] true_range_influence = np.mean( am.trange(array=True)[-self.true_range_window:] ) * self.true_range_influence_multiplier self.long_open_stop_order_price = self.cross_over_slice_window_highest + \ true_range_influence self.short_open_stop_order_price = self.cross_over_slice_window_lowest + \ true_range_influence def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class KingKeltnerStrategy(CtaTemplate): """""" author = ' use Python traders ' kk_length = 11 kk_dev = 1.6 trailing_percent = 0.8 fixed_size = 1 kk_up = 0 kk_down = 0 intra_trade_high = 0 intra_trade_low = 0 long_vt_orderids = [] short_vt_orderids = [] vt_orderids = [] parameters = ['kk_length', 'kk_dev', 'fixed_size'] variables = ['kk_up', 'kk_down'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(KingKeltnerStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log(" strategy initialization ") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log(" policy startup ") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log(" stop strategy ") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" for orderid in self.vt_orderids: self.cancel_order(orderid) self.vt_orderids.clear() am = self.am am.update_bar(bar) if not am.inited: return self.kk_up, self.kk_down = am.keltner(self.kk_length, self.kk_dev) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.send_oco_order(self.kk_up, self.kk_down, self.fixed_size) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price vt_orderids = self.sell( self.intra_trade_high * (1 - self.trailing_percent / 100), abs(self.pos), True) self.vt_orderids.extend(vt_orderids) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) vt_orderids = self.cover( self.intra_trade_low * (1 + self.trailing_percent / 100), abs(self.pos), True) self.vt_orderids.extend(vt_orderids) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if self.pos != 0: if self.pos > 0: for short_orderid in self.short_vt_orderids: self.cancel_order(short_orderid) elif self.pos < 0: for buy_orderid in self.long_vt_orderids: self.cancel_order(buy_orderid) for orderid in (self.long_vt_orderids + self.short_vt_orderids): if orderid in self.vt_orderids: self.vt_orderids.remove(orderid) self.put_event() def send_oco_order(self, buy_price, short_price, volume): """""" self.long_vt_orderids = self.buy(buy_price, volume, True) self.short_vt_orderids = self.short(short_price, volume, True) self.vt_orderids.extend(self.long_vt_orderids) self.vt_orderids.extend(self.short_vt_orderids) def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class CincoStrategy(CtaTemplate): """""" author = "用Python的交易员" boll_window = 42 boll_dev = 2.2 atr_window = 4 risk_level = 200 trailing_short = 0.7 trailing_long = 0.65 boll_up = 0 boll_down = 0 rsi_buy = 0 rsi_sell = 0 atr_value = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = [ "boll_window", "boll_dev", "risk_level", "atr_window", "trailing_short", "trailing_long" ] variables = [ "boll_up", "boll_down", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(CincoStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) # self.bg = MyGenerator(self.on_bar, self.interval, self.on_15min_bar) # 合成15分钟k线 self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) # 推送下一根k线 def on_15min_bar(self, bar: BarData): """""" self.cancel_all() # 先取消全部未成交的订单 am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) # 生成bolling带上下轨 boll_width = self.boll_up - self.boll_down # 计算bolling带宽度 ## 空仓时 if self.pos == 0: atr_fix = am.atr(self.atr_window) # 计算atr指标 self.trading_size = int( self.risk_level / atr_fix) # 根据用风险控制水平除以atr得到开仓量,吗每单固定风险,根据atr调整仓位大小 self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 self.buy(self.boll_up, self.trading_size, stop=True) # 在bolling带上轨开多仓 self.short(self.boll_down, self.trading_size, stop=True) # 在bolling带下轨开空仓 ## 持有多仓时 elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) # 计算持仓以后到达过的最高价 self.intra_trade_low = bar.low_price # 计算当根k线最低价 self.long_stop = (self.intra_trade_high - self.trailing_long * boll_width ) # 用最高价回撤bolling带宽度与参数的方式计算追踪止损位置 self.sell(self.long_stop, abs(self.pos), stop=True) # 在追踪止损位卖出全部持仓 ## 当持有空头仓位时 elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) # 计算持仓后的最低价 self.short_stop = (self.intra_trade_low + self.trailing_short * boll_width) # 计算追踪止损位置 self.cover(self.short_stop, abs(self.pos), stop=True) # 平掉全部空仓 self.put_event() # 更新vntrader界面数据 self.sync_data() # 将策略运行数据同步保存到本地 def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class CincoZHCStrategy(CtaTemplate): """""" author = "tonywang_efun" bar_window = 14 bar_z_window = 48 boll_window = 38 boll_dev = 2.3 rsi_window = 15 rsi_long = 58 rsi_short = 23 fast_window = 3 slow_window = 13 trailing_long = 2.6 trailing_short = 4.0 fixed_size = 2 boll_up = 0 boll_down = 0 rsi_value = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "bar_window", "bar_z_window", "boll_window", "boll_dev", "rsi_window", "rsi_long", "rsi_short", "fast_window", "slow_window", "trailing_long", "trailing_short", "fixed_size" ] variables = [ "boll_up", "boll_down", "rsi_value", "fast_ma", "slow_ma", "ma_trend", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__( self, cta_engine, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.bar_window, self.on_xmin_bar) self.bgz = BarGenerator(self.on_bar, self.bar_z_window, self.on_zmin_bar) self.am = ArrayManager() self.amz = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_bar(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) self.bgz.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited or not self.amz.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) self.rsi_value = self.am.rsi(self.rsi_window) boll_width = self.boll_up - self.boll_down if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy(self.boll_up, self.fixed_size, stop=True) if self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(self.boll_down, self.fixed_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_zmin_bar(self, bar: BarData): """""" self.amz.update_bar(bar) if not self.amz.inited: return self.fast_ma = self.amz.sma(self.fast_window) self.slow_ma = self.amz.sma(self.slow_window) if self.fast_ma > self.slow_ma: self.ma_trend = 1 elif self.fast_ma < self.slow_ma: self.ma_trend = -1 else: self.ma_trend = 0 self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class BollingerBotStrategy(CtaTemplate): """基于布林通道的交易策略""" author = u'tonywang_efun' # 策略参数 fixedSize = 2 # 每次交易的数量 bollLength = 40 # 通道窗口数 entryDev = 3.2 # 开仓偏差 exitDev = 1.2 # 平仓偏差 trailingPrcnt = 0.6 # 移动止损百分比 maLength = 13 # 过滤用均线窗口 initDays = 10 # 初始化数据所用的天数 # 策略变量 entryUp = 0 # 开仓上轨 exitUp = 0 # 平仓上轨 maFilter = 0 # 均线过滤 maFilter1 = 0 # 上一期均线 intraTradeHigh = 0 # 持仓期内的最高点 longEntry = 0 # 多头开仓 longExit = 0 # 多头平仓 # 参数列表,保存了参数的名称 parameters = [ 'fixedSize', 'bollLength', 'entryDev', 'exitDev', 'trailingPrcnt', 'maLength', 'initDays' ] # 变量列表,保存了变量的名称 variables = ['entryUp', 'exitUp', 'intraTradeHigh', 'longEntry'] # ---------------------------------------------------------------------- def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(BollingerBotStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager(40) # ---------------------------------------------------------------------- def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(self.initDays) # ---------------------------------------------------------------------- def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") # ---------------------------------------------------------------------- def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") # ---------------------------------------------------------------------- def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) # ---------------------------------------------------------------------- def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """收到5分钟K线""" # 撤销之前发出的尚未成交的委托(包括限价单和停止单) self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算指标数值 self.entryUp, self.exitUp = am.boll_double_up(self.bollLength, self.entryDev, self.exitDev) ma_array = am.sma(self.maLength, True) self.maFilter = ma_array[-1] self.maFilter1 = ma_array[-2] # 当前无仓位,发送OCO开仓委托 if self.pos == 0: self.intraTradeHigh = bar.high_price if bar.close_price > self.maFilter > self.maFilter1: self.longEntry = self.entryUp self.buy(self.longEntry, self.fixedSize, True) # 持有多头仓位 elif self.pos > 0: self.intraTradeHigh = max(self.intraTradeHigh, bar.high_price) self.longExit = self.intraTradeHigh * (1 - self.trailingPrcnt / 100) self.longExit = min(self.longExit, self.exitUp) self.sell(self.longExit, abs(self.pos), True) # 发出状态更新事件 self.put_event() def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" pass # ---------------------------------------------------------------------- def on_trade(self, trade): # 发出状态更新事件 self.put_event() # ---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" pass
class DoubleDayM30Strategy(CtaTemplate): """ 使用1m线合成 日线、30分钟、1分钟三种数据,并根据各自ma叠加进行卖卖的策略 """ author = "fsksf" window_mn = 30 # n分钟线 fast_window_day = 3 fast_window_m30 = 3 slow_window_day = 5 slow_window_m30 = 5 fast_ma_day = 0.0 fast_ma_m30 = 0.0 slow_ma_day = 0.0 slow_ma_m30 = 0.0 slow_ma_m1 = 0.0 parameters = [ "fast_window_day", "fast_window_m30", "slow_window_day", "slow_window_m30", "window_mn" ] variables = ["fast_ma_day", "slow_ma_day", "fast_ma_m30", "slow_ma_m30"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.day_bar_gen = BarGenerator(lambda x: None, interval=Interval.DAILY, window=1, on_window_bar=self.on_day_bar) self.m30_bar_gen = BarGenerator(self.on_bar, interval=Interval.MINUTE, window=self.window_mn, on_window_bar=self.on_m30_bar) self.day_am = ArrayManager(size=self.slow_window_day + 1) self.m30_am = ArrayManager(size=self.slow_window_m30 + 1) def on_m30_bar(self, bar): self.write_log('30分钟bar合成完毕') self.m30_am.update_bar(bar) def on_day_bar(self, bar): self.write_log('day bar合成完毕') self.day_am.update_bar(bar) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(100) 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.m30_bar_gen.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ # if self.cta_engine.gateway_name == "BACKTESTING": # update window self.m30_bar_gen.update_bar(bar) self.day_bar_gen.update_bar(bar) self.write_log(str(self.day_am.count)) if not (self.day_am.inited and self.m30_am.inited): return self.write_log('bar历史初始化完成') # 最后一个bar实时更新的,计算ma后删除 self.day_am.update_bar(self.day_bar_gen.last_bar) fast_ma_day = self.day_am.sma(self.fast_window_day, array=True) slow_ma_day = self.day_am.sma(self.slow_window_day, array=True) self.day_am.remove_last_bar() self.m30_am.update_bar(self.m30_bar_gen.last_bar) fast_ma_m30 = self.m30_am.sma(self.fast_window_m30, array=True) slow_ma_m30 = self.m30_am.sma(self.slow_window_m30, array=True) self.m30_am.remove_last_bar() self.fast_ma_day = fast_ma_day[-1] self.fast_ma_m30 = fast_ma_m30[-1] self.slow_ma_day = slow_ma_day[-1] self.slow_ma_m30 = slow_ma_m30[-1] cross_over = fast_ma_day[-2] < slow_ma_day[-2] and fast_ma_day[-1] > slow_ma_day[-1] and \ fast_ma_m30[-2] < slow_ma_m30[-2] and fast_ma_m30[-1] > slow_ma_m30[-1] cross_below = fast_ma_day[-2] > slow_ma_day[-2] and fast_ma_day[-1] < slow_ma_day[-1] and \ fast_ma_m30[-2] > slow_ma_m30[-2] and fast_ma_m30[-1] < slow_ma_m30[-1] if cross_over: if self.pos == 0: self.buy(bar.close_price, 1) elif self.pos < 0: self.cover(bar.close_price, 1) self.buy(bar.close_price, 1) elif cross_below: if self.pos == 0: self.short(bar.close_price, 1) elif self.pos > 0: self.sell(bar.close_price, 1) self.short(bar.close_price, 1) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class TSMyoDochSARStrategy(CtaTemplate): """""" author = "TheSuperMyo" # 日内交易 exit_time = time(hour=14, minute=56) # 针对不同交易时间的市场 open_time_night = time(hour=21, minute=0) # 商品夜盘 open_time_day_1 = time(hour=9, minute=0) # 商品 open_time_day_2 = time(hour=9, minute=30) # 股指 close_time_day = time(hour=15, minute=0) # 商品/股指(除了利率期货) close_time_night_1 = time(hour=23, minute=0) # 其他夜盘商品 close_time_night_2 = time(hour=1, minute=0) # 工业金属 close_time_night_3 = time(hour=2, minute=30) # 黄金/白银/原油 break_time_start_1 = time(hour=10, minute=15) # 商品茶歇 break_time_start_2 = time(hour=11, minute=30) # 全体午休 break_time_end_1 = time(hour=10, minute=30) # 商品茶歇 break_time_end_2 = time(hour=13, minute=0) # 股指下午 break_time_end_3 = time(hour=13, minute=30) # 商品下午 fit_bar = 3 # K线周期 offset_bar = 2 # 入场极值偏移 setup_bar = 85 # 基础拟合分钟数 end_window = 95 # 时间窗口分钟数 trailing_stop = 0.45 # 跟踪止损 fixed_size = 1 # 固定手数 bar_counter = 0 # 每日分钟计数器 SAR_stop_long = 0 SAR_stop_short = 0 AF = 0 long_entry = 0 short_entry = 0 long_exit = 0 short_exit = 0 hold_high = 0 hold_low = 0 parameters = [ 'offset_bar', 'end_window', 'setup_bar', 'fit_bar', 'fixed_size' ] variables = [ 'bar_counter', 'SAR_stop_long', 'SAR_stop_short', 'AF', 'hold_high', 'hold_low' ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TSMyoDochSARStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.fit_bar, self.on_fit_bar) # 股指每天240分钟 self.am = TSMArrayManager(240) # 策略自身订单管理 self.active_orderids = [] self.bars = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") # 不会用到昨日数据 self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def tick_filter(self, tick: TickData): """ 过滤异常时间的tick """ tick_time = tick.datetime.time() if tick_time < self.open_time_day_2: return False if tick_time > self.break_time_start_2 and tick_time < self.break_time_end_2: return False if tick_time > self.close_time_day: return False return True def on_tick(self, tick: TickData): """ Callback of new tick data update. """ if not self.tick_filter(tick): return self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ 1.分钟计数 2.根据信号挂单 3.计算SAR系统止损点位 """ self.bar_counter += 1 self.bg.update_bar(bar) self.cancel_all() if self.pos == 0 and bar.datetime.time() < self.exit_time: if self.long_entry: # 入场开多,收盘价 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.buy(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.short_entry: # 入场开空,收盘价 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.short(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.pos > 0: old_high = self.hold_high self.hold_high = max(self.hold_high, bar.high_price) if old_high - self.hold_high != 0: self.AF += 0.01 self.AF = min(self.AF, 0.1) self.SAR_stop_long = self.SAR_stop_long + ( self.hold_high - self.SAR_stop_long) * self.AF #self.stop_long = self.hold_high*(1-self.trailing_stop/100) if bar.datetime.time() > self.exit_time: # 日内平仓 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) else: # 停止单平多 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(self.SAR_stop_long, self.fixed_size, True, True) self.active_orderids.extend(orderids) if self.pos < 0: old_low = self.hold_low self.hold_low = min(self.hold_low, bar.low_price) if old_low - self.hold_low != 0: self.AF += 0.01 self.AF = min(self.AF, 0.1) self.SAR_stop_short = self.SAR_stop_short - ( self.SAR_stop_short - self.hold_low) * self.AF if bar.datetime.time() > self.exit_time: # 日内平仓 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) else: # 停止单平空 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(self.SAR_stop_short, self.fixed_size, True, True) self.active_orderids.extend(orderids) def on_fit_bar(self, bar: BarData): """ 1.负责每日开盘的初始化 2.计算极值并产生信号 """ # self.cta_engine.output(f"{bar.datetime.time()}") # self.write_log(f"{bar.datetime.time()}") am = self.am am.update_bar(bar) self.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] # 开盘fit_min_bar if last_bar.datetime.date() != bar.datetime.date(): # 初始化 self.bar_counter = self.fit_bar self.long_entry = 0 self.short_entry = 0 self.long_exit = 0 self.short_exit = 0 self.SAR_stop_long = 0 self.SAR_stop_short = 0 if self.bar_counter < self.setup_bar: return up_array, down_array = am.donchian( int((self.bar_counter) / self.fit_bar)) up = up_array[-1 - self.offset_bar] down = down_array[-1 - self.offset_bar] if self.pos == 0 and self.bar_counter < self.end_window: if bar.close_price > up: # 向上突破,开多信号 self.long_entry = 1 self.short_entry = 0 self.long_exit = 0 self.short_exit = 0 # 抛物线初始止损点 self.SAR_stop_long = bar.low_price if bar.close_price < down: # 向下突破,开空信号 self.long_entry = 0 self.short_entry = 1 self.long_exit = 0 self.short_exit = 0 # 抛物线初始止损点 self.SAR_stop_short = bar.high_price def on_order(self, order: OrderData): """ Callback of new order data update. """ # 移除已成交或已撤销的订单 if not order.is_active() and order.vt_orderid in self.active_orderids: self.active_orderids.remove(order.vt_orderid) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # 邮寄提醒 self.send_email( f"{trade.vt_symbol}在{trade.time}成交,价格{trade.price},方向{trade.direction}{trade.offset},数量{trade.volume}" ) self.long_entry = 0 self.short_entry = 0 self.long_exit = 0 self.short_exit = 0 if self.pos == 0: self.SAR_stop_long = 0 self.SAR_stop_short = 0 self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ # 刚刚生成的本地停止单 if stop_order.status == StopOrderStatus.WAITING: return # 撤销的本地停止单,从活跃列表移除 if stop_order.status == StopOrderStatus.CANCELLED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) # 触发的本地停止单,停止单移除,限价单加入 if stop_order.status == StopOrderStatus.TRIGGERED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) self.active_orderids.extend(stop_order.vt_orderids) # 撤掉其他停止单 for other_orderids in self.active_orderids: if other_orderids.startswith(STOPORDER_PREFIX): self.cancel_order(other_orderids)
class MLearnStrategy(CtaTemplate): """""" author = "用Python的交易员" load_bar_day = 20 sl_multiplier = 7.6 fixed_size = 1 db_record = 0 bar_window = 5 bar_size = 100 slippage_rate = 0.002 direction = Direction.NET atr_value = 0 trade_long_price = 0 trade_short_price = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_window = 30 vt_xm_orderids = [] parameters = [ "load_bar_day", "sl_multiplier", "fixed_size", "db_record", "bar_window", "bar_size", "slippage_rate" ] variables = [ "direction", "atr_value", "trade_long_price", "trade_long_price", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.bar_window, self.on_xmin_bar) #self.am_xm = MLP_Analyze(self.bar_size) self.am_xm = LSTM_Analyze(self.bar_size) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(self.load_bar_day) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_order_list(self.vt_xm_orderids) self.am_xm.update_bar(bar) if not self.am_xm.inited: return self.direction = self.am_xm.trend self.atr_value = self.am_xm.atr(self.atr_window) self.trade_long_price = get_trade_long_price(bar.close_price, self.slippage_rate) self.trade_short_price = get_trade_short_price(bar.close_price, self.slippage_rate) vt_orderids = [] if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.direction == Direction.LONG: vt_orderids = self.buy(self.trade_long_price, self.fixed_size) elif self.direction == Direction.SHORT: vt_orderids = self.short(self.trade_short_price, self.fixed_size) self.vt_xm_orderids.extend(vt_orderids) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price if self.direction == Direction.SHORT: vt_orderids = self.sell(self.trade_short_price, abs(self.pos)) else: self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier vt_orderids = self.sell(self.long_stop, abs(self.pos), True) self.vt_xm_orderids.extend(vt_orderids) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) if self.direction == Direction.LONG: vt_orderids = self.cover(self.trade_long_price, abs(self.pos)) else: self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier vt_orderids = self.cover(self.short_stop, abs(self.pos), True) self.vt_xm_orderids.extend(vt_orderids) if self.db_record: database_manager.save_bar_calc(bar, self.get_variables()) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # 数据库记录成交记录,bar记录,variables值 if self.db_record: database_manager.save_trade_data(trade, self.get_variables()) self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class DoubleRsiTrailing(CtaTemplate): """""" author = "yiran" s_window = 5 l_window = 15 rsi_window = 11 long_threshold_l_window = 50 long_threshold_s_window = 80 fixed_size = 1 start_time = time(hour=10) exit_time = time(hour=14, minute=55) long_order_record = [] short_order_record = [] rsi_value_l_window = -9999 rsi_value_s_window = -9999 exit_return = 0.02 exit_loss = 0.02 long_entered = False short_entered = False intra_trade_high = 0 intra_trade_low = 0 trailing_percent = 0.8 parameters = [ 's_window', 'l_window', "rsi_window", "long_threshold_l_window", "long_threshold_s_window", 'exit_return', 'exit_loss', "fixed_size" ] variables = ["rsi_value_l_window ", "rsi_value_s_window", "ma_trend"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long_l = self.long_threshold_l_window self.rsi_long_s = self.long_threshold_s_window self.rsi_short_l = 100 - self.long_threshold_l_window self.rsi_short_s = 100 - self.long_threshold_s_window self.bg5 = BarGenerator(self.on_bar, self.s_window, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, self.l_window, self.on_15min_bar) self.am15 = ArrayManager() self.long_order_record = [] self.short_order_record = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return self.rsi_value_s_window = self.am5.rsi(self.rsi_window) if self.long_threshold_l_window != -9999: self.long_entered = (self.rsi_value_s_window > self.rsi_long_s) and (self.rsi_value_l_window > self.rsi_long_l) self.short_entered = ( self.rsi_value_s_window < self.rsi_short_s) and ( self.rsi_value_l_window < self.rsi_short_l) else: return if self.start_time <= bar.datetime.time() < self.exit_time: if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.long_entered: self.buy(bar.close_price + 5, self.fixed_size) self.long_order_record.append(bar.close_price + 5) elif self.short_entered: self.short(bar.close_price - 5, self.fixed_size) self.short_order_record.append(bar.close_price - 5) elif self.pos > 0: buy_order_price = self.long_order_record[-1] self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.sell(self.intra_trade_high * \ (1 - self.trailing_percent / 100), abs(self.pos), True) # if bar.close_price >= buy_order_price*(1+self.exit_return): # self.sell(bar.close_price * 0.99, abs(self.pos)) # elif bar.close_price <= buy_order_price*(1-self.exit_loss): # self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.cover(self.intra_trade_low * (1 + \ self.trailing_percent / 100), abs(self.pos), True) # # if bar.close_price >= sell_order_price*(1+self.exit_loss): # self.cover(bar.close_price * 1.01, abs(self.pos)) # elif bar.close_price <= sell_order_price*(1-self.exit_return): # self.cover(bar.close_price * 1.01, abs(self.pos)) elif bar.datetime.time() > self.exit_time: if self.pos > 0: self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.cover(bar.close_price * 1.01, abs(self.pos)) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if not self.am15.inited: return self.rsi_value_l_window = self.am15.rsi(self.rsi_window) def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class TSMyoDLLTStrategy(CtaTemplate): """""" author = "TheSuperMyo" # 日内交易 exit_time = time(hour=14, minute=57) # 针对不同交易时间的市场 open_time_night = time(hour=21, minute=0) # 商品夜盘 open_time_day_1 = time(hour=9, minute=0) # 商品 open_time_day_2 = time(hour=9, minute=30) # 股指 close_time_day = time(hour=15, minute=0) # 商品/股指(除了利率期货) close_time_night_1 = time(hour=23, minute=0) # 其他夜盘商品 close_time_night_2 = time(hour=1, minute=0) # 工业金属 close_time_night_3 = time(hour=2, minute=30) # 黄金/白银/原油 break_time_start_1 = time(hour=10, minute=15) # 商品茶歇 break_time_start_2 = time(hour=11, minute=30) # 全体午休 break_time_end_1 = time(hour=10, minute=30) # 商品茶歇 break_time_end_2 = time(hour=13, minute=0) # 股指下午 break_time_end_3 = time(hour=13, minute=30) # 商品下午 fit_bar = 30 # 日间K线周期 LLT_len_slow = 20 LLT_len_fast = 10 trailing_stop = 2 # 跟踪止损 fixed_size = 1 # 固定手数 bar_counter = 0 # 每日分钟计数器 LLT_value_slow = 0 LLT_value_fast = 0 cross_up = 0 cross_down = 0 stop_long = 0 stop_short = 0 hold_high = 0 hold_low = 0 parameters = [ 'LLT_len_slow', 'LLT_len_fast', 'fit_bar', 'trailing_stop', 'fixed_size' ] variables = [ 'bar_counter', 'LLT_value_slow', 'LLT_value_fast', 'stop_long', 'stop_short', 'hold_high', 'hold_low', 'cross_up', 'cross_down' ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TSMyoDLLTStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = TSMArrayManager() # 策略自身订单管理 self.active_orderids = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def tick_filter(self, tick: TickData): """ 过滤异常时间的tick """ tick_time = tick.datetime.time() if tick_time < self.open_time_day_2: return False if tick_time > self.break_time_start_2 and tick_time < self.break_time_end_2: return False if tick_time > self.close_time_day: return False return True def on_tick(self, tick: TickData): """ Callback of new tick data update. """ if not self.tick_filter(tick): return self.bg.update_tick(tick) def on_bar(self, bar: BarData): self.bg.update_bar(bar) def on_fit_bar(self, bar: BarData): """ 1.分钟计数 2.挂撤单 """ self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.LLT_value_fast = am.LLT(self.LLT_len_fast, True) self.LLT_value_slow = am.LLT(self.LLT_len_slow, True) # 金叉 if self.LLT_value_fast[-2] < self.LLT_value_slow[ -2] and self.LLT_value_fast[-1] > self.LLT_value_slow[-1]: self.cross_up = (self.LLT_value_slow[-1] + self.LLT_value_slow[-2]) / 2 if self.pos == 0: # 入场开多 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.buy(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) # 死叉 if self.LLT_value_fast[-2] > self.LLT_value_slow[ -2] and self.LLT_value_fast[-1] < self.LLT_value_slow[-1]: self.cross_down = (self.LLT_value_slow[-1] + self.LLT_value_slow[-2]) / 2 if self.pos == 0: # 入场开空 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.short(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.pos > 0: self.hold_high = max(self.hold_high, bar.high_price) self.stop_long = self.hold_high * (1 - self.trailing_stop / 100) self.stop_long = max(self.stop_long, self.cross_up) # 停止单平多 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(self.stop_long, self.fixed_size, True, True) self.active_orderids.extend(orderids) if self.pos < 0: self.hold_low = min(self.hold_low, bar.low_price) self.stop_short = self.hold_low * (1 + self.trailing_stop / 100) self.stop_short = min(self.stop_short, self.cross_down) # 停止单平空 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(self.stop_short, self.fixed_size, True, True) self.active_orderids.extend(orderids) def on_order(self, order: OrderData): """ Callback of new order data update. """ # 移除已成交或已撤销的订单 if not order.is_active() and order.vt_orderid in self.active_orderids: self.active_orderids.remove(order.vt_orderid) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # 邮寄提醒 self.send_email( f"{trade.vt_symbol}在{trade.time}成交,价格{trade.price},方向{trade.direction}{trade.offset},数量{trade.volume}" ) if self.pos == 0: self.stop_long = 0 self.stop_short = 0 if self.pos > 0: self.hold_high = trade.price if self.pos < 0: self.hold_low = trade.price self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ # 刚刚生成的本地停止单 if stop_order.status == StopOrderStatus.WAITING: return # 撤销的本地停止单,从活跃列表移除 if stop_order.status == StopOrderStatus.CANCELLED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) # 触发的本地停止单,停止单移除,限价单加入 if stop_order.status == StopOrderStatus.TRIGGERED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) self.active_orderids.extend(stop_order.vt_orderids) # 撤掉其他停止单 for other_orderids in self.active_orderids: if other_orderids.startswith(STOPORDER_PREFIX): self.cancel_order(other_orderids)
class MyBollChannelStrategy(CtaTemplate): """""" author = "sheepbear" boll_window = 18 boll_dev = 3.4 fixed_size = 1 boll_up = 0 boll_down = 0 boll_mid = 0 parameters = ["boll_window", "boll_dev", "cci_window", "atr_window", "sl_multiplier", "fixed_size"] variables = ["boll_up", "boll_down", "cci_value", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) self.boll_mid = am.sma(self.boll_window) # Use boll mid as stop loss if self.pos == 0: self.buy(self.boll_up, self.fixed_size, True) self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: if bar.close_price <= self.boll_mid: self.sell(bar.close_price - 5, abs(self.pos)) elif self.pos < 0: if bar.close_price >= self.boll_mid: self.cover(bar.close_price + 5, abs(self.pos)) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class DoubleRsiAtr(CtaTemplate): """""" author = "yiran" s_window = 5 l_window = 15 atr_window = 20 atr_multiplier = 0.05 rsi_window = 11 long_threshold_l_window = 50 long_threshold_s_window = 80 exit_return = 0.02 exit_loss = 0.02 exit_return_soft_long = -0.1 exit_loss_soft_long = -0.2 exit_return_soft_short = 0.2 exit_loss_soft_short = 0.1 fixed_size = 1 start_time = time(hour=10) exit_time = time(hour=14, minute=55) long_order_record = [] short_order_record = [] rsi_value_l_window = -9999 rsi_value_s_window = -9999 atr_value = 0 position_hold = 0 long_entered = False short_entered = False parameters = [ 's_window', 'l_window', 'atr_window', 'atr_multiplier', 'exit_return_soft_long', 'exit_loss_soft_long', "rsi_window", 'exit_return_soft_short', 'exit_loss_soft_short', "long_threshold_l_window", "long_threshold_s_window", 'exit_return', 'exit_loss', "fixed_size" ] variables = ["rsi_value_l_window ", "rsi_value_s_window", "ma_trend"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long_l = self.long_threshold_l_window self.rsi_long_s = self.long_threshold_s_window self.rsi_short_l = 100 - self.long_threshold_l_window self.rsi_short_s = 100 - self.long_threshold_s_window self.bg5 = BarGenerator(self.on_bar, self.s_window, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, self.l_window, self.on_15min_bar) self.am15 = ArrayManager() self.long_order_record = [] self.short_order_record = [] self.atr_value_array = np.array([]) self.atr_profit_exit_recorder = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return self.rsi_value_s_window = self.am5.rsi(self.rsi_window) self.atr_value = self.am5.atr(self.atr_window) if self.long_threshold_l_window != -9999: self.long_entered = (self.rsi_value_s_window > self.rsi_long_s) and (self.rsi_value_l_window > self.rsi_long_l) self.short_entered = ( self.rsi_value_s_window < self.rsi_short_s) and ( self.rsi_value_l_window < self.rsi_short_l) else: return if self.start_time <= bar.datetime.time() < self.exit_time: if self.pos == 0: self.position_hold = 0 if self.long_entered: self.buy(bar.close_price + 5, self.fixed_size) self.long_order_record.append(bar.close_price + 5) elif self.short_entered: self.short(bar.close_price - 5, self.fixed_size) self.short_order_record.append(bar.close_price - 5) elif self.pos > 0: self.position_hold += 1 buy_order_price = self.long_order_record[-1] initial_profit_exit_price = buy_order_price * ( 1 + self.exit_return) # 波动变大+持仓周期变长,会使得止盈的点上移 moving_profit_exit_price = buy_order_price * ( 1 + self.exit_return_soft_long ) + self.atr_value * self.atr_multiplier * self.position_hold initial_loss_exit_price = buy_order_price * (1 - self.exit_loss) # 波动变大+持仓周期变长,会使得止损的点上移 moving_loss_exit_price = buy_order_price * ( 1 + self.exit_loss_soft_long ) + self.atr_value * self.atr_multiplier * self.position_hold if initial_profit_exit_price < moving_profit_exit_price: self.atr_profit_exit_recorder.append((1, bar.datetime)) else: self.atr_profit_exit_recorder.append((0, bar.datetime)) if bar.close_price >= max(initial_profit_exit_price, moving_profit_exit_price): self.sell(bar.close_price * 0.99, abs(self.pos)) elif bar.close_price <= max(initial_loss_exit_price, moving_loss_exit_price): self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.position_hold += 1 sell_order_price = self.short_order_record[-1] #初始的盈利要求比较低即空头平仓的价格比较高 initial_profit_exit_price = sell_order_price * ( 1 - self.exit_return) # 随着持仓时间推移和波动率变大,对应盈利方向上的头寸止盈要求变高,即空头平仓价格下移 moving_profit_exit_price = sell_order_price * ( 1 + self.exit_return_soft_short ) - self.atr_value * self.atr_multiplier * self.position_hold initial_loss_exit_price = sell_order_price * (1 + self.exit_loss) # 随着持仓时间推移和波动率变大,对应亏损方向上的头寸的平仓价格上升,即空头平仓价格上升 moving_loss_exit_price = sell_order_price * ( 1 + self.exit_loss_soft_short ) - self.atr_value * self.atr_multiplier * self.position_hold if bar.close_price >= min(initial_loss_exit_price, moving_loss_exit_price): self.cover(bar.close_price * 1.01, abs(self.pos)) elif bar.close_price <= min(initial_profit_exit_price, moving_profit_exit_price): self.cover(bar.close_price * 1.01, abs(self.pos)) # 通过设置合成Bar Data的周期可以使得持仓过夜 elif bar.datetime.time() > self.exit_time: if self.pos > 0: self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.cover(bar.close_price * 1.01, abs(self.pos)) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if not self.am15.inited: return self.rsi_value_l_window = self.am15.rsi(self.rsi_window) def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class CincoStrategyHN(CtaTemplate): """""" author = "Huang Ning" boll_window = 42 boll_dev = 2.0 trailing_long = 0.65 trailing_short = 0.7 atr_window = 10 risk_level = 100 boll_up = 0 boll_down = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "boll_window", "boll_dev", "trailing_long", "trailing_short", "atr_window", "risk_level" ] variables = [ "boll_up", "boll_down", "trading_size", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "atr_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(CincoStrategyHN, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """""" self.write_log("策略初始化") self.load_bar(10) def on_start(self): """""" self.write_log("策略启动") def on_stop(self): """""" self.write_log("策略停止") def on_tick(self, tick: TickData): """""" self.bg.update_tick(tick) def on_bar(self, bar: BarData): """""" self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) boll_width = self.boll_up - self.boll_down if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.trading_size = int(self.risk_level / self.atr_value) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 self.buy(self.boll_up, self.trading_size, stop=True) self.short(self.boll_down, self.trading_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_order(self, order: OrderData): """""" def on_trade(self, trade: TradeData): """""" self.put_event() def on_stop_order(self, stop_order: StopOrder): """""" self.put_event()
class OscillatorDriveStrategy(CtaTemplate): """""" author = "用Python的交易员" boll_window = 41 boll_dev = 2 atr_window = 15 trading_size = 1 risk_level = 50 sl_multiplier = 2.1 dis_open = 5 interval = 25 boll_up = 0 boll_down = 0 cci_value = 0 atr_value = 0 long_stop = 0 short_stop = 0 exit_up = 0 exit_down = 0 parameters = [ "boll_window", "boll_dev", "dis_open", "interval", "atr_window", "sl_multiplier" ] variables = [ "boll_up", "boll_down", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(OscillatorDriveStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.interval, self.on_xmin_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) self.ultosc = am.ultosc() buy_dis = 50 + self.dis_open sell_dis = 50 - self.dis_open self.atr_value = am.atr(self.atr_window) if self.pos == 0: self.trading_size = max(int(self.risk_level / self.atr_value), 1) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.ultosc > buy_dis: self.buy(self.boll_up, self.trading_size, True) elif self.ultosc < sell_dis: self.short(self.boll_down, self.trading_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class Boll_kk_vix_simple_Strategy(CtaTemplate): """ 本策略为反向策略,币本位 Reverse 反向 """ author = "yunya" open_window = 5 xminute_window = 15 com_length = 450 exit_dc_length = 10 fast_sma_length = 45 slow_sma_length = 110 cci_length = 30 cci_exit = 26 sl_multiplier = 8.0 fixed_size = 1 bollkk_ema = 0 bollkk_up = 0 bollkk_down = 0 bollkk_width = 0 cci_vlue = 0 long_stop = 0 short_stop = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 ma_trend = 0 exit_dc_long = 0 exit_dc_short = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "open_window", "xminute_window", "com_length", "fast_sma_length", "slow_sma_length", "cci_length", "cci_exit", "exit_dc_length", "sl_multiplier", "fixed_size", ] variables = [ "bollkk_ema", "bollkk_up", "bollkk_down", "bollkk_width", "cci_vlue", "long_stop", "short_stop", "exit_up", "exit_down", "atr_value", "long_entry", "short_entry", "ma_trend", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_xminute = BarGenerator(on_bar=self.on_bar, window=self.xminute_window, on_window_bar=self.on_xminute_bar, interval=Interval.MINUTE) self.am_xminute = ArrayManager(self.com_length + 10) self.bg = BarGenerator(self.on_bar, self.open_window, self.on_open_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_xminute.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) self.bg_xminute.update_bar(bar) def on_open_bar(self, bar: BarData): """ :param bar: :return: """ # 先使用挂单全撤的粗化订单管理 self.cancel_all() self.am.update_bar(bar) if not self.am_xminute.inited or not self.am.inited: return if self.pos == 0: # 根据布林带宽度动态调整仓位大小 # self.trading_size = max(int(self.risk_level / self.xminute_com_width), 1) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.cci_value > self.cci_exit and self.ma_trend > 0: self.buy(self.bollkk_up, self.fixed_size, True) elif self.cci_value < -self.cci_exit and self.ma_trend < 0: self.short(self.bollkk_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price exit_long_stop = self.intra_trade_high - self.bollkk_width * self.sl_multiplier exit_long_dc = max(exit_long_stop, self.exit_dc_long) self.exit_up = max(exit_long_dc, self.long_stop) self.sell(self.exit_up, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) exit_short_stop = self.intra_trade_low + self.bollkk_width * self.sl_multiplier exit_shout_dc = min(exit_short_stop, self.exit_dc_short) self.exit_down = min(exit_shout_dc, self.short_stop) self.cover(self.exit_down, abs(self.pos), True) self.put_event() self.sync_data() def on_xminute_bar(self, bar: BarData): """ :param bar: :return: """ # x分钟 多策略合合成的通道线 self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return bollkk_ema_value, self.bollkk_up, self.bollkk_down, = self.boll_kk_combination( high=self.am_xminute.high[:-1], close=self.am_xminute.close[:-1], low=self.am_xminute.low[:-1], com_length=self.com_length) # 计算开平信号 self.current_close = self.am_xminute.close[-1] self.last_close = self.am_xminute.close[-2] self.bollkk_ema = bollkk_ema_value[-1] self.bollkk_width = abs(self.bollkk_up - self.bollkk_down) self.cci_value = self.am_xminute.cci(self.cci_length) self.fast_ma = self.am_xminute.sma(self.fast_sma_length) self.slow_ma = self.am_xminute.sma(self.slow_sma_length) if self.fast_ma > self.slow_ma: self.ma_trend = 1 else: self.ma_trend = -1 self.atr_value = self.am_xminute.atr(30) self.exit_dc_short, self.exit_dc_long = self.am_xminute.donchian( self.exit_dc_length) self.sync_data() self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value self.sync_data() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def boll_kk_combination(self, high, close, low, com_length): """ 通过计算收盘价与收盘价均线之间的倍数,来自动调整boll 、kk 的通过宽度 """ # 计算组合均线 bollkk_ema = talib.EMA(close, com_length) # 计算自适布林带 boll_std = talib.STDDEV(close, com_length) boll_dev = abs(close - bollkk_ema) / boll_std boll_up = bollkk_ema + boll_dev * boll_std boll_down = bollkk_ema - boll_dev * boll_std # 计算自适肯特通道 kk_atr = talib.ATR(high, low, close, com_length) kk_dev = abs(close - bollkk_ema) / kk_atr kk_up = bollkk_ema + kk_atr * kk_dev kk_down = bollkk_ema - kk_atr * kk_dev bollkk_up = max(boll_up[-1], kk_up[-1]) bollkk_down = min(boll_down[-1], kk_down[-1]) return bollkk_ema, bollkk_up, bollkk_down,
class BollChannelStrategy(CtaTemplate): """""" author = "用Python的交易员" boll_window = 18 boll_dev = 3.4 cci_window = 10 atr_window = 30 sl_multiplier = 5.2 fixed_size = 1 boll_up = 0 boll_down = 0 cci_value = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = [ "boll_window", "boll_dev", "cci_window", "atr_window", "sl_multiplier", "fixed_size" ] variables = [ "boll_up", "boll_down", "cci_value", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(1) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) self.cci_value = am.cci(self.cci_window) self.atr_value = am.atr(self.atr_window) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.cci_value > 0: self.buy(self.boll_up, self.fixed_size, True) elif self.cci_value < 0: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class GridStockCta_v1(CtaTemplate): """ 1、如果没有仓位,以当前价格买入一个单位 2、获取最后一个成交 价格,计算出卖出价格和买入价格。 3、然后价格高于卖出价,马上挂出miker卖单。 """ author = "yunya" grid_amount = 20 # 网格最大量 grid_usdt_size = 20 # 首次使用多少USDT购买币 grid_usdt_capital = 200 # 网格最多使用的资金量USDT grid_buy_price = 1.0 # 网格距离 grid_sell_price = 1.0 position_inited = False position_proportion = 1.0 # 每次加仓比例 grid_count = 0 cumulative_usdt_volume = 0 buy_benchmark = 0 sell_benchmark = 0 buy_price = 0 sell_price = 0 buy_tick = 0 short_tick = 0 current_volume = 0 sell_fixed_size = 0 price_change = 0 min_volume = 0 len_tick_decimal = 0 parameters = [ "grid_amount", "grid_usdt_size", "grid_usdt_capital", "grid_buy_price", "grid_sell_price", "position_inited", "position_proportion", ] variables = [ "grid_count", "buy_benchmark", "sell_benchmark", "grid_usdt_volume", "cumulative_usdt_volume", "position_inited" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__( cta_engine, strategy_name, vt_symbol, setting, ) self.exchangematerial = ExchangeMaterial.OKEX_MATERIAL self.bg_open = BarGenerator(self.on_bar, 2, self.on_open_bar) self.am_open = ArrayManager() # 计算每次使用资金量 self.cumulative_usdt_volume = 0 self.target_pos = 0 self.grid_usdt_volume = 0 self.vt_orderids = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") contract = self.cta_engine.main_engine.get_contract(self.vt_symbol) self.min_volume = contract.min_volume self.len_tick_decimal = len(str(self.min_volume).split(".")[1]) self.load_bar(1) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_open.update_tick(tick) self.buy_tick = tick.bid_price_1 self.short_tick = tick.ask_price_1 def on_bar(self, bar: BarData): """""" self.bg_open.update_bar(bar) def on_open_bar(self, bar: BarData): """""" self.cancel_all() self.am_open.update_bar(bar) if not self.am_open.inited: return # 判断是否动态加仓 if self.position_inited: if self.position_proportion > 0 and self.grid_count > 0: self.grid_usdt_volume = self.grid_usdt_size * ( 1 + (self.position_proportion / 100) * self.grid_count) else: self.grid_usdt_volume = self.grid_usdt_size self.current_volume = self.grid_usdt_volume / bar.close_price # 判断是否已有成交记录,如果没有成交记录,就买入第一单 if not self.buy_benchmark and not self.sell_benchmark: # self.buy_price = bar.close_price - self.tick_price * self.pay_up vt_orderid = self.buy(self.buy_price, self.current_volume) self.vt_orderids.extend(vt_orderid) # 清空 self.cumulative_usdt_volume = 0 self.grid_count = 0 self.current_volume = 0 else: if bar.close_price < self.buy_benchmark: con1 = self.grid_count < self.grid_amount con2 = self.cumulative_usdt_volume < self.grid_usdt_capital if con1 or con2: # 取四舍五入 self.current_volume = float( format(self.current_volume, f".{self.len_tick_decimal}f")) vt_orderid = self.buy(self.buy_tick, self.current_volume, order_type=OrderType.MakerPostOnly) self.vt_orderids.extend(vt_orderid) else: self.write_log("达到最大仓位!停止加仓!") elif bar.close_price > self.sell_benchmark: # 判断 如果理论(不含手续费)self.pos 比交易所成交反馈回来的量小时,使用交易所反馈回来的量下单,同时把理论值设置为零 if self.pos > self.current_volume * 1.2: self.sell_fixed_size = self.current_volume else: self.sell_fixed_size = self.pos vt_orderid = self.sell(self.sell_price, abs(self.sell_fixed_size), order_type=OrderType.MakerPostOnly) self.vt_orderids.extend(vt_orderid) self.put_event() def on_order(self, order: OrderData): """ 判断是否完全成交,如果成交获取成交数量,计数器加减 移除成交、拒绝、撤单的订单号 """ if order.vt_orderid in self.vt_orderids: if order.status == Status.ALLTRADED: if order.direction == Direction.LONG: self.target_pos = order.traded self.grid_count += 1 self.cumulative_usdt_volume += self.grid_usdt_volume # 买入时,实际得到币量为总买量减手续费 msg = f"开仓,成交量为:{self.target_pos}" self.write_log(msg) self.target_pos = 0 else: self.target_pos = -order.traded self.grid_count -= 1 self.cumulative_usdt_volume -= self.grid_usdt_volume msg = f"平仓,成交量为:{self.target_pos}" self.write_log(msg) self.target_pos = 0 if not order.is_active(): self.vt_orderids.remove(order.vt_orderid) self.sync_data() def on_trade(self, trade: TradeData): """ 获取交易价格做为基准线 """ if trade.direction == Direction.LONG: self.price_change = trade.price # 成交最高价 msg = f"开仓,成交价格为:{self.price_change}" self.write_log(msg) else: self.price_change = trade.price msg = f"平仓,成交价格为:{self.price_change}" self.write_log(msg) # 计算当前网格买入价格和卖出价格 self.buy_benchmark = self.price_change * (1 - self.grid_buy_price / 100) self.sell_benchmark = self.price_change * (1 + self.grid_sell_price / 100) msg = f"下个网格加仓价格线为:{self.buy_benchmark},平仓位价格线为: {self.sell_benchmark}" self.write_log(msg) self.sync_data() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class GridStockCtaStrategy(CtaTemplate): """ 策略逻辑: 1、网格数量: 21 ,网格总限量资金: 3000 2、网格操作区间: 10% 3、网格跟踪指标 : 首次成交价格 4、网格上限: 网格跟踪指标 * (1 + 网格操作区间) 5、网格下限: 网格跟踪指标 * ( 1 - 网格操作区间) 6、网格步进 :( 网格上限 - 网格下限 ) / 网格数量 7、仓位单元 : 网格总限量 / 网格数量 8、网格启动、停止开关:振幅超过百分比例,网格暂时停止,等待8小时后重新启动 """ author = "yunya" open_window = 2 xminute_window = 5 xhour_window = 1 position_proportion = 1.0 # 每次加仓比例 grid_amount = 20 # 网格最大量 grid_usdt_size = 20 # 首次使用多少USDT购买币 grid_usdt_capital = 200 # 网格最多使用的资金量USDT grid_buy_price = 1.0 # 网格距离 grid_sell_price = 1.0 pay_up = 2 # 偏移pricetick buy_callback = 0.5 # 买入回调幅度 sell_callback = 0.5 # 卖出回调幅度 grid_amplitude = 5.0 # 振幅超过比例停止策略8小时 stop_time = 8 # 策略暂停时间 price_change = 0 # 网格基准线(每次成交价) current_volume = 0 # 当前下单币的数量 target_pos = 0 buy_benchmark = 0 sell_benchmark = 0 buy_price = 0 # 买入成交价 sell_price = 0 # 平仓成交价 grid_usdt_volume = 0 cumulative_usdt_volume = 0 # 累计使用金额 grid_count = 0 # 网格次数 intra_trade_high = 0 # 最高价 trade_high = 0 intra_trade_low = 0 # 最低价 trade_low = 0 amplitude = 0 # 振幅 tick_price = 0 time_stop = 0 # 计算得到的重新启动时间 buy_fixed_size = 0 sell_fixed_size = 0 len_tick_decimal = 0 # 获取当前币种盘口最小下单量 amplitude_inited = False # 振幅标签 first_time_inited = False # 判断是否是首次启动,如果是首次启动,清空初始化数据 min_volume = 0 parameters = [ "open_window", "xminute_window", "xhour_window", "position_proportion", "grid_amount", "grid_usdt_size", "grid_usdt_capital", "grid_buy_price", "grid_sell_price", "pay_up", "buy_callback", "sell_callback", "grid_amplitude", "stop_time", ] variables = [ "price_change", "current_volume", "buy_benchmark", "sell_benchmark", "buy_price", "sell_price", "grid_usdt_volume", "cumulative_usdt_volume", "grid_count", "intra_trade_high", "trade_high", "intra_trade_low", "trade_low", "amplitude", "amplitude_inited", "first_time_inited", "min_volume" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting,) self.exchangematerial = ExchangeMaterial.OKEX_MATERIAL self.bg_open = BarGenerator(self.on_bar,self.open_window,self.on_open_bar) self.am_open = ArrayManager() self.bg_minute = BarGenerator(self.on_bar,self.xminute_window,self.on_mintue_bar) self.am_minute = ArrayManager() self.bg_xhour = BarGenerator(self.on_bar, self.xhour_window, self.on_xhour_bar, Interval.HOUR) self.am_xhour = ArrayManager() self.ACTIVE_STATUSES = set([Status.SUBMITTING, Status.NOTTRADED]) # 计算每次使用资金量 self.cumulative_usdt_volume = 0 self.target_pos = 0 self.grid_usdt_volume = 0 self.amplitude = 0 self.tick_price = 0 self.engine_type = self.get_engine_type() #测试还是实盘 self.vt_orderids = [] self.buy_vt_orderid = 0 self.sell_vt_orderid = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") contract = self.on_get_contract() self.min_volume = contract.min_volume self.len_tick_decimal = len(str(self.min_volume).split(".")[1]) self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") if not self.first_time_inited: self.grid_count = 0 self.current_volume = 0 self.cumulative_usdt_volume = 0 self.first_time_inited = True def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_open.update_tick(tick) def on_bar(self, bar: BarData): """""" self.bg_open.update_bar(bar) self.bg_minute.update_bar(bar) self.bg_xhour.update_bar(bar) def on_open_bar(self, bar: BarData): """""" self.am_open.update_bar(bar) if not self.am_open.inited: return if self.buy_vt_orderid in self.vt_orderids: self.write_log(f"开多订单号:{self.buy_vt_orderid}" + "\n") get_order_orderid = self.on_get_order(self.buy_vt_orderid) self.write_log(f"查询挂单:{get_order_orderid}" + "\n") if get_order_orderid.status in self.ACTIVE_STATUSES: self.cancel_order(self.buy_vt_orderid) self.buy_vt_orderid = 0 elif self.sell_vt_orderid in self.vt_orderids: self.write_log(f"平多订单号:{self.sell_vt_orderid}" + "\n") get_order_orderid = self.on_get_order(self.sell_vt_orderid) self.write_log(f"查询挂单:{get_order_orderid}" + "\n") if get_order_orderid.status in self.ACTIVE_STATUSES: self.cancel_order(self.sell_vt_orderid) self.sell_vt_orderid = 0 # 判断 休眠时间 if self.amplitude_inited: if bar.datetime > self.time_stop: self.amplitude_inited = False return # 根据网格次数加仓 , 根据USDT量和价格计算出可购买的币数量 if self.position_proportion > 0 and self.grid_count > 0: self.grid_usdt_volume = self.grid_usdt_size * (1 + (self.position_proportion / 100) * self.grid_count) else: self.grid_usdt_volume = self.grid_usdt_size self.current_volume = self.grid_usdt_volume / bar.close_price if not self.pos or self.pos < self.min_volume: """ 1、如果空仓,以当前价格买入一份做为底仓 2、总网格次数减一 """ self.buy_price = bar.close_price - self.tick_price * self.pay_up # 取四舍五入 self.current_volume = float(format(self.current_volume, f".{self.len_tick_decimal}f")) USDT = bar.close_price * self.min_volume if self.current_volume < self.min_volume: msg = f"当前下单小于:{self.vt_symbol} 最小下单最,请重新设置最小下单量!最下小量为:{self.min_volume},需要约:{USDT}枚USDT" self.write_log(msg) return self.buy_vt_orderid = self.buy(self.buy_price, self.current_volume) # 把挂单信息添加到列表末尾 self.vt_orderids.extend(self.buy_vt_orderid) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price # 清空 self.cumulative_usdt_volume = 0 self.grid_count = 0 self.current_volume = 0 else: if bar.close_price < self.buy_benchmark: """ 当前收盘价低于下个网格买入价格时,判断买入时机: 1、价格在上次买入后,中间没有卖出的过程, 2、 """ if self.cumulative_usdt_volume < self.grid_usdt_capital: """ 买在最低位 """ self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.trade_low = self.intra_trade_low * (1 + self.buy_callback / 100) if self.trade_low < self.buy_benchmark: self.buy_price = self.trade_low else: self.buy_price = self.buy_benchmark # 取四舍五入 self.current_volume = float(format(self.current_volume, f".{self.len_tick_decimal}f")) self.buy_vt_orderid = self.buy(self.buy_price, self.current_volume) self.vt_orderids.extend(self.buy_vt_orderid) elif bar.close_price > self.sell_benchmark: if self.pos > 0: """ 卖在最高位 """ self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.trade_high = self.intra_trade_high * (1 - self.sell_callback / 100) if self.trade_high > self.sell_benchmark: self.sell_price = self.trade_high else: self.sell_price = self.sell_benchmark # 判断 如果理论(不含手续费)self.pos 比交易所成交反馈回来的量小时,使用交易所反馈回来的量下单,同时把理论值设置为零 if self.pos > self.current_volume * 1.2: self.sell_fixed_size = self.current_volume else: self.sell_fixed_size = self.pos self.sell_vt_orderid = self.sell(self.sell_price, abs(self.sell_fixed_size)) self.vt_orderids.extend(self.sell_vt_orderid) # 更新图形界面 self.put_event() def on_mintue_bar(self, bar: BarData): """ :return: """ self.am_minute.update_bar(bar) if not self.am_minute.inited: return # 计算振幅 self.amplitude = (bar.high_price - bar.low_price) / bar.high_price # 如果振幅超过指定值,策略撤掉所有挂单,并且进入休眠状态 if self.amplitude > self.grid_amplitude / 100: self.amplitude_inited = True self.time_stop = bar.datetime + datetime.timedelta(hours=self.stop_time) self.write_log(f"当前市场波动较大," f"振幅为:{self.amplitude},超过设置值,策略进入休眠," f"休眠到:{self.time_stop.strftime('%Y-%m-%d %H:%M:%S')}时重新启动策略") def on_xhour_bar(self, bar: BarData): """ :return: """ self.am_xhour.update_bar(bar) if not self.am_xhour.inited: return pass def on_order(self, order: OrderData): """ 判断是否完全成交,如果成交获取成交数量,计数器加减 移除成交、拒绝、撤单的订单号 """ if order.vt_orderid in self.vt_orderids: if order.status == Status.ALLTRADED: if order.direction == Direction.LONG: if self.buy_vt_orderid == order.vt_orderid: self.target_pos = order.traded self.grid_count += 1 self.cumulative_usdt_volume += self.grid_usdt_volume # 买入时,实际得到币量为总买量减手续费 msg = f"开仓,成交量为:{self.target_pos}" self.write_log(msg) self.target_pos = 0 self.buy_vt_orderid = 0 else: if self.sell_vt_orderid == order.vt_orderid: self.target_pos = -order.traded self.grid_count -= 1 self.cumulative_usdt_volume -= self.grid_usdt_volume msg = f"平仓,成交量为:{self.target_pos}" self.write_log(msg) self.target_pos = 0 self.sell_vt_orderid = 0 if not order.is_active(): self.vt_orderids.remove(order.vt_orderid) self.sync_data() def on_trade(self, trade: TradeData): """ 获取交易价格做为基准线 """ if trade.direction == Direction.LONG: self.price_change = trade.price # 成交最高价 msg = f"开仓,成交价格为:{self.price_change}" self.write_log(msg) else: self.price_change = trade.price msg = f"开仓,成交价格为:{self.price_change}" self.write_log(msg) # 计算当前网格买入价格和卖出价格 self.buy_benchmark = self.price_change * (1 - self.grid_buy_price / 100) self.sell_benchmark = self.price_change * (1 + self.grid_sell_price / 100) msg = f"下个网格加仓价格线为:{self.buy_benchmark},平仓位价格线为: {self.sell_benchmark}" self.write_log(msg) self.sync_data() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def on_get_contract(self): """ :return: """ return self.cta_engine.main_engine.get_contract(self.vt_symbol) def on_get_order(self,vt_orderid): """ 查询挂单数据 :return: """ return self.cta_engine.main_engine.get_order(vt_orderid) def on_get_trade(self,vt_orderid): """ 查询成交数据 :return: """ return self.cta_engine.main_engine.get_trade(vt_orderid)
class KingKeltnerStrategy(CtaTemplate): """""" author = "用Python的交易员" kk_length = 11 kk_dev = 1.6 trailing_percent = 0.8 fixed_size = 1 kk_up = 0 kk_down = 0 intra_trade_high = 0 intra_trade_low = 0 long_vt_orderids = [] short_vt_orderids = [] vt_orderids = [] parameters = ["kk_length", "kk_dev", "trailing_percent", "fixed_size"] variables = ["kk_up", "kk_down"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager(50) self.long_vt_orderids = [] self.short_vt_orderids = [] self.vt_orderids = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") #if self.get_engine_type() == EngineType.LIVE: #self.fo = open("C:\Study\MyDiary\VNPY_TSMyo_Log\VNPY_Log.txt", "a") #self.write_log("开启本地log记录文件") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") #if self.get_engine_type() == EngineType.LIVE and self.fo: #self.fo.close() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" # 把本地维护的所有委托单撤单 ''' for orderid in self.vt_orderids: self.cancel_order(orderid) self.vt_orderids.clear() ''' self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.kk_up, self.kk_down = am.keltner(self.kk_length, self.kk_dev) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price # oco单,二选一触发,同时挂上下轨突破的停止单,一个触发另一个立刻取消 # 经常用于防止在bar中波动过大,上下轨同时触发 self.send_oco_order(self.kk_up, self.kk_down, self.fixed_size) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price vt_orderids = self.sell( self.intra_trade_high * (1 - self.trailing_percent / 100), abs(self.pos), True) #self.vt_orderids.extend(vt_orderids) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) vt_orderids = self.cover( self.intra_trade_low * (1 + self.trailing_percent / 100), abs(self.pos), True) #self.vt_orderids.extend(vt_orderids) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ #if self.get_engine_type() == EngineType.LIVE and self.fo: #self.fo.write(str(datetime.now())+ '\t' + str(order)+'\n') # 配合实现OCO挂单 def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ ''' if self.pos != 0: if self.pos > 0: for short_orderid in self.short_vt_orderids: self.cancel_order(short_orderid) elif self.pos < 0: for buy_orderid in self.long_vt_orderids: self.cancel_order(buy_orderid) for orderid in (self.long_vt_orderids + self.short_vt_orderids): if orderid in self.vt_orderids: self.vt_orderids.remove(orderid) ''' #self.cancel_all() self.put_event() #if self.get_engine_type() == EngineType.LIVE and self.fo: #self.fo.write(str(datetime.now())+ '\t' + str(trade)+'\n') def send_oco_order(self, buy_price, short_price, volume): """""" self.long_vt_orderids = self.buy(buy_price, volume, True) self.short_vt_orderids = self.short(short_price, volume, True) #self.vt_orderids.extend(self.long_vt_orderids) #self.vt_orderids.extend(self.short_vt_orderids) def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class KTrendStrategy(CtaTemplatePatch): ''' 简单快速趋势策略: 开仓策略:采取模拟概率积分的方式,即 " 中长趋势线 + 短期趋势线 + 短期的日涨跌幅比例 + 日内分时高低差值" 组成 a. 中长线趋 long_trend_ma(>=5d): 可以选择多条,采取“与“的方式,即所有选择线的趋势都是一致的,才认为趋势确定。 b. 短期趋势 short_trend_ma(<=3d): 同中长线,可以选择多条,采取”与“的方式来确定。 c. 短期涨跌幅比例(short_rate):只有当短期内涨跌幅超过一个比例,才认为短期确定,采用累加的方式,或最大值的方式。 d. 概率积分:针对前面3个条件,可以进行概率假设取值,并进行累加出总的假设概率(<1.0), 即 long_trend_ma *K_lt + short_trend_ma*K_st + short_rate*K_sr 。 e. 日内分时高低差值(gap_rate): 当时开仓时,也不要追高/追低,要根据日内分时的最高值或最低值一定的差值才进行开仓。 f. 开仓的数量以1手为限定 止损策略:采取偏离开仓价格限额的方式或最大损失值的原则,即设定一定的限额,在开仓时都必须同时设置 a. 设定固定的平仓的价格损失比例 b. 转换为对应的价格,再加一定的滑点值,以促进及时成交; 止赢策略:当赢利超过一定比例或固定价格偏离值时,即触发止赢策略,具体操作可复用止损策略。 风控策略: 针对如下的风险要进行风险控制 a. 针对行情巨大的波动,如果损失已经超过了限额,但没能成交,要能动态调整设定的价格,以便保证成交; b. 发送给交易所委托,跨立易日后,这些数据可能被清除,需要开盘时重新发起委托。 ''' # 策略作者 author = "*****@*****.**" # 定义参数 order_duo_kong = "D&K" # 交易哪个方向向,D:只开多仓,K: 只开空仓,D&K:都可以开 bar_data_minutes = 60 # 控制生成BAR DATA的分钟数 long_trend_ma_num = 8 # 长线趋势线分别为5d, 10d, 20d, 40d, 80d,...., 为2表示选择5d,10d short_trend_ma_num = 8 # 短期趋势线别为2d, 3d. 为2表示选择1d, 2d. short_rate = 0.01 # 表示价格要涨跌幅要3%以上 k_lt = 0.4 # 表示长线趋势在总的假设概率中占比为40% k_st = 0.4 # 表示短线趋势在总的假设概率中占比为40% K_sr = 0.2 # 表示短线波动幅度在总的假设概率中占比为20% duo_kong_probability_threshold = 0.55 # 表示只有总的概超过此值后方可进行开仓 kai_probability_threshold = 0.7 # 表示只有总的概超过此值后方可进行开仓 kai_ping_price_allowance = 10 # 为了即时达成交易,相对于在当前价的基础进行对应加减,以快速的进行成交 gap_rate = 0.005 # 表示日内的开仓价格需要与日内最高或日内最低偏离1% ping_cang_rate = 0.01 # 移动止赢止损平仓的波动控制在+/-%左右 kai_num_per_order = 1 # 每次交易的开平手数 # 定义变量 # 支持中长线趋势的移动均线 # 支持短线趋势的移动均线 # 当前交易日的最高、最低价格, 用于配合gap_rate的判断 cur_day_hour = -1 # 当前交易日的小时数,用于在没有tick数据的判断当前的交易日 cur_day_high_price = 0.0 # 当前交易日的最高价格 cur_day_low_price = sys.float_info.max # 当前交易日的最低价格 trade_price = 0.0 # 持仓止赢的移动价格 # 添加参数和变量名到对应的列表 parameters = [ "order_duo_kong", "bar_data_minutes", "long_trend_ma_num", "short_trend_ma_num", "short_rate", "k_lt", "k_st", "K_sr", "duo_kong_probability_threshold", "kai_probability_threshold", "kai_ping_price_allowance", "gap_rate", "kai_num_per_order", "ping_cang_rate" ] variables = [ "trade_price", "cur_day_high_price", "cur_day_low_price", "cur_day_hour" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): ''' ''' super(KTrendStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) # K线合成器:从Tick合成分钟K线用 self.bg = BarGenerator(self.on_bar, self.bar_data_minutes, self.on_window_bar, Interval.MINUTE) # 时间序列容器:计算技术指标用 self.am = ArrayManager() def on_bar(self, bar: BarData): ''' 通过该函数收到新的1分钟K线推送 ''' # super().on_bar(bar) self.bg.update_bar(bar) #晚上8点夜盘前当前天,从夜盘开始算新的一天 if ((self.cur_day_hour == -1) or ((self.cur_day_hour > 8 and self.cur_day_hour < 20) and bar.datetime.hour > 20)): self.cur_day_high_price = 0.0 self.cur_day_low_price = sys.float_info.max #获取当前交易日的最高价和最低价 self.cur_day_hour = bar.datetime.hour self.cur_day_high_price = max(self.cur_day_high_price, bar.high_price) self.cur_day_low_price = min(self.cur_day_low_price, bar.low_price) # # if(self.pos != 0): # # 平仓分析 # self.ping_cang_analyse_bar(bar) # Write Log if (datetime.datetime.now().minute % 5 == 0): now = time.strftime('%Y-%m-%d %H:%M:%S') msg = now + " 收到1分钟K线推送" self.write_log(msg) msg = "持仓数:" + str(self.pos) + " cur_day_hour:" + str( self.cur_day_hour) + " high price:" + str( self.cur_day_high_price) + " low price:" + str( self.cur_day_low_price) self.write_log(msg) # 同步变量到硬盘 sync_data data self.sync_data() self.put_event() def on_window_bar(self, bar: BarData): ''' 收到指定的WINDOW BAR数据 ''' self.write_log("收到指定Windows的BARDATA数据") #print(str(sys._getframe().f_lineno)+" on_bar_1d:") # 清空未成交委托:为了防止之前下的单子在上一个Window Bar没有成交,但是下一个Window Bar可能已经调整了价格, # 保证策略在当前这Window Bar开始时的整个状态是清晰和唯一的。 self.cancel_all() am = self.am # 更新K线到时间序列容器中 am.update_bar(bar) # 若缓存的K线数量尚不够计算技术指标,则直接返回 if not am.inited: return if (self.pos == 0): # 开仓分析 self.kai_cang_analyse(bar) #else: # 平仓分析 # self.ping_cang_analyse(bar) # 更新 self.put_event() pass def trend_maker(self, ma_list): ''' 复用此函数来判断一组均线的走势, 头:DUO, 空:KONG, 非头空:NULL. ''' trend_list = [] # 保存趋势判断,‘DUO’: 多头,'KONG': 空头, "NULL" : 非多非空 for cur_lt in ma_list: # cur_lt_trend = [] for i in range(len(cur_lt) - 1): if (not math.isnan(cur_lt[i])) and (not math.isnan( cur_lt[i + 1])): if (cur_lt[i + 1] > cur_lt[i]): cur_lt_trend.append("DUO") elif (cur_lt[i + 1] < cur_lt[i]): cur_lt_trend.append("KONG") else: cur_lt_trend.append("NULL") duo_count = cur_lt_trend.count("DUO") kong_count = cur_lt_trend.count("KONG") null_count = cur_lt_trend.count("NULL") sub_count = duo_count + kong_count + null_count #print("[trend_maker]]cur_lt count - DUO: ", duo_count, "KONG: ", kong_count, "NULL: ", null_count) if ((duo_count) / sub_count > self.duo_kong_probability_threshold ): # 多头方向的值大于一定的比例, 可认为是多头 trend_list.append('DUO') elif ( (kong_count) / sub_count > self.duo_kong_probability_threshold ): # 空头方向的值大于一定的比例, 可认为是空头 trend_list.append('KONG') else: trend_list.append('NULL') # 否则认为是振荡 return trend_list def kai_cang_order(self, buy_or_short, price): ''' 开仓操作,买多或卖空 ''' if (buy_or_short): # 开多仓 self.write_log(" 开多仓") self.buy(price, self.kai_num_per_order) #print("[Kai Cang] Duo...") else: # 开空仓 self.write_log(" 开空仓") self.short(price, self.kai_num_per_order) #print("[Kai Cang] Kong...") def kai_cang_analyse(self, bar: BarData): ''' 是否开仓的策略分析, 整个策略的主要行为 ''' am = self.am # 计算各均线 # 计算中长期均线 lt_ma_10 = am.sma(10, array=True) lt_ma_20 = am.sma(20, array=True) lt_ma_30 = am.sma(30, array=True) lt_ma_40 = am.sma(40, array=True) lt_ma_50 = am.sma(50, array=True) lt_ma_60 = am.sma(60, array=True) lt_ma_70 = am.sma(70, array=True) lt_ma_80 = am.sma(80, array=True) lt_ma_90 = am.sma(90, array=True) # 计算短期均线 st_ma_2 = am.sma(2, array=True) st_ma_3 = am.sma(3, array=True) st_ma_4 = am.sma(4, array=True) st_ma_5 = am.sma(5, array=True) st_ma_6 = am.sma(6, array=True) st_ma_7 = am.sma(7, array=True) st_ma_8 = am.sma(8, array=True) st_ma_9 = am.sma(9, array=True) # 中长线趋势判断 # lt_list = [ lt_ma_10, lt_ma_20, lt_ma_30, lt_ma_40, lt_ma_50, lt_ma_60, lt_ma_70, lt_ma_80, lt_ma_90 ] lt_list = lt_list[0:self.long_trend_ma_num] # 只关注部分中长期趋势 # #print(str(sys._getframe().f_lineno)+" long_trend_ma_num:", len(lt_list)) # lt_trend = self.trend_maker(lt_list) lt_probability = [] # 保存多,空,NULL的比例 duo_count = lt_trend.count("DUO") kong_count = lt_trend.count("KONG") null_count = lt_trend.count("NULL") sub_count = duo_count + kong_count + null_count lt_probability.append(duo_count / sub_count) # 分别计算多头所占的比例 lt_probability.append(kong_count / sub_count) # 分别计算空头所占的比例 lt_probability.append(null_count / sub_count) # 分别计算非多非空,NULL所占的比例 # #print(str(sys._getframe().f_lineno)+" lt_probability Count:", duo_count, ", ", kong_count, ", ", null_count) #print(str(sys._getframe().f_lineno)+" lt_probability DUO:", lt_probability[0], ", ", lt_probability[1], ", ", lt_probability[2]) # 短线趋势判断 st_list = [ st_ma_2, st_ma_3, st_ma_4, st_ma_5, st_ma_6, st_ma_7, st_ma_8, st_ma_9 ] st_list = lt_list[0:self.short_trend_ma_num] # 只关注部分短期趋势 # #print(str(sys._getframe().f_lineno)+" short_trend_ma_num:", len(st_list)) # st_trend = self.trend_maker(st_list) st_probability = [] # 保存多,空,NULL的比例 duo_count = st_trend.count("DUO") kong_count = st_trend.count("KONG") null_count = st_trend.count("NULL") sub_count = duo_count + kong_count + null_count st_probability.append(duo_count / sub_count) # 分别计算多头所占的比例 st_probability.append(kong_count / sub_count) # 分别计算空头所占的比例 st_probability.append(null_count / sub_count) # 分别计算非多非空,NULL所占的比例 #print(str(sys._getframe().f_lineno)+" st_probability Count:", duo_count, ", ", kong_count, ", ", null_count) #print(str(sys._getframe().f_lineno)+" st_probability :", lt_probability[0], ", ", lt_probability[1], ", ", lt_probability[2]) # 短期涨跌幅比例(short rate: sr_ma_rate) if (len(st_list) > 1): sr_ma_rate = (st_list[-1][-1] - st_list[0][-1]) / st_list[0][-1] # 累计涨跌值 else: sr_ma_rate = (st_list[0][-1] - st_list[0][-2]) / st_list[0][-2] #print(str(sys._getframe().f_lineno)+" sr_ma_rate:", sr_ma_rate, ",short_rate:",self.short_rate) sr_ma_probability = sr_ma_rate / self.short_rate # 保存幅度的比例 duo_sr_probability = 0.0 kong_sr_probability = 0.0 if (sr_ma_probability > 0): if (sr_ma_probability >= 1.0): duo_sr_probability = 1.0 else: duo_sr_probability = sr_ma_probability else: if (sr_ma_probability <= -1.0): kong_sr_probability = 1.0 else: kong_sr_probability = abs(sr_ma_probability) #print(str(sys._getframe().f_lineno)+" sr_ma_probability:", sr_ma_probability) # 概率积分:针对前面3个条件,可以进行概率假设取值,并进行累加出总的假设概率 total_duo_probability = 0.0 total_kong_probability = 0.0 total_duo_probability = self.k_lt * lt_probability[ 0] + self.k_st * st_probability[ 0] + self.K_sr * duo_sr_probability # 多头的概率 total_kong_probability = self.k_lt * lt_probability[ 1] + self.k_st * st_probability[ 1] + self.K_sr * kong_sr_probability # 空头的概率 #print("Probability - DUO: ", total_duo_probability, "KONG: ", total_kong_probability, " threshold:",self.kai_probability_threshold) if ((self.order_duo_kong.upper() == "D" or self.order_duo_kong.upper() == "D&K") and (total_duo_probability > self.kai_probability_threshold)): #认为是多头,要进行多头操作 #print("DUO: high = ", self.cur_day_high_price, " close= ", bar.close_price, " Gap= ", self.gap_rate, " Rate= ",((self.cur_day_high_price - bar.close_price) /bar.close_price)) if (((self.cur_day_high_price - bar.close_price) / bar.close_price) >= self.gap_rate): price = bar.close_price + self.kai_ping_price_allowance self.kai_cang_order(True, price) #print("Kang DUO, price=",price) elif ((self.order_duo_kong.upper() == "K" or self.order_duo_kong.upper() == "D&K") and (total_kong_probability > self.kai_probability_threshold)): #认为是空头,要进行空头操作 #print("KONG: low = ", self.cur_day_low_price, " close= ", bar.close_price, " Gap= ", self.gap_rate, " Rate= ",((self.cur_day_low_price - bar.close_price) /bar.close_price)) if (((bar.close_price - self.cur_day_low_price) / bar.close_price) >= self.gap_rate): price = bar.close_price - self.kai_ping_price_allowance self.kai_cang_order(False, price) #print("Kang KONG, price=",price) pass def ping_cang_analyse_bar(self, bar: BarData): if self.getWinPips() > 30: self.clearOrder() pass
class DynamicBreakOut2Strategy(CtaTemplate): """基于布林通道的交易策略""" className = 'DynamicBreakOut2Strategy' author = u'ForwardCapital' # 策略参数 lookBackDays = 20 # devDays = 30 # 计算标准差时间窗口 initDays = 10 # 初始化数据所用的天数 fixedSize = 1 # 每次交易的数量 xMinBar = 15 ATR_N = 2 # 策略变量 ATR = 0 # 布林带中轨 entryUp = 0 # 开仓上轨 entryDown = 0 # 开仓下轨 exitUp = 0 # 平仓上轨 exitDown = 0 # 平仓上轨 shortEntry = 0 longEntry = 0 shortExit = 0 longExit = 0 orderList = [] # 保存委托代码的列表 buyOrderID = None sellOrderID = None shortOrderID = None coverOrderID = None minute = None timeFuncTurn = False # 参数列表,保存了参数的名称 paramList = [ 'className', 'author', 'vtSymbol', "fixedSize", "xMinBar", "ATR_N" ] # 变量列表,保存了变量的名称 varList = [] # 同步列表 syncList = [ 'pos', 'sellOrderID', 'coverOrderID', 'shortOrderID', 'buyOrderID', 'longExit', 'shortExit', 'orderList' ] #---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): """Constructor""" super(DynamicBreakOut2Strategy, self).__init__(ctaEngine, setting) self.bg = BarGenerator(self.on_bar, self.xMinBar, self.onFiveBar) self.am = ArrayManager(60) # self.ctaEngine.eventEngine.register(EVENT_TIMER, self.onTimeFunc) #---------------------------------------------------------------------- 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.bg.update_tick(tick) #---------------------------------------------------------------------- def on_bar(self, bar): """收到Bar推送(必须由用户继承实现)""" self.bg.update_bar(bar) if not self.am.inited: return # 只发平仓单,各指标已在bg.updateBar()函数内完成 if self.pos > 0: self.longExit = self.exitUp self.sellOrderID = self.sell(self.longExit, self.fixedSize, True) # if not self.longExit: # self.longExit = self.exitUp # if self.sellOrderID: # self.cancelOrder(self.sellOrderID) # else: # self.cancelAll() # self.sellOrderID = self.sell(self.longExit, self.fixedSize, True) # print u'None sellOrderID###多头平仓,单号:%s' % self.sellOrderID # self.sellOrderID = self.orderIDConvert(self.sellOrderID) # else: # if self.longExit != self.exitUp: # self.longExit = self.exitUp # self.cancelOrder(self.sellOrderID) elif self.pos < 0: self.shortExit = self.exitDown self.coverOrderID = self.cover(self.shortExit, self.fixedSize, True) # if not self.shortExit: # self.shortExit = self.exitDown # if self.coverOrderID: # self.cancelOrder(self.coverOrderID) # else: # self.cancelAll() # self.coverOrderID = self.cover(self.shortExit, self.fixedSize, True) # print u'None coverOrderID###空头平仓,单号:%s' % self.coverOrderID # self.coverOrderID = self.orderIDConvert(self.coverOrderID) # else: # if self.shortExit != self.exitDown: # self.shortExit = self.exitDown # self.cancelOrder(self.coverOrderID) #---------------------------------------------------------------------- def orderIDConvert(self, orderList): if not orderList: return [] else: return orderList[0] #---------------------------------------------------------------------- def onFiveBar(self, bar, lastTick): """收到5分钟K线""" # 保存K线数据 self.am.update_bar(bar) if not self.am.inited: return # 计算指标数值 volatilityArray = talib.STDDEV(self.am.close, timeperiod=self.devDays) self.lookBackDays = int( round(volatilityArray[-1] / volatilityArray[-2] * self.lookBackDays)) self.lookBackDays = min(self.lookBackDays, 55) self.lookBackDays = max(self.lookBackDays, 20) bBands = talib.BBANDS(self.am.close, timeperiod=self.lookBackDays) self.ATR = talib.ATR(self.am.high, self.am.low, self.am.close, self.lookBackDays)[-1] MidLine = bBands[1][-1] UpBand = bBands[0][-1] DnBand = bBands[2][-1] self.entryUp = max(max(self.am.high[-self.lookBackDays:]), UpBand) self.entryDown = min(min(self.am.low[-self.lookBackDays:]), DnBand) self.exitUp = max(MidLine, self.entryUp - self.ATR_N * self.ATR) self.exitDown = min(MidLine, self.entryDown + self.ATR_N * self.ATR) print(self.entryUp, self.entryDown) print(self.exitUp, self.exitDown) # 判断是否进行交易,只发开仓单 if not self.buyOrderID or self.buyOrderID in self.orderList: if self.pos == 0: if not self.longEntry: # if (self.entryUp-self.entryDown)/self.entryUp < 0.006: # print u'%s 高低点太窄,放弃交易!' % self.vtSymbol # return self.longEntry = self.entryUp self.buyOrderID = self.buy(self.longEntry, self.fixedSize, True) self.buyOrderID = self.orderIDConvert(self.buyOrderID) self.orderList.append(self.buyOrderID) elif self.longEntry != self.entryUp: self.cancel_order(self.buyOrderID) # if (self.entryUp-self.entryDown)/self.entryUp < 0.006: # print u'%s 高低点太窄,放弃交易!' % self.vtSymbol # return self.longEntry = self.entryUp self.buyOrderID = self.buy(self.longEntry, self.fixedSize, True) self.buyOrderID = self.orderIDConvert(self.buyOrderID) self.orderList.append(self.buyOrderID) if not self.shortOrderID or self.shortOrderID in self.orderList: if self.pos == 0: if not self.shortEntry: # if (self.entryUp-self.entryDown)/self.entryUp < 0.006: # print u'%s 高低点太窄,放弃交易!' % self.vtSymbol # return self.shortEntry = self.entryDown self.shortOrderID = self.short(self.shortEntry, self.fixedSize, True) self.shortOrderID = self.orderIDConvert(self.shortOrderID) self.orderList.append(self.shortOrderID) elif self.shortEntry != self.entryDown: self.cancel_order(self.shortOrderID) # if (self.entryUp-self.entryDown)/self.entryUp < 0.006: # print u'%s 高低点太窄,放弃交易!' % self.vtSymbol # return self.shortEntry = self.entryDown self.shortOrderID = self.short(self.shortEntry, self.fixedSize, True) self.shortOrderID = self.orderIDConvert(self.shortOrderID) self.orderList.append(self.shortOrderID) # 发出状态更新事件 # self.put_event() #---------------------------------------------------------------------- def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" # print u'委托变化推送:%s' % order.__dict__ # if self.buyOrderID: # if order.orderID == self.buyOrderID.split('.')[1]: # if order.status == STATUS_CANCELLED: # self.orderList.remove(self.buyOrderID) # if self.shortOrderID: # if order.orderID == self.shortOrderID.split('.')[1]: # if order.status == STATUS_CANCELLED: # self.orderList.remove(self.shortOrderID) # if self.sellOrderID: # if order.orderID == self.sellOrderID.split('.')[1]: # if order.status == STATUS_CANCELLED: # self.sellOrderID = self.sell(self.longExit, self.fixedSize, False) # print u'###多头平仓,单号:%s' % self.sellOrderID # self.sellOrderID = self.orderIDConvert(self.sellOrderID) # if self.coverOrderID: # if order.orderID == self.coverOrderID.split('.')[1]: # if order.status == STATUS_CANCELLED: # self.coverOrderID = self.cover(self.shortExit, self.fixedSize, False) # print u'###空头平仓,单号:%s' % self.coverOrderID # self.coverOrderID = self.orderIDConvert(self.coverOrderID) if order.offset in [ Offset.CLOSE, Offset.CLOSETODAY, Offset.CLOSEYESTERDAY ]: if order.status == Status.ALLTRADED: self.buyOrderID = None self.shortOrderID = None self.longExit = 0 self.shortExit = 0 pass #---------------------------------------------------------------------- def on_trade(self, trade): """收到成交推送(必须由用户继承实现)""" # print u'成交推送:%s' % trade.__dict__ # if self.buyOrderID: # if trade.tradeID == self.buyOrderID.split('.')[1]: # self.orderList.remove(self.buyOrderID) # if self.shortOrderID: # if trade.tradeID == self.shortOrderID.split('.')[1]: # self.orderList.remove(self.shortOrderID) # 发出状态更新事件 # self.put_event() pass #---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" if so.offset == Offset.OPEN: if so.status == StopOrderStatus.CANCELLED or so.status == StopOrderStatus.TRIGGERED: self.orderList.remove(so.stopOrderID) # if so.offset in [OFFSET_CLOSE, OFFSET_CLOSETODAY, OFFSET_CLOSEYESTERDAY]: # if self.sellOrderID: # if so.orderID == self.sellOrderID.split('.')[1]: # if so.status == STATUS_CANCELLED: # self.sellOrderID = self.sell(self.longExit, self.fixedSize, True) # print u'###多头平仓,单号:%s' % self.sellOrderID # self.sellOrderID = self.orderIDConvert(self.sellOrderID) # if self.coverOrderID: # if so.orderID == self.coverOrderID.split('.')[1]: # if so.status == STATUS_CANCELLED: # self.coverOrderID = self.cover(self.shortExit, self.fixedSize, True) # print u'###空头平仓,单号:%s' % self.coverOrderID # self.coverOrderID = self.orderIDConvert(self.coverOrderID) pass #---------------------------------------------------------------------- def onTimeFunc(self, event): now = dt.datetime.now() now_hour = now.hour now_minute = now.minute if self.minute != now_minute: self.minute = now_minute if not self.timeFuncTurn: self.timeFuncTurn = True if now_hour == 2 and now_minute == 32 and self.timeFuncTurn: self.cta_engine.saveSyncData(self) self.timeFuncTurn = False elif now_hour == 15 and now_minute == 10 and self.timeFuncTurn: self.buyOrderID = None self.shortOrderID = None self.coverOrderID = None self.sellOrderID = None self.longExit = 0 self.shortExit = 0 self.orderList = [] self.cta_engine.saveSyncData(self) self.timeFuncTurn = False
class OrderDemoStrategy(CtaTemplate): """""" author = "用Python的交易员" boll_window = 18 boll_dev = 3.4 fixed_size = 1 atr_window = 20 atr_multiplier = 2 boll_up = 0 boll_down = 0 boll_mid = 0 atr_value = 0 intra_trade_high = 0 long_sl = 0 intra_trade_low = 0 short_sl = 0 long_entry = 0 short_entry = 0 parameters = [ "boll_window", "boll_dev", "fixed_size", "atr_window", "atr_multiplier" ] variables = [ "boll_up", "boll_down", "boll_mid", "atr_value", "intra_trade_high", "long_sl", "intra_trade_low", "short_sl" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() self.buy_vt_orderids = [] self.sell_vt_orderids = [] self.short_vt_orderids = [] self.cover_vt_orderids = [] self.buy_price = 0 self.sell_price = 0 self.short_price = 0 self.cover_price = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" # 生成交易信号 am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) self.boll_mid = am.sma(self.boll_window) self.atr_value = am.atr(self.atr_window) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.buy_price = self.boll_up self.sell_price = 0 self.short_price = self.boll_down self.cover_price = 0 elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_sl = self.intra_trade_high - self.atr_value * self.atr_multiplier self.long_sl = max(self.boll_mid, self.long_sl) self.buy_price = 0 self.sell_price = self.long_sl self.short_price = 0 self.cover_price = 0 elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.intra_trade_high = bar.high_price self.short_sl = self.intra_trade_low + self.atr_value * self.atr_multiplier self.short_sl = min(self.boll_mid, self.short_sl) self.buy_price = 0 self.sell_price = 0 self.short_price = 0 self.cover_price = self.short_sl # 根据信号执行挂撤交易 if self.pos == 0: # 检查之前委托都已经结束 if not self.buy_vt_orderids: # 检查存在信号 if self.buy_price: self.buy_vt_orderids = self.buy(self.buy_price, self.fixed_size, True) self.buy_price = 0 # 执行需要清空信号 else: # 遍历委托号列表撤单 for vt_orderid in self.buy_vt_orderids: self.cancel_order(vt_orderid) if not self.short_vt_orderids: if self.short_price: self.short_vt_orderids = self.short( self.short_price, self.fixed_size, True) self.short_price = 0 else: for vt_orderid in self.short_vt_orderids: self.cancel_order(vt_orderid) elif self.pos > 0: if not self.sell_vt_orderids: if self.sell_price: self.sell_vt_orderids = self.sell(self.sell_price, abs(self.pos), True) self.sell_price = 0 else: for vt_orderid in self.sell_vt_orderids: self.cancel_order(vt_orderid) else: if not self.cover_vt_orderids: if self.cover_price: self.cover_vt_orderids = self.cover( self.cover_price, abs(self.pos), True) self.cover_price = 0 else: for vt_orderid in self.cover_vt_orderids: self.cancel_order(vt_orderid) # Update UI self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ # 如果发出的是停止单,委托状态的回调只能写在on_stop_order下 # 只处理撤销或者触发的停止单委托 if stop_order.status == StopOrderStatus.WAITING: return # 移除已经结束的停止单委托号 for buf_orderids in [ self.buy_vt_orderids, self.sell_vt_orderids, self.short_vt_orderids, self.cover_vt_orderids ]: if stop_order.stop_orderid in buf_orderids: buf_orderids.remove(stop_order.stop_orderid) # 发出新的委托 if self.pos == 0: if not self.buy_vt_orderids: if self.buy_price: self.buy_vt_orderids = self.buy(self.buy_price, self.fixed_size, True) self.buy_price = 0 if not self.short_vt_orderids: if self.short_price: self.short_vt_orderids = self.short( self.short_price, self.fixed_size, True) self.short_price = 0 elif self.pos > 0: if not self.sell_vt_orderids: if self.sell_price: self.sell_vt_orderids = self.sell(self.sell_price, abs(self.pos), True) self.sell_price = 0 else: if not self.cover_vt_orderids: if self.cover_price: self.cover_vt_orderids = self.cover( self.cover_price, abs(self.pos), True) self.cover_price = 0
class DoubleMaStrategy(CtaTemplate): author = "用Python的交易员" fast_window = 10 slow_window = 20 fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 period = 15 parameters = ["period", "fast_window", "slow_window"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.period, self.on_bar_period) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) 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) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_bar_period(self, bar: BarData): """ Callback of new bar data update. """ am = self.am am.update_bar(bar) if not am.inited: return fast_ma = am.sma(self.fast_window, array=True) self.fast_ma0 = fast_ma[-1] self.fast_ma1 = fast_ma[-2] slow_ma = am.sma(self.slow_window, array=True) self.slow_ma0 = slow_ma[-1] self.slow_ma1 = slow_ma[-2] cross_over = self.fast_ma0 > self.slow_ma0 and self.fast_ma1 < self.slow_ma1 cross_below = self.fast_ma0 < self.slow_ma0 and self.fast_ma1 > self.slow_ma1 if cross_over: if self.pos == 0: self.buy(bar.close_price, 1) elif self.pos < 0: self.cover(bar.close_price, 1) self.buy(bar.close_price, 1) elif cross_below: if self.pos == 0: self.short(bar.close_price, 1) elif self.pos > 0: self.sell(bar.close_price, 1) self.short(bar.close_price, 1) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class BollingerBotAG2002Strategy(CtaInvestmentTemplate): """基于布林通道的交易策略""" author = u'tonywang_efun' # 策略参数 initDays = 20 # 初始化数据所用的天数 fixedSize = 1 # 每次交易的数量 fixWinPrcnt = 2.4 # 固定止盈 # (多头参数) bollLength = 43 # 通道窗口数 entryDev = 3.0 # 开仓偏差 exitDev = 1.2 # 平仓偏差 trailingPrcnt = 1.2 # 移动止损百分比 maLength = 18 # 过滤用均线窗口 # (空头参数) shortBollLength = 28 # 通道窗口数 shortEntryDev = 3.6 # 开仓偏差 shortExitDev = 2.0 # 平仓偏差 shortTrailingPrcnt = 0.6 # 移动止损百分比 shortMaLength = 47 # 过滤用均线窗口 # 公共策略变量 posPrice = 0 # 持仓价 # 策略变量(多头) entryLine = 0 # 开仓上轨 exitLine = 0 # 平仓上轨 maFilter = 0 # 均线过滤 maFilterPrevious = 0 # 上一期均线 intraTradeHigh = 0 # 持仓期内的最高点 longEntry = 0 # 多头开仓 longExit = 0 # 多头平仓 # 策略变量(空头) shortEntryLine = 0 # 开仓上轨 shortExitLine = 0 # 平仓上轨 shortMaFilter = 0 # 均线过滤 shortMaFilterPrevious = 0 # 上一期均线 intraTradeLow = 0 # 持仓期内的最最低点 shortEntry = 0 # 空头开仓 shortExit = 0 # 空头平仓 # 参数列表,保存了参数的名称 parameters = [ 'initDays', 'fixedSize', 'fixWinPrcnt', 'bollLength', 'entryDev', 'exitDev', 'trailingPrcnt', 'maLength', 'shortBollLength', 'shortEntryDev', 'shortExitDev', 'shortTrailingPrcnt', 'shortMaLength' ] # 变量列表,保存了变量的名称 variables = [ 'entryLine', 'exitLine', 'shortEntryLine', 'shortExitLine', 'posPrice', 'longEntry', 'longExit', 'shortEntry', 'shortExit' ] # ---------------------------------------------------------------------- def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(BollingerBotAG2002Strategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_xmin_bar) self.am = ArrayManager(100) # ---------------------------------------------------------------------- def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(self.initDays) # ---------------------------------------------------------------------- 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) # ---------------------------------------------------------------------- def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """收到x分钟K线""" # 撤销之前发出的尚未成交的委托(包括限价单和停止单) self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算多头指标数值 self.entryLine, self.exitLine = am.boll_double_up( self.bollLength, self.entryDev, self.exitDev) ma_array = am.sma(self.maLength, True) self.maFilter = ma_array[-1] self.maFilterPrevious = ma_array[-2] # 计算空头指标数值 self.shortEntryLine, self.shortExitLine = am.boll_double_down( self.shortBollLength, self.shortEntryDev, self.shortExitDev) short_ma_array = am.sma(self.shortMaLength, True) self.shortMaFilter = short_ma_array[-1] self.shortMaFilterPrevious = short_ma_array[-2] # 当前无仓位,发送OCO开仓委托 if self.pos == 0: self.intraTradeHigh = bar.high_price self.intraTradeLow = bar.low_price if bar.close_price > self.maFilter > self.maFilterPrevious: self.longEntry = self.entryLine self.buy(self.longEntry, self.fixedSize, True) elif bar.close_price < self.shortMaFilter < self.shortMaFilterPrevious: self.shortEntry = self.shortEntryLine self.short(self.shortEntry, self.fixedSize, True) # 持有多头仓位 elif self.pos > 0: if bar.close_price > self.posPrice \ and (bar.close_price - self.posPrice) / self.posPrice > (self.fixWinPrcnt / 100): print("fix sell-------------------------------") self.sell(bar.close_price * 0.99, abs(self.pos)) else: self.intraTradeHigh = max(self.intraTradeHigh, bar.high_price) self.longExit = self.intraTradeHigh * ( 1 - self.trailingPrcnt / 100) self.longExit = min(self.longExit, self.exitLine) self.sell(self.longExit, abs(self.pos), True) # 持有空头仓位 elif self.pos < 0: self.intraTradeLow = min(self.intraTradeLow, bar.low_price) self.shortExit = self.intraTradeLow * ( 1 + self.shortTrailingPrcnt / 100) self.shortExit = max(self.shortExit, self.shortExitLine) self.cover(self.shortExit, abs(self.pos), True) # 发出状态更新事件 self.put_event() def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" pass # ---------------------------------------------------------------------- def on_trade(self, trade: TradeData): # 记录交易数据并分析投资情况 self.record_trade(trade, "BollingerBot", True) self.posPrice = trade.price self.put_event() # ---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" pass
class BollChannelStrategy(CtaTemplate): """""" author = '用Python的交易员' boll_window = 18 boll_dev = 3.4 cci_window = 10 atr_window = 30 sl_multiplier = 5.2 fixed_size = 1 boll_up = 0 boll_down = 0 cci_value = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = ['boll_window', 'boll_dev', 'cci_window', 'atr_window', 'sl_multiplier', 'fixed_size'] variables = ['boll_up', 'boll_down', 'cci_value', 'atr_value', 'intra_trade_high', 'intra_trade_low', 'long_stop', 'short_stop'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(BollChannelStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) self.cci_value = am.cci(self.cci_window) self.atr_value = am.atr(self.atr_window) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.cci_value > 0: self.buy(self.boll_up, self.fixed_size, True) elif self.cci_value < 0: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class DeviationStrategy(CtaTemplate): """""" author = "yunya" exchange = "BYBIT" xminute_window = 15 short_length = 30 medium_length = 60 long_length = 120 entry_window = 28 exit_window = 7 atr_window = 4 trading_size = 1 # risk_level = 0.2 ema_initde = 0 # trading_size = 0 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 parameters = ["entry_window", "exit_window", "atr_window", "risk_level"] variables = [ "ema_initde", "entry_up", "entry_down", "exit_up", "exit_down", "atr_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.xminute_window, self.on_xminute_bar, interval=Interval.MINUTE) self.am = ArrayManager(self.long_length + 100) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar_exchange(days=10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xminute_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.entry_up, self.entry_down = self.am.donchian(self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) short_ema = self.am.ema(self.short_length, True) mdeium_ema = self.am.ema(self.medium_length, True) long_ema = self.am.ema(self.long_length, True) short_mdeium_array = short_ema - mdeium_ema mdeium__long_array = mdeium_ema - long_ema current_short_mdeium = short_mdeium_array[-1] last_short_mdeium = short_mdeium_array[-2] current_mdeium_long = mdeium__long_array[-1] last_mdeium_long = mdeium__long_array[-2] con1 = current_short_mdeium > current_mdeium_long con2 = last_short_mdeium <= last_mdeium_long con3 = current_short_mdeium < current_mdeium_long con4 = last_short_mdeium >= last_mdeium_long if con1 and con2: self.ema_initde = 1 elif con3 and con4: self.ema_initde = -1 if not self.pos: self.atr_value = self.am.atr(self.atr_window) # if self.atr_value == 0: # return # # 反向合约的计算方法, # atr_risk = talib.ATR( # 1 / self.am.high, # 1 / self.am.low, # 1 / self.am.close, # self.atr_window # )[-1] # self.trading_size = max(int(self.risk_level / atr_risk), 1) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 if self.ema_initde > 0: self.buy(self.entry_up, self.trading_size, True) elif self.ema_initde < 0: self.short(self.entry_down, self.trading_size, True) elif self.pos > 0: sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: cover_price = min(self.short_stop, self.exit_up) self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def load_bar_exchange(self, days: int): """" 判断是属于那个交易所,使用不同的初始化方式 """ if self.exchange == Exchange.HUOBI: self.load_bar(days=days, use_database=True) self.write_log(f"{self.exchange}交易所,从本地获取{days}数据初始化!") elif self.exchange == Exchange.OKEX: self.load_bar(days=days, use_database=True) self.write_log(f"{self.exchange}交易所,从本地获取{days}数据初始化!") else: self.load_bar(days=days) self.write_log(f"{self.exchange}交易所,从交易获取{days}数据初始化!")
class MultiTimeframeStrategy(CtaTemplate): """""" author = '用Python的交易员' rsi_signal = 20 rsi_window = 14 fast_window = 5 slow_window = 20 fixed_size = 1 rsi_value = 0 rsi_long = 0 rsi_short = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 parameters = ['rsi_signal', 'rsi_window', 'fast_window', 'slow_window', 'fixed_size'] variables = ['rsi_value', 'rsi_long', 'rsi_short', 'fast_ma', 'slow_ma', 'ma_trend'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(MultiTimeframeStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.rsi_long = 50 + self.rsi_signal self.rsi_short = 50 - self.rsi_signal self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am15 = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return if not self.ma_trend: return self.rsi_value = self.am5.rsi(self.rsi_window) if self.pos == 0: if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy(bar.close_price + 5, self.fixed_size) elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(bar.close_price - 5, self.fixed_size) elif self.pos > 0: if self.ma_trend < 0 or self.rsi_value < 50: self.sell(bar.close_price - 5, abs(self.pos)) elif self.pos < 0: if self.ma_trend > 0 or self.rsi_value > 50: self.cover(bar.close_price + 5, abs(self.pos)) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if not self.am15.inited: return self.fast_ma = self.am15.sma(self.fast_window) self.slow_ma = self.am15.sma(self.slow_window) if self.fast_ma > self.slow_ma: self.ma_trend = 1 else: self.ma_trend = -1 def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class DoubleSignalGenerator(CtaTemplate): """""" author = "yiran" atr_window = 20 obv_window = 10 minus_dm_window = 10 mfi_window = 20 ad_window = 20 adosc_window = 20 plus_dm_window = 20 dx_window = 20 adx_window = 20 s_window = 5 l_window = 15 atr_multiplier = 0.05 rsi_window = 11 long_threshold_l_window = 50 long_threshold_s_window = 80 exit_return = 0.02 exit_loss = 0.02 exit_return_soft_long = -0.1 exit_loss_soft_long = -0.2 exit_return_soft_short = 0.2 exit_loss_soft_short = 0.1 fixed_size = 1 start_time = time(hour=10) exit_time = time(hour=14, minute=55) long_order_record = [] short_order_record = [] rsi_value_l_window = -9999 rsi_value_s_window = -9999 atr_value = 0 minus_dm_value = 0 obv_value = 0 mfi_value = 0 ad_value = 0 adosc_value = 0 plus_dm_value = 0 dx_value = 0 adx_value = 0 position_hold = 0 long_entered = False short_entered = False parameters = [] variables = [] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long_l = self.long_threshold_l_window self.rsi_long_s = self.long_threshold_s_window self.rsi_short_l = 100 - self.long_threshold_l_window self.rsi_short_s = 100 - self.long_threshold_s_window self.bg5 = BarGenerator(self.on_bar, self.s_window, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, self.l_window, self.on_15min_bar) self.am15 = ArrayManager() self.long_order_record = [] self.short_order_record = [] # 指标计算容器 self.rsi_value_recorder_l_window = [] self.rsi_time_recorder_l_window = [] self.rsi_value_recorder_s_window = [] self.rsi_time_recorder_s_window = [] self.atr_time_recorder = [] self.atr_value_recorder = [] self.obv_time_recorder = [] self.obv_value_recorder = [] self.minus_dm_time_recorder = [] self.minus_dm_value_recorder = [] self.mfi_time_recorder = [] self.mfi_value_recorder = [] self.ad_time_recorder = [] self.ad_value_recorder = [] self.adosc_time_recorder = [] self.adosc_value_recorder = [] self.plus_dm_time_recorder = [] self.plus_dm_value_recorder = [] self.dx_time_recorder = [] self.dx_value_recorder = [] self.adx_time_recorder = [] self.adx_value_recorder = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return self.rsi_value_s_window = self.am5.rsi(self.rsi_window) self.atr_value = self.am5.atr(self.atr_window) self.obv_value = self.am5.obv(self.obv_window) self.minus_dm_value = self.am5.minus_dm(self.minus_dm_window) self.mfi_value = self.am5.mfi(self.mfi_window) self.ad_value = self.am5.ad(self.ad_window) self.adosc_value = self.am5.adosc(self.adosc_window) self.plus_dm_value = self.am5.adosc(self.plus_dm_window) self.dx_value = self.am5.adosc(self.dx_window) self.adx_value = self.am5.adosc(self.adx_window) self.rsi_time_recorder_s_window.append(bar.datetime) self.rsi_value_recorder_s_window.append(self.rsi_value_s_window) self.atr_time_recorder.append(bar.datetime) self.atr_value_recorder.append(self.atr_value) self.obv_time_recorder.append(bar.datetime) self.obv_value_recorder.append(self.obv_value) self.minus_dm_time_recorder.append(bar.datetime) self.minus_dm_value_recorder.append(self.minus_dm_value) self.mfi_time_recorder.append(bar.datetime) self.mfi_value_recorder.append(self.mfi_value) self.ad_time_recorder.append(bar.datetime) self.ad_value_recorder.append(self.ad_value) self.adosc_time_recorder.append(bar.datetime) self.adosc_value_recorder.append(self.adosc_value) self.plus_dm_time_recorder.append(bar.datetime) self.plus_dm_value_recorder.append(self.plus_dm_value) self.dx_time_recorder.append(bar.datetime) self.dx_value_recorder.append(self.dx_value) self.adx_time_recorder.append(bar.datetime) self.adx_value_recorder.append(self.adx_value) def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if not self.am15.inited: return self.rsi_value_l_window = self.am15.rsi(self.rsi_window) self.rsi_time_recorder_l_window.append(bar.datetime) self.rsi_value_recorder_l_window.append(self.rsi_value_l_window) def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass