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 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)
def ma_info_update(self, am:ArrayManager): ma_info = {} ma_data = [] for i in self.ma_level: ma = am.sma(i) ma_info[i] = round(ma,2) ma_data.append(ma) data = [] diff = ma_data[-1] for v in ma_data: data.append(round(v / diff, 6)) ma_info["ma5"] = round(np.var(data)*1000000, 8) data = [] diff = ma_data[-3] for v in ma_data[:-2]: data.append(round(v / diff, 6)) ma_info["ma3"] = round(np.var(data)*1000000, 8) if len(self.ma_info) < 500: self.ma_info.append(ma_info) else: self.ma_info[:-1] = self.ma_info[1:] self.ma_info[-1] = ma_info
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,存在则不执行
def add_position(self, am:ArrayManager, bar:BarData, calc_data, setting={}): if self.safe_price is None: return if not (self.volumn < 0 and bar.close_price < self.safe_price or \ self.volumn > 0 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.volumn > 0: close_price = am.sma(120) if not self.add_pos: self.add_pos = True return self.strategy.buy(bar.close_price, 50, type=OrderType.MARKET) elif rg < -0.01 and self.volumn < 0: close_price = am.sma(120) if not self.add_pos: self.add_pos = True return self.strategy.short(bar.close_price, 50, type=OrderType.MARKET)
def ma120_close(self, am:ArrayManager, bar:BarData, calc_data): if self.safe_price is None: return rg = (bar.close_price / self.buy_price) - 1 close_price = None if rg > 0.01 and self.volumn > 0: close_price = am.sma(120) elif rg < -0.01 and self.volumn < 0: close_price = am.sma(120) for lvl in self.ma_lvl[-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.volumn < 0: if bar.close_price > close_price: calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price) return self.strategy.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET, extra= { "reason":"平仓:到达MA均线价{}".format(close_price)}) elif self.volumn > 0: if bar.close_price < close_price: calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price) return self.strategy.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET, extra={"reason": "平仓:到达MA均线价{}".format(close_price)})
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 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 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 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 TurtleDStrategy(CtaTemplate): """""" # 改版海龟信号-ma出场 author = "turtle_exit_ma" entry_window = 50 exit_window = 20 atr_window = 20 stop_multiple = 10 fixed_size = 1 can_long = True can_short = True entry_up = 0 entry_down = 0 exit_up = 0 exit_down = 0 atr_value = 0 long_entry = 0 short_entry = 0 long_stop = 0 short_stop = 0 parameters = [ "entry_window", "exit_window", "atr_window", "fixed_size", "stop_multiple", "can_long", "can_short" ] variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) self.exit_up = self.exit_down = self.am.sma(self.exit_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 if self.can_long: self.send_buy_orders(self.entry_up) if self.can_short: self.send_short_orders(self.entry_down) elif self.pos > 0: sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: cover_price = min(self.short_stop, self.exit_up) self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price self.long_stop = self.long_entry - self.stop_multiple * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + self.stop_multiple * self.atr_value def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def send_buy_orders(self, price): """""" self.buy(price, self.fixed_size, True) def send_short_orders(self, price): """""" self.short(price, self.fixed_size, True)
class ReverseCatchStrategy(CtaTemplate): author = "用Python的交易员" ma_level = [5, 10, 20, 30, 120] ma_tag = [] bd = [] fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 request_order = [] bar_identify = [] volumn = 0 kdj_record = [] parameters = ["ma_level"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] add_pos = False safe_price = None trend_record = MaTrendRecord def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(ReverseCatchStrategy, self).__init__( cta_engine, strategy_name, vt_symbol, setting ) self.bg = BarGenerator(self.on_bar, 1, self.on_1min_bar) self.am = ArrayManager(200) self.am3 = ArrayManager(150) self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar) self.am5 = ArrayManager(120) self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.order_data = None self.positions = CloseoutPosition(self, {"closeout_offset": 0.003}) 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.ma_info = [] five_min_open_5 = partial(self.reverse_shape_strategy, setting={"len":20, "atr":10, "atr_valve":0.8, "mid_sign":(7,14)}) self.open_strategy = { "1":[five_min_open_5], } self.offset = 40 self.ma120_track = None self.ma120_track_list = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(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 wave(self, data, window = 0.0002): if len(data) <= 0: return # r = array[::-1] result = { "value":[], "range":[], "pos":[], "length":[]} r = data l = len(data) - 1 now = r[0] # v_list.append(now) # p_list.append(0) pos = 1 vol = 0 u_tag = None d_tag = None end_tag = None start_pos = 0 while pos < l: if math.isnan(now): now = r[pos] pos += 1 continue else: start_pos = pos - 1 break while pos < l: if now < r[pos]: u_tag = pos if d_tag: diff = r[start_pos] - r[d_tag] if abs(diff / r[start_pos]) > window and d_tag - start_pos > 4: end_tag = d_tag elif now > r[pos]: d_tag = pos if u_tag: diff = r[start_pos] - r[u_tag] if abs(diff / r[start_pos]) > window and d_tag - start_pos > 4: end_tag = u_tag if end_tag is not None: result["range"].append(r[end_tag] / r[start_pos] - 1) result["length"].append(end_tag - start_pos) start_pos = end_tag result["value"].append(r[end_tag]) result["pos"].append(end_tag) end_tag = None vol += r[pos] - now now = r[pos] pos += 1 return pd.DataFrame(result) def mode_identify(self, bar: BarData): self.bar_identify = [] hl_scale = round(bar.high_price / bar.low_price - 1, 4) if hl_scale > 0.001: diff = bar.high_price - bar.low_price diff_up = bar.low_price + diff / 2 * 1.20 diff_down = bar.low_price + diff / 2 * 0.80 close = bar.close_price if bar.open_price < diff_up and bar.open_price > diff_down and \ bar.close_price < diff_up and bar.close_price > diff_down: if bar.close_price > bar.open_price: print("绿十字星",bar.datetime, bar.high_price,bar.low_price,diff,diff_up,diff_down, bar.open_price, bar.close_price) else: print("红十字星",bar.datetime, bar.high_price,bar.low_price,diff,diff_up,diff_down, bar.open_price, bar.close_price) def on_5min_bar(self, bar: BarData): self.std_range5.update(self.am5.range[-1]) self.am5.update_bar(bar) if not self.am.inited or not self.trading: return # self.on_strategy(self.am5, bar, self.open_strategy["5"]) # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR] # pattern = self.am5.pattern(list(KlinePattern)) # if len(pattern) > 0: # print(list(map(lambda x: (KLINE_PATTERN_CHINESE[x[0]],x[1]), pattern))) # self.pattern_record.add_pattern(pattern) # deg_full = calc_regress_deg(self.am.close[-40 :], False) # print("deg:",deg_full) # self.pattern_record.update() def open_v3(self, am:ArrayManager, bar:BarData): std_val2 = np.std(np.array(self.ma_tag[-10:-1])) mean_val2 = np.mean(np.array(self.ma_tag[-10:-1])) mean = np.mean(np.array(self.ma_tag[-30:-10])) if std_val2 < 0.2: if mean_val2 > 3: if mean_val2 >= (mean + 1): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif mean_val2 < 2: if mean_val2 <= (mean - 1): return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_v1(self, am:ArrayManager, bar:BarData): offset = -40 offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) mean_val = np.mean(calc_nums) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) if std_val < 1 and mean_val < 2 and self.ma_tag[-1] >= (mean_val + 2): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif std_val < 1 and mean_val > 3 and self.ma_tag[-1] <= (mean_val - 2): return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_v2(self, am:ArrayManager, bar:BarData): std_val2 = np.std(np.array(self.ma_tag[-10:-1])) mean_val2 = np.mean(np.array(self.ma_tag[-10:-1])) mean = np.mean(np.array(self.ma_tag[-30:-10])) if std_val2 < 0.2: if mean_val2 > 2.5: if mean_val2 >= (mean + 1): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif mean_val2 < 2.5: if mean_val2 <= (mean - 1): return self.short(bar.close_price, 1, type=OrderType.MARKET) def ma_trend_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}): # 60个bar后取消 if self.trend_record.std_val is not None: if len(self.trend_record.close) >= 60: self.trend_record.close = [] self.trend_record.std_val = None else: self.trend_record.close.append(bar.close_price) # 如果有新的bar,则覆盖 ma5_std = self.ma_info[-1]["ma5"] if ma5_std <= 0.16: self.trend_record.close = [] self.trend_record.std_val = ma5_std return if self.trend_record.std_val is not None and \ ma5_std > 0.8: y_fit = reg_util.regress_y_polynomial(self.trend_record.close, zoom=True) deg = calc_regress_deg(y_fit[:10], False) if deg < 0: # if k < 20 and d < 10 and j < 10: # if kdj[2] < 10: if self.pos == 0: calc_data["trade_open"] = "开空,deg={}".format(deg) return self.short(bar.close_price, 1, type=OrderType.MARKET) else: # if k > 80 and d > 90 and j > 90: # if kdj[2] > 90: if self.pos == 0: calc_data["trade_open"] = "开多,deg={}".format(deg) return self.buy(bar.close_price, 1, type=OrderType.MARKET) # v形反转捕获 def reverse_shape_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}): length = setting["len"] offset1 = int(-length) offset2 = int(-(length / 2)) close = am.close deg1 = calc_regress_deg(close[offset1:offset2], False) deg2 = calc_regress_deg(close[offset2:], False) atr = self.am.atr(setting["atr"]) atr_valve = setting["atr_valve"] if atr < atr_valve: return if deg1 > 0 and deg2 > 0 or \ deg1 < 0 and deg2 < 0: return if not (abs(deg1) > 0.15 and abs(deg2) > 0.1 and (abs(deg1) + abs(deg2)) > 0.3) : return close = am.close[-length:] min_val = np.min(close) max_val = np.max(close) mid_val = max_val if deg1 > 0 else min_val mid_pos = np.where(close == mid_val)[0][0] if mid_pos < setting["mid_sign"][0] or mid_pos > setting["mid_sign"][1]: return start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(close[:mid_pos]) start_pos = np.where(close == start_val)[0][0] l = mid_pos - start_pos # pos2 = np.where(close == min_val)[0][0] kdj = am.kdj() k = kdj["k"][-1] d = kdj["d"][-1] j = kdj["j"][-1] x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True) deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False) y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True) deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False) # print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val) cci = am.cci(20) ma60 = am.sma(60) if deg2 < 0: # if k < 20 and d < 10 and j < 10: # if kdj[2] < 10: if cci < -100 and bar.close_price < ma60: if self.pos == 0: calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci) return self.short(bar.close_price, 1, type=OrderType.MARKET) elif self.pos > 0: order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET) order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET) return order_id_cover.extend(order_id_buy) else: # if k > 80 and d > 90 and j > 90: # if kdj[2] > 90: if cci > 100 and bar.close_price > ma60: if self.pos == 0: calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci) return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif self.pos < 0: order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET) order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET) return order_id_cover.extend(order_id_buy) # print("找到大v形:", deg1, deg2 ) def ma120_close(self, am:ArrayManager, bar:BarData, calc_data): if self.safe_price is None: return rg = (bar.close_price / self.buy_price) - 1 close_price = None if rg > 0.01 and self.volumn > 0: close_price = am.sma(120) elif rg < -0.01 and self.volumn < 0: close_price = am.sma(120) for lvl in self.ma_lvl[-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.volumn < 0: if bar.close_price > close_price: calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price) return self.strategy.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET, extra= { "reason":"平仓:到达MA均线价{}".format(close_price)}) elif self.volumn > 0: if bar.close_price < close_price: calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price) return self.strategy.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.volumn < 0 and bar.close_price < self.safe_price or \ self.volumn > 0 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.volumn > 0: close_price = am.sma(120) if not self.add_pos: self.add_pos = True return self.strategy.buy(bar.close_price, 50, type=OrderType.MARKET) elif rg < -0.01 and self.volumn < 0: close_price = am.sma(120) if not self.add_pos: self.add_pos = True return self.strategy.short(bar.close_price, 50, type=OrderType.MARKET) def reverse2_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}): length = 30 offset1 = -30 offset2 = int(-10) close = am.close deg1 = calc_regress_deg(close[-30:-8], False) deg2 = calc_regress_deg(close[-8:], False) if deg1 > 0 and deg2 > 0 or \ deg1 < 0 and deg2 < 0: return if not (abs(deg1) > 0.15 and abs(deg2) > 0.15 and (abs(deg1) + abs(deg2)) > 0.35) : return close = am.close[-length:] min_val = np.min(close) max_val = np.max(close) mid_val = max_val if deg1 > 0 else min_val mid_pos = np.where(close == mid_val)[0][0] if mid_pos < setting["mid_sign"][0] or mid_pos > setting["mid_sign"][1]: return start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(close[:mid_pos]) start_pos = np.where(close == start_val)[0][0] l = mid_pos - start_pos # pos2 = np.where(close == min_val)[0][0] kdj = am.kdj() k = kdj["k"][-1] d = kdj["d"][-1] j = kdj["j"][-1] x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True) deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False) y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True) deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False) # print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val) cci = am.cci(20) ma60 = am.sma(60) if deg2 < 0: # if k < 20 and d < 10 and j < 10: # if kdj[2] < 10: if cci < -100 and bar.close_price < ma60: if self.pos == 0: calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci) return self.short(bar.close_price, 1, type=OrderType.MARKET) elif self.pos > 0: calc_data["trade_close"] = "平多后做空仓,deg={},cci={}".format(deg2, cci) order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET) order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET) return order_id_cover.extend(order_id_buy) else: # if k > 80 and d > 90 and j > 90: # if kdj[2] > 90: if cci > 100 and bar.close_price > ma60: if self.pos == 0: calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci) return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif self.pos < 0: calc_data["trade_close"] = "平空后多仓,deg={},cci={}".format(deg2, cci) order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET) order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET) return order_id_cover.extend(order_id_buy) def open5(self, am:ArrayManager, bar:BarData, calc_data): ma = self.ma_tag[-1] mean = calc_data["mean30_10"] atr = self.am.atr(10, array=True, length=20) tr = self.am.atr(1, array=True, length=11) # self.ma120_track ma120 = self.am.sma(120) # if std_val2 < 0.2: mean_std = calc_data["mean_std"] if mean_std < 0.8 and tr[-1] > 0.1 and tr[-1] / tr[-10] > 3 and tr[-1] / atr[-1] >= 1.7 and tr[-10] / atr[-10] < 1: if np.sum(self.am.range[-10:]) > 0 and self.ma120_track > 0: return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif self.ma120_track < 0: return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_kline1(self, am:ArrayManager, bar:BarData, calc_data): if KlinePattern.CDLEVENINGSTAR not in self.pattern_record: return # if std_val2 < 0.2: deg = calc_regress_deg(self.am.close[-5:], False) print("kline_strategy",deg) if deg < -0.1: return self.short(bar.close_price, 1, type=OrderType.MARKET) def generate_data(self, am:ArrayManager, bar:BarData): offset = -self.offset offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) std_val2 = np.std(np.array(self.ma_tag[-10:-1])) std_val3 = np.std(np.array(am.range[-30:-10])) ma = self.ma_tag[-1] mean_val = np.mean(calc_nums) mean_val2 = np.mean(np.array(self.ma_tag[-5:-1])) mean_val3 = np.mean(np.array(self.ma_tag[-20:-1])) mean_val4 = np.mean(np.array(self.ma_tag[-30:-5])) kdj_val = am.kdj() has_kdj_recore = False k = kdj_val["k"] d = kdj_val["d"] j = kdj_val["j"] if (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \ (k[-1] < 25 and d[-1] < 25 and j[-1] < 75): if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \ or \ (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]): has_kdj_recore = True t = local_to_eastern(bar.datetime.timestamp()) self.kdj_record.append((t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3), round(j[-1], 3))) deg1 = calc_regress_deg(am.close[offset : offset_m], False) deg2 = calc_regress_deg(am.close[offset_m :], False) deg3 = calc_regress_deg(am.close[-10 :], False) deg_full = calc_regress_deg(am.close[offset :], False) wave = self.wave(am.close[-30:]) wave_r_sum = np.sum(wave["range"]) macd=am.macd(20,40, 16) calc_data = (dict( ma_info=self.ma_info[-1:], kdj=[round(kdj_val["k"][-1],2),round(kdj_val["d"][-1],2),round(kdj_val["j"][-1],2)], cci_20=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=am.boll(20, 3.4), macd=[round(macd[0],2),round(macd[1],2),round(macd[2],2)], deg40_20=round(deg1,2), deg20_0=round(deg2,2), deg20_10=round(calc_regress_deg(am.close[-20:-10], False),2), deg30_10=round(calc_regress_deg(am.close[-30:-10], False),2),deg10_0=round(deg3,2), deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2), atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(am.atr(40, length=42), 3), time=bar.datetime, price=bar.close_price, ma=round(ma, 2), std_40=round(std_val, 2),mean40=round(mean_val,2), mean_std=np.mean(self.std_range.data[-5:]), std_10=round(std_val2,2), mean30_10=round(mean_val4,2), mean10=round(mean_val2,2), vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(), range_sum=np.sum(am.range[-5:]), pattern=list(map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())), ma120t=self.ma120_track, ma120t_list=self.ma120_track_list[-1:-10:-1], ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs), ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]), wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(am.atr(20, array=True,length=240)[-200:]), kdj_record=self.kdj_record[-10:], )) if self.ma_info[-1]["ma5"] <= 0.16: calc_data["kdj_key"] = True return calc_data def generate_3mindata(self, am:ArrayManager, bar:BarData): offset = -self.offset offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) std_val2 = np.std(np.array(self.ma_tag[-10:-1])) std_val3 = np.std(np.array(am.range[-30:-10])) ma = self.ma_tag[-1] mean_val = np.mean(calc_nums) mean_val2 = np.mean(np.array(self.ma_tag[-5:-1])) mean_val3 = np.mean(np.array(self.ma_tag[-20:-1])) mean_val4 = np.mean(np.array(self.ma_tag[-30:-5])) kdj_val = am.kdj() deg1 = calc_regress_deg(am.close[offset : offset_m], False) deg2 = calc_regress_deg(am.close[offset_m :], False) deg3 = calc_regress_deg(am.close[-10 :], False) deg_full = calc_regress_deg(am.close[offset :], False) wave = self.wave(am.close[-30:]) wave_r_sum = np.sum(wave["range"]) macd=am.macd(20,40, 16) calc_data = (dict( kdj=[round(kdj_val["k"][-1],2),round(kdj_val["d"][-1],2),round(kdj_val["j"][-1],2)], cci_20=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=am.boll(20, 3.4), macd=[round(macd[0],2),round(macd[1],2),round(macd[2],2)], deg40_20=round(deg1,2), deg20_0=round(deg2,2), deg20_10=round(calc_regress_deg(am.close[-20:-10], False),2), deg10_0=round(deg3,2), deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2), atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(am.atr(40, length=42), 3), time=bar.datetime, price=bar.close_price, ma=round(ma, 2), std_40=round(std_val, 2),mean40=round(mean_val,2), mean_std=np.mean(self.std_range.data[-5:]), std_10=round(std_val2,2), mean30_10=round(mean_val4,2), mean10=round(mean_val2,2), vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(), range_sum=np.sum(am.range[-5:]), pattern=list(map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())), ma120t=self.ma120_track, ma120t_list=self.ma120_track_list[-1:-10:-1], ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs), ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma_info=list(map(lambda x:x["std"], self.ma_info[-1:])), wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(am.atr(20, array=True,length=240)[-200:]) )) return calc_data 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 ma_info_update(self, am:ArrayManager): ma_info = {} ma_data = [] for i in self.ma_level: ma = am.sma(i) ma_info[i] = round(ma,2) ma_data.append(ma) data = [] diff = ma_data[-1] for v in ma_data: data.append(round(v / diff, 6)) ma_info["ma5"] = round(np.var(data)*1000000, 8) data = [] diff = ma_data[-3] for v in ma_data[:-2]: data.append(round(v / diff, 6)) ma_info["ma3"] = round(np.var(data)*1000000, 8) if len(self.ma_info) < 500: self.ma_info.append(ma_info) else: self.ma_info[:-1] = self.ma_info[1:] self.ma_info[-1] = ma_info def on_1min_bar(self, bar: BarData): self.am.update_bar(bar) am = self.am max_len = self.ma_level[-1] + 20 data = self.am.close[-max_len:-1] ma_lvl = [] for i in self.ma_level: ma = self.am.sma(i, True)[-1] ma_lvl.append(ma) l = len(ma_lvl) ma_lvl_tag = [] now = bar.close_price direction = 1 if now > ma_lvl[0] else 0 ma_lvl_tag.append(direction) for i in range(l-1): val = 1 if ma_lvl[i] > ma_lvl[i+1] else 0 ma_lvl_tag.append(val) bincount_val = np.bincount(np.array(ma_lvl_tag)) tag_val = 0 if len(bincount_val) == 2: tag_val = bincount_val[1] if len(self.ma_tag) < 200: self.ma_tag.append(tag_val) else: self.ma_tag[:-1] = self.ma_tag[1:] self.ma_tag[-1] = tag_val if self.tracker is not None: self.tracker["bar_data"].append(bar) self.std_range.update(self.am.range[-1]) ma120 = self.am.sma(120) if bar.close_price >= ma120: if self.ma120_track is None: self.ma120_track = 1 elif self.ma120_track > 0: self.ma120_track += 1 else: self.ma120_track_list.append(self.ma120_track) self.ma120_track = 1 elif bar.close_price < ma120: if self.ma120_track is None: self.ma120_track = -1 elif self.ma120_track < 0: self.ma120_track -= 1 else: self.ma120_track_list.append(self.ma120_track) self.ma120_track = -1 if not am.inited or not self.trading: return self.ma_info_update(am) calc_data = self.generate_data(am, bar) five_min_open_5 = partial(self.reverse_shape_strategy, setting={"len":20, "atr":10, "atr_valve":0.8, "mid_sign":(7,14)}) open_strategy = [self.reverse_shape_strategy, self.add_position] close_strategy = [self.positions.on_bar, self.ma120_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 init_order_data(self): # self.order_data = np.array([]) def on_order(self, order: OrderData): """ Callback of new order data update. """ print("{}产生了{},价格为{},笔数为{},交易{},pos={}".format(order.datetime.strftime("%m/%d %H:%M:%S"), order.offset.value + order.direction.value,order.price, order.volume, order.status.value, self.pos)) if order.vt_orderid in self.request_order: if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED: self.request_order.remove(order.vt_orderid) def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.vt_orderid in self.request_order: self.positions.on_trade(trade) if self.volumn == 0: self.add_pos = False if trade.direction == Direction.LONG: self.safe_price = trade.price * 1.003 self.volumn += trade.volume elif trade.direction == Direction.SHORT: self.safe_price = trade.price * 0.997 self.volumn -= trade.volume self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class MultiTimeframeStrategy(CtaTemplate): """""" author = "用Python的交易员" rsi_signal = 20 rsi_window = 14 fast_window = 5 slow_window = 20 fixed_size = 1 # 5min级bar下限价单时的加点,应该为最小变动价的整数倍 bar_add = 2 rsi_value = 0 rsi_long = 0 rsi_short = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 parameters = ["rsi_signal", "rsi_window", "fast_window", "slow_window", "fixed_size","bar_add"] variables = ["rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long = 50 + self.rsi_signal self.rsi_short = 50 - self.rsi_signal # 维护两组bg/am,对应不同时间周期 self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am15 = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return # 长周期趋势为短周期的过滤 if not self.ma_trend: return self.rsi_value = self.am5.rsi(self.rsi_window) if self.pos == 0: if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy(bar.close_price + self.bar_add, self.fixed_size) elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(bar.close_price - self.bar_add, self.fixed_size) elif self.pos > 0: if self.ma_trend < 0 or self.rsi_value < 50: self.sell(bar.close_price - self.bar_add, abs(self.pos)) elif self.pos < 0: if self.ma_trend > 0 or self.rsi_value > 50: self.cover(bar.close_price + self.bar_add, abs(self.pos)) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if not self.am15.inited: return self.fast_ma = self.am15.sma(self.fast_window) self.slow_ma = self.am15.sma(self.slow_window) # 根据15min级的MA设置方向 if self.fast_ma > self.slow_ma: self.ma_trend = 1 else: self.ma_trend = -1 def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class TripleMaSignal(CtaSignalPatch): """TripleMaSignal""" # 策略参数 # 三均线长度设置 maWindow1 = 10 maWindow2 = 30 maWindow3 = 90 # ma最新值 ma1 = 0 ma2 = 0 ma3 = 0 #---------------------------------------------------------------------- def __init__(self, strategy, KCircle=1): """Constructor""" super(TripleMaSignal, self).__init__(strategy) self.bg = BarGenerator(self.onBar, KCircle, self.onXminBar) self.am = ArrayManager(size=100) #---------------------------------------------------------------------- def onBar(self, bar): """K线更新""" self.bg.update_bar(bar) #---------------------------------------------------------------------- def onXminBar(self, bar=BarData): """X Min Bar""" # 保存K线数据 am = self.am am.update_bar(bar) if not am.inited: self.set_signal_pos(0) return if self.trading: self.updateSignal() #---------------------------------------------------------------------- def updateSignal(self): """X Min Bar""" self.set_signal_pos(self.getSignal()) pass #---------------------------------------------------------------------- def getSignal(self): """生成信号""" ma1Array = self.am.sma(self.maWindow1, True) self.ma10 = ma1Array[-2] self.ma1 = ma1Array[-1] self.ma2 = self.am.sma(self.maWindow2, False) self.ma3 = self.am.sma(self.maWindow3, False) # 开多,上穿 if self.ma1 > self.ma2 > self.ma3: return 1 # 开空,下穿 elif self.ma1 < self.ma2 < self.ma3: return -1 return 0
class MaLevelTrackStrategy(CtaTemplate): author = "用Python的交易员" ma_level = [5, 10, 20, 30, 120] ma_tag = [] bd = [] fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 request_order = [] bar_identify = [] parameters = ["ma_level"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(MaLevelTrackStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_1min_bar) self.am = ArrayManager(400) self.am3 = ArrayManager(150) self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar) self.am5 = ArrayManager(120) self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.order_data = None self.positions = Position(self) self.std_range = IntervalGen(np.std, 5) self.std_range3 = IntervalGen(np.std, 5) self.std_range5 = IntervalGen(np.std, 5) self.pattern_record = PatternRecord() # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3) self.pattern_record.set_expiry(list(KlinePattern), 1) five_min_open_5 = partial(self.reverse_shape_strategy, setting={ "atr": 10, "atr_valve": 0.8, "deg1": (10, 5), "deg2": 5 }) self.open_strategy = { "1": [self.reverse_shape_strategy], "5": [five_min_open_5], } self.offset = 40 self.ma120_track = None self.ma120_track_list = [] def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) self.bg3.update_tick(tick) self.bg5.update_tick(tick) def on_3min_bar(self, bar: BarData): self.am3.update_bar(bar) self.std_range3.update(self.am3.range[-1]) if not self.am.inited or not self.trading: return pattern = self.am3.pattern( [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS]) if len(pattern) > 0: print(pattern) self.pattern_record.add_pattern(pattern) # deg = calc_regress_deg(self.am3.close[-20:]) def wave(self, data, window=0.0002): if len(data) <= 0: return # r = array[::-1] result = {"value": [], "range": [], "pos": [], "length": []} r = data l = len(data) - 1 now = r[0] # v_list.append(now) # p_list.append(0) pos = 1 vol = 0 u_tag = None d_tag = None end_tag = None start_pos = 0 while pos < l: if math.isnan(now): now = r[pos] pos += 1 continue else: start_pos = pos - 1 break while pos < l: if now < r[pos]: u_tag = pos if d_tag: diff = r[start_pos] - r[d_tag] if abs(diff / r[start_pos]) > window and d_tag - start_pos > 1: end_tag = d_tag elif now > r[pos]: d_tag = pos if u_tag: diff = r[start_pos] - r[u_tag] if abs(diff / r[start_pos]) > window and d_tag - start_pos > 1: end_tag = u_tag if end_tag is not None: result["range"].append(r[end_tag] / r[start_pos] - 1) result["length"].append(end_tag - start_pos) start_pos = end_tag result["value"].append(r[end_tag]) result["pos"].append(end_tag) end_tag = None vol += r[pos] - now now = r[pos] pos += 1 return pd.DataFrame(result) def mode_identify(self, bar: BarData): self.bar_identify = [] hl_scale = round(bar.high_price / bar.low_price - 1, 4) if hl_scale > 0.001: diff = bar.high_price - bar.low_price diff_up = bar.low_price + diff / 2 * 1.20 diff_down = bar.low_price + diff / 2 * 0.80 close = bar.close_price if bar.open_price < diff_up and bar.open_price > diff_down and \ bar.close_price < diff_up and bar.close_price > diff_down: if bar.close_price > bar.open_price: print("绿十字星", bar.datetime, bar.high_price, bar.low_price, diff, diff_up, diff_down, bar.open_price, bar.close_price) else: print("红十字星", bar.datetime, bar.high_price, bar.low_price, diff, diff_up, diff_down, bar.open_price, bar.close_price) def on_5min_bar(self, bar: BarData): self.std_range5.update(self.am5.range[-1]) self.am5.update_bar(bar) if not self.am.inited or not self.trading: return self.on_strategy(self.am5, bar, self.open_strategy["5"]) # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR] # pattern = self.am5.pattern(list(KlinePattern)) # if len(pattern) > 0: # print(list(map(lambda x: (KLINE_PATTERN_CHINESE[x[0]],x[1]), pattern))) # self.pattern_record.add_pattern(pattern) # deg_full = calc_regress_deg(self.am.close[-40 :], False) # print("deg:",deg_full) # self.pattern_record.update() def open_v3(self, am: ArrayManager, bar: BarData): std_val2 = np.std(np.array(self.ma_tag[-10:-1])) mean_val2 = np.mean(np.array(self.ma_tag[-10:-1])) mean = np.mean(np.array(self.ma_tag[-30:-10])) if std_val2 < 0.2: if mean_val2 > 3: if mean_val2 >= (mean + 1): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif mean_val2 < 2: if mean_val2 <= (mean - 1): return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_v1(self, am: ArrayManager, bar: BarData): offset = -40 offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) mean_val = np.mean(calc_nums) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) if std_val < 1 and mean_val < 2 and self.ma_tag[-1] >= (mean_val + 2): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif std_val < 1 and mean_val > 3 and self.ma_tag[-1] <= (mean_val - 2): return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_v2(self, am: ArrayManager, bar: BarData): std_val2 = np.std(np.array(self.ma_tag[-10:-1])) mean_val2 = np.mean(np.array(self.ma_tag[-10:-1])) mean = np.mean(np.array(self.ma_tag[-30:-10])) if std_val2 < 0.2: if mean_val2 > 2.5: if mean_val2 >= (mean + 1): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif mean_val2 < 2.5: if mean_val2 <= (mean - 1): return self.short(bar.close_price, 1, type=OrderType.MARKET) def open2(self, am: ArrayManager, bar: BarData, calc_data): deg = calc_data["deg20"] ma = self.ma_tag[-1] if deg > 0.5 and ma > 3 and self.am5.range[-1] > -0.002: return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif deg < -0.5 and ma < 2 and self.am5.range[-1] < 0.002: return self.short(bar.close_price, 1, type=OrderType.MARKET) def open1(self, am: ArrayManager, bar: BarData, calc_data): mean = calc_data["mean30_10"] mean_val2 = calc_data["mean10"] # if std_val2 < 0.2: if mean_val2 > 3.5 and mean_val2 >= (mean + 2): return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif mean_val2 < 1.5 and mean_val2 <= (mean - 2): return self.short(bar.close_price, 1, type=OrderType.MARKET) # v形反转捕获 def reverse_shape_strategy(self, am: ArrayManager, bar: BarData, calc_data, setting={ "atr": 40, "atr_valve": 0.8, "deg1": (40, 20), "deg2": (20, 0), }): deg1 = calc_data["deg40_20"] deg2 = calc_data["deg20_0"] kdj = calc_data["kdj"] atr = self.am.atr(40) if atr < 0.08: return if deg1 > 0 and deg2 > 0 or \ deg1 < 0 and deg2 < 0: return if not (abs(deg1) > 0.15 and abs(deg2) > 0.1 and (abs(deg1) + abs(deg2)) > 0.3): return close = am.close[-40:] min_val = np.min(close) max_val = np.max(close) mid_val = max_val if deg1 > 0 else min_val mid_pos = np.where(close == mid_val)[0][0] if mid_pos < 10 or mid_pos > 30: return start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max( close[:mid_pos]) start_pos = np.where(close == start_val)[0][0] l = mid_pos - start_pos # pos2 = np.where(close == min_val)[0][0] x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True) deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False) y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True) deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False) print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val) if deg2 < 0: if kdj[0] < 20 and kdj[1] < 10 and kdj[2] < 10: # if kdj[2] < 10: return self.short(bar.close_price, 1, type=OrderType.MARKET) else: if kdj[0] > 80 and kdj[1] > 90 and kdj[2] > 90: # if kdj[2] > 90: return self.buy(bar.close_price, 1, type=OrderType.MARKET) # print("找到大v形:", deg1, deg2 ) def open5(self, am: ArrayManager, bar: BarData, calc_data): ma = self.ma_tag[-1] mean = calc_data["mean30_10"] atr = self.am.atr(10, array=True, length=20) tr = self.am.atr(1, array=True, length=11) # self.ma120_track ma120 = self.am.sma(120) # if std_val2 < 0.2: mean_std = calc_data["mean_std"] if mean_std < 0.8 and tr[-1] > 0.1 and tr[-1] / tr[-10] > 3 and tr[ -1] / atr[-1] >= 1.7 and tr[-10] / atr[-10] < 1: if np.sum(self.am.range[-10:]) > 0 and self.ma120_track > 0: return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif self.ma120_track < 0: return self.short(bar.close_price, 1, type=OrderType.MARKET) def open_kline1(self, am: ArrayManager, bar: BarData, calc_data): if KlinePattern.CDLEVENINGSTAR not in self.pattern_record: return # if std_val2 < 0.2: deg = calc_regress_deg(self.am.close[-5:], False) print("kline_strategy", deg) if deg < -0.1: return self.short(bar.close_price, 1, type=OrderType.MARKET) def generate_data(self, bar: BarData): offset = -self.offset offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) std_val2 = np.std(np.array(self.ma_tag[-10:-1])) std_val3 = np.std(np.array(self.am.range[-30:-10])) ma = self.ma_tag[-1] mean_val = np.mean(calc_nums) mean_val2 = np.mean(np.array(self.ma_tag[-5:-1])) mean_val3 = np.mean(np.array(self.ma_tag[-20:-1])) mean_val4 = np.mean(np.array(self.ma_tag[-30:-5])) kdj_val = self.am.kdj() deg1 = calc_regress_deg(self.am.close[offset:offset_m], False) deg2 = calc_regress_deg(self.am.close[offset_m:], False) deg3 = calc_regress_deg(self.am.close[-10:], False) deg_full = calc_regress_deg(self.am.close[offset:], False) wave = self.wave(self.am.close[-30:]) wave_r_sum = np.sum(wave["range"]) macd = self.am.macd(20, 40, 16) calc_data = (dict( kdj=[ round(kdj_val["k"][-1], 2), round(kdj_val["d"][-1], 2), round(kdj_val["j"][-1], 2) ], cci_20=self.am.cci(20), rsi=self.am.rsi(20), adx=self.am.adx(20), boll=self.am.boll(20, 3.4), macd=[round(macd[0], 2), round(macd[1], 2), round(macd[2], 2)], deg40_20=round(deg1, 2), deg20_0=round(deg2, 2), deg20_10=round(calc_regress_deg(self.am.close[-20:-10], False), 2), deg10_0=round(deg3, 2), deg30_15=round(calc_regress_deg(self.am.close[-30:-15], False), 2), deg15_0=round(calc_regress_deg(self.am.close[-15:], False), 2), deg_f=round(deg_full, 2), atr=round(self.am.atr(10, length=15), 3), tr=round(self.am.atr(1, length=2), 3), atr_40=round(self.am.atr(40, length=42), 3), time=bar.datetime, price=bar.close_price, ma=round(ma, 2), std_40=round(std_val, 2), mean40=round(mean_val, 2), mean_std=np.mean(self.std_range.data[-5:]), std_10=round(std_val2, 2), mean30_10=round(mean_val4, 2), mean10=round(mean_val2, 2), vol=self.am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=self.am.range[-1:-5:-1].tolist(), range_sum=np.sum(self.am.range[-5:]), pattern=list( map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())), ma120t=self.ma120_track, ma120t_list=self.ma120_track_list[-1:-10:-1], ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs), ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]), wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(self.am.atr(20, array=True, length=240)[-200:]))) return calc_data def on_strategy(self, am: ArrayManager, bar: BarData, strategy_list): calc_data = self.generate_data(bar) order_id = None if self.pos == 0: for open_strategy in strategy_list: if order_id is not None: break order_id = open_strategy(am, bar, calc_data) else: order_id = self.positions.on_strategy(bar, calc_data) if order_id is not None: offset = -self.offset offset_m = int(offset / 2) self.tracker["trade_info"].append( (self.am.time_array[offset], self.am.time_array[offset_m], bar.datetime, calc_data["deg40_20"], calc_data["deg20_0"])) self.request_order.extend(order_id) if self.tracker is not None: self.tracker["ma_tag_ls"].append(calc_data) def on_1min_bar(self, bar: BarData): self.am.update_bar(bar) am = self.am max_len = self.ma_level[-1] + 20 data = self.am.close[-max_len:-1] ma_lvl = [] for i in self.ma_level: ma = self.am.sma(i, True)[-1] ma_lvl.append(ma) l = len(ma_lvl) ma_lvl_tag = [] now = bar.close_price direction = 1 if now > ma_lvl[0] else 0 ma_lvl_tag.append(direction) for i in range(l - 1): val = 1 if ma_lvl[i] > ma_lvl[i + 1] else 0 ma_lvl_tag.append(val) bincount_val = np.bincount(np.array(ma_lvl_tag)) tag_val = 0 if len(bincount_val) == 2: tag_val = bincount_val[1] if len(self.ma_tag) < 200: self.ma_tag.append(tag_val) else: self.ma_tag[:-1] = self.ma_tag[1:] self.ma_tag[-1] = tag_val if self.tracker is not None: self.tracker["bar_data"].append(bar) self.std_range.update(self.am.range[-1]) ma120 = self.am.sma(120) if bar.close_price >= ma120: if self.ma120_track is None: self.ma120_track = 1 elif self.ma120_track > 0: self.ma120_track += 1 else: self.ma120_track_list.append(self.ma120_track) self.ma120_track = 1 elif bar.close_price < ma120: if self.ma120_track is None: self.ma120_track = -1 elif self.ma120_track < 0: self.ma120_track -= 1 else: self.ma120_track_list.append(self.ma120_track) self.ma120_track = -1 if not am.inited or not self.trading: return self.on_strategy(am, bar, self.open_strategy["1"]) # median_val = np.median(calc_nums) self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg3.update_bar(bar) self.bg5.update_bar(bar) self.bg.update_bar(bar) # def init_order_data(self): # self.order_data = np.array([]) def on_order(self, order: OrderData): """ Callback of new order data update. """ print("{}产生了{},价格为{},笔数为{},交易{},pos={}".format( order.datetime.strftime("%m/%d %H:%M:%S"), order.offset.value + order.direction.value, order.price, order.volume, order.status.value, self.pos)) if order.vt_orderid in self.request_order: self.positions.on_order(order) if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED: self.request_order.remove(order.vt_orderid) # if order.status == Status.ALLTRADED or order.status == Status.PARTTRADED: # if order.direction == Direction.LONG: # if self.positions.volumn == 0: # self.positions.close_price = round(order.price * 0.995) # self.positions.volumn += order.volume # elif order.direction == Direction.SHORT: # self.positions.volumn -= order.volume # elif order.direction == Direction.NET: # self.positions.volumn = order.volume def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class RsiAdaptStrategy(CtaTemplate): """ 策略逻辑: 一、、过虑信号 (小时周期) 使用rsiboll来判断信号强弱 二、开单信号 (分钟周期) 1、使用布林上下轨作为开单条件 三、止损 使用动态布林中轨止损 """ author = "yunya" min_window = 45 open_window = 15 rsi_length = 23 kk_length = 80 kk_dev = 2.0 trading_size = 1 atr_length = 30 rsi_entry = 0 kk_up = 0 kk_down = 0 long_stop = 0 short_stop = 0 rsi_value = 0 rsi_up = 0 rsi_dow = 0 ema_mid = 0 ema_length_new = 0 current_ema_mid = 0 last_ema_mid = 0 current_close = 0 last_close = 0 front_close = 0 exit_long = 0 exit_short = 0 long_entry = 0 short_entry = 0 long_stop_trade = 0 short_stop_drade = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 atr_value = 0 parameters = [ "open_window", "min_window", "rsi_length", "kk_length", "kk_dev", "trading_size", "atr_length", ] variables = [ "rsi_entry", "long_stop", "short_stop", "rsi_value", "rsi_up", "rsi_dow", "ema_mid", "ema_length_new", "current_ema_mid", "last_ema_mid", "current_close", "last_close", "front_close", "exit_long", "exit_short", "long_entry", "short_entry", "long_stop_trade", "short_stop_drade", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg_xminute = NewBarGenerator(on_bar=self.on_bar, window=self.min_window, on_window_bar=self.on_xminute_bar) self.am_xminute = ArrayManager(self.kk_length * 2 + 10) self.bg_open = NewBarGenerator(on_bar=self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar) self.am_open = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(30) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动。。") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止。。") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_open.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_5min_bar(self, bar: BarData): """ :param bar: :type bar: :return: :rtype: """ self.cancel_all() self.am_open.update_bar(bar) if not self.am_open.inited or not self.am_xminute.inited: return ema_mid_array = self.am_open.ema(self.kk_length, True) atr = self.am_open.atr(self.kk_length, True) kk_up_array = ema_mid_array + atr * self.kk_dev kk_down_array = ema_mid_array - atr * self.kk_dev self.ema_mid = ema_mid_array[-1] self.kk_up = kk_up_array[-1] self.kk_down = kk_down_array[-1] self.current_close = self.am_open.close[-1] self.last_close = self.am_open.close[-2] self.front_close = self.am_open.close[-3] if not self.pos: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.ema_length_new = self.kk_length self.atr_value = self.am_open.atr(self.atr_length) if self.rsi_entry > 0: self.buy(self.kk_up, self.trading_size, True) self.write_log( f"下多单:{bar.datetime}, {self.kk_up}, {self.trading_size}") elif self.rsi_entry < 0: self.short(self.kk_down, self.trading_size, True) self.write_log( f"下多单:{bar.datetime}, {self.kk_down}, {self.trading_size}") elif self.pos > 0: close_long = self.current_close > self.last_close > self.front_close if close_long: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) ema_mid_new = self.am_xminute.sma(self.ema_length_new, True) self.current_ema_mid = ema_mid_new[-1] self.last_ema_mid = ema_mid_new[-2] # 仓位是long 时,如果价格下穿新布林中轨 con1 = bar.close_price < self.current_ema_mid con2 = bar.close_price >= self.last_ema_mid if con1 and con2: self.exit_long_nex = bar.close_price # 保存当前收盘价 if self.exit_long_last == 0 or self.exit_long_nex > self.exit_long_last: self.exit_long_last = self.exit_long_nex self.ema_length_new = self.kk_length # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.ema_mid else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if bar.close_price > ( (self.ema_mid + self.current_ema_mid) / 2): self.exit_long = bar.close_price elif bar.close_price < self.ema_mid: self.exit_long = bar.close_price else: self.exit_long = self.ema_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.ema_mid self.long_stop = max(self.exit_long, self.long_stop_trade) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: close_short = self.current_close < self.last_close < self.front_close if close_short: self.ema_length_new -= 1 self.ema_length_new = max(self.ema_length_new, 5) ema_mid_new = self.am_xminute.sma(self.ema_length_new, True) self.current_ema_mid = ema_mid_new[-1] self.last_ema_mid = ema_mid_new[-2] # 仓位是short 时,如果价格上穿新布林中轨 con1 = bar.close_price > self.current_ema_mid con2 = bar.close_price <= self.last_ema_mid if con1 and con2: self.exit_short_nex = bar.close_price if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last: self.exit_short_last = self.exit_short_nex self.ema_length_new = self.kk_length self.exit_short = self.ema_mid else: if bar.close_price < (self.ema_mid + self.current_ema_mid / 2): self.exit_short = bar.close_price elif bar.close_price < self.ema_mid: self.exit_short = bar.close_price else: self.exit_short = self.ema_mid else: self.exit_short = self.ema_mid self.short_stop = min(self.exit_short, self.short_stop_drade) self.cover(self.short_stop, abs(self.pos), True) self.sync_data() self.put_event() def on_xminute_bar(self, bar: BarData): """ :param bar: :return: """ self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return ema_array = talib.EMA(self.am_xminute.close, self.rsi_length) std_array = talib.EMA(self.am_xminute.close, self.rsi_length) dev_array = abs(self.am_xminute.close[:-1] - ema_array[:-1]) / std_array[:-1] dev_max = max(dev_array[-self.rsi_length:]) rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length) rsi_up_array = rsi_array + rsi_array * dev_max rsi_dow_array = rsi_array - rsi_array * dev_max rsi_value_array = self.am_xminute.rsi(self.rsi_length, True) self.rsi_up = rsi_up_array[-1] self.rsi_dow = rsi_dow_array[-1] self.rsi_value = rsi_value_array[-1] current_rsi = rsi_value_array[-1] last_rsi = rsi_value_array[-2] current_rsi_up = rsi_up_array[-1] last_rsi_up = rsi_up_array[-2] current_rsi_down = rsi_dow_array[-1] last_rsi_down = rsi_dow_array[-2] con1 = current_rsi > current_rsi_up con2 = last_rsi <= last_rsi_up con3 = current_rsi < current_rsi_down con4 = last_rsi >= last_rsi_down if con1 > con2: self.rsi_entry = 1 elif con3 and con4: self.rsi_entry = -1 self.sync_data() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price # 成交最高价 self.long_stop_trade = self.long_entry - 2 * self.atr_value else: self.short_entry = trade.price self.short_stop_drade = self.short_entry + 2 * self.atr_value self.sync_data() def on_order(self, order: OrderData): """ 订单更新回调 Callback of new order data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event()
class DoubleDayM30M1Strategy(CtaTemplate): """ 使用1m线合成 日线、30分钟、1分钟三种数据,并根据各自ma叠加进行卖卖的策略 """ author = "fsksf" window_mn = 30 # n分钟线 fast_window_day = 3 fast_window_m30 = 3 fast_window_m1 = 3 slow_window_day = 5 slow_window_m30 = 5 slow_window_m1 = 5 fast_ma_day = 0.0 fast_ma_m30 = 0.0 fast_ma_m1 = 0.0 slow_ma_day = 0.0 slow_ma_m30 = 0.0 slow_ma_m1 = 0.0 parameters = [ "fast_window_day", "fast_window_m30", "fast_window_m1", "slow_window_day", "slow_window_m30", "slow_window_m1", "window_mn" ] variables = [ "fast_ma_day", "slow_ma_day", "fast_ma_m30", "slow_ma_m30", "fast_ma_m1", "slow_ma_m1" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.day_bar_gen = BarGenerator(lambda x: None, interval=Interval.DAILY, window=1, on_window_bar=self.on_day_bar) self.m30_bar_gen = BarGenerator(self.on_bar, interval=Interval.MINUTE, window=self.window_mn, on_window_bar=self.on_m30_bar) self.day_am = ArrayManager(size=self.slow_window_day + 1) self.m30_am = ArrayManager(size=self.slow_window_m30 + 1) self.m1_am = ArrayManager(size=self.slow_window_m1 + 1) def on_m30_bar(self, bar): self.m30_am.update_bar(bar) def on_day_bar(self, bar): print(bar.__dict__) self.day_am.update_bar(bar) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(100) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.m30_bar_gen.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ # if self.cta_engine.gateway_name == "BACKTESTING": # update window self.m30_bar_gen.update_bar(bar) self.day_bar_gen.update_bar(bar) self.m1_am.update_bar(bar) if not (self.day_am.inited and self.m30_am.inited and self.m1_am.inited): return # 最后一个bar实时更新的,计算ma后删除 # self.day_am.update_bar(self.day_bar_gen.last_bar) fast_ma_day = self.day_am.sma(self.fast_window_day, array=True) slow_ma_day = self.day_am.sma(self.slow_window_day, array=True) # self.m30_am.update_bar(self.m30_bar_gen.last_bar) fast_ma_m30 = self.m30_am.sma(self.fast_window_m30, array=True) slow_ma_m30 = self.m30_am.sma(self.slow_window_m30, array=True) fast_ma_m1 = self.m1_am.sma(self.fast_window_m1, array=True) slow_ma_m1 = self.m1_am.sma(self.slow_window_m1, array=True) self.fast_ma_day = fast_ma_day[-1] self.fast_ma_m30 = fast_ma_m30[-1] self.fast_ma_m1 = fast_ma_m1[-1] self.slow_ma_day = slow_ma_day[-1] self.slow_ma_m30 = slow_ma_m30[-1] self.slow_ma_m1 = slow_ma_m1[-1] cross_over = fast_ma_day[-2] < slow_ma_day[-2] and fast_ma_day[-1] > slow_ma_day[-1] and \ fast_ma_m30[-2] < slow_ma_m30[-2] and fast_ma_m30[-1] > slow_ma_m30[-1] and \ fast_ma_m1[-2] < slow_ma_m1[-2] and fast_ma_m1[-1] > slow_ma_m1[-1] cross_below = fast_ma_day[-2] > slow_ma_day[-2] and fast_ma_day[-1] < slow_ma_day[-1] and \ fast_ma_m30[-2] > slow_ma_m30[-2] and fast_ma_m30[-1] < slow_ma_m30[-1] and \ fast_ma_m1[-2] > slow_ma_m1[-2] and fast_ma_m1[-1] < slow_ma_m1[-1] if cross_over: self.write_log(f'触发买入:{str(bar.datetime)}') # print(f'触发买入:{str(bar.datetime)}') self.write_log( f'day: ma_fast: {fast_ma_day[-2:]}, slow: {slow_ma_day[-2:]} close_price: {self.day_am.close_array}' ) self.write_log( f'30m: ma_fast: {fast_ma_m30[-2:]}, slow: {slow_ma_m30[-2:]} close_price: {self.m30_am.close_array}' ) self.write_log( f'1m: ma_fast: {fast_ma_m1[-2:]}, slow: {slow_ma_m1[-2:]} close_price: {self.m1_am.close_array}' ) if self.pos == 0: self.buy(bar.close_price, 1) elif self.pos < 0: self.cover(bar.close_price, 1) self.buy(bar.close_price, 1) elif cross_below: if self.pos == 0: self.short(bar.close_price, 1) elif self.pos > 0: self.sell(bar.close_price, 1) self.short(bar.close_price, 1) # self.day_am.remove_last_bar() # self.m30_am.remove_last_bar() self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class TurtleFluidSizeStrategy(CtaTemplate): """""" # 改版海龟信号-ma出场-rsi过滤-atr浮动手数 author = "turtle_fluid_size" entry_window = 50 exit_window = 20 atr_window = 20 stop_multiple = 10 long_rsi = 50 short_rsi = 50 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 fluid_size = 1 symbol_size = 1 risk_percent = 0.002 risk_capital = 1000000 parameters = [ "entry_window", "exit_window", "atr_window", "fixed_size", "stop_multiple", "long_rsi", "short_rsi", "symbol_size", "risk_percent", "risk_capital" ] variables = [ "entry_up", "entry_down", "exit_up", "exit_down", "atr_value", "fluid_size" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) print(self.symbol_size, self.risk_percent, self.risk_capital) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(20) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return # Only calculates new entry channel when no position holding if not self.pos: self.entry_up, self.entry_down = self.am.donchian( self.entry_window) self.exit_up = self.exit_down = self.am.sma(self.exit_window) self.rsi_value = self.am.rsi(self.entry_window) if not self.pos: self.atr_value = self.am.atr(self.atr_window) risk_amount = self.risk_capital * self.risk_percent atr_amount = self.atr_value * self.symbol_size self.fluid_size = round(risk_amount / atr_amount) * self.fixed_size self.long_entry = 0 self.short_entry = 0 self.long_stop = 0 self.short_stop = 0 if self.fluid_size and self.rsi_value > self.long_rsi: self.send_buy_orders(self.entry_up) if self.fluid_size and self.rsi_value <= self.short_rsi: self.send_short_orders(self.entry_down) elif self.pos > 0: sell_price = max(self.long_stop, self.exit_down) self.sell(sell_price, abs(self.pos), True) elif self.pos < 0: cover_price = min(self.short_stop, self.exit_up) self.cover(cover_price, abs(self.pos), True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.long_entry = trade.price self.long_stop = self.long_entry - self.stop_multiple * self.atr_value else: self.short_entry = trade.price self.short_stop = self.short_entry + self.stop_multiple * self.atr_value def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def send_buy_orders(self, price): """""" self.buy(price, self.fluid_size, True) def send_short_orders(self, price): """""" self.short(price, self.fluid_size, True)
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()
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 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 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 BollVix(CtaTemplate): """""" author = "yunya" open_window = 15 boll_length = 530 fixed_size = 1 boll_mid_current = 0 boll_mid_last = 0 boll_up_current = 0 boll_up_last = 0 boll_down_current = 0 boll_down_last = 0 target_pos = 0 pos_inited = 0 boll_mid = 0 # 画图专用 time_list = [] open_list = [] high_list = [] low_list = [] close_list = [] volume_list = [] up_list = [] down_list = [] mid_list = [] mid_new_list = [] bias_value_list = [] bias_list = [] singnal_plot = [] singnal_list = None singnal = None plot_echarts = {} parameters = [ "open_window", "boll_length", "fixed_size", ] variables = [ "boll_mid_current", "boll_mid_last", "boll_up_current", "boll_up_last", "boll_down_current", "boll_down_last", "pos_inited", "target_pos" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_minute_bar, interval=Interval.MINUTE) self.am = ArrayManager(self.boll_length * 2) self.up_array: np.ndarray = np.zeros(5) self.down_array: np.ndarray = np.zeros(5) self.boll_inited = False self.boll_count = 0 self.engine_type = self.get_engine_type() self.vt_orderids = [] self.order_price = 0 self.pos_inited = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(12) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) # 只有实盘交易才使用BestLimit算法 if self.engine_type != EngineType.LIVE: return # 当前没有仓位 order_volume_open = self.target_pos - self.pos if not order_volume_open: return if order_volume_open > 0: if not self.vt_orderids: self.order_price = tick.bid_price_1 vt_orderids = self.buy(self.order_price, abs(order_volume_open)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.bid_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) elif order_volume_open < 0: if not self.vt_orderids: self.order_price = tick.ask_price_1 vt_orderids = self.short(self.order_price, abs(order_volume_open)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.ask_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_minute_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算布林 sma_array = self.am.sma(self.boll_length, True) std_array = self.am.std(self.boll_length, True) dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_length:].max() up = sma_array + std_array * dev_max down = sma_array - std_array * dev_max boll_mid_array = self.am.sma(self.boll_length, True) # 计算数组 self.boll_mid = boll_mid_array[-2] self.boll_up_current = up[-1] self.boll_up_last = up[-2] self.boll_down_current = down[-1] self.boll_down_last = down[-2] if not self.pos: self.pos_inited = 0 if self.am.close[-1] > self.boll_up_current and self.am.close[ -2] <= self.boll_up_last: if self.engine_type == EngineType.BACKTESTING: self.buy(bar.close_price, self.fixed_size) else: self.target_pos = self.fixed_size print("没有仓位,我开多") elif self.am.close[-1] < self.boll_down_current and self.am.close[ -2] >= self.boll_down_last: if self.engine_type == EngineType.BACKTESTING: self.short(bar.close_price, self.fixed_size) else: self.target_pos = -self.fixed_size print("没有仓位,我开空") elif self.pos > 0: self.sell(self.boll_mid, abs(self.pos), True) elif self.pos < 0: self.cover(self.boll_mid, abs(self.pos), True) # 画图专用 if self.singnal != self.singnal_list: plot = self.singnal else: plot = None self.time_list.append(bar.datetime) self.open_list.append(bar.open_price) self.high_list.append(bar.high_price) self.low_list.append(bar.low_price) self.close_list.append(bar.close_price) self.volume_list.append(bar.volume) self.up_list.append(self.boll_up_current) self.down_list.append(self.boll_down_current) self.mid_list.append(self.boll_mid) self.singnal_plot.append(plot) self.plot_echarts = { "datetime": self.time_list, "open": self.open_list, "high": self.high_list, "low": self.low_list, "close": self.close_list, "volume": self.low_list, "boll_up": self.up_list, "boll_down": self.down_list, "boll_mid": self.mid_list, "signal": self.singnal_plot } self.singnal_list = self.singnal self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction.value == Direction.LONG.value: if trade.offset.value == Offset.OPEN.value: self.singnal = 1 elif trade.offset.value == Offset.CLOSE.value: self.singnal = 0 else: self.singnal = None elif trade.direction.value == Direction.SHORT.value: if trade.offset.value == Offset.OPEN.value: self.singnal = -1 elif trade.offset.value == Offset.CLOSE.value: self.singnal = 0 else: self.singnal = None def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def boll_calculate(self): """ 计算布林 :return: """ if not self.boll_inited: self.boll_count += 1 if self.boll_count >= 6: self.boll_inited = True self.up_array[:-1] = self.up_array[1:] self.down_array[:-1] = self.down_array[1:] sma_array = self.am.sma(self.boll_length, True) std_array = self.am.std(self.boll_length, True) dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_length:].max() up = sma_array[-1] + std_array[-1] * dev_max down = sma_array[-1] - std_array[-1] * dev_max self.up_array[-1] = up self.down_array[-1] = down
def reverse2_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}): length = 30 offset1 = -30 offset2 = int(-10) close = am.close deg1 = calc_regress_deg(close[-30:-8], False) deg2 = calc_regress_deg(close[-8:], False) if deg1 > 0 and deg2 > 0 or \ deg1 < 0 and deg2 < 0: return if not (abs(deg1) > 0.15 and abs(deg2) > 0.15 and (abs(deg1) + abs(deg2)) > 0.35) : return close = am.close[-length:] min_val = np.min(close) max_val = np.max(close) mid_val = max_val if deg1 > 0 else min_val mid_pos = np.where(close == mid_val)[0][0] if mid_pos < setting["mid_sign"][0] or mid_pos > setting["mid_sign"][1]: return start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(close[:mid_pos]) start_pos = np.where(close == start_val)[0][0] l = mid_pos - start_pos # pos2 = np.where(close == min_val)[0][0] kdj = am.kdj() k = kdj["k"][-1] d = kdj["d"][-1] j = kdj["j"][-1] x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True) deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False) y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True) deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False) # print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val) cci = am.cci(20) ma60 = am.sma(60) if deg2 < 0: # if k < 20 and d < 10 and j < 10: # if kdj[2] < 10: if cci < -100 and bar.close_price < ma60: if self.pos == 0: calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci) return self.short(bar.close_price, 1, type=OrderType.MARKET) elif self.pos > 0: calc_data["trade_close"] = "平多后做空仓,deg={},cci={}".format(deg2, cci) order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET) order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET) return order_id_cover.extend(order_id_buy) else: # if k > 80 and d > 90 and j > 90: # if kdj[2] > 90: if cci > 100 and bar.close_price > ma60: if self.pos == 0: calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci) return self.buy(bar.close_price, 1, type=OrderType.MARKET) elif self.pos < 0: calc_data["trade_close"] = "平空后多仓,deg={},cci={}".format(deg2, cci) order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET) order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET) return order_id_cover.extend(order_id_buy)
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 PatternScoreStrategy(CtaTemplate): author = "用Python的交易员" ma_level = [10, 20, 30, 60, 120] ma_tag = [] bd = [] fast_ma0 = 0.0 fast_ma1 = 0.0 slow_ma0 = 0.0 slow_ma1 = 0.0 request_order = [] bar_identify = [] score = Score() count = 0 interval = 6 parameters = ["ma_level"] variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(PatternScoreStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar) self.am = ArrayManager(400) self.am3 = ArrayManager(150) self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar) self.am5 = ArrayManager(120) self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.order_data = None self.positions = Position(self) self.std_range = IntervalGen(np.std, 5) self.std_range3 = IntervalGen(np.std, 5) self.std_range5 = IntervalGen(np.std, 5) self.pattern_record = PatternRecord() # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3) self.pattern_record.set_expiry(list(KlinePattern), 1) self.open_strategy = [self.open_kline1] self.offset = 40 self.min = 0 self.max = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) self.bg3.update_tick(tick) self.bg5.update_tick(tick) def on_3min_bar(self, bar: BarData): self.am3.update_bar(bar) self.std_range3.update(self.am3.range[-1]) if not self.am.inited or not self.trading: return # deg = calc_regress_deg(self.am3.close[-20:]) def calc_score(self): score = 0 score += self.score.base for item in self.pattern_record.values(): score += item["value"] return score def on_5min_bar(self, bar: BarData): self.std_range5.update(self.am5.range[-1]) self.am5.update_bar(bar) if not self.am.inited or not self.trading: return diff_time = bar.datetime - self.am.time_array[-1] if diff_time.total_seconds() > 3600 or self.count > self.interval: self.count = 0 self.score.base = calc_regress_deg(self.am.close[-self.interval:], False) * 1000 print("score:", self.score.base, self.min, self.max) else: self.count += 1 # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR] pattern = self.am5.pattern(list(KlinePattern)) if len(pattern) > 0: print( list( map(lambda x: (KLINE_PATTERN_CHINESE[x[0]], x[1]), pattern))) self.pattern_record.add_pattern(pattern) deg_full = calc_regress_deg(self.am.close[-40:], False) print("deg:", deg_full) self.pattern_record.update() def open_kline1(self, bar: BarData, calc_data): score = self.calc_score() if score < self.min: self.min = score if score > self.max: self.max = score if abs(calc_data["range_sum"]) < 0.001 or abs(score) < 300: return # if std_val2 < 0.2: if score > 0 and calc_data["range_sum"] > 0: return self.buy(bar.close_price, 1, type=OrderType.MARKET, extra={ "reason": "开多,score={}, rang_sum={}".format( score, calc_data["range_sum"]) }) if score < 0 and calc_data["range_sum"] < 0: return self.short(bar.close_price, 1, type=OrderType.MARKET, extra={ "reason": "开多,score={}, rang_sum={}".format( score, calc_data["range_sum"]) }) def generate_data(self, bar: BarData): offset = -self.offset offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) std_val2 = np.std(np.array(self.ma_tag[-10:-1])) std_val3 = np.std(np.array(self.am.range[-30:-10])) ma = self.ma_tag[-1] mean_val = np.mean(calc_nums) mean_val2 = np.mean(np.array(self.ma_tag[-5:-1])) mean_val3 = np.mean(np.array(self.ma_tag[-20:-1])) mean_val4 = np.mean(np.array(self.ma_tag[-30:-5])) kdj_val = self.am.kdj() deg1 = calc_regress_deg(self.am.close[offset:offset_m], False) deg2 = calc_regress_deg(self.am.close[offset_m:], False) deg3 = calc_regress_deg(self.am.close[-10:], False) deg_full = calc_regress_deg(self.am.close[offset:], False) calc_data = (dict(kdj=[ round(kdj_val["k"][-1], 2), round(kdj_val["d"][-1], 2), round(kdj_val["j"][-1], 2) ], deg40_20=round(deg1, 2), deg20=round(deg2, 2), deg10=round(deg3, 2), deg_f=round(deg_full, 2), time=bar.datetime, price=bar.close_price, ma=round(ma, 2), std_40=round(std_val, 2), mean40=round(mean_val, 2), std_10=round(std_val2, 2), mean30_10=round(mean_val4, 2), mean10=round(mean_val2, 2), vol=self.am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=self.am.range[-1:-5:-1].tolist(), range_sum=np.sum(self.am.range[-5:]), atr=self.am.atr(10), tr=self.am.atr(1, length=2), pattern=list( map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())))) return calc_data def on_strategy(self, bar: BarData): calc_data = self.generate_data(bar) order_id = None if self.pos == 0: for open_strategy in self.open_strategy: if order_id is not None: break order_id = open_strategy(bar, calc_data) else: order_id = self.positions.on_strategy(bar, calc_data) if order_id is not None: offset = -self.offset offset_m = int(offset / 2) self.tracker["trade_info"].append( (self.am.time_array[offset], self.am.time_array[offset_m], bar.datetime, calc_data["deg40_20"], calc_data["deg20"])) self.request_order.extend(order_id) if self.tracker is not None: self.tracker["ma_tag_ls"].append(calc_data) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg3.update_bar(bar) self.bg5.update_bar(bar) am = self.am self.am.update_bar(bar) max_len = self.ma_level[-1] + 20 data = self.am.close[-max_len:-1] ma_lvl = [] for i in self.ma_level: ma = self.am.sma(i, True)[-1] ma_lvl.append(ma) l = len(ma_lvl) ma_lvl_tag = [] now = bar.close_price direction = 1 if now > ma_lvl[0] else 0 ma_lvl_tag.append(direction) for i in range(l - 1): val = 1 if ma_lvl[i] > ma_lvl[i + 1] else 0 ma_lvl_tag.append(val) bincount_val = np.bincount(np.array(ma_lvl_tag)) tag_val = 0 if len(bincount_val) == 2: tag_val = bincount_val[1] if len(self.ma_tag) < 200: self.ma_tag.append(tag_val) else: self.ma_tag[:-1] = self.ma_tag[1:] self.ma_tag[-1] = tag_val if self.tracker is not None: self.tracker["bar_data"].append(bar) self.std_range.update(self.am.range[-1]) if not self.am.inited or not self.trading: return self.on_strategy(bar) # median_val = np.median(calc_nums) self.put_event() # def init_order_data(self): # self.order_data = np.array([]) def on_order(self, order: OrderData): """ Callback of new order data update. """ print("{}产生了{},价格为{},交易{},".format( order.datetime.strftime("%m/%d %H:%M:%S"), order.offset.value + order.direction.value, order.price, order.status.value)) if order.vt_orderid in self.request_order: self.positions.on_order(order) if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED: self.request_order.remove(order.vt_orderid) # if order.status == Status.ALLTRADED or order.status == Status.PARTTRADED: # if order.direction == Direction.LONG: # if self.positions.volumn == 0: # self.positions.close_price = round(order.price * 0.995) # self.positions.volumn += order.volume # elif order.direction == Direction.SHORT: # self.positions.volumn -= order.volume # elif order.direction == Direction.NET: # self.positions.volumn = order.volume def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class BollVixSignal(CtaSignal): """ 布林 vix """ sma_array = 0 boll_up_array = 0 boll_down_array = 0 entry_crossover = 0 atr_value = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 def __init__(self, open_window, boll_window: int): """""" super().__init__() self.open_window = open_window self.boll_window = boll_window self.bg = BarGenerator(self.on_bar, self.open_window, self.on_xmin_bar) self.am = ArrayManager() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.am.update_bar(bar) if not self.am.inited: self.set_signal_pos(0) # Calculate array 计算数组 self.sma_array = self.am.sma(self.boll_window, True) std_array = self.am.sma(self.boll_window, True) dev = abs(self.am.close[:-1] - self.sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_window:].max() self.boll_up_array = self.sma_array[:-1] + std_array[:-1] * dev_max self.boll_down_array = self.sma_array[:-1] - std_array[:-1] * dev_max # Get current and last index last_sma = self.sma_array[-2] current_sma = self.sma_array[-1] last_close = self.am.close[-2] current_boll_up = self.boll_up_array[-1] last_boll_up = self.boll_up_array[-2] current_boll_down = self.boll_down_array[-1] last_boll_down = self.boll_down_array[-2] # Get crossover if last_close <= last_boll_up and current_boll_up < bar.close_price: self.set_signal_pos(1) elif last_close >= last_boll_down and current_boll_down > bar.close_price: self.set_signal_pos(-1) exit_long = last_close >= last_sma and current_sma > bar.close_price exit_short = last_close <= last_sma and current_sma < bar.close_price if exit_long and exit_short: self.set_signal_pos(0)
class BollVix(CtaTemplate): """""" author = "yunya" open_window = 15 boll_window = 80 fixed_size = 1 boll_mid_current = 0 boll_mid_last = 0 boll_up_current = 0 boll_up_last = 0 boll_down_current = 0 boll_down_last = 0 target_pos = 0 pos_inited = 0 parameters = [ "open_window", "boll_window", "fixed_size", ] variables = [ "boll_mid_current", "boll_mid_last", "boll_up_current", "boll_up_last", "boll_down_current", "boll_down_last", "pos_inited", "target_pos" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_minute_bar, interval=Interval.MINUTE) self.am = ArrayManager(self.boll_window * 2) self.up_array: np.ndarray = np.zeros(5) self.down_array: np.ndarray = np.zeros(5) self.boll_inited = False self.boll_count = 0 self.engine_type = self.get_engine_type() self.vt_orderids = [] self.order_price = 0 self.pos_inited = 0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(12) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) # 只有实盘交易才使用BestLimit算法 if self.engine_type != EngineType.LIVE: return # 当前没有仓位 order_volume_open = self.target_pos - self.pos if not order_volume_open: return if order_volume_open > 0: if not self.vt_orderids: self.order_price = tick.bid_price_1 vt_orderids = self.buy(self.order_price, abs(order_volume_open)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.bid_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) elif order_volume_open < 0: if not self.vt_orderids: self.order_price = tick.ask_price_1 vt_orderids = self.short(self.order_price, abs(order_volume_open)) self.vt_orderids.extend(vt_orderids) elif self.order_price != tick.ask_price_1: for vt_orderid in self.vt_orderids: self.cancel_order(vt_orderid) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_minute_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算布林 self.boll_calculate() if not self.boll_inited: return boll_mid_array = self.am.sma(self.boll_window, True) # 计算数组 self.boll_mid = boll_mid_array[-2] self.boll_up_current = self.up_array[-1] self.boll_up_last = self.up_array[-2] self.boll_down_current = self.down_array[-1] self.boll_down_last = self.down_array[-2] if not self.pos: self.pos_inited = 0 if self.am.close[-1] > self.boll_up_current and self.am.close[-2] <= self.boll_up_last: if self.engine_type == EngineType.BACKTESTING: self.buy(self.boll_up_current, self.fixed_size) else: self.target_pos = self.fixed_size print("没有仓位,我开多") elif self.am.close[-1] < self.boll_down_current and self.am.close[-2] >= self.boll_down_last: if self.engine_type == EngineType.BACKTESTING: self.short(self.boll_down_current, self.fixed_size) else: self.target_pos = -self.fixed_size print("没有仓位,我开空") elif self.pos > 0: self.sell(self.boll_mid, abs(self.pos), True) elif self.pos < 0: self.cover(self.boll_mid, abs(self.pos), True) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def boll_calculate(self): """ 计算布林 :return: """ if not self.boll_inited: self.boll_count += 1 if self.boll_count >= 6: self.boll_inited = True self.up_array[:-1] = self.up_array[1:] self.down_array[:-1] = self.down_array[1:] sma_array = self.am.sma(self.boll_window, True) std_array = self.am.std(self.boll_window, True) dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1] dev_max = dev[-self.boll_window:].max() up = sma_array[-1] + std_array[-1] * dev_max down = sma_array[-1] - std_array[-1] * dev_max self.up_array[-1] = up self.down_array[-1] = down
class 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 MyBollingStrategy(CtaTemplate): """基于布林通道的交易策略""" className = 'MyBollingerBotStrategy' 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 = 15 # 初始化数据所用的天数 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 = [] tradedata_boll = [] #所有的需要在布林线止损的交易单 tradedata_baoben = [] #所有的已经过了保本线的交易单 tradedata_day = [] #所有的需要在日线布林中轨止损的交易单 # 参数列表,保存了参数的名称 parameters = [ 'bollWindow5min', 'bollWindow15min', 'bollWindow30min', 'entryDev', 'initDays', '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, 9, self.onDayBar, Interval.HOUR) self.amDay = ArrayManager(30) head = [ "datetime", "BollStatus", "open", "close", "high", "low", "openInterest", "volume", "deal", "pDown", "pUp", "dealOpen" ] write_csv_file("datasig5.csv", head, None, "w") write_csv_file("datasig15.csv", head, None, "w") write_csv_file("datasig30.csv", head, None, "w") write_csv_file("datasigDay.csv", head, None, "w") head = [ "datetime", "orderid", "tradeid", "direction", "offset", "price", "volume" ] write_csv_file("datasigTrade.csv", head, None, "w") #---------------------------------------------------------------------- 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) #判断当前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线推送""" t1 = str(bar.datetime) t2 = str(datetime(2016, 2, 3, 21, 0, 0)) if t2 in t1: i = 0 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 if not self.tradedata: #策略启动到现在无交易 if self.ThirtyMinTrendStatus == 'panzhen' and self.DayTrendStatus == 'duotou': self.buy(self.longEntry, self.fixedSize, True) elif self.ThirtyMinTrendStatus == 'panzhen' and self.DayTrendStatus == 'kongtou': self.short(self.shortEntry, self.fixedSize, True) else: #策略启动到现在有交易 #需要在布林线上下轨止损的但系,重新发出止损单子 trade = self.tradedata[-1] if trade.offset == Offset.CLOSE: #最后一个交易为平仓单,发送开仓单在布林线上下轨 if self.ThirtyMinTrendStatus == 'panzhen' and self.DayTrendStatus == 'duotou': self.buy(self.longEntry, self.fixedSize, True) elif self.ThirtyMinTrendStatus == 'panzhen' and self.DayTrendStatus == 'kongtou': self.short(self.shortEntry, self.fixedSize, True) elif trade.offset == Offset.OPEN and trade.direction == Direction.LONG: # 最后一笔交易为多头仓位,发送平仓单在下轨 orderList = self.sell(self.longExit, trade.volume, True) print(u"策略:%s,委托止损单,30分钟下轨平仓" % self.className) elif trade.offset == Offset.OPEN and trade.direction == Direction.SHORT: # 最后一笔交易为空头仓位,发送平仓单在上轨 orderList = self.cover(self.shortExit, trade.volume, True) print(u"策略:%s,委托止损单,30分钟上轨平仓" % self.className) #需要在保本位置设置止损的交易单,重新发出止损单子 if len(self.tradedata_baoben) > 0: i = 0 while i < len(self.tradedata_day): volume = self.tradedata_baoben[i].volume i = i + 1 if self.tradedata_baoben[i - 1].direction == Direction.LONG: orderList = self.sell(self.tradedata_baoben[i].price, volume, True) print(u"策略:%s,委托止损单,保本价格平仓" % self.className) elif self.tradedata_baoben[i - 1].direction == Direction.SHORT: orderList = self.cover(self.tradedata_baoben[i].price, volume, True) print(u"策略:%s,委托止损单,保本价格平仓" % self.className) #需要在日线中轨止损的单子,需要在新的日线中轨处发出止损单 if len(self.tradedata_day) > 0: i = 0 volume = 0 while i < len(self.tradedata_day): volume = self.tradedata_day[i].volume + volume i = i + 1 if self.tradedata_day[i - 1].direction == Direction.LONG: orderList = self.sell(self.shortExit, volume, True) print(u"策略:%s,委托止损单,日线中轨平仓" % self.className) elif self.tradedata_day[i - 1].direction == Direction.SHORT: orderList = self.cover(self.shortExit, volume, True) print(u"策略:%s,委托止损单,日线中轨平仓" % self.className) 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("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线推送""" 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 len(self.tradedata_day) > 0: i = 0 volume = 0 while i < len(self.tradedata_day): volume = self.tradedata_day[i].volume + volume i = i + 1 if self.tradedata_day[i - 1].direction == Direction.LONG: orderList = self.sell(self.shortExit, volume, True) print(u"策略:%s,委托止损单,日线中轨平仓" % self.className) elif self.tradedata_day[i - 1].direction == Direction.SHORT: orderList = self.cover(self.shortExit, volume, True) print(u"策略:%s,委托止损单,日线中轨平仓" % self.className) ''' #日线盘整,上下轨开仓 if self.DayTrendStatus=="panzhen" and self.pos==0: self.cancelAll() orderList=[] orderList=self.buy(self.bollUpDay+self.priceTick, self.fixedSize, True) print (u"策略:%s,委托多单,日线上轨开仓"%self.__dict__["name"]) if orderList: print (u"策略:%s,委托单成功,单号%s"%(self.__dict__["name"],orderList[-1])) else: print (u"策略:%s,委托单失败"%self.__dict__["name"]) orderList=[] orderList=self.short(self.bollDownDay-self.priceTick, self.fixedSize, True) print (u"策略:%s,委托空单,日线下轨开仓"%self.__dict__["name"]) if orderList: print (u"策略:%s,委托单成功,单号%s"%(self.__dict__["name"],orderList[-1])) else: print (u"策略:%s,委托单失败"%self.__dict__["name"] ) ''' bardata = [ bar.datetime, self.DayTrendStatus, bar.open_price, bar.close_price, bar.high_price, bar.low_price, bar.open_interest, bar.volume, self.pos, self.bollDownDay, self.bollUpDay, self.dealopen ] write_csv_file("datasigDay.csv", None, bardata, "a+") print(u"时间:", bar.datetime) print(u"策略:%s,日线刷新,趋势状态,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s" % (self.className, self.FiveMinTrendStatus, self.FifteenMinTrendStatus, self.ThirtyMinTrendStatus, self.DayTrendStatus)) print(u"日线开盘价", self.amDay.open_array[1:]) print(u"日线收盘价", self.amDay.close_array[1:]) # 发出状态更新事件 self.put_event() #---------------------------------------------------------------------- def on_order(self, order): """收到委托变化推送(必须由用户继承实现)""" pass #---------------------------------------------------------------------- def on_trade(self, trade): #打印信息 print("策略:%s,趋势状态,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s" % (self.className, self.FiveMinTrendStatus, self.FifteenMinTrendStatus, self.ThirtyMinTrendStatus, self.DayTrendStatus)) print(u"策略:%s, 委托单成交" % self.className) print(trade.direction) print(trade.offset) #print "15min:",self.FifteenMinTrendStatus #print "5min:",self.FiveMinTrendStatus #head=["datetime","orderid","tradeid","direction","offset","price","volume"] #所有交易单保存下来 self.tradedata.append(trade) #开仓的交易单单独保存下来到需要布林止损的list中 if trade.offset == Offset.OPEN: self.tradedata_boll.append(trade) #保存到文件 tradedata = [ trade.datetime, trade.orderid, trade.tradeid, trade.direction, trade.offset, trade.price, trade.volume ] write_csv_file("datasigTrade.csv", None, tradedata, "a+") #开仓成功后先取消掉还有的挂单,主要针对的是日线的双向挂单 #if self.pos!=0: # self.cancel_all() # 发出状态更新事件 orderList = [] if trade.offset == Offset.OPEN and trade.direction == Direction.LONG: #多头成交,设置止损单 orderList = self.sell(self.bollDown30 - self.priceTick, trade.volume, True) print(u"委托止损单,30分钟下轨平仓") if orderList: print(u"委托单成功单号", orderList) else: print(u"委托单失败") elif trade.offset == Offset.OPEN and trade.direction == Direction.SHORT: #空头成交,设置止损单 orderList = self.cover(self.bollUp30 + self.priceTick, trade.volume, True) print(u"委托止损单,30分钟上轨平仓") if orderList: print(u"委托单成功单号", orderList) else: print(u"委托单失败") #更新周期状态 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.deal = 1 else: self.deal = -1 self.put_event() #---------------------------------------------------------------------- def on_stop_order(self, so): """停止单推送""" pass