class TestBar(object): def __init__(self): self.am = ArrayManager(390) self.bg = BarGenerator(self.on_bar, interval=Interval.DAILY) def on_bar(self, bar: BarData): # self.am.update_bar(bar) self.am.update_bar(bar)
class MACDSignal(CtaSignal): """""" def __init__(self, fast_window: int, slow_window: int, signal_period: int, period: int = 30): """""" super().__init__() self.fast_window = fast_window self.slow_window = slow_window self.signal_period = signal_period self.period = period self.bg = BarGenerator(self.on_bar, period, self.on_n_min_bar) self.am = ArrayManager( size=max(self.fast_window, self.slow_window, self.signal_period) + 50) logger.info( f"fast_window, slow_window, signal_period, period=" f"{self.fast_window, self.slow_window, self.signal_period, self.period}" ) 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_n_min_bar(self, bar: BarData): """""" self.am.update_bar(bar) if not self.am.inited: self.set_signal_pos(0) _, _, macd = self.am.macd(self.fast_window, self.slow_window, self.signal_period) if macd < -5: self.set_signal_pos(1) elif macd > 5: self.set_signal_pos(-1) else: # self.set_signal_pos(0) pass
def compute_index_zz500_specifications(self, df): # 注意:所有的数据库数据和列表数据都按照日期的正序排序(从小到大) # 计算zz500指数的技术指标并入库 """ @ 入参:指数k线信息 """ am = ArrayManager(size=600) for ix, row in df.iterrows(): d = row.to_dict() LOG.info(d['trade_date']) d['ts_code'] = d['ts_code'].replace('.', '_') bar = BarData( gateway_name='ctp', symbol=d['ts_code'], exchange=Exchange.SSE, datetime=string_to_datetime(d['trade_date'])) bar.symbol = d['ts_code'] bar.open_price = d['open'] bar.high_price = d['high'] bar.low_price = d['low'] bar.close_price = d['close'] am.update_bar(bar) rsi_20 = am.rsi(20) d['rsi_20'] = rsi_20 try: d['ma_5'] = am.sma(5) except: traceback.print_exc() LOG.error('************************') LOG.error(d['ts_code']) LOG.error(d['trade_date']) LOG.error(bar) d['ma_10'] = am.sma(10) d['ma_20'] = am.sma(20) d['ma_30'] = am.sma(30) d['ma_60'] = am.sma(60) d['ma_120'] = am.sma(120) d['ma_250'] = am.sma(250) d['ma_500'] = am.sma(500) flt = {'trade_date': d['trade_date']} cl_index_zz500 = self.db[CL_INDEX_ZZ500] # cl_index_zz500.replace_one(flt, d, upsert=False) cl_index_zz500.update_one(flt, {'$setOnInsert': d}, upsert=True) # 插入数据时,flt不存在则插入d,存在则不执行
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 RsiSignal(CtaSignal): """""" def __init__(self, rsi_window: int, rsi_level: float): """Constructor""" super().__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 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) rsi_value = self.am.rsi(self.rsi_window) if rsi_value >= self.rsi_long: self.set_signal_pos(1) elif rsi_value <= self.rsi_short: self.set_signal_pos(-1) else: self.set_signal_pos(0)
class MaTrendStrategy(CtaTemplate): author = "用Python的交易员" ma_level = [10, 20, 30, 60, 120] request_order = [] close_order = [] volumn = 0 kdj_record = [] parameters = ["ma_level"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] add_pos = False safe_price = None ma_info = pd.DataFrame() closeout_offset = 0.003 trade_mgr: TradeMgr = None def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(MaTrendStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 1, self.on_1min_bar, tz_info=eastern) self.am = ArrayManager(400) self.am3 = ArrayManager(150) self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar, tz_info=eastern) self.am5 = ArrayManager(100) self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar, tz_info=eastern) self.trade_mgr = TradeMgr(self, setting["capital"], OrderType.MARKET, {}) self.closeout_offset = 0.003 self.clock = ClockManager(datetime.time(hour=9, minute=30), datetime.time(hour=16, minute=0)) 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.offset = 40 self.init_datacreator() def init_datacreator(self): self.data_center = DataCenter(component={ "array_manager_1": self.am, "clock": self.clock }) self.data_creator = { "ma_info": MaInfoCreator(self.data_center), "trend_info": TrendInfoCreator(self.data_center), "ma_dist": MaDistCreator(self.data_center) } self.ma_info = self.data_creator["ma_info"] self.data_center.connect("trend_info", self.on_new_trend) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") 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 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 def closeout_strategy(self, am: ArrayManager, bar: BarData, calc_data): if self.trade_mgr.get_status() == PositionStatus.Short: if bar.close_price > self.closeout_price: calc_data["trade_close"] = "平仓:到达最低价{}".format( self.closeout_price) return self.trade_mgr.cover(bar.close_price) # return self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET, # extra={"reason": "平仓:到达最低价{}".format(self.closeout_price)}) elif self.trade_mgr.get_status() == PositionStatus.Long: if bar.close_price < self.closeout_price: calc_data["trade_close"] = "平仓:到达最低价{}".format( self.closeout_price) return self.trade_mgr.sell(bar.close_price) # return self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET, # extra={"reason": "平仓:到达最低价{}".format(self.closeout_price)}) ''' 检测3个ma闭合,空仓状态时如果小于0.01则标记起点,随后检测4个ma的穿越,计算角度,并买入。 根据时间和升幅进行加仓(急速提升的情况下,3ma的闭合间隙会加大), 3个ma如果遭遇再次闭合,则根据情况卖出 ''' def on_new_trend(self, data): self.trend_context = data["trend_info"] def range_score(self, am: ArrayManager, length): r_data = am.range[-length:] def ma_trend_strategy(self, am: ArrayManager, bar: BarData, calc_data): context = self.trend_context if context == None: return deg = context["deg"] data = context["data"] sign = context["sign"] if self.pos == 0: ma120 = self.ma_info.info[120] deg120 = calc_regress_deg(ma120[-5:], False) if deg < 0: calc_data["trade_open"] = "开空,deg={}".format(deg) sign() ratio = 0.2 if deg120 < 0 else 0.1 return self.trade_mgr.short(bar.close_price, ratio, {}) elif deg > 0: calc_data["trade_open"] = "开多,deg={}".format(deg) sign() ratio = 0.2 if deg120 > 0 else 0.1 return self.trade_mgr.buy(bar.close_price, ratio, {}) def trend_reverse_close(self, am: ArrayManager, bar: BarData, calc_data): if self.trade_mgr.get_status() != PositionStatus.Empty: data = self.ma_info.info[-60:] length = len(data) close = (data[10] + data[20] + data[30]) / 3 if length > 10: y_fit = reg_util.regress_y_polynomial(close[-10:], zoom=True) deg = calc_regress_deg(y_fit[:10], False) else: deg = calc_regress_deg(close[-10:], False) calc_data["trade_close_deg"] = deg if self.trade_mgr.get_status() == PositionStatus.Short: if deg > 0.01: calc_data["trade_close"] = "平仓:趋势反转{}".format(deg) return self.trade_mgr.cover(bar.close_price) elif self.trade_mgr.get_status() == PositionStatus.Long: if deg < -0.01: calc_data["trade_close"] = "平仓:趋势反转{}".format(deg) return self.trade_mgr.sell(bar.close_price) def ma_close(self, am: ArrayManager, bar: BarData, calc_data): if self.safe_price is None: return rg = (bar.close_price / self.trade_price) - 1 close_price = None if rg > 0.01 and self.trade_mgr.get_status() == PositionStatus.Long: close_price = am.sma(120) elif rg < -0.01 and self.trade_mgr.get_status( ) == PositionStatus.Short: close_price = am.sma(120) for lvl in self.ma_level[-1:]: # if len(self.order_data) < lvl: close_price = am.sma(lvl) break if close_price is None: lvl = self.ma_level[-1] close_price = am.sma(lvl) if self.trade_mgr.get_status() == PositionStatus.Short: if bar.close_price > close_price: calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price) return self.trade_mgr.cover(bar.close_price) # return self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET, # extra= { "reason":"平仓:到达MA均线价{}".format(close_price)}) elif self.trade_mgr.get_status() == PositionStatus.Long: if bar.close_price < close_price: calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price) return self.trade_mgr.sell(bar.close_price) # return self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET, # extra={"reason": "平仓:到达MA均线价{}".format(close_price)}) # 加仓算法 def add_position(self, am: ArrayManager, bar: BarData, calc_data, setting={}): if self.safe_price is None: return if not (self.trade_mgr.get_status() == PositionStatus.Short and bar.close_price < self.safe_price or \ self.trade_mgr.get_status() == PositionStatus.Long and bar.close_price > self.safe_price): return am = self.am rg = (bar.close_price / self.trade_price) - 1 close_price = None if rg > 0.01 and self.trade_mgr.get_status() == PositionStatus.Long: close_price = am.sma(120) if not self.add_pos: self.add_pos = True # scale = 1 - 0.002 # self.closeout_price = round(bar.close_price * scale, 2) return self.trade_mgr.buy(bar.close_price, 0.1, {}) elif rg < -0.01 and self.trade_mgr.get_status( ) == PositionStatus.Short: close_price = am.sma(120) if not self.add_pos: self.add_pos = True # scale = 1 + 0.002 # self.closeout_price = round(bar.close_price * scale, 2) return self.trade_mgr.short(bar.close_price, 0.1, {}) 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 def on_strategy(self, am: ArrayManager, bar: BarData, strategy_list, close_strategy_list, calc_data=None): order_id = None for open_strategy in strategy_list: if order_id is not None: break order_id = open_strategy(am, bar, calc_data) if order_id is None and self.pos != 0: for strategy in close_strategy_list: if order_id is not None: break order_id = strategy(am, 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.trend_context = None self.am.update_bar(bar) am = self.am max_len = self.ma_level[-1] + 20 data = self.am.close[-max_len:-1] if self.tracker is not None: self.tracker["bar_data"].append(bar) self.std_range.update(self.am.range[-1]) self.data_center.push("bar_data", bar) self.data_center.push("array_manager", self.am) if not am.inited or not self.trading: return calc_data = self.generate_data(am, bar) open_strategy = [self.ma_trend_strategy, self.add_position] close_strategy = [ self.ma_trend_strategy2, self.closeout_strategy, self.trend_reverse_close ] self.on_strategy(am, bar, open_strategy, close_strategy, calc_data) # 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 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)) self.trade_mgr.on_order(order) if order.vt_orderid in self.request_order: if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED: self.close_order.append(order.vt_orderid) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.trade_mgr.on_trade(trade) if trade.vt_orderid in self.request_order: # self.positions.on_trade(trade) if self.volumn == 0: self.add_pos = False self.trade_price = trade.price if trade.direction == Direction.LONG: self.safe_price = trade.price * 1.003 scale = 1 - self.closeout_offset self.closeout_price = round(trade.price * scale, 2) elif trade.direction == Direction.SHORT: self.safe_price = trade.price * 0.997 scale = 1 + self.closeout_offset self.closeout_price = round(trade.price * scale, 2) if trade.direction == Direction.LONG: self.volumn += trade.volume elif trade.direction == Direction.SHORT: self.volumn -= trade.volume if trade.vt_orderid in self.close_order: self.request_order.remove(trade.vt_orderid) self.close_order.remove(trade.vt_orderid) self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def ma_trend_strategy2(self, am: ArrayManager, bar: BarData, calc_data): context = self.trend_context if context == None: return deg = context["deg"] data = context["data"] sign = context["sign"] if self.pos > 0 and deg < 0: ma120 = self.ma_info.info[120] calc_data["trade_open"] = "平仓并开空,deg={}".format(deg) sign() self.trade_mgr.sell(bar.close_price) return self.trade_mgr.short(bar.close_price, 0.1, {}) elif self.pos < 0 and deg > 0: calc_data["trade_open"] = "开多,deg={}".format(deg) sign() self.trade_mgr.cover(bar.close_price) return self.trade_mgr.buy(bar.close_price, 0.1, {}) '''
def _init_k_data(self, code, k_data): # 注意:所有的数据库数据和列表数据都按照日期的正序排序(从小到大) """ 初始化股票数据库数据 @:param code 股票(指数)代码 """ if len(k_data) != 0: last_5_vol = deque([0.0] * 5) last_5_amount = deque([0.0] * 5) k_data = k_data.sort_values(by='trade_date') cl_stock_code = self.db[code] cl_stock_code.create_index([('trade_date', ASCENDING)], unique=True) am = ArrayManager(size=600) for ix, row in k_data.iterrows(): d = row.to_dict() d['ts_code'] = d['ts_code'].replace('.', '_') if 0.0 not in last_5_vol: vol_rate = d['vol'] / (sum(last_5_vol) / 5.0) amount_rate = d['amount'] / (sum(last_5_amount) / 5.0) d['vol_rate'] = vol_rate d['amount_rate'] = amount_rate else: d['vol_rate'] = 0.0 d['amount_rate'] = 0.0 last_5_vol.popleft() last_5_amount.popleft() last_5_vol.append(d['vol']) last_5_amount.append(d['amount']) if self._is_in_vnpy_db(d['ts_code'], update=False): # 构建vnpy股票数据库数据 self._build_db_vnpy(d) if d['ts_code'][-3:] == '_SH': exchange = Exchange.SSE d['exchange'] = 'SSE' else: exchange = Exchange.SZSE d['exchange'] = 'SZSE' bar = BarData( gateway_name='ctp', symbol=d['ts_code'], exchange=exchange, datetime=string_to_datetime(d['trade_date'])) bar.symbol = d['ts_code'] bar.volume = d['vol'] bar.open_price = d['open'] bar.high_price = d['high'] bar.low_price = d['low'] bar.close_price = d['close'] am.update_bar(bar) try: d['ma_5'] = am.sma(5) except: traceback.print_exc() LOG.error('************************') LOG.error(d['ts_code']) LOG.error(d['trade_date']) LOG.error(bar) d['ma_10'] = am.sma(10) d['ma_20'] = am.sma(20) d['ma_30'] = am.sma(30) d['ma_60'] = am.sma(60) d['ma_120'] = am.sma(120) d['ma_250'] = am.sma(250) d['ma_500'] = am.sma(500) d['high_5'] = np.max(am.high[-5:]) d['high_10'] = np.max(am.high[-10:]) d['high_20'] = np.max(am.high[-20:]) d['high_30'] = np.max(am.high[-30:]) d['high_60'] = np.max(am.high[-60:]) d['high_120'] = np.max(am.high[-120:]) d['high_250'] = np.max(am.high[-250:]) d['high_500'] = np.max(am.high[-500:]) d['low_5'] = np.min(am.low[-5:]) d['low_10'] = np.min(am.low[-10:]) d['low_20'] = np.min(am.low[-20:]) d['low_30'] = np.min(am.low[-30:]) d['low_60'] = np.min(am.low[-60:]) d['low_120'] = np.min(am.low[-120:]) d['low_250'] = np.min(am.low[-250:]) d['low_500'] = np.min(am.low[-500:]) flt = {'trade_date': d['trade_date']} cl_stock_code.replace_one(flt, d, upsert=True)
class TurtleCStrategy(CtaTemplate): """""" # 反向海龟信号 author = "turtle_inverse_trade" entry_window = 50 exit_window = 20 atr_window = 20 stop_multiple = 2 fixed_size = 1 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 parameters = [ "entry_window", "exit_window", "atr_window", "fixed_size", "stop_multiple" ] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TurtleCStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) # self.close_ma = self.am.sma(50) # self.entry_up += self.close_ma * 0.002 # self.entry_down -= self.close_ma * 0.002 self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) elif self.pos > 0: # inverse system # 有多头要卖出,等向上再卖出 self.sell(self.exit_up, abs(self.pos), False) elif self.pos < 0: # inverse system # 有空头要买回,等向下再补回 self.cover(self.exit_down, abs(self.pos), False) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price self.long_stop = self.long_entry - self.stop_multiple * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + self.stop_multiple * self.atr_value def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def send_buy_orders(self, price): """""" # invere system self.short(price, self.fixed_size, False) def send_short_orders(self, price): """""" # inverse system self.buy(price, self.fixed_size, False)
class MultiTimeframeStrategy(CtaTemplate): """""" author = "KK Taiwan 交易員" rsi_signal = 20 rsi_window = 14 fast_window = 12 # init define for 5mins * 12 = 1HR slow_window = 30# inti define for 5mins * 36 = 3HR 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","fast_ma1","slow_ma1"] 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 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)) ###KK 跟新長倉策略 self.pettyfast_ma = self.am5.sma(self.fast_window) self.pettyslow_ma = self.am5.sma(self.slow_window) if self.pettyfast_ma > self.pettyslow_ma: self.ma_pettytrend = 1 else: self.ma_pettytrend = -1 ##### if(buy list) if (self.ma_pettytrend < 0) and (time > 0) if 虧 平倉時間點限制 - 2 time if < 1 平倉 else 平倉時間點限制 - time if < 1 跟新下限 from 15 mins均線 #改為短平倉 and update limit else if time < 10 平倉時間點限制 +time if(short list) if (self.ma_pettytrend > 0) and (time > 0) if 虧 平倉時間點限制 - 2 time if timw<1 平倉 else 平倉時間點限制 - time if < 1 跟新下限 from 15 mins均線 else if time < 10 平倉時間點限制 + time if self.pos == 0: if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy_signal(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_signal(bar.close_price - 5, abs(self.pos)) elif self.pos < 0: if self.ma_trend > 0 or self.rsi_value > 50: self.cover_signal(bar.close_price + 5, abs(self.pos)) ### self.put_event()
class CincoRB2005Strategy(CtaTemplate): """""" author = "tonywang_efun" boll_window = 44 boll_dev = 2.0 rsi_window = 8 rsi_long = 58 rsi_short = 20 trailing_long = 2.6 trailing_short = 2.6 fixed_size = 2 boll_up = 0 boll_down = 0 rsi_value = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "boll_window", "boll_dev", "rsi_window", "rsi_long", "rsi_short", "trailing_long", "trailing_short", "fixed_size" ] variables = [ "boll_up", "boll_down", "rsi_value", "trading_size", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "atr_value" ] def __init__( self, cta_engine, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super(CincoRB2005Strategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 13, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) self.rsi_value = self.am.rsi(self.rsi_window) boll_width = self.boll_up - self.boll_down if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 # print(self.boll_up, self.boll_down, self.intra_trade_high, self.intra_trade_low) if self.rsi_value >= self.rsi_long: self.buy(self.boll_up, self.fixed_size, stop=True) if self.rsi_value <= self.rsi_short: self.short(self.boll_down, self.fixed_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class 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 CuatroStrategy(CtaTemplate): """""" author = "黄柠" # 定义参数 boll_window = 20 boll_dev = 2.0 rsi_window = 14 rsi_signal = 30 fast_window = 5 slow_window = 20 trailing_long = 1.0 trailing_short = 1.0 fixed_size = 1 # 定义变量 boll_up = 0.0 boll_down = 0.0 rsi_value = 0.0 rsi_long = 0.0 rsi_short = 0.0 fast_ma = 0.0 slow_ma = 0.0 ma_trend = 0 intra_trade_high = 0.0 intra_trade_low = 0.0 long_stop = 0.0 short_stop = 0.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: Any, 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): """ Callback of new bar data update. """ 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 engine_type = self.get_engine_type() 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: if engine_type == EngineType.BACKTESTING: self.buy(self.boll_up, self.fixed_size, stop=True) else: self.buy(self.boll_up, self.fixed_size, stop=True, lock=True) if self.ma_trend <= 0 and self.rsi_value <= self.rsi_short: if engine_type == EngineType.BACKTESTING: self.short(self.boll_down, self.fixed_size, stop=True) else: self.short(self.boll_down, self.fixed_size, stop=True, lock=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_15min_bar(self, bar: BarData): """ Callback of new bar data update. """ 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 = 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. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event()
class TurtleSignalStrategy(CtaTemplate): """""" author = "backtest example" entry_window = 20 exit_window = 10 atr_window = 20 fixed_size = 1 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 parameters = ["entry_window", "exit_window", "atr_window", "fixed_size"] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TurtleSignalStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) elif self.pos > 0: sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: cover_price = min(self.short_stop, self.exit_up) self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def send_buy_orders(self, price): """""" self.buy(price, self.fixed_size, True) def send_short_orders(self, price): """""" self.short(price, self.fixed_size, True)
class MyBollingDayStrategy(CtaTemplate): """基于布林通道的交易策略""" className = 'MyBollingDayStrategy' author = 'yuanhui' # 策略参数 #bollWindow = 26 # 通道窗口数 entryDev = 2 # 开仓偏差 bollWindow5min = 26 # 通道窗口数 entryDev5min = 2 # 开仓偏差 bollWindow15min = 26 # 通道窗口数 entryDev15min = 2 # 开仓偏差 bollWindow30min = 52 # 通道窗口数 entryDev30min = 2 # 开仓偏差 bollWindowDay = 26 # 通道窗口数 entryDevDay = 2 # 开仓偏差 #exitDev = 1.2 # 平仓偏差 #trailingPrcnt = 0.4 # 移动止损百分比 #maWindow = 10 # 过滤用均线窗口 initDays = 33 # 初始化数据所用的天数 fixedSize = 1 # 每次交易的数量 priceTick = 0.2 # 价格最小变动 DayTrendStatus='panzhen' #DuoTou, KongTou,Panzheng FifteenMinTrendStatus='panzhen' FiveMinTrendStatus='panzhen' ThirtyMinTrendStatus='panzhen' # 5Min策略变量 bollMid = 0 # 布林带中轨 BeforebollMid=0 #上一根K线的布林线中轨 #bollStd = 0 # 布林带宽度 bollUp = 0 # 开仓上轨 Beforebollup=0 #上一根K线的布林线上轨 bollDown = 0 # 平仓下轨 beforebolldown=0 #上一根K线的布林线下轨 # 15Min策略变量 bollMid15 = 0 # 布林带中轨 BeforebollMid15=0 #上一根K线的布林线中轨 #bollStd15 = 0 # 布林带宽度 bollUp15 = 0 # 开仓上轨 Beforebollup15=0 #上一根K线的布林线上轨 bollDown15 = 0 # 平仓下轨 beforebolldown15=0 #上一根K线的布林线下轨 # 30Min策略变量 bollMid30 = 0 # 布林带中轨 BeforebollMid30=0 #上一根K线的布林线中轨 #bollStd30 = 0 # 布林带宽度 bollUp30 = 0 # 开仓上轨 Beforebollup30=0 #上一根K线的布林线上轨 bollDown30 = 0 # 平仓下轨 beforebolldown30=0 #上一根K线的布林线下轨 # 日线策略变量 bollMidDay = 0 # 布林带中轨 BeforebollMidDay=0 #上一根K线的布林线中轨 #bollStd30 = 0 # 布林带宽度 bollUpDay = 0 # 开仓上轨 BeforebollupDay=0 #上一根K线的布林线上轨 bollDownDay= 0 # 平仓下轨 beforebolldownDay=0 #上一根K线的布林线下轨 #maFilter = 0 # 均线过滤 #maFilter1 = 0 # 上一期均线 intraTradeHigh = 0 # 持仓期内的最高点 longEntry = 0 #多头开仓位置 longExit = 0 #多头平仓位置 shortEntry=0 #空头开仓位置 shortExit=0 #空头平仓位置 #上一个交易单子保本否 lastTrade_baoben=False deal=0 # 多头平仓为正,空头平仓为 dealopen=0 # 多头开仓正,空头开仓负 orderList = [] # 保存委托代码的列表 tradedata=[] posdata=[] #仓位信息,每次开仓成功后把trade信息加入List,平仓后删除 tradedata_boll=[] #所有的需要在布林线止损的交易单 tradedata_baoben=[] #所有的已经过了保本线的交易单 tradedata_day=[] #日线级别交易单 zhishunpercent=0.005 #每笔止损百分比 # 参数列表,保存了参数的名称 parameters = [ 'bollWindowDay', 'entryDevDay', 'fixedSize', 'DayTrendStatus' ] # 变量列表,保存了变量的名称 variables = ['inited', 'trading', 'pos', 'bollUp', 'bollDown', 'bollUp15', 'bollDown15', 'bollUp30', 'bollDown30', 'FifteenMinTrendStatus', 'FiveMinTrendStatus', 'ThirtyMinTrendStatus' ] # 同步列表 syncList = ['pos', 'intraTradeHigh'] #---------------------------------------------------------------------- def __init__(self, ctaEngine, strategy_name, vt_symbol, setting): """Constructor""" #super(MyBollingerBotStrategy, self).__init__(ctaEngine, setting) super().__init__(ctaEngine, strategy_name, vt_symbol, setting) self.bm5 = BarGenerator(self.on_bar, 5, self.on_5Min_bar) self.am5 = ArrayManager(80) self.bm15 = BarGenerator(self.on_bar, 15, self.on_15Min_bar) self.am15 = ArrayManager(80) self.bm30 = BarGenerator(self.on_bar, 30, self.on_30Min_bar) self.am30 = ArrayManager(80) #self.bmDay = BarGenerator(self.on_bar, 6, self.onDayBar,Interval.HOUR) self.bmDay = BarGenerator(self.on_bar, 1, self.onDayBar,Interval.DAILY) self.amDay = ArrayManager(30) head=["datetime","BollStatus","open","close","high","low","pos","pDown","pMiddle","pUp","dealOpen"] current_path =os.getcwd()# os.path.abspath(__file__) write_csv_file(current_path+"\\datasig5.csv",head,None,"w") write_csv_file(current_path+"\\datasig15.csv",head,None,"w") write_csv_file(current_path+"\\datasig30.csv",head,None,"w") write_csv_file(current_path+"\\datasigDay.csv",head,None,"w") head=["datetime","orderid","tradeid","direction","offset","price","volume"] write_csv_file(current_path+"\\datasigTrade.csv",head,None,"w") head=["datetime","orderid","tradeid","direction","offset","price","volume","baoben"] write_csv_file(current_path+"\\datasigPos.csv",head,None,"w") print("self.cta_engine.capital %d",self.cta_engine.capital) #---------------------------------------------------------------------- def caculate_pos(self,zhishun:float): pos=0 pos=int(self.cta_engine.capital*self.zhishunpercent//zhishun) return pos def on_init(self): """初始化策略(必须由用户继承实现)""" self.write_log(u'%s策略初始化' %self.className) # 载入历史数据,并采用回放计算的方式初始化策略数值 initData = self.load_bar(self.initDays) #for bar in initData: # self.onBar(bar) #self.put_event() #---------------------------------------------------------------------- def on_start(self): """启动策略(必须由用户继承实现)""" self.write_log(u'%s策略启动' %self.className) self.put_event() #---------------------------------------------------------------------- def on_stop(self): """停止策略(必须由用户继承实现)""" self.write_log(u'%s策略停止' %self.className) self.put_event() #---------------------------------------------------------------------- def on_tick(self, tick): """收到行情TICK推送(必须由用户继承实现)""" self.bm5.updateTick(tick) #---------------------------------------------------------------------- def on_bar(self, bar: BarData): """收到Bar推送(必须由用户继承实现)""" #早盘开盘前一分钟收到的多余的tick的清除 if "09:29:00" in bar.datetime.strftime("%Y-%m-%d %H:%M:%S") and "IF" in bar.symbol: return if "08:59:00" in bar.datetime.strftime("%Y-%m-%d %H:%M:%S"): return #s基于日线判断趋势过滤,因此先更新 self.bmDay.update_bar(bar) #s基于30分钟更新 self.bm30.update_bar(bar) # 基于15分钟更新 self.bm15.update_bar(bar) # 基于5分钟更新 self.bm5.update_bar(bar) ''' if self.amDay.inited: self.onDayBar(bar) return else: self.amDay.update_bar(bar) return ''' #判断当前5Min布林线趋势状态 if not self.am5.inited or not self.am15.inited or not self.am30.inited or not self.amDay.inited: return if self.bm5.window_bar !=None: if self.bm5.window_bar.high_price > self.bollUp and self.bm5.window_bar.low_price > self.bollMid: self.FiveMinTrendStatus='duotou' elif self.bm5.window_bar.low_price < self.bollDown and self.bm5.window_bar.high_price < self.bollMid: self.FiveMinTrendStatus='kongtou' elif self.bm5.window_bar.low_price < self.bollMid and self.FiveMinTrendStatus=='duotou': self.FiveMinTrendStatus='panzhen' elif self.bm5.window_bar.high_price > self.bollMid and self.FiveMinTrendStatus=='kongtou': self.FiveMinTrendStatus='panzhen' #判断当前15Min布林线趋势状态 if self.bm15.window_bar!=None: if self.bm15.window_bar.high_price > self.bollUp15 and self.bm15.window_bar.low_price > self.bollMid15: self.FifteenMinTrendStatus='duotou' elif self.bm15.window_bar.low_price < self.bollDown15 and self.bm15.window_bar.high_price < self.bollMid15: self.FifteenMinTrendStatus='kongtou' elif self.bm15.window_bar.low_price < self.bollMid15 and self.FifteenMinTrendStatus=='duotou': self.FifteenMinTrendStatus='panzhen' elif self.bm15.window_bar.high_price > self.bollMid15 and self.FifteenMinTrendStatus=='kongtou': self.FifteenMinTrendStatus='panzhen' #判断当前30Min布林线趋势状态 if self.bm30.window_bar!=None: if self.bm30.window_bar.high_price > self.bollUp30 and self.bm30.window_bar.low_price > self.bollMid30: self.ThirtyMinTrendStatus='duotou' elif self.bm30.window_bar.low_price < self.bollDown30 and self.bm30.window_bar.high_price < self.bollMid30: self.ThirtyMinTrendStatus='kongtou' elif self.bm30.window_bar.low_price < self.bollMid30 and self.ThirtyMinTrendStatus=='duotou': self.ThirtyMinTrendStatus='panzhen' elif self.bm30.window_bar.high_price > self.bollMid30 and self.ThirtyMinTrendStatus=='kongtou': self.ThirtyMinTrendStatus='panzhen' #判断当前日线布林线趋势状态 if self.bmDay.window_bar!=None: if self.bmDay.window_bar.high_price > self.bollUpDay and self.bmDay.window_bar.low_price > self.bollMidDay: self.DayTrendStatus='duotou' elif self.bmDay.window_bar.low_price < self.bollDownDay and self.bmDay.window_bar.high_price < self.bollMidDay: self.DayTrendStatus='kongtou' elif self.bmDay.window_bar.low_price < self.bollMidDay and self.DayTrendStatus=='duotou': self.DayTrendStatus='panzhen' elif self.bmDay.window_bar.high_price > self.bollMidDay and self.DayTrendStatus=='kongtou': self.DayTrendStatus='panzhen' ''' if self.pos == 0: #self.intraTradeHigh = bar.high orderList=[] if self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='duotou' and self.FiveMinTrendStatus=='duotou': #self.longEntry = bar.close self.cancelAll() orderList=self.buy(bar.close+self.priceTick, self.fixedSize, True) print (u"策略:%s,委托多单,1分钟收盘价开仓"%self.__dict__["name"]) elif self.DayTrendStatus=='kongtou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='kongtou' and self.FiveMinTrendStatus=='kongtou': #self.shortEntry = bar.close self.cancelAll() orderList=self.short( bar.close-self.priceTick, self.fixedSize, True) print (u"策略:%s,委托空单,1分钟收盘价开仓"%self.__dict__["name"]) ''' #print (u'策略:',self.__dict__["name"]) #print (u"策略:%s,时间:%s,1分钟刷新,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s"%(self.__dict__["name"],bar.datetime,self.FiveMinTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.DayTrendStatus)) self.put_event() #---------------------------------------------------------------------- def on_5Min_bar(self, bar: BarData): """收到5分钟K线""" if not self.am5.inited or not self.am15.inited or not self.am30.inited or not self.amDay.inited: self.am5.update_bar(bar) return #计算上一个k线的布林中轨,上轨,下轨 self.BeforebollMid=self.am5.sma(self.bollWindow5min) self.Beforebollup,self.beforebolldown=self.am5.boll(self.bollWindow5min,self.entryDev5min) # 保存K线数据 self.am5.update_bar(bar) # 撤销之前发出的尚未成交的委托(包括限价单和停止单) #self.cancel_all() orderList=[] # 计算指标数值 self.bollMid = self.am5.sma(self.bollWindow5min) self.bollUp,self.bollDown = self.am5.boll(self.bollWindow5min,self.entryDev5min) #判断当前5Min布林线趋势状态 if bar.high_price > self.Beforebollup and bar.low_price > self.BeforebollMid: self.FiveMinTrendStatus='duotou' elif bar.low_price < self.beforebolldown and bar.high_price < self.BeforebollMid: self.FiveMinTrendStatus='kongtou' elif bar.low_price < self.BeforebollMid and self.FiveMinTrendStatus=='duotou': self.FiveMinTrendStatus='panzhen' elif bar.high_price > self.BeforebollMid and self.FiveMinTrendStatus=='kongtou': self.FiveMinTrendStatus='panzhen' ''' if bar.high > self.bollMid15 and self.FifteenMinTrendStatus == 'kongtou': self.FifteenMinTrendStatus=='panzhen' if bar.low < self.bollMid15 and self.FifteenMinTrendStatus == 'duotou': self.FifteenMinTrendStatus=='panzhen' ''' # 判断是否要进行交易 #print (u"策略:%s,5分钟刷新,趋势状态,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s"%(self.className,self.FiveMinTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.DayTrendStatus)) # 当前无仓位,发送OCO开仓委托 ''' if self.pos == 0: #self.intraTradeHigh = bar.high #多头处理 if self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus!='duotou' : orderList=self.buy(self.bollUp15+self.priceTick, self.fixedSize, True) print (u"策略:%s,委托多单,15分钟上轨开仓"%self.__dict__["name"]) elif self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus=="panzhen" : orderList=self.buy(self.bollUp30+self.priceTick, self.fixedSize, True) print (u"策略:%s,委托多单,30分钟上轨开仓"%self.__dict__["name"]) elif self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='duotou' and self.FiveMinTrendStatus=='duotou': self.longEntry = bar.close orderList=self.buy(self.longEntry+self.priceTick, self.fixedSize, True) print (u"策略:%s,委托多单,5分钟收盘价开仓"%self.__dict__["name"]) elif self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='duotou' and self.FiveMinTrendStatus!='duotou': self.longEntry=self.bollUp orderList=self.buy(self.longEntry+self.priceTick, self.fixedSize, True) print (u"策略:%s,委托多单,5分钟上轨开仓"%self.__dict__["name"]) #空头处理 elif self.DayTrendStatus=='kongtou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus!='kongtou' : orderList=self.short(self.bollDown15-self.priceTick, self.fixedSize, True) print (u"策略:%s,委托空单,15分钟下轨开仓"%self.__dict__["name"]) elif self.DayTrendStatus=='kongtou' and self.ThirtyMinTrendStatus=="panzhen" : orderList=self.short(self.bollDown30-self.priceTick, self.fixedSize, True) print (u"策略:%s,委托空单,30分钟下轨开仓"%self.__dict__["name"]) elif self.DayTrendStatus=='kongtou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='kongtou' and self.FiveMinTrendStatus=='kongtou': self.shortEntry = bar.close orderList=self.short(self.shortEntry-self.priceTick, self.fixedSize, True) print (u"策略:%s,委托空单,5分钟收盘价开仓"%self.__dict__["name"]) elif self.DayTrendStatus=='kongtou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='kongtou' and self.FiveMinTrendStatus!='kongtou': self.shortEntry=self.bollDown orderList=self.short(self.shortEntry-self.priceTick, self.fixedSize, True) print (u"策略:%s,委托空单,5分钟下轨开仓"%self.__dict__["name"]) # 持有多头仓位 elif self.pos > 0: orderList=self.sell(self.bollDown-self.priceTick, abs(self.pos), True) print (u"策略:%s,委托止损单,5分钟下轨平仓"%self.__dict__["name"]) # 持有空头仓位 elif self.pos < 0: orderList=self.cover(self.bollUp+self.priceTick, abs(self.pos), True) print (u"策略:%s,委托止损单,5分钟上轨平仓"%self.__dict__["name"]) with open("datasig5.csv","ab+",) as csvfile: writer = csv.writer(csvfile) writer.writerow([bar.datetime,bar.open, bar.close, bar.high, bar.low,bar.openInterest,bar.volume,self.deal,self.bollDown,self.bollUp,self.dealopen]) self.deal=0 self.dealopen=0 if orderList: print (u"策略:%s,委托单成功,单号%s"%(self.__dict__["name"],orderList[-1])) #else: # print u"策略:%s,委托单失败"%self.__dict__["name"] # 发出状态更新事件 ''' self.put_event() def on_15Min_bar(self, bar: BarData): """15分钟K线推送""" if not self.am15.inited or not self.am30.inited or not self.amDay.inited: self.am15.update_bar(bar) return #计算上一个k线的布林中轨,上轨,下轨 self.BeforebollMid15=self.am15.sma(self.bollWindow15min) self.Beforebollup15,self.beforebolldown15=self.am15.boll(self.bollWindow15min,self.entryDev15min) self.am15.update_bar(bar) # 计算指标数值 self.bollMid15 = self.am15.sma(self.bollWindow15min) self.bollUp15,self.bollDown15 = self.am15.boll(self.bollWindow15min,self.entryDev15min) #判断当前15Min布林线趋势状态 if bar.high_price > self.Beforebollup15 and bar.low_price > self.BeforebollMid15: self.FifteenMinTrendStatus='duotou' elif bar.low_price < self.beforebolldown15 and bar.high_price < self.BeforebollMid15: self.FifteenMinTrendStatus='kongtou' elif bar.low_price < self.BeforebollMid15 and self.FifteenMinTrendStatus=='duotou': self.FifteenMinTrendStatus='panzhen' elif bar.high_price > self.BeforebollMid15 and self.FifteenMinTrendStatus=='kongtou': self.FifteenMinTrendStatus='panzhen' #with open("datasig15.csv","ab+",) as csvfile: # writer = csv.writer(csvfile) #writer.writerow([bar.datetime,bar.open_price, bar.close_price, bar.high_price, bar.low_price,bar.open_interest,bar.volume,self.deal,self.bollDown15,self.bollUp15,self.dealopen]) #print (u"策略:%s,15分钟刷新,趋势状态,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s"%(self.className,self.FiveMinTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.DayTrendStatus)) #print u"15分钟收盘价",self.am15.closeArray[75:] # 当前无仓位,发送OCO开仓委托 ''' if self.pos == 0: self.intraTradeHigh = bar.high if self.FifteenMinTrendStatus=='panzhen': self.longEntry = self.bollUp15 self.shortEntry=self.booldown15 self.buy(self.longEntry, self.fixedSize, True) self.short(self.shortEntry,self.fixedSize,True) ''' # 发出状态更新事件 self.put_event() def on_30Min_bar(self, bar: BarData): """30分钟K线推送""" if not self.am30.inited or not self.amDay.inited: self.am30.update_bar(bar) return #计算上一个k线的布林中轨,上轨,下轨 self.BeforebollMid30=self.am30.sma(self.bollWindow30min) self.Beforebollup30,self.beforebolldown30=self.am30.boll(self.bollWindow30min,self.entryDev30min) self.am30.update_bar(bar) # 计算指标数值 self.bollMid30 = self.am30.sma(self.bollWindow30min) self.bollUp30,self.bollDown30 = self.am30.boll(self.bollWindow30min,self.entryDev30min) #判断当前30Min布林线趋势状态 if bar.high_price > self.Beforebollup30 and bar.low_price > self.BeforebollMid30: self.ThirtyMinTrendStatus='duotou' elif bar.low_price < self.beforebolldown30 and bar.high_price < self.BeforebollMid30: self.ThirtyMinTrendStatus='kongtou' elif bar.low_price < self.BeforebollMid30 and self.ThirtyMinTrendStatus=='duotou': self.ThirtyMinTrendStatus='panzhen' elif bar.high_price > self.BeforebollMid30 and self.ThirtyMinTrendStatus=='kongtou': self.ThirtyMinTrendStatus='panzhen' ''' self.cancel_all() #开平仓位置 self.intraTradeHigh = bar.high_price self.longEntry = self.bollUp30+self.priceTick self.longExit=self.bollDown30-self.priceTick self.shortEntry=self.bollDown30-self.priceTick self.shortExit=self.bollUp30+self.priceTick zhishun=self.bollUp30-self.bollDown30 volume=self.caculate_pos(zhishun) #volume=self.fixedSize #pos=self.posdata[-1] if (self.pos==0 and len(self.posdata)>0) or (not self.pos==0 and len(self.posdata)==0): print(u"仓位self.pos和仓位列表self.posdata不匹配") import sys sys.exit(1) if self.pos==0: #无仓位 if self.ThirtyMinTrendStatus=='panzhen' and self.DayTrendStatus=='duotou': self.buy(self.longEntry, volume, True) elif self.ThirtyMinTrendStatus=='panzhen' and self.DayTrendStatus=='kongtou': self.short(self.shortEntry,volume,True) else: #有仓位 #最后一个单子为开仓单,判断是否保本了 trade=self.tradedata[-1] if trade.offset==Offset.OPEN: if ( self.bollDown30 >trade.price and trade.direction==Direction.LONG) or (self.bollUp30 <trade.price and trade.direction==Direction.SHORT): self.lastTrade_baoben=True self.posdata[-1].baoben=True if trade.offset==Offset.CLOSE or self.lastTrade_baoben==True: #最后一个交易为平仓单,发送开仓单在布林线上下轨 if self.ThirtyMinTrendStatus=='panzhen' and self.DayTrendStatus=='duotou': self.buy(self.longEntry, volume, True) elif self.ThirtyMinTrendStatus=='panzhen' and self.DayTrendStatus=='kongtou': self.short(self.shortEntry,volume,True) #需要在布林线上下轨止损的单子,重新发出止损单子 # 最后一笔交易为多头仓位,没有保本,在下轨止损 elif trade.offset==Offset.OPEN and (trade.direction==Direction.LONG and self.posdata[-1].baoben==False): orderList=self.sell(max(self.longExit,self.bollMidDay), trade.volume, True) #print (u"策略:%s,委托止损单,30分钟下轨平仓"%self.className) # 最后一笔交易为空头仓位,没有保本,在上轨止损 elif trade.offset==Offset.OPEN and (trade.direction==Direction.SHORT and self.posdata[-1].baoben==False): orderList=self.cover(min(self.bollMidDay,self.shortExit), trade.volume, True) #print (u"策略:%s,委托止损单,30分钟上轨平仓"%self.className) #需要在保本位置设置止损的交易单,重新发出止损单子 #if self.lastTrade_baoben==True: i=0 while i <len(self.posdata): volume=self.posdata[i].volume if self.posdata[i].baoben==True: if self.posdata[i].direction==Direction.LONG: orderList=self.sell(max(self.posdata[i].price,self.bollMidDay), volume, True) #print (u"策略:%s,委托止损单,保本价格平仓"%self.className) elif self.posdata[i].direction==Direction.SHORT: orderList=self.cover(min(self.posdata[i].price,self.bollMidDay), volume, True) #print (u"策略:%s,委托止损单,保本价格平仓"%self.className) i=i+1 #需要在日线中轨止损的单子,需要在新的日线中轨处发出止损单 current_path =os.getcwd()# os.path.abspath(__file__) bardata=[bar.datetime,self.ThirtyMinTrendStatus,bar.open_price, bar.close_price, bar.high_price, bar.low_price,bar.open_interest,bar.volume,self.pos,self.bollDown30,self.bollUp30,self.dealopen] write_csv_file(current_path+"\\datasig30.csv",None,bardata,"a+") #print(u"时间:",bar.datetime) #print (u"策略:%s,30分钟刷新,趋势状态,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s"%(self.className,self.FiveMinTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.DayTrendStatus)) #print (u"30分钟收盘价",self.am30.close_array[60:]) ''' # 发出状态更新事件 self.put_event() def onDayBar(self, bar: BarData): """日K线推送""" t1=str(bar.datetime) t2=str(datetime(2016,1,28,21,0,0)) if t2 in t1: i=0 if not self.amDay.inited: self.amDay.update_bar(bar) return #计算上一个k线的布林中轨,上轨,下轨 self.BeforebollMidDay=self.amDay.sma(self.bollWindowDay) self.BeforebollupDay,self.beforebolldownDay=self.amDay.boll(self.bollWindowDay,self.entryDevDay) self.amDay.update_bar(bar) # 计算指标数值 self.bollMidDay = self.amDay.sma(self.bollWindowDay) self.bollUpDay,self.bollDownDay = self.amDay.boll(self.bollWindowDay,self.entryDevDay) #判断当前日线布林线趋势状态 if bar.high_price > self.BeforebollupDay and bar.low_price > self.BeforebollMidDay: self.DayTrendStatus='duotou' elif bar.low_price < self.beforebolldownDay and bar.high_price < self.BeforebollMidDay: self.DayTrendStatus='kongtou' elif bar.low_price < self.BeforebollMidDay and self.DayTrendStatus=='duotou': self.DayTrendStatus='panzhen' elif bar.high_price > self.BeforebollMidDay and self.DayTrendStatus=='kongtou': self.DayTrendStatus='panzhen' ''' if (self.pos==0 and len(self.tradedata_day)>0) or ( self.pos!=0 and len(self.tradedata_day)==0): print(u"仓位self.pos和仓位列表self.tradedata_day") import sys sys.exit(1) ''' self.intraTradeHigh = bar.high_price self.longEntry = self.bollUpDay+self.priceTick self.longExit=self.bollMidDay-self.priceTick self.shortEntry=self.bollDownDay-self.priceTick self.shortExit=self.bollMidDay+self.priceTick #需要在日线中轨止损的单子,需要在新的日线中轨处发出止损单 self.cancel_all() #if len(self.tradedata_day)>0: if self.pos!=0: if self.pos>0: orderList=self.sell(self.longExit, self.pos, True) print (u"策略:%s,委托止损单,日线中轨平仓"%self.className) else: orderList=self.cover(self.shortExit, abs(self.pos), True) print (u"策略:%s,委托止损单,日线中轨平仓"%self.className) ''' i=0 volume=0 while i <len(self.tradedata_day): volume=self.tradedata_day[i].volume if self.tradedata_day[i].direction==Direction.LONG: orderList=self.sell(self.longExit, volume, True) print (u"策略:%s,委托止损单,日线中轨平仓"%self.className) elif self.tradedata_day[i].direction==Direction.SHORT: orderList=self.cover(self.shortExit, volume, True) print (u"策略:%s,委托止损单,日线中轨平仓"%self.className) i=i+1 ''' zhishun=(self.bollUpDay-self.bollDownDay)/2 volume=self.caculate_pos(zhishun) #日线盘整,上下轨开仓 if self.DayTrendStatus=="panzhen" and self.pos==0 and volume!=0:#len(self.tradedata_day)==0: self.cancel_all() orderList=[] orderList=self.buy(self.bollUpDay+self.priceTick, volume, True) print (u"策略:%s,委托多单,日线上轨开仓"%self.className) if orderList: print (u"策略:%s,委托单成功,单号%s"%(self.className,orderList[-1])) else: print (u"策略:%s,委托单失败"%self.className) orderList=[] orderList=self.short(self.bollDownDay-self.priceTick, volume, True) print (u"策略:%s,委托空单,日线下轨开仓"%self.className) if orderList: print (u"策略:%s,委托单成功,单号%s"%(self.className,orderList[-1])) else: print (u"策略:%s,委托单失败"%self.className ) bardata=[bar.datetime,self.DayTrendStatus,bar.open_price, bar.close_price, bar.high_price, bar.low_price,self.pos,int(self.bollDownDay),int(self.bollMidDay),int(self.bollUpDay),self.dealopen] write_csv_file(os.getcwd()+"\\datasigDay.csv",None,bardata,"a+") print(u"日线刷新---------------") print(u"时间(日线刷新):",bar.datetime) print (u"策略:%s,日线刷新,趋势状态,日线趋势%s,15分钟趋势%s,30分钟趋势%s,5分钟趋势%s"%(self.className,self.DayTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.FiveMinTrendStatus)) #print (u"日线开盘价",self.amDay.open_array[1:]) #print (u"日线收盘价",self.amDay.close_array[1:]) #print(u"日线刷新---------------") # 发出状态更新事件 self.put_event() #---------------------------------------------------------------------- def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" if order.offset==Offset.CLOSE: print("new order") pass #---------------------------------------------------------------------- def on_trade(self, trade): #打印信息 print(u"成交单刷新---------------") print(u"时间(日线刷新):",trade.datetime) print ("策略:%s,趋势状态,日线趋势%s,15分钟趋势%s,30分钟趋势%s,5分钟趋势%s"%(self.className,self.DayTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.FiveMinTrendStatus)) print (u"策略:%s, 委托单成交"%self.className) print (trade.direction) print (trade.offset) #print "15min:",self.FifteenMinTrendStatus #print "5min:",self.FiveMinTrendStatus current_path =os.getcwd()# os.path.abspath(__file__) #head=["datetime","orderid","tradeid","direction","offset","price","volume"] #所有交易单保存下来 self.tradedata.append(trade) #开仓成功加入仓位list,平仓成功,删除最后加仓的仓位 self.cancel_all() if trade.offset==Offset.OPEN: self.tradedata_day.append(trade) self.tradedata_day[-1].baoben==False self.lastTrade_baoben=False if trade.offset==Offset.CLOSE: #self.cancel_all() if len(self.tradedata_day)>0: self.tradedata_day.pop() if len(self.posdata)>=1: #这一单平仓后,仓位list中还有仓位,说明上一个仓位是已经保本的仓位i self.lastTrade_baoben=True else: #清空 head=["datetime","orderid","tradeid","direction","offset","price","volume","baoben"] write_csv_file(current_path+"\\datasigPos.csv",head,None,"w") ''' #成交单是保本的平仓单需要,判断标准一,这次和上次都是平仓单 if self.tradedata[-1].offset==Offset.CLOSE and self.tradedata[-2].offset==offset.CLOSE: self.tradedata_baoben.pop #成交单是保本的平仓单,判断标准二,这次是平仓单,上次是开仓单,同时保本表示为True if (self.tradedata[-1].offset==Offset.CLOSE and self.tradedata[-2].offset==offset.OPEN) and self.lastTrade_baoben==True: self.tradedata_baoben.pop ''' #保存到文件 tradedata=[trade.datetime,trade.orderid,trade.tradeid,trade.direction,trade.offset,trade.price,trade.volume] write_csv_file(current_path+"\\datasigTrade.csv",None,tradedata,"a+") #写入仓位保存文件 head=["datetime","orderid","tradeid","direction","offset","price","volume","baoben"] # write_csv_file(current_path+"datasigPos.csv",head,None,"w") i=0 while i <len(self.posdata): posdata=[self.posdata[i].datetime,self.posdata[i].orderid,self.posdata[i].tradeid,self.posdata[i].direction,self.posdata[i].offset,self.posdata[i].price,self.posdata[i].volume,self.posdata[i].baoben] if i==0: write_csv_file(current_path+"\\datasigPos.csv",head,None,"w") #开仓成功后先取消掉还有的挂单,主要针对的是日线的双向挂单 write_csv_file(current_path+"\\datasigPos.csv",None,posdata,"a+") i=i+1 #if self.pos!=0: # self.cancel_all() # 发出状态更新事件 orderList=[] if trade.offset==Offset.OPEN and trade.direction==Direction.LONG: #多头成交,设置止损单 orderList=self.sell(self.bollMidDay-self.priceTick, trade.volume, True) print (u"委托止损单,日线中轨平仓") if orderList: print( u"委托单成功单号",orderList) else : print (u"委托单失败") elif trade.offset==Offset.OPEN and trade.direction==Direction.SHORT: #空头成交,设置止损单 orderList=self.cover(self.bollMidDay+self.priceTick, trade.volume, True) print (u"委托止损单,日线中轨平仓") if orderList: print( u"委托单成功单号",orderList) else : print (u"委托单失败") elif trade.offset==Offset.CLOSE: zhishun=(self.bollUpDay-self.bollDownDay)/2 volume=self.caculate_pos(zhishun) #日线盘整,上下轨开仓 if self.pos==0 and volume!=0:#len(self.tradedata_day)==0: self.cancel_all() orderList=[] orderList=self.buy(self.bollUpDay+self.priceTick, volume, True) print (u"策略:%s,委托多单,日线上轨开仓"%self.className) if orderList: print (u"策略:%s,委托单成功,单号%s"%(self.className,orderList[-1])) else: print (u"策略:%s,委托单失败"%self.className) orderList=[] orderList=self.short(self.bollDownDay-self.priceTick, volume, True) print (u"策略:%s,委托空单,日线下轨开仓"%self.className) if orderList: print (u"策略:%s,委托单成功,单号%s"%(self.className,orderList[-1])) else: print (u"策略:%s,委托单失败"%self.className ) #更新周期状态 if trade.offset==Offset.OPEN: if trade.direction==Direction.LONG: self.dealopen=1 self.DayTrendStatus="duotou" self.FifteenMinTrendStatus='duotou' self.FiveMinTrendStatus='duotou' self.ThirtyMinTrendStatus='duotou' else: self.dealopen=-1 self.DayTrendStatus="kongtou" self.FifteenMinTrendStatus='kongtou' self.FiveMinTrendStatus='kongtou' self.ThirtyMinTrendStatus='kongtou' if trade.offset==Offset.CLOSE: if trade.direction==Direction.LONG: self.ThirtyMinTrendStatus='kongtou' self.DayTrendStatus="panzhen" self.deal=1 else: self.deal=-1 self.put_event() #---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" pass
class RsiAdaptStrategy(CtaTemplate): """ 策略逻辑: 一、、过虑信号 (小时周期) 使用rsiboll来判断信号强弱 二、开单信号 (分钟周期) 1、使用布林上下轨作为开单条件 三、止损 使用动态布林中轨止损 """ author = "yunya" min_window = 15 open_window = 5 rsi_length = 15 boll_length = 80 boll_dev = 2.0 trading_size = 1 rsi_value = 0 rsi_up = 0 rsi_dow = 0 rsi_entry = 0 boll_up = 0 boll_down = 0 boll_mid = 0 boll_length_new = 0 current_boll_mid = 0 last_boll_mid = 0 current_close = 0 last_close = 0 front_close = 0 exit_long = 0 exit_short = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 parameters = [ "min_window", "open_window", "rsi_length", "boll_length", "boll_dev", "trading_size", ] variables = [ "rsi_value", "rsi_up", "rsi_dow", "rsi_entry", "boll_up", "boll_down", "boll_mid", "boll_length_new", "current_boll_mid", "last_boll_mid", "current_close", "last_close", "front_close", "exit_long", "exit_short", "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.atr_stop_array = np.zeros(10) self.bg_xminute = NewBarGenerator(on_bar=self.on_bar, window=self.min_window, on_window_bar=self.on_xminute_bar) self.am_xminute = ArrayManager(self.boll_length + 100) self.bg_open = NewBarGenerator(on_bar=self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar) self.am_open = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(10) self.put_event() def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动。。") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止。。") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_open.update_tick(tick) 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 if not self.pos: if self.rsi_entry > 0: self.buy(self.boll_up, self.trading_size, True) # print(bar.datetime, self.boll_up, self.trading_size) # print(bar.datetime, self.entry_up, self.trading_size, bar) elif self.rsi_entry < 0: self.short(self.boll_down, self.trading_size, True) elif self.pos > 0: # 仓位是long 时,如果价格下穿新布林中轨 con1 = bar.close_price < self.current_boll_mid con2 = bar.close_price >= self.last_boll_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.boll_length_new = self.boll_length # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.boll_mid else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if bar.close_price > ( (self.boll_mid + self.current_boll_mid) / 2): self.exit_long = bar.close_price elif bar.close_price < self.boll_mid: self.exit_long = bar.close_price else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.boll_mid self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: # 仓位是short 时,如果价格上穿新布林中轨 con1 = bar.close_price > self.current_boll_mid con2 = bar.close_price <= self.last_boll_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.boll_length_new = self.boll_length self.exit_short = self.boll_mid else: if bar.close_price < (self.boll_mid + self.current_boll_mid / 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), 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 rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length) ema_array = talib.EMA(self.am_xminute.close, self.rsi_length) dev_array = abs(self.am_xminute.close[:-1] - ema_array[:-1]) / rsi_array rsi_up_array = rsi_array + rsi_array * dev_array rsi_dow_array = rsi_array - rsi_array * dev_array self.rsi_value = self.am_xminute.rsi(self.rsi_length) self.rsi_up = rsi_up_array[-1] self.rsi_dow = rsi_dow_array[-1] current_rsi_up = rsi_up_array[-1] current_rsi_down = rsi_dow_array[-1] if self.rsi_value > current_rsi_up: self.rsi_entry = 1 elif self.rsi_value < current_rsi_down: self.rsi_entry = -1 self.boll_up, self.boll_down = self.am_xminute.boll( self.boll_length, self.boll_dev) self.boll_mid = self.am_xminute.sma(self.boll_length) self.current_close = self.am_xminute.close[-1] self.last_close = self.am_xminute.close[-2] self.front_close = self.am_xminute.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.boll_length_new = self.boll_length elif self.pos > 0: # 上涨或下跌时,布林中轨均值减1 close_long = self.current_close > self.last_close > self.front_close if close_long: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 5) elif self.pos < 0: close_short = self.current_close < self.last_close < self.front_close if close_short: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 5) boll_mid_new = self.am_xminute.sma(self.boll_length_new, True) self.current_boll_mid = boll_mid_new[-1] self.last_boll_mid = boll_mid_new[-2] self.sync_data() def on_trade(self, trade: TradeData): """ 有成交时 Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ 订单更新回调 Callback of new order data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event()
class ImprovedDtStrategy(CtaTemplate): """""" author = "用Python的交易员" fixed_size = 1 k1 = 0.15 k2 = 0.25 rsi_window = 30 rsi_signal = 10 trailing_long = 0.8 trailing_short = 1.4 daily_limit = 0 day_open = 0 day_high = 0 day_low = 0 day_range = 0 long_entry = 0 short_entry = 0 intra_trade_high = 0 intra_trade_low = 0 daily_count = 0 parameters = [ "k1", "k2", "rsi_window", "rsi_signal", "trailing_long", "trailing_short", "fixed_size" ] variables = ["day_range", "long_entry", "short_entry"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() self.last_bar = None 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) # 计算DT范围 if not self.last_bar: self.last_bar = bar return if self.last_bar.datetime.date() != bar.datetime.date(): if self.day_high: self.day_range = self.day_high - self.day_low self.long_entry = bar.open_price + self.k1 * self.day_range self.short_entry = bar.open_price - self.k2 * self.day_range self.day_open = bar.open_price self.day_high = bar.high_price self.day_low = bar.low_price self.long_entered = False self.short_entered = False self.daily_count = 0 else: self.day_high = max(self.day_high, bar.high_price) self.day_low = min(self.day_low, bar.low_price) self.last_bar = bar if not self.day_range or not self.am.inited: return # 计算技术指标 rsi_value = self.am.rsi(self.rsi_window) # 交易逻辑执行 if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.daily_count < self.daily_limit: if rsi_value >= 50 + self.rsi_signal: self.buy(self.long_entry, self.fixed_size, True) elif rsi_value <= 50 - self.rsi_signal: self.short(self.short_entry, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price long_stop = self.intra_trade_high * (1 - self.trailing_long / 100) long_stop = max(long_stop, self.short_entry) self.sell(long_stop, self.fixed_size, True) self.short(self.short_entry, self.fixed_size, True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_stop = self.intra_trade_low * (1 + self.trailing_short / 100) short_stop = min(short_stop, self.long_entry) self.cover(short_stop, self.fixed_size, True) self.buy(self.long_entry, self.fixed_size, 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 RsiSignal(CtaSignal): """""" minute_5_window = 5 minute_15_window = 15 minute_30_window = 30 hour_1_window = 1 ris_15_value = 0 def __init__(self, rsi_fast_window: int, rsi_middle_window: int, rsi_slow_window: int, rsi_level: float): """Constructor""" super().__init__() self.rsi_fast_window = rsi_fast_window self.rsi_middle_window = rsi_middle_window self.rsi_slow_window = rsi_slow_window self.rsi_level = rsi_level self.rsi_long = 50 + self.rsi_level self.rsi_short = 50 - self.rsi_level self.bg5 = BarGenerator(on_bar=self.on_bar, window=self.minute_5_window, on_window_bar=self.on_5minute_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(on_bar=self.on_bar, window=self.minute_15_window, on_window_bar=self.on_15minute_bar) self.am15 = ArrayManager() self.bg30 = BarGenerator(on_bar=self.on_bar, window=self.minute_30_window, on_window_bar=self.on_15minute_bar) self.am30 = ArrayManager() self.bg60 = BarGenerator(on_bar=self.on_bar, window=self.hour_1_window, on_window_bar=self.on_hour_bar, interval=Interval.HOUR) self.am60 = ArrayManager() 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.am60.update_bar(bar) self.am30.update_bar(bar) self.am15.update_bar(bar) self.bg5.update_bar(bar) def on_5minute_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am5.update_bar(bar) if not self.am5.inited: self.set_signal_pos(0) return rsi_fast_value = self.am5.rsi(self.rsi_fast_window, True) rsi_middle_value = self.am5.rsi(self.rsi_middle_window, True) rsi_slow_value = self.am5.rsi(self.rsi_slow_window, True) if rsi_value >= self.rsi_long: self.set_signal_pos(1) elif rsi_value <= self.rsi_short: self.set_signal_pos(-1) else: self.set_signal_pos(0) def on_15minute_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am15.update_bar(bar) if not self.am15.inited: return rsi_fast_value = self.am15.rsi(self.rsi_fast_window, True) rsi_middle_value = self.am15.rsi(self.rsi_middle_window, True) rsi_slow_value = self.am15.rsi(self.rsi_slow_window, True) last_fast_value = rsi_fast_value[-1] current_fast_value = rsi_fast_value[-2] last_middle_value = rsi_middle_value[-1] current_middle_value = rsi_middle_value[-2] last_slow_value = rsi_slow_value[-1] current_slow_value = rsi_slow_value[-2] def on_30minute_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am30.update_bar(bar) if not self.am30.inited: return rsi_fast_value = self.am30.rsi(self.rsi_fast_window, True) rsi_middle_value = self.am30.rsi(self.rsi_middle_window, True) rsi_slow_value = self.am30.rsi(self.rsi_slow_window, True) last_fast_value = rsi_fast_value[-1] current_fast_value = rsi_fast_value[-2] last_middle_value = rsi_middle_value[-1] current_middle_value = rsi_middle_value[-2] last_slow_value = rsi_slow_value[-1] current_slow_value = rsi_slow_value[-2] def on_hour_bar(self, bar: BarData): """ Callback of new bar data update. """ self.am60.update_bar(bar) if not self.am60.inited: return def on_rsi(self,close, fast, slow, rsi_long, rsi_short): """ 判断 rsi 在80 20线上下方金叉,死叉 :param close: :param fast: :param middle: :param slow: :param rsi_long: :param rsi_short: :return: """ rsi_fast_value = talib.RSI(close, fast) rsi_slow_value = talib.RSI(close, slow) last_fast_value = rsi_fast_value[-2] current_fast_value = rsi_fast_value[-1] last_slow_value = rsi_slow_value[-2] current_slow_value = rsi_slow_value[-1] # 判断 20线 下方 金叉 if last_fast_value < rsi_short: if last_fast_value <= last_slow_value and current_fast_value > current_slow_value: rsi_long_inited = 1 elif last_fast_value >= last_slow_value and current_fast_value < current_slow_value: rsi_long_inited = -1 else: rsi_long_initde = 0
class MaxSharpeStrategy(CtaTemplate): M = 10 predictor = PositionPredictor(M) if exists('weights.h5'): predictor.load_weights('weights.h5') parameters = ["M"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): super(MaxSharpeStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager(3 + self.M) # am.shape = (3 + M) def on_init(self): self.write_log('策略初始化') self.load_bar(len(self.cta_engine.history_data)) self.mu = self.cta_engine.capital / self.cta_engine.size # how many possible positions def on_start(self): self.write_log('策略启动') def on_stop(self): self.write_log('策略停止') def on_tick(self, tick: TickData): self.bg.update_tick(tick) def on_bar(self, bar: BarData): self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return xt = np.ones((self.M + 3), dtype=np.float32) # xt.shape = (M + 3) for i in range(1, self.M + 2): xt[i] = self.am.close[i] - self.am.close[i - 1] xt[self.M + 2] = self.pos / self.mu xt = tf.expand_dims(xt, axis=0) # xt.shape = (batch = 1, M + 3) F_t = self.predictor(xt) pos = int(F_t * self.mu) if self.pos > 0 and pos > 0: if pos > self.pos: self.buy(bar.close_price, pos - self.pos, stop=True) if pos < self.pos: self.sell(bar.close_price, self.pos - pos, stop=True) elif self.pos > 0 and pos < 0: self.sell(bar.close_price, abs(self.pos), stop=True) self.short(bar.close_price, abs(pos), stop=True) elif self.pos < 0 and pos < 0: if pos < self.pos: self.short(bar.close_price, self.pos - pos, stop=True) if pos > self.pos: self.cover(bar.close_price, pos - self.pos, stop=True) else: # self.pos < 0 and pos > 0 self.cover(bar.close_price, abs(self.pos), stop=True) self.buy(bar.close_price, abs(pos), stop=True) 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
def _update_k_data(self, code, k_data): # 注意:所有的数据库数据和列表数据都按照日期的正序排序(从小到大) """ 更新股票,股指每日数据(行情,K线,市值等0) @:param code 股票(指数)代码 @:param k_data ts中获取的最新df数据 """ if len(k_data) != 0: k_data = k_data.sort_values(by='trade_date') cl_stock_code = self.db[code] cl_stock_code.create_index([('trade_date', ASCENDING)], unique=True) # 更新k线数据 # 1、新增日K线入库 # 2、遍历数据库找出最近的500+22(必须保证更新数据操作在22天以内进行)条数据并更新最后的22条的ma和最高 最低价 for ix, row in k_data.iterrows(): d = row.to_dict() d['ts_code'] = d['ts_code'].replace('.', '_') if self._is_in_vnpy_db(d['ts_code'], update=True): # 更新vnpy数据库数据 self._build_db_vnpy(d) flt = {'trade_date': d['trade_date']} cl_stock_code.replace_one(flt, d, upsert=True) rec = list(cl_stock_code.find({}).sort("trade_date", DESCENDING).limit(522)) rec.reverse() am = ArrayManager(size=600) last_5_vol = deque([0.0] * 5) last_5_amount = deque([0.0] * 5) for d in rec: if 0.0 not in last_5_vol: vol_rate = d['vol'] / (sum(last_5_vol) / 5.0) amount_rate = d['amount'] / (sum(last_5_amount) / 5.0) d['vol_rate'] = vol_rate d['amount_rate'] = amount_rate else: d['vol_rate'] = 0.0 d['amount_rate'] = 0.0 last_5_vol.popleft() last_5_amount.popleft() last_5_vol.append(d['vol']) last_5_amount.append(d['amount']) if d['ts_code'][-3:] == '_SH': exchange = Exchange.SSE d['exchange'] = 'SSE' else: exchange = Exchange.SZSE d['exchange'] = 'SZSE' bar = BarData( gateway_name='ctp', symbol=d['ts_code'], exchange=exchange, datetime=string_to_datetime(d['trade_date'])) bar.symbol = d['ts_code'] bar.volume = d['vol'] bar.open_price = d['open'] bar.high_price = d['high'] bar.low_price = d['low'] bar.close_price = d['close'] am.update_bar(bar) if d['trade_date'] >= self.db_date: d['ma_5'] = am.sma(5) d['ma_10'] = am.sma(10) d['ma_20'] = am.sma(20) d['ma_30'] = am.sma(30) d['ma_60'] = am.sma(60) d['ma_120'] = am.sma(120) d['ma_250'] = am.sma(250) d['ma_500'] = am.sma(500) d['high_5'] = np.max(am.high[-5:]) d['high_10'] = np.max(am.high[-10:]) d['high_20'] = np.max(am.high[-20:]) d['high_30'] = np.max(am.high[-30:]) d['high_60'] = np.max(am.high[-60:]) d['high_120'] = np.max(am.high[-120:]) d['high_250'] = np.max(am.high[-250:]) d['high_500'] = np.max(am.high[-500:]) d['low_5'] = np.min(am.low[-5:]) d['low_10'] = np.min(am.low[-10:]) d['low_20'] = np.min(am.low[-20:]) d['low_30'] = np.min(am.low[-30:]) d['low_60'] = np.min(am.low[-60:]) d['low_120'] = np.min(am.low[-120:]) d['low_250'] = np.min(am.low[-250:]) d['low_500'] = np.min(am.low[-500:]) flt = {'trade_date': d['trade_date']} cl_stock_code.replace_one(flt, d, upsert=True)
class TurtleSignalStrategy(CtaTemplate): """""" author = "用Python的交易员" entry_window = 20 exit_window = 10 atr_window = 20 fixed_size = 1 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 parameters = ["entry_window", "exit_window", "atr_window", "fixed_size"] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TurtleSignalStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.entry_up, self.entry_down = self.am.donchian(self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) elif self.pos > 0: self.send_buy_orders(self.long_entry) sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: self.send_short_orders(self.short_entry) cover_price = min(self.short_stop, self.exit_up) self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def send_buy_orders(self, price): """""" t = self.pos / self.fixed_size if t < 1: self.buy(price, self.fixed_size, True) if t < 2: self.buy(price + self.atr_value * 0.5, self.fixed_size, True) if t < 3: self.buy(price + self.atr_value, self.fixed_size, True) if t < 4: self.buy(price + self.atr_value * 1.5, self.fixed_size, True) def send_short_orders(self, price): """""" t = self.pos / self.fixed_size if t > -1: self.short(price, self.fixed_size, True) if t > -2: self.short(price - self.atr_value * 0.5, self.fixed_size, True) if t > -3: self.short(price - self.atr_value, self.fixed_size, True) if t > -4: self.short(price - self.atr_value * 1.5, self.fixed_size, True)
class CincoStrategyHN(CtaTemplate): """""" author = "Huang Ning" boll_window = 42 boll_dev = 2.0 trailing_long = 0.65 trailing_short = 0.7 atr_window = 10 risk_level = 100 boll_up = 0 boll_down = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "boll_window", "boll_dev", "trailing_long", "trailing_short", "atr_window", "risk_level" ] variables = [ "boll_up", "boll_down", "trading_size", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "atr_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(CincoStrategyHN, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """""" self.write_log("策略初始化") self.load_bar(10) def on_start(self): """""" self.write_log("策略启动") def on_stop(self): """""" self.write_log("策略停止") def on_tick(self, tick: TickData): """""" self.bg.update_tick(tick) def on_bar(self, bar: BarData): """""" self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) boll_width = self.boll_up - self.boll_down if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.trading_size = int(self.risk_level / self.atr_value) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 self.buy(self.boll_up, self.trading_size, stop=True) self.short(self.boll_down, self.trading_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_order(self, order: OrderData): """""" def on_trade(self, trade: TradeData): """""" self.put_event() def on_stop_order(self, stop_order: StopOrder): """""" self.put_event()
class SuperTurtleStrategyHNTest(CtaTemplate): """""" author = "Huang Ning" entry_window = 28 exit_window = 7 atr_window = 4 risk_level = 0.2 trading_size = 0 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 parameters = ["entry_window", "exit_window", "atr_window", "risk_level"] variables = [ "entry_up", "entry_down", "exit_up", "exit_down", "trading_size", "atr_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 1, self.on_hour_bar, interval=Interval.HOUR) self.am = ArrayManager() def on_init(self): """""" self.write_log("策略初始化") self.load_bar(20) def on_start(self): """""" self.write_log("策略启动") def on_stop(self): """""" self.write_log("策略停止") def on_tick(self, tick: TickData): """""" self.bg.update_tick(tick) def on_bar(self, bar: BarData): """""" self.bg.update_bar(bar) def on_hour_bar(self, bar: BarData): """""" self.am.update_bar(bar) if not self.am.inited: return self.entry_up, self.entry_down = self.am.donchian(self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) if self.atr_value == 0: return atr_risk = talib.ATR(1 / self.am.high, 1 / self.am.low, 1 / self.am.close, self.atr_window)[-1] self.trading_size = max(int(self.risk_level / atr_risk), 1) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 self.buy(self.entry_up, self.trading_size, True) self.short(self.entry_down, self.trading_size, True) elif self.pos > 0: sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: cover_price = min(self.short_stop, self.exit_up) self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class MultiTimeframeStrategyHNTest(CtaTemplate): """""" author = "Huang Ning" parameters = [] variables = [] 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.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 RSIStrategy(CtaTemplate): """""" author = "用Python的交易员" no_trade_time_begin1 = time(hour=9, minute=0) no_trade_time_end1 = time(hour=9, minute=30) no_trade_time_begin2 = time(hour=23, minute=0) no_trade_time_end2 = time(hour=23, minute=30) load_bar_day = 20 boll_window = 16 boll_dev = 2.6 # cci_window = 10 atr_window = 30 # atr_ma_window = 10 rsi_f_window = 5 rsi_l_window = 10 grow_window = 5 reduce_window = 5 # rsi_entry = 16 # ma_window = 5 sl_multiplier = 7.6 fixed_size = 1 db_record = 0 bar_size = 100 boll_up = 0 boll_down = 0 # cci_value = 0 atr_value = 0 # atr_ma = 0 rsi_f_value = 0 rsi_l_value = 0 rsi_max_value = 0 rsi_min_value = 0 rsi_f_ma = 0 rsi_l_ma = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 vt_1m_orderids = [] vt_15m_orderids = [] parameters = [ "boll_window", "boll_dev", "atr_window", "rsi_f_window", "rsi_l_window", "grow_window", "reduce_window", "sl_multiplier", "fixed_size", "bar_size", "db_record" ] variables = [ "boll_up", "boll_down", "atr_value", "rsi_f_value", "rsi_l_value", "rsi_f_ma", "rsi_l_ma", "rsi_max_value", "rsi_min_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] # parameters = ["boll_window", "boll_dev", "cci_window","rsi_window","rsi_entry","ma_window", # "atr_window","atr_ma_window","sl_multiplier", "fixed_size"] # variables = ["boll_up", "boll_down", "cci_value", "atr_value","atr_ma","rsi_value", # "intra_trade_high", "intra_trade_low", "long_stop", "short_stop"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) #todo,多时间周期,分长短期,判断不同的指标 self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) #self.am_1m = ArrayManager() self.am_15m = ArrayManager(self.bar_size) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(self.load_bar_day) 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_order_list(self.vt_1m_orderids) # self.am_1m.update_bar(bar) # if not self.am_1m.inited: # return # # #todo 1分钟的策略 # # self.boll_up, self.boll_down = self.am_1m.boll(self.boll_window, self.boll_dev) # self.atr_value = self.am_1m.atr(self.atr_window) # rsi_f_array = self.am_1m.rsi(self.rsi_f_window, array=True) # rsi_l_array = self.am_1m.rsi(self.rsi_l_window, array=True) # self.rsi_f_value = rsi_f_array[-1] # self.rsi_l_value = rsi_l_array[-1] # # if self.pos == 0: # self.intra_trade_high = bar.high_price # self.intra_trade_low = bar.low_price # # # todo,波动不够大,应该过滤 # if self.rsi_f_value > self.rsi_l_value and if_keep_grow(self.grow_window, rsi_f_array): # vt_orderids = self.buy(self.boll_up, self.fixed_size, True) # self.vt_1m_orderids.extend(vt_orderids) # elif self.rsi_f_value < self.rsi_l_value and if_keep_reduce(self.reduce_window, rsi_f_array): # vt_orderids = self.short(self.boll_down, self.fixed_size, True) # self.vt_1m_orderids.extend(vt_orderids) # # todo,持续范围内小波动,震荡策略 # # # # elif self.pos > 0: # self.intra_trade_high = max(self.intra_trade_high, bar.high_price) # self.intra_trade_low = bar.low_price # if if_keep_reduce(self.reduce_window, rsi_f_array): # self.rsi_f_value < self.rsi_l_value and # vt_orderids = self.sell(bar.close_price - 5, abs(self.pos)) # else: # self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier # vt_orderids = self.sell(self.long_stop, abs(self.pos), True) # self.vt_1m_orderids.extend(vt_orderids) # elif self.pos < 0: # self.intra_trade_high = bar.high_price # self.intra_trade_low = min(self.intra_trade_low, bar.low_price) # if if_keep_grow(self.grow_window, rsi_f_array): # self.rsi_f_value > self.rsi_l_value and # vt_orderids = self.cover(bar.close_price + 5, abs(self.pos)) # else: # self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier # vt_orderids = self.cover(self.short_stop, abs(self.pos), True) # self.vt_1m_orderids.extend(vt_orderids) # if self.db_record: # database_manager.save_bar_calc(bar, self.get_variables()) # # self.put_event() self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_order_list(self.vt_15m_orderids) self.am_15m.update_bar(bar) if not self.am_15m.inited: return self.boll_up, self.boll_down = self.am_15m.boll( self.boll_window, self.boll_dev) #self.cci_value = am.cci(self.cci_window) self.atr_value = self.am_15m.atr(self.atr_window) # atr_array = am.atr(self.atr_window, array=True) # self.atr_value = atr_array[-1] #self.atr_ma = atr_array[-self.atr_ma_window:].mean() rsi_f_array = self.am_15m.rsi(self.rsi_f_window, array=True) rsi_l_array = self.am_15m.rsi(self.rsi_l_window, array=True) # self.rsi_max_value = rsi_f_array[-self.rsi_f_window:].max() # self.rsi_min_value = rsi_f_array[-self.rsi_f_window:].min() # self.rsi_f_ma = rsi_f_array[-self.rsi_f_window:].mean() # self.rsi_l_ma = rsi_f_array[-self.rsi_f_window:].mean() self.rsi_f_value = rsi_f_array[-1] self.rsi_l_value = rsi_l_array[-1] #self.ma_value = am.sma(self.ma_window) # if (bar.datetime.time() >= self.no_trade_time_begin1 and bar.datetime.time() <= self.no_trade_time_end1) \ # or (bar.datetime.time() >= self.no_trade_time_begin2 and bar.datetime.time() <= self.no_trade_time_end2): # return if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price #todo,波动不够大,应该过滤 #if self.rsi_f_value > 50 and self.rsi_f_value > self.rsi_l_value and if_keep_grow(self.grow_window, rsi_f_array) and self.rsi_f_value < 85: #self.rsi_f_value>=self.rsi_max_value: if self.rsi_f_value > self.rsi_l_value: #and if_keep_grow(self.grow_window, rsi_f_array): #self.buy(bar.close_price+5, self.fixed_size) vt_orderids = self.buy(self.boll_up, self.fixed_size, True) self.vt_15m_orderids.extend(vt_orderids) #elif self.rsi_f_value < 50 and self.rsi_f_value < self.rsi_l_value and if_keep_reduce(self.reduce_window, rsi_f_array) and self.rsi_f_value >15: #self.rsi_f_value <=self.rsi_min_value: elif self.rsi_f_value < self.rsi_l_value: # and if_keep_reduce(self.reduce_window, rsi_f_array): #self.short(bar.close_price-5, self.fixed_size) vt_orderids = self.short(self.boll_down, self.fixed_size, True) self.vt_15m_orderids.extend(vt_orderids) #todo,持续范围内小波动,震荡策略 elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price if if_keep_reduce( self.reduce_window, rsi_f_array): #self.rsi_f_value < self.rsi_l_value and vt_orderids = self.sell(bar.close_price - 5, abs(self.pos)) else: self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier vt_orderids = self.sell(self.long_stop, abs(self.pos), True) self.vt_15m_orderids.extend(vt_orderids) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) if if_keep_grow( self.grow_window, rsi_f_array): #self.rsi_f_value > self.rsi_l_value and vt_orderids = self.cover(bar.close_price + 5, abs(self.pos)) else: self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier vt_orderids = self.cover(self.short_stop, abs(self.pos), True) self.vt_15m_orderids.extend(vt_orderids) if self.db_record: database_manager.save_bar_calc(bar, self.get_variables()) 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. """ #数据库记录成交记录,bar记录,variables值 if self.db_record: database_manager.save_trade_data(trade, self.get_variables()) self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class AroonAtrStrategy(CtaTemplate): """""" author = "tonywang_efun" fixed_size = 1 bar_window = 26 boll_window = 39 boll_dev = 1.9 aroon_window = 14 aroon_long = 50 aroon_short = 50 atr_window = 30 atr_stop_multiplier = 3 boll_up = 0 boll_down = 0 aroon_up = 0 aroon_down = 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", "aroon_window", "aroon_long", "aroon_short", "atr_window", "atr_stop_multiplier" ] variables = [ "boll_up", "boll_down", "aroon_up", "aroon_down", "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.aroon_up, self.aroon_down = self.am.aroon(self.aroon_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.aroon_up > self.aroon_down and self.aroon_up > self.aroon_long: self.buy(self.boll_up, self.fixed_size, stop=True) if self.aroon_down > self.aroon_up and self.aroon_down > self.aroon_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 BollingerBotStrategy(CtaTemplate): """基于布林通道的交易策略""" className = 'BollingerBotStrategy' author = u'ForwardCapital' # 策略参数 bollWindow = 28 # 通道窗口数 entryDev = 3.2 # 开仓偏差 exitDev = 1.2 # 平仓偏差 trailingPrcnt = 0.4 # 移动止损百分比 maWindow = 10 # 过滤用均线窗口 initDays = 10 # 初始化数据所用的天数 fixedSize = 1 # 每次交易的数量 # 策略变量 bollMid = 0 # 布林带中轨 bollStd = 0 # 布林带宽度 entryUp = 0 # 开仓上轨 exitUp = 0 # 平仓上轨 maFilter = 0 # 均线过滤 maFilter1 = 0 # 上一期均线 intraTradeHigh = 0 # 持仓期内的最高点 longEntry = 0 # 多头开仓 longExit = 0 # 多头平仓 orderList = [] # 保存委托代码的列表 buyOrderID = None sellOrderID = None # 参数列表,保存了参数的名称 paramList = [ 'name', 'className', 'author', 'vtSymbol', 'bollWindow', 'entryDev', 'exitDev', 'trailingPrcnt', 'maWindow', 'initDays', 'fixedSize' ] # 变量列表,保存了变量的名称 varList = [ 'inited', 'trading', 'pos', 'bollMid', 'bollStd', 'entryUp', 'exitUp', 'intraTradeHigh', 'longEntry', 'longExit' ] # 同步列表 syncList = ['pos', 'intraTradeHigh'] #---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): """Constructor""" super(BollingerBotStrategy, 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): """收到5分钟K线""" # 保存K线数据 self.am.update_bar(bar) if not self.am.inited or not self.trading: return # 撤销之前发出的尚未成交的委托(包括限价单和停止单) # 计算指标数值 self.bollMid = self.am.sma(self.bollWindow) self.bollStd = self.am.std(self.bollWindow) self.entryUp = self.bollMid + self.bollStd * self.entryDev self.exitUp = self.bollMid + self.bollStd * self.exitDev maArray = self.am.sma(self.maWindow, True) self.maFilter = maArray[-1] self.maFilter1 = maArray[-2] # 判断是否要进行交易 if not self.buyOrderID: if self.pos == 0: self.intraTradeHigh = bar.high # 下开仓单 if bar.close > self.maFilter and self.maFilter > self.maFilter1: self.longEntry = self.entryUp self.buyOrderID = self.buy(self.longEntry, self.fixedSize, True) self.buyOrderID = self.orderIDConvert(self.buyOrderID) print('order None!!!buyOrderID is : %s ' % self.buyOrderID) self.orderList.append(self.buyOrderID) # 下平仓单 self.longExit = self.intraTradeHigh * ( 1 - self.trailingPrcnt / 100) self.longExit = min(self.longExit, self.exitUp) self.sellOrderID = self.sell(self.longExit, abs(self.pos), True) self.sellOrderID = self.orderIDConvert(self.sellOrderID) print('order None!!!ellOrderID is : %s ' % self.sellOrderID) self.orderList.append(self.sellOrderID) elif self.pos > 0: self.intraTradeHigh = max(self.intraTradeHigh, bar.high) # 下平仓单 self.longExit = self.intraTradeHigh * ( 1 - self.trailingPrcnt / 100) self.longExit = min(self.longExit, self.exitUp) self.sellOrderID = self.sell(self.longExit, abs(self.pos), True) self.sellOrderID = self.orderIDConvert(self.sellOrderID) print('order None!!!sellOrderID is : %s ' % self.sellOrderID) self.orderList.append(self.sellOrderID) else: if self.buyOrderID in self.orderList: self.intraTradeHigh = bar.high self.cancel_all() # 下开仓单 if bar.close > self.maFilter and self.maFilter > self.maFilter1: self.longEntry = self.entryUp self.buyOrderID = self.buy(self.longEntry, self.fixedSize, True) print('buyOrderID is : %s ' % self.buyOrderID) self.buyOrderID = self.orderIDConvert(self.buyOrderID) self.orderList.append(self.buyOrderID) # 下平仓单 self.longExit = self.intraTradeHigh * ( 1 - self.trailingPrcnt / 100) self.longExit = min(self.longExit, self.exitUp) self.sellOrderID = self.sell(self.longExit, abs(self.pos), True) self.sellOrderID = self.orderIDConvert(self.sellOrderID) print('sellOrderID is : %s ' % self.sellOrderID) self.orderList.append(self.sellOrderID) else: if self.sellOrderID in self.orderList: self.intraTradeHigh = max(self.intraTradeHigh, bar.high) self.cancel_order(self.sellOrderID) # 下平仓单 self.longExit = self.intraTradeHigh * ( 1 - self.trailingPrcnt / 100) self.longExit = min(self.longExit, self.exitUp) self.sellOrderID = self.sell(self.longExit, abs(self.pos), True) self.sellOrderID = self.orderIDConvert(self.sellOrderID) print('sellOrderID is : %s ' % self.sellOrderID) self.orderList.append(self.sellOrderID) else: self.intraTradeHigh = bar.high # 下开仓单 if bar.close > self.maFilter and self.maFilter > self.maFilter1: self.longEntry = self.entryUp self.buyOrderID = self.buy(self.longEntry, self.fixedSize, True) self.buyOrderID = self.orderIDConvert(self.buyOrderID) print('buyOrderID is : %s ' % self.buyOrderID) self.orderList.append(self.buyOrderID) # 下平仓单 self.longExit = self.intraTradeHigh * ( 1 - self.trailingPrcnt / 100) self.longExit = min(self.longExit, self.exitUp) self.sellOrderID = self.sell(self.longExit, abs(self.pos), True) self.sellOrderID = self.orderIDConvert( self.sellOrderID) print('sellOrderID is : %s ' % self.sellOrderID) self.orderList.append(self.sellOrderID) # 发出状态更新事件 # self.putEvent() #---------------------------------------------------------------------- def onOrder(self, order): """收到委托变化推送(必须由用户继承实现)""" pass #---------------------------------------------------------------------- def onTrade(self, trade): # 发出状态更新事件 self.put_event() #---------------------------------------------------------------------- def onStopOrder(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 HLBeatStrategy(CtaTemplate): """基于布林通道的交易策略""" className = 'HLBeatStrategy' author = u'ForwardCapital' # 策略参数 turtleWindow = 20 # 通道窗口数 ma1Window = 5 # 过滤用均线窗口 ma2Window = 10 # 过滤用均线窗口 initDays = 10 # 初始化数据所用的天数 fixedSize = 1 # 每次交易的数量 xMinBar = 15 # 策略变量 periodHigh = 0 # 布林带中轨 periodLow = 0 # 布林带宽度 entryUp = 0 # 开仓上轨 longEntry = 0 entryDown = 0 shortEntry = 0 # 开仓下轨 exitUp = 0 # 平仓上轨 shortExit = 0 exitDown = 0 longExit = 0 # 平仓上轨 CCIFilter = 0 # 均线过滤 CCIFilter1 = 0 # 上一期均线 intraTradeHigh = 0 # 持仓期内的最高点 intraTradeLow = 0 # 持仓期内的最低点 longEntry = 0 # 多头开仓 longExit = 0 # 多头平仓 orderList = [] # 保存委托代码的列表 buyOrderID = None sellOrderID = None shortOrderID = None coverOrderID = None minute = None timeFuncTurn = False # 参数列表,保存了参数的名称 paramList = [ 'className', 'author', 'vtSymbol', "turtleWindow", "ma1Window", "ma2Window", "xMinBar" ] # 变量列表,保存了变量的名称 varList = [] # 同步列表 syncList = [ 'pos', 'sellOrderID', 'coverOrderID', 'shortOrderID', 'buyOrderID', 'longExit', 'shortExit', 'orderList' ] #---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): """Constructor""" super(HLBeatStrategy, self).__init__(ctaEngine, setting) self.bm = BarGenerator(self.on_bar, self.xMinBar, self.onFiveBar) self.am = ArrayManager() self.cta_engine.eventEngine.register(EVENT_TIMER, self.onTimeFunc) #---------------------------------------------------------------------- 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) if not self.am.inited or not self.trading: return # 计算指标数值 self.exitUp = min(self.am.low[-self.turtleWindow / 2:]) self.exitDown = max(self.am.high[-self.turtleWindow / 2:]) # 只发平仓单 if self.pos > 0: if not self.longExit: self.longExit = self.exitDown if self.sellOrderID: self.cancel_order (self.sellOrderID) else: self.cancel_all() self.sellOrderID = self.sell(self.longExit, self.fixedSize, False) print(u'None sellOrderID###多头平仓,单号:%s' % self.sellOrderID) self.sellOrderID = self.orderIDConvert(self.sellOrderID) else: if self.longExit != self.exitDown: self.longExit = self.exitDown self.cancel_order(self.sellOrderID) elif self.pos < 0: if not self.shortExit: self.shortExit = self.exitUp if self.coverOrderID: self.cancel_order(self.coverOrderID) else: self.cancel_all() self.coverOrderID = self.cover(self.shortExit, self.fixedSize, False) print(u'None coverOrderID###空头平仓,单号:%s' % self.coverOrderID) self.coverOrderID = self.orderIDConvert(self.coverOrderID) else: if self.shortExit != self.exitUp: self.shortExit = self.exitUp self.cancel_order(self.coverOrderID) #---------------------------------------------------------------------- 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'highArray is ↓↓↓↓↓↓↓↓↓↓') print(self.am.high[-self.turtleWindow:]) print(u'lowArray is ↓↓↓↓↓↓↓↓↓↓') print(self.am.low[-self.turtleWindow:]) self.entryUp = max(self.am.high[-self.turtleWindow:]) self.entryDown = min(self.am.low[-self.turtleWindow:]) # self.exitUp = min(self.am.low[-self.turtleWindow/2:]) # self.exitDown = max(self.am.high[-self.turtleWindow/2:]) # print u'entryup:%s, entryDown:%s' % (self.entryUp, self.entryDown) # 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 self.buyOrderID in self.orderList: if self.pos == 0: if not self.longEntry: if (self.entryUp - self.entryDown) / self.entryUp < 0.006: print(u'%s 高低点太窄,放弃交易!' % self.vt_symbol) return self.longEntry = self.entryDown self.buyOrderID = self.buy(self.longEntry, self.fixedSize, False) self.buyOrderID = self.orderIDConvert(self.buyOrderID) self.orderList.append(self.buyOrderID) elif self.longEntry != self.entryDown: self.cancel_order(self.buyOrderID) if (self.entryUp - self.entryDown) / self.entryUp < 0.006: print(u'%s 高低点太窄,放弃交易!' % self.vt_symbol) return self.longEntry = self.entryDown self.buyOrderID = self.buy(self.longEntry, self.fixedSize, False) self.buyOrderID = self.orderIDConvert(self.buyOrderID) self.orderList.append(self.buyOrderID) if not self.shortOrderID or self.shortOrderID in self.orderList: if self.pos == 0: if not self.shortEntry: if (self.entryUp - self.entryDown) / self.entryUp < 0.006: print(u'%s 高低点太窄,放弃交易!' % self.vt_symbol) return self.shortEntry = self.entryUp self.shortOrderID = self.short(self.shortEntry, self.fixedSize, False) self.shortOrderID = self.orderIDConvert(self.shortOrderID) self.orderList.append(self.shortOrderID) elif self.shortEntry != self.entryUp: self.cancel_order(self.shortOrderID) if (self.entryUp - self.entryDown) / self.entryUp < 0.006: print(u'%s 高低点太窄,放弃交易!' % self.vt_symbol) return self.shortEntry = self.entryUp self.shortOrderID = self.short(self.shortEntry, self.fixedSize, False) self.shortOrderID = self.orderIDConvert(self.shortOrderID) self.orderList.append(self.shortOrderID) # 发出状态更新事件 # self.putEvent() #---------------------------------------------------------------------- def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" # print u'委托变化推送:%s' % order.__dict__ # if self.buyOrderID: # if order.orderID == self.buyOrderID.split('.')[1]: # if order.status == STATUS_CANCELLED: # self.orderList.remove(self.buyOrderID) # if self.shortOrderID: # if order.orderID == self.shortOrderID.split('.')[1]: # if order.status == STATUS_CANCELLED: # self.orderList.remove(self.shortOrderID) if self.sellOrderID: if order.orderID == self.sellOrderID.split('.')[1]: if order.status == Status.CANCELLED: self.sellOrderID = self.sell(self.longExit, self.fixedSize, False) print(u'###多头平仓,单号:%s' % self.sellOrderID) self.sellOrderID = self.orderIDConvert(self.sellOrderID) if self.coverOrderID: if order.orderID == self.coverOrderID.split('.')[1]: if order.status == Status.CANCELLED: self.coverOrderID = self.cover(self.shortExit, self.fixedSize, False) print(u'###空头平仓,单号:%s' % self.coverOrderID) self.coverOrderID = self.orderIDConvert(self.coverOrderID) pass #---------------------------------------------------------------------- def on_trade(self, trade): """收到成交推送(必须由用户继承实现)""" # print u'成交推送:%s' % trade.__dict__ if self.buyOrderID: if trade.tradeID == self.buyOrderID.split('.')[1]: self.orderList.remove(self.buyOrderID) if self.shortOrderID: if trade.tradeID == self.shortOrderID.split('.')[1]: self.orderList.remove(self.shortOrderID) if trade.offset in [ Offset.CLOSE, Offset.CLOSETODAY, Offset.CLOSEYESTERDAY ]: self.buyOrderID = None self.shortOrderID = None self.longExit = 0 self.shortExit = 0 # 发出状态更新事件 # self.putEvent() pass #---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" # print u'StopOrder回报,stopOrderID:%s, status:%s' % (so.stopOrderID, so.status) # if so.status == STOPORDER_CANCELLED or so.status == STOPORDER_TRIGGERED: # self.orderList.remove(so.stopOrderID) pass #---------------------------------------------------------------------- def onTimeFunc(self, event): now = dt.datetime.now() now_hour = now.hour now_minute = now.minute if self.minute != now_minute: self.minute = now_minute if not self.timeFuncTurn: self.timeFuncTurn = True if now_hour == 2 and now_minute == 32 and self.timeFuncTurn: self.cta_engine.saveSyncData(self) self.timeFuncTurn = False elif now_hour == 15 and now_minute == 10 and self.timeFuncTurn: self.buyOrderID = None self.shortOrderID = None self.coverOrderID = None self.sellOrderID = None self.longExit = 0 self.shortExit = 0 self.orderList = [] self.cta_engine.saveSyncData(self) self.timeFuncTurn = False
class Boll_Kc_Dc_Reverse_Strategy(CtaTemplate): """ 本策略为反向策略,币本位 Reverse 反向 """ author = "yunya" open_window = 2 xsmall_window = 15 com_length = 250 boll_kk_dev = 2.0 kk_atr_length = 30 sl_multiplier = 0.5 risk_level = 10000 trading_size = 0 xsmall_up_min = 0 xsmall_down_min = 0 xsmall_up_max = 0 xsmall_down_max = 0 xsmall_ema_mid = 0 xsmall_com_width = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 exit_up = 0 exit_down = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "open_window", "xsmall_window", "com_length", "boll_kk_dev", "kk_atr_length", "sl_multiplier", "risk_level", ] variables = [ "trading_size", "xsmall_up_min", "xsmall_down_min", "xsmall_up_max", "xsmall_down_max", "xsmall_ema_mid", "xsmall_com_width", "long_entry", "short_entry", "long_stop", "short_stop", "exit_up", "exit_down", "atr_value", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_xsmall = BarGenerator( on_bar=self.on_bar, window=self.xsmall_window, on_window_bar=self.on_xsmall_bar, interval=Interval.MINUTE ) self.am_xsmall = ArrayManager(self.com_length + 10) self.bg = BarGenerator(self.on_bar, self.open_window, self.on_open_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_xsmall.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) self.bg_xsmall.update_bar(bar) def on_open_bar(self,bar:BarData): """ :param bar: :return: """ # 先使用挂单全撤的粗化订单管理 self.cancel_all() self.am.update_bar(bar) if not self.am_xsmall.inited or not self.am.inited: return if self.pos == 0: # 根据布林带宽度动态调整仓位大小 self.trading_size = max(int(self.risk_level / self.xsmall_com_width), 1) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price # 如果价格突破 xsmall_up_min 线时,在xsmall_up_max 价格挂停止单 if self.am_xsmall.close[-1] >= self.xsmall_up_min and self.am.close[-1] >=self.xsmall_up_min: self.buy(self.xsmall_up_max,self.trading_size,True) # 如果价格突破 xsmall_down_min 线时,在xsmall_down_max 价格挂停止单 elif self.am_xsmall.close[-1] <= self.xsmall_down_min and self.am.close[-1] <= self.xsmall_down_min: self.short(self.xsmall_down_max,self.trading_size,True) elif self.pos > 0: # 成交价固定止损位与中轨中最大值为当前止损位 # self.exit_up = max(self.xsmall_ema_mid,self.long_stop) # 成交价回定止损 与最高价回撤一定比例通道宽度值 self.intra_trade_high = max(self.intra_trade_high,bar.high_price) self.intra_trade_low = bar.low_price exit_long_stop = self.intra_trade_high - self.xsmall_com_width * self.sl_multiplier self.exit_up = max(exit_long_stop,self.long_stop) self.sell(self.exit_up,abs(self.pos),True) elif self.pos < 0: # 成交价固定止损位与中轨中最小值为当前止损位 # self.exit_down = min(self.xsmall_ema_mid,self.short_stop) # 成交价回定止损 与最高价回撤一定比例通道宽度值 self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low,bar.low_price) exit_short_stop = self.intra_trade_low - self.xsmall_com_width * self.sl_multiplier self.exit_down = min(exit_short_stop,self.short_stop) self.cover(self.exit_down,abs(self.pos),True) self.sync_data() self.put_event() def on_xsmall_bar(self, bar: BarData): """ :param bar: :return: """ # x分钟 多策略合合成的通道线 self.am_xsmall.update_bar(bar) if not self.am_xsmall.inited : return self.xsmall_ema_mid,self.xsmall_com_width,self.xsmall_up_min, self.xsmall_down_min,\ self.xsmall_up_max, self.xsmall_down_max = self.boll_kc_dc_combination( high=self.am_xsmall.high[:-1], low=self.am_xsmall.low[:-1], close=self.am_xsmall.close[:-1], boll_kk_dev=self.boll_kk_dev, kk_atr_length=self.kk_atr_length, com_length=self.com_length ) # print(f"xsmall: mid:{self.xsmall_ema_mid},width:{self.xsmall_com_width},upmin:{self.xsmall_up_min},\ # downmin:{self.xsmall_down_min},upmax:{self.xsmall_up_max},downmax:{self.xsmall_down_max}" + "\n") self.atr_value = self.am_xsmall.atr(self.kk_atr_length) self.sync_data() self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value self.sync_data() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def boll_kc_dc_combination(self, high, close, low, boll_kk_dev,kk_atr_length,com_length): # 计算组合均线 ema_com = talib.EMA(close, com_length) # 计算布林带 boll_std = talib.STDDEV(close, com_length) boll_up = ema_com + boll_kk_dev * boll_std boll_down = ema_com - boll_kk_dev * boll_std # 计算肯特通道 kc_atr = talib.ATR(high, low, close, kk_atr_length) kc_up = ema_com + kc_atr * boll_kk_dev kc_dowm = ema_com - kc_atr * boll_kk_dev # 计算唐安奇通道 dc_up = talib.MAX(high, com_length) dc_down = talib.MIN(low, com_length) # 计算轨道 因kc通道是直接,最小值大概率是直接,所以去除 pass_up_min = min(dc_up[-1], boll_up[-1]) pass_down_min = max(dc_down[-1], boll_down[-1]) pass_up_max = max(kc_up[-1], dc_up[-1], boll_up[-1]) pass_down_max = min(kc_dowm[-1], dc_down[-1], boll_down[-1]) ema_mid = ema_com[-1] com_width = abs(pass_up_max - pass_down_max) return ema_mid, com_width, pass_up_min, pass_down_min, pass_up_max, pass_down_max
class 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 TurtleSignalStrategy(CtaTemplate): """""" author = "用Python的交易员" # 唐奇安上下轨突破的周期,买入位置 entry_window = 20 # 唐奇安通道,卖出位置 exit_window = 10 atr_window = 20 # 乘数,每次下单的单位大小 fixed_size = 1 entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 # 多头入场价,每次交易后,设置为当前交易价格 long_entry = 0 short_entry = 0 # 多头止损价格 long_stop = 0 short_stop = 0 parameters = ["entry_window", "exit_window", "atr_window", "fixed_size"] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(TurtleSignalStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ # 取消之前未成交的单子 self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding # 没有持仓时才计算入场价 if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) self.exit_up, self.exit_down = self.am.donchian(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 # 下本地止损单,等到突破或者跌破成交 self.send_buy_orders(self.entry_up) self.send_short_orders(self.entry_down) elif self.pos > 0: # 如果之前有多头突破单成交,下单,根据atr加仓. # 不用考虑历史仓位,默认前面都是按照规则正确下单成交的仓位,不考虑未成交情况 self.send_buy_orders(self.entry_up) # 止损价和止盈退出价中的大的一方 sell_price = max(self.long_stop, self.exit_down) # 下多头止盈单 self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: # 如果之前有空仓,加仓 self.send_short_orders(self.entry_down) cover_price = min(self.short_stop, self.exit_up) # 下空头止盈单 self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ print( f"海龟交易,{trade.tradeid}, {trade.price}, {trade.direction}, {trade.time}" ) if trade.direction == Direction.LONG: self.long_entry = trade.price # 修改多头止损价格 self.long_stop = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + 2 * self.atr_value def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def send_buy_orders(self, price): """""" t = self.pos / self.fixed_size if t < 1: self.buy(price, self.fixed_size, True) if t < 2: self.buy(price + self.atr_value * 0.5, self.fixed_size, True) if t < 3: self.buy(price + self.atr_value, self.fixed_size, True) if t < 4: self.buy(price + self.atr_value * 1.5, self.fixed_size, True) def send_short_orders(self, price): """""" t = self.pos / self.fixed_size if t > -1: self.short(price, self.fixed_size, True) if t > -2: self.short(price - self.atr_value * 0.5, self.fixed_size, True) if t > -3: self.short(price - self.atr_value, self.fixed_size, True) if t > -4: self.short(price - self.atr_value * 1.5, self.fixed_size, True)