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 __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 __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 __init__(self, rsi_window: int, rsi_level: float): """Constructor""" super(RsiSignal, self).__init__() self.rsi_window = rsi_window self.rsi_level = rsi_level self.rsi_long = 50 + self.rsi_level self.rsi_short = 50 - self.rsi_level self.bg = BarGenerator(self.on_bar) self.am = ArrayManager()
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()
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 MarketStationary(CtaTemplate): """""" author = "" stationary_threshold = 4 / 1000 market_open_time = time(hour=9, minute=30) start_record_time_m = time(hour=9, minute=30) start_trade_time_m = time(hour=10, minute=20) exit_time_m = time(hour=11, minute=30) start_trade_time_a = time(hour=13, minute=33) exit_time_a = time(hour=14, minute=55) fixed_size = 1 pct_array_m = [] pct_array_a = [] open_price = 0 draw_back_mean_m = 0 draw_back_inverse_mean_m = 0 draw_back_inverse_mean_a = 0 stationary_value_m = 0 draw_back_mean_a = 0 draw_back_inverse_a = 0 stationary_value_m = 0 stationary_value_a = 0 exit_loss = 5 / 1000 bar_num = 0 long_order_record_m = [] short_order_record_m = [] long_order_record_a = [] short_order_record_a = [] trend_bool_m = False trend_bool_a = False first_time_m = True first_time_a = True parameters = ['stationary_threshold'] variables = ['stationary_value_m', 'stationary_value_a', 'trend_bool'] 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=300) self.long_order_record_m = [] self.short_order_record_m = [] self.long_order_record_a = [] self.short_order_record_a = [] self.pct_array_m = [] self.pct_array_a = [] 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.am.update_bar(bar) if not self.am.inited: return am = self.am if bar.datetime.time() == self.market_open_time: self.open_price = bar.close_price if bar.datetime.time() == self.start_trade_time_m: self.bar_num = 0 elif bar.datetime.time() < self.start_trade_time_a: self.bar_num += 1 elif bar.datetime.time() >= self.exit_time_a: self.bar_num = 0 if self.open_price > 0: if bar.datetime.time() == self.start_trade_time_m: price_array = am.close[-self.bar_num:] draw_back_record = [] draw_back_inverse_record = [] for ind in range(self.bar_num): if ind < self.bar_num-1: self.pct_array_m = (price_array-price_array[ind])/price_array[ind] print(self.pct_array_m) draw_back = max(self.pct_array_m[ind+1:]) draw_back_inverse = -min(self.pct_array_m[ind+1:]) draw_back_record.append(draw_back) draw_back_inverse_record.append(draw_back_inverse) self.draw_back_mean_m = np.mean(draw_back_record) self.draw_back_inverse_mean_m = np.mean(draw_back_inverse_record) self.stationary_value_m = np.min([self.draw_back_mean_m, self.draw_back_inverse_mean_m]) if self.stationary_value_m < self.stationary_threshold: self.trend_bool_m = True elif bar.datetime.time() < self.exit_time_m: if self.trend_bool_m: if self.pos == 0 and self.first_time_m: if bar.close_price > self.open_price: self.buy(bar.close_price + 5, self.fixed_size) self.long_order_record_m.append(bar.close_price + 5) elif bar.close_price < self.open_price: self.short(bar.close_price - 5, self.fixed_size) self.short_order_record_m.append(bar.close_price - 5) elif self.pos > 0: self.first_time_m = False buy_order_price = self.long_order_record_m[-1] if bar.close_price <= buy_order_price * (1 - self.exit_loss): self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.first_time_m = False sell_order_price = self.short_order_record_m[-1] if bar.close_price >= sell_order_price * (1 + self.exit_loss): self.cover(bar.close_price * 1.01, abs(self.pos)) elif self.exit_time_m <= bar.datetime.time() < self.start_trade_time_a: 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.trend_bool_m = False self.first_time_m = True elif bar.datetime.time() == self.start_trade_time_a: price_array = am.close[-self.bar_num:] draw_back_record = [] draw_back_inverse_record = [] for ind in range(self.bar_num): if ind < self.bar_num-1: self.pct_array_a = (price_array-price_array[ind])/price_array[ind] draw_back = max(self.pct_array_a[ind+1:]) draw_back_inverse = -min(self.pct_array_a[ind+1:]) draw_back_record.append(draw_back) draw_back_inverse_record.append(draw_back_inverse) self.draw_back_mean_a = np.mean(draw_back_record) self.draw_back_inverse_mean_a = np.mean(draw_back_inverse_record) self.stationary_value_a = np.min([self.draw_back_mean_a, self.draw_back_inverse_mean_a]) if self.stationary_value_a < self.stationary_threshold: self.trend_bool_a = True elif self.start_trade_time_a <= bar.datetime.time() < self.exit_time_a: if self.trend_bool_a: if self.pos == 0 and self.first_time_a: if bar.close_price > self.open_price: self.buy(bar.close_price + 5, self.fixed_size) self.long_order_record_a.append(bar.close_price + 5) elif bar.close_price < self.open_price: self.short(bar.close_price - 5, self.fixed_size) self.short_order_record_a.append(bar.close_price - 5) elif self.pos > 0: self.first_time_a = False buy_order_price = self.long_order_record_a[-1] if bar.close_price <= buy_order_price * (1 - self.exit_loss): self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.first_time_a = False sell_order_price = self.short_order_record_a[-1] if bar.close_price >= sell_order_price * (1 + self.exit_loss): self.cover(bar.close_price * 1.01, abs(self.pos)) elif bar.datetime.time() >= self.exit_time_a: 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.trend_bool_a = False self.first_time_a = True self.open_price = 0 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 CincoAtrStrategy(CtaTemplate): """""" author = "tonywang_efun" fixed_size = 1 bar_window = 26 boll_window = 39 boll_dev = 1.9 rsi_window = 10 rsi_long = 74 rsi_short = 37 atr_window = 30 atr_stop_multiplier = 1.5 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 atr_value = 0 parameters = [ "fixed_size", "bar_window", "boll_window", "boll_dev", "rsi_window", "rsi_long", "rsi_short", "atr_window", "atr_stop_multiplier" ] variables = [ "boll_up", "boll_down", "rsi_value", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__( self, cta_engine, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.bar_window, self.on_xmin_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.rsi_value = self.am.rsi(self.rsi_window) self.atr_value = self.am.atr(self.atr_window) self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 if self.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.atr_value * self.atr_stop_multiplier 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.atr_value * self.atr_stop_multiplier 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 FbbStrategy(CtaTemplate): """""" author = "feng.shao" boll_window = 20 # boll_dev = 2.0 # boll_bw_limit = 0.01 fixed_size: float = 0.2 # 单笔buy 暂时固定为总资产的 千分之 1~4 (风险随之增加) limit_amt = 10.0 # 最小交易资金10 USDT -binance #BB boll_up = 0 boll_down = 0 boll_mid = 0 boll_pb = 0 boll_bw = 0 #kdj k = 0 d = 0 j = 0 last_boll_pb = 0 parameters = [ "boll_window", "boll_dev", # "boll_dev_2", # "boll_pb_sal", "boll_bw_limit", "fixed_size" ] variables = [ # "boll_up", # "boll_down", # "boll_mid", "boll_pb", # "boll_bw", # "boll_up_2", # "boll_down_2", # "boll_mid_2", # "boll_pb_2", # "boll_bw_2", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_mins_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(2) 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_mins_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 # start self.get_boll(bar) self.get_kdj() print( str(self.k) + " - " + str(self.d) + " - " + str(self.j) + " - " + bar.datetime.strftime("%Y-%m-%d %H:%M:%S")) # 低于 boll_down 并且width 不小于limit 买入 if self.boll_pb <= 0 and self.boll_bw > self.boll_bw_limit: self.buy(bar.close_price, self.check_minimum_size(bar.close_price, self.fixed_size), False) if self.pos > 0: # 上穿 up 卖出信号 if self.last_boll_pb < 1 <= self.boll_pb and self.boll_bw < self.boll_bw_limit: self.sell(bar.close_price, self.pos, False) # 未达up 而下穿 mid 卖出 if self.last_boll_pb > 0.5 >= self.boll_pb and self.boll_bw < self.boll_bw_limit: self.sell(bar.close_price, self.pos, False) # down 下方 ,width 很小 卖出 if self.boll_pb <= 0 and self.boll_bw <= self.boll_bw_limit: self.sell(bar.close_price, self.pos, False) self.last_boll_pb = self.boll_pb # self.short(bar.close_price, self.fixed_size, False) # self.cover(bar.close_price, self.pos, False) self.put_event() def check_minimum_size(self, price: float, order_size) -> float: min_size = self.size_by_limit_amt(self.limit_amt, price) return max(order_size, min_size) def kdj_signal(self): if self.d <= self.k < 20: return True def get_boll(self, bar: BarData): self.boll_up, self.boll_mid, self.boll_down = self.am.boll( self.boll_window, self.boll_dev) self.boll_pb = self.percentbeta(bar.close_price, self.boll_up, self.boll_down) self.boll_bw = self.bandwidth(self.boll_up, self.boll_mid, self.boll_down) def get_kdj(self): self.k, self.d, self.j = self.am.kdj() 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 def percentbeta(self, close: float, up: float, low: float) -> float: """ %b of boll """ pb = (close - low) / (up - low) return pb def bandwidth(self, up: float, mid: float, low: float) -> float: """ bandwidth of boll """ bw = (up - low) / mid return bw def size_by_limit_amt(self, limit_amt: float, price: float) -> float: return math.ceil(limit_amt / price * 1000000) / 1000000
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()
class DoubleDayM30M1Strategy(CtaTemplate): """ 使用1m线合成 日线、30分钟、1分钟三种数据,并根据各自ma叠加进行卖卖的策略 """ author = "fsksf" window_mn = 30 # n分钟线 fast_window_day = 3 fast_window_m30 = 3 fast_window_m1 = 3 slow_window_day = 5 slow_window_m30 = 5 slow_window_m1 = 5 fast_ma_day = 0.0 fast_ma_m30 = 0.0 fast_ma_m1 = 0.0 slow_ma_day = 0.0 slow_ma_m30 = 0.0 slow_ma_m1 = 0.0 parameters = [ "fast_window_day", "fast_window_m30", "fast_window_m1", "slow_window_day", "slow_window_m30", "slow_window_m1", "window_mn" ] variables = [ "fast_ma_day", "slow_ma_day", "fast_ma_m30", "slow_ma_m30", "fast_ma_m1", "slow_ma_m1" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.day_bar_gen = BarGenerator(lambda x: None, interval=Interval.DAILY, window=1, on_window_bar=self.on_day_bar) self.m30_bar_gen = BarGenerator(self.on_bar, interval=Interval.MINUTE, window=self.window_mn, on_window_bar=self.on_m30_bar) self.day_am = ArrayManager(size=self.slow_window_day + 1) self.m30_am = ArrayManager(size=self.slow_window_m30 + 1) self.m1_am = ArrayManager(size=self.slow_window_m1 + 1) def on_m30_bar(self, bar): self.m30_am.update_bar(bar) def on_day_bar(self, bar): print(bar.__dict__) self.day_am.update_bar(bar) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(100) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.m30_bar_gen.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ # if self.cta_engine.gateway_name == "BACKTESTING": # update window self.m30_bar_gen.update_bar(bar) self.day_bar_gen.update_bar(bar) self.m1_am.update_bar(bar) if not (self.day_am.inited and self.m30_am.inited and self.m1_am.inited): return # 最后一个bar实时更新的,计算ma后删除 # self.day_am.update_bar(self.day_bar_gen.last_bar) fast_ma_day = self.day_am.sma(self.fast_window_day, array=True) slow_ma_day = self.day_am.sma(self.slow_window_day, array=True) # self.m30_am.update_bar(self.m30_bar_gen.last_bar) fast_ma_m30 = self.m30_am.sma(self.fast_window_m30, array=True) slow_ma_m30 = self.m30_am.sma(self.slow_window_m30, array=True) fast_ma_m1 = self.m1_am.sma(self.fast_window_m1, array=True) slow_ma_m1 = self.m1_am.sma(self.slow_window_m1, array=True) self.fast_ma_day = fast_ma_day[-1] self.fast_ma_m30 = fast_ma_m30[-1] self.fast_ma_m1 = fast_ma_m1[-1] self.slow_ma_day = slow_ma_day[-1] self.slow_ma_m30 = slow_ma_m30[-1] self.slow_ma_m1 = slow_ma_m1[-1] cross_over = fast_ma_day[-2] < slow_ma_day[-2] and fast_ma_day[-1] > slow_ma_day[-1] and \ fast_ma_m30[-2] < slow_ma_m30[-2] and fast_ma_m30[-1] > slow_ma_m30[-1] and \ fast_ma_m1[-2] < slow_ma_m1[-2] and fast_ma_m1[-1] > slow_ma_m1[-1] cross_below = fast_ma_day[-2] > slow_ma_day[-2] and fast_ma_day[-1] < slow_ma_day[-1] and \ fast_ma_m30[-2] > slow_ma_m30[-2] and fast_ma_m30[-1] < slow_ma_m30[-1] and \ fast_ma_m1[-2] > slow_ma_m1[-2] and fast_ma_m1[-1] < slow_ma_m1[-1] if cross_over: self.write_log(f'触发买入:{str(bar.datetime)}') # print(f'触发买入:{str(bar.datetime)}') self.write_log( f'day: ma_fast: {fast_ma_day[-2:]}, slow: {slow_ma_day[-2:]} close_price: {self.day_am.close_array}' ) self.write_log( f'30m: ma_fast: {fast_ma_m30[-2:]}, slow: {slow_ma_m30[-2:]} close_price: {self.m30_am.close_array}' ) self.write_log( f'1m: ma_fast: {fast_ma_m1[-2:]}, slow: {slow_ma_m1[-2:]} close_price: {self.m1_am.close_array}' ) 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.day_am.remove_last_bar() # self.m30_am.remove_last_bar() 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 CuatroStrategy(CtaTemplate): """""" author = "vn_trader" boll_window = 20 boll_dev = 1.8 rsi_window = 14 rsi_signal = 19 fast_window = 4 slow_window = 26 trailing_long = 0.5 trailing_short = 0.3 fixed_size = 1 boll_up = 0 boll_down = 0 rsi_value = 0 rsi_long = 0 rsi_short = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 parameters = [ "boll_window", "boll_dev", "rsi_window", "rsi_signal", "fast_window", "slow_window", "trailing_long", "trailing_short", "fixed_size" ] variables = [ "boll_up", "boll_down", "rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__( self, cta_engine, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.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.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am5 = ArrayManager() 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 or not self.am15.inited: return self.boll_up, self.boll_down = self.am5.boll(self.boll_window, self.boll_dev) self.rsi_value = self.am5.rsi(self.rsi_window) boll_width = self.boll_up - self.boll_down # No position if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy(self.boll_up, self.fixed_size, stop=True) if self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(self.boll_down, self.fixed_size, stop=True) # Long position 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) # Short position 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, abs(self.pos), stop=True) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if 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 elif self.fast_ma < self.slow_ma: self.ma_trend = -1 else: self.ma_trend = 0 self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class BollVix(CtaTemplate): """""" author = "yunya" open_window = 15 boll_length = 530 fixed_size = 1 boll_mid_current = 0 boll_mid_last = 0 boll_up_current = 0 boll_up_last = 0 boll_down_current = 0 boll_down_last = 0 target_pos = 0 pos_inited = 0 boll_mid = 0 # 画图专用 time_list = [] open_list = [] high_list = [] low_list = [] close_list = [] volume_list = [] up_list = [] down_list = [] mid_list = [] mid_new_list = [] bias_value_list = [] bias_list = [] singnal_plot = [] singnal_list = None singnal = None plot_echarts = {} parameters = [ "open_window", "boll_length", "fixed_size", ] variables = [ "boll_mid_current", "boll_mid_last", "boll_up_current", "boll_up_last", "boll_down_current", "boll_down_last", "pos_inited", "target_pos" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_minute_bar, interval=Interval.MINUTE) self.am = ArrayManager(self.boll_length * 2) self.up_array: np.ndarray = np.zeros(5) self.down_array: np.ndarray = np.zeros(5) self.boll_inited = False self.boll_count = 0 self.engine_type = self.get_engine_type() self.vt_orderids = [] self.order_price = 0 self.pos_inited = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(12) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) # 只有实盘交易才使用BestLimit算法 if self.engine_type != EngineType.LIVE: return # 当前没有仓位 order_volume_open = self.target_pos - self.pos if not order_volume_open: return if order_volume_open > 0: if not self.vt_orderids: self.order_price = tick.bid_price_1 vt_orderids = self.buy(self.order_price, abs(order_volume_open)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.bid_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) elif order_volume_open < 0: if not self.vt_orderids: self.order_price = tick.ask_price_1 vt_orderids = self.short(self.order_price, abs(order_volume_open)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.ask_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_minute_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算布林 sma_array = self.am.sma(self.boll_length, True) std_array = self.am.std(self.boll_length, True) dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_length:].max() up = sma_array + std_array * dev_max down = sma_array - std_array * dev_max boll_mid_array = self.am.sma(self.boll_length, True) # 计算数组 self.boll_mid = boll_mid_array[-2] self.boll_up_current = up[-1] self.boll_up_last = up[-2] self.boll_down_current = down[-1] self.boll_down_last = down[-2] if not self.pos: self.pos_inited = 0 if self.am.close[-1] > self.boll_up_current and self.am.close[ -2] <= self.boll_up_last: if self.engine_type == EngineType.BACKTESTING: self.buy(bar.close_price, self.fixed_size) else: self.target_pos = self.fixed_size print("没有仓位,我开多") elif self.am.close[-1] < self.boll_down_current and self.am.close[ -2] >= self.boll_down_last: if self.engine_type == EngineType.BACKTESTING: self.short(bar.close_price, self.fixed_size) else: self.target_pos = -self.fixed_size print("没有仓位,我开空") elif self.pos > 0: self.sell(self.boll_mid, abs(self.pos), True) elif self.pos < 0: self.cover(self.boll_mid, abs(self.pos), True) # 画图专用 if self.singnal != self.singnal_list: plot = self.singnal else: plot = None self.time_list.append(bar.datetime) self.open_list.append(bar.open_price) self.high_list.append(bar.high_price) self.low_list.append(bar.low_price) self.close_list.append(bar.close_price) self.volume_list.append(bar.volume) self.up_list.append(self.boll_up_current) self.down_list.append(self.boll_down_current) self.mid_list.append(self.boll_mid) self.singnal_plot.append(plot) self.plot_echarts = { "datetime": self.time_list, "open": self.open_list, "high": self.high_list, "low": self.low_list, "close": self.close_list, "volume": self.low_list, "boll_up": self.up_list, "boll_down": self.down_list, "boll_mid": self.mid_list, "signal": self.singnal_plot } self.singnal_list = self.singnal self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction.value == Direction.LONG.value: if trade.offset.value == Offset.OPEN.value: self.singnal = 1 elif trade.offset.value == Offset.CLOSE.value: self.singnal = 0 else: self.singnal = None elif trade.direction.value == Direction.SHORT.value: if trade.offset.value == Offset.OPEN.value: self.singnal = -1 elif trade.offset.value == Offset.CLOSE.value: self.singnal = 0 else: self.singnal = None def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def boll_calculate(self): """ 计算布林 :return: """ if not self.boll_inited: self.boll_count += 1 if self.boll_count >= 6: self.boll_inited = True self.up_array[:-1] = self.up_array[1:] self.down_array[:-1] = self.down_array[1:] sma_array = self.am.sma(self.boll_length, True) std_array = self.am.std(self.boll_length, True) dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_length:].max() up = sma_array[-1] + std_array[-1] * dev_max down = sma_array[-1] - std_array[-1] * dev_max self.up_array[-1] = up self.down_array[-1] = down
class DudlThrust_NewStrategy(CtaTemplate): """""" author = "yunyu" window_min = 15 rolling_period = 70 upper_open = 0.5 lower_open = 0.6 stop_multiplier = 1.8 dc_length = 30 cci_length = 10 cci_stop = 20 trailing_tax = 1.8 fixed_size = 1 up = 0 down = 0 exit_shour = 0 exit_long = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 long_entry = 0 short_entry = 0 long_out = 0 short_out = 0 cci_value = 0 ask = 0 bid = 0 parameters = [ "window_min", "rolling_period", "upper_open", "lower_open", "stop_multiplier", "dc_length", "cci_length", "cci_stop", "trailing_tax", "fixed_size", ] variables = [ "up", "down", "exit_shour", "exit_long", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "long_entry", "short_entry", "long_out", "short_out", "cci_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(on_bar=self.on_bar) self.am = ArrayManager( (max(self.dc_length, self.rolling_period) + 10) * 60) self.bg_xmin = BarGenerator(on_bar=self.on_bar, window=self.window_min, on_window_bar=self.on_xmin_bar) self.am_xmin = ArrayManager( max(self.dc_length, self.rolling_period) + 10) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xmin.update_bar(bar) self.cancel_all() self.exit_shour, self.exit_long = self.am.donchian(self.dc_length * 60) if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.cci_value > self.cci_stop: self.buy(self.up, self.fixed_size, True) elif self.cci_value < -self.cci_stop: self.short(self.down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.long_out = self.intra_trade_high * (1 - self.trailing_tax / 100) self.long_stop = max(self.long_entry, self.long_out, self.exit_long) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_out = self.intra_trade_low * (1 + self.trailing_tax / 100) self.short_stop = min(self.short_entry, self.short_out, self.exit_shour) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xmin_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am_xmin.update_bar(bar) if not self.am_xmin.inited: return self.up, self.down = self.dualthrust(self.am_xmin.high, self.am_xmin.low, self.am_xmin.close, self.am_xmin.open, self.rolling_period, self.upper_open, self.lower_open) self.cci_value = self.am_xmin.cci(self.cci_length) self.atr_value = self.am.atr(16) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: long_price = trade.price self.long_entry = long_price - self.stop_multiplier * self.atr_value else: short_price = trade.price self.short_entry = short_price + self.stop_multiplier * self.atr_value self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass # self.put_event() def market_order(self): """""" pass # self.buy(self.last_tick.limit_up, 1) # self.write_log("执行市价单测试") def limit_order(self): """""" pass # self.buy(self.last_tick.limit_down, 1) # self.write_log("执行限价单测试") def stop_order(self): """""" pass # self.buy(self.last_tick.ask_price_1, 1, True) # self.write_log("执行停止单测试") def dualthrust(self, high, low, close, open, n, k1, k2): """ :param high: :param low: :param close: :return: """ #计算N日最高价的最高价,收盘价的最高价、最低价,最低价的最低价 hh = high[-n:-1].max() lc = close[-n:-1].min() hc = close[-n:-1].max() ll = low[-n:-1].max() #计算range,上下轨的距离前一根K线开盘价的距离 range = max(hh - lc, hc - ll) up = open[-2] + k1 * range down = open[-2] - k2 * range return up, down
class CincoStrategy(CtaTemplate): """""" author = "vnpy" boll_window = 42 boll_dev = 2.2 trailing_long = 0.65 trailing_short = 0.65 atr_window = 4 risk_level = 300 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: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.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_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
def __init__(self, strategy, KCircle=1): """Constructor""" super(TripleMaCrossSignal, self).__init__(strategy) self.bg = BarGenerator(self.onBar, KCircle, self.onXminBar) self.am = ArrayManager(size=100)
class TripleMaSignal(CtaSignalPatch): """TripleMaSignal""" # 策略参数 # 三均线长度设置 maWindow1 = 10 maWindow2 = 30 maWindow3 = 90 # ma最新值 ma1 = 0 ma2 = 0 ma3 = 0 #---------------------------------------------------------------------- def __init__(self, strategy, KCircle=1): """Constructor""" super(TripleMaSignal, self).__init__(strategy) self.bg = BarGenerator(self.onBar, KCircle, self.onXminBar) self.am = ArrayManager(size=100) #---------------------------------------------------------------------- def onBar(self, bar): """K线更新""" self.bg.update_bar(bar) #---------------------------------------------------------------------- def onXminBar(self, bar=BarData): """X Min Bar""" # 保存K线数据 am = self.am am.update_bar(bar) if not am.inited: self.set_signal_pos(0) return if self.trading: self.updateSignal() #---------------------------------------------------------------------- def updateSignal(self): """X Min Bar""" self.set_signal_pos(self.getSignal()) pass #---------------------------------------------------------------------- def getSignal(self): """生成信号""" ma1Array = self.am.sma(self.maWindow1, True) self.ma10 = ma1Array[-2] self.ma1 = ma1Array[-1] self.ma2 = self.am.sma(self.maWindow2, False) self.ma3 = self.am.sma(self.maWindow3, False) # 开多,上穿 if self.ma1 > self.ma2 > self.ma3: return 1 # 开空,下穿 elif self.ma1 < self.ma2 < self.ma3: return -1 return 0
class EmaStrategy(CtaTemplate): author = "CHENG LI" trade_money = 1000000 fixed_size = 1 bars = [] # exit_time = time(hour=14, minute=55) # for EMA algorithm fast_window = 12 slow_window = 48 fast_ema0 = 0.0 fast_ema1 = 0.0 slow_ema0 = 0.0 slow_ema1 = 0.0 # 菲阿里四价:昨日高点、昨日低点、昨天收盘、今天开盘 yesterday_high = 0.0 yesterday_low = 0.0 yesterday_close = 0.0 today_open = 0.0 short_stop_loss = 0.0 long_stop_loss = 0.0 parameters = ["fast_window", "slow_window", "trade_money"] variables = [ "fast_ema0", "fast_ema1", "slow_ema0", "slow_ema1", "yesterday_high", "yesterday_low", "yesterday_close", "today_open", "short_stop_loss", "long_stop_loss" ] def __init__(self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict): super(EmaStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_hour = BarGenerator(self.on_bar, window=1, on_window_bar=self.on_hour_bar, interval=Interval.HOUR) self.bg_day = BarGenerator(self.on_bar, window=24, on_window_bar=self.on_day_bar, interval=Interval.HOUR) self.am_hour = ArrayManager(100) self.am_day = ArrayManager(2) self.bars = [] def on_init(self): print("on init") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ print("on_start strategy") def on_tick(self, tick: TickData): self.bg_hour.update_tick(tick) self.bg_day.update_tick(tick) def on_bar(self, bar: BarData): self.bg_hour.update_bar(bar) self.bg_day.update_bar(bar) def on_day_bar(self, bar: BarData): """ 菲阿里四价算法实现 """ # bar 初始化 self.cancel_all() am = self.am_day am.update_bar(bar) if not am.inited: self.bars.append(bar) return self.bars.append(bar) if len(self.bars) <= 2: return else: self.bars.pop(0) last_bar = self.bars[-2] # compute 4 different prices from data self.yesterday_high = last_bar.high_price self.yesterday_low = last_bar.low_price self.yesterday_close = last_bar.close_price self.today_open = bar.open_price # 设置多头止损 if self.today_open / self.yesterday_high > 1.005: # 如果当天开盘价大于昨天最高价 self.long_stop_loss = self.yesterday_high elif self.today_open / self.yesterday_high < 0.995: # 如果当天开盘价小于昨天最高价 self.long_stop_loss = self.today_open else: # 如果当天开盘价接近于昨天最高价 self.long_stop_loss = (self.yesterday_high + self.yesterday_low) / 2 # 设置多头止损为昨天中间价 # 设置空头止损 if self.today_open / self.yesterday_low < 0.995: # 如果当天开盘价小于昨天最低价 self.short_stop_loss = self.yesterday_low elif self.today_open / self.yesterday_low > 1.005: # 如果当天开盘价大于昨天最低价 self.short_stop_loss = self.today_open else: # 如果当天开盘价接近于昨天最低价 self.short_stop_loss = (self.yesterday_high + self.yesterday_low) / 2 self.put_event() def on_hour_bar(self, bar: BarData): # 确保day bar初始化 self.am_hour.update_bar(bar) if not self.am_hour.inited: return self.am_day.update_bar(bar) if not self.am_day.inited: return # compute exp. moving average fast_ema = self.am_hour.ema(self.fast_window, array=True) self.fast_ema0 = fast_ema[-1] # at T self.fast_ema1 = fast_ema[-2] # at T-1 slow_ema = self.am_hour.ema(self.slow_window, array=True) self.slow_ema0 = slow_ema[-1] self.slow_ema1 = slow_ema[-2] # identify trend: 1:bullish, -1:bearish, 0:sideways if self.fast_ema0 > self.slow_ema0 and self.fast_ema1 < self.slow_ema1: trend_status = 1 elif self.fast_ema0 < self.slow_ema0 and self.fast_ema1 > self.slow_ema1: trend_status = -1 else: trend_status = 0 self.fixed_size = 0.1 * self.trade_money / bar.close_price # if bar.datetime.time() < self.exit_time: if self.pos == 0: # 没有仓位 if trend_status == 1: if bar.close_price > self.yesterday_high: self.buy(bar.close_price * 1.005, self.fixed_size) # 做多 elif trend_status == -1: if bar.close_price < self.yesterday_low: self.short(bar.close_price * 0.995, self.fixed_size) # 做空 elif self.pos > 0: # 有多头仓位 if bar.close_price < self.long_stop_loss: # 如果当前价格小于多头止损线 if trend_status == -1: self.sell(bar.close_price * 0.995, abs(self.pos)) # 先平多头仓位,再反手开空 self.short(bar.close_price * 0.995, self.fixed_size) # 做空 else: self.sell(bar.close_price * 0.995, abs(self.pos)) # 止 else: # 继续做多 if trend_status == 1: if bar.close_price > self.yesterday_high: self.buy(bar.close_price * 1.005, self.fixed_size) # 做多 elif self.pos < 0: # 有空头的仓位 if bar.close_price > self.short_stop_loss: # 如果当前价格大于空头止损线 if trend_status == 1: self.cover(bar.close_price * 1.005, abs(self.pos)) # 先平空头仓位, 然后反手开多 self.buy(bar.close_price * 1.005, self.fixed_size) # 做多按照开仓的资金来计算 else: self.cover(bar.close_price * 1.005, abs(self.pos)) else: # 继续做空 if trend_status == -1: if bar.close_price < self.yesterday_low: self.short(bar.close_price * 0.995, self.fixed_size) self.put_event() def on_trade(self, trade: TradeData): pass def on_order(self, order: OrderData): pass def on_stop_order(self, stop_order: StopOrder): pass
class RsiAdaptStrategy(CtaTemplate): """ 策略逻辑: 一、、过虑信号 (小时周期) 使用rsiboll来判断信号强弱 二、开单信号 (分钟周期) 1、使用布林上下轨作为开单条件 三、止损 使用动态布林中轨止损 """ author = "yunya" min_window = 45 open_window = 15 rsi_length = 23 kk_length = 80 kk_dev = 2.0 trading_size = 1 atr_length = 30 rsi_entry = 0 kk_up = 0 kk_down = 0 long_stop = 0 short_stop = 0 rsi_value = 0 rsi_up = 0 rsi_dow = 0 ema_mid = 0 ema_length_new = 0 current_ema_mid = 0 last_ema_mid = 0 current_close = 0 last_close = 0 front_close = 0 exit_long = 0 exit_short = 0 long_entry = 0 short_entry = 0 long_stop_trade = 0 short_stop_drade = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 atr_value = 0 parameters = [ "open_window", "min_window", "rsi_length", "kk_length", "kk_dev", "trading_size", "atr_length", ] variables = [ "rsi_entry", "long_stop", "short_stop", "rsi_value", "rsi_up", "rsi_dow", "ema_mid", "ema_length_new", "current_ema_mid", "last_ema_mid", "current_close", "last_close", "front_close", "exit_long", "exit_short", "long_entry", "short_entry", "long_stop_trade", "short_stop_drade", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_xminute = NewBarGenerator(on_bar=self.on_bar, window=self.min_window, on_window_bar=self.on_xminute_bar) self.am_xminute = ArrayManager(self.kk_length * 2 + 10) self.bg_open = NewBarGenerator(on_bar=self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar) self.am_open = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(30) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动。。") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止。。") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_open.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_5min_bar(self, bar: BarData): """ :param bar: :type bar: :return: :rtype: """ self.cancel_all() self.am_open.update_bar(bar) if not self.am_open.inited or not self.am_xminute.inited: return ema_mid_array = self.am_open.ema(self.kk_length, True) atr = self.am_open.atr(self.kk_length, True) kk_up_array = ema_mid_array + atr * self.kk_dev kk_down_array = ema_mid_array - atr * self.kk_dev self.ema_mid = ema_mid_array[-1] self.kk_up = kk_up_array[-1] self.kk_down = kk_down_array[-1] self.current_close = self.am_open.close[-1] self.last_close = self.am_open.close[-2] self.front_close = self.am_open.close[-3] if not self.pos: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.ema_length_new = self.kk_length self.atr_value = self.am_open.atr(self.atr_length) if self.rsi_entry > 0: self.buy(self.kk_up, self.trading_size, True) self.write_log( f"下多单:{bar.datetime}, {self.kk_up}, {self.trading_size}") elif self.rsi_entry < 0: self.short(self.kk_down, self.trading_size, True) self.write_log( f"下多单:{bar.datetime}, {self.kk_down}, {self.trading_size}") elif self.pos > 0: close_long = self.current_close > self.last_close > self.front_close if close_long: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) ema_mid_new = self.am_xminute.sma(self.ema_length_new, True) self.current_ema_mid = ema_mid_new[-1] self.last_ema_mid = ema_mid_new[-2] # 仓位是long 时,如果价格下穿新布林中轨 con1 = bar.close_price < self.current_ema_mid con2 = bar.close_price >= self.last_ema_mid if con1 and con2: self.exit_long_nex = bar.close_price # 保存当前收盘价 if self.exit_long_last == 0 or self.exit_long_nex > self.exit_long_last: self.exit_long_last = self.exit_long_nex self.ema_length_new = self.kk_length # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.ema_mid else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if bar.close_price > ( (self.ema_mid + self.current_ema_mid) / 2): self.exit_long = bar.close_price elif bar.close_price < self.ema_mid: self.exit_long = bar.close_price else: self.exit_long = self.ema_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.ema_mid self.long_stop = max(self.exit_long, self.long_stop_trade) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: close_short = self.current_close < self.last_close < self.front_close if close_short: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) ema_mid_new = self.am_xminute.sma(self.ema_length_new, True) self.current_ema_mid = ema_mid_new[-1] self.last_ema_mid = ema_mid_new[-2] # 仓位是short 时,如果价格上穿新布林中轨 con1 = bar.close_price > self.current_ema_mid con2 = bar.close_price <= self.last_ema_mid if con1 and con2: self.exit_short_nex = bar.close_price if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last: self.exit_short_last = self.exit_short_nex self.ema_length_new = self.kk_length self.exit_short = self.ema_mid else: if bar.close_price < (self.ema_mid + self.current_ema_mid / 2): self.exit_short = bar.close_price elif bar.close_price < self.ema_mid: self.exit_short = bar.close_price else: self.exit_short = self.ema_mid else: self.exit_short = self.ema_mid self.short_stop = min(self.exit_short, self.short_stop_drade) self.cover(self.short_stop, abs(self.pos), True) self.sync_data() self.put_event() def on_xminute_bar(self, bar: BarData): """ :param bar: :return: """ self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return ema_array = talib.EMA(self.am_xminute.close, self.rsi_length) std_array = talib.EMA(self.am_xminute.close, self.rsi_length) dev_array = abs(self.am_xminute.close[:-1] - ema_array[:-1]) / std_array[:-1] dev_max = max(dev_array[-self.rsi_length:]) rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length) rsi_up_array = rsi_array + rsi_array * dev_max rsi_dow_array = rsi_array - rsi_array * dev_max rsi_value_array = self.am_xminute.rsi(self.rsi_length, True) self.rsi_up = rsi_up_array[-1] self.rsi_dow = rsi_dow_array[-1] self.rsi_value = rsi_value_array[-1] current_rsi = rsi_value_array[-1] last_rsi = rsi_value_array[-2] current_rsi_up = rsi_up_array[-1] last_rsi_up = rsi_up_array[-2] current_rsi_down = rsi_dow_array[-1] last_rsi_down = rsi_dow_array[-2] con1 = current_rsi > current_rsi_up con2 = last_rsi <= last_rsi_up con3 = current_rsi < current_rsi_down con4 = last_rsi >= last_rsi_down if con1 > con2: self.rsi_entry = 1 elif con3 and con4: self.rsi_entry = -1 self.sync_data() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop_trade = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop_drade = self.short_entry + 2 * self.atr_value self.sync_data() def on_order(self, order: OrderData): """ 订单更新回调 Callback of new order data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event()
class GridStockCtaStrategy(CtaTemplate): """ 策略逻辑: 1、网格数量: 21 ,网格总限量资金: 3000 2、网格操作区间: 10% 3、网格跟踪指标 : 首次成交价格 4、网格上限: 网格跟踪指标 * (1 + 网格操作区间) 5、网格下限: 网格跟踪指标 * ( 1 - 网格操作区间) 6、网格步进 :( 网格上限 - 网格下限 ) / 网格数量 7、仓位单元 : 网格总限量 / 网格数量 8、网格启动、停止开关:振幅超过百分比例,网格暂时停止,等待8小时后重新启动 """ author = "yunya" open_window = 2 xminute_window = 5 xhour_window = 1 position_proportion = 1.0 # 每次加仓比例 grid_amount = 20 # 网格最大量 grid_usdt_size = 20 # 首次使用多少USDT购买币 grid_usdt_capital = 200 # 网格最多使用的资金量USDT grid_buy_price = 1.0 # 网格距离 grid_sell_price = 1.0 pay_up = 2 # 偏移pricetick buy_callback = 0.5 # 买入回调幅度 sell_callback = 0.5 # 卖出回调幅度 sleep_switch = False # 睡眠开关,默认关 grid_amplitude = 5.0 # 振幅超过比例停止策略8小时 stop_time = 8 # 策略暂停时间 price_change = 0 # 网格基准线(每次成交价) current_volume = 0 # 当前下单币的数量 target_pos = 0 buy_benchmark = 0 sell_benchmark = 0 buy_price = 0 # 买入成交价 sell_price = 0 # 平仓成交价 grid_usdt_volume = 0 cumulative_usdt_volume = 0 # 累计使用金额 grid_count = 0 # 网格次数 intra_trade_high = 0 # 最高价 trade_high = 0 intra_trade_low = 0 # 最低价 trade_low = 0 amplitude = 0 # 振幅 tick_price = 0 time_stop = 0 # 计算得到的重新启动时间 buy_fixed_size = 0 sell_fixed_size = 0 len_tick_decimal = 0 # 获取当前币种盘口最小下单量 amplitude_inited = False # 振幅标签 first_time_inited = False # 判断是否是首次启动,如果是首次启动,清空初始化数据 min_volume = 0 buy_tick = 0 short_tick = 0 parameters = [ "open_window", "xminute_window", "xhour_window", "position_proportion", "grid_amount", "grid_usdt_size", "grid_usdt_capital", "grid_buy_price", "grid_sell_price", "pay_up", "buy_callback", "sell_callback", "sleep_switch", "grid_amplitude", "stop_time", ] variables = [ "price_change", "current_volume", "buy_benchmark", "sell_benchmark", "grid_usdt_volume", "cumulative_usdt_volume", "grid_count", "amplitude", "amplitude_inited", "first_time_inited", "min_volume" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__( cta_engine, strategy_name, vt_symbol, setting, ) self.exchangematerial = ExchangeMaterial.OKEX_MATERIAL self.bg_open = BarGenerator(self.on_bar, self.open_window, self.on_open_bar) self.am_open = ArrayManager() self.bg_minute = BarGenerator(self.on_bar, self.xminute_window, self.on_mintue_bar) self.am_minute = ArrayManager() self.bg_xhour = BarGenerator(self.on_bar, self.xhour_window, self.on_xhour_bar, Interval.HOUR) self.am_xhour = ArrayManager() # 计算每次使用资金量 self.cumulative_usdt_volume = 0 self.target_pos = 0 self.grid_usdt_volume = 0 self.amplitude = 0 self.tick_price = 0 self.engine_type = self.get_engine_type() # 测试还是实盘 self.vt_orderids = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") contract = self.cta_engine.main_engine.get_contract(self.vt_symbol) self.min_volume = contract.min_volume self.len_tick_decimal = len(str(self.min_volume).split(".")[1]) self.load_bar(1) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") if not self.first_time_inited: self.grid_count = 0 self.current_volume = 0 self.cumulative_usdt_volume = 0 self.first_time_inited = True self.amplitude_inited = False def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_open.update_tick(tick) self.buy_tick = tick.bid_price_1 self.short_tick = tick.ask_price_1 def on_bar(self, bar: BarData): """""" self.bg_open.update_bar(bar) self.bg_minute.update_bar(bar) self.bg_xhour.update_bar(bar) def on_open_bar(self, bar: BarData): """""" self.am_open.update_bar(bar) if not self.am_open.inited: return self.cancel_all() # 判断 休眠时间 if self.amplitude_inited: if bar.datetime > self.time_stop: self.amplitude_inited = False return # 根据网格次数加仓 , 根据USDT量和价格计算出可购买的币数量 if self.position_proportion > 0 and self.grid_count > 0: self.grid_usdt_volume = self.grid_usdt_size * ( 1 + (self.position_proportion / 100) * self.grid_count) else: self.grid_usdt_volume = self.grid_usdt_size self.current_volume = self.grid_usdt_volume / bar.close_price if not self.pos or self.pos < self.min_volume: """ 1、如果空仓,以当前价格买入一份做为底仓 2、总网格次数减一 """ self.buy_price = bar.close_price - self.tick_price * self.pay_up # 取四舍五入 self.current_volume = float( format(self.current_volume, f".{self.len_tick_decimal}f")) USDT = bar.close_price * self.min_volume if self.current_volume < self.min_volume: msg = f"当前下单小于:{self.vt_symbol} 最小下单最,请重新设置最小下单量!最下小量为:{self.min_volume},需要约:{USDT}枚USDT" self.write_log(msg) return vt_orderid = self.buy(self.buy_price, self.current_volume, order_type=OrderType.MakerPostOnly) # 把挂单信息添加到列表末尾 self.vt_orderids.extend(vt_orderid) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price # 清空 self.cumulative_usdt_volume = 0 self.grid_count = 0 self.current_volume = 0 else: if bar.close_price < self.buy_benchmark: """ 当前收盘价低于下个网格买入价格时,判断买入时机: 1、价格在上次买入后,中间没有卖出的过程, 2、 """ if self.cumulative_usdt_volume < self.grid_usdt_capital: """ 买在最低位 """ self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.trade_low = self.intra_trade_low * ( 1 + self.buy_callback / 100) if self.trade_low < self.buy_benchmark: self.buy_price = self.trade_low else: self.buy_price = self.buy_benchmark # 取四舍五入 self.current_volume = float( format(self.current_volume, f".{self.len_tick_decimal}f")) vt_orderid = self.buy(self.buy_price, self.current_volume, order_type=OrderType.MakerPostOnly) self.vt_orderids.extend(vt_orderid) elif bar.close_price > self.sell_benchmark: if self.pos > 0: """ 卖在最高位 """ self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.trade_high = self.intra_trade_high * ( 1 - self.sell_callback / 100) if self.trade_high > self.sell_benchmark: self.sell_price = self.trade_high else: self.sell_price = self.sell_benchmark # 判断 如果理论(不含手续费)self.pos 比交易所成交反馈回来的量小时,使用交易所反馈回来的量下单,同时把理论值设置为零 if self.pos > self.current_volume * 1.2: self.sell_fixed_size = self.current_volume else: self.sell_fixed_size = self.pos vt_orderid = self.sell(self.sell_price, abs(self.sell_fixed_size), order_type=OrderType.MakerPostOnly) self.vt_orderids.extend(vt_orderid) # 更新图形界面 self.put_event() def on_mintue_bar(self, bar: BarData): """ :return: """ self.am_minute.update_bar(bar) if not self.am_minute.inited: return # 计算振幅 if self.sleep_switch: self.amplitude = (bar.high_price - bar.low_price) / bar.high_price # 如果振幅超过指定值,策略撤掉所有挂单,并且进入休眠状态 if self.amplitude > self.grid_amplitude / 100: self.amplitude_inited = True self.time_stop = bar.datetime + datetime.timedelta( hours=self.stop_time) time_stop = self.time_stop.replace(tzinfo=UTC_TZ) self.write_log( f"当前市场波动较大," f"振幅为:{self.amplitude},超过设置值,策略进入休眠," f"休眠到:{time_stop.strftime('%Y-%m-%d %H:%M:%S')}时重新启动策略") def on_xhour_bar(self, bar: BarData): """ :return: """ self.am_xhour.update_bar(bar) if not self.am_xhour.inited: return pass def on_order(self, order: OrderData): """ 判断是否完全成交,如果成交获取成交数量,计数器加减 移除成交、拒绝、撤单的订单号 """ if order.vt_orderid in self.vt_orderids: if order.status == Status.ALLTRADED: if order.direction == Direction.LONG: self.target_pos = order.traded self.grid_count += 1 self.cumulative_usdt_volume += self.grid_usdt_volume # 买入时,实际得到币量为总买量减手续费 msg = f"开仓,成交量为:{self.target_pos}" self.write_log(msg) self.target_pos = 0 else: self.target_pos = -order.traded self.grid_count -= 1 self.cumulative_usdt_volume -= self.grid_usdt_volume msg = f"平仓,成交量为:{self.target_pos}" self.write_log(msg) self.target_pos = 0 if not order.is_active(): self.vt_orderids.remove(order.vt_orderid) self.sync_data() def on_trade(self, trade: TradeData): """ 获取交易价格做为基准线 """ if trade.direction == Direction.LONG: self.price_change = trade.price # 成交最高价 msg = f"开仓,成交价格为:{self.price_change}" self.write_log(msg) else: self.price_change = trade.price msg = f"平仓,成交价格为:{self.price_change}" self.write_log(msg) # 计算当前网格买入价格和卖出价格 self.buy_benchmark = self.price_change * (1 - self.grid_buy_price / 100) self.sell_benchmark = self.price_change * (1 + self.grid_sell_price / 100) msg = f"下个网格加仓价格线为:{self.buy_benchmark},平仓位价格线为: {self.sell_benchmark}" self.write_log(msg) self.sync_data() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class MultiTimeframeStrategy(CtaTemplate): """""" author = "用Python的交易员" rsi_signal = 20 rsi_window = 14 fast_window = 5 slow_window = 20 fixed_size = 1 # 5min级bar下限价单时的加点,应该为最小变动价的整数倍 bar_add = 2 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","bar_add"] variables = ["rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long = 50 + self.rsi_signal self.rsi_short = 50 - self.rsi_signal # 维护两组bg/am,对应不同时间周期 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 + self.bar_add, self.fixed_size) elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(bar.close_price - self.bar_add, self.fixed_size) elif self.pos > 0: if self.ma_trend < 0 or self.rsi_value < 50: self.sell(bar.close_price - self.bar_add, abs(self.pos)) elif self.pos < 0: if self.ma_trend > 0 or self.rsi_value > 50: self.cover(bar.close_price + self.bar_add, 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) # 根据15min级的MA设置方向 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 MaLevelTrackStrategy(CtaTemplate): author = "用Python的交易员" ma_level = [5, 10, 20, 30, 120] ma_tag = [] bd = [] fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 request_order = [] bar_identify = [] parameters = ["ma_level"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(MaLevelTrackStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_1min_bar) self.am = ArrayManager(400) self.am3 = ArrayManager(150) self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar) self.am5 = ArrayManager(120) self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.order_data = None self.positions = Position(self) self.std_range = IntervalGen(np.std, 5) self.std_range3 = IntervalGen(np.std, 5) self.std_range5 = IntervalGen(np.std, 5) self.pattern_record = PatternRecord() # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3) self.pattern_record.set_expiry(list(KlinePattern), 1) five_min_open_5 = partial(self.reverse_shape_strategy, setting={ "atr": 10, "atr_valve": 0.8, "deg1": (10, 5), "deg2": 5 }) self.open_strategy = { "1": [self.reverse_shape_strategy], "5": [five_min_open_5], } self.offset = 40 self.ma120_track = None self.ma120_track_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("策略启动") 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) self.bg3.update_tick(tick) self.bg5.update_tick(tick) def on_3min_bar(self, bar: BarData): self.am3.update_bar(bar) self.std_range3.update(self.am3.range[-1]) if not self.am.inited or not self.trading: return pattern = self.am3.pattern( [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS]) if len(pattern) > 0: print(pattern) self.pattern_record.add_pattern(pattern) # deg = calc_regress_deg(self.am3.close[-20:]) def wave(self, data, window=0.0002): if len(data) <= 0: return # r = array[::-1] result = {"value": [], "range": [], "pos": [], "length": []} r = data l = len(data) - 1 now = r[0] # v_list.append(now) # p_list.append(0) pos = 1 vol = 0 u_tag = None d_tag = None end_tag = None start_pos = 0 while pos < l: if math.isnan(now): now = r[pos] pos += 1 continue else: start_pos = pos - 1 break while pos < l: if now < r[pos]: u_tag = pos if d_tag: diff = r[start_pos] - r[d_tag] if abs(diff / r[start_pos]) > window and d_tag - start_pos > 1: end_tag = d_tag elif now > r[pos]: d_tag = pos if u_tag: diff = r[start_pos] - r[u_tag] if abs(diff / r[start_pos]) > window and d_tag - start_pos > 1: end_tag = u_tag if end_tag is not None: result["range"].append(r[end_tag] / r[start_pos] - 1) result["length"].append(end_tag - start_pos) start_pos = end_tag result["value"].append(r[end_tag]) result["pos"].append(end_tag) end_tag = None vol += r[pos] - now now = r[pos] pos += 1 return pd.DataFrame(result) def mode_identify(self, bar: BarData): self.bar_identify = [] hl_scale = round(bar.high_price / bar.low_price - 1, 4) if hl_scale > 0.001: diff = bar.high_price - bar.low_price diff_up = bar.low_price + diff / 2 * 1.20 diff_down = bar.low_price + diff / 2 * 0.80 close = bar.close_price if bar.open_price < diff_up and bar.open_price > diff_down and \ bar.close_price < diff_up and bar.close_price > diff_down: if bar.close_price > bar.open_price: print("绿十字星", bar.datetime, bar.high_price, bar.low_price, diff, diff_up, diff_down, bar.open_price, bar.close_price) else: print("红十字星", bar.datetime, bar.high_price, bar.low_price, diff, diff_up, diff_down, bar.open_price, bar.close_price) def on_5min_bar(self, bar: BarData): self.std_range5.update(self.am5.range[-1]) self.am5.update_bar(bar) if not self.am.inited or not self.trading: return self.on_strategy(self.am5, bar, self.open_strategy["5"]) # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR] # pattern = self.am5.pattern(list(KlinePattern)) # if len(pattern) > 0: # print(list(map(lambda x: (KLINE_PATTERN_CHINESE[x[0]],x[1]), pattern))) # self.pattern_record.add_pattern(pattern) # deg_full = calc_regress_deg(self.am.close[-40 :], False) # print("deg:",deg_full) # self.pattern_record.update() def open_v3(self, am: ArrayManager, bar: BarData): std_val2 = np.std(np.array(self.ma_tag[-10:-1])) mean_val2 = np.mean(np.array(self.ma_tag[-10:-1])) mean = np.mean(np.array(self.ma_tag[-30:-10])) if std_val2 < 0.2: if mean_val2 > 3: if mean_val2 >= (mean + 1): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif mean_val2 < 2: if mean_val2 <= (mean - 1): return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_v1(self, am: ArrayManager, bar: BarData): offset = -40 offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) mean_val = np.mean(calc_nums) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) if std_val < 1 and mean_val < 2 and self.ma_tag[-1] >= (mean_val + 2): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif std_val < 1 and mean_val > 3 and self.ma_tag[-1] <= (mean_val - 2): return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_v2(self, am: ArrayManager, bar: BarData): std_val2 = np.std(np.array(self.ma_tag[-10:-1])) mean_val2 = np.mean(np.array(self.ma_tag[-10:-1])) mean = np.mean(np.array(self.ma_tag[-30:-10])) if std_val2 < 0.2: if mean_val2 > 2.5: if mean_val2 >= (mean + 1): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif mean_val2 < 2.5: if mean_val2 <= (mean - 1): return self.short(bar.close_price, 1, type=OrderType.MARKET) def open2(self, am: ArrayManager, bar: BarData, calc_data): deg = calc_data["deg20"] ma = self.ma_tag[-1] if deg > 0.5 and ma > 3 and self.am5.range[-1] > -0.002: return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif deg < -0.5 and ma < 2 and self.am5.range[-1] < 0.002: return self.short(bar.close_price, 1, type=OrderType.MARKET) def open1(self, am: ArrayManager, bar: BarData, calc_data): mean = calc_data["mean30_10"] mean_val2 = calc_data["mean10"] # if std_val2 < 0.2: if mean_val2 > 3.5 and mean_val2 >= (mean + 2): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif mean_val2 < 1.5 and mean_val2 <= (mean - 2): return self.short(bar.close_price, 1, type=OrderType.MARKET) # v形反转捕获 def reverse_shape_strategy(self, am: ArrayManager, bar: BarData, calc_data, setting={ "atr": 40, "atr_valve": 0.8, "deg1": (40, 20), "deg2": (20, 0), }): deg1 = calc_data["deg40_20"] deg2 = calc_data["deg20_0"] kdj = calc_data["kdj"] atr = self.am.atr(40) if atr < 0.08: return if deg1 > 0 and deg2 > 0 or \ deg1 < 0 and deg2 < 0: return if not (abs(deg1) > 0.15 and abs(deg2) > 0.1 and (abs(deg1) + abs(deg2)) > 0.3): return close = am.close[-40:] min_val = np.min(close) max_val = np.max(close) mid_val = max_val if deg1 > 0 else min_val mid_pos = np.where(close == mid_val)[0][0] if mid_pos < 10 or mid_pos > 30: return start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max( close[:mid_pos]) start_pos = np.where(close == start_val)[0][0] l = mid_pos - start_pos # pos2 = np.where(close == min_val)[0][0] x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True) deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False) y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True) deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False) print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val) if deg2 < 0: if kdj[0] < 20 and kdj[1] < 10 and kdj[2] < 10: # if kdj[2] < 10: return self.short(bar.close_price, 1, type=OrderType.MARKET) else: if kdj[0] > 80 and kdj[1] > 90 and kdj[2] > 90: # if kdj[2] > 90: return self.buy(bar.close_price, 1, type=OrderType.MARKET) # print("找到大v形:", deg1, deg2 ) def open5(self, am: ArrayManager, bar: BarData, calc_data): ma = self.ma_tag[-1] mean = calc_data["mean30_10"] atr = self.am.atr(10, array=True, length=20) tr = self.am.atr(1, array=True, length=11) # self.ma120_track ma120 = self.am.sma(120) # if std_val2 < 0.2: mean_std = calc_data["mean_std"] if mean_std < 0.8 and tr[-1] > 0.1 and tr[-1] / tr[-10] > 3 and tr[ -1] / atr[-1] >= 1.7 and tr[-10] / atr[-10] < 1: if np.sum(self.am.range[-10:]) > 0 and self.ma120_track > 0: return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif self.ma120_track < 0: return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_kline1(self, am: ArrayManager, bar: BarData, calc_data): if KlinePattern.CDLEVENINGSTAR not in self.pattern_record: return # if std_val2 < 0.2: deg = calc_regress_deg(self.am.close[-5:], False) print("kline_strategy", deg) if deg < -0.1: return self.short(bar.close_price, 1, type=OrderType.MARKET) def generate_data(self, bar: BarData): offset = -self.offset offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) std_val2 = np.std(np.array(self.ma_tag[-10:-1])) std_val3 = np.std(np.array(self.am.range[-30:-10])) ma = self.ma_tag[-1] mean_val = np.mean(calc_nums) mean_val2 = np.mean(np.array(self.ma_tag[-5:-1])) mean_val3 = np.mean(np.array(self.ma_tag[-20:-1])) mean_val4 = np.mean(np.array(self.ma_tag[-30:-5])) kdj_val = self.am.kdj() deg1 = calc_regress_deg(self.am.close[offset:offset_m], False) deg2 = calc_regress_deg(self.am.close[offset_m:], False) deg3 = calc_regress_deg(self.am.close[-10:], False) deg_full = calc_regress_deg(self.am.close[offset:], False) wave = self.wave(self.am.close[-30:]) wave_r_sum = np.sum(wave["range"]) macd = self.am.macd(20, 40, 16) calc_data = (dict( kdj=[ round(kdj_val["k"][-1], 2), round(kdj_val["d"][-1], 2), round(kdj_val["j"][-1], 2) ], cci_20=self.am.cci(20), rsi=self.am.rsi(20), adx=self.am.adx(20), boll=self.am.boll(20, 3.4), macd=[round(macd[0], 2), round(macd[1], 2), round(macd[2], 2)], deg40_20=round(deg1, 2), deg20_0=round(deg2, 2), deg20_10=round(calc_regress_deg(self.am.close[-20:-10], False), 2), deg10_0=round(deg3, 2), deg30_15=round(calc_regress_deg(self.am.close[-30:-15], False), 2), deg15_0=round(calc_regress_deg(self.am.close[-15:], False), 2), deg_f=round(deg_full, 2), atr=round(self.am.atr(10, length=15), 3), tr=round(self.am.atr(1, length=2), 3), atr_40=round(self.am.atr(40, length=42), 3), time=bar.datetime, price=bar.close_price, ma=round(ma, 2), std_40=round(std_val, 2), mean40=round(mean_val, 2), mean_std=np.mean(self.std_range.data[-5:]), std_10=round(std_val2, 2), mean30_10=round(mean_val4, 2), mean10=round(mean_val2, 2), vol=self.am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=self.am.range[-1:-5:-1].tolist(), range_sum=np.sum(self.am.range[-5:]), pattern=list( map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())), ma120t=self.ma120_track, ma120t_list=self.ma120_track_list[-1:-10:-1], ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs), ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]), wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(self.am.atr(20, array=True, length=240)[-200:]))) return calc_data def on_strategy(self, am: ArrayManager, bar: BarData, strategy_list): calc_data = self.generate_data(bar) order_id = None if self.pos == 0: for open_strategy in strategy_list: if order_id is not None: break order_id = open_strategy(am, bar, calc_data) else: order_id = self.positions.on_strategy(bar, calc_data) if order_id is not None: offset = -self.offset offset_m = int(offset / 2) self.tracker["trade_info"].append( (self.am.time_array[offset], self.am.time_array[offset_m], bar.datetime, calc_data["deg40_20"], calc_data["deg20_0"])) self.request_order.extend(order_id) if self.tracker is not None: self.tracker["ma_tag_ls"].append(calc_data) def on_1min_bar(self, bar: BarData): self.am.update_bar(bar) am = self.am max_len = self.ma_level[-1] + 20 data = self.am.close[-max_len:-1] ma_lvl = [] for i in self.ma_level: ma = self.am.sma(i, True)[-1] ma_lvl.append(ma) l = len(ma_lvl) ma_lvl_tag = [] now = bar.close_price direction = 1 if now > ma_lvl[0] else 0 ma_lvl_tag.append(direction) for i in range(l - 1): val = 1 if ma_lvl[i] > ma_lvl[i + 1] else 0 ma_lvl_tag.append(val) bincount_val = np.bincount(np.array(ma_lvl_tag)) tag_val = 0 if len(bincount_val) == 2: tag_val = bincount_val[1] if len(self.ma_tag) < 200: self.ma_tag.append(tag_val) else: self.ma_tag[:-1] = self.ma_tag[1:] self.ma_tag[-1] = tag_val if self.tracker is not None: self.tracker["bar_data"].append(bar) self.std_range.update(self.am.range[-1]) ma120 = self.am.sma(120) if bar.close_price >= ma120: if self.ma120_track is None: self.ma120_track = 1 elif self.ma120_track > 0: self.ma120_track += 1 else: self.ma120_track_list.append(self.ma120_track) self.ma120_track = 1 elif bar.close_price < ma120: if self.ma120_track is None: self.ma120_track = -1 elif self.ma120_track < 0: self.ma120_track -= 1 else: self.ma120_track_list.append(self.ma120_track) self.ma120_track = -1 if not am.inited or not self.trading: return self.on_strategy(am, bar, self.open_strategy["1"]) # median_val = np.median(calc_nums) self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg3.update_bar(bar) self.bg5.update_bar(bar) self.bg.update_bar(bar) # def init_order_data(self): # self.order_data = np.array([]) def on_order(self, order: OrderData): """ Callback of new order data update. """ print("{}产生了{},价格为{},笔数为{},交易{},pos={}".format( order.datetime.strftime("%m/%d %H:%M:%S"), order.offset.value + order.direction.value, order.price, order.volume, order.status.value, self.pos)) if order.vt_orderid in self.request_order: self.positions.on_order(order) if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED: self.request_order.remove(order.vt_orderid) # if order.status == Status.ALLTRADED or order.status == Status.PARTTRADED: # if order.direction == Direction.LONG: # if self.positions.volumn == 0: # self.positions.close_price = round(order.price * 0.995) # self.positions.volumn += order.volume # elif order.direction == Direction.SHORT: # self.positions.volumn -= order.volume # elif order.direction == Direction.NET: # self.positions.volumn = order.volume 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 Mike_Dc_Strategy(CtaTemplate): """""" author = "yunya" exchange : Exchange = "" mike_window = 1 mike_length = 30 dc_length = 10 kk_length = 20 kk_dev = 2.0 sl_trade = 2 fixed_size = 1 ask = 0 bid = 0 ema_mid = 0 ema_hh = 0 ema_ll = 0 ema_wr = 0 #初级压力线 ema_mr = 0 #中级压力线 ema_sr = 0 #高级压力线 ema_ws = 0 #初级支撑线 ema_ms = 0 #中级支撑线 ema_ss = 0 #高级支撑线 dc_up = 0 dc_down = 0 kk_up = 0 kk_down = 0 atr_value = 0 long_stop = 0 short_stop = 0 long_stop_trade = 0 short_stop_trade = 0 long_enrty = 0 short_enrty = 0 ema_entry_crossover = 0 boll_entry_crossover = 0 boll_width = 0 parameters = [ "exchange", "mike_window", "mike_length", "dc_length", "kk_length", "kk_dev", "sl_trade", "fixed_size", ] variables = [ "long_stop", "short_stop", "ema_entry_crossover", "boll_entry_crossover", "boll_width", "ema_mid", "ema_hh", "ema_ll", "ema_wr", "ema_mr", "ema_sr", "ema_ws", "ema_ms", "ema_ss", ] def __init__(self, cta_engine, strategy_nam_xhoure, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_nam_xhoure, vt_symbol, setting) self.bg_xhour = BarGenerator( on_bar=self.on_bar, window=self.mike_window, on_window_bar=self.on_hour_bar, interval=Interval.HOUR ) self.am_xhour = ArrayManager(max(self.dc_length ,self.kk_length) + 10) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.exchange_load_bar(self.exchange) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_xhour.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xhour.update_bar(bar) def on_hour_bar(self, bar: BarData): """ 计算 mike 指标线 :param_xhour bar: :return: """ self.am_xhour.update_bar(bar) if not self.am_xhour.inited: return # 计算mike压力支撑线 ema_array = (self.am_xhour.close[:-1] + self.am_xhour.high[:-1] + self.am_xhour.low[:-1]) / 3 self.ema_mid = ema_array[-1] self.ema_hh = self.am_xhour.high[-self.mike_length:-1].max() self.ema_ll = self.am_xhour.low[-self.mike_length:-1].min() self.ema_wr = self.ema_mid + (self.ema_mid - self.ema_ll) self.ema_mr = self.ema_mid + (self.ema_hh - self.ema_ll) self.ema_sr = 2 * self.ema_hh - self.ema_ll self.ema_ws = self.ema_mid - (self.ema_hh - self.ema_mid) self.ema_ms = self.ema_mid - (self.ema_hh - self.ema_ll) self.ema_ss = 2 * self.ema_ll - self.ema_hh if (self.am_xhour.close[-1] > self.ema_sr) or (self.ema_ms < self.am_xhour.close[-1] < self.ema_ws): self.ema_entry_crossover = 1 elif (self.am_xhour.close[-1] < self.ema_ss) or (self.ema_mr > self.am_xhour.close[-1] > self.ema_wr): self.ema_entry_crossover = -1 self.kk_up,self.kk_down = self.am_xhour.keltner(self.kk_length,self.kk_dev) self.dc_up,self.dc_down = self.am_xhour.donchian(self.dc_length) if self.pos == 0: self.atr_value = self.am_xhour.atr(30) if self.ema_entry_crossover > 0 : self.buy(self.kk_up, self.fixed_size,True) print(self.kk_up) elif self.ema_entry_crossover < 0 : self.short(self.kk_down, self.fixed_size,True) elif self.pos > 0: self.long_stop = max(self.dc_down,self.long_stop_trade) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.short_stop = min(self.dc_up,self.short_stop_trade) self.cover(self.short_stop, abs(self.pos), True) self.sync_data() self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass # self.write_log(f"on_order: status:{order.status}, orderid: {order.vt_orderid}, offset:{order.offset}, price:{order.price}, volume:{order.volume}, traded: {order.traded}") # self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # if trade.direction == Direction.LONG: # self.long_enrty = trade.price # self.long_stop_trade = self.long_enrty - 2 * self.atr_value # # else: # self.short_enrty = trade.price # self.short_stop_trade = self.short_enrty + 2 * self.atr_value self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def exchange_load_bar(self,exchange:Exchange): """ 如果是火币,ok 交易所,就从数据库获取初始化数据 """ if exchange == Exchange.OKEX or exchange == Exchange.HUOBI: self.load_bar(days=10,use_database=True) else: self.load_bar(10)
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_15min_bar,interval=Interval.HOUR) self.am = ArrayManager()
class MacdBollDcStrategy(CtaTemplate): """""" author = "云崖" open_window = 2 xminute_window = 15 xhour_window = 1 fast_length = 14 show_length = 28 boll_length = 20 boll_dev = 2.0 dc_length = 30 trailing_tax = 2.0 fixed_size = 1 macd_inited = 0 boll_up = 0 boll_down = 0 dc_up = 0 dc_down = 0 exit_long = 0 exit_short = 0 long_stop = 0 short_stop = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "open_window", "xminute_window", "xhour_window", "fast_length", "show_length", "boll_length", "boll_dev", "dc_length", "trailing_tax", "fixed_size", ] variables = [ "macd_inited", "boll_up", "boll_down", "dc_up", "dc_down", "exit_long", "exit_short", "long_stop", "short_stop", ] def __init__(self, cta_engine, strategy_nam_xminutee, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_nam_xminutee, vt_symbol, setting) self.bg_open = NewBarGenerator(self.on_bar, self.open_window, self.on_open_bar) self.am_open = ArrayManager() self.bg_xminute = NewBarGenerator(self.on_bar, self.xminute_window, self.on_xminute_bar) self.am_xminute = ArrayManager(150) self.bg_xhour = NewBarGenerator(self.on_bar, self.xhour_window, self.on_xhour_bar, interval=Interval.HOUR) self.am_xhour = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_xminute.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xhour.update_bar(bar) self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_open_bar(self, bar: BarData): """""" self.cancel_all() self.am_open.update_bar(bar) if not self.am_xminute.inited or not self.am_open.inited: return if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 if self.macd_inited > 0: self.buy(self.boll_up, self.fixed_size, True) elif self.macd_inited < 0: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price long_high = self.intra_trade_high * (1 - self.trailing_tax / 100) self.long_stop = max(self.exit_long, long_high) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) stop_low = self.intra_trade_low * (1 + self.trailing_tax / 100) self.short_stop = min(self.exit_short, stop_low) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xminute_bar(self, bar: BarData): """""" self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return self.boll_up, self.boll_down = self.am_xminute.boll( self.boll_length, self.boll_dev) self.exit_short, self.exit_long = self.am_xminute.donchian( self.dc_length) def on_xhour_bar(self, bar: BarData): """ :param bar: :type bar: :return: :rtype: """ self.am_xhour.update_bar(bar) if self.am_xhour.inited: return fast_ema_value = self.am_xhour.ema(self.fast_length, True) show_ema_value = self.am_xhour.ema(self.show_length, True) diff = fast_ema_value - show_ema_value macd_diff = (fast_ema_value - show_ema_value) / show_ema_value * 100 if diff[-2] > macd_diff[-2]: self.macd_inited = 1 elif diff[-2] < macd_diff[-2]: self.macd_inited = -1 def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event()
class 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 PatternScoreStrategy(CtaTemplate): author = "用Python的交易员" ma_level = [10, 20, 30, 60, 120] ma_tag = [] bd = [] fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 request_order = [] bar_identify = [] score = Score() count = 0 interval = 6 parameters = ["ma_level"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(PatternScoreStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager(400) self.am3 = ArrayManager(150) self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar) self.am5 = ArrayManager(120) self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.order_data = None self.positions = Position(self) self.std_range = IntervalGen(np.std, 5) self.std_range3 = IntervalGen(np.std, 5) self.std_range5 = IntervalGen(np.std, 5) self.pattern_record = PatternRecord() # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3) self.pattern_record.set_expiry(list(KlinePattern), 1) self.open_strategy = [self.open_kline1] self.offset = 40 self.min = 0 self.max = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") 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) self.bg3.update_tick(tick) self.bg5.update_tick(tick) def on_3min_bar(self, bar: BarData): self.am3.update_bar(bar) self.std_range3.update(self.am3.range[-1]) if not self.am.inited or not self.trading: return # deg = calc_regress_deg(self.am3.close[-20:]) def calc_score(self): score = 0 score += self.score.base for item in self.pattern_record.values(): score += item["value"] return score def on_5min_bar(self, bar: BarData): self.std_range5.update(self.am5.range[-1]) self.am5.update_bar(bar) if not self.am.inited or not self.trading: return diff_time = bar.datetime - self.am.time_array[-1] if diff_time.total_seconds() > 3600 or self.count > self.interval: self.count = 0 self.score.base = calc_regress_deg(self.am.close[-self.interval:], False) * 1000 print("score:", self.score.base, self.min, self.max) else: self.count += 1 # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR] pattern = self.am5.pattern(list(KlinePattern)) if len(pattern) > 0: print( list( map(lambda x: (KLINE_PATTERN_CHINESE[x[0]], x[1]), pattern))) self.pattern_record.add_pattern(pattern) deg_full = calc_regress_deg(self.am.close[-40:], False) print("deg:", deg_full) self.pattern_record.update() def open_kline1(self, bar: BarData, calc_data): score = self.calc_score() if score < self.min: self.min = score if score > self.max: self.max = score if abs(calc_data["range_sum"]) < 0.001 or abs(score) < 300: return # if std_val2 < 0.2: if score > 0 and calc_data["range_sum"] > 0: return self.buy(bar.close_price, 1, type=OrderType.MARKET, extra={ "reason": "开多,score={}, rang_sum={}".format( score, calc_data["range_sum"]) }) if score < 0 and calc_data["range_sum"] < 0: return self.short(bar.close_price, 1, type=OrderType.MARKET, extra={ "reason": "开多,score={}, rang_sum={}".format( score, calc_data["range_sum"]) }) def generate_data(self, bar: BarData): offset = -self.offset offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) std_val2 = np.std(np.array(self.ma_tag[-10:-1])) std_val3 = np.std(np.array(self.am.range[-30:-10])) ma = self.ma_tag[-1] mean_val = np.mean(calc_nums) mean_val2 = np.mean(np.array(self.ma_tag[-5:-1])) mean_val3 = np.mean(np.array(self.ma_tag[-20:-1])) mean_val4 = np.mean(np.array(self.ma_tag[-30:-5])) kdj_val = self.am.kdj() deg1 = calc_regress_deg(self.am.close[offset:offset_m], False) deg2 = calc_regress_deg(self.am.close[offset_m:], False) deg3 = calc_regress_deg(self.am.close[-10:], False) deg_full = calc_regress_deg(self.am.close[offset:], False) calc_data = (dict(kdj=[ round(kdj_val["k"][-1], 2), round(kdj_val["d"][-1], 2), round(kdj_val["j"][-1], 2) ], deg40_20=round(deg1, 2), deg20=round(deg2, 2), deg10=round(deg3, 2), deg_f=round(deg_full, 2), time=bar.datetime, price=bar.close_price, ma=round(ma, 2), std_40=round(std_val, 2), mean40=round(mean_val, 2), std_10=round(std_val2, 2), mean30_10=round(mean_val4, 2), mean10=round(mean_val2, 2), vol=self.am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=self.am.range[-1:-5:-1].tolist(), range_sum=np.sum(self.am.range[-5:]), atr=self.am.atr(10), tr=self.am.atr(1, length=2), pattern=list( map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())))) return calc_data def on_strategy(self, bar: BarData): calc_data = self.generate_data(bar) order_id = None if self.pos == 0: for open_strategy in self.open_strategy: if order_id is not None: break order_id = open_strategy(bar, calc_data) else: order_id = self.positions.on_strategy(bar, calc_data) if order_id is not None: offset = -self.offset offset_m = int(offset / 2) self.tracker["trade_info"].append( (self.am.time_array[offset], self.am.time_array[offset_m], bar.datetime, calc_data["deg40_20"], calc_data["deg20"])) self.request_order.extend(order_id) if self.tracker is not None: self.tracker["ma_tag_ls"].append(calc_data) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg3.update_bar(bar) self.bg5.update_bar(bar) am = self.am self.am.update_bar(bar) max_len = self.ma_level[-1] + 20 data = self.am.close[-max_len:-1] ma_lvl = [] for i in self.ma_level: ma = self.am.sma(i, True)[-1] ma_lvl.append(ma) l = len(ma_lvl) ma_lvl_tag = [] now = bar.close_price direction = 1 if now > ma_lvl[0] else 0 ma_lvl_tag.append(direction) for i in range(l - 1): val = 1 if ma_lvl[i] > ma_lvl[i + 1] else 0 ma_lvl_tag.append(val) bincount_val = np.bincount(np.array(ma_lvl_tag)) tag_val = 0 if len(bincount_val) == 2: tag_val = bincount_val[1] if len(self.ma_tag) < 200: self.ma_tag.append(tag_val) else: self.ma_tag[:-1] = self.ma_tag[1:] self.ma_tag[-1] = tag_val if self.tracker is not None: self.tracker["bar_data"].append(bar) self.std_range.update(self.am.range[-1]) if not self.am.inited or not self.trading: return self.on_strategy(bar) # median_val = np.median(calc_nums) self.put_event() # def init_order_data(self): # self.order_data = np.array([]) def on_order(self, order: OrderData): """ Callback of new order data update. """ print("{}产生了{},价格为{},交易{},".format( order.datetime.strftime("%m/%d %H:%M:%S"), order.offset.value + order.direction.value, order.price, order.status.value)) if order.vt_orderid in self.request_order: self.positions.on_order(order) if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED: self.request_order.remove(order.vt_orderid) # if order.status == Status.ALLTRADED or order.status == Status.PARTTRADED: # if order.direction == Direction.LONG: # if self.positions.volumn == 0: # self.positions.close_price = round(order.price * 0.995) # self.positions.volumn += order.volume # elif order.direction == Direction.SHORT: # self.positions.volumn -= order.volume # elif order.direction == Direction.NET: # self.positions.volumn = order.volume 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 TrendModelStrategy(CtaTemplate): """""" author = "yiran" fixed_size = 1 fast_ma_macd = 9 slow_ma_macd = 26 signal_macd = 4 true_range_window = 4 true_range_influence_multiplier = 0.5 cross_over_record_max_num = 50 cross_over_slice_window = 4 trail_bar_window = 6 bar_num = 0 bar_num_after_crossover = 0 mdif = 0 cross_above_0 = False cross_under_0 = False cross_over_record_array = np.zeros(shape=(4, cross_over_record_max_num)) cross_over_slice_window_highest = 0 cross_over_slice_window_lowest = 0 last_cross_over_interval = 0 last_cross_over_side = 0 long_open_stop_order_price = 0 long_close_stop_order_price = 0 short_open_stop_order_price = 0 short_close_stop_order_price = 0 parameters = [ 'fast_ma_macd', 'slow_ma_macd', 'signal_macd', 'true_range_window', 'cross_over_record_max_num', 'true_range_influence_multiplier', 'cross_over_slice_window', 'trail_bar_window' ] variables = [ 'bar_num', 'bar_num_after_crossover', 'mdif', 'cross_above_0', 'cross_under_0' 'cross_over_slice_window_highest', 'cross_over_slice_window_lowest', 'last_cross_over_interval', 'long_open_stop_order_price', 'lass_cross_over_side', 'short_open_stop_order_price', 'short_close_stop_order_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.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.am.update_bar(bar) self.bar_num += 1 if not self.am.inited: return am = self.am self.mdif, signal, hist = am.macd(self.fast_ma_macd, self.slow_ma_macd, self.signal_macd, array=True) self.long_close_stop_order_price = am.low[-self.trail_bar_window:].min( ) self.short_close_stop_order_price = am.high[-self. trail_bar_window:].max() if self.mdif[-2] < 0 < self.mdif[-1]: self.cross_above_0 = True elif self.mdif[-2] > 0 > self.mdif[-1]: self.cross_under_0 = True if self.cross_under_0 or self.cross_above_0: # bar_num self.cross_over_record_array[ 0, :-1] = self.cross_over_record_array[0, 1:] # high self.cross_over_record_array[ 1, :-1] = self.cross_over_record_array[1, 1:] # low self.cross_over_record_array[ 2, :-1] = self.cross_over_record_array[2, 1:] # cross_over_side self.cross_over_record_array[ 3, :-1] = self.cross_over_record_array[3, 1:] self.cross_over_record_array[0, -1] = self.bar_num self.cross_over_record_array[1, -1] = am.high[-1] self.cross_over_record_array[2, -1] = am.low[-1] if self.cross_above_0: side = 1 elif self.cross_under_0: side = -1 self.cross_over_record_array[3, -1] = side self.cross_above_0, self.cross_under_0 = False, False self.cross_over_slice_window_highest = np.max( self.cross_over_record_array[1, -self.cross_over_slice_window:]) self.cross_over_slice_window_lowest = np.min( self.cross_over_record_array[2, -self.cross_over_slice_window:]) self.last_cross_over_interval = self.bar_num - \ self.cross_over_record_array[0, -1] self.last_cross_over_side = self.cross_over_record_array[3, -1] true_range_influence = np.mean( am.trange(array=True) [-self.true_range_window:]) * self.true_range_influence_multiplier self.long_open_stop_order_price = self.cross_over_slice_window_highest + \ true_range_influence self.short_open_stop_order_price = self.cross_over_slice_window_lowest + \ true_range_influence if self.pos == 0: if self.last_cross_over_interval <= self.cross_over_record_max_num: if self.last_cross_over_side == 1: self.buy(self.long_open_stop_order_price, self.fixed_size, stop=True) if self.last_cross_over_side == -1: self.short(self.short_close_stop_order_price, self.fixed_size, stop=True) elif self.pos > 0: self.sell(self.long_close_stop_order_price, self.pos, stop=True) elif self.pos < 0: self.cover(self.short_close_stop_order_price, np.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 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 AberrationStrategy(CtaTemplate): """""" author = "yunya" open_window = 15 boll_length = 80 boll_dev = 2.0 cci_length = 6 cci_exit = 10.0 fixed_size = 1 boll_up = 0 boll_down = 0 boll_mid = 0 boll_mid_new = 0 cci_value = 0 exit_long = 0 exit_short = 0 boll_length_new = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 parameters = [ "open_window", "boll_length", "boll_dev", "cci_length", "cci_exit", "fixed_size", ] variables = [ "boll_up", "boll_down", "boll_mid", "cci_value", "exit_long", "exit_short", "boll_length_new", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_xmin_bar) self.am = ArrayManager(int(self.boll_length) + 100) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算原布林带 self.boll_up, self.boll_down = self.am.boll(self.boll_length, self.boll_dev) self.boll_mid = am.sma(self.boll_length) self.cci_value = am.cci(self.cci_length) # 如果没有仓位,两条布林window一样 if self.pos == 0: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.boll_length_new = self.boll_length if self.cci_value > self.cci_exit: self.buy(self.boll_up, self.fixed_size, stop=True) if self.cci_value < -self.cci_exit: self.short(self.boll_down, self.fixed_size, stop=True) elif self.pos > 0: # 上涨或下跌时,布林中轨均值减1 close_long = am.close[-1] > am.close[-2] > am.close[-3] if close_long: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 20) # 计算新的布林带 self.boll_mid_new = am.sma(self.boll_length_new, True) # 仓位是long 时,如果价格上穿新布林中轨 con1 = am.close[-1] < self.boll_mid_new[-1] con2 = am.close[-2] >= self.boll_mid_new[-2] if con1 and con2: self.exit_long_nex = am.close[-1] # 保存当前收盘价 if self.exit_long_nex > self.exit_long_last or self.exit_long_last == 0: self.exit_long_last = self.exit_long_nex self.boll_length_new = self.boll_length # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.boll_mid # print(f"我是多单,exitlast:{self.exit_short_last},重置布林中轨参数,止损挂{self.exit_long}:") else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if self.am.close[-1] > ( (self.boll_mid + self.boll_mid_new[-1]) / 2): self.exit_long = bar.close_price # print(f"我是多单,收盘价在两个中轨均值上方,以收盘价挂止损单:{self.exit_long}") elif bar.close_price < self.boll_mid: self.exit_long = bar.close_price else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在新中轨上方,以原中轨挂止损单:{self.exit_long}") self.sell(self.exit_long, abs(self.pos), stop=True) elif self.pos < 0: close_short = am.close[-1] < am.close[-2] < am.close[-3] if close_short: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 20) # 计算新的布林带 self.boll_mid_new = am.sma(self.boll_length_new, True) # 仓位是short 时,如果价格上穿新布林中轨 con3 = am.close[-1] > self.boll_mid_new[-1] con4 = am.close[-2] <= self.boll_mid_new[-2] if con3 and con4: self.exit_short_nex = am.close[-1] if self.exit_short_nex < self.exit_short_last or self.exit_short_last == 0: self.exit_short_last = self.exit_short_nex self.boll_length_new = self.boll_length self.exit_short = self.boll_mid else: if self.am.close[-1] < (self.boll_mid + self.boll_mid_new[-1] / 2): self.exit_short = bar.close_price elif bar.close_price > self.boll_mid: self.exit_short = bar.close_price else: self.exit_short = self.boll_mid else: self.exit_short = self.boll_mid self.cover(self.exit_short, abs(self.pos), stop=True) 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. """ self.put_event() pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event() 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 GridStockCtaStrategy(CtaTemplate): """ 期货网格策略逻辑: 1、支持正向合约和反向合约交易逻辑(设置正向和反向标记来转换) 2、网格格数设置50格,多空各25格(参数) 3、网格总限量资金: 3000USDT 或 合约张数 4、网格操作区间: 10% 3、网格跟踪指标 : 首次成交价格 4、网格上限: 网格跟踪指标 * (1 + 网格操作区间) 5、网格下限: 网格跟踪指标 * ( 1 - 网格操作区间) 6、网格步进 :( 网格上限 - 网格下限 ) / 网格数量 7、仓位单元 : 网格总限量 / 网格数量 8、网格启动、停止开关:振幅超过百分比例,网格暂时停止,等待8小时后重新启动 """ author = "yunya" open_window = 2 xminute_window = 5 xhour_window = 1 position_proportion = 1 # 每次加仓比例 grid_amount = 20 # 网格最大量 grid_usdt_size = 10 # 首次使用多少USDT购买币 grid_usdt_capital = 1000 # 网格最多使用的资金量USDT grid_buy_price = 0.2 # 网格距离 grid_sell_price = 0.25 pay_up = 2 # 偏移pricetick buy_callback = 2 # 买入回调幅度 sell_callback = 2 # 卖出回调幅度 grid_amplitude = 5 # 振幅超过比例停止策略8小时 stop_time = 8 # 策略暂停时间 # active_orderids = set() # 保存不重复的订单号 price_change = 0 # 网格基准线(每次成交价) current_grid = 0 max_target = 0 # 当前网格最大最 current_volume = 0 # 当前下单币的数量 buy_benchmark = 0 sell_benchmark = 0 buy_price = 0 # 买入成交价 sell_price = 0 # 平仓成交价 grid_usdt_volume = 0 cumulative_usdt_volume = 0 # 累计使用金额 grid_count = 0 # 网格次数 intra_trade_high = 0 # 最高价 trade_high = 0 last_trade_high = 0 intra_trade_low = 0 # 最低价 trade_low = 0 last_trade_low = 0 amplitude = 0 # 振幅 tick_price = 0 amplitude_inited = False # 振幅标签 time_stop = 0 # 计算得到的重新启动时间 parameters = [ "open_window", "xminute_window", "xhour_window", "position_proportion", "grid_amount", "grid_usdt_size", "grid_usdt_capital", "grid_buy_price", "grid_sell_price", "pay_up", "buy_callback", "sell_callback", "grid_amplitude", "stop_time", ] variables = [ "price_change", "current_grid", "max_target", "current_volume", "buy_benchmark", "sell_benchmark", "buy_price", "sell_price", "grid_usdt_volume", "cumulative_usdt_volume", "grid_count", "intra_trade_high", "trade_high", "last_trade_high", "intra_trade_low", "trade_low", "last_trade_low", "amplitude", "tick_price", "amplitude_inited", "time_stop", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_open = BarGenerator(self.on_bar, self.open_window, self.on_open_bar) self.am_open = ArrayManager() self.bg_minute = BarGenerator(self.on_bar, self.xminute_window, self.on_mintue_bar) self.am_minute = ArrayManager() self.bg_xhour = BarGenerator(self.on_bar, self.xhour_window, self.on_xhour_bar, Interval.HOUR) self.am_xhour = ArrayManager() # 计算每次使用资金量 self.cumulative_usdt_volume = 0 self.grid_usdt_volume = 0 self.amplitude = 0 self.tick_price = 0 # self.active_orderids = set() 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_open.update_tick(tick) def on_bar(self, bar: BarData): """""" self.bg_open.update_bar(bar) self.bg_minute.update_bar(bar) self.bg_xhour.update_bar(bar) def on_open_bar(self, bar: BarData): """""" self.am_open.update_bar(bar) if not self.am_open.inited: return self.cancel_all() # 判断 休眠时间 if self.amplitude_inited: if bar.datetime > self.time_stop: self.amplitude_inited = False return # 根据网格次数加仓 , 根据USDT量和价格计算出可购买的币数量 if self.position_proportion > 0 or self.grid_count > 0: self.grid_usdt_volume = self.grid_usdt_size * ( 1 + (self.position_proportion / 100) * self.grid_count) else: self.grid_usdt_volume = self.grid_usdt_size self.current_volume = self.grid_usdt_volume / bar.close_price self.write_log( f"使用 {self.grid_usdt_volume} 枚USDT,可购买 {self.current_volume} 枚币") self.tick_price = self.get_pricetick() if not self.pos: """ 1、如果空仓,以当前价格买入一份做为底仓 2、总网格次数减一 """ msg = f"tick_price:{self.tick_price}" self.write_log(msg=msg) buy_price = bar.close_price - self.tick_price * self.pay_up self.buy(buy_price, self.current_volume) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.grid_count += 1 self.cumulative_usdt_volume += self.grid_usdt_volume else: if bar.close_price < self.buy_benchmark: """ 当前收盘价低于下个网格买入价格时,判断买入时机: 1、价格在上次买入后,中间没有卖出的过程, 2、 """ if self.cumulative_usdt_volume < self.grid_usdt_capital: """ 买在最低位 """ self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.trade_low = self.intra_trade_low * ( 1 + self.buy_callback / 100) if self.trade_low <= self.buy_benchmark: if self.last_trade_low > 0: self.last_trade_low = min(self.trade_low, self.last_trade_low) else: self.last_trade_low = self.trade_low if bar.close_price <= self.last_trade_low: self.buy_price = self.last_trade_low else: self.buy_price = bar.close_price + self.tick_price * self.pay_up # 加价保证成交 self.buy(self.buy_price, self.current_volume) self.grid_count += 1 self.cumulative_usdt_volume += self.grid_usdt_volume self.last_trade_low = self.trade_low elif bar.close_price > self.sell_benchmark: if self.pos > 0: """ 卖在最高位 """ self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price self.trade_high = self.intra_trade_high * ( 1 - self.sell_callback / 100) if self.trade_high >= self.sell_benchmark: if self.last_trade_high > 0: self.last_trade_high = max(self.trade_high, self.last_trade_high) else: self.last_trade_high = self.trade_high if bar.close_price >= self.last_trade_high: self.sell_price = self.last_trade_high else: self.sell_price = bar.close_price - self.tick_price * self.pay_up # 判断 最后一次全部卖完 if self.pos > self.current_volume * 1.2: self.cover(self.sell_price, abs(self.current_volume)) self.grid_count -= 1 self.cumulative_usdt_volume -= self.grid_usdt_volume else: self.cover(self.sell_price, abs(self.pos)) self.grid_count -= 1 self.cumulative_usdt_volume -= self.grid_usdt_volume # 更新图形界面 self.put_event() def on_mintue_bar(self, bar: BarData): """ :return: """ self.am_minute.update_bar(bar) if not self.am_minute.inited: return # 计算振幅 self.amplitude = (bar.high_price - bar.low_price) / bar.high_price # 如果振幅超过指定值,策略撤掉所有挂单,并且进入休眠状态 if self.amplitude > self.grid_amplitude / 100: self.amplitude_inited = True self.time_stop = bar.datetime + datetime.timedelta( hours=self.stop_time) self.write_log( f"当前市场波动较大," f"振幅为:{self.amplitude},超过设置值,策略进入休眠," f"休眠到:{self.time_stop.strftime('%Y-%m-%d %H:%M:%S')}时重新启动策略") def on_xhour_bar(self, bar: BarData): """ :return: """ self.am_xhour.update_bar(bar) if not self.am_xhour.inited: return pass def on_order(self, order: OrderData): """ Callback of new order data update. """ pass # # 保存活动委托的委托号 # if order.is_active(): # self.active_orderids.add(order.vt_orderid) # # 移除已结束(撤单、全成)委托的委托号 # elif order.vt_orderid in self.active_orderids: # self.active_orderids.remove(order.vt_orderid) # # self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.price_change = trade.price # 成交最高价 else: self.price_change = trade.price # 计算当前网格买入价格和卖出价格 self.buy_benchmark = self.price_change * (1 - self.grid_buy_price) self.sell_benchmark = self.price_change * (1 + self.grid_sell_price) self.sync_data() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class ZZ500Strategy(CtaTemplate): # 参考文档: https://www.doc88.com/p-5748746646083.html # TODO: 对参数调优之后再做指标共振平滑处理看效果如何 author = "digu" score_bull = 4 # 各指标得分和,超过阈值之后才发出买入信号 score_bear = 3 # 各指标得分和,低于阈值之后才发出卖出信号 pct_cnt_low = 30 # 上涨股票占比 pct_cnt_high = 90 pct_ma60_low = 40 pct_ma60_high = 90 cnt_8ma_low = 3 cnt_8ma_high = 5 ds_tushare = DataServiceTushare() c1 = 0 c2 = 0 c3 = 0 c4 = 0 c5 = 0 c6 = 0 parameters = [ "score_bull", "score_bear", "pct_cnt_low", "pct_cnt_high", "pct_ma60_low", "pct_ma60_high", "cnt_8ma_low", "cnt_8ma_high" ] 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=500) self.lst_turnover_rate_f = list() # 保存zz500的历史流通盘换手率 self.deque_quantile_20 = deque() self.pct_cnt_score_pre = 0 # 保存前一天的上涨股占比得分 self.cnt_8ma_score_pre = 0 # 保存前一天的8ma得分 self.ma_bull_score_pre = 0 # 保存前一天的均线多空得分 self.rsi_score_pre = 0 # 保存前一天的rsi得分 self.turnover_rate_f_score_pre = 0 # 保存前一天的流通盘换手率得分 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") 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. """ # TODO 获取zz500的相关信息 info_zz500 = self.ds_tushare.get_zz500( '000905_SH', time_to_str(bar.datetime, '%Y%m%d')) if info_zz500 is None: LOG.info('zz500 None date: %s' % time_to_str(bar.datetime, '%Y%m%d')) return self.lst_turnover_rate_f.append(info_zz500['turnover_rate_f']) arr_turnover_rate_f = np.array(self.lst_turnover_rate_f) arr_turnover_rate_f.sort() idx_turnover_rate_f = np.argwhere( arr_turnover_rate_f > info_zz500['turnover_rate_f'] - 0.0000001)[0] quantile_turnover_rate_f = idx_turnover_rate_f / arr_turnover_rate_f.size if len(self.deque_quantile_20) < 20: self.deque_quantile_20.append(quantile_turnover_rate_f) else: self.deque_quantile_20.popleft() self.deque_quantile_20.append(quantile_turnover_rate_f) am = self.am am.update_bar(bar) if not am.inited: return # 判断当日上涨股票数目比例 pct_cnt = (info_zz500['stk_cnt_up'] * 100.0) / ( info_zz500['stk_cnt_up'] + info_zz500['stk_cnt_down']) if pct_cnt > self.pct_cnt_high: pct_cnt_score = 1 elif pct_cnt < self.pct_cnt_low: pct_cnt_score = 0 else: pct_cnt_score = self.pct_cnt_score_pre self.pct_cnt_score_pre = pct_cnt_score # 判断大于ma60强势股票数目比例 pct_ma60 = (info_zz500['stk_cnt_ma60_up'] * 100.0) / ( info_zz500['stk_cnt_ma60_up'] + info_zz500['stk_cnt_ma60_down']) if pct_ma60 < self.pct_ma60_low or pct_ma60 > self.pct_ma60_high: pct_ma60_score = 0 else: pct_ma60_score = 1 # 判断8ma指标 cnt_ma = 0 cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[ 'ma_5'] else cnt_ma cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[ 'ma_10'] else cnt_ma cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[ 'ma_20'] else cnt_ma cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[ 'ma_30'] else cnt_ma cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[ 'ma_60'] else cnt_ma cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[ 'ma_120'] else cnt_ma cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[ 'ma_250'] else cnt_ma cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[ 'ma_500'] else cnt_ma if cnt_ma > self.cnt_8ma_high: cnt_8ma_score = 1 elif cnt_ma < self.cnt_8ma_low: cnt_8ma_score = 0 else: cnt_8ma_score = self.cnt_8ma_score_pre self.cnt_8ma_score_pre = cnt_8ma_score # 判断均线多空排列指标 if info_zz500['ma_30'] > info_zz500['ma_20'] and info_zz500[ 'ma_20'] > info_zz500['ma_10']: ma_bull_score = 0 elif info_zz500['ma_10'] > info_zz500['ma_20'] and info_zz500[ 'ma_20'] > info_zz500['ma_30']: ma_bull_score = 1 else: ma_bull_score = self.ma_bull_score_pre self.ma_bull_score_pre = ma_bull_score # 判断平滑相对强弱指标MA(RSI(20), 20) arr_rsi_20 = self.am.rsi(20, array=True)[-20:] rsi_20_mean = np.mean(arr_rsi_20) rsi_20_std = np.std(arr_rsi_20) if arr_rsi_20[-1] > rsi_20_mean + rsi_20_std: rsi_score = 1 elif arr_rsi_20[-1] < rsi_20_mean - rsi_20_std: rsi_score = 0 else: rsi_score = self.rsi_score_pre self.rsi_score_pre = rsi_score # 判断A股换手率指标(历史分位数q)得分 quantile_20_mean = np.mean(np.array(self.deque_quantile_20)) quantile_20_std = np.std(np.array(self.deque_quantile_20)) if quantile_turnover_rate_f > quantile_20_mean + quantile_20_std: turnover_rate_f_score = 1 elif quantile_turnover_rate_f < quantile_20_mean - quantile_20_std: turnover_rate_f_score = 0 else: turnover_rate_f_score = self.turnover_rate_f_score_pre self.turnover_rate_f_score_pre = turnover_rate_f_score ZZ500Strategy.c1 += pct_cnt_score ZZ500Strategy.c2 += pct_ma60_score ZZ500Strategy.c3 += cnt_8ma_score ZZ500Strategy.c4 += ma_bull_score ZZ500Strategy.c5 += rsi_score ZZ500Strategy.c6 += turnover_rate_f_score score = pct_cnt_score + pct_ma60_score + cnt_8ma_score + ma_bull_score + rsi_score + turnover_rate_f_score flag_buy = True if score > self.score_bull else False flag_sell = True if score < self.score_bear else False if flag_buy: if self.pos == 0: self.cancel_all() self.buy(bar.close_price, 1) # self.buy(bar.close_price, 1, True) elif flag_sell: if self.pos > 0: self.cancel_all() self.sell(bar.close_price, 1) # self.sell(bar.close_price, 1, 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 DudlThrustKkStrategy(CtaTemplate): """""" author = "yunyu" xminute_window = 1 rolling_period = 70 upper_open = 0.2 lower_open = 0.2 cci_window = 30 keltner_window = 24 keltner_dev = 1 fixed_size = 1 cci_value = 0 exit_kk_up = 0 exit_kk_down = 0 dualthrust_up = 0 dualthrust_down = 0 ask = 0 bid = 0 parameters = [ "xminute_window", "rolling_period", "upper_open", "lower_open", "cci_window", "keltner_window", "keltner_dev", "fixed_size", ] variables = [ "dualthrust_up", "dualthrust_down", "cci_value", "exit_kk_up", "exit_kk_down", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(on_bar=self.on_bar, window=self.xminute_window, on_window_bar=self.on_min_bar, interval=Interval.MINUTE) 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) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_min_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am.update_bar(bar) self.cancel_all() if not self.am.inited: return self.dualthrust_up, self.dualthrust_down = self.dualthrust( self.am.high, self.am.low, self.am.close, self.am.open, self.rolling_period, self.upper_open, self.lower_open) self.cci_value = self.am.cci(self.cci_window) print(self.cci_value) self.keltner_up, self.keltner_down = self.am.keltner( self.keltner_window, self.keltner_dev) if self.pos == 0: if self.cci_value > 0: self.buy(self.dualthrust_up, self.fixed_size, True) elif self.cci_value < 0: self.short(self.dualthrust_down, self.fixed_size, True) elif self.pos > 0: self.sell(self.exit_kk_down, self.fixed_size, True) elif self.pos < 0: self.cover(self.exit_kk_up, self.fixed_size, True) self.put_event() 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. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass # self.put_event() def market_order(self): """""" pass # self.buy(self.last_tick.limit_up, 1) # self.write_log("执行市价单测试") def limit_order(self): """""" pass # self.buy(self.last_tick.limit_down, 1) # self.write_log("执行限价单测试") def stop_order(self): """""" pass # self.buy(self.last_tick.ask_price_1, 1, True) # self.write_log("执行停止单测试") def dualthrust(self, high, low, close, open, n, k1, k2): """ :param high: :param low: :param close: :return: """ #计算N日最高价的最高价,收盘价的最高价、最低价,最低价的最低价 hh = high[-n:].max() lc = close[-n:].min() hc = close[-n:].max() ll = low[-n:].min() #计算range,上下轨的距离前一根K线开盘价的距离 range = max(hh - lc, hc - ll) up = open[-2] + k1 * range down = open[-2] - k2 * range return up, down
class MultiTimeframeStrategyHNTest(CtaTemplate): """""" author = "Huang Ning" bar_window1 = 5 bar_window2 = 15 rsi_signal = 20 rsi_window = 14 fast_window = 12 slow_window = 20 fixed_size = 1 pricetick_multiplier1 = 0.2 pricetick_multiplier2 = 0 rsi_value = 0 rsi_long = 0 rsi_short = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 parameters = [ "bar_window1", "bar_window2", "rsi_signal", "rsi_window", "fast_window", "slow_window", "fixed_size", "pricetick_multiplier1", "pricetick_multiplier2" ] variables = [ "rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.pricetick = self.get_pricetick() self.rsi_long = 50 + self.rsi_signal self.rsi_short = 50 - self.rsi_signal self.bg1 = XminBarGenerator(self.on_bar, self.bar_window1, self.on_Xmin1_bar) self.am1 = ArrayManager() self.bg2 = XminBarGenerator(self.on_bar, self.bar_window2, self.on_Xmin2_bar) self.am2 = ArrayManager() self.buy_vt_orderids = [] self.sell_vt_orderids = [] self.short_vt_orderids = [] self.cover_vt_orderids = [] self.buy_price = 0 self.sell_price = 0 self.short_price = 0 self.cover_price = 0 def on_init(self): """""" 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.bg1.update_tick(tick) def on_bar(self, bar: BarData): """""" # 注意:不同周期K线合成的顺序对结果是有影响的 self.bg1.update_bar(bar) self.bg2.update_bar(bar) if self.buy_vt_orderids: for vt_orderid in self.buy_vt_orderids: self.cancel_order(vt_orderid) self.buy_vt_orderids = self.buy( bar.close_price + self.pricetick * self.pricetick_multilplier2, self.fixed_size, True) elif self.sell_vt_orderids: for vt_orderid in self.sell_vt_orderids: self.cancel_order(vt_orderid) self.sell_vt_orderids = self.sell( bar.close_price - self.pricetick * self.pricetick_multilplier2, self.fixed_size, True) elif self.short_vt_orderids: for vt_orderid in self.short_vt_orderids: self.cancel_order(vt_orderid) self.short_vt_orderids = self.short( bar.close_price - self.pricetick * self.pricetick_multilplier2, self.fixed_size, True) elif self.cover_vt_orderids: for vt_orderid in self.cover_vt_orderids: self.cancel_order(vt_orderid) self.cover_vt_orderids = self.cover( bar.close_price + self.pricetick * self.pricetick_multilplier2, self.fixed_size, True) def on_Xmin1_bar(self, bar: BarData): """""" self.am1.update_bar(bar) if not self.am1.inited: return if not self.ma_trend: return self.rsi_value = self.am1.rsi(self.rsi_window) if self.pos == 0: self.buy_price = bar.close_price + self.pricetick * self.pricetick_multiplier1 self.sell_price = 0 self.short_price = bar.close_price - self.pricetick * self.pricetick_multiplier1 self.cover_price = 0 elif self.pos > 0: self.buy_price = 0 self.sell_price = bar.close_price - self.pricetick * self.pricetick_multiplier1 self.short_price = 0 self.cover_price = 0 else: self.buy_price = 0 self.sell_price = 0 self.short_price = 0 self.cover_price = bar.close_price + self.pricetick * self.pricetick_multiplier1 if self.pos == 0: if not self.buy_vt_orderids: if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy(self.buy_price, self.fixed_size, True) self.buy_price = 0 else: for vt_orderid in self.buy_vt_orderids: self.cancel_order(vt_orderid) if not self.short_vt_orderids: if self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(self.short_price, self.fixed_size, True) self.short_price = 0 else: for vt_orderid in self.short_vt_orderids: self.cancel_order(vt_orderid) elif self.pos > 0: if not self.sell_vt_orderids: if self.ma_trend < 0 or self.rsi_value < 50: self.sell(self.sell_price, abs(self.pos), True) self.sell_price = 0 else: for vt_orderid in self.sell_vt_orderids: self.cancel_order(vt_orderid) else: if not self.cover_vt_orderids: if self.ma_trend > 0 or self.rsi_value > 50: self.cover(self.cover_price, abs(self.pos), True) self.cover_price = 0 else: for vt_orderid in self.cover_vt_orderids: self.cancel_order(vt_orderid) def on_Xmin2_bar(self, bar: BarData): """""" self.am2.update_bar(bar) if not self.am2.inited: return self.fast_ma = self.am2.sma(self.fast_window) self.slow_ma = self.am2.sma(self.slow_window) if self.fast_ma > self.slow_ma: self.ma_trend = 1 elif self.fast_ma < self.slow_ma: self.ma_trend = -1 else: self.ma_trend = 0 def on_stop_order(self, stop_order: StopOrder): """""" if stop_order.status == StopOrderStatus.WAITING: return for buf_orderids in [ self.buy_vt_orderids, self.sell_vt_orderids, self.short_vt_orderids, self.cover_vt_orderids ]: if stop_order.stop_orderid in buf_orderids: buf_orderids.remove(stop_order.stop_orderid)
class AtrStop_Ut(CtaTemplate): """""" author = "yunya" atrstop_window = 46 open_window = 5 nloss_singnal = 2.7 trailing_tax = 2.0 risk_level = 5000 exit_dc_length = 50 atr_length = 30 atrstop_entry = 0 current_atr_stop = 0.0 last_atr_stop = 0.0 intra_trade_high = 0 intra_trade_low = 0 nloss_array = 0.0 long_stop = 0 short_stop = 0 trading_size = 0 exit_down = 0 exit_up = 0 ask = 0 bid = 0 atr_value = 0 count = 0 parameters = [ "atrstop_window", "open_window", "nloss_singnal", "trailing_tax", "risk_level", "exit_dc_length", "atr_length" ] variables = [ "atrstop_entry", "current_atr_stop", "last_atr_stop", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "exit_down", "exit_up", "trading_size", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.atr_stop_array = np.zeros(10) self.bg_xmin = NewBarGenerator(self.on_bar, window=self.atrstop_window, on_window_bar=self.on_xmin_bar, interval=Interval.MINUTE) self.am_xmin = ArrayManager() self.bg_5min = BarGenerator(self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar) self.am_5min = ArrayManager(self.exit_dc_length * int(self.atr_length / self.open_window) + 10) self.inited_atr_stop = False def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(10) # self.put_event() def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动。。") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止。。") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_5min.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xmin.update_bar(bar) self.bg_5min.update_bar(bar) def on_5min_bar(self, bar: BarData): self.cancel_all() self.am_5min.update_bar(bar) if not self.am_5min.inited or not self.am_xmin.inited: return if self.atr_stop_array[-3] == 0: return self.exit_up, self.exit_down = self.am_5min.donchian( self.exit_dc_length * int(self.atr_length / self.open_window)) # print(f"dc上轨:{self.exit_up},下轨:{self.exit_down}") if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.atrstop_entry > 0: self.buy(self.current_atr_stop, self.trading_size, True) elif self.atrstop_entry < 0: self.short(self.current_atr_stop, self.trading_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) long_high = self.intra_trade_high * \ (1 - self.trailing_tax / 100) self.long_stop = max(self.exit_down, long_high) self.sell(self.long_stop, abs(self.pos), True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_low = self.intra_trade_low * \ (1 + self.trailing_tax / 100) self.short_stop = min(self.exit_up, short_low) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xmin_bar(self, bar: BarData): """""" am_xmin = self.am_xmin am_xmin.update_bar(bar) self.atr_stop_array[:-1] = self.atr_stop_array[1:] if not am_xmin.inited: return # 计算轨道线 nloss self.nloss_array = am_xmin.atr(30, array=True) * self.nloss_singnal # 计算轨道线 self.atr_stop_array = self.atrstop(am_xmin.close, self.atr_stop_array, self.nloss_array) # 初始化 atr_stop_array 保证前三个有值 if self.count < 4: self.count += 1 return self.current_atr_stop = self.atr_stop_array[-1] self.last_atr_stop = self.atr_stop_array[-2] current_bar = self.am_xmin.close[-1] if self.current_atr_stop > self.last_atr_stop and current_bar > self.current_atr_stop: self.atrstop_entry = 1 elif self.current_atr_stop < self.last_atr_stop and current_bar < self.current_atr_stop: self.atrstop_entry = -1 else: self.atrstop_entry = 0 if self.pos == 0: self.atr_value = self.am_xmin.atr(self.atr_length) self.trading_size = max(int(self.risk_level / self.atr_value), 1) self.sync_data() self.put_event() def on_trade(self, trade: TradeData): """ 有成交时 Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ 订单更新回调 Callback of new order data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event() def atrstop(self, close, atrstop, nlossatr): # 计算轨道线 if (close[-1] > atrstop[-2]) and (close[-2] > atrstop[-2]): atrstop[-1] = max(atrstop[-2], close[-1] - nlossatr[-1]) elif (close[-1] < atrstop[-2]) and (close[-2] < atrstop[-2]): atrstop[-1] = min(atrstop[-2], close[-1] + nlossatr[-1]) elif (close[-1] > atrstop[-2]): atrstop[-1] = (close[-1] - nlossatr[-1]) else: atrstop[-1] = (close[-1] + nlossatr[-1]) return atrstop
class DoubleRsiAtr(CtaTemplate): """""" author = "yiran" s_window = 5 l_window = 15 atr_window = 20 atr_multiplier = 0.05 rsi_window = 11 long_threshold_l_window = 50 long_threshold_s_window = 80 exit_return = 0.02 exit_loss = 0.02 exit_return_soft_long = -0.1 exit_loss_soft_long = -0.2 exit_return_soft_short = 0.2 exit_loss_soft_short = 0.1 fixed_size = 1 start_time = time(hour=10) exit_time = time(hour=14, minute=55) long_order_record = [] short_order_record = [] rsi_value_l_window = -9999 rsi_value_s_window = -9999 atr_value = 0 position_hold = 0 long_entered = False short_entered = False parameters = [ 's_window', 'l_window', 'atr_window', 'atr_multiplier', 'exit_return_soft_long', 'exit_loss_soft_long', "rsi_window", 'exit_return_soft_short', 'exit_loss_soft_short', "long_threshold_l_window", "long_threshold_s_window", 'exit_return', 'exit_loss', "fixed_size" ] variables = ["rsi_value_l_window ", "rsi_value_s_window", "ma_trend"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long_l = self.long_threshold_l_window self.rsi_long_s = self.long_threshold_s_window self.rsi_short_l = 100 - self.long_threshold_l_window self.rsi_short_s = 100 - self.long_threshold_s_window self.bg5 = BarGenerator(self.on_bar, self.s_window, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, self.l_window, self.on_15min_bar) self.am15 = ArrayManager() self.long_order_record = [] self.short_order_record = [] self.atr_value_array = np.array([]) self.atr_profit_exit_recorder = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return self.rsi_value_s_window = self.am5.rsi(self.rsi_window) self.atr_value = self.am5.atr(self.atr_window) if self.long_threshold_l_window != -9999: self.long_entered = (self.rsi_value_s_window > self.rsi_long_s) and (self.rsi_value_l_window > self.rsi_long_l) self.short_entered = ( self.rsi_value_s_window < self.rsi_short_s) and ( self.rsi_value_l_window < self.rsi_short_l) else: return if self.start_time <= bar.datetime.time() < self.exit_time: if self.pos == 0: self.position_hold = 0 if self.long_entered: self.buy(bar.close_price + 5, self.fixed_size) self.long_order_record.append(bar.close_price + 5) elif self.short_entered: self.short(bar.close_price - 5, self.fixed_size) self.short_order_record.append(bar.close_price - 5) elif self.pos > 0: self.position_hold += 1 buy_order_price = self.long_order_record[-1] initial_profit_exit_price = buy_order_price * ( 1 + self.exit_return) # 波动变大+持仓周期变长,会使得止盈的点上移 moving_profit_exit_price = buy_order_price * ( 1 + self.exit_return_soft_long ) + self.atr_value * self.atr_multiplier * self.position_hold initial_loss_exit_price = buy_order_price * (1 - self.exit_loss) # 波动变大+持仓周期变长,会使得止损的点上移 moving_loss_exit_price = buy_order_price * ( 1 + self.exit_loss_soft_long ) + self.atr_value * self.atr_multiplier * self.position_hold if initial_profit_exit_price < moving_profit_exit_price: self.atr_profit_exit_recorder.append((1, bar.datetime)) else: self.atr_profit_exit_recorder.append((0, bar.datetime)) if bar.close_price >= max(initial_profit_exit_price, moving_profit_exit_price): self.sell(bar.close_price * 0.99, abs(self.pos)) elif bar.close_price <= max(initial_loss_exit_price, moving_loss_exit_price): self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.position_hold += 1 sell_order_price = self.short_order_record[-1] #初始的盈利要求比较低即空头平仓的价格比较高 initial_profit_exit_price = sell_order_price * ( 1 - self.exit_return) # 随着持仓时间推移和波动率变大,对应盈利方向上的头寸止盈要求变高,即空头平仓价格下移 moving_profit_exit_price = sell_order_price * ( 1 + self.exit_return_soft_short ) - self.atr_value * self.atr_multiplier * self.position_hold initial_loss_exit_price = sell_order_price * (1 + self.exit_loss) # 随着持仓时间推移和波动率变大,对应亏损方向上的头寸的平仓价格上升,即空头平仓价格上升 moving_loss_exit_price = sell_order_price * ( 1 + self.exit_loss_soft_short ) - self.atr_value * self.atr_multiplier * self.position_hold if bar.close_price >= min(initial_loss_exit_price, moving_loss_exit_price): self.cover(bar.close_price * 1.01, abs(self.pos)) elif bar.close_price <= min(initial_profit_exit_price, moving_profit_exit_price): self.cover(bar.close_price * 1.01, abs(self.pos)) # 通过设置合成Bar Data的周期可以使得持仓过夜 elif bar.datetime.time() > self.exit_time: if self.pos > 0: self.sell(bar.close_price * 0.99, abs(self.pos)) elif self.pos < 0: self.cover(bar.close_price * 1.01, abs(self.pos)) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if not self.am15.inited: return self.rsi_value_l_window = self.am15.rsi(self.rsi_window) def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class 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)