def generate_3mindata(self, am:ArrayManager, 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(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 = am.kdj() deg1 = calc_regress_deg(am.close[offset : offset_m], False) deg2 = calc_regress_deg(am.close[offset_m :], False) deg3 = calc_regress_deg(am.close[-10 :], False) deg_full = calc_regress_deg(am.close[offset :], False) wave = self.wave(am.close[-30:]) wave_r_sum = np.sum(wave["range"]) macd=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=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=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(am.close[-20:-10], False),2), deg10_0=round(deg3,2), deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2), atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(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=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(), range_sum=np.sum(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]), ma_info=list(map(lambda x:x["std"], self.ma_info[-1:])), wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(am.atr(20, array=True,length=240)[-200:]) )) return calc_data
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)
def generate_data(self, am: ArrayManager, bar: BarData): offset = -self.offset offset_m = int(offset / 2) std_val3 = np.std(np.array(am.range[-30:-10])) kdj_val = am.kdj() has_kdj_recore = False k = kdj_val["k"] d = kdj_val["d"] j = kdj_val["j"] if (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \ (k[-1] < 25 and d[-1] < 25 and j[-1] < 75): if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \ or \ (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]): has_kdj_recore = True t = bar.datetime self.kdj_record.append( (t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3), round(j[-1], 3))) deg1 = calc_regress_deg(am.close[offset:offset_m], False) deg2 = calc_regress_deg(am.close[offset_m:], False) deg3 = calc_regress_deg(am.close[-10:], False) deg_full = calc_regress_deg(am.close[offset:], False) macd = 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=am.cci(20), rsi=am.rsi(20), adx=am.adx(20), boll=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(am.close[-20:-10], False), 2), deg30_15=round(calc_regress_deg(am.close[-30:-15], False), 2), deg15_0=round(calc_regress_deg(am.close[-15:], False), 2), deg_f=round(deg_full, 2), deg30_10=round(calc_regress_deg(am.close[-30:-10], False), 2), deg10_0=round(deg3, 2), atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3), atr_40=round(am.atr(40, length=42), 3), time=bar.datetime, price=bar.close_price, mean_std=np.mean(self.std_range.data[-5:]), vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(), range_sum=np.sum(am.range[-5:]), pattern=list( map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())), atr_mean=np.mean(am.atr(20, array=True, length=240)[-200:]), )) if self.ma_info.info.index.size >= 31: ma5 = self.ma_info.info[5][-31:] x = AnalyseWave(ma5) calc_data["ma5_info"] = x.optimize ma10 = self.ma_info.info[10][-31:] x = AnalyseWave(ma10) calc_data["ma10_info"] = x.optimize return calc_data
class DudlThrustEmaPositionStrategy(CtaTemplate): """""" author = "yunyu" open_window = 5 xminute_window = 30 rolling_period = 70 upper_open = 0.45 lower_open = 0.45 cci_length = 5 ema_length = 60 position_atr_length = 6 risk_level = 1000 # fixed_size = 1 trading_size = 0 atr_value = 0 up = 0 down = 0 current_ema = 0 last_ema = 0 ema_mid = 0 ema_new_value = 0 ema_length_new = 0 cci_value = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 current_close = 0 last_close = 0 front_close = 0 exit_long = 0 exit_short = 0 ask = 0 bid = 0 parameters = [ "open_window", "xminute_window", "rolling_period", "upper_open", "lower_open", "cci_length", "ema_length", "position_atr_length", "risk_level" ] variables = [ "trading_size", "up", "down", "current_ema", "last_ema", "ema_mid", "ema_new_value", "ema_length_new", "cci_value", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", "current_close", "last_close", "front_close", "exit_long", "exit_short", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_open = BarGenerator(on_bar=self.on_bar, window=self.open_window, on_window_bar=self.on_open_bar) self.am_open = ArrayManager() self.bg = NewBarGenerator(on_bar=self.on_bar, window=self.xminute_window, on_window_bar=self.on_xmin_bar) self.am = ArrayManager(self.rolling_period + 50) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) self.bg_open.update_bar(bar) def on_open_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am_open.update_bar(bar) if not self.am.inited or not self.am_open.inited: return if self.pos == 0: self.cci_value = self.am.cci(self.cci_length) # 判断数据是否正常,如果atr 计算结果正常,才计算仓位,避免下单时下出不正常的数量 self.atr_value = self.am.atr(self.position_atr_length) if self.atr_value == 0: return self.trading_size = max(int(self.risk_level / self.atr_value), 1) if self.cci_value > 0: self.buy(self.up, self.trading_size, True) elif self.cci_value < 0: self.short(self.down, self.trading_size, True) elif self.pos > 0: con1 = bar.close_price < self.current_ema con2 = bar.close_price >= self.last_ema if con1 and con2: self.exit_long_nex = bar.close_price # 保存当前收盘价 if self.exit_long_last == 0 or self.exit_long_nex > self.exit_long_last: self.exit_long_last = self.exit_long_nex self.ema_length_new = self.ema_length self.exit_long = self.ema_mid else: if bar.close_price > ( (self.ema_mid + self.current_ema) / 2): self.exit_long = bar.close_price elif bar.close_price < self.ema_mid: self.exit_long = bar.close_price else: self.exit_long = self.ema_mid else: self.exit_long = self.ema_mid self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: con1 = bar.close_price > self.current_ema con2 = bar.close_price <= self.last_ema if con1 and con2: self.exit_short_nex = bar.close_price if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last: self.exit_short_last = self.exit_short_nex self.ema_length_new = self.ema_length self.exit_short = self.ema_mid else: if bar.close_price < (self.ema_mid + self.current_ema / 2): self.exit_short = bar.close_price elif bar.close_price < self.ema_mid: self.exit_short = bar.close_price else: self.exit_short = self.ema_mid else: self.exit_short = self.ema_mid self.cover(self.exit_short, abs(self.pos), True) self.put_event() self.sync_data() def on_xmin_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am.update_bar(bar) if not self.am.inited: return # 计算海龟 上轨,下轨 high_max = self.am.high[-self.rolling_period:].max() close_min = self.am.close[-self.rolling_period:].min() close_max = self.am.close[-self.rolling_period:].max() low_min = self.am.low[-self.rolling_period:].min() hc = high_max - close_min cl = close_max - low_min dual = max(hc, cl) self.up = self.am.open[-2] + dual * self.upper_open self.down = self.am.open[-2] - dual * self.upper_open # print(f"up:{self.up},{self.down}") self.current_close = self.am.close[-1] self.last_close = self.am.close[-2] self.front_close = self.am.close[-3] if self.pos == 0: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.ema_length_new = self.ema_length elif self.pos > 0: close_long = self.current_close > self.last_close > self.front_close if close_long: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) elif self.pos < 0: close_short = self.current_close < self.last_close < self.front_close if close_short: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) self.ema_mid = self.am.ema(self.ema_length) ema_mid_new = self.am.ema(self.ema_length_new, True) self.current_ema = ema_mid_new[-1] self.last_ema = ema_mid_new[-2] def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass # self.put_event() def market_order(self): """""" pass # self.buy(self.last_tick.limit_up, 1) # self.write_log("执行市价单测试") def limit_order(self): """""" pass # self.buy(self.last_tick.limit_down, 1) # self.write_log("执行限价单测试") def stop_order(self): """""" pass
class 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 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 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 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
def generate_data(self, am:ArrayManager, 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(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 = am.kdj() has_kdj_recore = False k = kdj_val["k"] d = kdj_val["d"] j = kdj_val["j"] if (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \ (k[-1] < 25 and d[-1] < 25 and j[-1] < 75): if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \ or \ (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]): has_kdj_recore = True t = local_to_eastern(bar.datetime.timestamp()) self.kdj_record.append((t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3), round(j[-1], 3))) deg1 = calc_regress_deg(am.close[offset : offset_m], False) deg2 = calc_regress_deg(am.close[offset_m :], False) deg3 = calc_regress_deg(am.close[-10 :], False) deg_full = calc_regress_deg(am.close[offset :], False) wave = self.wave(am.close[-30:]) wave_r_sum = np.sum(wave["range"]) macd=am.macd(20,40, 16) calc_data = (dict( ma_info=self.ma_info[-1:], kdj=[round(kdj_val["k"][-1],2),round(kdj_val["d"][-1],2),round(kdj_val["j"][-1],2)], cci_20=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=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(am.close[-20:-10], False),2), deg30_10=round(calc_regress_deg(am.close[-30:-10], False),2),deg10_0=round(deg3,2), deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2), atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(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=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(), range_sum=np.sum(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(am.atr(20, array=True,length=240)[-200:]), kdj_record=self.kdj_record[-10:], )) if self.ma_info[-1]["ma5"] <= 0.16: calc_data["kdj_key"] = True return calc_data
def reverse2_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}): length = 30 offset1 = -30 offset2 = int(-10) close = am.close deg1 = calc_regress_deg(close[-30:-8], False) deg2 = calc_regress_deg(close[-8:], False) if deg1 > 0 and deg2 > 0 or \ deg1 < 0 and deg2 < 0: return if not (abs(deg1) > 0.15 and abs(deg2) > 0.15 and (abs(deg1) + abs(deg2)) > 0.35) : return close = am.close[-length:] 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 < setting["mid_sign"][0] or mid_pos > setting["mid_sign"][1]: 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] kdj = am.kdj() k = kdj["k"][-1] d = kdj["d"][-1] j = kdj["j"][-1] 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) cci = am.cci(20) ma60 = am.sma(60) if deg2 < 0: # if k < 20 and d < 10 and j < 10: # if kdj[2] < 10: if cci < -100 and bar.close_price < ma60: if self.pos == 0: calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci) return self.short(bar.close_price, 1, type=OrderType.MARKET) elif self.pos > 0: calc_data["trade_close"] = "平多后做空仓,deg={},cci={}".format(deg2, cci) order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET) order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET) return order_id_cover.extend(order_id_buy) else: # if k > 80 and d > 90 and j > 90: # if kdj[2] > 90: if cci > 100 and bar.close_price > ma60: if self.pos == 0: calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci) return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif self.pos < 0: calc_data["trade_close"] = "平空后多仓,deg={},cci={}".format(deg2, cci) order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET) order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET) return order_id_cover.extend(order_id_buy)
class MinuteSuperTurtleStrategy(CtaTemplate): """ 唐安奇通道策略 """ author = "yuya" open_window = 15 entry_window = 28 exit_window = 7 atr_window = 4 cci_window = 10 risk_level = 0.2 trading_size = 0 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 cci_value = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 parameters = [ "open_window", "entry_window", "exit_window", "atr_window", "risk_level", "cci_window" ] variables = [ "entry_up", "entry_down", "exit_up", "exit_down", "trading_size", "atr_value", "cci_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.open_window, self.on_hour_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.bg.update_bar(bar) def on_hour_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.entry_up, self.entry_down = self.am.donchian(self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) self.cci_value = self.am.cci(self.cci_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) if self.atr_value == 0: return # 反向合约的计算方法, atr_risk = talib.ATR(1 / self.am.high, 1 / self.am.low, 1 / self.am.close, self.atr_window)[-1] self.trading_size = max(int(self.risk_level / atr_risk), 1) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 if self.cci_value > 0: self.buy(self.entry_up, self.trading_size, True) elif self.cci_value < 0: self.short(self.entry_down, self.trading_size, True) elif self.pos > 0: sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: cover_price = min(self.short_stop, self.exit_up) self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class TurtleCCIStrategy(CtaTemplate): """基于布林通道的交易策略""" className = 'TurtleCCIStrategy' author = u'ForwardCapital' # 策略参数 turtleWindow = 20 # 通道窗口数 trailingPrcnt = 0.4 # 移动止损百分比 CCIWindow = 14 # 过滤用均线窗口 ma1Window = 10 # 过滤用均线窗口 ma2Window = 20 # 过滤用均线窗口 initDays = 10 # 初始化数据所用的天数 fixedSize = 1 # 每次交易的数量 # 策略变量 periodHigh = 0 # 布林带中轨 periodLow = 0 # 布林带宽度 entryUp = 0 # 开仓上轨 exitUp = 0 # 平仓上轨 CCIFilter = 0 # 均线过滤 CCIFilter1 = 0 # 上一期均线 intraTradeHigh = 0 # 持仓期内的最高点 intraTradeLow = 0 # 持仓期内的最低点 longEntry = 0 # 多头开仓 longExit = 0 # 多头平仓 orderList = [] # 保存委托代码的列表 buyOrderID = None sellOrderID = None shortOrderID = None coverOrderID = None # 参数列表,保存了参数的名称 paramList = [] # 变量列表,保存了变量的名称 varList = [] # 同步列表 syncList = ['pos', 'intraTradeHigh', 'intraTradeLow'] #---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): """Constructor""" super(TurtleCCIStrategy, self).__init__(ctaEngine, setting) self.bm = BarGenerator(self.on_bar, 15, self.onFiveBar) self.am = ArrayManager() #---------------------------------------------------------------------- def on_init(self): """初始化策略(必须由用户继承实现)""" self.write_log(u'策略初始化') # 载入历史数据,并采用回放计算的方式初始化策略数值 self.load_bar(self.initDays) self.put_event() #---------------------------------------------------------------------- def on_start(self): """启动策略(必须由用户继承实现)""" self.write_log(u'策略启动') self.put_event() #---------------------------------------------------------------------- def on_stop(self): """停止策略(必须由用户继承实现)""" self.write_log(u'策略停止') self.put_event() #---------------------------------------------------------------------- def on_tick(self, tick): """收到行情TICK推送(必须由用户继承实现)""" self.bm.update_tick(tick) #---------------------------------------------------------------------- def on_bar(self, bar): """收到Bar推送(必须由用户继承实现)""" self.bm.update_bar(bar) #---------------------------------------------------------------------- def orderIDConvert(self, orderList): if not orderList: return [] else: return orderList[0] #---------------------------------------------------------------------- def onFiveBar(self, bar, lastTick): """收到5分钟K线""" # 保存K线数据 self.am.update_bar(bar) if not self.am.inited or not self.trading: return # 撤销之前发出的尚未成交的委托(包括限价单和停止单) print(u'onFiveBar↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓,datetime:%s' % bar.datetime) # 计算指标数值 self.entryUp = max(self.am.high[-self.turtleWindow:]) self.entryDown = min(self.am.low[-self.turtleWindow:]) self.entryUp = self.bollMid + self.bollStd * self.entryDev self.exitUp = self.bollMid + self.bollStd * self.exitDev ma1 = self.am.sma(self.ma1Window, False) ma2 = self.am.sma(self.ma2Window, False) cci = self.am.cci(self.CCIWindow, True) # 判断是否要进行交易 if not self.buyOrderID or not self.shortOrderID: if self.pos == 0: # 下开仓单 if ma1 > ma2: self.buyOrderID = self.buy(self.entryUp, self.fixedSize, True) self.buyOrderID = self.orderIDConvert(self.buyOrderID) print('None order!!!buyOrderID is : %s ' % self.buyOrderID) if self.buyOrderID: self.orderList.append(self.buyOrderID) else: self.shortOrderID = self.short(self.entryDown, self.fixedSize, True) self.shortOrderID = self.orderIDConvert(self.shortOrderID) print('None order!!!shortOrderID is : %s ' % self.shortOrderID) if self.shortOrderID: self.orderList.append(self.shortOrderID) elif self.pos > 0: # 下平仓单 if cci[-1] < 100 and cci[-2] > 100: # ######此处实盘需要修改发单价格 self.sellOrderID = self.sell(bar.low * 0.9, self.fixedSize) self.sellOrderID = self.orderIDConvert(self.sellOrderID) print('order None!!!sellOrderID is : %s ' % self.sellOrderID) if self.sellOrderID: self.orderList.append(self.sellOrderID) elif self.pos < 0: # 下平仓单 if cci[-1] > -100 and cci[-2] < -100: # ######此处实盘需要修改发单价格 self.coverOrderID = self.cover(bar.high * 0.9, self.fixedSize) self.coverOrderID = self.orderIDConvert(self.coverOrderID) print('order None!!!coverOrderID is : %s ' % self.coverOrderID) if self.coverOrderID: self.orderList.append(self.coverOrderID) else: if self.buyOrderID in self.orderList or self.shortOrderID in self.orderList: self.cancel_all() # 下开仓单 if ma1 > ma2: self.buyOrderID = self.buy(self.entryUp, self.fixedSize, True) self.buyOrderID = self.orderIDConvert(self.buyOrderID) print('buyOrderID is : %s ' % self.buyOrderID) if self.buyOrderID: self.orderList.append(self.buyOrderID) else: self.shortOrderID = self.short(self.entryDown, self.fixedSize, True) self.shortOrderID = self.orderIDConvert(self.shortOrderID) print('shortOrderID is : %s ' % self.shortOrderID) if self.shortOrderID: self.orderList.append(self.shortOrderID) else: if self.pos > 0: # 下平仓单 if cci[-1] < 100 and cci[-2] > 100: # ######此处实盘需要修改发单价格 self.sellOrderID = self.sell(bar.low * 0.9, self.fixedSize) self.sellOrderID = self.orderIDConvert( self.sellOrderID) print('order None!!!sellOrderID is : %s ' % self.sellOrderID) if self.sellOrderID: self.orderList.append(self.sellOrderID) elif self.pos < 0: # 下平仓单 if cci[-1] > -100 and cci[-2] < -100: # ######此处实盘需要修改发单价格 self.coverOrderID = self.cover(bar.high * 0.9, self.fixedSize) self.coverOrderID = self.orderIDConvert( self.coverOrderID) print('order None!!!coverOrderID is : %s ' % self.coverOrderID) if self.coverOrderID: self.orderList.append(self.coverOrderID) elif self.pos == 0: # 下开仓单 if ma1 > ma2: self.buyOrderID = self.buy(self.entryUp, self.fixedSize, True) self.buyOrderID = self.orderIDConvert(self.buyOrderID) print('buyOrderID is : %s ' % self.buyOrderID) if self.buyOrderID: self.orderList.append(self.buyOrderID) else: self.shortOrderID = self.short(self.entryDown, self.fixedSize, True) self.shortOrderID = self.orderIDConvert( self.shortOrderID) print('shortOrderID is : %s ' % self.shortOrderID) if self.shortOrderID: self.orderList.append(self.shortOrderID) # 发出状态更新事件 # self.putEvent() #---------------------------------------------------------------------- def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" pass #---------------------------------------------------------------------- def on_trade(self, trade): """收到成交推送(必须由用户继承实现)""" print(u'成交推送:%s' % trade) self.orderList.remove(trade.tradeID) # 发出状态更新事件 # self.putEvent() #---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" print(u'StopOrder回报,stopOrderID:%s, status:%s' % (so.stopOrderID, so.status)) if so.status == StopOrderStatus.CANCELLED or so.status == StopOrderStatus.TRIGGERED: self.orderList.remove(so.stopOrderID) pass
class Boll_kk_vix_simple_Strategy(CtaTemplate): """ 本策略为反向策略,币本位 Reverse 反向 """ author = "yunya" open_window = 5 xminute_window = 15 com_length = 450 exit_dc_length = 10 fast_sma_length = 45 slow_sma_length = 110 cci_length = 30 cci_exit = 26 sl_multiplier = 8.0 fixed_size = 1 bollkk_ema = 0 bollkk_up = 0 bollkk_down = 0 bollkk_width = 0 cci_vlue = 0 long_stop = 0 short_stop = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 ma_trend = 0 exit_dc_long = 0 exit_dc_short = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "open_window", "xminute_window", "com_length", "fast_sma_length", "slow_sma_length", "cci_length", "cci_exit", "exit_dc_length", "sl_multiplier", "fixed_size", ] variables = [ "bollkk_ema", "bollkk_up", "bollkk_down", "bollkk_width", "cci_vlue", "long_stop", "short_stop", "exit_up", "exit_down", "atr_value", "long_entry", "short_entry", "ma_trend", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_xminute = BarGenerator(on_bar=self.on_bar, window=self.xminute_window, on_window_bar=self.on_xminute_bar, interval=Interval.MINUTE) self.am_xminute = ArrayManager(self.com_length + 10) self.bg = BarGenerator(self.on_bar, self.open_window, self.on_open_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_xminute.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) self.bg_xminute.update_bar(bar) def on_open_bar(self, bar: BarData): """ :param bar: :return: """ # 先使用挂单全撤的粗化订单管理 self.cancel_all() self.am.update_bar(bar) if not self.am_xminute.inited or not self.am.inited: return if self.pos == 0: # 根据布林带宽度动态调整仓位大小 # self.trading_size = max(int(self.risk_level / self.xminute_com_width), 1) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.cci_value > self.cci_exit and self.ma_trend > 0: self.buy(self.bollkk_up, self.fixed_size, True) elif self.cci_value < -self.cci_exit and self.ma_trend < 0: self.short(self.bollkk_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price exit_long_stop = self.intra_trade_high - self.bollkk_width * self.sl_multiplier exit_long_dc = max(exit_long_stop, self.exit_dc_long) self.exit_up = max(exit_long_dc, self.long_stop) self.sell(self.exit_up, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) exit_short_stop = self.intra_trade_low + self.bollkk_width * self.sl_multiplier exit_shout_dc = min(exit_short_stop, self.exit_dc_short) self.exit_down = min(exit_shout_dc, self.short_stop) self.cover(self.exit_down, abs(self.pos), True) self.put_event() self.sync_data() def on_xminute_bar(self, bar: BarData): """ :param bar: :return: """ # x分钟 多策略合合成的通道线 self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return bollkk_ema_value, self.bollkk_up, self.bollkk_down, = self.boll_kk_combination( high=self.am_xminute.high[:-1], close=self.am_xminute.close[:-1], low=self.am_xminute.low[:-1], com_length=self.com_length) # 计算开平信号 self.current_close = self.am_xminute.close[-1] self.last_close = self.am_xminute.close[-2] self.bollkk_ema = bollkk_ema_value[-1] self.bollkk_width = abs(self.bollkk_up - self.bollkk_down) self.cci_value = self.am_xminute.cci(self.cci_length) self.fast_ma = self.am_xminute.sma(self.fast_sma_length) self.slow_ma = self.am_xminute.sma(self.slow_sma_length) if self.fast_ma > self.slow_ma: self.ma_trend = 1 else: self.ma_trend = -1 self.atr_value = self.am_xminute.atr(30) self.exit_dc_short, self.exit_dc_long = self.am_xminute.donchian( self.exit_dc_length) self.sync_data() self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value self.sync_data() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def boll_kk_combination(self, high, close, low, com_length): """ 通过计算收盘价与收盘价均线之间的倍数,来自动调整boll 、kk 的通过宽度 """ # 计算组合均线 bollkk_ema = talib.EMA(close, com_length) # 计算自适布林带 boll_std = talib.STDDEV(close, com_length) boll_dev = abs(close - bollkk_ema) / boll_std boll_up = bollkk_ema + boll_dev * boll_std boll_down = bollkk_ema - boll_dev * boll_std # 计算自适肯特通道 kk_atr = talib.ATR(high, low, close, com_length) kk_dev = abs(close - bollkk_ema) / kk_atr kk_up = bollkk_ema + kk_atr * kk_dev kk_down = bollkk_ema - kk_atr * kk_dev bollkk_up = max(boll_up[-1], kk_up[-1]) bollkk_down = min(boll_down[-1], kk_down[-1]) return bollkk_ema, bollkk_up, bollkk_down,