class DudlThrustEmaPositionStrategy(CtaTemplate): """""" author = "yunyu" open_window = 5 xminute_window = 30 rolling_period = 70 upper_open = 0.45 lower_open = 0.45 cci_length = 5 ema_length = 60 position_atr_length = 6 risk_level = 1000 # fixed_size = 1 trading_size = 0 atr_value = 0 up = 0 down = 0 current_ema = 0 last_ema = 0 ema_mid = 0 ema_new_value = 0 ema_length_new = 0 cci_value = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 current_close = 0 last_close = 0 front_close = 0 exit_long = 0 exit_short = 0 ask = 0 bid = 0 parameters = [ "open_window", "xminute_window", "rolling_period", "upper_open", "lower_open", "cci_length", "ema_length", "position_atr_length", "risk_level" ] variables = [ "trading_size", "up", "down", "current_ema", "last_ema", "ema_mid", "ema_new_value", "ema_length_new", "cci_value", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", "current_close", "last_close", "front_close", "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_open = BarGenerator(on_bar=self.on_bar, window=self.open_window, on_window_bar=self.on_open_bar) self.am_open = ArrayManager() self.bg = NewBarGenerator(on_bar=self.on_bar, window=self.xminute_window, on_window_bar=self.on_xmin_bar) self.am = ArrayManager(self.rolling_period + 50) 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 # 买一价 def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) self.bg_open.update_bar(bar) def on_open_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am_open.update_bar(bar) if not self.am.inited or not self.am_open.inited: return if self.pos == 0: self.cci_value = self.am.cci(self.cci_length) # 判断数据是否正常,如果atr 计算结果正常,才计算仓位,避免下单时下出不正常的数量 self.atr_value = self.am.atr(self.position_atr_length) if self.atr_value == 0: return self.trading_size = max(int(self.risk_level / self.atr_value), 1) if self.cci_value > 0: self.buy(self.up, self.trading_size, True) elif self.cci_value < 0: self.short(self.down, self.trading_size, True) elif self.pos > 0: con1 = bar.close_price < self.current_ema con2 = bar.close_price >= self.last_ema if con1 and con2: self.exit_long_nex = bar.close_price # 保存当前收盘价 if self.exit_long_last == 0 or self.exit_long_nex > self.exit_long_last: self.exit_long_last = self.exit_long_nex self.ema_length_new = self.ema_length self.exit_long = self.ema_mid else: if bar.close_price > ( (self.ema_mid + self.current_ema) / 2): self.exit_long = bar.close_price elif bar.close_price < self.ema_mid: self.exit_long = bar.close_price else: self.exit_long = self.ema_mid else: self.exit_long = self.ema_mid self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: con1 = bar.close_price > self.current_ema con2 = bar.close_price <= self.last_ema if con1 and con2: self.exit_short_nex = bar.close_price if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last: self.exit_short_last = self.exit_short_nex self.ema_length_new = self.ema_length self.exit_short = self.ema_mid else: if bar.close_price < (self.ema_mid + self.current_ema / 2): self.exit_short = bar.close_price elif bar.close_price < self.ema_mid: self.exit_short = bar.close_price else: self.exit_short = self.ema_mid else: self.exit_short = self.ema_mid self.cover(self.exit_short, abs(self.pos), True) self.put_event() self.sync_data() def on_xmin_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am.update_bar(bar) if not self.am.inited: return # 计算海龟 上轨,下轨 high_max = self.am.high[-self.rolling_period:].max() close_min = self.am.close[-self.rolling_period:].min() close_max = self.am.close[-self.rolling_period:].max() low_min = self.am.low[-self.rolling_period:].min() hc = high_max - close_min cl = close_max - low_min dual = max(hc, cl) self.up = self.am.open[-2] + dual * self.upper_open self.down = self.am.open[-2] - dual * self.upper_open # print(f"up:{self.up},{self.down}") self.current_close = self.am.close[-1] self.last_close = self.am.close[-2] self.front_close = self.am.close[-3] if self.pos == 0: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.ema_length_new = self.ema_length elif self.pos > 0: close_long = self.current_close > self.last_close > self.front_close if close_long: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) elif self.pos < 0: close_short = self.current_close < self.last_close < self.front_close if close_short: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) self.ema_mid = self.am.ema(self.ema_length) ema_mid_new = self.am.ema(self.ema_length_new, True) self.current_ema = ema_mid_new[-1] self.last_ema = ema_mid_new[-2] 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. """ pass 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
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 RsiAdaptStrategy(CtaTemplate): """ 策略逻辑: 一、、过虑信号 (小时周期) 使用rsiboll来判断信号强弱 二、开单信号 (分钟周期) 1、使用布林上下轨作为开单条件 三、止损 使用动态布林中轨止损 """ author = "yunya" min_window = 45 open_window = 15 rsi_length = 23 kk_length = 80 kk_dev = 2.0 trading_size = 1 atr_length = 30 rsi_entry = 0 kk_up = 0 kk_down = 0 long_stop = 0 short_stop = 0 rsi_value = 0 rsi_up = 0 rsi_dow = 0 ema_mid = 0 ema_length_new = 0 current_ema_mid = 0 last_ema_mid = 0 current_close = 0 last_close = 0 front_close = 0 exit_long = 0 exit_short = 0 long_entry = 0 short_entry = 0 long_stop_trade = 0 short_stop_drade = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 atr_value = 0 parameters = [ "open_window", "min_window", "rsi_length", "kk_length", "kk_dev", "trading_size", "atr_length", ] variables = [ "rsi_entry", "long_stop", "short_stop", "rsi_value", "rsi_up", "rsi_dow", "ema_mid", "ema_length_new", "current_ema_mid", "last_ema_mid", "current_close", "last_close", "front_close", "exit_long", "exit_short", "long_entry", "short_entry", "long_stop_trade", "short_stop_drade", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) 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.kk_length * 2 + 10) 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(30) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动。。") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止。。") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_open.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_5min_bar(self, bar: BarData): """ :param bar: :type bar: :return: :rtype: """ self.cancel_all() self.am_open.update_bar(bar) if not self.am_open.inited or not self.am_xminute.inited: return ema_mid_array = self.am_open.ema(self.kk_length, True) atr = self.am_open.atr(self.kk_length, True) kk_up_array = ema_mid_array + atr * self.kk_dev kk_down_array = ema_mid_array - atr * self.kk_dev self.ema_mid = ema_mid_array[-1] self.kk_up = kk_up_array[-1] self.kk_down = kk_down_array[-1] self.current_close = self.am_open.close[-1] self.last_close = self.am_open.close[-2] self.front_close = self.am_open.close[-3] if not self.pos: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.ema_length_new = self.kk_length self.atr_value = self.am_open.atr(self.atr_length) if self.rsi_entry > 0: self.buy(self.kk_up, self.trading_size, True) self.write_log( f"下多单:{bar.datetime}, {self.kk_up}, {self.trading_size}") elif self.rsi_entry < 0: self.short(self.kk_down, self.trading_size, True) self.write_log( f"下多单:{bar.datetime}, {self.kk_down}, {self.trading_size}") elif self.pos > 0: close_long = self.current_close > self.last_close > self.front_close if close_long: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) ema_mid_new = self.am_xminute.sma(self.ema_length_new, True) self.current_ema_mid = ema_mid_new[-1] self.last_ema_mid = ema_mid_new[-2] # 仓位是long 时,如果价格下穿新布林中轨 con1 = bar.close_price < self.current_ema_mid con2 = bar.close_price >= self.last_ema_mid if con1 and con2: self.exit_long_nex = bar.close_price # 保存当前收盘价 if self.exit_long_last == 0 or self.exit_long_nex > self.exit_long_last: self.exit_long_last = self.exit_long_nex self.ema_length_new = self.kk_length # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.ema_mid else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if bar.close_price > ( (self.ema_mid + self.current_ema_mid) / 2): self.exit_long = bar.close_price elif bar.close_price < self.ema_mid: self.exit_long = bar.close_price else: self.exit_long = self.ema_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.ema_mid self.long_stop = max(self.exit_long, self.long_stop_trade) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: close_short = self.current_close < self.last_close < self.front_close if close_short: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) ema_mid_new = self.am_xminute.sma(self.ema_length_new, True) self.current_ema_mid = ema_mid_new[-1] self.last_ema_mid = ema_mid_new[-2] # 仓位是short 时,如果价格上穿新布林中轨 con1 = bar.close_price > self.current_ema_mid con2 = bar.close_price <= self.last_ema_mid if con1 and con2: self.exit_short_nex = bar.close_price if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last: self.exit_short_last = self.exit_short_nex self.ema_length_new = self.kk_length self.exit_short = self.ema_mid else: if bar.close_price < (self.ema_mid + self.current_ema_mid / 2): self.exit_short = bar.close_price elif bar.close_price < self.ema_mid: self.exit_short = bar.close_price else: self.exit_short = self.ema_mid else: self.exit_short = self.ema_mid self.short_stop = min(self.exit_short, self.short_stop_drade) self.cover(self.short_stop, abs(self.pos), True) self.sync_data() 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 ema_array = talib.EMA(self.am_xminute.close, self.rsi_length) std_array = talib.EMA(self.am_xminute.close, self.rsi_length) dev_array = abs(self.am_xminute.close[:-1] - ema_array[:-1]) / std_array[:-1] dev_max = max(dev_array[-self.rsi_length:]) rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length) rsi_up_array = rsi_array + rsi_array * dev_max rsi_dow_array = rsi_array - rsi_array * dev_max rsi_value_array = self.am_xminute.rsi(self.rsi_length, True) self.rsi_up = rsi_up_array[-1] self.rsi_dow = rsi_dow_array[-1] self.rsi_value = rsi_value_array[-1] current_rsi = rsi_value_array[-1] last_rsi = rsi_value_array[-2] 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] con1 = current_rsi > current_rsi_up con2 = last_rsi <= last_rsi_up con3 = current_rsi < current_rsi_down con4 = last_rsi >= last_rsi_down if con1 > con2: self.rsi_entry = 1 elif con3 and con4: self.rsi_entry = -1 self.sync_data() 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_drade = self.short_entry + 2 * self.atr_value self.sync_data() 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 EmaStrategy(CtaTemplate): author = "CHENG LI" trade_money = 1000000 fixed_size = 1 bars = [] # exit_time = time(hour=14, minute=55) # for EMA algorithm fast_window = 12 slow_window = 48 fast_ema0 = 0.0 fast_ema1 = 0.0 slow_ema0 = 0.0 slow_ema1 = 0.0 # 菲阿里四价:昨日高点、昨日低点、昨天收盘、今天开盘 yesterday_high = 0.0 yesterday_low = 0.0 yesterday_close = 0.0 today_open = 0.0 short_stop_loss = 0.0 long_stop_loss = 0.0 parameters = ["fast_window", "slow_window", "trade_money"] variables = [ "fast_ema0", "fast_ema1", "slow_ema0", "slow_ema1", "yesterday_high", "yesterday_low", "yesterday_close", "today_open", "short_stop_loss", "long_stop_loss" ] def __init__(self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict): super(EmaStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_hour = BarGenerator(self.on_bar, window=1, on_window_bar=self.on_hour_bar, interval=Interval.HOUR) self.bg_day = BarGenerator(self.on_bar, window=24, on_window_bar=self.on_day_bar, interval=Interval.HOUR) self.am_hour = ArrayManager(100) self.am_day = ArrayManager(2) self.bars = [] def on_init(self): print("on init") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ print("on_start strategy") def on_tick(self, tick: TickData): self.bg_hour.update_tick(tick) self.bg_day.update_tick(tick) def on_bar(self, bar: BarData): self.bg_hour.update_bar(bar) self.bg_day.update_bar(bar) def on_day_bar(self, bar: BarData): """ 菲阿里四价算法实现 """ # bar 初始化 self.cancel_all() am = self.am_day am.update_bar(bar) if not am.inited: self.bars.append(bar) return self.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] # compute 4 different prices from data self.yesterday_high = last_bar.high_price self.yesterday_low = last_bar.low_price self.yesterday_close = last_bar.close_price self.today_open = bar.open_price # 设置多头止损 if self.today_open / self.yesterday_high > 1.005: # 如果当天开盘价大于昨天最高价 self.long_stop_loss = self.yesterday_high elif self.today_open / self.yesterday_high < 0.995: # 如果当天开盘价小于昨天最高价 self.long_stop_loss = self.today_open else: # 如果当天开盘价接近于昨天最高价 self.long_stop_loss = (self.yesterday_high + self.yesterday_low) / 2 # 设置多头止损为昨天中间价 # 设置空头止损 if self.today_open / self.yesterday_low < 0.995: # 如果当天开盘价小于昨天最低价 self.short_stop_loss = self.yesterday_low elif self.today_open / self.yesterday_low > 1.005: # 如果当天开盘价大于昨天最低价 self.short_stop_loss = self.today_open else: # 如果当天开盘价接近于昨天最低价 self.short_stop_loss = (self.yesterday_high + self.yesterday_low) / 2 self.put_event() def on_hour_bar(self, bar: BarData): # 确保day bar初始化 self.am_hour.update_bar(bar) if not self.am_hour.inited: return self.am_day.update_bar(bar) if not self.am_day.inited: return # compute exp. moving average fast_ema = self.am_hour.ema(self.fast_window, array=True) self.fast_ema0 = fast_ema[-1] # at T self.fast_ema1 = fast_ema[-2] # at T-1 slow_ema = self.am_hour.ema(self.slow_window, array=True) self.slow_ema0 = slow_ema[-1] self.slow_ema1 = slow_ema[-2] # identify trend: 1:bullish, -1:bearish, 0:sideways if self.fast_ema0 > self.slow_ema0 and self.fast_ema1 < self.slow_ema1: trend_status = 1 elif self.fast_ema0 < self.slow_ema0 and self.fast_ema1 > self.slow_ema1: trend_status = -1 else: trend_status = 0 self.fixed_size = 0.1 * self.trade_money / bar.close_price # if bar.datetime.time() < self.exit_time: if self.pos == 0: # 没有仓位 if trend_status == 1: if bar.close_price > self.yesterday_high: self.buy(bar.close_price * 1.005, self.fixed_size) # 做多 elif trend_status == -1: if bar.close_price < self.yesterday_low: self.short(bar.close_price * 0.995, self.fixed_size) # 做空 elif self.pos > 0: # 有多头仓位 if bar.close_price < self.long_stop_loss: # 如果当前价格小于多头止损线 if trend_status == -1: self.sell(bar.close_price * 0.995, abs(self.pos)) # 先平多头仓位,再反手开空 self.short(bar.close_price * 0.995, self.fixed_size) # 做空 else: self.sell(bar.close_price * 0.995, abs(self.pos)) # 止 else: # 继续做多 if trend_status == 1: if bar.close_price > self.yesterday_high: self.buy(bar.close_price * 1.005, self.fixed_size) # 做多 elif self.pos < 0: # 有空头的仓位 if bar.close_price > self.short_stop_loss: # 如果当前价格大于空头止损线 if trend_status == 1: self.cover(bar.close_price * 1.005, abs(self.pos)) # 先平空头仓位, 然后反手开多 self.buy(bar.close_price * 1.005, self.fixed_size) # 做多按照开仓的资金来计算 else: self.cover(bar.close_price * 1.005, abs(self.pos)) else: # 继续做空 if trend_status == -1: if bar.close_price < self.yesterday_low: self.short(bar.close_price * 0.995, self.fixed_size) self.put_event() def on_trade(self, trade: TradeData): pass def on_order(self, order: OrderData): pass def on_stop_order(self, stop_order: StopOrder): pass
class DeviationStrategy(CtaTemplate): """""" author = "yunya" exchange = "BYBIT" xminute_window = 15 short_length = 30 medium_length = 60 long_length = 120 entry_window = 28 exit_window = 7 atr_window = 4 trading_size = 1 # risk_level = 0.2 ema_initde = 0 # trading_size = 0 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 parameters = ["entry_window", "exit_window", "atr_window", "risk_level"] variables = [ "ema_initde", "entry_up", "entry_down", "exit_up", "exit_down", "atr_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.xminute_window, self.on_xminute_bar, interval=Interval.MINUTE) self.am = ArrayManager(self.long_length + 100) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar_exchange(days=10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xminute_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.entry_up, self.entry_down = self.am.donchian(self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) short_ema = self.am.ema(self.short_length, True) mdeium_ema = self.am.ema(self.medium_length, True) long_ema = self.am.ema(self.long_length, True) short_mdeium_array = short_ema - mdeium_ema mdeium__long_array = mdeium_ema - long_ema current_short_mdeium = short_mdeium_array[-1] last_short_mdeium = short_mdeium_array[-2] current_mdeium_long = mdeium__long_array[-1] last_mdeium_long = mdeium__long_array[-2] con1 = current_short_mdeium > current_mdeium_long con2 = last_short_mdeium <= last_mdeium_long con3 = current_short_mdeium < current_mdeium_long con4 = last_short_mdeium >= last_mdeium_long if con1 and con2: self.ema_initde = 1 elif con3 and con4: self.ema_initde = -1 if not self.pos: self.atr_value = self.am.atr(self.atr_window) # if self.atr_value == 0: # return # # 反向合约的计算方法, # atr_risk = talib.ATR( # 1 / self.am.high, # 1 / self.am.low, # 1 / self.am.close, # self.atr_window # )[-1] # self.trading_size = max(int(self.risk_level / atr_risk), 1) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 if self.ema_initde > 0: self.buy(self.entry_up, self.trading_size, True) elif self.ema_initde < 0: self.short(self.entry_down, self.trading_size, True) elif self.pos > 0: sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: cover_price = min(self.short_stop, self.exit_up) self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def load_bar_exchange(self, days: int): """" 判断是属于那个交易所,使用不同的初始化方式 """ if self.exchange == Exchange.HUOBI: self.load_bar(days=days, use_database=True) self.write_log(f"{self.exchange}交易所,从本地获取{days}数据初始化!") elif self.exchange == Exchange.OKEX: self.load_bar(days=days, use_database=True) self.write_log(f"{self.exchange}交易所,从本地获取{days}数据初始化!") else: self.load_bar(days=days) self.write_log(f"{self.exchange}交易所,从交易获取{days}数据初始化!")