def generate_3mindata(self, am:ArrayManager, bar:BarData): offset = -self.offset offset_m = int(offset / 2) calc_nums = np.array(self.ma_tag[-offset:-1]) # var_val = np.var(calc_nums) std_val = np.std(calc_nums) std_val2 = np.std(np.array(self.ma_tag[-10:-1])) std_val3 = np.std(np.array(am.range[-30:-10])) ma = self.ma_tag[-1] mean_val = np.mean(calc_nums) mean_val2 = np.mean(np.array(self.ma_tag[-5:-1])) mean_val3 = np.mean(np.array(self.ma_tag[-20:-1])) mean_val4 = np.mean(np.array(self.ma_tag[-30:-5])) kdj_val = am.kdj() deg1 = calc_regress_deg(am.close[offset : offset_m], False) deg2 = calc_regress_deg(am.close[offset_m :], False) deg3 = calc_regress_deg(am.close[-10 :], False) deg_full = calc_regress_deg(am.close[offset :], False) wave = self.wave(am.close[-30:]) wave_r_sum = np.sum(wave["range"]) macd=am.macd(20,40, 16) calc_data = (dict( kdj=[round(kdj_val["k"][-1],2),round(kdj_val["d"][-1],2),round(kdj_val["j"][-1],2)], cci_20=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=am.boll(20, 3.4), macd=[round(macd[0],2),round(macd[1],2),round(macd[2],2)], deg40_20=round(deg1,2), deg20_0=round(deg2,2), deg20_10=round(calc_regress_deg(am.close[-20:-10], False),2), deg10_0=round(deg3,2), deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2), atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(am.atr(40, length=42), 3), time=bar.datetime, price=bar.close_price, ma=round(ma, 2), std_40=round(std_val, 2),mean40=round(mean_val,2), mean_std=np.mean(self.std_range.data[-5:]), std_10=round(std_val2,2), mean30_10=round(mean_val4,2), mean10=round(mean_val2,2), vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(), range_sum=np.sum(am.range[-5:]), pattern=list(map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())), ma120t=self.ma120_track, ma120t_list=self.ma120_track_list[-1:-10:-1], ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs), ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]), ma_info=list(map(lambda x:x["std"], self.ma_info[-1:])), wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(am.atr(20, array=True,length=240)[-200:]) )) return calc_data
class RsiAdaptStrategy(CtaTemplate): """ 策略逻辑: 一、、过虑信号 (小时周期) 使用rsiboll来判断信号强弱 二、开单信号 (分钟周期) 1、使用布林上下轨作为开单条件 三、止损 使用动态布林中轨止损 """ author = "yunya" min_window = 15 open_window = 5 rsi_length = 15 boll_length = 80 boll_dev = 2.0 trading_size = 1 rsi_value = 0 rsi_up = 0 rsi_dow = 0 rsi_entry = 0 boll_up = 0 boll_down = 0 boll_mid = 0 boll_length_new = 0 current_boll_mid = 0 last_boll_mid = 0 current_close = 0 last_close = 0 front_close = 0 exit_long = 0 exit_short = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 parameters = [ "min_window", "open_window", "rsi_length", "boll_length", "boll_dev", "trading_size", ] variables = [ "rsi_value", "rsi_up", "rsi_dow", "rsi_entry", "boll_up", "boll_down", "boll_mid", "boll_length_new", "current_boll_mid", "last_boll_mid", "current_close", "last_close", "front_close", "exit_long", "exit_short", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", ] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.atr_stop_array = np.zeros(10) self.bg_xminute = NewBarGenerator(on_bar=self.on_bar, window=self.min_window, on_window_bar=self.on_xminute_bar) self.am_xminute = ArrayManager(self.boll_length + 100) self.bg_open = NewBarGenerator(on_bar=self.on_bar, window=self.open_window, on_window_bar=self.on_5min_bar) self.am_open = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化。。") self.load_bar(10) self.put_event() def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动。。") self.put_event() def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止。。") self.put_event() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_open.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_5min_bar(self, bar: BarData): """ :param bar: :type bar: :return: :rtype: """ self.cancel_all() self.am_open.update_bar(bar) if not self.am_open.inited or not self.am_xminute.inited: return if not self.pos: if self.rsi_entry > 0: self.buy(self.boll_up, self.trading_size, True) # print(bar.datetime, self.boll_up, self.trading_size) # print(bar.datetime, self.entry_up, self.trading_size, bar) elif self.rsi_entry < 0: self.short(self.boll_down, self.trading_size, True) elif self.pos > 0: # 仓位是long 时,如果价格下穿新布林中轨 con1 = bar.close_price < self.current_boll_mid con2 = bar.close_price >= self.last_boll_mid if con1 and con2: self.exit_long_nex = bar.close_price # 保存当前收盘价 if self.exit_long_last == 0 or self.exit_long_nex > self.exit_long_last: self.exit_long_last = self.exit_long_nex self.boll_length_new = self.boll_length # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.boll_mid else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if bar.close_price > ( (self.boll_mid + self.current_boll_mid) / 2): self.exit_long = bar.close_price elif bar.close_price < self.boll_mid: self.exit_long = bar.close_price else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.boll_mid self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: # 仓位是short 时,如果价格上穿新布林中轨 con1 = bar.close_price > self.current_boll_mid con2 = bar.close_price <= self.last_boll_mid if con1 and con2: self.exit_short_nex = bar.close_price if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last: self.exit_short_last = self.exit_short_nex self.boll_length_new = self.boll_length self.exit_short = self.boll_mid else: if bar.close_price < (self.boll_mid + self.current_boll_mid / 2): self.exit_short = bar.close_price elif bar.close_price < self.boll_mid: self.exit_short = bar.close_price else: self.exit_short = self.boll_mid else: self.exit_short = self.boll_mid self.cover(self.exit_short, abs(self.pos), True) self.sync_data() self.put_event() def on_xminute_bar(self, bar: BarData): """ :param bar: :return: """ self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length) ema_array = talib.EMA(self.am_xminute.close, self.rsi_length) dev_array = abs(self.am_xminute.close[:-1] - ema_array[:-1]) / rsi_array rsi_up_array = rsi_array + rsi_array * dev_array rsi_dow_array = rsi_array - rsi_array * dev_array self.rsi_value = self.am_xminute.rsi(self.rsi_length) self.rsi_up = rsi_up_array[-1] self.rsi_dow = rsi_dow_array[-1] current_rsi_up = rsi_up_array[-1] current_rsi_down = rsi_dow_array[-1] if self.rsi_value > current_rsi_up: self.rsi_entry = 1 elif self.rsi_value < current_rsi_down: self.rsi_entry = -1 self.boll_up, self.boll_down = self.am_xminute.boll( self.boll_length, self.boll_dev) self.boll_mid = self.am_xminute.sma(self.boll_length) self.current_close = self.am_xminute.close[-1] self.last_close = self.am_xminute.close[-2] self.front_close = self.am_xminute.close[-3] if self.pos == 0: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.boll_length_new = self.boll_length elif self.pos > 0: # 上涨或下跌时,布林中轨均值减1 close_long = self.current_close > self.last_close > self.front_close if close_long: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 5) elif self.pos < 0: close_short = self.current_close < self.last_close < self.front_close if close_short: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 5) boll_mid_new = self.am_xminute.sma(self.boll_length_new, True) self.current_boll_mid = boll_mid_new[-1] self.last_boll_mid = boll_mid_new[-2] self.sync_data() def on_trade(self, trade: TradeData): """ 有成交时 Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ 订单更新回调 Callback of new order data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event()
class 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 AberrationBiasStrategy(CtaTemplate): """ 目前使用中轨加速,可以考虑使用另外一根均线来加速,这样可以避免在开仓时被平。 """ author = "yunya" open_window = 60 boll_length = 80 boll_dev = 2.0 bias = 1.0 cci_length = 6 cci_exit = 10.0 fixed_size = 1 boll_up = 0 boll_down = 0 boll_mid = 0 boll_mid_new = 0 boll_mid_array = 0 bias_value_array = 0 bias_value = 0 cci_value = 0 exit_long = 0 exit_short = 0 boll_length_new = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 parameters = [ "open_window", "boll_length", "boll_dev", "bias", "cci_length", "cci_exit", "fixed_size", ] variables = [ "boll_up", "boll_down", "boll_mid", "bias_value", "cci_value", "exit_long", "exit_short", "boll_length_new", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_xmin_bar) self.am = ArrayManager(int(self.boll_length) + 100) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算原布林带 self.boll_up, self.boll_down = self.am.boll(self.boll_length, self.boll_dev) self.boll_mid_array = am.sma(self.boll_length, True) self.boll_mid = self.boll_mid_array[-1] self.bias_value_array = (self.am.close - self.boll_mid_array) / self.boll_mid_array self.bias_value = self.bias_value_array[-1] self.cci_value = am.cci(self.cci_length) # 如果没有仓位,两条布林window一样 if self.pos == 0: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.boll_length_new = self.boll_length if self.cci_value > self.cci_exit: self.buy(self.boll_up, self.fixed_size, True) if self.cci_value < -self.cci_exit: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: # 上涨或下跌时,布林中轨均值减1 close_long = am.close[-1] > am.close[-2] > am.close[-3] if close_long: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 20) # 计算新的布林带 self.boll_mid_new = am.sma(self.boll_length_new, True) # 仓位是long 时,如果价格上穿新布林中轨 con1 = am.close[-1] < self.boll_mid_new[-1] con2 = am.close[-2] >= self.boll_mid_new[-2] if con1 and con2: self.exit_long_nex = am.close[-1] # 保存当前收盘价 if self.exit_long_nex > self.exit_long_last or self.exit_long_last == 0: self.exit_long_last = self.exit_long_nex self.boll_length_new = self.boll_length # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.boll_mid # print(f"我是多单,exitlast:{self.exit_short_last},重置布林中轨参数,止损挂{self.exit_long}:") else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if self.am.close[-1] > ( (self.boll_mid + self.boll_mid_new[-1]) / 2): self.exit_long = bar.close_price # print(f"我是多单,收盘价在两个中轨均值上方,以收盘价挂止损单:{self.exit_long}") elif bar.close_price < self.boll_mid: self.exit_long = bar.close_price else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在新中轨上方,以原中轨挂止损单:{self.exit_long}") if self.bias_value > self.bias: self.exit_long = max(bar.close_price, self.exit_long) self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: close_short = am.close[-1] < am.close[-2] < am.close[-3] if close_short: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 20) # 计算新的布林带 self.boll_mid_new = am.sma(self.boll_length_new, True) # 仓位是short 时,如果价格上穿新布林中轨 con3 = am.close[-1] > self.boll_mid_new[-1] con4 = am.close[-2] <= self.boll_mid_new[-2] if con3 and con4: self.exit_short_nex = am.close[-1] if self.exit_short_nex < self.exit_short_last or self.exit_short_last == 0: self.exit_short_last = self.exit_short_nex self.boll_length_new = self.boll_length self.exit_short = self.boll_mid else: if self.am.close[-1] < (self.boll_mid + self.boll_mid_new[-1] / 2): self.exit_short = bar.close_price elif bar.close_price > self.boll_mid: self.exit_short = bar.close_price else: self.exit_short = self.boll_mid else: self.exit_short = self.boll_mid if self.bias_value < -self.bias: self.exit_short = min(self.exit_short, bar.close_price) self.cover(self.exit_short, abs(self.pos), True) self.put_event() self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event() pass
class CincoStrategyHN(CtaTemplate): """""" author = "Huang Ning" boll_window = 42 boll_dev = 2.0 trailing_long = 0.65 trailing_short = 0.7 atr_window = 10 risk_level = 100 boll_up = 0 boll_down = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "boll_window", "boll_dev", "trailing_long", "trailing_short", "atr_window", "risk_level" ] variables = [ "boll_up", "boll_down", "trading_size", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "atr_value" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(CincoStrategyHN, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """""" self.write_log("策略初始化") self.load_bar(10) def on_start(self): """""" self.write_log("策略启动") def on_stop(self): """""" self.write_log("策略停止") def on_tick(self, tick: TickData): """""" self.bg.update_tick(tick) def on_bar(self, bar: BarData): """""" self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) boll_width = self.boll_up - self.boll_down if not self.pos: self.atr_value = self.am.atr(self.atr_window) self.trading_size = int(self.risk_level / self.atr_value) self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 self.buy(self.boll_up, self.trading_size, stop=True) self.short(self.boll_down, self.trading_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_order(self, order: OrderData): """""" def on_trade(self, trade: TradeData): """""" self.put_event() def on_stop_order(self, stop_order: StopOrder): """""" self.put_event()
class CuatroStrategy(CtaTemplate): """""" author = "KeKe" rsi_signal = 19 # 定义rsi阈值 rsi_window = 14 fast_window = 4 slow_window = 26 boll_window = 20 boll_dev = 1.8 trailing_short = 0.3 trailing_long = 0.5 fixed_size = 1 boll_up = 0 boll_down = 0 rsi_value = 0 rsi_long = 0 rsi_short = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 long_stop = 0 short_stop = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "rsi_signal", "rsi_window", "fast_window", "slow_window", "boll_window", "boll_dev", "trailing_long", "trailing_short", "fixed_size" ] variables = [ "boll_up", "boll_down", "rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(CuatroStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long = 50 + self.rsi_signal # 用rsi阈值定义rsi超买区域 self.rsi_short = 50 - self.rsi_signal # 用rsi阈值定义rsi超卖区域 self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) # 合成5分钟K线 self.am5 = ArrayManager() # 初始化5分钟k线的时间序列 self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar) # 合成15分钟k线 self.am15 = ArrayManager() # 初始化15分钟k线的时间序列 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) # 载入最近10根bar 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) # 将1分钟k线推送入bg5合成5分钟线 self.bg15.update_bar(bar) # 将1分钟k线推送入bg15合成15分钟线 def on_5min_bar(self, bar: BarData): """在5分钟级别进行交易""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return if not self.ma_trend: # 如果ma_trend没有初始化,就跳过这根bar return self.rsi_value = self.am5.rsi(self.rsi_window) # 生成5分钟线的rsi指标 self.boll_up, self.boll_down = self.am5.boll( self.boll_window, self.boll_dev) # 生成5分钟线的bolling指标 boll_width = self.boll_up - self.boll_down # 赋值boll宽度变量 ## 当空仓时 if self.pos == 0: self.intra_trade_low = bar.low_price # 记录最低价,用于追踪买入后最低价 self.intra_trade_high = bar.high_price # 记录最高价,用于追踪买入后最高价 if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: # 当上升趋势,且进入超买区 self.buy(self.boll_up, self.fixed_size, True) # 在bolling带上轨开1手多头单 elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short: # 当下降趋势,且进入超卖区 self.short(self.boll_down, self.fixed_size, True) # 在bolling带下轨开1手空头仓位 ## 当持有多头仓时 elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) # 逐根k线记录到达过的最高价 self.long_stop = (self.intra_trade_high - self.trailing_long * boll_width ) # 追踪止损位是最高价*0.5*boll宽度 self.sell(self.long_stop, abs(self.pos), True, True) # 在追踪止损价位平所有多头仓 ## 当持有空头仓时 elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) # 逐根k线记录到达过的最低价 self.short_stop = (self.intra_trade_low + self.trailing_short * boll_width) # 追踪止损位 self.cover(self.short_stop, abs(self.pos), True, True) # 轧空 self.put_event() def on_15min_bar(self, bar: BarData): """在15分钟级别主要用于判断市场的趋势,起筛选作用""" self.am15.update_bar(bar) # 推送bar,生成15分钟的时间序列 if not self.am15.inited: # 判断15分钟线是否已初始化 return self.fast_ma = self.am15.sma(self.fast_window) # 生成15分钟级别的移动平均线快线 self.slow_ma = self.am15.sma(self.slow_window) # 生成15分钟级别的移动平均线慢线 if self.fast_ma > self.slow_ma: # 当金叉以后 self.ma_trend = 1 # 1代表上升趋势 else: self.ma_trend = -1 # -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 AroonAtrStrategy(CtaTemplate): """""" author = "tonywang_efun" fixed_size = 1 bar_window = 26 boll_window = 39 boll_dev = 1.9 aroon_window = 14 aroon_long = 50 aroon_short = 50 atr_window = 30 atr_stop_multiplier = 3 boll_up = 0 boll_down = 0 aroon_up = 0 aroon_down = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "fixed_size", "bar_window", "boll_window", "boll_dev", "aroon_window", "aroon_long", "aroon_short", "atr_window", "atr_stop_multiplier" ] variables = [ "boll_up", "boll_down", "aroon_up", "aroon_down", "atr_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] def __init__( self, cta_engine, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.bar_window, self.on_xmin_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.aroon_up, self.aroon_down = self.am.aroon(self.aroon_window) self.atr_value = self.am.atr(self.atr_window) self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 if self.aroon_up > self.aroon_down and self.aroon_up > self.aroon_long: self.buy(self.boll_up, self.fixed_size, stop=True) if self.aroon_down > self.aroon_up and self.aroon_down > self.aroon_short: self.short(self.boll_down, self.fixed_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.atr_value * self.atr_stop_multiplier self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.atr_value * self.atr_stop_multiplier self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
def generate_data(self, am: ArrayManager, bar: BarData): offset = -self.offset offset_m = int(offset / 2) std_val3 = np.std(np.array(am.range[-30:-10])) kdj_val = am.kdj() has_kdj_recore = False k = kdj_val["k"] d = kdj_val["d"] j = kdj_val["j"] if (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \ (k[-1] < 25 and d[-1] < 25 and j[-1] < 75): if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \ or \ (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]): has_kdj_recore = True t = bar.datetime self.kdj_record.append( (t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3), round(j[-1], 3))) deg1 = calc_regress_deg(am.close[offset:offset_m], False) deg2 = calc_regress_deg(am.close[offset_m:], False) deg3 = calc_regress_deg(am.close[-10:], False) deg_full = calc_regress_deg(am.close[offset:], False) macd = am.macd(20, 40, 16) calc_data = (dict( kdj=[ round(kdj_val["k"][-1], 2), round(kdj_val["d"][-1], 2), round(kdj_val["j"][-1], 2) ], cci_20=am.cci(20), rsi=am.rsi(20), adx=am.adx(20), boll=am.boll(20, 3.4), macd=[round(macd[0], 2), round(macd[1], 2), round(macd[2], 2)], deg40_20=round(deg1, 2), deg20_0=round(deg2, 2), deg20_10=round(calc_regress_deg(am.close[-20:-10], False), 2), deg30_15=round(calc_regress_deg(am.close[-30:-15], False), 2), deg15_0=round(calc_regress_deg(am.close[-15:], False), 2), deg_f=round(deg_full, 2), deg30_10=round(calc_regress_deg(am.close[-30:-10], False), 2), deg10_0=round(deg3, 2), atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3), atr_40=round(am.atr(40, length=42), 3), time=bar.datetime, price=bar.close_price, mean_std=np.mean(self.std_range.data[-5:]), vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(), range_sum=np.sum(am.range[-5:]), pattern=list( map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())), atr_mean=np.mean(am.atr(20, array=True, length=240)[-200:]), )) if self.ma_info.info.index.size >= 31: ma5 = self.ma_info.info[5][-31:] x = AnalyseWave(ma5) calc_data["ma5_info"] = x.optimize ma10 = self.ma_info.info[10][-31:] x = AnalyseWave(ma10) calc_data["ma10_info"] = x.optimize return calc_data
class Aberration_V2_Strategy(CtaTemplate): """ 1、v1基础版上,调整了开仓进场条件为布林带收口。 2、去掉cci """ author = "yunya" open_window = 15 boll_length = 440 boll_dev = 1.8 fixed_size = 1 boll_up = 0 boll_up_last = 0 boll_down = 0 boll_down_last = 0 boll_mid = 0 boll_mid_new = 0 boll_mid_array = 0 boll_length_new = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 bbw_min = 0 bbw_ma = 0 bbw = 0 amplitude = 0 stop_time = 8 time_stop = 0 amplitude_inited = False # 画图专用 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", "boll_dev", "bias", "cci_length", "cci_exit", "fixed_size", ] variables = [ "boll_up", "boll_down", "boll_mid", "bias_value", "cci_value", "exit_long", "exit_short", "boll_length_new", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.open_window, self.on_xmin_bar) self.am = ArrayManager(int(self.boll_length) * 2) self.boll_length_new = self.boll_length def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算原布林带 boll_up_array, boll_down_array = self.am.boll(self.boll_length, self.boll_dev, True) boll_mid_array = am.sma(self.boll_length, True) self.boll_up = boll_up_array[-1] self.boll_up_last = boll_up_array[-2] self.boll_down = boll_down_array[-1] self.boll_down_last = boll_down_array[-2] self.boll_mid = boll_mid_array[-1] # 计算布林宽度 bbw_array = (boll_up_array - boll_down_array) / boll_mid_array bbw_length = int(self.boll_length / 2) self.bbw_min = bbw_array[-bbw_length - 1:-1].min() self.bbw_ma = bbw_array[-bbw_length - 1:-1].mean() self.bbw = bbw_array[-1] # 计算新中轨 close_short = am.close[-1] < am.close[-2] close_long = am.close[-1] > am.close[-2] if close_short or close_long: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 10) self.boll_mid_new = am.sma(self.boll_length_new, True) # 如果没有仓位,两条布林window一样 if self.pos == 0: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.boll_length_new = self.boll_length if self.bbw > self.bbw_min and self.bbw_min < self.bbw_ma: if self.am.close[-1] > self.boll_up and self.am.close[ -2] <= self.boll_up_last: self.buy(bar.close_price, self.fixed_size) elif self.am.close[-1] < self.boll_up and self.am.close[ -2] >= self.boll_up_last: self.short(bar.close_price, self.fixed_size) elif self.pos > 0: # 仓位是long 时,如果价格上穿新布林中轨 con1 = am.close[-1] < self.boll_mid_new[-1] con2 = am.close[-2] >= self.boll_mid_new[-2] if con1 and con2: self.exit_long_nex = am.close[-1] # 保存当前收盘价 if self.exit_long_nex > self.exit_long_last or self.exit_long_last == 0: self.exit_long_last = self.exit_long_nex self.boll_length_new = self.boll_length - 10 # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.boll_mid # print(f"我是多单,exitlast:{self.exit_short_last},重置布林中轨参数,止损挂{self.exit_long}:") else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if self.am.close[-1] > ( (self.boll_mid + self.boll_mid_new[-1]) / 2): self.exit_long = bar.close_price # print(f"我是多单,收盘价在两个中轨均值上方,以收盘价挂止损单:{self.exit_long}") elif bar.close_price < self.boll_mid: self.exit_long = bar.close_price else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在新中轨上方,以原中轨挂止损单:{self.exit_long}") self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: # 仓位是short 时,如果价格上穿新布林中轨 con3 = am.close[-1] > self.boll_mid_new[-1] con4 = am.close[-2] <= self.boll_mid_new[-2] if con3 and con4: self.exit_short_nex = am.close[-1] if self.exit_short_nex < self.exit_short_last or self.exit_short_last == 0: self.exit_short_last = self.exit_short_nex self.boll_length_new = self.boll_length - 10 self.exit_short = self.boll_mid else: if self.am.close[-1] < (self.boll_mid + self.boll_mid_new[-1] / 2): self.exit_short = bar.close_price elif bar.close_price > self.boll_mid: self.exit_short = bar.close_price else: self.exit_short = self.boll_mid else: self.exit_short = self.boll_mid self.cover(self.exit_short, abs(self.pos), 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) self.down_list.append(self.boll_down) self.mid_list.append(self.boll_mid) self.mid_new_list.append(self.boll_mid_new[-1]) 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, "boll_mid_new": self.mid_new_list, "bias": self.bias_value_list, "bias_value": self.bias_list, "signal": self.singnal_plot } self.singnal_list = self.singnal self.put_event() self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # 画图专用 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. """ self.put_event() pass
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
class MacdRsibollDcMinuteStrategy(CtaTemplate): """ 策略逻辑: 一、、过虑信号 (小时周期) 1、使用macd 快慢线交叉来判断多空大方向。 2、使用rsiboll来判断信号强弱 二、开单信号 (分钟周期) 1、使用布林上下轨作为开单条件 三、止损 1、使用固定止损 2、dc 移动止损 3、布林宽度比例 三个止损相结合的方式 """ author = "yunya" max_window = 45 min_window = 15 open_window = 5 fast_macd = 12 slow_macd = 26 signal_macd = 9 macd_trend_level = 1.0 rsi_length = 15 boll_length = 20 boll_dev = 2.0 dc_length = 20 atr_window = 30 trailing_tax = 2.0 risk_level = 1 exit_down = 0 exit_up = 0 macd = 0 macd_entry = 0 rsi_entry = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "max_window", "min_window", "open_window", "fast_macd", "slow_macd", "signal_macd", "macd_trend_level", "boll_length", "boll_dev", "rsi_length", "dc_length", "atr_window", "trailing_tax", "risk_level", ] variables = [ "exit_down", "exit_up", "macd", "macd_entry", "rsi_entry", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "atr_value", ] 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_xhour = NewBarGenerator( on_bar=self.on_bar, window=self.max_window, on_window_bar=self.on_xhour_bar, interval=Interval.MINUTE # 由小时修改到分钟级 ) self.am_hour = ArrayManager(self.boll_length + 100) 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(self.dc_length * int(self.min_window / self.open_window) + 30) 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) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 self.put_event() def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xhour.update_bar(bar) self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_5min_bar(self, bar: BarData): self.cancel_all() self.am_open.update_bar(bar) if not self.am_open.inited or not self.am_xminute.inited or not self.am_hour.inited: return # self.exit_up, self.exit_down = self.am_open.donchian( self.dc_length * int(self.min_window / self.open_window)) if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price if self.macd_entry > 0 and 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) if self.macd_entry < 0 and self.rsi_entry < 0: self.short(self.boll_down, self.trading_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) long_high = self.intra_trade_high * \ (1 - self.trailing_tax / 100) self.long_stop = max(self.exit_down, long_high) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) short_low = self.intra_trade_low * \ (1 + self.trailing_tax / 100) self.short_stop = min(self.exit_up, short_low) self.cover(short_low, abs(self.pos), True) self.put_event() def on_xminute_bar(self, bar: BarData): """ :param bar: :return: """ self.am_xminute.update_bar(bar) if not self.am_hour.inited or 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, True) 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] current_rsi_value = self.rsi_value[-1] if current_rsi_value > current_rsi_up: self.rsi_entry = 1 elif current_rsi_value < current_rsi_down: self.rsi_entry = -1 else: self.rsi_entry = 0 self.boll_up, self.boll_down = self.am_xminute.boll(self.boll_length, self.boll_dev) def on_xhour_bar(self, bar: BarData): """""" am_hour = self.am_hour am_hour.update_bar(bar) if not am_hour.inited: return macd_signal, signal, hist = self.am_hour.macd( self.fast_macd, self.slow_macd, self.signal_macd ) self.macd = signal - hist if self.macd > self.macd_trend_level: self.macd_entry = 1 elif self.macd < (-self.macd_trend_level): self.macd_entry = -1 else: self.macd_entry = 0 # 动态调整仓位 if not self.pos: self.atr_value = self.am_hour.atr(self.atr_window) if self.atr_value == 0: # 保证仓位值是有效的 return # 正向合约 atr_risk = self.am_hour.atr(self.atr_window) self.trading_size = max(int(self.risk_level / atr_risk), 1) 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 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
class RisBollStrategy(CtaTemplate): """ 目前使用中轨加速,可以考虑使用另外一根均线来加速,这样可以避免在开仓时被平。 """ author = "yunya" open_window = 15 boll_length = 80 boll_dev = 2.0 rsi_window = 12 rsi_entry = 19 atr_window = 16 long_trailing = 4.0 short_trailing = 4.0 fixed_size = 1 rsi_long = 0 rsi_short = 0 rsi_value = 0 atr_value = 0 boll_up = 0 boll_down = 0 boll_mid = 0 boll_mid_new = 0 exit_long = 0 exit_short = 0 boll_length_new = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 long_stop_trade = 0 short_stop_trade = 0 trade_price_long = 0 trade_price_short = 0 parameters = [ "open_window", "boll_length", "boll_dev", "rsi_window", "rsi_entry", "atr_window", "long_trailing", "short_trailing", "fixed_size", ] variables = [ "rsi_long", "rsi_short", "rsi_value", "atr_value", "boll_up", "boll_down", "boll_mid", "boll_mid_new", "exit_long", "exit_short", "boll_length_new", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", "long_stop_trade", "short_stop_trade", "trade_price_long", "trade_price_short", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_xmin_bar) self.am = ArrayManager(int(self.boll_length) + 100) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.rsi_long = 50 + self.rsi_entry self.rsi_short = 50 - self.rsi_entry self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算原布林带 self.boll_up, self.boll_down = self.am.boll(self.boll_length, self.boll_dev) self.boll_mid = am.sma(self.boll_length) self.rsi_value = am.rsi(self.rsi_window) # 如果没有仓位,两条布林window一样 if self.pos == 0: self.atr_value = am.atr(self.atr_window) self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.boll_length_new = self.boll_length if self.rsi_value > self.rsi_long: self.buy(self.boll_up, self.fixed_size, True) if self.rsi_value < self.rsi_short: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: # 上涨或下跌时,布林中轨均值减1 close_long = am.close[-1] > am.close[-2] > am.close[-3] > am.close[-4] if close_long: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 10) # 计算新的布林带 self.boll_mid_new = am.sma(self.boll_length_new, True) # 仓位是long 时,如果价格上穿新布林中轨 con1 = am.close[-1] < self.boll_mid_new[-1] con2 = am.close[-2] >= self.boll_mid_new[-2] if con1 and con2: self.exit_long_nex = am.close[-1] # 保存当前收盘价 if self.exit_long_nex > self.exit_long_last or self.exit_long_last == 0: self.exit_long_last = self.exit_long_nex self.boll_length_new = self.boll_length # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.boll_mid else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if self.am.close[-1] > ((self.boll_mid + self.boll_mid_new[-1]) / 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 else: self.exit_long = self.boll_mid if bar.close_price < self.trade_price_long * (1 - self.long_trailing / 100): exit_long_price = self.trade_price_long * (1 - (self.long_trailing + 1) / 100) self.exit_long = max(exit_long_price, self.exit_long) self.exit_long = max(self.exit_long, self.long_stop_trade) self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: close_short = am.close[-1] < am.close[-2] < am.close[-3] < am.close[-4] if close_short: self.boll_length_new -= 1 self.boll_length_new = max(self.boll_length_new, 10) # 计算新的布林带 self.boll_mid_new = am.sma(self.boll_length_new, True) # 仓位是short 时,如果价格上穿新布林中轨 con3 = am.close[-1] > self.boll_mid_new[-1] con4 = am.close[-2] <= self.boll_mid_new[-2] if con3 and con4: self.exit_short_nex = am.close[-1] if self.exit_short_nex < self.exit_short_last or self.exit_short_last == 0: self.exit_short_last = self.exit_short_nex self.boll_length_new = self.boll_length self.exit_short = self.boll_mid else: if self.am.close[-1] < (self.boll_mid + self.boll_mid_new[-1] / 2): self.exit_short = bar.close_price elif bar.close_price > self.boll_mid: self.exit_short = bar.close_price else: self.exit_short = self.boll_mid else: self.exit_short = self.boll_mid # 如果 有3%以上的收益,止损价为买入成交价 if bar.close_price > self.trade_price_short * (1 + self.short_trailing / 100): exit_short_price = self.trade_price_short * (1 + (self.short_trailing + 1) / 100) self.exit_short = min(exit_short_price, self.exit_short) self.exit_short = min(self.exit_short, self.short_stop_trade) self.cover(self.exit_short, abs(self.pos), True) self.put_event() self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ if trade.direction == Direction.LONG: self.trade_price_long = trade.price # 成交最高价 self.long_stop_trade = self.trade_price_long - 2 * self.atr_value else: self.trade_price_short = trade.price self.short_stop_trade = self.trade_price_short + 2 * self.atr_value self.sync_data() self.put_event()
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 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 RSIStrategy(CtaTemplate): """""" author = "用Python的交易员" no_trade_time_begin1 = time(hour=9, minute=0) no_trade_time_end1 = time(hour=9, minute=30) no_trade_time_begin2 = time(hour=23, minute=0) no_trade_time_end2 = time(hour=23, minute=30) load_bar_day = 20 boll_window = 16 boll_dev = 2.6 # cci_window = 10 atr_window = 30 # atr_ma_window = 10 rsi_f_window = 5 rsi_l_window = 10 grow_window = 5 reduce_window = 5 # rsi_entry = 16 # ma_window = 5 sl_multiplier = 7.6 fixed_size = 1 db_record = 0 bar_size = 100 boll_up = 0 boll_down = 0 # cci_value = 0 atr_value = 0 # atr_ma = 0 rsi_f_value = 0 rsi_l_value = 0 rsi_max_value = 0 rsi_min_value = 0 rsi_f_ma = 0 rsi_l_ma = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 vt_1m_orderids = [] vt_15m_orderids = [] parameters = [ "boll_window", "boll_dev", "atr_window", "rsi_f_window", "rsi_l_window", "grow_window", "reduce_window", "sl_multiplier", "fixed_size", "bar_size", "db_record" ] variables = [ "boll_up", "boll_down", "atr_value", "rsi_f_value", "rsi_l_value", "rsi_f_ma", "rsi_l_ma", "rsi_max_value", "rsi_min_value", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop" ] # parameters = ["boll_window", "boll_dev", "cci_window","rsi_window","rsi_entry","ma_window", # "atr_window","atr_ma_window","sl_multiplier", "fixed_size"] # variables = ["boll_up", "boll_down", "cci_value", "atr_value","atr_ma","rsi_value", # "intra_trade_high", "intra_trade_low", "long_stop", "short_stop"] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) #todo,多时间周期,分长短期,判断不同的指标 self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar) #self.am_1m = ArrayManager() self.am_15m = ArrayManager(self.bar_size) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(self.load_bar_day) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ # self.cancel_order_list(self.vt_1m_orderids) # self.am_1m.update_bar(bar) # if not self.am_1m.inited: # return # # #todo 1分钟的策略 # # self.boll_up, self.boll_down = self.am_1m.boll(self.boll_window, self.boll_dev) # self.atr_value = self.am_1m.atr(self.atr_window) # rsi_f_array = self.am_1m.rsi(self.rsi_f_window, array=True) # rsi_l_array = self.am_1m.rsi(self.rsi_l_window, array=True) # self.rsi_f_value = rsi_f_array[-1] # self.rsi_l_value = rsi_l_array[-1] # # if self.pos == 0: # self.intra_trade_high = bar.high_price # self.intra_trade_low = bar.low_price # # # todo,波动不够大,应该过滤 # if self.rsi_f_value > self.rsi_l_value and if_keep_grow(self.grow_window, rsi_f_array): # vt_orderids = self.buy(self.boll_up, self.fixed_size, True) # self.vt_1m_orderids.extend(vt_orderids) # elif self.rsi_f_value < self.rsi_l_value and if_keep_reduce(self.reduce_window, rsi_f_array): # vt_orderids = self.short(self.boll_down, self.fixed_size, True) # self.vt_1m_orderids.extend(vt_orderids) # # todo,持续范围内小波动,震荡策略 # # # # elif self.pos > 0: # self.intra_trade_high = max(self.intra_trade_high, bar.high_price) # self.intra_trade_low = bar.low_price # if if_keep_reduce(self.reduce_window, rsi_f_array): # self.rsi_f_value < self.rsi_l_value and # vt_orderids = self.sell(bar.close_price - 5, abs(self.pos)) # else: # self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier # vt_orderids = self.sell(self.long_stop, abs(self.pos), True) # self.vt_1m_orderids.extend(vt_orderids) # elif self.pos < 0: # self.intra_trade_high = bar.high_price # self.intra_trade_low = min(self.intra_trade_low, bar.low_price) # if if_keep_grow(self.grow_window, rsi_f_array): # self.rsi_f_value > self.rsi_l_value and # vt_orderids = self.cover(bar.close_price + 5, abs(self.pos)) # else: # self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier # vt_orderids = self.cover(self.short_stop, abs(self.pos), True) # self.vt_1m_orderids.extend(vt_orderids) # if self.db_record: # database_manager.save_bar_calc(bar, self.get_variables()) # # self.put_event() self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_order_list(self.vt_15m_orderids) self.am_15m.update_bar(bar) if not self.am_15m.inited: return self.boll_up, self.boll_down = self.am_15m.boll( self.boll_window, self.boll_dev) #self.cci_value = am.cci(self.cci_window) self.atr_value = self.am_15m.atr(self.atr_window) # atr_array = am.atr(self.atr_window, array=True) # self.atr_value = atr_array[-1] #self.atr_ma = atr_array[-self.atr_ma_window:].mean() rsi_f_array = self.am_15m.rsi(self.rsi_f_window, array=True) rsi_l_array = self.am_15m.rsi(self.rsi_l_window, array=True) # self.rsi_max_value = rsi_f_array[-self.rsi_f_window:].max() # self.rsi_min_value = rsi_f_array[-self.rsi_f_window:].min() # self.rsi_f_ma = rsi_f_array[-self.rsi_f_window:].mean() # self.rsi_l_ma = rsi_f_array[-self.rsi_f_window:].mean() self.rsi_f_value = rsi_f_array[-1] self.rsi_l_value = rsi_l_array[-1] #self.ma_value = am.sma(self.ma_window) # if (bar.datetime.time() >= self.no_trade_time_begin1 and bar.datetime.time() <= self.no_trade_time_end1) \ # or (bar.datetime.time() >= self.no_trade_time_begin2 and bar.datetime.time() <= self.no_trade_time_end2): # return if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price #todo,波动不够大,应该过滤 #if self.rsi_f_value > 50 and self.rsi_f_value > self.rsi_l_value and if_keep_grow(self.grow_window, rsi_f_array) and self.rsi_f_value < 85: #self.rsi_f_value>=self.rsi_max_value: if self.rsi_f_value > self.rsi_l_value: #and if_keep_grow(self.grow_window, rsi_f_array): #self.buy(bar.close_price+5, self.fixed_size) vt_orderids = self.buy(self.boll_up, self.fixed_size, True) self.vt_15m_orderids.extend(vt_orderids) #elif self.rsi_f_value < 50 and self.rsi_f_value < self.rsi_l_value and if_keep_reduce(self.reduce_window, rsi_f_array) and self.rsi_f_value >15: #self.rsi_f_value <=self.rsi_min_value: elif self.rsi_f_value < self.rsi_l_value: # and if_keep_reduce(self.reduce_window, rsi_f_array): #self.short(bar.close_price-5, self.fixed_size) vt_orderids = self.short(self.boll_down, self.fixed_size, True) self.vt_15m_orderids.extend(vt_orderids) #todo,持续范围内小波动,震荡策略 elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price if if_keep_reduce( self.reduce_window, rsi_f_array): #self.rsi_f_value < self.rsi_l_value and vt_orderids = self.sell(bar.close_price - 5, abs(self.pos)) else: self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier vt_orderids = self.sell(self.long_stop, abs(self.pos), True) self.vt_15m_orderids.extend(vt_orderids) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) if if_keep_grow( self.grow_window, rsi_f_array): #self.rsi_f_value > self.rsi_l_value and vt_orderids = self.cover(bar.close_price + 5, abs(self.pos)) else: self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier vt_orderids = self.cover(self.short_stop, abs(self.pos), True) self.vt_15m_orderids.extend(vt_orderids) if self.db_record: database_manager.save_bar_calc(bar, self.get_variables()) self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ #数据库记录成交记录,bar记录,variables值 if self.db_record: database_manager.save_trade_data(trade, self.get_variables()) self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class FbbStrategy(CtaTemplate): """""" author = "feng.shao" boll_window = 20 # boll_dev = 2.0 # boll_bw_limit = 0.01 fixed_size: float = 0.2 # 单笔buy 暂时固定为总资产的 千分之 1~4 (风险随之增加) limit_amt = 10.0 # 最小交易资金10 USDT -binance #BB boll_up = 0 boll_down = 0 boll_mid = 0 boll_pb = 0 boll_bw = 0 #kdj k = 0 d = 0 j = 0 last_boll_pb = 0 parameters = [ "boll_window", "boll_dev", # "boll_dev_2", # "boll_pb_sal", "boll_bw_limit", "fixed_size" ] variables = [ # "boll_up", # "boll_down", # "boll_mid", "boll_pb", # "boll_bw", # "boll_up_2", # "boll_down_2", # "boll_mid_2", # "boll_pb_2", # "boll_bw_2", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 15, self.on_mins_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(2) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_mins_bar(self, bar: BarData): """ Callback of new bar data update. """ self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # start self.get_boll(bar) self.get_kdj() print( str(self.k) + " - " + str(self.d) + " - " + str(self.j) + " - " + bar.datetime.strftime("%Y-%m-%d %H:%M:%S")) # 低于 boll_down 并且width 不小于limit 买入 if self.boll_pb <= 0 and self.boll_bw > self.boll_bw_limit: self.buy(bar.close_price, self.check_minimum_size(bar.close_price, self.fixed_size), False) if self.pos > 0: # 上穿 up 卖出信号 if self.last_boll_pb < 1 <= self.boll_pb and self.boll_bw < self.boll_bw_limit: self.sell(bar.close_price, self.pos, False) # 未达up 而下穿 mid 卖出 if self.last_boll_pb > 0.5 >= self.boll_pb and self.boll_bw < self.boll_bw_limit: self.sell(bar.close_price, self.pos, False) # down 下方 ,width 很小 卖出 if self.boll_pb <= 0 and self.boll_bw <= self.boll_bw_limit: self.sell(bar.close_price, self.pos, False) self.last_boll_pb = self.boll_pb # self.short(bar.close_price, self.fixed_size, False) # self.cover(bar.close_price, self.pos, False) self.put_event() def check_minimum_size(self, price: float, order_size) -> float: min_size = self.size_by_limit_amt(self.limit_amt, price) return max(order_size, min_size) def kdj_signal(self): if self.d <= self.k < 20: return True def get_boll(self, bar: BarData): self.boll_up, self.boll_mid, self.boll_down = self.am.boll( self.boll_window, self.boll_dev) self.boll_pb = self.percentbeta(bar.close_price, self.boll_up, self.boll_down) self.boll_bw = self.bandwidth(self.boll_up, self.boll_mid, self.boll_down) def get_kdj(self): self.k, self.d, self.j = self.am.kdj() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass def percentbeta(self, close: float, up: float, low: float) -> float: """ %b of boll """ pb = (close - low) / (up - low) return pb def bandwidth(self, up: float, mid: float, low: float) -> float: """ bandwidth of boll """ bw = (up - low) / mid return bw def size_by_limit_amt(self, limit_amt: float, price: float) -> float: return math.ceil(limit_amt / price * 1000000) / 1000000
class CincoRB2005Strategy(CtaTemplate): """""" author = "tonywang_efun" boll_window = 44 boll_dev = 2.0 rsi_window = 8 rsi_long = 58 rsi_short = 20 trailing_long = 2.6 trailing_short = 2.6 fixed_size = 2 boll_up = 0 boll_down = 0 rsi_value = 0 trading_size = 0 intra_trade_high = 0 intra_trade_low = 0 long_stop = 0 short_stop = 0 atr_value = 0 parameters = [ "boll_window", "boll_dev", "rsi_window", "rsi_long", "rsi_short", "trailing_long", "trailing_short", "fixed_size" ] variables = [ "boll_up", "boll_down", "rsi_value", "trading_size", "intra_trade_high", "intra_trade_low", "long_stop", "short_stop", "atr_value" ] def __init__( self, cta_engine, strategy_name: str, vt_symbol: str, setting: dict, ): """""" super(CincoRB2005Strategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, 13, self.on_15min_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_15min_bar(self, bar: BarData): """""" self.cancel_all() self.am.update_bar(bar) if not self.am.inited: return self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) self.rsi_value = self.am.rsi(self.rsi_window) boll_width = self.boll_up - self.boll_down if not self.pos: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 # print(self.boll_up, self.boll_down, self.intra_trade_high, self.intra_trade_low) if self.rsi_value >= self.rsi_long: self.buy(self.boll_up, self.fixed_size, stop=True) if self.rsi_value <= self.rsi_short: self.short(self.boll_down, self.fixed_size, stop=True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = self.intra_trade_high - self.trailing_long * boll_width self.sell(self.long_stop, abs(self.pos), stop=True) else: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = self.intra_trade_low + self.trailing_short * boll_width self.cover(self.short_stop, abs(self.pos), stop=True) self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass
class MacdBollDcStrategy(CtaTemplate): """""" author = "云崖" open_window = 2 xminute_window = 15 xhour_window = 1 fast_length = 14 show_length = 28 boll_length = 20 boll_dev = 2.0 dc_length = 30 trailing_tax = 2.0 fixed_size = 1 macd_inited = 0 boll_up = 0 boll_down = 0 dc_up = 0 dc_down = 0 exit_long = 0 exit_short = 0 long_stop = 0 short_stop = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "open_window", "xminute_window", "xhour_window", "fast_length", "show_length", "boll_length", "boll_dev", "dc_length", "trailing_tax", "fixed_size", ] variables = [ "macd_inited", "boll_up", "boll_down", "dc_up", "dc_down", "exit_long", "exit_short", "long_stop", "short_stop", ] def __init__(self, cta_engine, strategy_nam_xminutee, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_nam_xminutee, vt_symbol, setting) self.bg_open = NewBarGenerator(self.on_bar, self.open_window, self.on_open_bar) self.am_open = ArrayManager() self.bg_xminute = NewBarGenerator(self.on_bar, self.xminute_window, self.on_xminute_bar) self.am_xminute = ArrayManager(150) self.bg_xhour = NewBarGenerator(self.on_bar, self.xhour_window, self.on_xhour_bar, interval=Interval.HOUR) self.am_xhour = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg_xminute.update_tick(tick) self.ask = tick.ask_price_1 # 卖一价 self.bid = tick.bid_price_1 # 买一价 def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg_xhour.update_bar(bar) self.bg_xminute.update_bar(bar) self.bg_open.update_bar(bar) def on_open_bar(self, bar: BarData): """""" self.cancel_all() self.am_open.update_bar(bar) if not self.am_xminute.inited or not self.am_open.inited: return if self.pos == 0: self.intra_trade_high = bar.high_price self.intra_trade_low = bar.low_price self.long_stop = 0 self.short_stop = 0 if self.macd_inited > 0: self.buy(self.boll_up, self.fixed_size, True) elif self.macd_inited < 0: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.intra_trade_low = bar.low_price long_high = self.intra_trade_high * (1 - self.trailing_tax / 100) self.long_stop = max(self.exit_long, long_high) self.sell(self.long_stop, abs(self.pos), True) elif self.pos < 0: self.intra_trade_high = bar.high_price self.intra_trade_low = min(self.intra_trade_low, bar.low_price) stop_low = self.intra_trade_low * (1 + self.trailing_tax / 100) self.short_stop = min(self.exit_short, stop_low) self.cover(self.short_stop, abs(self.pos), True) self.put_event() def on_xminute_bar(self, bar: BarData): """""" self.am_xminute.update_bar(bar) if not self.am_xminute.inited: return self.boll_up, self.boll_down = self.am_xminute.boll( self.boll_length, self.boll_dev) self.exit_short, self.exit_long = self.am_xminute.donchian( self.dc_length) def on_xhour_bar(self, bar: BarData): """ :param bar: :type bar: :return: :rtype: """ self.am_xhour.update_bar(bar) if self.am_xhour.inited: return fast_ema_value = self.am_xhour.ema(self.fast_length, True) show_ema_value = self.am_xhour.ema(self.show_length, True) diff = fast_ema_value - show_ema_value macd_diff = (fast_ema_value - show_ema_value) / show_ema_value * 100 if diff[-2] > macd_diff[-2]: self.macd_inited = 1 elif diff[-2] < macd_diff[-2]: self.macd_inited = -1 def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ self.put_event()
class AberrationBias_V1_Strategy(CtaTemplate): """ 目前使用中轨加速,可以考虑使用另外一根均线来加速,这样可以避免在开仓时被平。 """ author = "yunya" open_window = 15 boll_length = 560 boll_dev = 1.6 bias = 0.16 cci_length = 6 cci_exit = 10.0 fixed_size = 1 boll_up = 0 boll_down = 0 boll_mid = 0 boll_mid_new = 0 boll_mid_array = 0 bias_value_array = 0 bias_value = 0 cci_value = 0 exit_long = 0 exit_short = 0 boll_length_new = 0 exit_long_nex = 0 exit_long_last = 0 exit_short_nex = 0 exit_short_last = 0 # 画图专用 time_list = [] open_list = [] high_list = [] low_list = [] close_list = [] volume_list = [] up_list = [] down_list = [] mid_list = [] mid_new_list = [] exit_long_list = [] exit_short_list = [] bias_value_list = [] bias_list = [] singnal_plot = [] singnal_list = None singnal = None plot_echarts = {} parameters = [ "open_window", "boll_length", "boll_dev", "bias", "cci_length", "cci_exit", "fixed_size", ] variables = [ "boll_up", "boll_down", "boll_mid", "bias_value", "cci_value", "exit_long", "exit_short", "boll_length_new", "exit_long_nex", "exit_long_last", "exit_short_nex", "exit_short_last", ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super().__init__(cta_engine, strategy_name, vt_symbol, setting) self.bg = BarGenerator(self.on_bar, self.open_window, self.on_xmin_bar) self.am = ArrayManager(int(self.boll_length) * 2 + 10) def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_xmin_bar(self, bar: BarData): """""" self.cancel_all() am = self.am am.update_bar(bar) if not am.inited: return # 计算原布林带 self.boll_up, self.boll_down = self.am.boll(self.boll_length, self.boll_dev) self.boll_mid_array = am.sma(self.boll_length, True) self.boll_mid = self.boll_mid_array[-1] self.bias_value_array = (self.am.close - self.boll_mid_array) / self.boll_mid_array self.bias_value = self.bias_value_array[-1] self.cci_value = am.cci(self.cci_length) # 上涨或下跌时,布林中轨均值减1 close_long = am.close[-1] > am.close[-2] close_short = am.close[-1] < am.close[-2] if close_long or close_short: self.boll_length_new -= 2 self.boll_length_new = max(self.boll_length_new, 5) # 计算新的布林带 self.boll_mid_new = am.sma(int(self.boll_length_new), True) # 如果没有仓位,两条布林window一样 if self.pos == 0: self.exit_long_nex = 0 self.exit_long_last = 0 self.exit_short_nex = 0 self.exit_short_last = 0 self.boll_length_new = self.boll_length # 远离均线不开仓位 if self.bias > abs(self.bias_value): if self.cci_value > self.cci_exit: self.buy(self.boll_up, self.fixed_size, True) if self.cci_value < -self.cci_exit: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: # 仓位是long 时,如果价格上穿新布林中轨 con1 = am.close[-1] < self.boll_mid_new[-1] con2 = am.close[-2] >= self.boll_mid_new[-2] if con1 and con2: self.exit_long_nex = am.close[-1] # 保存当前收盘价 if self.exit_long_nex > self.exit_long_last or self.exit_long_last == 0: self.exit_long_last = self.exit_long_nex self.boll_length_new = self.boll_length - 10 # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损 self.exit_long = self.boll_mid # print(f"我是多单,exitlast:{self.exit_short_last},重置布林中轨参数,止损挂{self.exit_long}:") else: # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单 if self.am.close[-1] > ( (self.boll_mid + self.boll_mid_new[-1]) / 2): self.exit_long = bar.close_price # print(f"我是多单,收盘价在两个中轨均值上方,以收盘价挂止损单:{self.exit_long}") elif bar.close_price < self.boll_mid: self.exit_long = bar.close_price else: self.exit_long = self.boll_mid # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},") else: self.exit_long = (self.boll_mid + self.boll_mid_new[-2]) / 2 # print(f"我是多单,收盘价在新中轨上方,以原中轨挂止损单:{self.exit_long}") if self.bias_value > self.bias: self.exit_long = max(bar.close_price, self.exit_long) exit_long = (self.boll_mid + self.boll_mid_new[-1]) / 2 if bar.close_price > exit_long: self.exit_long = max(self.exit_long, exit_long) self.sell(self.exit_long, abs(self.pos), True) elif self.pos < 0: # 仓位是short 时,如果价格上穿新布林中轨 con3 = am.close[-1] > self.boll_mid_new[-1] con4 = am.close[-2] <= self.boll_mid_new[-2] if con3 and con4: self.exit_short_nex = am.close[-1] if self.exit_short_nex < self.exit_short_last or self.exit_short_last == 0: self.exit_short_last = self.exit_short_nex self.boll_length_new = self.boll_length - 10 self.exit_short = self.boll_mid else: if self.am.close[-1] < (self.boll_mid + self.boll_mid_new[-1] / 2): self.exit_short = bar.close_price elif bar.close_price > self.boll_mid: self.exit_short = bar.close_price else: self.exit_short = self.boll_mid else: self.exit_short = (self.boll_mid + self.boll_mid_new[-1]) / 2 if self.bias_value < -self.bias: self.exit_short = min(self.exit_short, bar.close_price) exit_short = (self.boll_mid + self.boll_mid_new[-1]) / 2 if bar.close_price < exit_short: self.exit_short = min(self.exit_short, exit_short) self.cover(self.exit_short, 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) # self.down_list.append(self.boll_down) # self.mid_list.append(self.boll_mid) # self.mid_new_list.append(self.boll_mid_new[-1]) # self.exit_long_list.append(self.exit_long) # self.exit_short_list.append(self.exit_short) # 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, # "boll_mid_new": self.mid_new_list, # "bias": self.bias_value_list, # "bias_value": self.bias_list, # "exit_long": self.exit_long_list, # "exit_short": self.exit_short_list, # "signal": self.singnal_plot # # } # self.singnal_list = self.singnal self.put_event() self.sync_data() def on_order(self, order: OrderData): """ Callback of new order data update. """ self.put_event() pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ # 画图专用 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
class CuatroStrategy(CtaTemplate): """""" author = "KeKe" rsi_signal = 19 rsi_window = 14 fast_window = 4 slow_window = 26 boll_window = 21 boll_dev = 1.9 trailing_short = 0.3 trailing_long = 0.5 fixed_size = 1 boll_up = 0 boll_down = 0 rsi_value = 0 rsi_long = 0 rsi_short = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 long_stop = 0 short_stop = 0 intra_trade_high = 0 intra_trade_low = 0 parameters = [ "rsi_signal", "rsi_window", "fast_window", "slow_window", "boll_window", "boll_dev", "trailing_long", "trailing_short", "fixed_size" ] variables = [ "boll_up", "boll_down", "rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend", "long_stop", "short_stop" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(CuatroStrategy, 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) self.boll_up, self.boll_down = self.am5.boll(self.boll_window, self.boll_dev) boll_width = self.boll_up - self.boll_down if self.pos == 0: self.intra_trade_low = bar.low_price self.intra_trade_high = bar.high_price if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy(self.boll_up, self.fixed_size, True) elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(self.boll_down, self.fixed_size, True) elif self.pos > 0: self.intra_trade_high = max(self.intra_trade_high, bar.high_price) self.long_stop = (self.intra_trade_high - self.trailing_long * boll_width) self.sell(self.long_stop, abs(self.pos), True, True) elif self.pos < 0: self.intra_trade_low = min(self.intra_trade_low, bar.low_price) self.short_stop = (self.intra_trade_low + self.trailing_short * boll_width) self.cover(self.short_stop, abs(self.pos), True, True) 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