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 TurtleFluidSizeStrategy(CtaTemplate): """""" # 改版海龟信号-ma出场-rsi过滤-atr浮动手数 author = "turtle_fluid_size" entry_window = 50 exit_window = 20 atr_window = 20 stop_multiple = 10 long_rsi = 50 short_rsi = 50 fixed_size = 1 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 fluid_size = 1 symbol_size = 1 risk_percent = 0.002 risk_capital = 1000000 parameters = [ "entry_window", "exit_window", "atr_window", "fixed_size", "stop_multiple", "long_rsi", "short_rsi", "symbol_size", "risk_percent", "risk_capital" ] variables = [ "entry_up", "entry_down", "exit_up", "exit_down", "atr_value", "fluid_size" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) print(self.symbol_size, self.risk_percent, self.risk_capital) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) 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.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) self.exit_up = self.exit_down = self.am.sma(self.exit_window) self.rsi_value = self.am.rsi(self.entry_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) risk_amount = self.risk_capital * self.risk_percent atr_amount = self.atr_value * self.symbol_size self.fluid_size = round(risk_amount / atr_amount) * self.fixed_size self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 if self.fluid_size and self.rsi_value > self.long_rsi: self.send_buy_orders(self.entry_up) if self.fluid_size and self.rsi_value <= self.short_rsi: self.send_short_orders(self.entry_down) 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 - self.stop_multiple * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + self.stop_multiple * self.atr_value 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 send_buy_orders(self, price): """""" self.buy(price, self.fluid_size, True) def send_short_orders(self, price): """""" self.short(price, self.fluid_size, True)
class RsiDcVixStrategy(CtaTemplate): """ Rsi 原版逻辑 Rsi 值 上破临界值 80 时平空做多,下破临界值 20 时平多做空。 Rsi 策略优化思路: 一、指标计算方式 1、计算 N 周期 rsi 2、计算 N 周期 RSI 的最大值为上轨,最小值为下轨 3、rsi 上穿上轨,并且 rsi 大于 50 ,做多 3、rsi 下穿下轨,并且 rsi 小于 50 ,做空 """ author = "yunya" open_window = 45 rsi_window = 100 exit_window = 65 ema_window = 65 atr_window = 16 atr_window_ma = 10 atr_multiplier = 10.0 pos_trailing = 3.0 fixed_size = 1 exit_up = 0 exit_down = 0 atr_value = 0 atr_value_ma = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 long_trade_stop = 0 short_trade_stop = 0 intra_trade_high = 0 intra_trade_low = 0 rsi_value_current = 0 rsi_value_last = 0 rsi_up_current = 0 rsi_up_last = 0 rsi_down_current = 0 rsi_down_last = 0 exit_long_nex = 0 exit_long_last = 0 exit_long = 0 exit_short_nex = 0 exit_short_last = 0 exit_short = 0 boll_mid = 0 boll_mid_new = 0 ema_window_new = 0 parameters = [ "open_window", "rsi_window", "exit_window", "ema_window", "atr_window", "atr_multiplier", "pos_trailing", "fixed_size", ] variables = [ "exit_up", "exit_down", "atr_value", "long_entry", "short_entry", "long_stop", "short_stop", "long_trade_stop", "short_trade_stop", "intra_trade_high", "intra_trade_low", "rsi_value_current", "rsi_value_last", "rsi_up_current", "rsi_up_last", "rsi_down_current", "rsi_down_last", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_15min_bar) self.am = ArrayManager(self.rsi_window * 2) self.count: int = 0 self.size: int = 4 self.rsi_inited: bool = False self.rsi_up_array: np.ndarray = np.zeros(self.size) self.rsi_down_array: np.ndarray = np.zeros(self.size) 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 tick data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算 dev_max rsi_array = talib.RSI(self.am.close, self.rsi_window) if not self.rsi_inited: self.count += 1 if self.count >= self.size: self.rsi_inited = True # rsi 上下轨容器 self.rsi_up_array[:-1] = self.rsi_up_array[1:] self.rsi_down_array[:-1] = self.rsi_down_array[1:] rsi_up = rsi_array[-self.rsi_window:].max() rsi_down = rsi_array[-self.rsi_window:].min() self.rsi_up_array[-1] = rsi_up self.rsi_down_array[-1] = rsi_down if not self.rsi_inited: return rsi_value_array = am.rsi(self.rsi_window, True) self.rsi_value_current = rsi_value_array[-1] self.rsi_value_last = rsi_value_array[-2] # 取前一个值 self.rsi_up_current = self.rsi_up_array[-2] self.rsi_up_last = self.rsi_up_array[-3] self.rsi_down_current = self.rsi_down_array[-2] self.rsi_down_last = self.rsi_down_array[-3] self.exit_up, self.exit_down = self.am.donchian(self.exit_window) atr_value_array = am.atr(self.atr_window, True) self.atr_value = atr_value_array[-1] self.atr_value_ma = atr_value_array[-self.atr_window_ma:].mean() self.boll_mid = am.sma(self.ema_window) # 没有仓 if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price rsi_inited_up = self.rsi_value_current > self.rsi_up_current and self.rsi_value_last <= self.rsi_up_last rsi_inited_down = self.rsi_value_current < self.rsi_down_current and self.rsi_value_last >= self.rsi_down_last atr_inited = self.atr_value > self.atr_window_ma self.ema_window_new = self.ema_window if rsi_inited_up and atr_inited and self.rsi_value_current > 50: self.buy(bar.close_price + 5, self.fixed_size) elif rsi_inited_down and atr_inited and self.rsi_value_current < 50: self.short(bar.close_price - 5, 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 self.long_stop = self.intra_trade_high - self.atr_value * self.atr_multiplier self.long_stop = max(self.long_stop, self.exit_down) self.long_stop = max(self.long_stop, self.long_trade_stop) # 上涨或下跌时,布林中轨均值减1 close_long = am.close[-1] > am.close[-2] > am.close[-3] if close_long: self.ema_window_new -= 1 self.ema_window_new = max(self.ema_window_new, 10) # 计算新的布林带 self.boll_mid_new = am.sma(self.ema_window_new, True) # 仓位是long 时,如果价格上穿新布林中轨 con1 = am.close[-1] < self.boll_mid_new[-1] con2 = am.close[-2] >= self.boll_mid_new[-2] if con1 and con2: self.exit_long_nex = am.close[-1] # 保存当前收盘价 if self.exit_long_nex > self.exit_long_last or self.exit_long_last == 0: self.exit_long_last = self.exit_long_nex self.ema_window_new = self.ema_window # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.boll_mid # print(f"我是多单,exitlast:{self.exit_short_last},重置布林中轨参数,止损挂{self.exit_long}:") else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if self.am.close[-1] > ( (self.boll_mid + self.boll_mid_new[-1]) / 2): self.exit_long = bar.close_price # print(f"我是多单,收盘价在两个中轨均值上方,以收盘价挂止损单:{self.exit_long}") elif bar.close_price < self.boll_mid: self.exit_long = bar.close_price else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.boll_mid self.long_stop = max(self.long_stop, self.exit_long) 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.atr_multiplier self.short_stop = min(self.short_stop, self.exit_up) self.short_stop = min(self.short_stop, self.short_trade_stop) close_short = am.close[-1] < am.close[-2] < am.close[-3] if close_short: self.ema_window_new -= 1 self.ema_window_new = max(self.ema_window_new, 10) # 计算新的布林带 self.boll_mid_new = am.sma(self.ema_window_new, True) # 仓位是short 时,如果价格上穿新布林中轨 con3 = am.close[-1] > self.boll_mid_new[-1] con4 = am.close[-2] <= self.boll_mid_new[-2] if con3 and con4: self.exit_short_nex = am.close[-1] if self.exit_short_nex < self.exit_short_last or self.exit_short_last == 0: self.exit_short_last = self.exit_short_nex self.ema_window_new = self.ema_window self.exit_short = self.boll_mid else: if self.am.close[-1] < (self.boll_mid + self.boll_mid_new[-1] / 2): self.exit_short = bar.close_price elif bar.close_price > self.boll_mid: self.exit_short = bar.close_price else: self.exit_short = self.boll_mid else: self.exit_short = self.boll_mid self.short_stop = min(self.short_stop, self.exit_short) self.cover(self.short_stop, abs(self.pos), True) self.put_event() 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. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_trade_stop = self.long_entry * (1 - self.pos_trailing / 100) else: self.short_entry = trade.price self.short_trade_stop = self.short_entry * ( 1 + self.pos_trailing / 100) self.put_event() self.sync_data()
class TurtleSignalStrategy(CtaTemplate): """""" author = "backtest example" entry_window = 20 exit_window = 10 atr_window = 20 fixed_size = 1 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", "fixed_size"] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TurtleSignalStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) 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.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) 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 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 send_buy_orders(self, price): """""" self.buy(price, self.fixed_size, True) def send_short_orders(self, price): """""" self.short(price, self.fixed_size, True)
class AtrStop_Ut(CtaTemplate): """""" author = "yunya" atrstop_window = 46 open_window = 5 nloss_singnal = 2.7 trailing_tax = 2.0 risk_level = 5000 exit_dc_length = 50 atr_length = 30 atrstop_entry = 0 current_atr_stop = 0.0 last_atr_stop = 0.0 intra_trade_high = 0 intra_trade_low = 0 nloss_array = 0.0 long_stop = 0 short_stop = 0 trading_size = 0 exit_down = 0 exit_up = 0 ask = 0 bid = 0 atr_value = 0 count = 0 parameters = [ "atrstop_window", "open_window", "nloss_singnal", "trailing_tax", "risk_level", "exit_dc_length", "atr_length" ] variables = [ "atrstop_entry", "current_atr_stop", "last_atr_stop", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "exit_down", "exit_up", "trading_size", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.atr_stop_array = np.zeros(10) self.bg_xmin = NewBarGenerator( self.on_bar, window=self.atrstop_window, on_window_bar=self.on_xmin_bar, interval=Interval.MINUTE ) self.am_xmin = ArrayManager() self.bg_5min = BarGenerator( self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar ) self.am_5min = ArrayManager(self.exit_dc_length * int(self.atr_length / self.open_window) + 10) self.inited_atr_stop = False # 状态控制初始化 self.chase_long_trigger = False self.chase_sell_trigger = False self.chase_short_trigger = False self.chase_cover_trigger = False self.cancel_status = False self.long_trade_volume = 0 self.short_trade_volume = 0 self.sell_trade_volume = 0 self.cover_trade_volume = 0 self.chase_interval = 10 # 拆单间隔:秒 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(10) # self.put_event() 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): working_order_dict = self.get_position_detail(tick.vt_symbol).active_orders # working_order_dict = self.order_dict if working_order_dict: # 委托完成状态 order_finished = False vt_orderid = list(working_order_dict.items())[0][0] # 委托单vt_orderid working_order = list(working_order_dict.items())[0][1] # 委托单字典 # 开平仓追单,部分交易没有平仓指令(Offset.NONE) """获取到未成交委托单后检查未成交委托量>0,tick.datetime - 未成交委托单的datetime>追单间隔(chase_interval), 同时chase_long_trigger状态未触发和有vt_orderid的判定(之前有收过空vt_orderid,所有要加个过滤),撤销该未成交委托单, 赋值chase_long_trigger为True.chase_long_trigger为True且没有未成交委托单时执行追单, 如有未成交委托单则调用cancel_surplus_order取消所有未成交委托单,追单的委托单发送出去后初始化chase_long_trigger. 其他方向的撤单追单也是一样的流程""" if working_order.offset in (Offset.NONE, Offset.OPEN): if working_order.direction == Direction.LONG: self.long_trade_volume = working_order.untrade if ( tick.datetime - working_order.datetime).seconds > self.chase_interval and self.long_trade_volume > 0 and ( not self.chase_long_trigger) and vt_orderid: # 撤销之前发出的未成交订单 self.cancel_order(vt_orderid) self.chase_long_trigger = True elif working_order.direction == Direction.SHORT: self.short_trade_volume = working_order.untrade if ( tick.datetime - working_order.datetime).seconds > self.chase_interval and self.short_trade_volume > 0 and ( not self.chase_short_trigger) and vt_orderid: self.cancel_order(vt_orderid) self.chase_short_trigger = True # 平仓追单 elif working_order.offset in (Offset.CLOSE, Offset.CLOSETODAY): if working_order.direction == Direction.SHORT: self.sell_trade_volume = working_order.untrade if ( tick.datetime - working_order.datetime).seconds > self.chase_interval and self.sell_trade_volume > 0 and ( not self.chase_sell_trigger) and vt_orderid: self.cancel_order(vt_orderid) self.chase_sell_trigger = True if working_order.direction == Direction.LONG: self.cover_trade_volume = working_order.untrade if ( tick.datetime - working_order.datetime).seconds > self.chase_interval and self.cover_trade_volume > 0 and ( not self.chase_cover_trigger) and vt_orderid: self.cancel_order(vt_orderid) self.chase_cover_trigger = True else: order_finished = True self.cancel_status = False if self.chase_long_trigger: if order_finished: self.buy(tick.ask_price_1, self.long_trade_volume) self.chase_long_trigger = False else: self.cancel_surplus_order(list(working_order_dict)) elif self.chase_short_trigger: if order_finished: self.short(tick.bid_price_1, self.short_trade_volume) self.chase_short_trigger = False else: self.cancel_surplus_order(list(working_order_dict)) elif self.chase_sell_trigger: if order_finished: self.sell(tick.bid_price_1, self.sell_trade_volume) self.chase_sell_trigger = False else: self.cancel_surplus_order(list(working_order_dict)) elif self.chase_cover_trigger: if order_finished: self.cover(tick.ask_price_1, self.cover_trade_volume) self.chase_cover_trigger = False else: self.cancel_surplus_order(list(working_order_dict)) # ------------------------------------------------------------------------------------ def cancel_surplus_order(self, orderids: list): """ 撤销剩余活动委托单 """ if not self.cancel_status: for vt_orderid in orderids: self.cancel_order(vt_orderid) self.cancel_status = True def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xmin.update_bar(bar) self.bg_5min.update_bar(bar) def on_5min_bar(self, bar: BarData): self.cancel_all() self.am_5min.update_bar(bar) if not self.am_5min.inited or not self.am_xmin.inited: return if self.atr_stop_array[-3] == 0: return self.exit_up, self.exit_down = self.am_5min.donchian( self.exit_dc_length * int(self.atr_length / self.open_window)) # print(f"dc上轨:{self.exit_up},下轨:{self.exit_down}") if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.atrstop_entry > 0: self.buy(self.current_atr_stop, self.trading_size, True) elif self.atrstop_entry < 0: self.short(self.current_atr_stop, self.trading_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) long_high = self.intra_trade_high * \ (1 - self.trailing_tax / 100) self.long_stop = max(self.exit_down, long_high) self.sell(self.long_stop, abs(self.pos), True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_low = self.intra_trade_low * \ (1 + self.trailing_tax / 100) self.short_stop = min(self.exit_up, short_low) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xmin_bar(self, bar: BarData): """""" am_xmin = self.am_xmin am_xmin.update_bar(bar) self.atr_stop_array[:-1] = self.atr_stop_array[1:] if not am_xmin.inited: return # 计算轨道线 nloss self.nloss_array = am_xmin.atr(30, array=True) * self.nloss_singnal # 计算轨道线 self.atr_stop_array = self.atrstop( am_xmin.close, self.atr_stop_array, self.nloss_array ) # 初始化 atr_stop_array 保证前三个有值 if self.count < 4: self.count += 1 return self.current_atr_stop = self.atr_stop_array[-1] self.last_atr_stop = self.atr_stop_array[-2] current_bar = self.am_xmin.close[-1] if self.current_atr_stop > self.last_atr_stop and current_bar > self.current_atr_stop: self.atrstop_entry = 1 elif self.current_atr_stop < self.last_atr_stop and current_bar < self.current_atr_stop: self.atrstop_entry = -1 else: self.atrstop_entry = 0 if self.pos == 0: self.atr_value = self.am_xmin.atr(self.atr_length) self.trading_size = max(int(self.risk_level / self.atr_value), 1) self.sync_data() 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. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event() def atrstop(self, close, atrstop, nlossatr): # 计算轨道线 if (close[-1] > atrstop[-2]) and (close[-2] > atrstop[-2]): atrstop[-1] = max(atrstop[-2], close[-1] - nlossatr[-1]) elif (close[-1] < atrstop[-2]) and (close[-2] < atrstop[-2]): atrstop[-1] = min(atrstop[-2], close[-1] + nlossatr[-1]) elif (close[-1] > atrstop[-2]): atrstop[-1] = (close[-1] - nlossatr[-1]) else: atrstop[-1] = (close[-1] + nlossatr[-1]) return atrstop
class BollBbWidthtrategy(CtaTemplate): """ 布林带策略优化: 1、计算布林极限指标 BB = (收盘价 - 布林下轨)/(上轨 - 下轩) 区间:0-1 2、计算布林宽度指标 width = (上轨 - 下轨) / 中轨 区间: """ author = "yunya" open_window = 36 boll_length = 24 prop = 1.8 atr_window = 30 sl_multiplier = 0.2 dc_length = 20 fixed_size = 1 entry_crossover = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop_trade = 0 short_stop_trade = 0 long_stop = 0 short_stop = 0 exit_short = 0 exit_long = 0 entry_ema = 0 parameters = [ "open_window", "boll_length", "dc_length", "sl_multiplier", "prop", "fixed_size", ] variables = ["entry_crossover", "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 = NewBarGenerator(self.on_bar, self.open_window, self.on_xmin_bar) self.am = ArrayManager(int(self.boll_length) + 100) 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_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # Calculate array 计算数组 self.sma_array = am.sma(self.boll_length, True) std_array = am.sma(self.boll_length, True) dev = abs(self.am.close[:-1] - self.sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_length:].max() self.boll_up_array = self.sma_array + std_array * dev_max self.boll_down_array = self.sma_array - std_array * dev_max # Get current and last index current_sma = self.sma_array[-1] last_sma = self.sma_array[-2] last_close = self.am.close[-2] currnet_boll_up = self.boll_up_array[-1] last_boll_up = self.boll_up_array[-2] current_boll_down = self.boll_down_array[-1] last_boll_down = self.boll_down_array[-2] up_limit = current_sma * (1 + self.prop / 100) down_limit = current_sma * (1 - self.prop / 100) boll_width = currnet_boll_up - current_boll_down # Get crossover if (last_close <= last_boll_up and currnet_boll_up < bar.close_price < up_limit): self.entry_crossover = 1 elif (last_close >= last_boll_down and current_boll_down > bar.close_price > down_limit): self.entry_crossover = -1 if (last_close <= last_sma and bar.close_price > current_sma): self.entry_ema = -1 elif (last_close >= last_sma and bar.close_price < current_sma): self.entry_ema = 1 else: self.entry_ema = 0 self.atr_value = am.atr(self.atr_window) self.exit_short, self.exit_long = self.am.donchian(self.dc_length) if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.entry_crossover > 0: self.buy(up_limit, self.fixed_size, True) elif self.entry_crossover < 0: self.short(down_limit, self.fixed_size, True) elif self.pos > 0: if self.entry_ema > 0: self.sell((bar.close_price - 5), abs(self.pos)) # 最高价回撤比例、固定止损、唐安奇下轨中的最大值为止损位 self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price long_stop_high = self.intra_trade_high - boll_width * self.sl_multiplier long_high_trade = max(long_stop_high, self.long_stop_trade) self.long_stop = max(self.exit_long, long_high_trade) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: if self.entry_ema < 0: self.cover((bar.close_price + 5), abs(self.pos)) else: # 最低价回撤比例、固定止损、唐安奇上轨中的最小值为止损位 self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_stop_low = self.intra_trade_low + boll_width * self.sl_multiplier short_low_trade = min(short_stop_low, self.short_stop_trade) self.short_stop = min(short_low_trade, self.exit_short) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop_trade = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop_trade = self.short_entry + 2 * self.atr_value self.sync_data() self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event() pass
class LifeHunterStrategy(CtaTemplate): """""" author = "super dino" entry_window = 28 exit_window = 7 fast_period = 12 slow_period = 26 signal_period = 9 trend_level = 10 atr_window = 4 risk_level = 0.2 trailing_tax = 0.3 trading_size = 0 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 MACD_sign = 0 signal = 0 hist = 0 MACD_trend = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 intra_trade_high = 0 intra_trade_low = 0 long_out = 0 short_out = 0 parameters = [ "entry_window", "exit_window", "fast_period", "slow_period", "signal_period", "trend_level", "atr_window", "risk_level", "trailing_tax" ] variables = [ "trading_size", "entry_up", "entry_down", "exit_up", "exit_down", "atr_value", "MACD_sign", "signal", "hist", "MACD_trend", "long_entry", "short_entry", "long_stop", "short_stop", "intra_trade_high", "intra_trade_low", "long_out", "short_out" ] 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, 30, self.on_30min_bar) self.am = ArrayManager() self.am30 = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) 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) self.cancel_all() self.am.update_bar(bar) if not self.am.inited or not self.am30.inited: return # No Position 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.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 if self.MACD_trend > 0: self.buy(self.entry_up, self.trading_size, True) if self.MACD_trend < 0: self.short(self.entry_down, self.trading_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_out = self.intra_trade_high * \ (1 - self.trailing_tax / 100) sell_price = max(self.long_stop, self.exit_down, self.long_out) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_out = self.intra_trade_low * \ (1 + self.trailing_tax / 100) cover_price = min(self.short_stop, self.exit_up, self.short_out) self.cover(cover_price, abs(self.pos), True) if bar.datetime.day == 21: print(bar.datetime, self.entry_up, bar.open_price, bar.high_price, bar.low_price, bar.close_price) self.put_event() def on_30min_bar(self, bar: BarData): """""" self.am30.update_bar(bar) if not self.am30.inited: return self.entry_up, self.entry_down = self.am30.donchian(self.entry_window) self.exit_up, self.exit_down = self.am30.donchian(self.exit_window) if bar.datetime.day == 21: print("on 30 min", bar.datetime, self.entry_up) self.MACD_sign, self.signal, self.hist = self.am30.macd( self.fast_period, self.slow_period, self.signal_period) self.MACD_sign = self.signal - self.hist if self.MACD_sign > self.trend_level: self.MACD_trend = 1 elif self.MACD_sign < (-self.trend_level): self.MACD_trend = -1 else: self.MACD_trend = 0 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 msg = f"新的成交,策略是{self.strategy_name},方向{trade.direction},开平{trade.offset},当前仓位{self.pos}" self.send_email(msg) 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 Mike_Dc_Strategy(CtaTemplate): """""" author = "yunya" exchange : Exchange = "" mike_window = 1 mike_length = 30 dc_length = 10 kk_length = 20 kk_dev = 2.0 sl_trade = 2 fixed_size = 1 ask = 0 bid = 0 ema_mid = 0 ema_hh = 0 ema_ll = 0 ema_wr = 0 #初级压力线 ema_mr = 0 #中级压力线 ema_sr = 0 #高级压力线 ema_ws = 0 #初级支撑线 ema_ms = 0 #中级支撑线 ema_ss = 0 #高级支撑线 dc_up = 0 dc_down = 0 kk_up = 0 kk_down = 0 atr_value = 0 long_stop = 0 short_stop = 0 long_stop_trade = 0 short_stop_trade = 0 long_enrty = 0 short_enrty = 0 ema_entry_crossover = 0 boll_entry_crossover = 0 boll_width = 0 parameters = [ "exchange", "mike_window", "mike_length", "dc_length", "kk_length", "kk_dev", "sl_trade", "fixed_size", ] variables = [ "long_stop", "short_stop", "ema_entry_crossover", "boll_entry_crossover", "boll_width", "ema_mid", "ema_hh", "ema_ll", "ema_wr", "ema_mr", "ema_sr", "ema_ws", "ema_ms", "ema_ss", ] def __init__(self, cta_engine, strategy_nam_xhoure, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_nam_xhoure, vt_symbol, setting) self.bg_xhour = BarGenerator( on_bar=self.on_bar, window=self.mike_window, on_window_bar=self.on_hour_bar, interval=Interval.HOUR ) self.am_xhour = ArrayManager(max(self.dc_length ,self.kk_length) + 10) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.exchange_load_bar(self.exchange) 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_xhour.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xhour.update_bar(bar) def on_hour_bar(self, bar: BarData): """ 计算 mike 指标线 :param_xhour bar: :return: """ self.am_xhour.update_bar(bar) if not self.am_xhour.inited: return # 计算mike压力支撑线 ema_array = (self.am_xhour.close[:-1] + self.am_xhour.high[:-1] + self.am_xhour.low[:-1]) / 3 self.ema_mid = ema_array[-1] self.ema_hh = self.am_xhour.high[-self.mike_length:-1].max() self.ema_ll = self.am_xhour.low[-self.mike_length:-1].min() self.ema_wr = self.ema_mid + (self.ema_mid - self.ema_ll) self.ema_mr = self.ema_mid + (self.ema_hh - self.ema_ll) self.ema_sr = 2 * self.ema_hh - self.ema_ll self.ema_ws = self.ema_mid - (self.ema_hh - self.ema_mid) self.ema_ms = self.ema_mid - (self.ema_hh - self.ema_ll) self.ema_ss = 2 * self.ema_ll - self.ema_hh if (self.am_xhour.close[-1] > self.ema_sr) or (self.ema_ms < self.am_xhour.close[-1] < self.ema_ws): self.ema_entry_crossover = 1 elif (self.am_xhour.close[-1] < self.ema_ss) or (self.ema_mr > self.am_xhour.close[-1] > self.ema_wr): self.ema_entry_crossover = -1 self.kk_up,self.kk_down = self.am_xhour.keltner(self.kk_length,self.kk_dev) self.dc_up,self.dc_down = self.am_xhour.donchian(self.dc_length) if self.pos == 0: self.atr_value = self.am_xhour.atr(30) if self.ema_entry_crossover > 0 : self.buy(self.kk_up, self.fixed_size,True) print(self.kk_up) elif self.ema_entry_crossover < 0 : self.short(self.kk_down, self.fixed_size,True) elif self.pos > 0: self.long_stop = max(self.dc_down,self.long_stop_trade) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.short_stop = min(self.dc_up,self.short_stop_trade) self.cover(self.short_stop, abs(self.pos), True) self.sync_data() self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass # self.write_log(f"on_order: status:{order.status}, orderid: {order.vt_orderid}, offset:{order.offset}, price:{order.price}, volume:{order.volume}, traded: {order.traded}") # self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # if trade.direction == Direction.LONG: # self.long_enrty = trade.price # self.long_stop_trade = self.long_enrty - 2 * self.atr_value # # else: # self.short_enrty = trade.price # self.short_stop_trade = self.short_enrty + 2 * self.atr_value self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def exchange_load_bar(self,exchange:Exchange): """ 如果是火币,ok 交易所,就从数据库获取初始化数据 """ if exchange == Exchange.OKEX or exchange == Exchange.HUOBI: self.load_bar(days=10,use_database=True) else: self.load_bar(10)
class RsiMomentumMinuteStrategy(CtaTemplate): """ EOS 遗产回测参数为: open_window = 50 rsi_window = 3 rsi_entry = 3 atr_window = 30 atr_ma_window = 15 exit_window = 33 """ author = "yunya" open_window = 15 rsi_window = 4 rsi_entry = 19 atr_window = 16 atr_ma_window = 10 exit_window = 20 pay_up = 10 trading_size = 1 # risk_level = 5000 # trading_size = 0 atr_value = 0 atr_ma = 0 rsi_value = 0 rsi_long = 0 rsi_short = 0 exit_up = 0 exit_down = 0 tick_price = 0 engine_type = 0 parameters = [ "open_window", "rsi_window", "rsi_entry", "atr_window", "atr_ma_window", "exit_window", "pay_up", "trading_size", ] variables = [ "atr_value", "atr_ma", "rsi_value", "rsi_long", "rsi_short", "exit_up", "exit_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, self.open_window, self.on_hour_bar, interval=Interval.MINUTE) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.rsi_long = 50 + self.rsi_entry self.rsi_short = 50 - self.rsi_entry self.engine_type = self.get_engine_type() # 测试还是实盘 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_hour_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return atr_array = am.atr(self.atr_window, array=True) self.atr_value = atr_array[-1] self.atr_ma = atr_array[-self.atr_ma_window:].mean() self.rsi_value = am.rsi(self.rsi_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if self.pos == 0: # self.trading_size = max(int(self.risk_level / self.atr_value), 1) if self.engine_type != EngineType.LIVE: self.tick_price = self.get_pricetick() * self.pay_up else: self.tick_price = bar.close_price * 5 / 1000 if self.atr_value > self.atr_ma: if self.rsi_value > self.rsi_long: self.buy(bar.close_price + self.tick_price * self.pay_up, self.trading_size) elif self.rsi_value < self.rsi_short: self.short(bar.close_price - self.tick_price * self.pay_up, self.trading_size) elif self.pos > 0: self.sell(self.exit_down, abs(self.pos), stop=True) elif self.pos < 0: self.cover(self.exit_up, abs(self.pos), stop=True) self.put_event() 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 Boll_Control_Proportion_Vix_Width(CtaTemplate): """""" author = "yunya" win_open = 21 boll_window = 90 prop = 1.8 atr_window = 30 trailing_long = 0.9 trailing_short = 0.9 exit_dc_length = 0 fixed_size = 1 exit_long = 0 exit_short = 0 entry_crossover = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = [ "win_open", "boll_window", "prop", "trailing_long", "trailing_short", "fixed_size", ] variables = [ "entry_crossover", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "exit_long", "exit_short", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.win_open, self.on_xmin_bar) self.am = ArrayManager(self.boll_window + 100) 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_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # Calculate array 计算数组 self.sma_array = am.sma(self.boll_window, True) std_array = am.sma(self.boll_window, True) dev = abs(self.am.close[:-1] - self.sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_window:].max() self.boll_up_array = self.sma_array + std_array * dev_max self.boll_down_array = self.sma_array - std_array * dev_max # Get current and last index current_sma = self.sma_array[-1] last_close = self.am.close[-2] currnet_boll_up = self.boll_up_array[-1] last_boll_up = self.boll_up_array[-2] current_boll_down = self.boll_down_array[-1] last_boll_down = self.boll_down_array[-2] up_limit = current_sma * (1 + self.prop / 100) down_limit = current_sma * (1 - self.prop / 100) boll_width = currnet_boll_up - current_boll_down self.exit_long, self.exit_short = self.am.donchian(self.exit_dc_length) # Get crossover if (last_close <= last_boll_up and bar.close_price > currnet_boll_up and bar.close_price < up_limit): self.entry_crossover = 1 elif (last_close >= last_boll_down and bar.close_price < current_boll_down and bar.close_price > down_limit): self.entry_crossover = -1 if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.entry_crossover > 0: self.buy(up_limit, self.fixed_size, True) elif self.entry_crossover < 0: self.short(down_limit, 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 long_stop_high = self.intra_trade_high - boll_width * self.trailing_long self.long_stop = max(long_stop_high, self.exit_short) 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 + boll_width * self.trailing_short self.cover(self.short_stop, abs(self.pos), True) self.sync_data() self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() 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. """ self.put_event() pass
class AtrStopRsiDcStrategy(CtaTemplate): """""" author = "yunya" hour_window = 1 minute_window = 50 open_window = 5 rsi_length = 15 distance_line = 2.0 nloss_singnal = 3.1 exit_dc_length = 30 sl_multiplier = 8.0 fixd_size = 1 atr_window = 30 exit_dowm = 0 exit_up = 0 atr_entry = 0 rsi_entry = 0 current_atr_stop = 0.0 last_atr_stop = 0.0 intra_trade_high = 0 intra_trade_low = 0 nloss_array = 0.0 long_stop = 0 short_stop = 0 ask = 0 bid = 0 atr_value = 0 parameters = [ "hour_window", "minute_window", "open_window", "nloss_singnal", "rsi_length", "exit_dc_length", "sl_multiplier", "distance_line", "fixd_size", "atr_window" ] variables = [ "current_atr_stop", "last_atr_stop", "long_stop", "short_stop", "atr_entry", "atr_value", "ask", "bid" ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.atr_stop_array = np.zeros(10) self.bg_xhour = NewBarGenerator(on_bar=self.on_bar, window=self.hour_window, on_window_bar=self.on_xhour_bar, interval=Interval.HOUR) self.am_hour = ArrayManager() self.bg_xminute = NewBarGenerator(on_bar=self.on_bar, window=self.minute_window, on_window_bar=self.on_xminute_bar) self.am_xminute = ArrayManager() self.bg_open = NewBarGenerator(on_bar=self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar) self.am_open = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(10) self.put_event() 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_open.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xhour.update_bar(bar) self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_5min_bar(self, bar: BarData): self.cancel_all() self.am_open.update_bar(bar) if not self.am_open.inited or not self.am_xminute.inited or not self.am_hour.inited: return self.atr_value = self.am_open.atr(self.atr_window) if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price up_limit = self.current_atr_stop * (1 + self.distance_line / 100) down_limit = self.current_atr_stop * (1 - self.distance_line / 100) if self.atr_entry > 0 and self.rsi_entry > 0 and bar.close_price < up_limit: self.buy(up_limit, self.fixd_size, True) elif self.atr_entry < 0 and self.rsi_entry < 0 and bar.close_price > down_limit: self.short(down_limit, self.fixd_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 long_stop_high = self.intra_trade_high - self.atr_value * self.sl_multiplier self.long_stop = max(self.exit_up, long_stop_high) 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) short_stop_low = self.intra_trade_low + self.atr_value * self.sl_multiplier self.short_stop = min(self.exit_dowm, short_stop_low) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xminute_bar(self, bar: BarData): """ :param bar: :return: """ self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length) ema_array = talib.EMA(self.am_xminute.close, self.rsi_length) dev_array = abs(self.am_xminute.close[:-1] - ema_array[:-1]) / rsi_array rsi_up_array = rsi_array + rsi_array * dev_array rsi_dow_array = rsi_array - rsi_array * dev_array self.rsi_value = self.am_xminute.rsi(self.rsi_length, True) self.rsi_up = rsi_up_array[-1] self.rsi_dow = rsi_dow_array[-1] current_rsi_up = rsi_up_array[-1] last_rsi_up = rsi_up_array[-2] current_rsi_down = rsi_dow_array[-1] last_rsi_down = rsi_dow_array[-2] current_rsi_value = self.rsi_value[-1] last_rsi_value = self.rsi_value[-2] if (current_rsi_value > current_rsi_up) and (last_rsi_value <= last_rsi_up): self.rsi_entry = 1 elif (current_rsi_value < current_rsi_down) and (last_rsi_value >= last_rsi_down): self.rsi_entry = -1 else: self.rsi_entry = 0 # print(self.rsi_entry) self.exit_dowm, self.exit_up = self.am_xminute.donchian( self.exit_dc_length) def on_xhour_bar(self, bar: BarData): """""" am_hour = self.am_hour am_hour.update_bar(bar) self.atr_stop_array[:-1] = self.atr_stop_array[1:] if not am_hour.inited: return # 计算轨道线 nloss self.ema_array = am_hour.ema(3, array=True) self.nloss_array = am_hour.atr(16, array=True) * self.nloss_singnal # 计算轨道线 self.atr_stop_array = self.atrstop(am_hour.close, self.atr_stop_array, self.nloss_array) # print(self.atr_stop_array) # 初始化 if self.atr_stop_array[-3] == 0: return self.current_atr_stop = self.atr_stop_array[-1] self.last_atr_stop = self.atr_stop_array[-2] current_ema = self.ema_array[-1] last_ema = self.ema_array[-2] if current_ema > self.current_atr_stop and last_ema <= self.last_atr_stop: self.atr_entry = 1 elif current_ema < self.current_atr_stop and last_ema >= self.last_atr_stop: self.atr_entry = -1 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. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event() def atrstop(self, close, atrstop, nlossatr): # 计算轨道线 if (close[-1] > atrstop[-2]) and (close[-2] > atrstop[-2]): atrstop[-1] = max(atrstop[-2], close[-1] - nlossatr[-1]) elif (close[-1] < atrstop[-2]) and (close[-2] < atrstop[-2]): atrstop[-1] = min(atrstop[-2], close[-1] + nlossatr[-1]) elif (close[-1] > atrstop[-2]): atrstop[-1] = (close[-1] - nlossatr[-1]) else: atrstop[-1] = (close[-1] + nlossatr[-1]) return atrstop
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 TurtleSignal(object): """""" # ---------------------------------------------------------------------- def __init__(self, entryWindow, exitWindow, entryDev, exitDev, rsiWindow, rsiSignal): """Constructor""" self.entryWindow = entryWindow self.exitWindow = exitWindow self.entryDev = entryDev self.exitDev = exitDev self.rsiWindow = rsiWindow self.rsiSignal = rsiSignal self.am = ArrayManager(60) self.atrVolatility = 0 self.entryUp = 0 self.entryDown = 0 self.exitUp = 0 self.exitDown = 0 self.rsiValue = 0 self.unit = 0 self.result = None self.lastResult = None # ---------------------------------------------------------------------- def onBar(self, bar): """""" self.am.update_bar(bar) if not self.am.inited: return self.generateSignal(bar) self.calculateIndicator() # ---------------------------------------------------------------------- def calculateIndicator(self): """""" keltnerEntryUp, keltnerEntryDown = self.am.keltner( self.entryWindow, self.entryDev) keltnerExitUp, keltnerExitDown = self.am.keltner( self.exitWindow, self.exitDev) donchianEntryUp, donchianEntryDown = self.am.donchian(self.entryWindow) donchianExitUp, donchianExitDown = self.am.donchian(self.exitWindow) self.entryUp = max(donchianEntryUp, keltnerEntryUp) self.entryDown = min(donchianEntryDown, keltnerEntryDown) self.exitUp = min(keltnerExitUp, donchianExitUp) self.exitDown = max(keltnerExitDown, donchianExitDown) self.rsiValue = self.am.rsi(self.rsiWindow) # ---------------------------------------------------------------------- def generateSignal(self, bar): """""" # 平仓 if self.unit > 0: if bar.low_price <= self.exitDown: self.close(self.exitDown) if self.unit < 0: if bar.high_price >= self.exitUp: self.close(self.exitUp) # 开仓 else: if self.rsiValue >= (50 + self.rsiSignal): if bar.high_price >= self.entryUp: self.open(self.entryUp, 1) elif self.rsiValue <= (50 - self.rsiSignal): if bar.low_price <= self.entryDown: self.open(self.entryDown, -1) # ---------------------------------------------------------------------- def open(self, price, change): """""" self.unit += change if not self.result: self.result = TurtleResult() self.result.open(price, change) # ---------------------------------------------------------------------- def close(self, price): """""" self.unit = 0 self.result.close(price) self.lastResult = self.result self.result = None # ---------------------------------------------------------------------- def getLastPnl(self): """""" if not self.lastResult: return 0 return self.lastResult.pnl
class AtrStop_Ut(CtaTemplate): """""" author = "yunya" atrstop_window = 46 open_window = 5 nloss_singnal = 2.7 trailing_tax = 2.0 risk_level = 5000 exit_dc_length = 50 atr_length = 30 atrstop_entry = 0 current_atr_stop = 0.0 last_atr_stop = 0.0 intra_trade_high = 0 intra_trade_low = 0 nloss_array = 0.0 long_stop = 0 short_stop = 0 trading_size = 0 exit_down = 0 exit_up = 0 ask = 0 bid = 0 atr_value = 0 count = 0 parameters = [ "atrstop_window", "open_window", "nloss_singnal", "trailing_tax", "risk_level", "exit_dc_length", "atr_length" ] variables = [ "atrstop_entry", "current_atr_stop", "last_atr_stop", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "exit_down", "exit_up", "trading_size", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.atr_stop_array = np.zeros(10) self.bg_xmin = NewBarGenerator(self.on_bar, window=self.atrstop_window, on_window_bar=self.on_xmin_bar, interval=Interval.MINUTE) self.am_xmin = ArrayManager() self.bg_5min = BarGenerator(self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar) self.am_5min = ArrayManager(self.exit_dc_length * int(self.atr_length / self.open_window) + 10) self.inited_atr_stop = False def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(10) # self.put_event() 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_5min.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xmin.update_bar(bar) self.bg_5min.update_bar(bar) def on_5min_bar(self, bar: BarData): self.cancel_all() self.am_5min.update_bar(bar) if not self.am_5min.inited or not self.am_xmin.inited: return if self.atr_stop_array[-3] == 0: return self.exit_up, self.exit_down = self.am_5min.donchian( self.exit_dc_length * int(self.atr_length / self.open_window)) # print(f"dc上轨:{self.exit_up},下轨:{self.exit_down}") if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.atrstop_entry > 0: self.buy(self.current_atr_stop, self.trading_size, True) elif self.atrstop_entry < 0: self.short(self.current_atr_stop, self.trading_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) long_high = self.intra_trade_high * \ (1 - self.trailing_tax / 100) self.long_stop = max(self.exit_down, long_high) self.sell(self.long_stop, abs(self.pos), True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_low = self.intra_trade_low * \ (1 + self.trailing_tax / 100) self.short_stop = min(self.exit_up, short_low) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xmin_bar(self, bar: BarData): """""" am_xmin = self.am_xmin am_xmin.update_bar(bar) self.atr_stop_array[:-1] = self.atr_stop_array[1:] if not am_xmin.inited: return # 计算轨道线 nloss self.nloss_array = am_xmin.atr(30, array=True) * self.nloss_singnal # 计算轨道线 self.atr_stop_array = self.atrstop(am_xmin.close, self.atr_stop_array, self.nloss_array) # 初始化 atr_stop_array 保证前三个有值 if self.count < 4: self.count += 1 return self.current_atr_stop = self.atr_stop_array[-1] self.last_atr_stop = self.atr_stop_array[-2] current_bar = self.am_xmin.close[-1] if self.current_atr_stop > self.last_atr_stop and current_bar > self.current_atr_stop: self.atrstop_entry = 1 elif self.current_atr_stop < self.last_atr_stop and current_bar < self.current_atr_stop: self.atrstop_entry = -1 else: self.atrstop_entry = 0 if self.pos == 0: self.atr_value = self.am_xmin.atr(self.atr_length) self.trading_size = max(int(self.risk_level / self.atr_value), 1) self.sync_data() 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. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event() def atrstop(self, close, atrstop, nlossatr): # 计算轨道线 if (close[-1] > atrstop[-2]) and (close[-2] > atrstop[-2]): atrstop[-1] = max(atrstop[-2], close[-1] - nlossatr[-1]) elif (close[-1] < atrstop[-2]) and (close[-2] < atrstop[-2]): atrstop[-1] = min(atrstop[-2], close[-1] + nlossatr[-1]) elif (close[-1] > atrstop[-2]): atrstop[-1] = (close[-1] - nlossatr[-1]) else: atrstop[-1] = (close[-1] + nlossatr[-1]) return atrstop
class MomentumHunterStrategy(CtaTemplate): """""" author = "KEKE" boll_window = 36 boll_dev = 2 atr_window = 30 atr_ma_window = 20 exit_window = 40 rsi_window = 30 rsi_entry = 14 dis_open = 56 dis_salir = 10 ultosc_entry = 14 fixed_size = 10 boll_up = 0 boll_down = 0 rsi_trend = 0 atr_value = 0 exit_up = 0 exit_down = 0 aroonosc_value = 0 trading_size = 0 parameters = [ "boll_window", "boll_dev", "atr_window", "dis_open", "dis_salir", "exit_window", "rsi_window", "rsi_entry", "ultosc_entry", "fixed_size" ] variables = [ "boll_up", "boll_down", "atr_value", "rsi_trend", "exit_up", "exit_down", "aroonosc_value", "trading_size" ] 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, 30, self.on_30min_bar) self.am = ArrayManager() self.bg2 = BarGenerator(self.on_bar, 60, self.on_60min_bar) self.am2 = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.rsi_buy = 50 + self.rsi_entry self.rsi_sell = 50 - self.rsi_entry self.ultosc_buy = 50 + self.ultosc_entry self.ultosc_sell = 50 - self.ultosc_entry 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) self.bg2.update_bar(bar) def on_30min_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.aroonosc_value = am.aroonosc(self.boll_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) atr_array = am.atr(self.atr_window, array=True) self.atr_value = atr_array[-1] self.atr_ma = atr_array[-self.atr_ma_window:].mean() if self.pos == 0: self.trading_size = self.fixed_size * bar.close_price if self.atr_value > self.atr_ma and self.rsi_trend > 0: if self.aroonosc_value > self.dis_open: self.buy(bar.close_price + 10, self.trading_size) elif self.atr_value > self.atr_ma and self.rsi_trend < 0: if self.aroonosc_value < -self.dis_open: self.short(bar.close_price - 10, self.trading_size) elif self.pos > 0: if bar.low_price < (self.exit_down + self.dis_salir): self.sell(bar.close_price - 10, abs(self.pos)) elif self.pos < 0: if bar.high_price > (self.exit_up - self.dis_salir): self.cover(bar.close_price + 10, abs(self.pos)) self.put_event() def on_60min_bar(self, bar: BarData): """""" am2 = self.am2 am2.update_bar(bar) if not am2.inited: return ultosc_value = am2.ultosc() rsi_value = am2.rsi(self.rsi_window) if rsi_value > self.rsi_buy and ultosc_value > self.ultosc_buy: self.rsi_trend = 1 elif rsi_value < self.rsi_sell and ultosc_value < self.ultosc_sell: self.rsi_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 DudlThrust_NewStrategy(CtaTemplate): """""" author = "yunyu" window_min = 15 rolling_period = 70 upper_open = 0.5 lower_open = 0.6 stop_multiplier = 1.8 dc_length = 30 cci_length = 10 cci_stop = 20 trailing_tax = 1.8 fixed_size = 1 up = 0 down = 0 exit_shour = 0 exit_long = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 long_entry = 0 short_entry = 0 long_out = 0 short_out = 0 cci_value = 0 ask = 0 bid = 0 parameters = [ "window_min", "rolling_period", "upper_open", "lower_open", "stop_multiplier", "dc_length", "cci_length", "cci_stop", "trailing_tax", "fixed_size", ] variables = [ "up", "down", "exit_shour", "exit_long", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "long_entry", "short_entry", "long_out", "short_out", "cci_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(on_bar=self.on_bar) self.am = ArrayManager( (max(self.dc_length, self.rolling_period) + 10) * 60) self.bg_xmin = BarGenerator(on_bar=self.on_bar, window=self.window_min, on_window_bar=self.on_xmin_bar) self.am_xmin = ArrayManager( max(self.dc_length, self.rolling_period) + 10) 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) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xmin.update_bar(bar) self.cancel_all() self.exit_shour, self.exit_long = self.am.donchian(self.dc_length * 60) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.cci_value > self.cci_stop: self.buy(self.up, self.fixed_size, True) elif self.cci_value < -self.cci_stop: self.short(self.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_out = self.intra_trade_high * (1 - self.trailing_tax / 100) self.long_stop = max(self.long_entry, self.long_out, self.exit_long) 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_out = self.intra_trade_low * (1 + self.trailing_tax / 100) self.short_stop = min(self.short_entry, self.short_out, self.exit_shour) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xmin_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am_xmin.update_bar(bar) if not self.am_xmin.inited: return self.up, self.down = self.dualthrust(self.am_xmin.high, self.am_xmin.low, self.am_xmin.close, self.am_xmin.open, self.rolling_period, self.upper_open, self.lower_open) self.cci_value = self.am_xmin.cci(self.cci_length) self.atr_value = self.am.atr(16) 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: long_price = trade.price self.long_entry = long_price - self.stop_multiplier * self.atr_value else: short_price = trade.price self.short_entry = short_price + self.stop_multiplier * self.atr_value self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass # self.put_event() def market_order(self): """""" pass # self.buy(self.last_tick.limit_up, 1) # self.write_log("执行市价单测试") def limit_order(self): """""" pass # self.buy(self.last_tick.limit_down, 1) # self.write_log("执行限价单测试") def stop_order(self): """""" pass # self.buy(self.last_tick.ask_price_1, 1, True) # self.write_log("执行停止单测试") def dualthrust(self, high, low, close, open, n, k1, k2): """ :param high: :param low: :param close: :return: """ #计算N日最高价的最高价,收盘价的最高价、最低价,最低价的最低价 hh = high[-n:-1].max() lc = close[-n:-1].min() hc = close[-n:-1].max() ll = low[-n:-1].max() #计算range,上下轨的距离前一根K线开盘价的距离 range = max(hh - lc, hc - ll) up = open[-2] + k1 * range down = open[-2] - k2 * range return up, down
class TurtleEStrategy(CtaTemplate): """""" # 改版海龟信号-吊灯止损法出场 author = "turtle_entry_following_stop" entry_window = 50 exit_window = 20 atr_window = 20 # stop_multiple = 10 fixed_size = 1 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 sl_multiplier = 3 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = [ "entry_window", "exit_window", "atr_window", "fixed_size", "sl_multiplier" ] variables = ["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.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) 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.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) self.atr_value = self.am.atr(self.atr_window) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) 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_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 - self.stop_multiple * self.atr_value # else: # self.short_entry = trade.price # self.short_stop = self.short_entry + self.stop_multiple * self.atr_value 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 send_buy_orders(self, price): """""" self.buy(price, self.fixed_size, True) def send_short_orders(self, price): """""" self.short(price, self.fixed_size, True)
class MacdBollDcStrategy(CtaTemplate): """""" author = "云崖" open_window = 2 xminute_window = 15 xhour_window = 1 fast_length = 14 show_length = 28 boll_length = 20 boll_dev = 2.0 dc_length = 30 trailing_tax = 2.0 fixed_size = 1 macd_inited = 0 boll_up = 0 boll_down = 0 dc_up = 0 dc_down = 0 exit_long = 0 exit_short = 0 long_stop = 0 short_stop = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "open_window", "xminute_window", "xhour_window", "fast_length", "show_length", "boll_length", "boll_dev", "dc_length", "trailing_tax", "fixed_size", ] variables = [ "macd_inited", "boll_up", "boll_down", "dc_up", "dc_down", "exit_long", "exit_short", "long_stop", "short_stop", ] def __init__(self, cta_engine, strategy_nam_xminutee, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_nam_xminutee, vt_symbol, setting) self.bg_open = NewBarGenerator(self.on_bar, self.open_window, self.on_open_bar) self.am_open = ArrayManager() self.bg_xminute = NewBarGenerator(self.on_bar, self.xminute_window, self.on_xminute_bar) self.am_xminute = ArrayManager(150) self.bg_xhour = NewBarGenerator(self.on_bar, self.xhour_window, self.on_xhour_bar, interval=Interval.HOUR) self.am_xhour = 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) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xhour.update_bar(bar) self.bg_xminute.update_bar(bar) 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_xminute.inited or not self.am_open.inited: return if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 if self.macd_inited > 0: self.buy(self.boll_up, self.fixed_size, True) elif self.macd_inited < 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 long_high = self.intra_trade_high * (1 - self.trailing_tax / 100) self.long_stop = max(self.exit_long, long_high) 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) stop_low = self.intra_trade_low * (1 + self.trailing_tax / 100) self.short_stop = min(self.exit_short, stop_low) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xminute_bar(self, bar: BarData): """""" self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return self.boll_up, self.boll_down = self.am_xminute.boll( self.boll_length, self.boll_dev) self.exit_short, self.exit_long = self.am_xminute.donchian( self.dc_length) def on_xhour_bar(self, bar: BarData): """ :param bar: :type bar: :return: :rtype: """ self.am_xhour.update_bar(bar) if self.am_xhour.inited: return fast_ema_value = self.am_xhour.ema(self.fast_length, True) show_ema_value = self.am_xhour.ema(self.show_length, True) diff = fast_ema_value - show_ema_value macd_diff = (fast_ema_value - show_ema_value) / show_ema_value * 100 if diff[-2] > macd_diff[-2]: self.macd_inited = 1 elif diff[-2] < macd_diff[-2]: self.macd_inited = -1 def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() 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. """ self.put_event()
class BollVixV2(CtaTemplate): """""" author = "yunya" open_window = 15 boll_length = 510 fixed_size = 1 boll_mid_current = 0 boll_mid_last = 0 boll_up_current = 0 boll_up_last = 0 boll_down_current = 0 boll_down_last = 0 target_pos = 0 pos_inited = 0 boll_mid = 0 # 画图专用 time_list = [] open_list = [] high_list = [] low_list = [] close_list = [] volume_list = [] up_list = [] down_list = [] mid_list = [] mid_new_list = [] bias_value_list = [] bias_list = [] singnal_plot = [] singnal_list = None singnal = None plot_echarts = {} parameters = [ "open_window", "boll_length", "fixed_size", ] variables = [ "boll_mid_current", "boll_mid_last", "boll_up_current", "boll_up_last", "boll_down_current", "boll_down_last", "pos_inited", "target_pos" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_minute_bar, interval=Interval.MINUTE) self.am = ArrayManager(self.boll_length * 2) self.up_array: np.ndarray = np.zeros(5) self.down_array: np.ndarray = np.zeros(5) self.boll_inited = False self.boll_count = 0 self.engine_type = self.get_engine_type() self.vt_orderids = [] self.order_price = 0 self.pos_inited = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(12) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) # 只有实盘交易才使用BestLimit算法 if self.engine_type != EngineType.LIVE: return # 当前没有仓位 order_volume_open = self.target_pos - self.pos if not order_volume_open: return if order_volume_open > 0: if not self.vt_orderids: self.order_price = tick.bid_price_1 vt_orderids = self.buy(self.order_price, abs(order_volume_open)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.bid_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) elif order_volume_open < 0: if not self.vt_orderids: self.order_price = tick.ask_price_1 vt_orderids = self.short(self.order_price, abs(order_volume_open)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.ask_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_minute_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算布林 sma_array = self.am.sma(self.boll_length, True) std_array = self.am.std(self.boll_length, True) dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1] # dev_max = dev[-self.boll_length:].max() dev_max = dev[-self.boll_length:].mean() up = sma_array + std_array * dev_max down = sma_array - std_array * dev_max boll_length = self.boll_length / 2 boll_mid_array = self.am.sma(self.boll_length, True) dc_up, dc_down = self.am.donchian(self.dc_length, True) self.exit_long = dc_up[-2] self.exit_short = dc_down[-2] # 计算数组 self.boll_mid = boll_mid_array[-2] self.boll_up_current = up[-1] self.boll_up_last = up[-2] self.boll_down_current = down[-1] self.boll_down_last = down[-2] if not self.pos: self.pos_inited = 0 if self.am.close[-1] > self.boll_up_current and self.am.close[ -2] <= self.boll_up_last: if self.engine_type == EngineType.BACKTESTING: self.buy(bar.close_price, self.fixed_size) else: self.target_pos = self.fixed_size print("没有仓位,我开多") elif self.am.close[-1] < self.boll_down_current and self.am.close[ -2] >= self.boll_down_last: if self.engine_type == EngineType.BACKTESTING: self.short(bar.close_price, self.fixed_size) else: self.target_pos = -self.fixed_size print("没有仓位,我开空") elif self.pos > 0: self.exit_long = max(self.exit_long, self.boll_mid) self.sell(self.boll_mid, abs(self.pos), True) elif self.pos < 0: self.exit_short = min(self.exit_short, self.boll_mid) self.cover(self.boll_mid, abs(self.pos), True) # 画图专用 if self.singnal != self.singnal_list: plot = self.singnal else: plot = None self.time_list.append(bar.datetime) self.open_list.append(bar.open_price) self.high_list.append(bar.high_price) self.low_list.append(bar.low_price) self.close_list.append(bar.close_price) self.volume_list.append(bar.volume) self.up_list.append(self.boll_up_current) self.down_list.append(self.boll_down_current) self.mid_list.append(self.boll_mid) self.singnal_plot.append(plot) self.plot_echarts = { "datetime": self.time_list, "open": self.open_list, "high": self.high_list, "low": self.low_list, "close": self.close_list, "volume": self.low_list, "boll_up": self.up_list, "boll_down": self.down_list, "boll_mid": self.mid_list, "signal": self.singnal_plot } self.singnal_list = self.singnal self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction.value == Direction.LONG.value: if trade.offset.value == Offset.OPEN.value: self.singnal = 1 elif trade.offset.value == Offset.CLOSE.value: self.singnal = 0 else: self.singnal = None elif trade.direction.value == Direction.SHORT.value: if trade.offset.value == Offset.OPEN.value: self.singnal = -1 elif trade.offset.value == Offset.CLOSE.value: self.singnal = 0 else: self.singnal = None def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def boll_calculate(self): """ 计算布林 :return: """ if not self.boll_inited: self.boll_count += 1 if self.boll_count >= 6: self.boll_inited = True self.up_array[:-1] = self.up_array[1:] self.down_array[:-1] = self.down_array[1:] sma_array = self.am.sma(self.boll_length, True) std_array = self.am.std(self.boll_length, True) dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_length:].max() up = sma_array[-1] + std_array[-1] * dev_max down = sma_array[-1] - std_array[-1] * dev_max self.up_array[-1] = up self.down_array[-1] = down
class SuperTurtleStrategyHNTest(CtaTemplate): """""" author = "Huang Ning" entry_window = 28 exit_window = 7 atr_window = 4 risk_level = 0.2 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 = [ "entry_up", "entry_down", "exit_up", "exit_down", "trading_size", "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, 1, self.on_hour_bar, interval=Interval.HOUR) self.am = ArrayManager() def on_init(self): """""" self.write_log("策略初始化") self.load_bar(20) 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_hour_bar(self, bar: BarData): """""" 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) 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 self.buy(self.entry_up, self.trading_size, True) 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
class AtrStop_Dc_Strategy(CtaTemplate): """""" author = "yunya" atrstop_window = 46 open_window = 5 distance_line = 2.0 nloss_singnal = 2.7 dc_length = 50 fixd_size = 1 atr_window = 30 atr_entry = 0 current_atr_stop = 0.0 last_atr_stop = 0.0 nloss_array = 0.0 exit_short = 0 exit_long = 0 ask = 0 bid = 0 atr_value = 0 parameters = [ "atrstop_window", "open_window", "nloss_singnal", "dc_length", "distance_line", "fixd_size", "atr_window" ] variables = [ "current_atr_stop", "last_atr_stop", "exit_short", "exit_long", "atr_entry", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.atr_stop_array = np.zeros(10) self.bg_xmin = NewBarGenerator( self.on_bar, window=self.atrstop_window, on_window_bar=self.on_xmin_bar ) self.am_xmin = ArrayManager() self.bg_5min = BarGenerator( self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar ) self.am_5min = 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_5min.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xmin.update_bar(bar) self.bg_5min.update_bar(bar) def on_5min_bar(self, bar: BarData): self.cancel_all() self.am_5min.update_bar(bar) if not self.am_5min.inited or not self.am_xmin.inited: return if self.atr_stop_array[-3] == 0: return self.atr_value = self.am_5min.atr(self.atr_window) if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price up_limit = self.current_atr_stop * (1 + self.distance_line / 100) down_limit = self.current_atr_stop * (1 - self.distance_line / 100) if self.atr_entry > 0 and bar.close_price < up_limit: self.buy(self.current_atr_stop, self.fixd_size, True) elif self.atr_entry < 0 and bar.close_price > down_limit: self.short(self.current_atr_stop, self.fixd_size, True) elif self.pos > 0: self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: self.cover(self.exit_short, abs(self.pos), True) self.put_event() def on_xmin_bar(self, bar: BarData): """""" am_xmin = self.am_xmin am_xmin.update_bar(bar) self.atr_stop_array[:-1] = self.atr_stop_array[1:] if not am_xmin.inited: return # 计算轨道线 nloss self.ema_array = am_xmin.ema(3, array=True) self.nloss_array = am_xmin.atr(16, array=True) * self.nloss_singnal # 计算轨道线 self.atr_stop_array = self.atrstop( am_xmin.close, self.atr_stop_array, self.nloss_array ) # 初始化 if self.atr_stop_array[-3] == 0: return self.current_atr_stop = self.atr_stop_array[-1] self.last_atr_stop = self.atr_stop_array[-2] current_ema = self.ema_array[-1] last_ema = self.ema_array[-2] if last_ema <= self.last_atr_stop and current_ema > self.current_atr_stop: self.atr_entry = 1 elif last_ema >= self.last_atr_stop and current_ema < self.current_atr_stop: self.atr_entry = -1 self.exit_short,self.exit_long = self.am_xmin.donchian(self.dc_length) 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. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event() def atrstop(self, close, atrstop, nlossatr): # 计算轨道线 if (close[-1] > atrstop[-2]) and (close[-2] > atrstop[-2]): atrstop[-1] = max(atrstop[-2], close[-1] - nlossatr[-1]) elif (close[-1] < atrstop[-2]) and (close[-2] < atrstop[-2]): atrstop[-1] = min(atrstop[-2], close[-1] + nlossatr[-1]) elif (close[-1] > atrstop[-2]): atrstop[-1] = (close[-1] - nlossatr[-1]) else: atrstop[-1] = (close[-1] + nlossatr[-1]) return atrstop
class TurtleSignalStrategy(CtaTemplate): """""" author = "用Python的交易员" # 唐奇安上下轨突破的周期,买入位置 entry_window = 20 # 唐奇安通道,卖出位置 exit_window = 10 atr_window = 20 # 乘数,每次下单的单位大小 fixed_size = 1 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", "fixed_size"] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TurtleSignalStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) 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.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding # 没有持仓时才计算入场价 if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 # 下本地止损单,等到突破或者跌破成交 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) elif self.pos > 0: # 如果之前有多头突破单成交,下单,根据atr加仓. # 不用考虑历史仓位,默认前面都是按照规则正确下单成交的仓位,不考虑未成交情况 self.send_buy_orders(self.entry_up) # 止损价和止盈退出价中的大的一方 sell_price = max(self.long_stop, self.exit_down) # 下多头止盈单 self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: # 如果之前有空仓,加仓 self.send_short_orders(self.entry_down) 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. """ print( f"海龟交易,{trade.tradeid}, {trade.price}, {trade.direction}, {trade.time}" ) 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 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 send_buy_orders(self, price): """""" t = self.pos / self.fixed_size if t < 1: self.buy(price, self.fixed_size, True) if t < 2: self.buy(price + self.atr_value * 0.5, self.fixed_size, True) if t < 3: self.buy(price + self.atr_value, self.fixed_size, True) if t < 4: self.buy(price + self.atr_value * 1.5, self.fixed_size, True) def send_short_orders(self, price): """""" t = self.pos / self.fixed_size if t > -1: self.short(price, self.fixed_size, True) if t > -2: self.short(price - self.atr_value * 0.5, self.fixed_size, True) if t > -3: self.short(price - self.atr_value, self.fixed_size, True) if t > -4: self.short(price - self.atr_value * 1.5, self.fixed_size, True)
class MacdRsibollDcMinuteStrategy(CtaTemplate): """ 策略逻辑: 一、、过虑信号 (小时周期) 1、使用macd 快慢线交叉来判断多空大方向。 2、使用rsiboll来判断信号强弱 二、开单信号 (分钟周期) 1、使用布林上下轨作为开单条件 三、止损 1、使用固定止损 2、dc 移动止损 3、布林宽度比例 三个止损相结合的方式 """ author = "yunya" max_window = 45 min_window = 15 open_window = 5 fast_macd = 12 slow_macd = 26 signal_macd = 9 macd_trend_level = 1.0 rsi_length = 15 boll_length = 20 boll_dev = 2.0 dc_length = 20 atr_window = 30 trailing_tax = 2.0 risk_level = 1 exit_down = 0 exit_up = 0 macd = 0 macd_entry = 0 rsi_entry = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "max_window", "min_window", "open_window", "fast_macd", "slow_macd", "signal_macd", "macd_trend_level", "boll_length", "boll_dev", "rsi_length", "dc_length", "atr_window", "trailing_tax", "risk_level", ] variables = [ "exit_down", "exit_up", "macd", "macd_entry", "rsi_entry", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "atr_value", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.atr_stop_array = np.zeros(10) self.bg_xhour = NewBarGenerator( on_bar=self.on_bar, window=self.max_window, on_window_bar=self.on_xhour_bar, interval=Interval.MINUTE # 由小时修改到分钟级 ) self.am_hour = ArrayManager(self.boll_length + 100) self.bg_xminute = NewBarGenerator( on_bar=self.on_bar, window=self.min_window, on_window_bar=self.on_xminute_bar ) self.am_xminute = ArrayManager(self.boll_length + 100) self.bg_open = NewBarGenerator( on_bar=self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar ) self.am_open = ArrayManager(self.dc_length * int(self.min_window / self.open_window) + 30) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(10) self.put_event() 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_open.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xhour.update_bar(bar) self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_5min_bar(self, bar: BarData): self.cancel_all() self.am_open.update_bar(bar) if not self.am_open.inited or not self.am_xminute.inited or not self.am_hour.inited: return # self.exit_up, self.exit_down = self.am_open.donchian( self.dc_length * int(self.min_window / self.open_window)) if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.macd_entry > 0 and self.rsi_entry > 0: self.buy(self.boll_up, self.trading_size, True) # print(bar.datetime, self.boll_up, self.trading_size) # print(bar.datetime, self.entry_up, self.trading_size, bar) if self.macd_entry < 0 and self.rsi_entry < 0: 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) long_high = self.intra_trade_high * \ (1 - self.trailing_tax / 100) self.long_stop = max(self.exit_down, long_high) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_low = self.intra_trade_low * \ (1 + self.trailing_tax / 100) self.short_stop = min(self.exit_up, short_low) self.cover(short_low, abs(self.pos), True) self.put_event() def on_xminute_bar(self, bar: BarData): """ :param bar: :return: """ self.am_xminute.update_bar(bar) if not self.am_hour.inited or not self.am_xminute.inited: return rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length) ema_array = talib.EMA(self.am_xminute.close, self.rsi_length) dev_array = abs(self.am_xminute.close[:-1] - ema_array[:-1]) / rsi_array rsi_up_array = rsi_array + rsi_array * dev_array rsi_dow_array = rsi_array - rsi_array * dev_array self.rsi_value = self.am_xminute.rsi(self.rsi_length, True) self.rsi_up = rsi_up_array[-1] self.rsi_dow = rsi_dow_array[-1] current_rsi_up = rsi_up_array[-1] current_rsi_down = rsi_dow_array[-1] current_rsi_value = self.rsi_value[-1] if current_rsi_value > current_rsi_up: self.rsi_entry = 1 elif current_rsi_value < current_rsi_down: self.rsi_entry = -1 else: self.rsi_entry = 0 self.boll_up, self.boll_down = self.am_xminute.boll(self.boll_length, self.boll_dev) def on_xhour_bar(self, bar: BarData): """""" am_hour = self.am_hour am_hour.update_bar(bar) if not am_hour.inited: return macd_signal, signal, hist = self.am_hour.macd( self.fast_macd, self.slow_macd, self.signal_macd ) self.macd = signal - hist if self.macd > self.macd_trend_level: self.macd_entry = 1 elif self.macd < (-self.macd_trend_level): self.macd_entry = -1 else: self.macd_entry = 0 # 动态调整仓位 if not self.pos: self.atr_value = self.am_hour.atr(self.atr_window) if self.atr_value == 0: # 保证仓位值是有效的 return # 正向合约 atr_risk = self.am_hour.atr(self.atr_window) self.trading_size = max(int(self.risk_level / atr_risk), 1) 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. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event()
class RsiMomentumStrategy(CtaTemplate): """""" author = "用Python的交易员" atr_window = 16 atr_ma_window = 10 rsi_window = 4 rsi_entry = 19 risk_level = 5000 exit_window = 20 trading_size = 0 target_pos = 0 atr_value = 0 atr_ma = 0 rsi_value = 0 rsi_long = 0 rsi_short = 0 parameters = [ "atr_window", "atr_ma_window", "rsi_window", "rsi_entry", "exit_window" ] variables = [ "atr_value", "atr_ma", "rsi_value", "rsi_long", "rsi_short", "target_pos" ] 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, 1, self.on_hour_bar, interval=Interval.HOUR) self.am = ArrayManager() self.engine_type = self.get_engine_type() self.vt_orderids = [] self.order_price = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.rsi_long = 50 + self.rsi_entry self.rsi_short = 50 - self.rsi_entry 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) # 只有实盘交易才使用BestLimit算法 if self.engine_type != EngineType.LIVE: return order_volume = self.target_pos - self.pos if not order_volume: return if order_volume > 0: if not self.vt_orderids: self.order_price = tick.bid_price_1 vt_orderids = self.buy( self.order_price, abs(order_volume)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.bid_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) elif order_volume < 0: if not self.vt_orderids: self.order_price = tick.ask_price_1 vt_orderids = self.short( self.order_price, abs(order_volume) ) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.ask_price_1: self.cancel_order(self.vt_orderid) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_hour_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return atr_array = am.atr(self.atr_window, array=True) self.atr_value = atr_array[-1] self.atr_ma = atr_array[-self.atr_ma_window:].mean() self.rsi_value = am.rsi(self.rsi_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if self.pos == 0: self.trading_size = max(int(self.risk_level / self.atr_value), 1) if self.atr_value > self.atr_ma: if self.rsi_value > self.rsi_long: if self.engine_type == EngineType.BACKTESTING: self.buy(bar.close_price + 5, self.trading_size) else: self.target_pos = self.trading_size elif self.rsi_value < self.rsi_short: if self.engine_type == EngineType.BACKTESTING: self.short(bar.close_price - 5, self.trading_size) else: self.target_pos = -self.trading_size elif self.pos > 0: self.sell(self.exit_down, abs(self.pos), stop=True) elif self.pos < 0: self.cover(self.exit_up, abs(self.pos), stop=True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ # 只有实盘交易才使用BestLimit算法 if self.engine_type != EngineType.LIVE: return if not order.is_active() and order.vt_orderid in self.vt_orderids: self.vt_orderids.remove(order.vt_orderid) if not self.vt_orderids: self.order_price = 0 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 TurtleSignalStrategy(CtaTemplate): """""" author = "用Python的交易员" entry_window = 20 exit_window = 10 atr_window = 20 fixed_size = 1 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", "fixed_size"] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TurtleSignalStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) 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.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) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) elif self.pos > 0: self.send_buy_orders(self.long_entry) sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: self.send_short_orders(self.short_entry) 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 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 send_buy_orders(self, price): """""" t = self.pos / self.fixed_size if t < 1: self.buy(price, self.fixed_size, True) if t < 2: self.buy(price + self.atr_value * 0.5, self.fixed_size, True) if t < 3: self.buy(price + self.atr_value, self.fixed_size, True) if t < 4: self.buy(price + self.atr_value * 1.5, self.fixed_size, True) def send_short_orders(self, price): """""" t = self.pos / self.fixed_size if t > -1: self.short(price, self.fixed_size, True) if t > -2: self.short(price - self.atr_value * 0.5, self.fixed_size, True) if t > -3: self.short(price - self.atr_value, self.fixed_size, True) if t > -4: self.short(price - self.atr_value * 1.5, self.fixed_size, True)
class TurtleCStrategy(CtaTemplate): """""" # 反向海龟信号 author = "turtle_inverse_trade" entry_window = 50 exit_window = 20 atr_window = 20 stop_multiple = 2 fixed_size = 1 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", "fixed_size", "stop_multiple" ] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TurtleCStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) 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.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) # self.close_ma = self.am.sma(50) # self.entry_up += self.close_ma * 0.002 # self.entry_down -= self.close_ma * 0.002 self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) elif self.pos > 0: # inverse system # 有多头要卖出,等向上再卖出 self.sell(self.exit_up, abs(self.pos), False) elif self.pos < 0: # inverse system # 有空头要买回,等向下再补回 self.cover(self.exit_down, abs(self.pos), False) 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 - self.stop_multiple * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + self.stop_multiple * self.atr_value 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 send_buy_orders(self, price): """""" # invere system self.short(price, self.fixed_size, False) def send_short_orders(self, price): """""" # inverse system self.buy(price, self.fixed_size, False)
class TurtleSignalStrategyHNTest(CtaTemplate): """""" author = "Huang Ning" entry_window = 20 exit_window = 10 atr_window = 20 fixed_size = 1 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", "fixed_size" ] variables = [ "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.am = ArrayManager() self.buy_vt_orderids = [] self.sell_vt_orderids = [] self.short_vt_orderids = [] self.cover_vt_orderids = [] def on_init(self): """""" self.write_log("策略初始化") self.load_bar(20) 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.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window ) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) elif self.pos > 0: self.send_buy_orders(self.entry_up) sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: self.send_short_orders(self.entry_down) 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): """""" 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 def on_order(self, order: OrderData): """""" def on_stop_order(self, stop_order: StopOrder): """""" def send_buy_orders(self, price): """""" t = self.pos / self.fixed_size if t < 1: self.buy(price, self.fixed_size, True) if t < 2: self.buy(price + self.atr_value * 0.5, self.fixed_size, True) if t < 3: self.buy(price + self.atr_value, self.fixed_size, True) if t < 4: self.buy(price + self.atr_value * 1.5, self.fixed_size, True) def send_short_orders(self, price): """""" t = self.pos / self.fixed_size if t > -1: self.short(price, self.fixed_size, True) if t > -2: self.short(price - self.atr_value * 0.5, self.fixed_size, True) if t > -3: self.short(price - self.atr_value, self.fixed_size, True) if t > -4: self.short(price - self.atr_value * 1.5, self.fixed_size, True)