class MaSignal(CtaSignal): """""" def __init__(self, fast_window: int, slow_window: int): """""" super(MaSignal, self).__init__() self.fast_window = fast_window self.slow_window = slow_window self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.am.update_bar(bar) if not self.am.inited: self.set_signal_pos(0) fast_ma = self.am.sma(self.fast_window) slow_ma = self.am.sma(self.slow_window) if fast_ma > slow_ma: self.set_signal_pos(1) elif fast_ma < slow_ma: self.set_signal_pos(-1) else: self.set_signal_pos(0)
class CciSignal(CtaSignal): """""" def __init__(self, cci_window: int, cci_level: float): """""" super(CciSignal, self).__init__() self.cci_window = cci_window self.cci_level = cci_level self.cci_long = self.cci_level self.cci_short = -self.cci_level self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am.update_bar(bar) if not self.am.inited: self.set_signal_pos(0) cci_value = self.am.cci(self.cci_window) if cci_value >= self.cci_long: self.set_signal_pos(1) elif cci_value <= self.cci_short: self.set_signal_pos(-1) else: self.set_signal_pos(0)
class BollingerBotJD2001Strategy(CtaInvestmentTemplate): """基于布林通道的交易策略""" author = u'tonywang_efun' # 策略参数 initDays = 20 # 初始化数据所用的天数 fixedSize = 2 # 每次交易的数量 # (多头参数) bollLength = 60 # 通道窗口数 entryDev = 3.2 # 开仓偏差 exitDev = 1.2 # 平仓偏差 trailingPrcnt = 1.4 # 移动止损百分比 maLength = 11 # 过滤用均线窗口 # (空头参数) shortBollLength = 28 # 通道窗口数 shortEntryDev = 4.4 # 开仓偏差 shortExitDev = 1.4 # 平仓偏差 shortTrailingPrcnt = 1.0 # 移动止损百分比 shortMaLength = 42 # 过滤用均线窗口 # 策略变量(多头) entryLine = 0 # 开仓上轨 exitLine = 0 # 平仓上轨 maFilter = 0 # 均线过滤 maFilterPrevious = 0 # 上一期均线 intraTradeHigh = 0 # 持仓期内的最高点 longEntry = 0 # 多头开仓 longExit = 0 # 多头平仓 # 策略变量(空头) shortEntryLine = 0 # 开仓上轨 shortExitLine = 0 # 平仓上轨 shortMaFilter = 0 # 均线过滤 shortMaFilterPrevious = 0 # 上一期均线 intraTradeLow = 0 # 持仓期内的最最低点 shortEntry = 0 # 空头开仓 shortExit = 0 # 空头平仓 # 参数列表,保存了参数的名称 parameters = [ 'initDays', 'fixedSize', 'bollLength', 'entryDev', 'exitDev', 'trailingPrcnt', 'maLength', 'shortBollLength', 'shortEntryDev', 'shortExitDev', 'shortTrailingPrcnt', 'shortMaLength' ] # 变量列表,保存了变量的名称 variables = [ 'entryLine', 'exitLine', 'shortEntryLine', 'shortExitLine', 'intraTradeHigh', 'intraTradeLow', 'longEntry', 'longExit', 'shortEntry', 'shortExit' ] # ---------------------------------------------------------------------- def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(BollingerBotJD2001Strategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 6, self.on_xmin_bar) self.am = ArrayManager(100) # ---------------------------------------------------------------------- def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(self.initDays) # ---------------------------------------------------------------------- def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() # ---------------------------------------------------------------------- def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() # ---------------------------------------------------------------------- def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) # ---------------------------------------------------------------------- def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """收到x分钟K线""" # 撤销之前发出的尚未成交的委托(包括限价单和停止单) self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算多头指标数值 self.entryLine, self.exitLine = am.boll_double_up( self.bollLength, self.entryDev, self.exitDev) ma_array = am.sma(self.maLength, True) self.maFilter = ma_array[-1] self.maFilterPrevious = ma_array[-2] # 计算空头指标数值 self.shortEntryLine, self.shortExitLine = am.boll_double_down( self.shortBollLength, self.shortEntryDev, self.shortExitDev) short_ma_array = am.sma(self.shortMaLength, True) self.shortMaFilter = short_ma_array[-1] self.shortMaFilterPrevious = short_ma_array[-2] # 当前无仓位,发送OCO开仓委托 if self.pos == 0: self.intraTradeHigh = bar.high_price self.intraTradeLow = bar.low_price if bar.close_price > self.maFilter > self.maFilterPrevious: self.longEntry = self.entryLine self.buy(self.longEntry, self.fixedSize, True) elif bar.close_price < self.shortMaFilter < self.shortMaFilterPrevious: self.shortEntry = self.shortEntryLine self.short(self.shortEntry, self.fixedSize, True) # 持有多头仓位 elif self.pos > 0: self.intraTradeHigh = max(self.intraTradeHigh, bar.high_price) self.longExit = self.intraTradeHigh * (1 - self.trailingPrcnt / 100) self.longExit = min(self.longExit, self.exitLine) self.sell(self.longExit, abs(self.pos), True) # 持有空头仓位 elif self.pos < 0: self.intraTradeLow = min(self.intraTradeLow, bar.low_price) self.shortExit = self.intraTradeLow * ( 1 + self.shortTrailingPrcnt / 100) self.shortExit = max(self.shortExit, self.shortExitLine) self.cover(self.shortExit, abs(self.pos), True) # 发出状态更新事件 self.put_event() def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" pass # ---------------------------------------------------------------------- def on_trade(self, trade): # 记录交易数据并分析投资情况 self.record_trade(trade, "BollingerBot", True) self.put_event() # ---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" pass
class OrmStrategy(CtaTemplate): """""" author = "用Python的交易员" atr_length = 22 atr_ma_length = 10 rsi_length = 5 rsi_entry = 16 trailing_percent = 0.8 fixed_size = 1 atr_value = 0 atr_ma = 0 rsi_value = 0 rsi_buy = 0 rsi_sell = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "atr_length", "atr_ma_length", "rsi_length", "rsi_entry", "trailing_percent", "fixed_size" ] variables = [ "atr_value", "atr_ma", "rsi_value", "rsi_buy", "rsi_sell", "intra_trade_high", "intra_trade_low" ] 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.rsi_buy = 50 + self.rsi_entry self.rsi_sell = 50 - self.rsi_entry self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.sync_from_database() self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.sync_to_database() 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() am = self.am am.update_bar(bar) if not am.inited: return atr_array = am.atr(self.atr_length, array=True) self.atr_value = atr_array[-1] self.atr_ma = atr_array[-self.atr_ma_length:].mean() self.rsi_value = am.rsi(self.rsi_length) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.atr_value > self.atr_ma: if self.rsi_value > self.rsi_buy: self.buy(bar.close_price + 5, self.fixed_size) elif self.rsi_value < self.rsi_sell: 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 long_stop = self.intra_trade_high * \ (1 - self.trailing_percent / 100) self.sell(long_stop, abs(self.pos), stop=True) elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.intra_trade_high = bar.high_price short_stop = self.intra_trade_low * \ (1 + self.trailing_percent / 100) self.cover(short_stop, abs(self.pos), stop=True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.sync_to_database() self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def sync_to_database(self): """""" if not self.trading: return variables = self.get_variables() save_strategy_data(self.strategy_name, variables) def sync_from_database(self): """""" variables = load_strategy_data(self.strategy_name) for key in self.variables: if key in variables: setattr(self, key, variables[key])
class CincoStrategyHN(CtaTemplate): """""" author = "Huang Ning" boll_window = 42 boll_dev = 2.0 trailing_long = 0.65 trailing_short = 0.7 atr_window = 10 risk_level = 100 boll_up = 0 boll_down = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "boll_window", "boll_dev", "trailing_long", "trailing_short", "atr_window", "risk_level" ] variables = [ "boll_up", "boll_down", "trading_size", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "atr_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(CincoStrategyHN, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """""" self.write_log("策略初始化") self.load_bar(10) def on_start(self): """""" self.write_log("策略启动") def on_stop(self): """""" self.write_log("策略停止") def on_tick(self, tick: TickData): """""" self.bg.update_tick(tick) def on_bar(self, bar: BarData): """""" self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) boll_width = self.boll_up - self.boll_down if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.trading_size = int(self.risk_level / self.atr_value) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 self.buy(self.boll_up, self.trading_size, stop=True) self.short(self.boll_down, self.trading_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_order(self, order: OrderData): """""" def on_trade(self, trade: TradeData): """""" self.put_event() def on_stop_order(self, stop_order: StopOrder): """""" self.put_event()
class 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().__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: self.send_buy_orders(self.entry_up) # 2ATR止损或者出场窗口期唐奇安通道突破 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. """ # 成交后计算2ATR止损位置 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 # 实现每0.5ATR加仓一个单位 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 BollChannelStrategy(CtaTemplate): """""" author = '用Python的交易员' boll_window = 18 boll_dev = 3.4 cci_window = 10 atr_window = 30 sl_multiplier = 5.2 fixed_size = 1 boll_up = 0 boll_down = 0 cci_value = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = ['boll_window', 'boll_dev', 'cci_window', 'atr_window', 'sl_multiplier', 'fixed_size'] variables = ['boll_up', 'boll_down', 'cci_value', 'atr_value', 'intra_trade_high', 'intra_trade_low', 'long_stop', 'short_stop'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(BollChannelStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) self.cci_value = am.cci(self.cci_window) self.atr_value = am.atr(self.atr_window) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.cci_value > 0: self.buy(self.boll_up, self.fixed_size, True) elif self.cci_value < 0: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class DoubleMaExitMaReinStrategy(CtaTemplate): # 入场用快均线和慢均线交叉加过滤器(收盘价+atr),快均线一般固定为5,相当于使用单均线入场 # 出场用满均线的.x系数的均线出场,出场后在反向信号触发前有n次重新入场的机会(通道入场)。 author = "double_ma_exit_ma_rein" is_say_log = False fast_window = 20 slow_window = 40 atr_multi = 0.5 mid_multi = 0.8 max_rein = 1 fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 parameters = [ "fast_window", "slow_window", "atr_multi", "mid_multi", "max_rein" ] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager(size=80) self.local_stop = True self.limit_up = 1.04 self.limit_down = 0.96 self.watch_long = False self.watch_short = False self.boll_up = 0 self.boll_down = 0 self.long_rein = False self.short_rein = False self.long_rein_count = 0 self.short_rein_count = 0 self.rein_highest = 0 self.rein_lowest = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") # 回撤引擎,load_bar只有days(回溯交易日)和callback有作用,其他传入参数都没有作用。 self.load_bar(80) 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. """ # 运行新bar之前,撤销之前的委托,否则容易各种异常 self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return fast_ma = am.sma(self.fast_window, array=True) self.fast_ma0 = fast_ma[-1] self.fast_ma1 = fast_ma[-2] slow_ma = am.sma(self.slow_window, array=True) self.slow_ma0 = slow_ma[-1] self.slow_ma1 = slow_ma[-2] cross_over = self.fast_ma0 > self.slow_ma0 and self.fast_ma1 < self.slow_ma1 cross_below = self.fast_ma0 < self.slow_ma0 and self.fast_ma1 > self.slow_ma1 # 监测状态是持续性的,在状态未撤销之前且没有成交(没有仓位),每根bar都会发本地单 if self.watch_long and self.pos == 0: self.buy(self.boll_up, 1, True) self.say_log("WatchLong:", bar.datetime, "boll_up:", self.boll_up) if self.watch_short and self.pos == 0: self.short(self.boll_down, 1, True) self.say_log("watchShort:", bar.datetime, "boll_down:", self.boll_down) # 重新入场监测 if self.long_rein and self.pos == 0: up, down = am.donchian(self.slow_window) # up = self.rein_highest self.buy(up, 1, True) self.say_log("ReinLong:", bar.datetime, "rein_up:", up, "long_rein_count:", self.long_rein_count) if self.short_rein and self.pos == 0: up, down = am.donchian(self.slow_window) # down = self.rein_lowest self.short(down, 1, True) self.say_log("ReinShort:", bar.datetime, "rein_down:", down, "short_rein_count:", self.short_rein_count) # 计算前高前低 if self.pos == 0: if not self.long_rein and not self.short_rein: self.rein_highest = bar.high_price self.rein_lowest = bar.low_price # 快速出场条件 if self.pos > 0: self.rein_highest = max(self.rein_highest, bar.high_price) mid_ma = am.sma(int(self.slow_window * self.mid_multi)) self.sell(mid_ma, abs(self.pos), True) self.say_log("Close-Long-Ahead:", bar.datetime, 'mid_ma:', mid_ma) if self.pos < 0: self.rein_lowest = min(self.rein_lowest, bar.low_price) mid_ma = am.sma(int(self.slow_window * self.mid_multi)) self.cover(mid_ma, abs(self.pos), True) self.say_log("Close-Short-Ahead:", bar.datetime, 'mid_ma:', mid_ma) # 交叉信号是一次性的,只在触发的bar运行,没成交的单在下一根bar计算之前会被撤销 if cross_over: # 金叉,撤销做空监测单并取消做空监测 # 撤销重新做空的监测 self.cancel_all() self.watch_short = False self.short_rein = False self.short_rein_count = 0 # 通道只在触发信号的时候计算,后续不再改变。 atr_value = am.atr(self.slow_window) * self.atr_multi self.boll_up = bar.close_price + atr_value if self.pos == 0: # 立即发本地单,等待下一根撮合,同时开始监测做多 self.buy(self.boll_up, 1, True) if self.trading: self.watch_long = True self.say_log("Signal:", bar.datetime, "pos:", self.pos, "close_up:", self.boll_up, "close:", bar.close_price, "gloden-cross open", "trading:", self.trading) elif self.pos < 0: # 有空头,碰到金叉后,先超价立即平仓 # 反向单先发本地单,等待下一根bar一起撮合,并且开启做多监测 self.cover(bar.close_price * self.limit_up, abs(self.pos), False) self.buy(self.boll_up, 1, True) self.watch_long = True self.say_log("Signal:", bar.datetime, "pos:", self.pos, "close_up:", self.boll_up, "close:", bar.close_price, "gloden-cross close and open") elif cross_below: self.cancel_all() self.watch_long = False self.long_rein = False self.long_rein_count = 0 atr_value = am.atr(self.slow_window) * self.atr_multi self.boll_down = bar.close_price - atr_value if self.pos == 0: self.short(self.boll_down, 1, True) if self.trading: self.watch_short = True self.say_log("Signal:", bar.datetime, "pos:", self.pos, "close_down:", self.boll_down, "close:", bar.close_price, "dead-cross open", "trading:", self.trading) elif self.pos > 0: self.sell(bar.close_price * self.limit_down, abs(self.pos), False) self.short(self.boll_down, 1, True) self.watch_short = True self.say_log("Signal:", bar.datetime, "pos:", self.pos, "close_down:", self.boll_down, "close:", bar.close_price, "dead-cross close and open") self.say_log('datetime:', bar.datetime, 'pos:', self.pos, 'watch-long:', self.watch_long, 'watch_short:', self.watch_short, 'long-rein:', self.long_rein, 'short-rein:', self.short_rein, 'highest:', self.rein_highest, 'lowest:', self.rein_lowest) self.say_log('==' * 50) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.say_log("order", order.datetime, order.direction, order.offset, order.price, order.volume) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.offset == Offset.OPEN: if trade.direction == Direction.LONG: self.watch_long = False self.long_rein = False else: self.watch_short = False self.short_rein = False else: # 交易时做多平仓(平空头),并且不是由于双均线交叉触发的,开启重新入场监测 if trade.direction == Direction.LONG and not self.watch_long: # 重入空头次数小于最大限制,才能重入空头 if self.short_rein_count < self.max_rein: self.short_rein = True self.short_rein_count += 1 if trade.direction == Direction.SHORT and not self.watch_short: if self.long_rein_count < self.max_rein: self.long_rein = True self.long_rein_count += 1 self.say_log("Trade:", trade.datetime, trade.direction, trade.offset, trade.price, trade.volume) self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.say_log("stop-order", stop_order.direction, stop_order.offset, stop_order.price, stop_order.volume) def say_log(self, *args): if self.is_say_log: print(*args)
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 BollVixSignal(CtaSignal): """ 布林 vix """ sma_array = 0 boll_up_array = 0 boll_down_array = 0 entry_crossover = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 def __init__(self, open_window, boll_window: int): """""" super().__init__() self.open_window = open_window self.boll_window = boll_window self.bg = BarGenerator(self.on_bar, self.open_window, self.on_xmin_bar) self.am = ArrayManager() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.am.update_bar(bar) if not self.am.inited: self.set_signal_pos(0) # Calculate array 计算数组 self.sma_array = self.am.sma(self.boll_window, True) std_array = self.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[:-1] + std_array[:-1] * dev_max self.boll_down_array = self.sma_array[:-1] - std_array[:-1] * dev_max # Get current and last index last_sma = self.sma_array[-2] current_sma = self.sma_array[-1] last_close = self.am.close[-2] current_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] # Get crossover if last_close <= last_boll_up and current_boll_up < bar.close_price: self.set_signal_pos(1) elif last_close >= last_boll_down and current_boll_down > bar.close_price: self.set_signal_pos(-1) exit_long = last_close >= last_sma and current_sma > bar.close_price exit_short = last_close <= last_sma and current_sma < bar.close_price if exit_long and exit_short: self.set_signal_pos(0)
class KingKeltnerStrategy(CtaTemplate): """""" author = '用Python的交易员' kk_length = 11 kk_dev = 1.6 trailing_percent = 0.8 fixed_size = 1 kk_up = 0 kk_down = 0 intra_trade_high = 0 intra_trade_low = 0 buy_orderidList = [] short_orderidList = [] orderList = [] parameters = ['kk_length', 'kk_dev', 'fixed_size'] variables = ['kk_up', 'kk_down'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(KingKeltnerStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" for orderid in self.orderList: self.cancel_order(orderid) self.orderList = [] am = self.am am.update_bar(bar) if not am.inited: return self.kk_up, self.kk_down = am.keltner(self.kk_length, self.kk_dev) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.send_oco_order(self.kk_up, self.kk_down, self.fixed_size) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price vt_orderid = self.sell( self.intra_trade_high * (1 - self.trailing_percent / 100), abs(self.pos), True) self.orderList.append(vt_orderid) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) vt_orderid = self.cover( self.intra_trade_low * (1 + self.trailing_percent / 100), abs(self.pos), True) self.orderList.append(vt_orderid) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if self.pos != 0: if self.pos > 0: for short_orderid in self.short_orderidList: self.cancel_order(short_orderid) elif self.pos < 0: for buy_orderid in self.buy_orderidList: self.cancel_order(buy_orderid) for orderid in (self.buy_orderidList + self.short_orderidList): if orderid in self.orderList: self.orderList.remove(orderid) self.put_event() def send_oco_order(self, buy_price, short_price, volume): """""" self.buy_orderidList = self.buy(buy_price, volume, True) self.short_orderidList = self.short(short_price, volume, True) self.orderList.append(self.buy_orderidList) self.orderList.append(self.short_orderidList) def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class TSMyoRBKRSIStrategy(CtaTemplate): """ 针对本地停止单触发的撤单失败导致重复挂单 1.给cancel_all()返回值,去标记是否出现 OmsEngine中找不到 的情况,做相应处理 2.策略自身维护一个订单列表,使用 on_stop_order/on_order 去同步cta_engine的 策略—订单列表map ,做相应判断 """ author = "TheSuperMyo" setup_coef = 0.25 break_coef = 0.2 enter_coef_1 = 1.07 enter_coef_2 = 0.07 fixed_size = 1 donchian_window = 30 atr_stop = 4 atr_window = 35 atr_ma_len = 20 er_filter = 0.23 trailing_stop = 0.6 multiplier = 1 buy_break = 0 # 突破买入价 sell_setup = 0 # 观察卖出价 sell_enter = 0 # 反转卖出价 buy_enter = 0 # 反转买入价 buy_setup = 0 # 观察买入价 sell_break = 0 # 突破卖出价 intra_trade_high = 0 intra_trade_low = 0 day_high = 0 day_low = 0 day_close = 0 tend_high = 0 tend_low = 0 atr_value = 0 atr_ma_value = 0 limited_size = 8 td_traded = 0 exit_time = time(hour=14, minute=56) # 针对不同交易时间的市场 open_time_night = time(hour=21, minute=0) # 商品夜盘 open_time_day_1 = time(hour=9, minute=0) # 商品 open_time_day_2 = time(hour=9, minute=30) # 股指 close_time_day = time(hour=15, minute=0) # 商品/股指(除了利率期货) close_time_night_1 = time(hour=23, minute=0) # 其他夜盘商品 close_time_night_2 = time(hour=1, minute=0) # 工业金属 close_time_night_3 = time(hour=2, minute=30) # 黄金/白银/原油 break_time_start_1 = time(hour=10, minute=15) # 商品茶歇 break_time_start_2 = time(hour=11, minute=30) # 全体午休 break_time_end_1 = time(hour=10, minute=30) # 商品茶歇 break_time_end_2 = time(hour=13, minute=0) # 股指下午 break_time_end_3 = time(hour=13, minute=30) # 商品下午 parameters = [ "trailing_stop", "er_filter", "donchian_window", "limited_size", "atr_stop", "atr_window", "atr_ma_len" ] variables = [ "tend_low", "tend_high", "atr_value", "atr_ma_value", "buy_break", "sell_setup", "sell_enter", "buy_enter", "buy_setup", "sell_break" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TSMyoRBKRSIStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = TSMArrayManager() self.bars = [] self.vt_orderids = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def tick_filter(self, tick: TickData): """ 过滤异常时间的tick """ tick_time = tick.datetime.time() if tick_time < self.open_time_day_2: return False if tick_time > self.break_time_start_2 and tick_time < self.break_time_end_2: return False if tick_time > self.close_time_day: return False return True def on_tick(self, tick: TickData): """ Callback of new tick data update. """ if not self.tick_filter(tick): return self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ # 如果撤单过程中出现在OMSEngine找不到订单 # 则可能是挂单的EVENT_ORDER还未处理,跳过该此次执行 any_not_find = 0 any_not_find = self.cancel_all() if any_not_find == 1: self.write_log("出现撤单找不到问题,跳过此次执行") return am = self.am am.update_bar(bar) if not am.inited: return self.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] # 判断开盘bar,先使用split判别有夜盘品种开盘 # last_bar是昨天的,也就是说bar是今天第一根 if (last_bar.datetime.date() != bar.datetime.date()): if self.day_high: self.buy_setup = self.day_low - self.setup_coef * ( self.day_high - self.day_close) # 观察买入价 self.sell_setup = self.day_high + self.setup_coef * ( self.day_close - self.day_low) # 观察卖出 self.buy_enter = (self.enter_coef_1 / 2) * ( self.day_high + self.day_low) - self.enter_coef_2 * self.day_high # 反转买入价 self.sell_enter = (self.enter_coef_1 / 2) * ( self.day_high + self.day_low) - self.enter_coef_2 * self.day_low # 反转卖出价 self.buy_break = self.sell_setup + self.break_coef * ( self.sell_setup - self.buy_setup) # 突破买入价 self.sell_break = self.buy_setup - self.break_coef * ( self.sell_setup - self.buy_setup) # 突破卖出价 self.write_log(f"{bar.datetime.date()}开盘使用数据:") self.write_log( f"昨收:{self.day_close},昨高:{self.day_high},昨低:{self.day_low}") self.write_log(f"计算得出:") self.write_log(f"上中轨:{self.sell_setup},下中轨:{self.buy_setup}") self.day_high = bar.high_price self.day_low = bar.low_price self.day_close = bar.close_price self.td_traded = 0 # 盘中记录当日HLC,为第二天计算做准备 else: self.day_high = max(self.day_high, bar.high_price) self.day_low = min(self.day_low, bar.low_price) self.day_close = bar.close_price if not self.sell_setup: return # N分钟内最高价和最低价 self.tend_high, self.tend_low = am.donchian(self.donchian_window) # ATR相关指标 atr_array = am.atr(self.atr_window, True) self.atr_value = atr_array[-1] self.atr_ma_value = atr_array[-self.atr_ma_len:].mean() # ER er_value = am.er(20, False) if er_value > self.er_filter: er_flag = 1 # 交易时间 if (bar.datetime.time() < self.exit_time): # 设置ATR过滤,只有波动扩大才开仓 if self.pos == 0 and self.atr_value > self.atr_ma_value and er_flag == 1: self.write_log(f"波动扩大:{self.atr_value} > {self.atr_ma_value}") self.intra_trade_low = bar.low_price self.intra_trade_high = bar.high_price # N分钟内最高价在sell_setup之上 if self.tend_high > self.sell_setup: self.write_log( f"N分钟内 tend_high > sell_setup:{self.tend_high} > {self.sell_setup}" ) # 添加过滤,突破价不低于最高价,才进场 long_entry = max(self.buy_break, self.day_high) # 检查策略是否还有订单留存,或者是否达到交易上限 if self.vt_orderids or self.td_traded >= self.limited_size: self.write_log("撤单不干净或达到交易限制,无法挂单") return orderids = self.buy(long_entry, self.fixed_size, stop=True, lock=True) self.vt_orderids.extend(orderids) # 反转系统进场,手数可以和趋势系统做区分 orderids = self.short(self.sell_enter, self.multiplier * self.fixed_size, stop=True, lock=True) self.vt_orderids.extend(orderids) self.write_log( f"stop_order for buy & short:{long_entry} & {self.sell_enter}" ) elif self.tend_low < self.buy_setup: self.write_log( f"N分钟内 tend_low < buy_setup:{self.tend_low} < {self.buy_setup}" ) short_entry = min(self.sell_break, self.day_low) if self.vt_orderids or self.td_traded >= self.limited_size: self.write_log("撤单不干净或达到交易限制,无法挂单") return orderids = self.short(short_entry, self.fixed_size, stop=True, lock=True) self.vt_orderids.extend(orderids) orderids = self.buy(self.buy_enter, self.multiplier * self.fixed_size, stop=True, lock=True) self.vt_orderids.extend(orderids) self.write_log( f"stop_order for short & buy:{short_entry} & {self.buy_enter}" ) elif self.pos > 0: # 跟踪止损出场(百分比&ATR) self.intra_trade_high = max(self.intra_trade_high, bar.high_price) long_stop = max( self.intra_trade_high * (1 - self.trailing_stop / 100), self.intra_trade_high - self.atr_stop * self.atr_value) if self.vt_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(long_stop, abs(self.pos), stop=True, lock=True) self.vt_orderids.extend(orderids) self.write_log(f"stop_order for sell:{long_stop}") elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_stop = min( self.intra_trade_low * (1 + self.trailing_stop / 100), self.intra_trade_low + self.atr_stop * self.atr_value) if self.vt_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(short_stop, abs(self.pos), stop=True, lock=True) self.vt_orderids.extend(orderids) self.write_log(f"stop_order for cover:{short_stop}") # 日内策略,最后6分钟不断尝试平仓 else: if self.pos > 0: if self.vt_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(bar.close_price, abs(self.pos), lock=True) self.vt_orderids.extend(orderids) elif self.pos < 0: if self.vt_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(bar.close_price, abs(self.pos), lock=True) self.vt_orderids.extend(orderids) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ # 移除成交或撤销的订单 if not order.is_active() and order.vt_orderid in self.vt_orderids: self.vt_orderids.remove(order.vt_orderid) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.td_traded += 1 self.write_log( f"{trade.vt_symbol}在{trade.time}成交,价格{trade.price},方向{trade.direction}{trade.offset},数量{trade.volume}" ) self.send_email( f"{trade.vt_symbol}在{trade.time}成交,价格{trade.price},方向{trade.direction}{trade.offset},数量{trade.volume}" ) self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ # 根据状态处理 # 刚刚生成的本地停止单 if stop_order.status == StopOrderStatus.WAITING: return # 撤销的本地停止单,从列表移除 if stop_order.status == StopOrderStatus.CANCELLED: if stop_order.stop_orderid in self.vt_orderids: self.vt_orderids.remove(stop_order.stop_orderid) # 触发的本地停止单,停止单移除,限价单加入 if stop_order.status == StopOrderStatus.TRIGGERED: if stop_order.stop_orderid in self.vt_orderids: self.vt_orderids.remove(stop_order.stop_orderid) self.vt_orderids.extend(stop_order.vt_orderids) # 撤掉其他停止单 for other_stop_orderids in self.vt_orderids: if other_stop_orderids.startswith(STOPORDER_PREFIX): self.cancel_order(other_stop_orderids)
class DoubleTrendModelStrategy(CtaTemplate): """""" author = "yiran" fixed_size = 1 s_window = 5 l_window = 15 fast_ma_macd = 9 slow_ma_macd = 26 signal_macd = 4 true_range_window = 4 true_range_influence_multiplier = 0.5 cross_over_record_max_num_s = 50 cross_over_slice_window_s = 4 trail_bar_window_s = 6 cross_over_record_max_num_l = 50 cross_over_slice_window_l = 4 trail_bar_window_l = 6 bar_num_s = 0 bar_num_after_crossover_s = 0 bar_num_l = 0 bar_num_after_crossover_l = 0 mdif_s = 0 cross_above_0_s = False cross_under_0_s = False cross_over_record_array_s = np.zeros(shape=(4, cross_over_record_max_num_s)) cross_over_slice_window_highest_s = 0 cross_over_slice_window_lowest_s = 0 last_cross_over_interval_s = 0 last_cross_over_side_s = 0 mdif_l = 0 cross_above_0_l = False cross_under_0_l = False cross_over_record_array_l = np.zeros(shape=(4, cross_over_record_max_num_l)) cross_over_slice_window_highest_l = 0 cross_over_slice_window_lowest_l = 0 last_cross_over_interval_l = 0 last_cross_over_side_l = 0 long_open_stop_order_price_l = 0 long_close_stop_order_price_l = 0 short_open_stop_order_price_l = 0 short_close_stop_order_price_l = 0 long_open_stop_order_price_s = 0 long_close_stop_order_price_s = 0 short_open_stop_order_price_s = 0 short_close_stop_order_price_s = 0 parameters = [ 'fast_ma_macd', 'slow_ma_macd', 'signal_macd', 'true_range_window', 'cross_over_record_max_num_l', 'cross_over_record_max_num_s', 's_window', 'l_window', 'true_range_influence_multiplier', 'cross_over_slice_window_l', 'cross_over_slice_window_s', 'trail_bar_window_l', 'trail_bar_window_s' ] variables = [] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bars = [] self.bg5 = BarGenerator(self.on_bar, self.s_window, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, self.l_window, self.on_15min_bar) self.am15 = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am5.update_bar(bar) self.bar_num_s += 1 if not self.am5.inited: return am = self.am5 self.mdif_s, signal, hist = am.macd(self.fast_ma_macd, self.slow_ma_macd, self.signal_macd, array=True) self.long_close_stop_order_price_s = am.low[-self. trail_bar_window_s:].min() self.short_close_stop_order_price_s = am.high[ -self.trail_bar_window_s:].max() if self.mdif_s[-2] < 0 < self.mdif_s[-1]: self.cross_above_0_s = True elif self.mdif_s[-2] > 0 > self.mdif_s[-1]: self.cross_under_0_s = True if self.cross_under_0_s or self.cross_above_0_s: # bar_num self.cross_over_record_array_s[ 0, :-1] = self.cross_over_record_array_s[0, 1:] # high self.cross_over_record_array_s[ 1, :-1] = self.cross_over_record_array_s[1, 1:] # low self.cross_over_record_array_s[ 2, :-1] = self.cross_over_record_array_s[2, 1:] # cross_over_side self.cross_over_record_array_s[ 3, :-1] = self.cross_over_record_array_s[3, 1:] self.cross_over_record_array_s[0, -1] = self.bar_num_s self.cross_over_record_array_s[1, -1] = am.high[-1] self.cross_over_record_array_s[2, -1] = am.low[-1] if self.cross_above_0_s: side = 1 elif self.cross_under_0_s: side = -1 self.cross_over_record_array_s[3, -1] = side self.cross_above_0_s, self.cross_under_0_s = False, False self.cross_over_slice_window_highest_s = np.max( self.cross_over_record_array_s[1, -self.cross_over_slice_window_s:]) self.cross_over_slice_window_lowest_s = np.min( self.cross_over_record_array_s[2, -self.cross_over_slice_window_s:]) self.last_cross_over_interval_s = self.bar_num_s - \ self.cross_over_record_array_s[0, -1] self.last_cross_over_side_s = self.cross_over_record_array_s[3, -1] true_range_influence = np.mean( am.trange(array=True) [-self.true_range_window:]) * self.true_range_influence_multiplier self.long_open_stop_order_price_s = self.cross_over_slice_window_highest_s + \ true_range_influence self.short_open_stop_order_price_s = self.cross_over_slice_window_lowest_s + \ true_range_influence cross_overl_l = self.last_cross_over_interval_l <= self.last_cross_over_interval_l if self.pos == 0 and cross_overl_l: if self.last_cross_over_interval_s <= self.cross_over_record_max_num_s: if self.last_cross_over_side_s == 1 and self.last_cross_over_side_l == 1: self.buy(self.long_open_stop_order_price_s, self.fixed_size, stop=True) if self.last_cross_over_side_s == -1 and self.last_cross_over_side_l == -1: self.short(self.short_close_stop_order_price_s, self.fixed_size, stop=True) elif self.pos > 0: self.sell(self.long_close_stop_order_price_s, self.pos, stop=True) elif self.pos < 0: self.cover(self.short_close_stop_order_price_s, np.abs(self.pos), stop=True) self.put_event() def on_15min_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am15.update_bar(bar) self.bar_num_l += 1 if not self.am15.inited: return am = self.am15 self.mdif_l, signal, hist = am.macd(self.fast_ma_macd, self.slow_ma_macd, self.signal_macd, array=True) self.long_close_stop_order_price_l = am.low[-self. trail_bar_window_l:].min() self.short_close_stop_order_price_l = am.high[ -self.trail_bar_window_l:].max() if self.mdif_l[-2] < 0 < self.mdif_l[-1]: self.cross_above_0_l = True elif self.mdif_l[-2] > 0 > self.mdif_l[-1]: self.cross_under_0_l = True if self.cross_under_0_l or self.cross_above_0_l: # bar_num self.cross_over_record_array_l[ 0, :-1] = self.cross_over_record_array_l[0, 1:] # high self.cross_over_record_array_l[ 1, :-1] = self.cross_over_record_array_l[1, 1:] # low self.cross_over_record_array_l[ 2, :-1] = self.cross_over_record_array_l[2, 1:] # cross_over_side self.cross_over_record_array_l[ 3, :-1] = self.cross_over_record_array_l[3, 1:] self.cross_over_record_array_l[0, -1] = self.bar_num_l self.cross_over_record_array_l[1, -1] = am.high[-1] self.cross_over_record_array_l[2, -1] = am.low[-1] if self.cross_above_0_l: side = 1 elif self.cross_under_0_l: side = -1 self.cross_over_record_array_l[3, -1] = side self.cross_above_0_l, self.cross_under_0_l = False, False self.last_cross_over_interval_l = self.bar_num_l - \ self.cross_over_record_array_l[0, -1] self.last_cross_over_side_l = self.cross_over_record_array_l[3, -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 MacdAP001Strategy(CtaInvestmentTemplate): """基于布林通道的交易策略""" author = u'tonywang_efun' # 策略参数 initDays = 15 # 初始化数据所用的天数 fixedSize = 1 # 每次交易的数量 fixWinPrcnt = 5 # 固定止盈百分比 shortfixWinPrcnt = 5 # 固定止盈百分比 # 公共策略变量 posPrice = 0 # 持仓价 macd = 0 signal = 0 hist = 0 red_bar_num = 0 green_bar_num = 0 # 参数列表,保存了参数的名称 parameters = ['initDays', 'fixedSize', 'fixWinPrcnt', 'shortfixWinPrcnt'] # 变量列表,保存了变量的名称 variables = ['posPrice', 'macd', 'signal', 'hist'] # ---------------------------------------------------------------------- def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(MacdAP001Strategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 1, self.on_xmin_bar) self.am = ArrayManager(50) # ---------------------------------------------------------------------- def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(self.initDays) # ---------------------------------------------------------------------- def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() # ---------------------------------------------------------------------- def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() # ---------------------------------------------------------------------- def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) # ---------------------------------------------------------------------- def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """收到x分钟K线""" # 撤销之前发出的尚未成交的委托(包括限价单和停止单) self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算多头指标数值 self.macd, self.signal, self.hist = am.macd(12, 26, 9) if self.hist > 0: self.red_bar_num += 1 self.green_bar_num = 0 elif self.hist < 0: self.red_bar_num = 0 self.green_bar_num += 1 if self.red_bar_num == 1: print(bar.datetime, self.macd, self.signal, self.hist) # 当前无仓位,发送OCO开仓委托 if self.pos == 0: self.intraTradeHigh = bar.high_price self.intraTradeLow = bar.low_price if self.hist > 0: self.buy(bar.close_price, self.fixedSize) elif self.hist < 0: self.short(bar.close_price, self.fixedSize) # 持有多头仓位 elif self.pos > 0: if 0 < self.posPrice < bar.close_price \ and (bar.close_price - self.posPrice) / self.posPrice > (self.fixWinPrcnt / 100): self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.hist < 0: self.sell(bar.close_price * 0.99, abs(self.pos)) else: self.intraTradeHigh = max(self.intraTradeHigh, bar.high_price) # 持有空头仓位 elif self.pos < 0: if bar.close_price < self.posPrice \ and (self.posPrice - bar.close_price) / self.posPrice > (self.shortfixWinPrcnt / 100): self.cover(bar.close_price * 1.01, abs(self.pos)) elif self.hist > 0: self.cover(bar.close_price * 1.01, abs(self.pos)) else: self.intraTradeLow = min(self.intraTradeLow, bar.low_price) # 发出状态更新事件 self.put_event() def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" pass # ---------------------------------------------------------------------- def on_trade(self, trade): # 记录交易数据并分析投资情况 self.record_trade(trade, "MACD", True) self.posPrice = trade.price self.put_event() # ---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" pass
class CciSignal(CtaSignal): """ """ cci_up_array = 0 cci_dow_array = 0 cci_value = 0 cci_up = 0 cci_down = 0 cci_ma = 0 last_cci_value = 0 current_cci_value = 0 last_cci_up = 0 current_cci_up = 0 last_cci_down = 0 current_cci_down = 0 last_cci_ma = 0 current_cci_ma = 0 def __init__(self, open_window: int, cci_window: int, cci_level: float): """""" super().__init__() self.open_window = open_window self.cci_window = cci_window self.cci_level = cci_level self.cci_long = self.cci_level self.cci_short = -self.cci_level self.bg = BarGenerator(self.on_bar, self.open_window, self.on_x_bar) self.am = ArrayManager() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ :param bar: :return: """ self.bg.update_bar(bar) def on_x_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am.update_bar(bar) if not self.am.inited: self.set_signal_pos(0) # 计算 前一根K线的 cci cci_array = talib.CCI(self.am.high[:-1], self.am.low[:-1], self.am.close[:-1], self.cci_window) cci_ema = talib.EMA(cci_array, self.cci_window) dev_array = abs( cci_array[-self.cci_window:] - cci_ema[-self.cci_window:]) / cci_ema[-self.cci_window:] dev = np.max(dev_array[-self.cci_window:]) self.cci_up_array = cci_ema[ -self.cci_window:] + cci_array[-self.cci_window:] * dev self.cci_dow_array = cci_ema[ -self.cci_window:] - cci_array[-self.cci_window:] * dev self.cci_value = self.am.cci(self.cci_window, True) self.last_cci_value = self.cci_value[-2] self.current_cci_value = self.cci_value[-1] self.last_cci_up = self.cci_up_array[-2] self.current_cci_up = self.cci_up_array[-1] self.last_cci_down = self.cci_dow_array[-2] self.current_cci_down = self.cci_dow_array[-1] self.last_cci_ma = cci_ema[-2] self.current_cci_ma = cci_ema[-1] if self.last_cci_value <= self.last_cci_up and self.current_cci_value > self.current_cci_up: self.set_signal_pos(1) elif self.last_cci_value >= self.last_cci_up and self.current_cci_value < self.current_cci_up: self.set_signal_pos(-1) cci_sell = self.last_cci_value >= self.last_cci_ma and self.current_cci_value < self.current_cci_ma cci_court = self.last_cci_value <= self.last_cci_ma and self.current_cci_value > self.current_cci_ma if cci_sell and cci_court: self.set_signal_pos(0)
class Boll_Kc_Dc_Reverse_Strategy(CtaTemplate): """ 本策略为反向策略,币本位 Reverse 反向 """ author = "yunya" open_window = 2 xsmall_window = 15 com_length = 250 boll_kk_dev = 2.0 kk_atr_length = 30 sl_multiplier = 0.5 risk_level = 10000 trading_size = 0 xsmall_up_min = 0 xsmall_down_min = 0 xsmall_up_max = 0 xsmall_down_max = 0 xsmall_ema_mid = 0 xsmall_com_width = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 exit_up = 0 exit_down = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "open_window", "xsmall_window", "com_length", "boll_kk_dev", "kk_atr_length", "sl_multiplier", "risk_level", ] variables = [ "trading_size", "xsmall_up_min", "xsmall_down_min", "xsmall_up_max", "xsmall_down_max", "xsmall_ema_mid", "xsmall_com_width", "long_entry", "short_entry", "long_stop", "short_stop", "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_xsmall = BarGenerator( on_bar=self.on_bar, window=self.xsmall_window, on_window_bar=self.on_xsmall_bar, interval=Interval.MINUTE ) self.am_xsmall = 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_xsmall.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) self.bg_xsmall.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_xsmall.inited or not self.am.inited: return if self.pos == 0: # 根据布林带宽度动态调整仓位大小 self.trading_size = max(int(self.risk_level / self.xsmall_com_width), 1) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price # 如果价格突破 xsmall_up_min 线时,在xsmall_up_max 价格挂停止单 if self.am_xsmall.close[-1] >= self.xsmall_up_min and self.am.close[-1] >=self.xsmall_up_min: self.buy(self.xsmall_up_max,self.trading_size,True) # 如果价格突破 xsmall_down_min 线时,在xsmall_down_max 价格挂停止单 elif self.am_xsmall.close[-1] <= self.xsmall_down_min and self.am.close[-1] <= self.xsmall_down_min: self.short(self.xsmall_down_max,self.trading_size,True) elif self.pos > 0: # 成交价固定止损位与中轨中最大值为当前止损位 # self.exit_up = max(self.xsmall_ema_mid,self.long_stop) # 成交价回定止损 与最高价回撤一定比例通道宽度值 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.xsmall_com_width * self.sl_multiplier self.exit_up = max(exit_long_stop,self.long_stop) self.sell(self.exit_up,abs(self.pos),True) elif self.pos < 0: # 成交价固定止损位与中轨中最小值为当前止损位 # self.exit_down = min(self.xsmall_ema_mid,self.short_stop) # 成交价回定止损 与最高价回撤一定比例通道宽度值 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.xsmall_com_width * self.sl_multiplier self.exit_down = min(exit_short_stop,self.short_stop) self.cover(self.exit_down,abs(self.pos),True) self.sync_data() self.put_event() def on_xsmall_bar(self, bar: BarData): """ :param bar: :return: """ # x分钟 多策略合合成的通道线 self.am_xsmall.update_bar(bar) if not self.am_xsmall.inited : return self.xsmall_ema_mid,self.xsmall_com_width,self.xsmall_up_min, self.xsmall_down_min,\ self.xsmall_up_max, self.xsmall_down_max = self.boll_kc_dc_combination( high=self.am_xsmall.high[:-1], low=self.am_xsmall.low[:-1], close=self.am_xsmall.close[:-1], boll_kk_dev=self.boll_kk_dev, kk_atr_length=self.kk_atr_length, com_length=self.com_length ) # print(f"xsmall: mid:{self.xsmall_ema_mid},width:{self.xsmall_com_width},upmin:{self.xsmall_up_min},\ # downmin:{self.xsmall_down_min},upmax:{self.xsmall_up_max},downmax:{self.xsmall_down_max}" + "\n") self.atr_value = self.am_xsmall.atr(self.kk_atr_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_kc_dc_combination(self, high, close, low, boll_kk_dev,kk_atr_length,com_length): # 计算组合均线 ema_com = talib.EMA(close, com_length) # 计算布林带 boll_std = talib.STDDEV(close, com_length) boll_up = ema_com + boll_kk_dev * boll_std boll_down = ema_com - boll_kk_dev * boll_std # 计算肯特通道 kc_atr = talib.ATR(high, low, close, kk_atr_length) kc_up = ema_com + kc_atr * boll_kk_dev kc_dowm = ema_com - kc_atr * boll_kk_dev # 计算唐安奇通道 dc_up = talib.MAX(high, com_length) dc_down = talib.MIN(low, com_length) # 计算轨道 因kc通道是直接,最小值大概率是直接,所以去除 pass_up_min = min(dc_up[-1], boll_up[-1]) pass_down_min = max(dc_down[-1], boll_down[-1]) pass_up_max = max(kc_up[-1], dc_up[-1], boll_up[-1]) pass_down_max = min(kc_dowm[-1], dc_down[-1], boll_down[-1]) ema_mid = ema_com[-1] com_width = abs(pass_up_max - pass_down_max) return ema_mid, com_width, pass_up_min, pass_down_min, pass_up_max, pass_down_max
class AtrRsiStrategyHN(CtaTemplate): """""" author = "黄柠" # 参数 atr_length = 22 atr_ma_length = 10 rsi_length = 5 rsi_entry = 16 trailing_percent = 0.8 fixed_size = 1 # 变量 atr_value = 0.0 atr_ma = 0.0 rsi_value = 0.0 rsi_buy = 0.0 rsi_sell = 0.0 intra_trade_high = 0.0 intra_trade_low = 0.0 parameters = [ "atr_length", "atr_ma_length", "rsi_length", "rsi_entry", "trailing_percent", "fixed_size" ] variables = [ "atr_value", "rsi_buy", "rsi_sell", "intra_trade_high", "intra_trade_low" ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(self, cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): self.write_log("策略初始化") self.rsi_buy = 50 + self.rsi_entry self.rsi_sell = 50 - self.rsi_entry self.load_bar(10) def on_start(self): self.write_log("策略启动") def on_stop(self): self.write_log("策略停止") def on_tick(self, tick: TickData): self.bg.update_tick(tick) def on_bar(self, bar: BarData): self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return atr_array = am.atr(self.atr_length, array=True) self.atr_value = atr_array[-1] self.atr_ma = atr_array[-self.atr_ma_length].mean() self.rsi_value = am.rsi(self.rsi_length) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price # 当atr_value大于atr_ma时,表明市场波动性增大,趋势正在增强 if self.atr_value > self.atr_ma: # 在趋势增强的情况下,用rsi指标产生交易信号 if self.rsi_value > self.rsi_buy: self.buy(bar.close_price + 5, self.fixed_size) elif self.rsi_value < self.rsi_sell: self.short(bar.close_price - 5, self.fixed_size) if self.pos > 0: # 移动止损,首先找到交易周期内价格最高点 self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price long_stop = self.intra_trade_high * (1 - self.trailing_percent / 100) self.sell(long_stop, abs(self.pos), stop=True) elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.intra_trade_high = bar.high_price short_stop = self.intra_trade_low * (1 + self.trailing_percent / 100) self.cover(short_stop, abs(self.pos), stop=True) self.put_event()
class ExampleStrategy(CtaTemplate): """""" author = "DEAN" boll_window = 18 boll_dev = 3.4 cci_window = 10 atr_window = 30 sl_multiplier = 5.2 fixed_size = 1 boll_up = 0 boll_down = 0 cci_value = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = ["boll_window", "boll_dev", "cci_window", "atr_window", "sl_multiplier", "fixed_size"] variables = ["boll_up", "boll_down", "cci_value", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(ExampleStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) self.cci_value = am.cci(self.cci_window) self.atr_value = am.atr(self.atr_window) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.cci_value > 0: self.buy(self.boll_up, self.fixed_size, True) elif self.cci_value < 0: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class AtrRsiStrategy(CtaTemplate): """""" author = '用Python的交易员' atr_length = 22 atr_ma_length = 10 rsi_length = 5 rsi_entry = 16 trailing_percent = 0.8 fixed_size = 1 atr_value = 0 atr_ma = 0 rsi_value = 0 rsi_buy = 0 rsi_sell = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = ['atr_length', 'atr_ma_length', 'rsi_length', 'rsi_entry', 'trailing_percent', 'fixed_size'] variables = ['atr_value', 'atr_ma', 'rsi_value', 'rsi_buy', 'rsi_sell'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(AtrRsiStrategy, 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.rsi_buy = 50 + self.rsi_entry self.rsi_sell = 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) def on_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 atr_array = am.atr(self.atr_length, array=True) self.atr_value = atr_array[-1] self.atr_ma = atr_array[-self.atr_ma_length:].mean() self.rsi_value = am.rsi(self.rsi_length) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.atr_value > self.atr_ma: if self.rsi_value > self.rsi_buy: self.buy(bar.close_price + 5, self.fixed_size) elif self.rsi_value < self.rsi_sell: 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 long_stop = self.intra_trade_high * \ (1 - self.trailing_percent / 100) self.sell(long_stop, abs(self.pos), stop=True) elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.intra_trade_high = bar.high_price short_stop = self.intra_trade_low * \ (1 + self.trailing_percent / 100) self.cover(short_stop, abs(self.pos), stop=True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class TSMyoIntraday30momStrategy(CtaTemplate): """""" author = "TheSuperMyo" # 日内交易 exit_time = time(hour=14, minute=56) # 针对不同交易时间的市场 open_time_night = time(hour=21, minute=0) # 商品夜盘 open_time_day_1 = time(hour=9, minute=0) # 商品 open_time_day_2 = time(hour=9, minute=30) # 股指 close_time_day = time(hour=15, minute=0) # 商品/股指(除了利率期货) close_time_night_1 = time(hour=23, minute=0) # 其他夜盘商品 close_time_night_2 = time(hour=1, minute=0) # 工业金属 close_time_night_3 = time(hour=2, minute=30) # 黄金/白银/原油 break_time_start_1 = time(hour=10, minute=15) # 商品茶歇 break_time_start_2 = time(hour=11, minute=30) # 全体午休 break_time_end_1 = time(hour=10, minute=30) # 商品茶歇 break_time_end_2 = time(hour=13, minute=0) # 股指下午 break_time_end_3 = time(hour=13, minute=30) # 商品下午 trailing_stop = 0.4 # 跟踪止损 stop_loss = 20 th = 0.5 / 100 # 涨跌幅阈值 fixed_size = 1 # 固定手数 bar_counter = 0 # 计数器 long_entry = 0 short_entry = 0 hold_high = 0 hold_low = 0 parameters = ['th', 'stop_loss', 'fixed_size'] #variables = ['bar_counter','long_entry','short_entry','hold_high','hold_low'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TSMyoIntraday30momStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 30, self.on_30_bar) # 股指每天240分钟 self.am = TSMArrayManager(240) # 策略自身订单管理 self.active_orderids = [] self.bars = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") # 不会用到昨日数据 self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def tick_filter(self, tick: TickData): """ 过滤异常时间的tick """ tick_time = tick.datetime.time() if tick_time < self.open_time_day_2: return False if tick_time > self.break_time_start_2 and tick_time < self.break_time_end_2: return False if tick_time > self.close_time_day: return False return True def on_tick(self, tick: TickData): """ Callback of new tick data update. """ if not self.tick_filter(tick): return self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ 根据信号挂单 """ self.cancel_all() self.bg.update_bar(bar) if self.pos == 0 and bar.datetime.time() < self.exit_time: if self.long_entry: # 入场开多,收盘价 self.hold_high = bar.high_price if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.buy(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.short_entry: # 入场开空,收盘价 self.hold_low = bar.low_price if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.short(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.pos > 0: self.long_entry = 0 self.short_entry = 0 #self.hold_high = max(self.hold_high,bar.high_price) #stop_long = self.hold_high * (1-self.trailing_stop/100) stop_long = self.hold_high - self.stop_loss if bar.datetime.time() > self.exit_time: # 日内平仓 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) else: # 停止单平多 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(stop_long, self.fixed_size, True, True) self.active_orderids.extend(orderids) if self.pos < 0: self.long_entry = 0 self.short_entry = 0 #self.hold_low = min(self.hold_low,bar.low_price) #stop_short = self.hold_low * (1+self.trailing_stop/100) stop_short = self.hold_low + self.stop_loss if bar.datetime.time() > self.exit_time: # 日内平仓 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) else: # 停止单平空 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(stop_short, self.fixed_size, True, True) self.active_orderids.extend(orderids) def on_30_bar(self, bar: BarData): """ 1.负责每日开盘的初始化 2.计算极值并产生信号 """ # self.cta_engine.output(f"{bar.datetime.time()}") # self.write_log(f"{bar.datetime.time()}") self.bar_counter += 1 am = self.am am.update_bar(bar) self.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] # 开盘bar if last_bar.datetime.date() != bar.datetime.date(): # 初始化 self.bar_counter = 1 self.long_entry = 0 self.short_entry = 0 if self.bar_counter != 7: return f1 = (am.close[-7] - am.close[-8]) / am.close[-8] f2 = (bar.close_price - bar.open_price) / bar.open_price print("930-1000:{0}, 1400-1430:{1}".format(f1, f2)) # 空仓且指示方向相同 if self.pos == 0 and f1 * f2 > 0: if f1 > self.th: # 开多信号 self.long_entry = 1 self.short_entry = 0 if f1 < -self.th: # 开空信号 self.long_entry = 0 self.short_entry = 1 def on_order(self, order: OrderData): """ Callback of new order data update. """ # 移除已成交或已撤销的订单 if not order.is_active() and order.vt_orderid in self.active_orderids: self.active_orderids.remove(order.vt_orderid) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # 邮寄提醒 self.send_email( f"{trade.vt_symbol}在{trade.time}成交,价格{trade.price},方向{trade.direction}{trade.offset},数量{trade.volume}" ) if self.pos > 0: self.hold_high = trade.price if self.pos < 0: self.hold_low = trade.price self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ # 刚刚生成的本地停止单 if stop_order.status == StopOrderStatus.WAITING: return # 撤销的本地停止单,从活跃列表移除 if stop_order.status == StopOrderStatus.CANCELLED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) # 触发的本地停止单,停止单移除,限价单加入 if stop_order.status == StopOrderStatus.TRIGGERED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) self.active_orderids.extend(stop_order.vt_orderids) # 撤掉其他停止单 for other_orderids in self.active_orderids: if other_orderids.startswith(STOPORDER_PREFIX): self.cancel_order(other_orderids)
class MacdStrategy(CtaTemplate): """基于布林通道的交易策略""" author = u'tonywang_efun' # 策略参数 fixed_size = 1 # 每次交易的数量 fixed_long_win_percent = 0.5 # 固定止盈百分比(多头) fixed_short_win_percent = 0.5 # 固定止盈百分比(空头) # 公共策略变量 pos_price = 0 # 持仓价 intra_trade_high = 0 intra_trade_low = 0 macd = 0 signal = 0 hist = 0 red_bar_num = 0 green_bar_num = 0 exit_time = time(hour=14, minute=55) night_open_time = time(hour=21, minute=00) last_bar = None new_day = False # 参数列表,保存了参数的名称 parameters = ['fixed_size', 'fixed_long_win_percent', 'fixed_short_win_percent'] # 变量列表,保存了变量的名称 variables = ['pos_price', 'intra_trade_high', 'intra_trade_low', 'macd', 'signal', 'hist'] # ---------------------------------------------------------------------- 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, 20, self.on_xmin_bar) self.am = ArrayManager() # ---------------------------------------------------------------------- def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) # ---------------------------------------------------------------------- def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") 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. """ if not self.last_bar or self.last_bar.datetime.date() != bar.datetime.date(): self.new_day = True self.last_bar = bar self.bg.update_bar(bar) if self.pos > 0: if self.exit_time <= bar.datetime.time() <= self.night_open_time: self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: if self.exit_time <= bar.datetime.time() <= self.night_open_time: self.cover(bar.close_price * 1.01, abs(self.pos)) def on_xmin_bar(self, bar: BarData): """收到x分钟K线""" # 撤销之前发出的尚未成交的委托(包括限价单和停止单) self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算多头指标数值 self.macd, self.signal, self.hist = am.macd(12, 26, 9) if self.hist > 0: self.red_bar_num += 1 self.green_bar_num = 0 elif self.hist < 0: self.red_bar_num = 0 self.green_bar_num += 1 if self.pos == 0 and (bar.datetime.time() < self.exit_time or bar.datetime.time() > self.night_open_time): self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.hist > 0: self.buy(bar.close_price, self.fixed_size) elif self.hist < 0: self.short(bar.close_price, self.fixed_size) # 持有多头仓位 elif self.pos > 0: if self.pos_price > bar.close_price \ and (self.pos_price - bar.close_price) / self.pos_price > (self.fixed_long_win_percent / 100): self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.hist < 0: self.sell(bar.close_price * 0.99, abs(self.pos)) else: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) # 持有空头仓位 elif self.pos < 0: if bar.close_price > self.pos_price \ and (bar.close_price - self.pos_price) / self.pos_price > (self.fixed_short_win_percent / 100): self.cover(bar.close_price * 1.01, abs(self.pos)) elif self.hist > 0: self.cover(bar.close_price * 1.01, abs(self.pos)) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) # 发出状态更新事件 self.put_event() def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" pass # ---------------------------------------------------------------------- def on_trade(self, trade): self.pos_price = trade.price self.put_event() # ---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" pass
class DoubleMaRsiStrategy(CtaTemplate): # 在双均线基础上增加rsi多空过滤 author = "double_ma_rsi" fast_window = 20 slow_window = 40 fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 parameters = ["fast_window", "slow_window"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager(size=60) self.local_stop = False self.limit_up = 1.04 self.limit_down = 0.96 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") # switch from load minute bar to hour bar # 回撤引擎,load_bar只有days(回溯交易日)和callback有作用,其他传入参数都没有作用。 self.load_bar(30) 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.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return rsi = am.rsi(self.slow_window) fast_ma = am.sma(self.fast_window, array=True) self.fast_ma0 = fast_ma[-1] self.fast_ma1 = fast_ma[-2] slow_ma = am.sma(self.slow_window, array=True) self.slow_ma0 = slow_ma[-1] self.slow_ma1 = slow_ma[-2] cross_over = self.fast_ma0 > self.slow_ma0 and self.fast_ma1 < self.slow_ma1 cross_below = self.fast_ma0 < self.slow_ma0 and self.fast_ma1 > self.slow_ma1 if cross_over: if self.pos == 0: self.buy(bar.close_price * self.limit_up, 1, self.local_stop) # print("Signal:", bar.datetime, "pos:", self.pos, "price:", bar.close_price, "gloden-cross open") elif self.pos < 0: self.cover(bar.close_price * self.limit_up, abs(self.pos), self.local_stop) # print("Signal:", bar.datetime, "pos:", self.pos, "price:", bar.close_price, "gloden-cross close short") if rsi > 50: # print("Signal:", bar.datetime, "pos:", self.pos, "price:", bar.close_price, "gloden-cross open long after close") self.buy(bar.close_price * self.limit_up, 1, self.local_stop) elif cross_below: if self.pos == 0: self.short(bar.close_price * self.limit_down, 1, self.local_stop) # print("Signal:", bar.datetime, "pos:", self.pos, "price:", bar.close_price, "dead-cross open") elif self.pos > 0: self.sell(bar.close_price * self.limit_down, abs(self.pos), self.local_stop) # print("Signal:", bar.datetime, "pos:", self.pos, "price:", bar.close_price, "dead-cross close long") if rsi < 50: self.short(bar.close_price * self.limit_down, 1, self.local_stop) # print("Signal:", bar.datetime, "pos:", self.pos, "price:", bar.close_price, "dead-cross open short after close") # print('==' * 50) # print('datetime:', bar.datetime, 'pos:', self.pos) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ # print("order", order.datetime, order.direction, order.offset, order.price, order.volume) pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # print("Trade:", trade.datetime, trade.direction, trade.offset, trade.price, trade.volume) self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
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 TurtleDStrategy(CtaTemplate): """""" # 改版海龟信号-ma出场 author = "turtle_exit_ma" entry_window = 50 exit_window = 20 atr_window = 20 stop_multiple = 10 fixed_size = 1 can_long = True can_short = True 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", "can_long", "can_short" ] 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.exit_up = self.exit_down = self.am.sma(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 if self.can_long: self.send_buy_orders(self.entry_up) if self.can_short: 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.fixed_size, True) def send_short_orders(self, price): """""" self.short(price, self.fixed_size, True)
class CincoP2005Strategy(CtaTemplate): """""" author = "tonywang_efun" bar_window = 15 boll_window = 34 boll_dev = 3.0 rsi_window = 12 rsi_long = 69 rsi_short = 22 trailing_long = 2.2 trailing_short = 2.6 fixed_size = 2 boll_up = 0 boll_down = 0 rsi_value = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = [ "bar_window", "boll_window", "boll_dev", "rsi_window", "rsi_long", "rsi_short", "trailing_long", "trailing_short", "fixed_size" ] variables = [ "boll_up", "boll_down", "rsi_value", "trading_size", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", ] def __init__( self, cta_engine, strategy_name: str, vt_symbol: str, setting: dict, ): """""" print(self.bar_window) super(CincoP2005Strategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) print(self.bar_window) self.bg = BarGenerator(self.on_bar, self.bar_window, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) self.rsi_value = self.am.rsi(self.rsi_window) boll_width = self.boll_up - self.boll_down if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 # print(self.boll_up, self.boll_down, self.intra_trade_high, self.intra_trade_low) if self.rsi_value >= self.rsi_long: self.buy(self.boll_up, self.fixed_size, stop=True) if self.rsi_value <= self.rsi_short: self.short(self.boll_down, self.fixed_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class OscillatorDriveStrategy(CtaTemplate): """""" author = "用Python的交易员" boll_window = 34 boll_dev = 2.4 atr_window = 20 trading_size = 1 risk_level = 50 sl_multiplier = 1.8 dis_open = 8 interval = 25 boll_up = 0 boll_down = 0 cci_value = 0 atr_value = 0 long_stop = 0 short_stop = 0 exit_up = 0 exit_down = 0 parameters = [ "boll_window", "boll_dev", "dis_open", "interval", "atr_window", "sl_multiplier" ] variables = [ "boll_up", "boll_down", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(OscillatorDriveStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.interval, self.on_xmin_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) self.ultosc = am.ultosc() buy_dis = 50 + self.dis_open sell_dis = 50 - self.dis_open self.atr_value = am.atr(self.atr_window) if self.pos == 0: self.trading_size = max(int(self.risk_level / self.atr_value), 1) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.ultosc > buy_dis: self.buy(self.boll_up, self.trading_size, True) elif self.ultosc < sell_dis: self.short(self.boll_down, self.trading_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class RsiDollarATR(CtaTemplate): """""" author = "yiran" dollar_threshold = 1_00_00_00_0 long_trend_cum_threshold = 10 short_trend_cum_threshold = 10 init_dollar_bar_num = 100 rsi_window = 10 atr_window = 10 rsi_up_threshold = 70 sma_short_window = 5 sma_long_window = 20 exit_loss = 0.02 exit_return = 0.2 atr_multiplier = 0.05 cross_over_day = 10 fixed_size = 1 long_order_record = [] short_order_record = [] rsi_value = 0 atr_value = 0 long_trend_cum = 0 short_trend_cum = 0 stop_price = 0 exit_price = 0 hold_bar_num = 0 cum_filtered = False dollar_bar_finished = False long_trend = False short_trend = False long_trend_days = np.inf short_trend_days = np.inf parameters = [ 'rsi_window', 'rsi_up_threshold', 'atr_window', 'sma_short_window', 'cross_over_day', 'sma_long_window', 'atr_multiplier', 'long_trend_cum_threshold', 'short_trend_cum_threshold', 'exit_loss','exit_return', 'sma_short_window', 'sma_long_window'] variables = ['rsi_value', 'atr_value', 'exit_price'] 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.long_order_record = [] self.short_order_record = [] self.one_minute_bar_price_list = [] self.one_minute_bar_volume_list = [] self.time_list = [] self.one_minute_bar_num_list = [] # dollar-bar self.high_list = [] self.low_list = [] self.close_list = [] self.open_list = [] self.volume_list = [] # cum_filter_bar self.cum_high_list = [] self.cum_low_list = [] self.cum_close_list = [] self.cum_open_list = [] self.cum_volume_list = [] self.cum_time_list = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.one_minute_bar_price_list.append(bar.close_price) self.one_minute_bar_volume_list.append(bar.volume) dollar_amount = np.sum( np.array( self.one_minute_bar_price_list) * np.array( self.one_minute_bar_volume_list)) if dollar_amount >= self.dollar_threshold: high_price = np.max(self.one_minute_bar_price_list) close = self.one_minute_bar_price_list[-1] low_price = np.min(self.one_minute_bar_price_list) open_price = self.one_minute_bar_price_list[0] volume = np.sum(self.one_minute_bar_volume_list) self.high_list.append(high_price) self.close_list.append(close) self.open_list.append(open_price) self.volume_list.append(volume) self.low_list.append(low_price) self.time_list.append(bar.datetime) self.one_minute_bar_num_list.append( len(self.one_minute_bar_price_list)) self.one_minute_bar_volume_list = [] self.one_minute_bar_price_list = [] # 交易策略信号计算在dollar合成之后 self.dollar_bar_finished = True if len(self.high_list) < self.init_dollar_bar_num: return if self.dollar_bar_finished: self.cancel_all() close_array = np.array(self.close_list) high_array = np.array(self.high_list) low_array = np.array(self.low_list) open_array = np.array(self.open_list) volume_array = np.array(self.volume_list) if close_array.shape[0] < self.rsi_window: self.dollar_bar_finished = False return self.rsi_value = talib.RSI(close_array, self.rsi_window)[-1] if self.rsi_value > self.rsi_up_threshold: self.long_trend_cum += 1 elif self.rsi_value < 100 - self.rsi_up_threshold: self.short_trend_cum += 1 if self.long_trend_cum >= self.long_trend_cum_threshold or self.short_trend_cum >= self.short_trend_cum_threshold: self.cum_filtered = True if self.cum_filtered: self.cum_close_list.append(close_array[-1]) self.cum_high_list.append(high_array[-1]) self.cum_low_list.append(low_array[-1]) self.cum_open_list.append(open_array[-1]) self.cum_volume_list.append(volume_array[-1]) self.cum_time_list.append(bar.datetime) if len( self.cum_open_list) < max( self.sma_long_window, self.atr_window): self.dollar_bar_finished = False self.cum_filtered = False self.long_trend_cum = 0 self.short_trend_cum = 0 return cum_close_array = np.array(self.cum_close_list) cum_high_array = np.array(self.cum_high_list) cum_low_array = np.array(self.cum_low_list) cum_open_array = np.array(self.cum_open_list) sma_short_window_array = talib.SMA( cum_close_array, self.sma_short_window) sma_long_window_array = talib.SMA( cum_close_array, self.sma_long_window) atr_array = talib.ATR( cum_high_array, cum_low_array, cum_close_array, self.atr_window) self.atr_value = atr_array[-1] if sma_long_window_array[-2] > sma_short_window_array[-2] and sma_long_window_array[-1] < sma_short_window_array[-1]: self.long_trend = True self.long_trend_days = 0 elif sma_long_window_array[-2] < sma_short_window_array[-2] and sma_long_window_array[-1] > sma_short_window_array[-1]: self.short_trend = True self.short_trend_days = 0 if self.short_trend_days != np.inf: self.short_trend_days += 1 elif self.long_trend_days != np.inf: self.long_trend_days += 1 if self.pos == 0: self.stop_price = 0 self.exit_price = 0 self.hold_bar_num = 0 if self.short_trend and self.short_trend_days < self.cross_over_day: self.short(bar.close_price - 5, self.fixed_size) self.short_order_record.append(bar.close_price - 5) elif self.long_trend and self.long_trend_days < self.cross_over_day: self.buy(bar.close_price + 5, self.fixed_size) self.long_order_record.append(bar.close_price + 5) elif self.pos > 0: self.long_trend = False self.long_trend_days = np.inf buy_order_price = self.long_order_record[-1] self.stop_price = buy_order_price * (1 - self.exit_loss) self.exit_price = buy_order_price * \ (1 + self.exit_return) - self.hold_bar_num * self.atr_value * self.atr_multiplier if bar.close_price <= self.exit_price: self.sell(bar.close_price * 0.99, abs(self.pos)) elif bar.close_price >= self.exit_price: self.sell(bar.close_price * 0.99, abs(self.pos)) self.hold_bar_num += 1 elif self.pos < 0: self.short_trend = False self.short_trend_days = np.inf sell_order_price = self.short_order_record[-1] self.stop_price = sell_order_price * (1 + self.exit_loss) self.exit_price = sell_order_price * \ (1 - self.exit_return) + self.hold_bar_num * self.atr_value * self.atr_multiplier if bar.close_price >= self.stop_price: self.cover(bar.close_price * 1.01, abs(self.pos)) elif bar.close_price <= self.exit_price: self.cover(bar.close_price * 1.01, abs(self.pos)) self.hold_bar_num += 1 self.dollar_bar_finished = False self.cum_filtered = False self.long_trend_cum = 0 self.short_trend_cum = 0 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 AtrRsiStrategy(CtaTemplate): """""" author = "用Python的交易员" # 第一个参数最好是作者,万一泄露时还可以证明是你的 ## 下面6个是定义策略的参数,参数初始化给默认值 atr_length = 22 atr_ma_length = 10 rsi_length = 5 rsi_entry = 16 # 计算初始化的时候计算rsi买入或者卖出的阈值 trailing_percent = 0.8 fixed_size = 1 ## 下面6个是定义策略的默认变量,变量默认给0,代表初始化 atr_value = 0 atr_ma = 0 rsi_value = 0 rsi_buy = 0 rsi_sell = 0 intra_trade_high = 0 intra_trade_low = 0 ## 将策略参数的名称字符串放入parameters列表,告诉vnpy这些是参数 parameters = [ "atr_length", "atr_ma_length", "rsi_length", "rsi_entry", "trailing_percent", "fixed_size" ] ## 将策略变量的名称字符串放入variables列表,告诉vnpy这些是变量 variables = [ "atr_value", "atr_ma", "rsi_value", "rsi_buy", "rsi_sell", "intra_trade_high", "intra_trade_low" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """想显示在策略页面上的,仅仅用来临时存放和调度的临时变量,可以在__init__中进行定义""" 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.rsi_buy = 50 + self.rsi_entry # 定义超买区域 self.rsi_sell = 50 - self.rsi_entry # 定义超卖区域 self.load_bar(10) # cta策略必须在初始化时加载历史k线,把初始化状态算出来。如果是国内品种,如果至少要10天的历史k线计算,考虑到国内黄金周小长假连同周末经常停止交易10天左右,那么这里最好加载20天的历史k线 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. 实盘中CTP或Bitmex接口每次推送tick变化时都会调用 """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. K线推送的函数。一定是1分钟k线的推送。用于回测,实盘柜台只推送tick """ self.cancel_all() # 每根k线推送后,撤销之前一根K线上下的所有未成交订单,会导致比较频繁的撤单 am = self.am # 实例化ArrayManager对象 am.update_bar(bar) # 将k线推送到ArrayManager if not am.inited: # 如判断ArrayManager初始化状态,如果ArrayManager没有完成初始化状态,就不管他 return atr_array = am.atr(self.atr_length, array=True) # 传入atr的时间窗口,创建atr时间序列 self.atr_value = atr_array[-1] # 取最近的atr数值为atr_value self.atr_ma = atr_array[-self.atr_ma_length:].mean() # 给atr时间序列取最老的atr_ma_length个数据的平均值,赋值给atr_ma self.rsi_value = am.rsi(self.rsi_length) # 传入rsi的时间窗口创建rsi指标时间序列 ## 没有持仓的情况 if self.pos == 0: self.intra_trade_high = bar.high_price # 将当根bar的最高价赋值,下面似乎没有用到这个值 self.intra_trade_low = bar.low_price # 将当根bar的最低价赋值,下面似乎没有用到这个值 ## 进场逻辑(5行代码) if self.atr_value > self.atr_ma: # 【过滤】当atr超过其10天均值时,意味着短期波动显著上升 if self.rsi_value > self.rsi_buy: # 【信号】当最近的rsi进入超买区域 self.buy(bar.close_price + 5, self.fixed_size) # 按照当根bar的收盘价+5个bp下多头限价单,固定仓位1手 elif self.rsi_value < self.rsi_sell: # 【信号】当rsi进入超卖区域 self.short(bar.close_price - 5, self.fixed_size) # 按照当根bar的收盘价-5个bp下空头限价单,固定仓位1手 ## 出场策略,移动止损方法 ## 持有多头仓位的情况 elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) # 跟踪买入后价格最高到过什么位置 self.intra_trade_low = bar.low_price # 记录当根k线最低价水平 long_stop = self.intra_trade_high * \ (1 - self.trailing_percent / 100) # 最高价*价格固定百分比(回撤)作为出场位置 self.sell(long_stop, abs(self.pos), stop=True) # 使用停止单卖出,目的在于不等待价格走完,而是当价格下跌超出回撤比例时,立刻执行卖出操作 ## 持有空头仓位的情况 elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) # 跟踪买入后价格最低到过什么位置 self.intra_trade_high = bar.high_price short_stop = self.intra_trade_low * \ (1 + self.trailing_percent / 100) self.cover(short_stop, abs(self.pos), stop=True) self.put_event() # 刷新vntrader界面上的数据 def on_order(self, order: OrderData): """ Callback of new order data update. 委托状态推送:发出委托-券商收到-推到交易所-看到委托在交易所中某档挂单-反馈“未成交状态”-成交1手-委托状态变成“部分成交-成交全部-委托状态变成“全部成交” """ 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 IndicatorStrategy(CtaTemplate): """ 目前使用中轨加速,可以考虑使用另外一根均线来加速,这样可以避免在开仓时被平。 """ author = "yunya" open_window = 15 boll_window = 10 slow_length = 55 fixed_size = 1 condition_long = False condition_short = False indicator_current = 0 indicator_last = 0 boll_up_current = 0 boll_up_last = 0 boll_down_current = 0 boll_down_last = 0 boll_mid_current = 0 boll_mid_last = 0 parameters = [ "open_window", "fast_length", "slow_length", "fixed_size", ] variables = [ "condition_long", "condition_short", "indicator_current", "indicator_last", "boll_up_current", "boll_up_last", "boll_down_current", "boll_down_last", "boll_mid_current", "boll_mid_last", ] 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_xmin_bar) self.am = ArrayManager(self.boll_window * 3 + 50) self.count: int = 0 self.count_boll: int = 0 self.indicator_inited: bool = False self.boll_inited: bool = False self.mtm_size: int = self.slow_length self.indicator_np_array: np.ndarray = np.zeros(self.boll_window * 3 + 5) 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) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return indicator = self.indicator_array(self.am.high, self.am.low, self.am.close, self.boll_window, self.indicator_np_array) if not self.indicator_inited: return # 自适应布林带 median = ta.SMA(indicator, self.boll_window) std = np.std(indicator, axis=0) z_score = abs(indicator - median) / std m_z = z_score[-self.boll_window - 1:-2].max() up = median + std * m_z dn = median - std * m_z if indicator[-1] > up[-1] and indicator[-2] <= up[-2]: print("开多" + "\n") elif indicator[-1] < median[-1] and indicator[-2] >= median[-2]: print("平多" + "\n") if indicator[-1] < dn[-1] and indicator[-2] >= dn[-2]: print("开空" + "\n") elif indicator[-1] > median[-1] and indicator[-2] <= median[-2]: print("平空" + "\n") # # exit() # # # 计算 大布林 # sma_array = am.sma(self.slow_length, True) # std_array = am.std(self.slow_length, True) # dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1] # # dev_max = dev[-self.slow_length:].mean() # boll_up_max_array = sma_array + std_array * dev_max # boll_down_max_array = sma_array - std_array * dev_max # # boll_up_max = boll_up_max_array[-1] # boll_down_max = boll_down_max_array[-1] # # # 大于大周期布林上轨,不做空,小于布林下轨,不做多 # if bar.close_price > boll_up_max: # self.condition_long = True # else: # self.condition_long = False # # if bar.close_price < boll_down_max: # self.condition_short = True # else: # self.condition_short = False # # self.indicator_current = self.indicator[-1] # self.indicator_last = self.indicator[-2] # self.boll_up_current = self.boll_up_array[-1] # self.boll_up_last = self.boll_up_array[-2] # self.boll_down_current = self.boll_down_array[-1] # self.boll_down_last = self.boll_down_array[-2] # self.boll_mid_current = self.boll_mid_array[-1] # self.boll_mid_last = self.boll_mid_array[-2] # # # 如果没有仓位,两条布林window一样 # if self.pos == 0: # condition1 = self.indicator_current > self.boll_up_current # condition2 = self.indicator_last <= self.boll_up_last # # condition3 = self.indicator_current < self.boll_up_current # condition4 = self.indicator_last >= self.boll_down_last # # if condition1 and condition2: # # 在大网下轨,不做多 # if self.condition_short: # self.buy(bar.close_price + 10, self.fixed_size) # # elif condition3 and condition4: # # 在大网上轨,不做空 # if self.condition_long: # self.short(bar.close_price - 10, self.fixed_size) # # elif self.pos > 0: # condition1 = self.indicator_current < self.boll_mid_current # condition2 = self.indicator_last >= self.boll_mid_last # if condition1 and condition2: # self.sell(bar.close_price - 10, abs(self.pos)) # # elif self.pos < 0: # condition1 = self.indicator_current > self.boll_mid_current # condition2 = self.indicator_last <= self.boll_mid_last # if condition1 and condition2: # self.cover(bar.close_price + 10, abs(self.pos)) # # self.put_event() # self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ pass # if trade.direction == Direction.LONG: # self.trade_price_long = trade.price # 成交最高价 # self.long_stop_trade = self.trade_price_long - self.atr_multiple * self.atr_value # else: # self.trade_price_short = trade.price # self.short_stop_trade = self.trade_price_short + self.atr_multiple * self.atr_value # # self.sync_data() # self.put_event() def atr_wd(self, high, low, close, n): """ 计算 atr 相对 close 的波动因子 """ atr = ta.ATR(high, low, close, n) ma = ta.SMA(close, n) wd_atr = atr / ma return wd_atr[-1] def mtm_atr(self, high, low, close, n): """ 1、计算 mtm值(用去掉量纲方式计算) 2、用 atr 的方式计算得到 mtm_atr """ # 计算MTM值 high_shift = shift(high, 1) low_shift = shift(low, 1) close_shift = shift(close, 1) # 补全 high_shift[0] = high_shift[1] low_shift[0] = low_shift[1] close_shift[0] = close_shift[1] # 计算mtm mtm_high = high / high_shift - 1 mtm_low = low / low_shift - 1 mtm_close = close / close_shift - 1 mtm_atr = ta.ATR(mtm_high, mtm_low, mtm_close, n) return mtm_atr[-1] def mem_atr_mean_array(self, high, low, close, n): """ :return: """ # 计算MTM值 high_shift = shift(high, 1) low_shift = shift(low, 1) close_shift = shift(close, 1) # 补全 high_shift[0] = high_shift[1] low_shift[0] = low_shift[1] close_shift[0] = close_shift[1] # 计算mtm mtm_high = high / high_shift - 1 mtm_low = low / low_shift - 1 mtm_close = close / close_shift - 1 # 计算MTM均值 mtm_high_mean = ta.SMA(mtm_high, n) mtm_low_mean = ta.SMA(mtm_low, n) mtm_close_mean = ta.SMA(mtm_close, n) mtm_mean_atr = ta.ATR(mtm_high_mean, mtm_low_mean, mtm_close_mean, n) return mtm_mean_atr[-1] def indicator_array(self, high, low, close, n, indicator_np): """ :return: """ self.count += 1 if not self.indicator_inited and self.count >= self.mtm_size: self.indicator_inited = True indicator_np[:-1] = indicator_np[1:] close_shift = shift(close, 1) close_shift[0] = close_shift[1] mtm_close = close / close_shift - 1 close_mtm = ta.SMA(mtm_close, n)[-1] atr_wd = self.atr_wd(high, low, close, n) mtm_atr = self.mtm_atr(high, low, close, n) mtm_atr_mean = self.mem_atr_mean_array(high, low, close, n) indicator = close_mtm * atr_wd * mtm_atr * mtm_atr_mean indicator_np[-1] = indicator return indicator_np
class TSMyoImpulseStrategy(CtaTemplate): """""" author = "TheSuperMyo" # 日内交易 exit_time = time(hour=14, minute=56) # 针对不同交易时间的市场 open_time_night = time(hour=21, minute=0) # 商品夜盘 open_time_day_1 = time(hour=9, minute=0) # 商品 open_time_day_2 = time(hour=9, minute=30) # 股指 close_time_day = time(hour=15, minute=0) # 商品/股指(除了利率期货) close_time_night_1 = time(hour=23, minute=0) # 其他夜盘商品 close_time_night_2 = time(hour=1, minute=0) # 工业金属 close_time_night_3 = time(hour=2, minute=30) # 黄金/白银/原油 break_time_start_1 = time(hour=10, minute=15) # 商品茶歇 break_time_start_2 = time(hour=11, minute=30) # 全体午休 break_time_end_1 = time(hour=10, minute=30) # 商品茶歇 break_time_end_2 = time(hour=13, minute=0) # 股指下午 break_time_end_3 = time(hour=13, minute=30) # 商品下午 exit_counter = 0 bar_tr = 0 bar_atr = 0 long_open = 0 short_open = 0 long_stop = 0 short_stop = 0 tr_k1 = 3.0 tr_k2 = 2.0 close_range = 0.2 xmin = 20 fixed_size = 1 parameters = ["tr_k1", "tr_k2", "close_range", "xmin"] variables = [ "exit_counter", "bar_tr", "bar_atr", "long_open", "long_stop", "short_open", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TSMyoImpulseStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.xmin, self.on_xmin_bar) self.am = TSMArrayManager() # 策略自身订单管理 self.active_orderids = [] self.bars = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") # 根据需要的历史数据长度设定 self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def tick_filter(self, tick: TickData): """ 过滤异常时间的tick """ pass def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ 1.挂单 """ self.bg.update_bar(bar) self.cancel_all() if bar.datetime.time() < self.exit_time: if self.pos == 0: if self.long_open: # 开多 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.buy(self.long_open, self.fixed_size, lock=True, stop=True) self.active_orderids.extend(orderids) elif self.short_open: # 开空 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.short(self.short_open, self.fixed_size, lock=True, stop=True) self.active_orderids.extend(orderids) if self.pos > 0: self.exit_counter += 1 if self.exit_counter > self.xmin: if self.long_stop: # 停止单止损 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(self.long_stop, self.fixed_size, lock=True, stop=True) self.active_orderids.extend(orderids) if self.pos < 0: self.exit_counter += 1 if self.exit_counter > self.xmin: if self.short_stop: # 停止单止损 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(self.long_stop, self.fixed_size, lock=True, stop=True) self.active_orderids.extend(orderids) # 日内交易 else: if self.pos > 0: # 平多 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(bar.close_price, self.fixed_size, lock=True) self.active_orderids.extend(orderids) if self.pos < 0: # 平空 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(bar.close_price, self.fixed_size, lock=True) self.active_orderids.extend(orderids) self.put_event() def on_xmin_bar(self, bar: BarData): """ 1.开盘/盘中信号生成 2.生成止损价位 """ # for debug 930为930-945bar时间戳 # self.cta_engine.output(bar.datetime.time()) am = self.am am.update_bar(bar) if not am.inited: return # 当前bar的TR和之前bars的ATR self.bar_tr = am.tr(False) atr_array = am.atr(240 / self.xmin, True) self.bar_atr = atr_array[-2] self.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] # 第一根xminbar if last_bar.datetime.date() != bar.datetime.date(): if self.bar_tr > self.bar_atr * self.tr_k1: # 计算close是否收在两端close_range内 lv = (bar.close_price - bar.low_price) / (bar.high_price - bar.low_price) if lv < self.close_range: # 快速下跌波动且close收低,开多信号 self.long_open = bar.close_price self.long_stop = bar.low_price self.short_stop = 0 self.short_open = 0 elif lv > (1 - self.close_range): # 快速上涨波动且close收高,开空信号 self.short_open = bar.close_price self.short_stop = bar.high_price self.long_open = 0 self.long_stop = 0 elif self.pos == 0: if self.bar_tr > self.bar_atr * self.tr_k2: # 计算close是否收在两端close_range内 lv = (bar.close_price - bar.low_price) / (bar.high_price - bar.low_price) if lv < self.close_range: # 快速下跌波动且close收低,开多信号 self.long_open = bar.close_price self.long_stop = bar.low_price self.short_stop = 0 self.short_open = 0 elif lv > (1 - self.close_range): # 快速上涨波动且close收高,开空信号 self.short_open = bar.close_price self.short_stop = bar.high_price self.long_open = 0 self.long_stop = 0 self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ # 移除已成交或已撤销的订单 if not order.is_active() and order.vt_orderid in self.active_orderids: self.active_orderids.remove(order.vt_orderid) def on_trade(self, trade: TradeData): """ 1.重置倒计时 """ if self.pos == 0: self.exit_counter = 0 # 邮寄提醒 self.send_email( f"{trade.vt_symbol}在{trade.time}成交,价格{trade.price},方向{trade.direction}{trade.offset},数量{trade.volume}" ) self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ # 刚刚生成的本地停止单 if stop_order.status == StopOrderStatus.WAITING: return # 撤销的本地停止单,从活跃列表移除 if stop_order.status == StopOrderStatus.CANCELLED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) # 触发的本地停止单,停止单移除,限价单加入 if stop_order.status == StopOrderStatus.TRIGGERED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) self.active_orderids.extend(stop_order.vt_orderids) # 撤掉其他停止单 for other_orderids in self.active_orderids: if other_orderids.startswith(STOPORDER_PREFIX): self.cancel_order(other_orderids)
class TSMyoBollSARStrategy(CtaTemplate): """""" author = "TheSuperMyo" # 日内交易 exit_time = time(hour=14, minute=56) # 针对不同交易时间的市场 open_time_night = time(hour=21, minute=0) # 商品夜盘 open_time_day_1 = time(hour=9, minute=0) # 商品 open_time_day_2 = time(hour=9, minute=30) # 股指 close_time_day = time(hour=15, minute=0) # 商品/股指(除了利率期货) close_time_night_1 = time(hour=23, minute=0) # 其他夜盘商品 close_time_night_2 = time(hour=1, minute=0) # 工业金属 close_time_night_3 = time(hour=2, minute=30) # 黄金/白银/原油 break_time_start_1 = time(hour=10, minute=15) # 商品茶歇 break_time_start_2 = time(hour=11, minute=30) # 全体午休 break_time_end_1 = time(hour=10, minute=30) # 商品茶歇 break_time_end_2 = time(hour=13, minute=0) # 股指下午 break_time_end_3 = time(hour=13, minute=30) # 商品下午 fit_bar = 3 # K线周期 boll_len = 26 # 布林带周期 boll_nstd = 2.5 # 布林带宽 low_std_len = 6 # 波动率持续低迷周期 low_std_value = 9.2 # 波动率阈值 setup_bar = 85 # 基础拟合分钟数 trailing_stop = 0.45 # 跟踪止损 fixed_size = 1 # 固定手数 bar_counter = 0 # 每日分钟计数器 SAR_stop_long = 0 SAR_stop_short = 0 AF = 0 long_entry = 0 short_entry = 0 long_exit = 0 short_exit = 0 hold_high = 0 hold_low = 0 parameters = [ 'low_std_value', 'low_std_len', 'boll_nstd', 'boll_len', 'setup_bar', 'fit_bar', 'fixed_size' ] variables = [ 'bar_counter', 'SAR_stop_long', 'SAR_stop_short', 'AF', 'hold_high', 'hold_low' ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TSMyoBollSARStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.fit_bar, self.on_fit_bar) # 股指每天240分钟 self.am = TSMArrayManager(240) # 策略自身订单管理 self.active_orderids = [] self.bars = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") # 不会用到昨日数据 self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def tick_filter(self, tick: TickData): """ 过滤异常时间的tick """ tick_time = tick.datetime.time() if tick_time < self.open_time_day_2: return False if tick_time > self.break_time_start_2 and tick_time < self.break_time_end_2: return False if tick_time > self.close_time_day: return False return True def on_tick(self, tick: TickData): """ Callback of new tick data update. """ if not self.tick_filter(tick): return self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ 1.分钟计数 2.根据信号挂单 3.计算SAR系统止损点位 """ self.bar_counter += 1 self.bg.update_bar(bar) self.cancel_all() if self.pos == 0 and bar.datetime.time() < self.exit_time: if self.long_entry: # 入场开多,收盘价 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.buy(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.short_entry: # 入场开空,收盘价 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.short(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) if self.pos > 0: old_high = self.hold_high self.hold_high = max(self.hold_high, bar.high_price) if old_high - self.hold_high != 0: self.AF += 0.01 self.AF = min(self.AF, 0.1) self.SAR_stop_long = self.SAR_stop_long + ( self.hold_high - self.SAR_stop_long) * self.AF #self.stop_long = self.hold_high*(1-self.trailing_stop/100) if bar.datetime.time() > self.exit_time: # 日内平仓 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) else: # 停止单平多 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.sell(self.SAR_stop_long, self.fixed_size, True, True) self.active_orderids.extend(orderids) if self.pos < 0: old_low = self.hold_low self.hold_low = min(self.hold_low, bar.low_price) if old_low - self.hold_low != 0: self.AF += 0.01 self.AF = min(self.AF, 0.1) self.SAR_stop_short = self.SAR_stop_short - ( self.SAR_stop_short - self.hold_low) * self.AF if bar.datetime.time() > self.exit_time: # 日内平仓 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(bar.close_price, self.fixed_size, False, True) self.active_orderids.extend(orderids) else: # 停止单平空 if self.active_orderids: self.write_log("撤单不干净,无法挂单") return orderids = self.cover(self.SAR_stop_short, self.fixed_size, True, True) self.active_orderids.extend(orderids) def on_fit_bar(self, bar: BarData): """ 1.负责每日开盘的初始化 2.计算极值并产生信号 """ # self.cta_engine.output(f"{bar.datetime.time()}") # self.write_log(f"{bar.datetime.time()}") am = self.am am.update_bar(bar) self.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] # 开盘fit_min_bar if last_bar.datetime.date() != bar.datetime.date(): # 初始化 self.bar_counter = self.fit_bar self.long_entry = 0 self.short_entry = 0 self.long_exit = 0 self.short_exit = 0 self.SAR_stop_long = 0 self.SAR_stop_short = 0 if self.bar_counter < self.fit_bar * self.boll_len: return boll_up, boll_down = am.boll(self.boll_len, self.boll_nstd, False) std_array = am.std(self.low_std_len, True) std = std_array[-2] if self.pos == 0 and std < self.low_std_value: if bar.close_price > boll_up: # 向上突破,开多信号 self.long_entry = 1 self.short_entry = 0 self.long_exit = 0 self.short_exit = 0 # 抛物线初始止损点 self.SAR_stop_long = bar.low_price if bar.close_price < boll_down: # 向下突破,开空信号 self.long_entry = 0 self.short_entry = 1 self.long_exit = 0 self.short_exit = 0 # 抛物线初始止损点 self.SAR_stop_short = bar.high_price def on_order(self, order: OrderData): """ Callback of new order data update. """ # 移除已成交或已撤销的订单 if not order.is_active() and order.vt_orderid in self.active_orderids: self.active_orderids.remove(order.vt_orderid) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # 邮寄提醒 self.send_email( f"{trade.vt_symbol}在{trade.time}成交,价格{trade.price},方向{trade.direction}{trade.offset},数量{trade.volume}" ) self.long_entry = 0 self.short_entry = 0 self.long_exit = 0 self.short_exit = 0 if self.pos == 0: self.SAR_stop_long = 0 self.SAR_stop_short = 0 self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ # 刚刚生成的本地停止单 if stop_order.status == StopOrderStatus.WAITING: return # 撤销的本地停止单,从活跃列表移除 if stop_order.status == StopOrderStatus.CANCELLED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) # 触发的本地停止单,停止单移除,限价单加入 if stop_order.status == StopOrderStatus.TRIGGERED: if stop_order.stop_orderid in self.active_orderids: self.active_orderids.remove(stop_order.stop_orderid) self.active_orderids.extend(stop_order.vt_orderids) # 撤掉其他停止单 for other_orderids in self.active_orderids: if other_orderids.startswith(STOPORDER_PREFIX): self.cancel_order(other_orderids)
class SuperComboStrategy(CtaTemplate): """""" author = "用Python的交易员" # Parameters thrust_long = 0.34 trailing_long = 0.35 thrust_short = 0.4 trailing_short = 0.8 trading_size = 1 # Variables day_open = 0 day_high = 0 day_low = 0 sum_range = 0 long_entry = 0 short_entry = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 last_bar = None parameters = [ "thrust_long", "trailing_long", "thrust_short", "trailing_short", "trading_size" ] variables = [ "day_high", "day_low", "sum_range", "long_entry", "short_entry", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() if not self.last_bar: self.last_bar = bar return # For a new day, update all entry_range if bar.datetime.day != self.last_bar.datetime.day: self.sum_range = self.day_high - self.day_low self.day_open = bar.open_price self.day_high = bar.high_price self.day_low = bar.low_price long_entry_range = self.thrust_long * self.sum_range self.long_entry = self.day_open + long_entry_range short_entry_range = self.thrust_short * self.sum_range self.short_entry = self.day_open - short_entry_range # Otherwise update daily high/low price else: self.day_high = max(self.day_high, bar.high_price) self.day_low = min(self.day_low, bar.low_price) self.long_entry = max(self.long_entry, self.day_high) self.short_entry = min(self.short_entry, self.day_low) # Only open positions before 14:55 if bar.datetime.time() < time(14, 55): # No pos if not self.pos: self.intra_trade_low = bar.low_price self.intra_trade_high = bar.high_price if bar.close_price > self.day_open: self.buy(self.long_entry, self.trading_size, True, lock=True) else: self.short(self.short_entry, self.trading_size, True, lock=True) # Long pos elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high * \ (1 - self.trailing_long / 100) self.sell(self.long_stop, abs(self.pos), True, True) # Short pos else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low * \ (1 + self.trailing_short / 100) self.cover(self.short_stop, abs(self.pos), True, True) # Close all positions after 14:55 else: if self.pos > 0: self.sell(bar.close_price - 10, abs(self.pos), lock=True) elif self.pos < 0: self.cover(bar.close_price + 10, abs(self.pos), lock=True) self.last_bar = bar self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ pass 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 DualThrustStrategy(CtaTemplate): """""" author = "用Python的交易员" fixed_size = 1 k1 = 0.4 k2 = 0.6 bars = [] day_open = 0 day_high = 0 day_low = 0 range = 0 long_entry = 0 short_entry = 0 exit_time = time(hour=14, minute=55) long_entered = False short_entered = False parameters = ["k1", "k2", "fixed_size"] variables = ["range", "long_entry", "short_entry"] 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.bars = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def 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.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] if last_bar.datetime.date() != bar.datetime.date(): if self.day_high: self.range = self.day_high - self.day_low self.long_entry = bar.open_price + self.k1 * self.range self.short_entry = bar.open_price - self.k2 * self.range self.day_open = bar.open_price self.day_high = bar.high_price self.day_low = bar.low_price self.long_entered = False self.short_entered = False else: self.day_high = max(self.day_high, bar.high_price) self.day_low = min(self.day_low, bar.low_price) if not self.range: return if bar.datetime.time() < self.exit_time: if self.pos == 0: if bar.close_price > self.day_open: if not self.long_entered: self.buy(self.long_entry, self.fixed_size, stop=True) else: if not self.short_entered: self.short(self.short_entry, self.fixed_size, stop=True) elif self.pos > 0: self.long_entered = True self.sell(self.short_entry, self.fixed_size, stop=True) if not self.short_entered: self.short(self.short_entry, self.fixed_size, stop=True) elif self.pos < 0: self.short_entered = True self.cover(self.long_entry, self.fixed_size, stop=True) if not self.long_entered: self.buy(self.long_entry, self.fixed_size, stop=True) else: if self.pos > 0: self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.cover(bar.close_price * 1.01, abs(self.pos)) self.put_event() def on_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 DualThrustStrategy(CtaTemplate): """""" author = "用Python的交易员" fixed_size = 1 k1 = 0.4 k2 = 0.6 bars = [] day_open = 0 day_high = 0 day_low = 0 range = 0 long_entry = 0 short_entry = 0 exit_time = time(hour=14, minute=55) long_entered = False short_entered = False parameters = ["k1", "k2", "fixed_size"] variables = ["range", "long_entry", "short_entry", "exit_time"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(DualThrustStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() self.bars = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def 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.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] if last_bar.datetime.date() != bar.datetime.date(): if self.day_high: self.range = self.day_high - self.day_low self.long_entry = bar.open_price + self.k1 * self.range self.short_entry = bar.open_price - self.k2 * self.range self.day_open = bar.open_price self.day_high = bar.high_price self.day_low = bar.low_price self.long_entered = False self.short_entered = False else: self.day_high = max(self.day_high, bar.high_price) self.day_low = min(self.day_low, bar.low_price) if not self.range: return if bar.datetime.time() < self.exit_time: if self.pos == 0: if bar.close_price > self.day_open: if not self.long_entered: self.buy(self.long_entry, self.fixed_size, stop=True) else: if not self.short_entered: self.short(self.short_entry, self.fixed_size, stop=True) elif self.pos > 0: self.long_entered = True self.sell(self.short_entry, self.fixed_size, stop=True) if not self.short_entered: self.short(self.short_entry, self.fixed_size, stop=True) elif self.pos < 0: self.short_entered = True self.cover(self.long_entry, self.fixed_size, stop=True) if not self.long_entered: self.buy(self.long_entry, self.fixed_size, stop=True) else: if self.pos > 0: self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.cover(bar.close_price * 1.01, abs(self.pos)) self.put_event() def on_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 CincoStrategy(CtaTemplate): """""" author = "用Python的交易员" boll_window = 51 boll_dev = 2.5 atr_window = 4 risk_level = 200 trailing_short = 0.8 trailing_long = 0.5 boll_up = 0 boll_down = 0 rsi_buy = 0 rsi_sell = 0 atr_value = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 interval = 15 parameters = [ "boll_window", "boll_dev", "risk_level", "atr_window", "interval", "trailing_short", "trailing_long" ] variables = [ "boll_up", "boll_down", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(CincoStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.interval, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev) boll_width = self.boll_up - self.boll_down if self.pos == 0: atr_fix = am.atr(self.atr_window) self.trading_size = int(self.risk_level / atr_fix) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.buy(self.boll_up, self.trading_size, True) self.short(self.boll_down, self.trading_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_stop = (self.intra_trade_high - self.trailing_long * boll_width) 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.trailing_short * boll_width) 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. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class KingKeltnerStrategy(CtaTemplate): """""" author = '用Python的交易员' kk_length = 11 kk_dev = 1.6 trailing_percent = 0.8 fixed_size = 1 kk_up = 0 kk_down = 0 intra_trade_high = 0 intra_trade_low = 0 long_vt_orderids = [] short_vt_orderids = [] vt_orderids = [] parameters = ['kk_length', 'kk_dev', 'fixed_size'] variables = ['kk_up', 'kk_down'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(KingKeltnerStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" for orderid in self.vt_orderids: self.cancel_order(orderid) self.vt_orderids.clear() am = self.am am.update_bar(bar) if not am.inited: return self.kk_up, self.kk_down = am.keltner(self.kk_length, self.kk_dev) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.send_oco_order(self.kk_up, self.kk_down, self.fixed_size) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price vt_orderid = self.sell(self.intra_trade_high * (1 - self.trailing_percent / 100), abs(self.pos), True) self.vt_orderids.append(vt_orderid) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) vt_orderid = self.cover(self.intra_trade_low * (1 + self.trailing_percent / 100), abs(self.pos), True) self.vt_orderids.append(vt_orderid) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if self.pos != 0: if self.pos > 0: for short_orderid in self.short_vt_orderids: self.cancel_order(short_orderid) elif self.pos < 0: for buy_orderid in self.long_vt_orderids: self.cancel_order(buy_orderid) for orderid in (self.long_vt_orderids + self.short_vt_orderids): if orderid in self.vt_orderids: self.vt_orderids.remove(orderid) self.put_event() def send_oco_order(self, buy_price, short_price, volume): """""" self.long_vt_orderids = self.buy(buy_price, volume, True) self.short_vt_orderids = self.short(short_price, volume, True) self.vt_orderids.extend(self.long_vt_orderids) self.vt_orderids.extend(self.short_vt_orderids) def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class DemoStrategy0(CtaTemplate): """""" author = "用Python的交易员" dc_length = 11 trailing_percent = 0.8 fixed_size = 1 dc_up = 0 dc_down = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = ["dc_length", "trailing_percent", "fixed_size"] variables = ["dc_up", "dc_down"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" # 全撤 self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算指标 self.dc_up, self.dc_down = am.donchian(self.dc_length) # 检查信号 if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.buy(self.dc_up, self.fixed_size, True) self.short(self.dc_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_stop = self.intra_trade_high * (1 - self.trailing_percent / 100) if bar.low_price <= long_stop: self.sell(bar.close_price - 10, abs(self.pos)) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_stop = self.intra_trade_low * (1 + self.trailing_percent / 100) if bar.high_price >= short_stop: self.cover(bar.close_price + 10, abs(self.pos)) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class MultiTimeframeStrategy(CtaTemplate): """""" author = '用Python的交易员' rsi_signal = 20 rsi_window = 14 fast_window = 5 slow_window = 20 fixed_size = 1 rsi_value = 0 rsi_long = 0 rsi_short = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 parameters = ['rsi_signal', 'rsi_window', 'fast_window', 'slow_window', 'fixed_size'] variables = ['rsi_value', 'rsi_long', 'rsi_short', 'fast_ma', 'slow_ma', 'ma_trend'] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(MultiTimeframeStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.rsi_long = 50 + self.rsi_signal self.rsi_short = 50 - self.rsi_signal self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am15 = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return if not self.ma_trend: return self.rsi_value = self.am5.rsi(self.rsi_window) if self.pos == 0: if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy(bar.close_price + 5, self.fixed_size) elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(bar.close_price - 5, self.fixed_size) elif self.pos > 0: if self.ma_trend < 0 or self.rsi_value < 50: self.sell(bar.close_price - 5, abs(self.pos)) elif self.pos < 0: if self.ma_trend > 0 or self.rsi_value > 50: self.cover(bar.close_price + 5, abs(self.pos)) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if not self.am15.inited: return self.fast_ma = self.am15.sma(self.fast_window) self.slow_ma = self.am15.sma(self.slow_window) if self.fast_ma > self.slow_ma: self.ma_trend = 1 else: self.ma_trend = -1 def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class DoubleMaStrategy(CtaTemplate): author = "用Python的交易员" fast_window = 10 slow_window = 20 fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 parameters = ["fast_window", "slow_window"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(DoubleMaStrategy, 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(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. """ am = self.am am.update_bar(bar) if not am.inited: return fast_ma = am.sma(self.fast_window, array=True) self.fast_ma0 = fast_ma[-1] self.fast_ma1 = fast_ma[-2] slow_ma = am.sma(self.slow_window, array=True) self.slow_ma0 = slow_ma[-1] self.slow_ma1 = slow_ma[-2] cross_over = self.fast_ma0 > self.slow_ma0 and self.fast_ma1 < self.slow_ma1 cross_below = self.fast_ma0 < self.slow_ma0 and self.fast_ma1 > self.slow_ma1 if cross_over: if self.pos == 0: self.buy(bar.close_price, 1) elif self.pos < 0: self.cover(bar.close_price, 1) self.buy(bar.close_price, 1) elif cross_below: if self.pos == 0: self.short(bar.close_price, 1) elif self.pos > 0: self.sell(bar.close_price, 1) self.short(bar.close_price, 1) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass