示例#1
0
    def add_position(self,
                     am: ArrayManager,
                     bar: BarData,
                     calc_data,
                     setting={}):

        if self.safe_price is None:
            return

        if not (self.trade_mgr.get_status() == PositionStatus.Short and bar.close_price < self.safe_price or \
                self.trade_mgr.get_status() == PositionStatus.Long and bar.close_price > self.safe_price):
            return

        am = self.am
        rg = (bar.close_price / self.trade_price) - 1

        close_price = None
        if rg > 0.01 and self.trade_mgr.get_status() == PositionStatus.Long:
            close_price = am.sma(120)
            if not self.add_pos:
                self.add_pos = True
                # scale = 1 - 0.002
                # self.closeout_price = round(bar.close_price * scale, 2)
                return self.trade_mgr.buy(bar.close_price, 0.1, {})
        elif rg < -0.01 and self.trade_mgr.get_status(
        ) == PositionStatus.Short:
            close_price = am.sma(120)
            if not self.add_pos:
                self.add_pos = True
                # scale = 1 + 0.002
                # self.closeout_price = round(bar.close_price * scale, 2)
                return self.trade_mgr.short(bar.close_price, 0.1, {})
示例#2
0
    def ma_close(self, am: ArrayManager, bar: BarData, calc_data):

        if self.safe_price is None:
            return

        rg = (bar.close_price / self.trade_price) - 1

        close_price = None
        if rg > 0.01 and self.trade_mgr.get_status() == PositionStatus.Long:
            close_price = am.sma(120)
        elif rg < -0.01 and self.trade_mgr.get_status(
        ) == PositionStatus.Short:
            close_price = am.sma(120)

        for lvl in self.ma_level[-1:]:
            # if len(self.order_data) < lvl:
            close_price = am.sma(lvl)
            break

        if close_price is None:
            lvl = self.ma_level[-1]
            close_price = am.sma(lvl)

        if self.trade_mgr.get_status() == PositionStatus.Short:
            if bar.close_price > close_price:
                calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price)
                return self.trade_mgr.cover(bar.close_price)
                # return self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET,
                #        extra= { "reason":"平仓:到达MA均线价{}".format(close_price)})

        elif self.trade_mgr.get_status() == PositionStatus.Long:
            if bar.close_price < close_price:
                calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price)
                return self.trade_mgr.sell(bar.close_price)
    def ma_info_update(self, am:ArrayManager):
        
        ma_info = {}
        ma_data = []
        for i in self.ma_level:
            ma = am.sma(i)
            ma_info[i] = round(ma,2)
            ma_data.append(ma)
        
        data = []
        diff = ma_data[-1]
        for v in ma_data:
            data.append(round(v / diff, 6))

        ma_info["ma5"] = round(np.var(data)*1000000, 8)

        data = []
        diff = ma_data[-3]
        for v in ma_data[:-2]:
            data.append(round(v / diff, 6))

        ma_info["ma3"] = round(np.var(data)*1000000, 8)

        if len(self.ma_info) < 500:
            self.ma_info.append(ma_info)
        else:
            self.ma_info[:-1] = self.ma_info[1:]
            self.ma_info[-1] = ma_info
示例#4
0
 def compute_index_zz500_specifications(self, df):
     # 注意:所有的数据库数据和列表数据都按照日期的正序排序(从小到大)
     # 计算zz500指数的技术指标并入库
     """
     @ 入参:指数k线信息
     """
     am = ArrayManager(size=600)   
     for ix, row in df.iterrows():
         d = row.to_dict()
         LOG.info(d['trade_date'])   
         d['ts_code'] = d['ts_code'].replace('.', '_')
         bar = BarData(
                 gateway_name='ctp', symbol=d['ts_code'],
                 exchange=Exchange.SSE,
                 datetime=string_to_datetime(d['trade_date']))
         bar.symbol = d['ts_code']
         bar.open_price = d['open']
         bar.high_price = d['high']
         bar.low_price = d['low']
         bar.close_price = d['close']
         am.update_bar(bar)      
         rsi_20 = am.rsi(20)
         d['rsi_20'] = rsi_20
         try:
             d['ma_5'] = am.sma(5)
         except:
             traceback.print_exc()                    
             LOG.error('************************')
             LOG.error(d['ts_code'])
             LOG.error(d['trade_date'])
             LOG.error(bar)
         d['ma_10'] = am.sma(10)
         d['ma_20'] = am.sma(20)
         d['ma_30'] = am.sma(30)
         d['ma_60'] = am.sma(60)
         d['ma_120'] = am.sma(120)
         d['ma_250'] = am.sma(250)
         d['ma_500'] = am.sma(500)
         flt = {'trade_date': d['trade_date']}
         cl_index_zz500 = self.db[CL_INDEX_ZZ500]
         # cl_index_zz500.replace_one(flt, d, upsert=False)
         cl_index_zz500.update_one(flt, {'$setOnInsert': d}, upsert=True)   # 插入数据时,flt不存在则插入d,存在则不执行
    def add_position(self, am:ArrayManager, bar:BarData, calc_data, setting={}):

        if self.safe_price is None:
            return

        if not (self.volumn < 0 and bar.close_price < self.safe_price or \
                self.volumn > 0 and bar.close_price > self.safe_price):
            return

        am = self.am
        rg = (bar.close_price / self.trade_price) - 1

        close_price = None
        if rg > 0.01 and self.volumn > 0:
            close_price = am.sma(120)
            if not self.add_pos:
                self.add_pos = True
                return self.strategy.buy(bar.close_price, 50, type=OrderType.MARKET) 
        elif rg < -0.01 and self.volumn < 0:
            close_price = am.sma(120)
            if not self.add_pos:
                self.add_pos = True
                return self.strategy.short(bar.close_price, 50, type=OrderType.MARKET) 
    def ma120_close(self, am:ArrayManager, bar:BarData, calc_data):
        
        if self.safe_price is None:
            return

        rg = (bar.close_price / self.buy_price) - 1

        close_price = None
        if rg > 0.01 and self.volumn > 0:
            close_price = am.sma(120)
        elif rg < -0.01 and self.volumn < 0:
            close_price = am.sma(120)
            

        for lvl in self.ma_lvl[-1:]:
            # if len(self.order_data) < lvl:
            close_price = am.sma(lvl)
            break
        

        if close_price is None:
            lvl = self.ma_level[-1]
            close_price = am.sma(lvl)

        
        
        if self.volumn < 0:
            if bar.close_price > close_price:
                calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price)
                return self.strategy.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET,
                       extra= { "reason":"平仓:到达MA均线价{}".format(close_price)})
                 
        elif self.volumn > 0:
            if bar.close_price < close_price:
                calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price)
                return self.strategy.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET,
                       extra={"reason": "平仓:到达MA均线价{}".format(close_price)})
示例#7
0
class MaSignal(CtaSignal):
    """"""

    def __init__(self, fast_window: int, slow_window: int):
        """"""
        super(MaSignal, self).__init__()

        self.fast_window = fast_window
        self.slow_window = slow_window

        self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)
        if not self.am.inited:
            self.set_signal_pos(0)

        fast_ma = self.am.sma(self.fast_window)
        slow_ma = self.am.sma(self.slow_window)

        if fast_ma > slow_ma:
            self.set_signal_pos(1)
        elif fast_ma < slow_ma:
            self.set_signal_pos(-1)
        else:
            self.set_signal_pos(0)
示例#8
0
class MyBollingDayStrategy(CtaTemplate):
    """基于布林通道的交易策略"""
    className = 'MyBollingDayStrategy'
    author = 'yuanhui'

    # 策略参数
    #bollWindow = 26         # 通道窗口数
    entryDev = 2          # 开仓偏差    
    bollWindow5min = 26         # 通道窗口数
    entryDev5min = 2          # 开仓偏差
    bollWindow15min = 26         # 通道窗口数
    entryDev15min = 2          # 开仓偏差    
    bollWindow30min = 52         # 通道窗口数
    entryDev30min = 2          # 开仓偏差
    bollWindowDay = 26         # 通道窗口数
    entryDevDay = 2          # 开仓偏差
    
    #exitDev = 1.2           # 平仓偏差
    #trailingPrcnt = 0.4     # 移动止损百分比
    #maWindow = 10           # 过滤用均线窗口
    initDays = 33           # 初始化数据所用的天数
    fixedSize = 1           # 每次交易的数量
    priceTick = 0.2         # 价格最小变动 
    
    DayTrendStatus='panzhen'  #DuoTou, KongTou,Panzheng
    FifteenMinTrendStatus='panzhen'
    FiveMinTrendStatus='panzhen'
    ThirtyMinTrendStatus='panzhen'
    

    # 5Min策略变量    
    bollMid = 0                         # 布林带中轨
    BeforebollMid=0                     #上一根K线的布林线中轨
    #bollStd = 0                         # 布林带宽度
    bollUp = 0                          # 开仓上轨
    Beforebollup=0                      #上一根K线的布林线上轨
    bollDown = 0                        # 平仓下轨    
    beforebolldown=0                    #上一根K线的布林线下轨
    
    # 15Min策略变量    
    bollMid15 = 0                         # 布林带中轨
    BeforebollMid15=0                     #上一根K线的布林线中轨
    #bollStd15 = 0                         # 布林带宽度
    bollUp15 = 0                          # 开仓上轨
    Beforebollup15=0                      #上一根K线的布林线上轨
    bollDown15 = 0                        # 平仓下轨    
    beforebolldown15=0                    #上一根K线的布林线下轨    
 
    # 30Min策略变量    
    bollMid30 = 0                         # 布林带中轨
    BeforebollMid30=0                     #上一根K线的布林线中轨
    #bollStd30 = 0                         # 布林带宽度
    bollUp30 = 0                          # 开仓上轨
    Beforebollup30=0                      #上一根K线的布林线上轨
    bollDown30 = 0                        # 平仓下轨    
    beforebolldown30=0                    #上一根K线的布林线下轨       
    
    # 日线策略变量    
    bollMidDay = 0                         # 布林带中轨
    BeforebollMidDay=0                     #上一根K线的布林线中轨
    #bollStd30 = 0                         # 布林带宽度
    bollUpDay = 0                          # 开仓上轨
    BeforebollupDay=0                      #上一根K线的布林线上轨
    bollDownDay= 0                        # 平仓下轨    
    beforebolldownDay=0                    #上一根K线的布林线下轨         
  
    #maFilter = 0                        # 均线过滤
    #maFilter1 = 0                       # 上一期均线                   
    
    intraTradeHigh = 0                  # 持仓期内的最高点  
    longEntry = 0                       #多头开仓位置
    longExit = 0                        #多头平仓位置 
    shortEntry=0                        #空头开仓位置
    shortExit=0                         #空头平仓位置
    #上一个交易单子保本否
    lastTrade_baoben=False
    
    deal=0                              # 多头平仓为正,空头平仓为  
    dealopen=0                          # 多头开仓正,空头开仓负 
    
    
    orderList = []                      # 保存委托代码的列表
    tradedata=[] 
    posdata=[]         #仓位信息,每次开仓成功后把trade信息加入List,平仓后删除
    tradedata_boll=[] #所有的需要在布林线止损的交易单
    tradedata_baoben=[] #所有的已经过了保本线的交易单
    tradedata_day=[] #日线级别交易单
    
    zhishunpercent=0.005   #每笔止损百分比

    # 参数列表,保存了参数的名称
    parameters = [
                 'bollWindowDay',
                 'entryDevDay',
                 'fixedSize',
                 'DayTrendStatus'
    ]    

    # 变量列表,保存了变量的名称
    variables = ['inited',
               'trading',
               'pos',
               'bollUp',
               'bollDown',
               'bollUp15',
               'bollDown15',
               'bollUp30',
               'bollDown30',               
               'FifteenMinTrendStatus',
               'FiveMinTrendStatus',
               'ThirtyMinTrendStatus'
               ]
    
    # 同步列表
    syncList = ['pos',
                'intraTradeHigh']

    #----------------------------------------------------------------------

        
    def __init__(self, ctaEngine, strategy_name, vt_symbol, setting):
        """Constructor"""
        #super(MyBollingerBotStrategy, self).__init__(ctaEngine, setting)
        super().__init__(ctaEngine, strategy_name, vt_symbol, setting)
        
        self.bm5 = BarGenerator(self.on_bar, 5, self.on_5Min_bar)
        self.am5 = ArrayManager(80)
        
        self.bm15 = BarGenerator(self.on_bar, 15, self.on_15Min_bar)
        self.am15 = ArrayManager(80)        
        
        self.bm30 = BarGenerator(self.on_bar, 30, self.on_30Min_bar)
        self.am30 = ArrayManager(80)                
 
        #self.bmDay = BarGenerator(self.on_bar, 6, self.onDayBar,Interval.HOUR)
        self.bmDay = BarGenerator(self.on_bar, 1, self.onDayBar,Interval.DAILY)
        self.amDay = ArrayManager(30)       
        
        head=["datetime","BollStatus","open","close","high","low","pos","pDown","pMiddle","pUp","dealOpen"]
        current_path =os.getcwd()# os.path.abspath(__file__)
        write_csv_file(current_path+"\\datasig5.csv",head,None,"w")
        write_csv_file(current_path+"\\datasig15.csv",head,None,"w")
        write_csv_file(current_path+"\\datasig30.csv",head,None,"w")
        write_csv_file(current_path+"\\datasigDay.csv",head,None,"w")
        
        head=["datetime","orderid","tradeid","direction","offset","price","volume"]
        write_csv_file(current_path+"\\datasigTrade.csv",head,None,"w")
        head=["datetime","orderid","tradeid","direction","offset","price","volume","baoben"]
        write_csv_file(current_path+"\\datasigPos.csv",head,None,"w")        
        
        print("self.cta_engine.capital %d",self.cta_engine.capital)
  
    #----------------------------------------------------------------------
    def caculate_pos(self,zhishun:float):
        pos=0
        pos=int(self.cta_engine.capital*self.zhishunpercent//zhishun)
        return pos
    
    def on_init(self):
        """初始化策略(必须由用户继承实现)"""
        self.write_log(u'%s策略初始化' %self.className)
        
        # 载入历史数据,并采用回放计算的方式初始化策略数值
        initData = self.load_bar(self.initDays)
        #for bar in initData:
        #   self.onBar(bar)

        #self.put_event()

    #----------------------------------------------------------------------
    def on_start(self):
        """启动策略(必须由用户继承实现)"""
        self.write_log(u'%s策略启动' %self.className)
        self.put_event()

    #----------------------------------------------------------------------
    def on_stop(self):
        """停止策略(必须由用户继承实现)"""
        self.write_log(u'%s策略停止' %self.className)
        self.put_event()

    #----------------------------------------------------------------------
    def on_tick(self, tick):
        """收到行情TICK推送(必须由用户继承实现)"""
        self.bm5.updateTick(tick)

    #----------------------------------------------------------------------
    def on_bar(self, bar: BarData):
        """收到Bar推送(必须由用户继承实现)"""
        #早盘开盘前一分钟收到的多余的tick的清除
        if "09:29:00" in bar.datetime.strftime("%Y-%m-%d %H:%M:%S") and "IF" in bar.symbol:
            return
        if "08:59:00" in bar.datetime.strftime("%Y-%m-%d %H:%M:%S"):
            return

        #s基于日线判断趋势过滤,因此先更新
        self.bmDay.update_bar(bar)        
        #s基于30分钟更新
        self.bm30.update_bar(bar)
        # 基于15分钟更新
        self.bm15.update_bar(bar)
        # 基于5分钟更新
        self.bm5.update_bar(bar)        
        '''
        if  self.amDay.inited:
            self.onDayBar(bar)
            return
        else:
            self.amDay.update_bar(bar)
            return
        '''              
       
        #判断当前5Min布林线趋势状态
        if not self.am5.inited or not self.am15.inited or not self.am30.inited or not self.amDay.inited:
            return
        if self.bm5.window_bar !=None:   
            if self.bm5.window_bar.high_price > self.bollUp and self.bm5.window_bar.low_price > self.bollMid:
                self.FiveMinTrendStatus='duotou'
            elif self.bm5.window_bar.low_price < self.bollDown and self.bm5.window_bar.high_price < self.bollMid:
                self.FiveMinTrendStatus='kongtou'
            elif self.bm5.window_bar.low_price < self.bollMid and self.FiveMinTrendStatus=='duotou':
                self.FiveMinTrendStatus='panzhen'
            elif self.bm5.window_bar.high_price > self.bollMid and self.FiveMinTrendStatus=='kongtou':
                self.FiveMinTrendStatus='panzhen'        
            #判断当前15Min布林线趋势状态
        if self.bm15.window_bar!=None:
            if self.bm15.window_bar.high_price > self.bollUp15 and self.bm15.window_bar.low_price > self.bollMid15:
                self.FifteenMinTrendStatus='duotou'
            elif self.bm15.window_bar.low_price < self.bollDown15 and self.bm15.window_bar.high_price < self.bollMid15:
                self.FifteenMinTrendStatus='kongtou'
            elif self.bm15.window_bar.low_price < self.bollMid15 and self.FifteenMinTrendStatus=='duotou':
                self.FifteenMinTrendStatus='panzhen'
            elif self.bm15.window_bar.high_price > self.bollMid15 and self.FifteenMinTrendStatus=='kongtou':
                self.FifteenMinTrendStatus='panzhen'
            #判断当前30Min布林线趋势状态
        if self.bm30.window_bar!=None:
            if self.bm30.window_bar.high_price > self.bollUp30 and self.bm30.window_bar.low_price > self.bollMid30:
                self.ThirtyMinTrendStatus='duotou'
            elif self.bm30.window_bar.low_price < self.bollDown30 and self.bm30.window_bar.high_price < self.bollMid30:
                self.ThirtyMinTrendStatus='kongtou'
            elif self.bm30.window_bar.low_price < self.bollMid30 and self.ThirtyMinTrendStatus=='duotou':
                self.ThirtyMinTrendStatus='panzhen'
            elif self.bm30.window_bar.high_price > self.bollMid30 and self.ThirtyMinTrendStatus=='kongtou':
                self.ThirtyMinTrendStatus='panzhen'
            #判断当前日线布林线趋势状态
        if self.bmDay.window_bar!=None:
            if self.bmDay.window_bar.high_price > self.bollUpDay and self.bmDay.window_bar.low_price > self.bollMidDay:
                self.DayTrendStatus='duotou'
            elif self.bmDay.window_bar.low_price < self.bollDownDay and self.bmDay.window_bar.high_price < self.bollMidDay:
                self.DayTrendStatus='kongtou'
            elif self.bmDay.window_bar.low_price < self.bollMidDay and self.DayTrendStatus=='duotou':
                self.DayTrendStatus='panzhen'
            elif self.bmDay.window_bar.high_price > self.bollMidDay and self.DayTrendStatus=='kongtou':
                self.DayTrendStatus='panzhen'
        '''
                
        if self.pos == 0:
            #self.intraTradeHigh = bar.high
            orderList=[]
            if self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='duotou' and self.FiveMinTrendStatus=='duotou':
                #self.longEntry = bar.close
                self.cancelAll()
                orderList=self.buy(bar.close+self.priceTick, self.fixedSize, True)        
                print (u"策略:%s,委托多单,1分钟收盘价开仓"%self.__dict__["name"]) 
            elif self.DayTrendStatus=='kongtou'  and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='kongtou' and self.FiveMinTrendStatus=='kongtou':
                #self.shortEntry = bar.close
                self.cancelAll()
                orderList=self.short( bar.close-self.priceTick, self.fixedSize, True)   
                print (u"策略:%s,委托空单,1分钟收盘价开仓"%self.__dict__["name"])
        '''      
        #print (u'策略:',self.__dict__["name"])
        #print (u"策略:%s,时间:%s,1分钟刷新,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s"%(self.__dict__["name"],bar.datetime,self.FiveMinTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.DayTrendStatus))  
        self.put_event()

#----------------------------------------------------------------------
    def on_5Min_bar(self, bar: BarData):
        """收到5分钟K线"""        

        if not self.am5.inited or not self.am15.inited or not self.am30.inited or not self.amDay.inited:
            self.am5.update_bar(bar)
            return        
        #计算上一个k线的布林中轨,上轨,下轨
        self.BeforebollMid=self.am5.sma(self.bollWindow5min)
        self.Beforebollup,self.beforebolldown=self.am5.boll(self.bollWindow5min,self.entryDev5min)
        
        # 保存K线数据
        self.am5.update_bar(bar)
        
        # 撤销之前发出的尚未成交的委托(包括限价单和停止单)
        #self.cancel_all()
        orderList=[]
    
        # 计算指标数值
        self.bollMid = self.am5.sma(self.bollWindow5min)
        self.bollUp,self.bollDown = self.am5.boll(self.bollWindow5min,self.entryDev5min)

        #判断当前5Min布林线趋势状态
        if bar.high_price > self.Beforebollup and bar.low_price > self.BeforebollMid:
            self.FiveMinTrendStatus='duotou'
        elif bar.low_price < self.beforebolldown and bar.high_price < self.BeforebollMid:
            self.FiveMinTrendStatus='kongtou'
        elif bar.low_price < self.BeforebollMid and self.FiveMinTrendStatus=='duotou':
            self.FiveMinTrendStatus='panzhen'
        elif bar.high_price > self.BeforebollMid and self.FiveMinTrendStatus=='kongtou':
            self.FiveMinTrendStatus='panzhen'
        '''
        if bar.high > self.bollMid15 and self.FifteenMinTrendStatus == 'kongtou':
            self.FifteenMinTrendStatus=='panzhen'
        if bar.low < self.bollMid15 and self.FifteenMinTrendStatus == 'duotou':      
            self.FifteenMinTrendStatus=='panzhen'       
        '''   
        # 判断是否要进行交易
        #print (u"策略:%s,5分钟刷新,趋势状态,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s"%(self.className,self.FiveMinTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.DayTrendStatus))
        # 当前无仓位,发送OCO开仓委托
        '''        
        if self.pos == 0:
            #self.intraTradeHigh = bar.high
            #多头处理
            if self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus!='duotou' :
                orderList=self.buy(self.bollUp15+self.priceTick, self.fixedSize, True)
                print (u"策略:%s,委托多单,15分钟上轨开仓"%self.__dict__["name"])
            elif self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus=="panzhen" :
                orderList=self.buy(self.bollUp30+self.priceTick, self.fixedSize, True)
                print (u"策略:%s,委托多单,30分钟上轨开仓"%self.__dict__["name"])     
            elif self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='duotou' and self.FiveMinTrendStatus=='duotou':
                self.longEntry = bar.close
                orderList=self.buy(self.longEntry+self.priceTick, self.fixedSize, True)        
                print (u"策略:%s,委托多单,5分钟收盘价开仓"%self.__dict__["name"])
            elif self.DayTrendStatus=='duotou' and self.ThirtyMinTrendStatus!="panzhen"  and self.FifteenMinTrendStatus=='duotou' and self.FiveMinTrendStatus!='duotou':
                self.longEntry=self.bollUp
                orderList=self.buy(self.longEntry+self.priceTick, self.fixedSize, True)    
                print (u"策略:%s,委托多单,5分钟上轨开仓"%self.__dict__["name"])
            #空头处理    
            elif  self.DayTrendStatus=='kongtou' and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus!='kongtou' :
                orderList=self.short(self.bollDown15-self.priceTick, self.fixedSize, True)
                print (u"策略:%s,委托空单,15分钟下轨开仓"%self.__dict__["name"])
            elif  self.DayTrendStatus=='kongtou' and self.ThirtyMinTrendStatus=="panzhen" :
                orderList=self.short(self.bollDown30-self.priceTick, self.fixedSize, True)
                print (u"策略:%s,委托空单,30分钟下轨开仓"%self.__dict__["name"])   
            elif self.DayTrendStatus=='kongtou'  and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='kongtou' and self.FiveMinTrendStatus=='kongtou':
                self.shortEntry = bar.close
                orderList=self.short(self.shortEntry-self.priceTick, self.fixedSize, True)   
                print (u"策略:%s,委托空单,5分钟收盘价开仓"%self.__dict__["name"])
            elif self.DayTrendStatus=='kongtou'  and self.ThirtyMinTrendStatus!="panzhen" and self.FifteenMinTrendStatus=='kongtou' and self.FiveMinTrendStatus!='kongtou':
                self.shortEntry=self.bollDown
                orderList=self.short(self.shortEntry-self.priceTick, self.fixedSize, True)  
                print (u"策略:%s,委托空单,5分钟下轨开仓"%self.__dict__["name"])
                     

        # 持有多头仓位
        elif self.pos > 0:
            orderList=self.sell(self.bollDown-self.priceTick, abs(self.pos), True)
            print (u"策略:%s,委托止损单,5分钟下轨平仓"%self.__dict__["name"])
        # 持有空头仓位
        elif self.pos < 0:
            orderList=self.cover(self.bollUp+self.priceTick, abs(self.pos), True)
            print (u"策略:%s,委托止损单,5分钟上轨平仓"%self.__dict__["name"])
    
        with open("datasig5.csv","ab+",) as csvfile: 
            writer = csv.writer(csvfile)
            writer.writerow([bar.datetime,bar.open, bar.close, bar.high, bar.low,bar.openInterest,bar.volume,self.deal,self.bollDown,self.bollUp,self.dealopen])
        self.deal=0
        self.dealopen=0
        

        if orderList:
            print (u"策略:%s,委托单成功,单号%s"%(self.__dict__["name"],orderList[-1]))
        #else:
         #   print u"策略:%s,委托单失败"%self.__dict__["name"]            
        # 发出状态更新事件
        '''
        self.put_event()        


    def on_15Min_bar(self, bar: BarData):
        """15分钟K线推送"""
    
        if not self.am15.inited or not self.am30.inited or not self.amDay.inited:
            self.am15.update_bar(bar)
            return
        
        #计算上一个k线的布林中轨,上轨,下轨
        self.BeforebollMid15=self.am15.sma(self.bollWindow15min)
        self.Beforebollup15,self.beforebolldown15=self.am15.boll(self.bollWindow15min,self.entryDev15min)   
    
        self.am15.update_bar(bar)        
        # 计算指标数值
        self.bollMid15 = self.am15.sma(self.bollWindow15min)
        self.bollUp15,self.bollDown15 = self.am15.boll(self.bollWindow15min,self.entryDev15min)

    
        #判断当前15Min布林线趋势状态
        if bar.high_price > self.Beforebollup15 and bar.low_price > self.BeforebollMid15:
            self.FifteenMinTrendStatus='duotou'
        elif bar.low_price < self.beforebolldown15 and bar.high_price < self.BeforebollMid15:
            self.FifteenMinTrendStatus='kongtou'
        elif bar.low_price < self.BeforebollMid15 and self.FifteenMinTrendStatus=='duotou':
            self.FifteenMinTrendStatus='panzhen'
        elif bar.high_price > self.BeforebollMid15 and self.FifteenMinTrendStatus=='kongtou':
            self.FifteenMinTrendStatus='panzhen'
   
        #with open("datasig15.csv","ab+",) as csvfile: 
        #    writer = csv.writer(csvfile)
            #writer.writerow([bar.datetime,bar.open_price, bar.close_price, bar.high_price, bar.low_price,bar.open_interest,bar.volume,self.deal,self.bollDown15,self.bollUp15,self.dealopen])
        
        #print (u"策略:%s,15分钟刷新,趋势状态,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s"%(self.className,self.FiveMinTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.DayTrendStatus))
        #print u"15分钟收盘价",self.am15.closeArray[75:]
        # 当前无仓位,发送OCO开仓委托
        '''
        if self.pos == 0:
            self.intraTradeHigh = bar.high
            
            if self.FifteenMinTrendStatus=='panzhen':
                self.longEntry = self.bollUp15
                self.shortEntry=self.booldown15
                self.buy(self.longEntry, self.fixedSize, True)
                self.short(self.shortEntry,self.fixedSize,True)
        '''
        # 发出状态更新事件
        self.put_event() 
        
    def on_30Min_bar(self, bar: BarData):
        """30分钟K线推送"""

            
        if not self.am30.inited or not self.amDay.inited:
            self.am30.update_bar(bar)
            return
        
        #计算上一个k线的布林中轨,上轨,下轨
        self.BeforebollMid30=self.am30.sma(self.bollWindow30min)
        self.Beforebollup30,self.beforebolldown30=self.am30.boll(self.bollWindow30min,self.entryDev30min)   
    
        self.am30.update_bar(bar)        
        # 计算指标数值
        self.bollMid30 = self.am30.sma(self.bollWindow30min)
        self.bollUp30,self.bollDown30 = self.am30.boll(self.bollWindow30min,self.entryDev30min)

    
        #判断当前30Min布林线趋势状态
        if bar.high_price > self.Beforebollup30 and bar.low_price > self.BeforebollMid30:
            self.ThirtyMinTrendStatus='duotou'
        elif bar.low_price < self.beforebolldown30 and bar.high_price < self.BeforebollMid30:
            self.ThirtyMinTrendStatus='kongtou'
        elif bar.low_price < self.BeforebollMid30 and self.ThirtyMinTrendStatus=='duotou':
            self.ThirtyMinTrendStatus='panzhen'
        elif bar.high_price > self.BeforebollMid30 and self.ThirtyMinTrendStatus=='kongtou':
            self.ThirtyMinTrendStatus='panzhen'
        '''
        self.cancel_all()
        #开平仓位置
        self.intraTradeHigh = bar.high_price
        self.longEntry = self.bollUp30+self.priceTick
        self.longExit=self.bollDown30-self.priceTick             
        self.shortEntry=self.bollDown30-self.priceTick      
        self.shortExit=self.bollUp30+self.priceTick
        zhishun=self.bollUp30-self.bollDown30
        volume=self.caculate_pos(zhishun)    
        #volume=self.fixedSize
        #pos=self.posdata[-1]
        
        if (self.pos==0 and len(self.posdata)>0) or (not self.pos==0 and len(self.posdata)==0):
            print(u"仓位self.pos和仓位列表self.posdata不匹配")
            import sys
            sys.exit(1)
        
        if self.pos==0:  #无仓位
            if self.ThirtyMinTrendStatus=='panzhen' and self.DayTrendStatus=='duotou':
                self.buy(self.longEntry, volume, True)            
            elif self.ThirtyMinTrendStatus=='panzhen' and self.DayTrendStatus=='kongtou':  
                self.short(self.shortEntry,volume,True)    
        else:            #有仓位
            #最后一个单子为开仓单,判断是否保本了
            trade=self.tradedata[-1]
            if trade.offset==Offset.OPEN:
                if ( self.bollDown30 >trade.price and trade.direction==Direction.LONG) or (self.bollUp30 <trade.price and trade.direction==Direction.SHORT):
                    self.lastTrade_baoben=True
                    self.posdata[-1].baoben=True
                
            
            if trade.offset==Offset.CLOSE or self.lastTrade_baoben==True:    #最后一个交易为平仓单,发送开仓单在布林线上下轨
                if self.ThirtyMinTrendStatus=='panzhen' and self.DayTrendStatus=='duotou':
                    self.buy(self.longEntry, volume, True)            
                elif self.ThirtyMinTrendStatus=='panzhen' and self.DayTrendStatus=='kongtou':                     
                    self.short(self.shortEntry,volume,True)           
            #需要在布林线上下轨止损的单子,重新发出止损单子
            # 最后一笔交易为多头仓位,没有保本,在下轨止损
            elif trade.offset==Offset.OPEN and (trade.direction==Direction.LONG and self.posdata[-1].baoben==False): 
                orderList=self.sell(max(self.longExit,self.bollMidDay), trade.volume, True)
                #print (u"策略:%s,委托止损单,30分钟下轨平仓"%self.className)
            # 最后一笔交易为空头仓位,没有保本,在上轨止损
            elif trade.offset==Offset.OPEN and (trade.direction==Direction.SHORT and self.posdata[-1].baoben==False): 
                orderList=self.cover(min(self.bollMidDay,self.shortExit), trade.volume, True)
                #print (u"策略:%s,委托止损单,30分钟上轨平仓"%self.className)   
            #需要在保本位置设置止损的交易单,重新发出止损单子
            #if self.lastTrade_baoben==True:
            i=0
            while i <len(self.posdata):
                volume=self.posdata[i].volume
                if self.posdata[i].baoben==True:
                    if self.posdata[i].direction==Direction.LONG:
                        orderList=self.sell(max(self.posdata[i].price,self.bollMidDay), volume, True)
                        #print (u"策略:%s,委托止损单,保本价格平仓"%self.className)          
                    elif self.posdata[i].direction==Direction.SHORT:
                        orderList=self.cover(min(self.posdata[i].price,self.bollMidDay), volume, True)
                        #print (u"策略:%s,委托止损单,保本价格平仓"%self.className)
                i=i+1    
            #需要在日线中轨止损的单子,需要在新的日线中轨处发出止损单

        current_path =os.getcwd()# os.path.abspath(__file__)
        bardata=[bar.datetime,self.ThirtyMinTrendStatus,bar.open_price, bar.close_price, bar.high_price, bar.low_price,bar.open_interest,bar.volume,self.pos,self.bollDown30,self.bollUp30,self.dealopen]
        write_csv_file(current_path+"\\datasig30.csv",None,bardata,"a+")
        #print(u"时间:",bar.datetime)
        #print (u"策略:%s,30分钟刷新,趋势状态,5分钟趋势%s,15分钟趋势%s,30分钟趋势%s,日线趋势%s"%(self.className,self.FiveMinTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.DayTrendStatus))
        #print (u"30分钟收盘价",self.am30.close_array[60:]) 
        '''
        # 发出状态更新事件
        self.put_event()      
        
    def onDayBar(self, bar: BarData):
        """日K线推送"""
        t1=str(bar.datetime)
        t2=str(datetime(2016,1,28,21,0,0))
        if t2 in t1:
            i=0        
        if not self.amDay.inited:
            self.amDay.update_bar(bar)
            return
        

        #计算上一个k线的布林中轨,上轨,下轨
        self.BeforebollMidDay=self.amDay.sma(self.bollWindowDay)
        self.BeforebollupDay,self.beforebolldownDay=self.amDay.boll(self.bollWindowDay,self.entryDevDay)   
    
        self.amDay.update_bar(bar)        
        # 计算指标数值
        self.bollMidDay = self.amDay.sma(self.bollWindowDay)
        self.bollUpDay,self.bollDownDay = self.amDay.boll(self.bollWindowDay,self.entryDevDay)

    
        #判断当前日线布林线趋势状态
        if bar.high_price > self.BeforebollupDay and bar.low_price > self.BeforebollMidDay:
            self.DayTrendStatus='duotou'
        elif bar.low_price < self.beforebolldownDay and bar.high_price < self.BeforebollMidDay:
            self.DayTrendStatus='kongtou'
        elif bar.low_price < self.BeforebollMidDay and self.DayTrendStatus=='duotou':
            self.DayTrendStatus='panzhen'
        elif bar.high_price > self.BeforebollMidDay and self.DayTrendStatus=='kongtou':
            self.DayTrendStatus='panzhen'
        '''
        if (self.pos==0 and len(self.tradedata_day)>0) or ( self.pos!=0 and len(self.tradedata_day)==0):
            print(u"仓位self.pos和仓位列表self.tradedata_day")
            import sys
            sys.exit(1)
        '''    
        self.intraTradeHigh = bar.high_price
        self.longEntry = self.bollUpDay+self.priceTick
        self.longExit=self.bollMidDay-self.priceTick             
        self.shortEntry=self.bollDownDay-self.priceTick      
        self.shortExit=self.bollMidDay+self.priceTick
          
        #需要在日线中轨止损的单子,需要在新的日线中轨处发出止损单
        self.cancel_all()
        #if len(self.tradedata_day)>0:
        if self.pos!=0:
            if self.pos>0:
                orderList=self.sell(self.longExit, self.pos, True)
                print (u"策略:%s,委托止损单,日线中轨平仓"%self.className)  
            else:
                orderList=self.cover(self.shortExit, abs(self.pos), True)
                print (u"策略:%s,委托止损单,日线中轨平仓"%self.className)  
            '''
            i=0
            volume=0
            while i <len(self.tradedata_day):
                volume=self.tradedata_day[i].volume
                
                if self.tradedata_day[i].direction==Direction.LONG:
                    orderList=self.sell(self.longExit, volume, True)
                    print (u"策略:%s,委托止损单,日线中轨平仓"%self.className)          
                elif self.tradedata_day[i].direction==Direction.SHORT:
                    orderList=self.cover(self.shortExit, volume, True)
                    print (u"策略:%s,委托止损单,日线中轨平仓"%self.className)              
                i=i+1  
            '''
        zhishun=(self.bollUpDay-self.bollDownDay)/2
        volume=self.caculate_pos(zhishun)            
        #日线盘整,上下轨开仓  
        if self.DayTrendStatus=="panzhen" and self.pos==0 and volume!=0:#len(self.tradedata_day)==0:
            self.cancel_all()
            orderList=[]
            orderList=self.buy(self.bollUpDay+self.priceTick, volume, True)
            print (u"策略:%s,委托多单,日线上轨开仓"%self.className)
            if orderList:
                print (u"策略:%s,委托单成功,单号%s"%(self.className,orderList[-1]))
            else:
                print (u"策略:%s,委托单失败"%self.className)              
            orderList=[]    
            orderList=self.short(self.bollDownDay-self.priceTick, volume, True)
            print (u"策略:%s,委托空单,日线下轨开仓"%self.className)                       
            if orderList:
                print (u"策略:%s,委托单成功,单号%s"%(self.className,orderList[-1]))
            else:
                print (u"策略:%s,委托单失败"%self.className )             
                
        
        bardata=[bar.datetime,self.DayTrendStatus,bar.open_price, bar.close_price, bar.high_price, bar.low_price,self.pos,int(self.bollDownDay),int(self.bollMidDay),int(self.bollUpDay),self.dealopen]
        write_csv_file(os.getcwd()+"\\datasigDay.csv",None,bardata,"a+")        
        print(u"日线刷新---------------")
        print(u"时间(日线刷新):",bar.datetime)
        print (u"策略:%s,日线刷新,趋势状态,日线趋势%s,15分钟趋势%s,30分钟趋势%s,5分钟趋势%s"%(self.className,self.DayTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.FiveMinTrendStatus))
        #print (u"日线开盘价",self.amDay.open_array[1:])
        #print (u"日线收盘价",self.amDay.close_array[1:])
        #print(u"日线刷新---------------")

    
        # 发出状态更新事件
        self.put_event()               
 
    #----------------------------------------------------------------------
    def on_order(self, order):
        """收到委托变化推送(必须由用户继承实现)"""
        if order.offset==Offset.CLOSE:
            print("new order")
        pass

    #----------------------------------------------------------------------
    def on_trade(self, trade):
        #打印信息
        print(u"成交单刷新---------------")
        print(u"时间(日线刷新):",trade.datetime)
        print ("策略:%s,趋势状态,日线趋势%s,15分钟趋势%s,30分钟趋势%s,5分钟趋势%s"%(self.className,self.DayTrendStatus,self.FifteenMinTrendStatus,self.ThirtyMinTrendStatus,self.FiveMinTrendStatus))
        
        print (u"策略:%s, 委托单成交"%self.className)
        print (trade.direction)
        print (trade.offset)
        #print "15min:",self.FifteenMinTrendStatus
        #print "5min:",self.FiveMinTrendStatus
        current_path =os.getcwd()# os.path.abspath(__file__)
        #head=["datetime","orderid","tradeid","direction","offset","price","volume"]
        #所有交易单保存下来
        self.tradedata.append(trade)
        #开仓成功加入仓位list,平仓成功,删除最后加仓的仓位
        self.cancel_all()
        if trade.offset==Offset.OPEN:
            self.tradedata_day.append(trade)
            self.tradedata_day[-1].baoben==False
            self.lastTrade_baoben=False
           
        if trade.offset==Offset.CLOSE:
            #self.cancel_all()
            if len(self.tradedata_day)>0:
                self.tradedata_day.pop()
            if len(self.posdata)>=1: #这一单平仓后,仓位list中还有仓位,说明上一个仓位是已经保本的仓位i
                self.lastTrade_baoben=True
            else:
                #清空
                head=["datetime","orderid","tradeid","direction","offset","price","volume","baoben"]
                write_csv_file(current_path+"\\datasigPos.csv",head,None,"w")
                
               
        '''     
        #成交单是保本的平仓单需要,判断标准一,这次和上次都是平仓单
        if self.tradedata[-1].offset==Offset.CLOSE and self.tradedata[-2].offset==offset.CLOSE:
            self.tradedata_baoben.pop
        #成交单是保本的平仓单,判断标准二,这次是平仓单,上次是开仓单,同时保本表示为True
        if (self.tradedata[-1].offset==Offset.CLOSE and self.tradedata[-2].offset==offset.OPEN) and self.lastTrade_baoben==True:
            self.tradedata_baoben.pop
        '''        
        
        #保存到文件
        
        tradedata=[trade.datetime,trade.orderid,trade.tradeid,trade.direction,trade.offset,trade.price,trade.volume]
        write_csv_file(current_path+"\\datasigTrade.csv",None,tradedata,"a+")  
        #写入仓位保存文件
    
        head=["datetime","orderid","tradeid","direction","offset","price","volume","baoben"]
        #    write_csv_file(current_path+"datasigPos.csv",head,None,"w")        
        i=0
        while i <len(self.posdata):
            posdata=[self.posdata[i].datetime,self.posdata[i].orderid,self.posdata[i].tradeid,self.posdata[i].direction,self.posdata[i].offset,self.posdata[i].price,self.posdata[i].volume,self.posdata[i].baoben]
            if i==0:
                write_csv_file(current_path+"\\datasigPos.csv",head,None,"w")           #开仓成功后先取消掉还有的挂单,主要针对的是日线的双向挂单
         
            write_csv_file(current_path+"\\datasigPos.csv",None,posdata,"a+") 
            i=i+1
        #if self.pos!=0:        
        #    self.cancel_all()
        # 发出状态更新事件
        orderList=[]
        if trade.offset==Offset.OPEN and trade.direction==Direction.LONG: #多头成交,设置止损单
            orderList=self.sell(self.bollMidDay-self.priceTick, trade.volume, True)
            print (u"委托止损单,日线中轨平仓")
            if orderList:
                print( u"委托单成功单号",orderList)    
            else :
                print (u"委托单失败")                  
        elif trade.offset==Offset.OPEN and trade.direction==Direction.SHORT: #空头成交,设置止损单
            orderList=self.cover(self.bollMidDay+self.priceTick, trade.volume, True)
            print (u"委托止损单,日线中轨平仓")
            if orderList:
                print( u"委托单成功单号",orderList)    
            else :
                print (u"委托单失败") 
        
        elif trade.offset==Offset.CLOSE:
            zhishun=(self.bollUpDay-self.bollDownDay)/2
            volume=self.caculate_pos(zhishun)            
            #日线盘整,上下轨开仓  
            if  self.pos==0  and volume!=0:#len(self.tradedata_day)==0:
                self.cancel_all()
                orderList=[]
                orderList=self.buy(self.bollUpDay+self.priceTick, volume, True)
                print (u"策略:%s,委托多单,日线上轨开仓"%self.className)
                if orderList:
                    print (u"策略:%s,委托单成功,单号%s"%(self.className,orderList[-1]))
                else:
                    print (u"策略:%s,委托单失败"%self.className)              
                orderList=[]    
                orderList=self.short(self.bollDownDay-self.priceTick, volume, True)
                print (u"策略:%s,委托空单,日线下轨开仓"%self.className)                       
                if orderList:
                    print (u"策略:%s,委托单成功,单号%s"%(self.className,orderList[-1]))
                else:
                    print (u"策略:%s,委托单失败"%self.className )                
        
        #更新周期状态          
        if trade.offset==Offset.OPEN:
            if trade.direction==Direction.LONG:
                self.dealopen=1
                self.DayTrendStatus="duotou"
                self.FifteenMinTrendStatus='duotou'
                self.FiveMinTrendStatus='duotou'
                self.ThirtyMinTrendStatus='duotou'
            else:
                self.dealopen=-1
                self.DayTrendStatus="kongtou"
                self.FifteenMinTrendStatus='kongtou'
                self.FiveMinTrendStatus='kongtou'
                self.ThirtyMinTrendStatus='kongtou'
                
        if trade.offset==Offset.CLOSE:
            if trade.direction==Direction.LONG:
                self.ThirtyMinTrendStatus='kongtou'
                self.DayTrendStatus="panzhen"
                self.deal=1
            else:
                self.deal=-1
                

        self.put_event()

    #----------------------------------------------------------------------
    def on_stop_order(self, so):
        """停止单推送"""
        pass
class MultiTimeframeStrategy(CtaTemplate):
    """"""
    author = "KK Taiwan 交易員"

    rsi_signal = 20
    rsi_window = 14
    fast_window = 12 # init define for 5mins * 12 = 1HR  
    slow_window = 30# inti define for 5mins * 36 = 3HR
    fixed_size = 1

    rsi_value = 0
    rsi_long = 0
    rsi_short = 0
    fast_ma = 0
    slow_ma = 0
    ma_trend = 0

    parameters = ["rsi_signal", "rsi_window",
                  "fast_window", "slow_window",
                  "fixed_size"]

    variables = ["rsi_value", "rsi_long", "rsi_short",
                 "fast_ma", "slow_ma", "ma_trend","fast_ma1","slow_ma1"]
    

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.rsi_long = 50 + self.rsi_signal
        self.rsi_short = 50 - self.rsi_signal

        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am5 = ArrayManager()

        self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        self.am15 = ArrayManager()
        
            



    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg5.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        確認長短週期策略
        """
        self.bg5.update_bar(bar)
        self.bg15.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        self.am5.update_bar(bar)
        if not self.am5.inited:
            return

        if not self.ma_trend:
            return

        self.rsi_value = self.am5.rsi(self.rsi_window)

        if self.pos == 0:
            if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                self.buy(bar.close_price + 5, self.fixed_size)
            elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                self.short(bar.close_price - 5, self.fixed_size)

        elif self.pos > 0:
            if self.ma_trend < 0 or self.rsi_value < 50:
                self.sell(bar.close_price - 5, abs(self.pos))

        elif self.pos < 0:
            if self.ma_trend > 0 or self.rsi_value > 50:
                self.cover(bar.close_price + 5, abs(self.pos))

        ###KK 跟新長倉策略
        self.pettyfast_ma = self.am5.sma(self.fast_window)
        self.pettyslow_ma = self.am5.sma(self.slow_window)
        if self.pettyfast_ma > self.pettyslow_ma:
            self.ma_pettytrend = 1
        else:
            self.ma_pettytrend = -1
          

    #####
        if(buy list) 
          if (self.ma_pettytrend < 0) and (time > 0)
             if 虧 
              平倉時間點限制 - 2 time
              if < 1 平倉
             else
              平倉時間點限制 - time 
             if < 1
               跟新下限 from 15 mins均線
               #改為短平倉 and update limit
          else if time < 10
             平倉時間點限制 +time

        if(short list) 
           if (self.ma_pettytrend > 0) and (time > 0)
             if 虧 
               平倉時間點限制 - 2 time
               if timw<1
                  平倉
             else
              平倉時間點限制 - time
               if < 1
                   跟新下限 from 15 mins均線
          else if time < 10 
             平倉時間點限制 + time

        if self.pos == 0:
            if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                self.buy_signal(bar.close_price + 5, self.fixed_size)
            elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                self.short(bar.close_price - 5, self.fixed_size)

        elif self.pos > 0:
            if self.ma_trend < 0 or self.rsi_value < 50:
                self.sell_signal(bar.close_price - 5, abs(self.pos))

        elif self.pos < 0:
            if self.ma_trend > 0 or self.rsi_value > 50:
                self.cover_signal(bar.close_price + 5, abs(self.pos))
        ###
            
        self.put_event()
示例#10
0
class BollingerBotStrategy(CtaTemplate):
    """基于布林通道的交易策略"""
    className = 'BollingerBotStrategy'
    author = u'ForwardCapital'

    # 策略参数
    bollWindow = 28  # 通道窗口数
    entryDev = 3.2  # 开仓偏差
    exitDev = 1.2  # 平仓偏差
    trailingPrcnt = 0.4  # 移动止损百分比
    maWindow = 10  # 过滤用均线窗口
    initDays = 10  # 初始化数据所用的天数
    fixedSize = 1  # 每次交易的数量

    # 策略变量
    bollMid = 0  # 布林带中轨
    bollStd = 0  # 布林带宽度
    entryUp = 0  # 开仓上轨
    exitUp = 0  # 平仓上轨

    maFilter = 0  # 均线过滤
    maFilter1 = 0  # 上一期均线

    intraTradeHigh = 0  # 持仓期内的最高点
    longEntry = 0  # 多头开仓
    longExit = 0  # 多头平仓

    orderList = []  # 保存委托代码的列表
    buyOrderID = None
    sellOrderID = None

    # 参数列表,保存了参数的名称
    paramList = [
        'name', 'className', 'author', 'vtSymbol', 'bollWindow', 'entryDev',
        'exitDev', 'trailingPrcnt', 'maWindow', 'initDays', 'fixedSize'
    ]

    # 变量列表,保存了变量的名称
    varList = [
        'inited', 'trading', 'pos', 'bollMid', 'bollStd', 'entryUp', 'exitUp',
        'intraTradeHigh', 'longEntry', 'longExit'
    ]

    # 同步列表
    syncList = ['pos', 'intraTradeHigh']

    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(BollingerBotStrategy, self).__init__(ctaEngine, setting)

        self.bm = BarGenerator(self.on_bar, 15, self.onFiveBar)
        self.am = ArrayManager()

    #----------------------------------------------------------------------
    def on_init(self):
        """初始化策略(必须由用户继承实现)"""
        self.write_log(u'策略初始化')

        # 载入历史数据,并采用回放计算的方式初始化策略数值
        self.load_bar(self.initDays)

        self.put_event()

    #----------------------------------------------------------------------
    def on_start(self):
        """启动策略(必须由用户继承实现)"""
        self.write_log(u'策略启动')
        self.put_event()

    #----------------------------------------------------------------------
    def on_stop(self):
        """停止策略(必须由用户继承实现)"""
        self.write_log(u'策略停止')
        self.put_event()

    #----------------------------------------------------------------------
    def on_tick(self, tick):
        """收到行情TICK推送(必须由用户继承实现)"""
        self.bm.update_tick(tick)

    #----------------------------------------------------------------------
    def on_bar(self, bar):
        """收到Bar推送(必须由用户继承实现)"""
        self.bm.update_bar(bar)

    #----------------------------------------------------------------------
    def orderIDConvert(self, orderList):
        if not orderList:
            return []
        else:
            return orderList[0]

    #----------------------------------------------------------------------
    def onFiveBar(self, bar):
        """收到5分钟K线"""
        # 保存K线数据
        self.am.update_bar(bar)
        if not self.am.inited or not self.trading:
            return

        # 撤销之前发出的尚未成交的委托(包括限价单和停止单)
        # 计算指标数值
        self.bollMid = self.am.sma(self.bollWindow)
        self.bollStd = self.am.std(self.bollWindow)
        self.entryUp = self.bollMid + self.bollStd * self.entryDev
        self.exitUp = self.bollMid + self.bollStd * self.exitDev

        maArray = self.am.sma(self.maWindow, True)
        self.maFilter = maArray[-1]
        self.maFilter1 = maArray[-2]

        # 判断是否要进行交易
        if not self.buyOrderID:
            if self.pos == 0:
                self.intraTradeHigh = bar.high
                # 下开仓单
                if bar.close > self.maFilter and self.maFilter > self.maFilter1:
                    self.longEntry = self.entryUp
                    self.buyOrderID = self.buy(self.longEntry, self.fixedSize,
                                               True)
                    self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                    print('order None!!!buyOrderID is : %s ' % self.buyOrderID)
                    self.orderList.append(self.buyOrderID)
                    # 下平仓单
                    self.longExit = self.intraTradeHigh * (
                        1 - self.trailingPrcnt / 100)
                    self.longExit = min(self.longExit, self.exitUp)

                    self.sellOrderID = self.sell(self.longExit, abs(self.pos),
                                                 True)
                    self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                    print('order None!!!ellOrderID is : %s ' %
                          self.sellOrderID)
                    self.orderList.append(self.sellOrderID)
            elif self.pos > 0:
                self.intraTradeHigh = max(self.intraTradeHigh, bar.high)
                # 下平仓单
                self.longExit = self.intraTradeHigh * (
                    1 - self.trailingPrcnt / 100)
                self.longExit = min(self.longExit, self.exitUp)

                self.sellOrderID = self.sell(self.longExit, abs(self.pos),
                                             True)
                self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                print('order None!!!sellOrderID is : %s ' % self.sellOrderID)
                self.orderList.append(self.sellOrderID)

        else:
            if self.buyOrderID in self.orderList:
                self.intraTradeHigh = bar.high
                self.cancel_all()
                # 下开仓单
                if bar.close > self.maFilter and self.maFilter > self.maFilter1:
                    self.longEntry = self.entryUp
                    self.buyOrderID = self.buy(self.longEntry, self.fixedSize,
                                               True)
                    print('buyOrderID is : %s ' % self.buyOrderID)
                    self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                    self.orderList.append(self.buyOrderID)
                    # 下平仓单
                    self.longExit = self.intraTradeHigh * (
                        1 - self.trailingPrcnt / 100)
                    self.longExit = min(self.longExit, self.exitUp)

                    self.sellOrderID = self.sell(self.longExit, abs(self.pos),
                                                 True)
                    self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                    print('sellOrderID is : %s ' % self.sellOrderID)
                    self.orderList.append(self.sellOrderID)
            else:
                if self.sellOrderID in self.orderList:
                    self.intraTradeHigh = max(self.intraTradeHigh, bar.high)
                    self.cancel_order(self.sellOrderID)
                    # 下平仓单
                    self.longExit = self.intraTradeHigh * (
                        1 - self.trailingPrcnt / 100)
                    self.longExit = min(self.longExit, self.exitUp)

                    self.sellOrderID = self.sell(self.longExit, abs(self.pos),
                                                 True)
                    self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                    print('sellOrderID is : %s ' % self.sellOrderID)
                    self.orderList.append(self.sellOrderID)
                else:
                    self.intraTradeHigh = bar.high
                    # 下开仓单
                    if bar.close > self.maFilter and self.maFilter > self.maFilter1:
                        self.longEntry = self.entryUp
                        self.buyOrderID = self.buy(self.longEntry,
                                                   self.fixedSize, True)
                        self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                        print('buyOrderID is : %s ' % self.buyOrderID)
                        self.orderList.append(self.buyOrderID)
                        # 下平仓单
                        self.longExit = self.intraTradeHigh * (
                            1 - self.trailingPrcnt / 100)
                        self.longExit = min(self.longExit, self.exitUp)

                        self.sellOrderID = self.sell(self.longExit,
                                                     abs(self.pos), True)
                        self.sellOrderID = self.orderIDConvert(
                            self.sellOrderID)
                        print('sellOrderID is : %s ' % self.sellOrderID)
                        self.orderList.append(self.sellOrderID)

        # 发出状态更新事件
        # self.putEvent()

    #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委托变化推送(必须由用户继承实现)"""
        pass

    #----------------------------------------------------------------------
    def onTrade(self, trade):
        # 发出状态更新事件
        self.put_event()

    #----------------------------------------------------------------------
    def onStopOrder(self, so):
        """停止单推送"""
        print(u'StopOrder回报,stopOrderID:%s, status:%s' %
              (so.stopOrderID, so.status))
        if so.status == StopOrderStatus.CANCELLED or so.status == StopOrderStatus.TRIGGERED:
            self.orderList.remove(so.stopOrderID)
        pass
示例#11
0
class TurtleDStrategy(CtaTemplate):
    """"""
    # 改版海龟信号-ma出场
    author = "turtle_exit_ma"

    entry_window = 50
    exit_window = 20
    atr_window = 20
    stop_multiple = 10
    fixed_size = 1

    can_long = True
    can_short = True

    entry_up = 0
    entry_down = 0
    exit_up = 0
    exit_down = 0
    atr_value = 0

    long_entry = 0
    short_entry = 0
    long_stop = 0
    short_stop = 0

    parameters = [
        "entry_window", "exit_window", "atr_window", "fixed_size",
        "stop_multiple", "can_long", "can_short"
    ]
    variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.bg = BarGenerator(self.on_bar)
        self.am = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(20)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.cancel_all()

        self.am.update_bar(bar)
        if not self.am.inited:
            return

        # Only calculates new entry channel when no position holding
        if not self.pos:
            self.entry_up, self.entry_down = self.am.donchian(
                self.entry_window)

        self.exit_up = self.exit_down = self.am.sma(self.exit_window)

        if not self.pos:
            self.atr_value = self.am.atr(self.atr_window)

            self.long_entry = 0
            self.short_entry = 0
            self.long_stop = 0
            self.short_stop = 0

            if self.can_long:
                self.send_buy_orders(self.entry_up)

            if self.can_short:
                self.send_short_orders(self.entry_down)
        elif self.pos > 0:
            sell_price = max(self.long_stop, self.exit_down)
            self.sell(sell_price, abs(self.pos), True)
        elif self.pos < 0:
            cover_price = min(self.short_stop, self.exit_up)
            self.cover(cover_price, abs(self.pos), True)

        self.put_event()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price
            self.long_stop = self.long_entry - self.stop_multiple * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop = self.short_entry + self.stop_multiple * self.atr_value

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass

    def send_buy_orders(self, price):
        """"""
        self.buy(price, self.fixed_size, True)

    def send_short_orders(self, price):
        """"""
        self.short(price, self.fixed_size, True)
class ReverseCatchStrategy(CtaTemplate):
    author = "用Python的交易员"

    ma_level = [5, 10, 20, 30, 120]
    ma_tag = []
    bd = []
    fast_ma0 = 0.0
    fast_ma1 = 0.0

    slow_ma0 = 0.0
    slow_ma1 = 0.0
    request_order = []
    bar_identify = []
    volumn = 0
    kdj_record = []
    parameters = ["ma_level"]
    variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"]
    add_pos = False
    safe_price = None
    trend_record = MaTrendRecord

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(ReverseCatchStrategy, self).__init__(
            cta_engine, strategy_name, vt_symbol, setting
        )
        self.bg = BarGenerator(self.on_bar, 1, self.on_1min_bar)
        self.am = ArrayManager(200)
        self.am3 = ArrayManager(150)
        self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar)
        self.am5 = ArrayManager(120)
        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.order_data = None
        self.positions = CloseoutPosition(self, {"closeout_offset": 0.003})
        self.std_range = IntervalGen(np.std,5)
        self.std_range3 = IntervalGen(np.std,5)        
        self.std_range5 = IntervalGen(np.std,5)
        self.pattern_record = PatternRecord()
        # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3)
        self.pattern_record.set_expiry(list(KlinePattern), 1)
        self.ma_info = []
        
        five_min_open_5 = partial(self.reverse_shape_strategy, setting={"len":20, "atr":10, "atr_valve":0.8, "mid_sign":(7,14)})
        self.open_strategy = {
            "1":[five_min_open_5],
        }
        self.offset = 40
        self.ma120_track = None
        self.ma120_track_list = []
    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(5)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

        self.put_event()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)
        self.bg3.update_tick(tick)
        self.bg5.update_tick(tick)

    def on_3min_bar(self, bar: BarData):
        self.am3.update_bar(bar)
        self.std_range3.update(self.am3.range[-1])
        if not self.am.inited or not self.trading:
            return   
        pattern = self.am3.pattern([KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS])
        
        if len(pattern) > 0:
            print(pattern)
            self.pattern_record.add_pattern(pattern)
            # deg = calc_regress_deg(self.am3.close[-20:])
    
    def wave(self, data, window = 0.0002):

            if len(data) <= 0:
                return 
            # r = array[::-1]
            result = { "value":[], "range":[],  "pos":[], "length":[]}
            r = data
            l = len(data) - 1
            now = r[0]
            # v_list.append(now)
            # p_list.append(0)
            pos = 1

            vol = 0
            u_tag = None
            d_tag = None
            end_tag = None
            start_pos = 0
            while pos < l:
                if math.isnan(now):
                    now = r[pos]
                    pos += 1
                    continue
                else:
                    start_pos = pos - 1
                    break

            while pos < l:

                if now < r[pos]:
                    u_tag = pos
                    if d_tag:
                        diff = r[start_pos] - r[d_tag]
                        if abs(diff / r[start_pos]) > window and d_tag - start_pos > 4:
                            end_tag = d_tag
                            
                elif now > r[pos]:
                    d_tag = pos
                    if u_tag:
                        diff = r[start_pos] - r[u_tag]
                        if abs(diff / r[start_pos]) > window and d_tag - start_pos > 4:
                            end_tag = u_tag

                if end_tag is not None:
                    result["range"].append(r[end_tag] / r[start_pos] - 1)
                    result["length"].append(end_tag - start_pos)
                    start_pos = end_tag
                    result["value"].append(r[end_tag])
                    result["pos"].append(end_tag)
                    end_tag = None

                vol += r[pos] - now
                now = r[pos]
                pos += 1
            return pd.DataFrame(result)

    
    def mode_identify(self, bar: BarData):
        self.bar_identify = []
        hl_scale = round(bar.high_price / bar.low_price - 1, 4)
        if hl_scale > 0.001:
            diff = bar.high_price - bar.low_price
            diff_up = bar.low_price + diff / 2 * 1.20
            diff_down = bar.low_price + diff / 2 * 0.80 
            close = bar.close_price
            if bar.open_price < diff_up and bar.open_price > diff_down and \
               bar.close_price < diff_up and bar.close_price > diff_down:
                if bar.close_price > bar.open_price:
                    print("绿十字星",bar.datetime, bar.high_price,bar.low_price,diff,diff_up,diff_down, bar.open_price, bar.close_price)
                else:
                    print("红十字星",bar.datetime, bar.high_price,bar.low_price,diff,diff_up,diff_down, bar.open_price, bar.close_price)
        

    def on_5min_bar(self, bar: BarData):
        self.std_range5.update(self.am5.range[-1])
        self.am5.update_bar(bar)
        if not self.am.inited or not self.trading:
            return   
        
        # self.on_strategy(self.am5, bar, self.open_strategy["5"])
        # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR]
    #     pattern = self.am5.pattern(list(KlinePattern))
    #     if len(pattern) > 0:
    #         print(list(map(lambda x: (KLINE_PATTERN_CHINESE[x[0]],x[1]), pattern)))
    #         self.pattern_record.add_pattern(pattern)
    #         deg_full = calc_regress_deg(self.am.close[-40 :], False)
    #         print("deg:",deg_full)
        
    #     self.pattern_record.update()

    def open_v3(self, am:ArrayManager, bar:BarData):
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        mean_val2 = np.mean(np.array(self.ma_tag[-10:-1]))
        mean = np.mean(np.array(self.ma_tag[-30:-10]))

        if std_val2 < 0.2: 
            if mean_val2 > 3:
                if mean_val2 >= (mean + 1):
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif mean_val2 < 2:
                if mean_val2 <= (mean - 1):
                    return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def open_v1(self, am:ArrayManager, bar:BarData):
        offset = -40
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        mean_val = np.mean(calc_nums)
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        if std_val < 1 and mean_val < 2 and self.ma_tag[-1] >= (mean_val + 2):
            return self.buy(bar.close_price, 1, type=OrderType.MARKET)
        elif std_val < 1 and mean_val > 3 and self.ma_tag[-1] <= (mean_val - 2):
            return self.short(bar.close_price, 1, type=OrderType.MARKET)
    
    def open_v2(self, am:ArrayManager, bar:BarData):
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        mean_val2 = np.mean(np.array(self.ma_tag[-10:-1]))
        mean = np.mean(np.array(self.ma_tag[-30:-10]))

        if std_val2 < 0.2:
            if mean_val2 > 2.5:
                if mean_val2 >= (mean + 1):
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif mean_val2 < 2.5:
                if mean_val2 <= (mean - 1):
                    return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def ma_trend_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}):
        
        # 60个bar后取消
        if self.trend_record.std_val is not None:
            if len(self.trend_record.close) >= 60:
                self.trend_record.close = []
                self.trend_record.std_val = None
            else:
                self.trend_record.close.append(bar.close_price)
            
            
        # 如果有新的bar,则覆盖
        ma5_std = self.ma_info[-1]["ma5"]
        if ma5_std <= 0.16:
            self.trend_record.close = []
            self.trend_record.std_val = ma5_std
            return
        

        if  self.trend_record.std_val is not None and \
            ma5_std > 0.8:
            y_fit = reg_util.regress_y_polynomial(self.trend_record.close, zoom=True)
            deg = calc_regress_deg(y_fit[:10], False)

            if deg < 0:
                # if k < 20 and d < 10 and j < 10:
                # if kdj[2] < 10:
                if self.pos == 0:
                    calc_data["trade_open"] = "开空,deg={}".format(deg)
                    return self.short(bar.close_price, 1, type=OrderType.MARKET)

            else:
                # if k > 80 and d > 90 and j > 90:
                # if kdj[2] > 90:
                if self.pos == 0:
                    calc_data["trade_open"] = "开多,deg={}".format(deg)
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)




    # v形反转捕获
    def reverse_shape_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}):
        length = setting["len"]
        offset1 = int(-length)
        offset2 = int(-(length / 2))
        close = am.close
        deg1 = calc_regress_deg(close[offset1:offset2], False)
        deg2 = calc_regress_deg(close[offset2:], False)
        

        atr = self.am.atr(setting["atr"])
        atr_valve = setting["atr_valve"]
        if atr < atr_valve:
            return

        if deg1 > 0 and deg2 > 0 or \
           deg1 < 0 and deg2 < 0:
            return
        
        if not (abs(deg1) > 0.15 and abs(deg2) > 0.1 and (abs(deg1) + abs(deg2)) > 0.3) :
            return

        close = am.close[-length:]
        min_val = np.min(close)
        max_val = np.max(close)
        mid_val =  max_val if deg1 > 0 else min_val
        mid_pos = np.where(close == mid_val)[0][0]

        if mid_pos < setting["mid_sign"][0] or mid_pos > setting["mid_sign"][1]:
            return

        start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(close[:mid_pos])
        start_pos = np.where(close == start_val)[0][0]
        l = mid_pos - start_pos
        
        # pos2 = np.where(close == min_val)[0][0]
        kdj = am.kdj()
        k = kdj["k"][-1]
        d = kdj["d"][-1]
        j = kdj["j"][-1]
        x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True)
        deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False)
        y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True)
        deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False)
        # print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val)
        cci = am.cci(20)
        ma60 = am.sma(60)
        if deg2 < 0:
            # if k < 20 and d < 10 and j < 10:
            # if kdj[2] < 10:
            
            if cci < -100 and bar.close_price < ma60:
                if self.pos == 0:
                   calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci)
                   return self.short(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos > 0:
                   order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                   order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET)
                   return order_id_cover.extend(order_id_buy)
        else:
            # if k > 80 and d > 90 and j > 90:
            # if kdj[2] > 90:
            if cci > 100 and bar.close_price > ma60:
                
                if self.pos == 0:
                    calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci)
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos < 0:
                    order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                    order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET)
                    return order_id_cover.extend(order_id_buy)

        # print("找到大v形:", deg1, deg2 )

    def ma120_close(self, am:ArrayManager, bar:BarData, calc_data):
        
        if self.safe_price is None:
            return

        rg = (bar.close_price / self.buy_price) - 1

        close_price = None
        if rg > 0.01 and self.volumn > 0:
            close_price = am.sma(120)
        elif rg < -0.01 and self.volumn < 0:
            close_price = am.sma(120)
            

        for lvl in self.ma_lvl[-1:]:
            # if len(self.order_data) < lvl:
            close_price = am.sma(lvl)
            break
        

        if close_price is None:
            lvl = self.ma_level[-1]
            close_price = am.sma(lvl)

        
        
        if self.volumn < 0:
            if bar.close_price > close_price:
                calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price)
                return self.strategy.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET,
                       extra= { "reason":"平仓:到达MA均线价{}".format(close_price)})
                 
        elif self.volumn > 0:
            if bar.close_price < close_price:
                calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price)
                return self.strategy.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET,
                       extra={"reason": "平仓:到达MA均线价{}".format(close_price)})


    
    def add_position(self, am:ArrayManager, bar:BarData, calc_data, setting={}):

        if self.safe_price is None:
            return

        if not (self.volumn < 0 and bar.close_price < self.safe_price or \
                self.volumn > 0 and bar.close_price > self.safe_price):
            return

        am = self.am
        rg = (bar.close_price / self.trade_price) - 1

        close_price = None
        if rg > 0.01 and self.volumn > 0:
            close_price = am.sma(120)
            if not self.add_pos:
                self.add_pos = True
                return self.strategy.buy(bar.close_price, 50, type=OrderType.MARKET) 
        elif rg < -0.01 and self.volumn < 0:
            close_price = am.sma(120)
            if not self.add_pos:
                self.add_pos = True
                return self.strategy.short(bar.close_price, 50, type=OrderType.MARKET) 

    def reverse2_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}):
        length = 30
        offset1 = -30
        offset2 = int(-10)
        close = am.close
        deg1 = calc_regress_deg(close[-30:-8], False)
        deg2 = calc_regress_deg(close[-8:], False)
        

        if deg1 > 0 and deg2 > 0 or \
           deg1 < 0 and deg2 < 0:
            return
        
        if not (abs(deg1) > 0.15 and abs(deg2) > 0.15 and (abs(deg1) + abs(deg2)) > 0.35) :
            return

        close = am.close[-length:]
        min_val = np.min(close)
        max_val = np.max(close)
        mid_val =  max_val if deg1 > 0 else min_val
        mid_pos = np.where(close == mid_val)[0][0]

        if mid_pos < setting["mid_sign"][0] or mid_pos > setting["mid_sign"][1]:
            return

        start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(close[:mid_pos])
        start_pos = np.where(close == start_val)[0][0]
        l = mid_pos - start_pos

        # pos2 = np.where(close == min_val)[0][0]
        kdj = am.kdj()
        k = kdj["k"][-1]
        d = kdj["d"][-1]
        j = kdj["j"][-1]
        x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True)
        deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False)
        y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True)
        deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False)
        # print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val)
        cci = am.cci(20)
        ma60 = am.sma(60)
        if deg2 < 0:
            # if k < 20 and d < 10 and j < 10:
            # if kdj[2] < 10:
            
            if cci < -100 and bar.close_price < ma60:
                if self.pos == 0:
                   calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci)
                   return self.short(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos > 0:
                   calc_data["trade_close"] = "平多后做空仓,deg={},cci={}".format(deg2, cci)
                   order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                   order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET)
                   return order_id_cover.extend(order_id_buy)
        else:
            # if k > 80 and d > 90 and j > 90:
            # if kdj[2] > 90:
            if cci > 100 and bar.close_price > ma60:
                
                if self.pos == 0:
                    calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci)
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos < 0:
                    calc_data["trade_close"] = "平空后多仓,deg={},cci={}".format(deg2, cci)
                    order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                    order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET)
                    return order_id_cover.extend(order_id_buy)



    def open5(self, am:ArrayManager, bar:BarData, calc_data):
        
        ma = self.ma_tag[-1]
        mean = calc_data["mean30_10"]
        atr = self.am.atr(10, array=True, length=20)
        tr = self.am.atr(1, array=True, length=11)
        # self.ma120_track
        ma120 = self.am.sma(120)
        # if std_val2 < 0.2: 
        mean_std = calc_data["mean_std"]
        if mean_std < 0.8 and tr[-1] > 0.1 and tr[-1] / tr[-10] > 3 and tr[-1] / atr[-1] >= 1.7 and tr[-10] / atr[-10] < 1:
            if np.sum(self.am.range[-10:]) > 0 and self.ma120_track > 0:
                return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif self.ma120_track < 0:
                return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def open_kline1(self, am:ArrayManager, bar:BarData, calc_data):
        
        if KlinePattern.CDLEVENINGSTAR not in self.pattern_record:
            return
        # if std_val2 < 0.2: 
        deg = calc_regress_deg(self.am.close[-5:], False)
        print("kline_strategy",deg)
        if deg < -0.1:
            return self.short(bar.close_price, 1, type=OrderType.MARKET)
       
    def generate_data(self, am:ArrayManager, bar:BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(am.range[-30:-10]))
        ma = self.ma_tag[-1]
        
        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        
        kdj_val = am.kdj()
        has_kdj_recore = False
        k = kdj_val["k"]
        d = kdj_val["d"]
        j = kdj_val["j"]
        if  (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \
            (k[-1] < 25 and d[-1] < 25 and j[-1] < 75):
            if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \
                or \
            (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]):
                has_kdj_recore = True
                t = local_to_eastern(bar.datetime.timestamp())
                self.kdj_record.append((t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3), round(j[-1], 3)))

        
        deg1 = calc_regress_deg(am.close[offset : offset_m], False)
        deg2 = calc_regress_deg(am.close[offset_m :], False)
        deg3 = calc_regress_deg(am.close[-10 :], False)
        deg_full = calc_regress_deg(am.close[offset :], False)

        wave = self.wave(am.close[-30:])
        wave_r_sum = np.sum(wave["range"])


        macd=am.macd(20,40, 16)
        calc_data = (dict(
                ma_info=self.ma_info[-1:],
                kdj=[round(kdj_val["k"][-1],2),round(kdj_val["d"][-1],2),round(kdj_val["j"][-1],2)],
                cci_20=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=am.boll(20, 3.4),
                macd=[round(macd[0],2),round(macd[1],2),round(macd[2],2)],
                deg40_20=round(deg1,2), deg20_0=round(deg2,2), deg20_10=round(calc_regress_deg(am.close[-20:-10], False),2), 
                deg30_10=round(calc_regress_deg(am.close[-30:-10], False),2),deg10_0=round(deg3,2),
                deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2),
                atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(am.atr(40, length=42), 3),
                time=bar.datetime, price=bar.close_price, ma=round(ma, 2), 
                std_40=round(std_val, 2),mean40=round(mean_val,2), mean_std=np.mean(self.std_range.data[-5:]),
                std_10=round(std_val2,2), mean30_10=round(mean_val4,2), mean10=round(mean_val2,2),
                vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(),
                range_sum=np.sum(am.range[-5:]), 
                pattern=list(map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())),
                ma120t=self.ma120_track, 
                ma120t_list=self.ma120_track_list[-1:-10:-1], 
                ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs),
                ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), 
                ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]),
                ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]),
                wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(am.atr(20, array=True,length=240)[-200:]),
                kdj_record=self.kdj_record[-10:],
                ))
        if self.ma_info[-1]["ma5"] <= 0.16:
            calc_data["kdj_key"] = True
        return calc_data

    def generate_3mindata(self, am:ArrayManager, bar:BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(am.range[-30:-10]))
        ma = self.ma_tag[-1]
        
        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        kdj_val = am.kdj()

        deg1 = calc_regress_deg(am.close[offset : offset_m], False)
        deg2 = calc_regress_deg(am.close[offset_m :], False)
        deg3 = calc_regress_deg(am.close[-10 :], False)
        deg_full = calc_regress_deg(am.close[offset :], False)

        wave = self.wave(am.close[-30:])
        wave_r_sum = np.sum(wave["range"])
        macd=am.macd(20,40, 16)
        calc_data = (dict(
                kdj=[round(kdj_val["k"][-1],2),round(kdj_val["d"][-1],2),round(kdj_val["j"][-1],2)],
                cci_20=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=am.boll(20, 3.4),
                macd=[round(macd[0],2),round(macd[1],2),round(macd[2],2)],
                deg40_20=round(deg1,2), deg20_0=round(deg2,2), deg20_10=round(calc_regress_deg(am.close[-20:-10], False),2), deg10_0=round(deg3,2),
                deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2),
                atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(am.atr(40, length=42), 3),
                time=bar.datetime, price=bar.close_price, ma=round(ma, 2), 
                std_40=round(std_val, 2),mean40=round(mean_val,2), mean_std=np.mean(self.std_range.data[-5:]),
                std_10=round(std_val2,2), mean30_10=round(mean_val4,2), mean10=round(mean_val2,2),
                vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(),
                range_sum=np.sum(am.range[-5:]), 
                pattern=list(map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())),
                ma120t=self.ma120_track, 
                ma120t_list=self.ma120_track_list[-1:-10:-1], 
                ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs),
                ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), 
                ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]),
                ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]),
                ma_info=list(map(lambda x:x["std"], self.ma_info[-1:])),
                wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(am.atr(20, array=True,length=240)[-200:])
                ))

        return calc_data

    def on_strategy(self, am:ArrayManager, bar: BarData, strategy_list, close_strategy_list, calc_data=None):
        
            
        order_id = None

        for open_strategy in strategy_list:
            if order_id is not None:
                break
            order_id = open_strategy(am, bar, calc_data)

        if order_id is None and self.pos != 0:
            for strategy in close_strategy_list:
                if order_id is not None:
                    break
                order_id = strategy(am, bar, calc_data)

        
        if order_id is not None:
            offset = -self.offset
            offset_m = int(offset / 2)
            self.tracker["trade_info"].append((
                        self.am.time_array[offset], self.am.time_array[offset_m], bar.datetime, calc_data["deg40_20"], calc_data["deg20_0"]))
            self.request_order.extend(order_id)
        
        if self.tracker is not None:
            self.tracker["ma_tag_ls"].append(calc_data)

    def ma_info_update(self, am:ArrayManager):
        
        ma_info = {}
        ma_data = []
        for i in self.ma_level:
            ma = am.sma(i)
            ma_info[i] = round(ma,2)
            ma_data.append(ma)
        
        data = []
        diff = ma_data[-1]
        for v in ma_data:
            data.append(round(v / diff, 6))

        ma_info["ma5"] = round(np.var(data)*1000000, 8)

        data = []
        diff = ma_data[-3]
        for v in ma_data[:-2]:
            data.append(round(v / diff, 6))

        ma_info["ma3"] = round(np.var(data)*1000000, 8)

        if len(self.ma_info) < 500:
            self.ma_info.append(ma_info)
        else:
            self.ma_info[:-1] = self.ma_info[1:]
            self.ma_info[-1] = ma_info

    
    def on_1min_bar(self, bar: BarData):
        self.am.update_bar(bar)
        am = self.am
        

        max_len = self.ma_level[-1] + 20
        data = self.am.close[-max_len:-1]
        ma_lvl = []
        for i in self.ma_level:
            ma = self.am.sma(i, True)[-1]
            ma_lvl.append(ma)
        
        
        l = len(ma_lvl)
        ma_lvl_tag = []
        now = bar.close_price
        direction = 1 if now > ma_lvl[0] else 0
        ma_lvl_tag.append(direction)
        for i in range(l-1):
            val = 1 if ma_lvl[i] > ma_lvl[i+1] else 0
            ma_lvl_tag.append(val)
        bincount_val = np.bincount(np.array(ma_lvl_tag))
        tag_val = 0
        if len(bincount_val) == 2:
            tag_val = bincount_val[1]

        if len(self.ma_tag) < 200:
            self.ma_tag.append(tag_val)
        else:
            self.ma_tag[:-1] = self.ma_tag[1:]
            self.ma_tag[-1] = tag_val
        if self.tracker is not None:
            self.tracker["bar_data"].append(bar)
        self.std_range.update(self.am.range[-1])

        ma120 = self.am.sma(120)
        
        if bar.close_price >= ma120:
            if self.ma120_track is None:
                self.ma120_track = 1
            elif self.ma120_track > 0:
                self.ma120_track += 1
            else:
                self.ma120_track_list.append(self.ma120_track)
                self.ma120_track = 1
        elif bar.close_price < ma120:
            if self.ma120_track is None:
                self.ma120_track = -1
            elif self.ma120_track < 0:
                self.ma120_track -= 1
            else:
                self.ma120_track_list.append(self.ma120_track)
                self.ma120_track = -1



        if not am.inited or not self.trading:
            return

        self.ma_info_update(am)
        calc_data = self.generate_data(am, bar)
        five_min_open_5 = partial(self.reverse_shape_strategy, setting={"len":20, "atr":10, "atr_valve":0.8, "mid_sign":(7,14)})
        open_strategy = [self.reverse_shape_strategy, self.add_position]
        close_strategy = [self.positions.on_bar, self.ma120_close]
        self.on_strategy(am, bar, open_strategy, close_strategy, calc_data)
            # median_val = np.median(calc_nums)
        
        self.put_event()

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg3.update_bar(bar)
        self.bg5.update_bar(bar)
        self.bg.update_bar(bar)

        

    # def init_order_data(self):
    #     self.order_data = np.array([])
        

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        print("{}产生了{},价格为{},笔数为{},交易{},pos={}".format(order.datetime.strftime("%m/%d %H:%M:%S"), order.offset.value + order.direction.value,order.price, order.volume, order.status.value, self.pos))
        
        if order.vt_orderid in self.request_order:
            if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED:
                self.request_order.remove(order.vt_orderid)


    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.vt_orderid in self.request_order:
            self.positions.on_trade(trade)
            if self.volumn == 0:
                self.add_pos = False
                
                if trade.direction == Direction.LONG:
                    self.safe_price = trade.price * 1.003
                    self.volumn += trade.volume
                elif trade.direction == Direction.SHORT:
                    self.safe_price = trade.price * 0.997
                    self.volumn -= trade.volume
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
示例#13
0
class MultiTimeframeStrategy(CtaTemplate):
    """"""
    author = "用Python的交易员"

    rsi_signal = 20
    rsi_window = 14
    fast_window = 5
    slow_window = 20
    fixed_size = 1
    # 5min级bar下限价单时的加点,应该为最小变动价的整数倍
    bar_add = 2

    rsi_value = 0
    rsi_long = 0
    rsi_short = 0
    fast_ma = 0
    slow_ma = 0
    ma_trend = 0

    parameters = ["rsi_signal", "rsi_window",
                  "fast_window", "slow_window",
                  "fixed_size","bar_add"]

    variables = ["rsi_value", "rsi_long", "rsi_short",
                 "fast_ma", "slow_ma", "ma_trend"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.rsi_long = 50 + self.rsi_signal
        self.rsi_short = 50 - self.rsi_signal

        # 维护两组bg/am,对应不同时间周期
        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am5 = ArrayManager()

        self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        self.am15 = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg5.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg5.update_bar(bar)
        self.bg15.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        
        self.cancel_all()

        self.am5.update_bar(bar)
        if not self.am5.inited:
            return

        # 长周期趋势为短周期的过滤
        if not self.ma_trend:
            return

        self.rsi_value = self.am5.rsi(self.rsi_window)

        if self.pos == 0:
            if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                self.buy(bar.close_price + self.bar_add, self.fixed_size)
            elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                self.short(bar.close_price - self.bar_add, self.fixed_size)

        elif self.pos > 0:
            if self.ma_trend < 0 or self.rsi_value < 50:
                self.sell(bar.close_price - self.bar_add, abs(self.pos))

        elif self.pos < 0:
            if self.ma_trend > 0 or self.rsi_value > 50:
                self.cover(bar.close_price + self.bar_add, abs(self.pos))

        self.put_event()

    def on_15min_bar(self, bar: BarData):
        """"""
        self.am15.update_bar(bar)
        if not self.am15.inited:
            return

        self.fast_ma = self.am15.sma(self.fast_window)
        self.slow_ma = self.am15.sma(self.slow_window)

        # 根据15min级的MA设置方向
        if self.fast_ma > self.slow_ma:
            self.ma_trend = 1
        else:
            self.ma_trend = -1

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
示例#14
0
class TripleMaSignal(CtaSignalPatch):
    """TripleMaSignal"""

    # 策略参数
    # 三均线长度设置
    maWindow1 = 10
    maWindow2 = 30
    maWindow3 = 90

    # ma最新值
    ma1 = 0
    ma2 = 0
    ma3 = 0

    #----------------------------------------------------------------------
    def __init__(self, strategy, KCircle=1):
        """Constructor"""
        super(TripleMaSignal, self).__init__(strategy)

        self.bg = BarGenerator(self.onBar, KCircle, self.onXminBar)
        self.am = ArrayManager(size=100)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """K线更新"""
        self.bg.update_bar(bar)

    #----------------------------------------------------------------------
    def onXminBar(self, bar=BarData):
        """X Min Bar"""

        # 保存K线数据
        am = self.am
        am.update_bar(bar)
        if not am.inited:
            self.set_signal_pos(0)
            return

        if self.trading:
            self.updateSignal()

    #----------------------------------------------------------------------
    def updateSignal(self):
        """X Min Bar"""
        self.set_signal_pos(self.getSignal())
        pass

    #----------------------------------------------------------------------
    def getSignal(self):
        """生成信号"""

        ma1Array = self.am.sma(self.maWindow1, True)
        self.ma10 = ma1Array[-2]
        self.ma1 = ma1Array[-1]

        self.ma2 = self.am.sma(self.maWindow2, False)
        self.ma3 = self.am.sma(self.maWindow3, False)

        # 开多,上穿
        if self.ma1 > self.ma2 > self.ma3:
            return 1
        # 开空,下穿
        elif self.ma1 < self.ma2 < self.ma3:
            return -1

        return 0
示例#15
0
class MaLevelTrackStrategy(CtaTemplate):
    author = "用Python的交易员"

    ma_level = [5, 10, 20, 30, 120]
    ma_tag = []
    bd = []
    fast_ma0 = 0.0
    fast_ma1 = 0.0

    slow_ma0 = 0.0
    slow_ma1 = 0.0
    request_order = []
    bar_identify = []

    parameters = ["ma_level"]
    variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(MaLevelTrackStrategy, self).__init__(cta_engine, strategy_name,
                                                   vt_symbol, setting)
        self.bg = BarGenerator(self.on_bar, 15, self.on_1min_bar)
        self.am = ArrayManager(400)
        self.am3 = ArrayManager(150)
        self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar)
        self.am5 = ArrayManager(120)
        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.order_data = None
        self.positions = Position(self)
        self.std_range = IntervalGen(np.std, 5)
        self.std_range3 = IntervalGen(np.std, 5)
        self.std_range5 = IntervalGen(np.std, 5)
        self.pattern_record = PatternRecord()
        # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3)
        self.pattern_record.set_expiry(list(KlinePattern), 1)

        five_min_open_5 = partial(self.reverse_shape_strategy,
                                  setting={
                                      "atr": 10,
                                      "atr_valve": 0.8,
                                      "deg1": (10, 5),
                                      "deg2": 5
                                  })
        self.open_strategy = {
            "1": [self.reverse_shape_strategy],
            "5": [five_min_open_5],
        }
        self.offset = 40
        self.ma120_track = None
        self.ma120_track_list = []

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

        self.put_event()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)
        self.bg3.update_tick(tick)
        self.bg5.update_tick(tick)

    def on_3min_bar(self, bar: BarData):
        self.am3.update_bar(bar)
        self.std_range3.update(self.am3.range[-1])
        if not self.am.inited or not self.trading:
            return
        pattern = self.am3.pattern(
            [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS])

        if len(pattern) > 0:
            print(pattern)
            self.pattern_record.add_pattern(pattern)
            # deg = calc_regress_deg(self.am3.close[-20:])

    def wave(self, data, window=0.0002):

        if len(data) <= 0:
            return
        # r = array[::-1]
        result = {"value": [], "range": [], "pos": [], "length": []}
        r = data
        l = len(data) - 1
        now = r[0]
        # v_list.append(now)
        # p_list.append(0)
        pos = 1

        vol = 0
        u_tag = None
        d_tag = None
        end_tag = None
        start_pos = 0
        while pos < l:
            if math.isnan(now):
                now = r[pos]
                pos += 1
                continue
            else:
                start_pos = pos - 1
                break

        while pos < l:

            if now < r[pos]:
                u_tag = pos
                if d_tag:
                    diff = r[start_pos] - r[d_tag]
                    if abs(diff /
                           r[start_pos]) > window and d_tag - start_pos > 1:
                        end_tag = d_tag

            elif now > r[pos]:
                d_tag = pos
                if u_tag:
                    diff = r[start_pos] - r[u_tag]
                    if abs(diff /
                           r[start_pos]) > window and d_tag - start_pos > 1:
                        end_tag = u_tag

            if end_tag is not None:
                result["range"].append(r[end_tag] / r[start_pos] - 1)
                result["length"].append(end_tag - start_pos)
                start_pos = end_tag
                result["value"].append(r[end_tag])
                result["pos"].append(end_tag)
                end_tag = None

            vol += r[pos] - now
            now = r[pos]
            pos += 1
        return pd.DataFrame(result)

    def mode_identify(self, bar: BarData):
        self.bar_identify = []
        hl_scale = round(bar.high_price / bar.low_price - 1, 4)
        if hl_scale > 0.001:
            diff = bar.high_price - bar.low_price
            diff_up = bar.low_price + diff / 2 * 1.20
            diff_down = bar.low_price + diff / 2 * 0.80
            close = bar.close_price
            if bar.open_price < diff_up and bar.open_price > diff_down and \
               bar.close_price < diff_up and bar.close_price > diff_down:
                if bar.close_price > bar.open_price:
                    print("绿十字星", bar.datetime, bar.high_price, bar.low_price,
                          diff, diff_up, diff_down, bar.open_price,
                          bar.close_price)
                else:
                    print("红十字星", bar.datetime, bar.high_price, bar.low_price,
                          diff, diff_up, diff_down, bar.open_price,
                          bar.close_price)

    def on_5min_bar(self, bar: BarData):
        self.std_range5.update(self.am5.range[-1])
        self.am5.update_bar(bar)
        if not self.am.inited or not self.trading:
            return

        self.on_strategy(self.am5, bar, self.open_strategy["5"])
        # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR]

    #     pattern = self.am5.pattern(list(KlinePattern))
    #     if len(pattern) > 0:
    #         print(list(map(lambda x: (KLINE_PATTERN_CHINESE[x[0]],x[1]), pattern)))
    #         self.pattern_record.add_pattern(pattern)
    #         deg_full = calc_regress_deg(self.am.close[-40 :], False)
    #         print("deg:",deg_full)

    #     self.pattern_record.update()

    def open_v3(self, am: ArrayManager, bar: BarData):
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        mean_val2 = np.mean(np.array(self.ma_tag[-10:-1]))
        mean = np.mean(np.array(self.ma_tag[-30:-10]))

        if std_val2 < 0.2:
            if mean_val2 > 3:
                if mean_val2 >= (mean + 1):
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif mean_val2 < 2:
                if mean_val2 <= (mean - 1):
                    return self.short(bar.close_price,
                                      1,
                                      type=OrderType.MARKET)

    def open_v1(self, am: ArrayManager, bar: BarData):
        offset = -40
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        mean_val = np.mean(calc_nums)
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        if std_val < 1 and mean_val < 2 and self.ma_tag[-1] >= (mean_val + 2):
            return self.buy(bar.close_price, 1, type=OrderType.MARKET)
        elif std_val < 1 and mean_val > 3 and self.ma_tag[-1] <= (mean_val -
                                                                  2):
            return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def open_v2(self, am: ArrayManager, bar: BarData):
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        mean_val2 = np.mean(np.array(self.ma_tag[-10:-1]))
        mean = np.mean(np.array(self.ma_tag[-30:-10]))

        if std_val2 < 0.2:
            if mean_val2 > 2.5:
                if mean_val2 >= (mean + 1):
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif mean_val2 < 2.5:
                if mean_val2 <= (mean - 1):
                    return self.short(bar.close_price,
                                      1,
                                      type=OrderType.MARKET)

    def open2(self, am: ArrayManager, bar: BarData, calc_data):
        deg = calc_data["deg20"]
        ma = self.ma_tag[-1]
        if deg > 0.5 and ma > 3 and self.am5.range[-1] > -0.002:
            return self.buy(bar.close_price, 1, type=OrderType.MARKET)
        elif deg < -0.5 and ma < 2 and self.am5.range[-1] < 0.002:
            return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def open1(self, am: ArrayManager, bar: BarData, calc_data):

        mean = calc_data["mean30_10"]
        mean_val2 = calc_data["mean10"]
        # if std_val2 < 0.2:
        if mean_val2 > 3.5 and mean_val2 >= (mean + 2):
            return self.buy(bar.close_price, 1, type=OrderType.MARKET)
        elif mean_val2 < 1.5 and mean_val2 <= (mean - 2):
            return self.short(bar.close_price, 1, type=OrderType.MARKET)

    # v形反转捕获
    def reverse_shape_strategy(self,
                               am: ArrayManager,
                               bar: BarData,
                               calc_data,
                               setting={
                                   "atr": 40,
                                   "atr_valve": 0.8,
                                   "deg1": (40, 20),
                                   "deg2": (20, 0),
                               }):

        deg1 = calc_data["deg40_20"]
        deg2 = calc_data["deg20_0"]
        kdj = calc_data["kdj"]

        atr = self.am.atr(40)

        if atr < 0.08:
            return

        if deg1 > 0 and deg2 > 0 or \
           deg1 < 0 and deg2 < 0:
            return

        if not (abs(deg1) > 0.15 and abs(deg2) > 0.1 and
                (abs(deg1) + abs(deg2)) > 0.3):
            return

        close = am.close[-40:]
        min_val = np.min(close)
        max_val = np.max(close)
        mid_val = max_val if deg1 > 0 else min_val
        mid_pos = np.where(close == mid_val)[0][0]

        if mid_pos < 10 or mid_pos > 30:
            return

        start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(
            close[:mid_pos])
        start_pos = np.where(close == start_val)[0][0]
        l = mid_pos - start_pos

        # pos2 = np.where(close == min_val)[0][0]

        x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True)
        deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False)
        y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True)
        deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False)
        print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l,
              start_val, mid_val)
        if deg2 < 0:
            if kdj[0] < 20 and kdj[1] < 10 and kdj[2] < 10:
                # if kdj[2] < 10:
                return self.short(bar.close_price, 1, type=OrderType.MARKET)
        else:
            if kdj[0] > 80 and kdj[1] > 90 and kdj[2] > 90:
                # if kdj[2] > 90:
                return self.buy(bar.close_price, 1, type=OrderType.MARKET)

        # print("找到大v形:", deg1, deg2 )

    def open5(self, am: ArrayManager, bar: BarData, calc_data):

        ma = self.ma_tag[-1]
        mean = calc_data["mean30_10"]
        atr = self.am.atr(10, array=True, length=20)
        tr = self.am.atr(1, array=True, length=11)
        # self.ma120_track
        ma120 = self.am.sma(120)
        # if std_val2 < 0.2:
        mean_std = calc_data["mean_std"]
        if mean_std < 0.8 and tr[-1] > 0.1 and tr[-1] / tr[-10] > 3 and tr[
                -1] / atr[-1] >= 1.7 and tr[-10] / atr[-10] < 1:
            if np.sum(self.am.range[-10:]) > 0 and self.ma120_track > 0:
                return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif self.ma120_track < 0:
                return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def open_kline1(self, am: ArrayManager, bar: BarData, calc_data):

        if KlinePattern.CDLEVENINGSTAR not in self.pattern_record:
            return
        # if std_val2 < 0.2:
        deg = calc_regress_deg(self.am.close[-5:], False)
        print("kline_strategy", deg)
        if deg < -0.1:
            return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def generate_data(self, bar: BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(self.am.range[-30:-10]))
        ma = self.ma_tag[-1]

        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        kdj_val = self.am.kdj()

        deg1 = calc_regress_deg(self.am.close[offset:offset_m], False)
        deg2 = calc_regress_deg(self.am.close[offset_m:], False)
        deg3 = calc_regress_deg(self.am.close[-10:], False)
        deg_full = calc_regress_deg(self.am.close[offset:], False)

        wave = self.wave(self.am.close[-30:])
        wave_r_sum = np.sum(wave["range"])
        macd = self.am.macd(20, 40, 16)
        calc_data = (dict(
            kdj=[
                round(kdj_val["k"][-1], 2),
                round(kdj_val["d"][-1], 2),
                round(kdj_val["j"][-1], 2)
            ],
            cci_20=self.am.cci(20),
            rsi=self.am.rsi(20),
            adx=self.am.adx(20),
            boll=self.am.boll(20, 3.4),
            macd=[round(macd[0], 2),
                  round(macd[1], 2),
                  round(macd[2], 2)],
            deg40_20=round(deg1, 2),
            deg20_0=round(deg2, 2),
            deg20_10=round(calc_regress_deg(self.am.close[-20:-10], False), 2),
            deg10_0=round(deg3, 2),
            deg30_15=round(calc_regress_deg(self.am.close[-30:-15], False), 2),
            deg15_0=round(calc_regress_deg(self.am.close[-15:], False), 2),
            deg_f=round(deg_full, 2),
            atr=round(self.am.atr(10, length=15), 3),
            tr=round(self.am.atr(1, length=2), 3),
            atr_40=round(self.am.atr(40, length=42), 3),
            time=bar.datetime,
            price=bar.close_price,
            ma=round(ma, 2),
            std_40=round(std_val, 2),
            mean40=round(mean_val, 2),
            mean_std=np.mean(self.std_range.data[-5:]),
            std_10=round(std_val2, 2),
            mean30_10=round(mean_val4, 2),
            mean10=round(mean_val2, 2),
            vol=self.am.volume[-1],
            std_range=self.std_range.data[-1:-5:-1],
            range=self.am.range[-1:-5:-1].tolist(),
            range_sum=np.sum(self.am.range[-5:]),
            pattern=list(
                map(lambda x: KLINE_PATTERN_CHINESE[x],
                    self.pattern_record.keys())),
            ma120t=self.ma120_track,
            ma120t_list=self.ma120_track_list[-1:-10:-1],
            ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs),
            ma120t_sum=np.sum(self.ma120_track_list[-20:-1] +
                              [self.ma120_track]),
            ma120t_mean=np.mean(self.ma120_track_list[-20:-1] +
                                [self.ma120_track]),
            ma120t_std=np.std(self.ma120_track_list[-20:-1] +
                              [self.ma120_track]),
            wave_cnt=len(wave),
            wave_r_sum=wave_r_sum,
            atr_mean=np.mean(self.am.atr(20, array=True, length=240)[-200:])))

        return calc_data

    def on_strategy(self, am: ArrayManager, bar: BarData, strategy_list):
        calc_data = self.generate_data(bar)

        order_id = None
        if self.pos == 0:
            for open_strategy in strategy_list:
                if order_id is not None:
                    break
                order_id = open_strategy(am, bar, calc_data)
        else:
            order_id = self.positions.on_strategy(bar, calc_data)

        if order_id is not None:
            offset = -self.offset
            offset_m = int(offset / 2)
            self.tracker["trade_info"].append(
                (self.am.time_array[offset], self.am.time_array[offset_m],
                 bar.datetime, calc_data["deg40_20"], calc_data["deg20_0"]))
            self.request_order.extend(order_id)

        if self.tracker is not None:
            self.tracker["ma_tag_ls"].append(calc_data)

    def on_1min_bar(self, bar: BarData):
        self.am.update_bar(bar)
        am = self.am
        max_len = self.ma_level[-1] + 20
        data = self.am.close[-max_len:-1]
        ma_lvl = []
        for i in self.ma_level:
            ma = self.am.sma(i, True)[-1]
            ma_lvl.append(ma)

        l = len(ma_lvl)
        ma_lvl_tag = []
        now = bar.close_price
        direction = 1 if now > ma_lvl[0] else 0
        ma_lvl_tag.append(direction)
        for i in range(l - 1):
            val = 1 if ma_lvl[i] > ma_lvl[i + 1] else 0
            ma_lvl_tag.append(val)
        bincount_val = np.bincount(np.array(ma_lvl_tag))
        tag_val = 0
        if len(bincount_val) == 2:
            tag_val = bincount_val[1]

        if len(self.ma_tag) < 200:
            self.ma_tag.append(tag_val)
        else:
            self.ma_tag[:-1] = self.ma_tag[1:]
            self.ma_tag[-1] = tag_val
        if self.tracker is not None:
            self.tracker["bar_data"].append(bar)
        self.std_range.update(self.am.range[-1])

        ma120 = self.am.sma(120)

        if bar.close_price >= ma120:
            if self.ma120_track is None:
                self.ma120_track = 1
            elif self.ma120_track > 0:
                self.ma120_track += 1
            else:
                self.ma120_track_list.append(self.ma120_track)
                self.ma120_track = 1
        elif bar.close_price < ma120:
            if self.ma120_track is None:
                self.ma120_track = -1
            elif self.ma120_track < 0:
                self.ma120_track -= 1
            else:
                self.ma120_track_list.append(self.ma120_track)
                self.ma120_track = -1

        if not am.inited or not self.trading:
            return

        self.on_strategy(am, bar, self.open_strategy["1"])
        # median_val = np.median(calc_nums)

        self.put_event()

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg3.update_bar(bar)
        self.bg5.update_bar(bar)
        self.bg.update_bar(bar)

    # def init_order_data(self):
    #     self.order_data = np.array([])

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        print("{}产生了{},价格为{},笔数为{},交易{},pos={}".format(
            order.datetime.strftime("%m/%d %H:%M:%S"),
            order.offset.value + order.direction.value, order.price,
            order.volume, order.status.value, self.pos))

        if order.vt_orderid in self.request_order:
            self.positions.on_order(order)
            if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED:
                self.request_order.remove(order.vt_orderid)
        # if order.status == Status.ALLTRADED or order.status == Status.PARTTRADED:
        #     if order.direction == Direction.LONG:
        #         if self.positions.volumn == 0:
        #             self.positions.close_price = round(order.price * 0.995)
        #         self.positions.volumn += order.volume
        #     elif order.direction == Direction.SHORT:
        #         self.positions.volumn -= order.volume
        #     elif order.direction == Direction.NET:
        #         self.positions.volumn = order.volume

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
示例#16
0
class RsiAdaptStrategy(CtaTemplate):
    """
	策略逻辑:
	一、、过虑信号  (小时周期)
	使用rsiboll来判断信号强弱

	二、开单信号 (分钟周期)
	1、使用布林上下轨作为开单条件

	三、止损
	使用动态布林中轨止损

	"""
    author = "yunya"

    min_window = 45
    open_window = 15
    rsi_length = 23
    kk_length = 80
    kk_dev = 2.0
    trading_size = 1
    atr_length = 30

    rsi_entry = 0
    kk_up = 0
    kk_down = 0
    long_stop = 0
    short_stop = 0
    rsi_value = 0
    rsi_up = 0
    rsi_dow = 0
    ema_mid = 0
    ema_length_new = 0
    current_ema_mid = 0
    last_ema_mid = 0
    current_close = 0
    last_close = 0
    front_close = 0
    exit_long = 0
    exit_short = 0
    long_entry = 0
    short_entry = 0
    long_stop_trade = 0
    short_stop_drade = 0
    exit_long_nex = 0
    exit_long_last = 0
    exit_short_nex = 0
    exit_short_last = 0
    atr_value = 0

    parameters = [
        "open_window",
        "min_window",
        "rsi_length",
        "kk_length",
        "kk_dev",
        "trading_size",
        "atr_length",
    ]

    variables = [
        "rsi_entry",
        "long_stop",
        "short_stop",
        "rsi_value",
        "rsi_up",
        "rsi_dow",
        "ema_mid",
        "ema_length_new",
        "current_ema_mid",
        "last_ema_mid",
        "current_close",
        "last_close",
        "front_close",
        "exit_long",
        "exit_short",
        "long_entry",
        "short_entry",
        "long_stop_trade",
        "short_stop_drade",
        "exit_long_nex",
        "exit_long_last",
        "exit_short_nex",
        "exit_short_last",
    ]

    def __init__(
        self,
        cta_engine: Any,
        strategy_name: str,
        vt_symbol: str,
        setting: dict,
    ):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.bg_xminute = NewBarGenerator(on_bar=self.on_bar,
                                          window=self.min_window,
                                          on_window_bar=self.on_xminute_bar)
        self.am_xminute = ArrayManager(self.kk_length * 2 + 10)

        self.bg_open = NewBarGenerator(on_bar=self.on_bar,
                                       window=self.open_window,
                                       on_window_bar=self.on_5min_bar)
        self.am_open = ArrayManager()

    def on_init(self):
        """
		Callback when strategy is inited.
		"""
        self.write_log("策略初始化。。")
        self.load_bar(30)

    def on_start(self):
        """
		Callback when strategy is started.
		"""
        self.write_log("策略启动。。")

    def on_stop(self):
        """
		Callback when strategy is stopped.
		"""
        self.write_log("策略停止。。")

    def on_tick(self, tick: TickData):
        """
		Callback of new tick data update.
		"""
        self.bg_open.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
		Callback of new bar data update.
		"""
        self.bg_xminute.update_bar(bar)
        self.bg_open.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """
		:param bar: 
		:type bar: 
		:return: 
		:rtype: 
		"""
        self.cancel_all()
        self.am_open.update_bar(bar)

        if not self.am_open.inited or not self.am_xminute.inited:
            return

        ema_mid_array = self.am_open.ema(self.kk_length, True)
        atr = self.am_open.atr(self.kk_length, True)
        kk_up_array = ema_mid_array + atr * self.kk_dev
        kk_down_array = ema_mid_array - atr * self.kk_dev

        self.ema_mid = ema_mid_array[-1]
        self.kk_up = kk_up_array[-1]
        self.kk_down = kk_down_array[-1]

        self.current_close = self.am_open.close[-1]
        self.last_close = self.am_open.close[-2]
        self.front_close = self.am_open.close[-3]

        if not self.pos:
            self.exit_long_nex = 0
            self.exit_long_last = 0
            self.exit_short_nex = 0
            self.exit_short_last = 0
            self.ema_length_new = self.kk_length

            self.atr_value = self.am_open.atr(self.atr_length)

            if self.rsi_entry > 0:
                self.buy(self.kk_up, self.trading_size, True)
                self.write_log(
                    f"下多单:{bar.datetime}, {self.kk_up}, {self.trading_size}")

            elif self.rsi_entry < 0:
                self.short(self.kk_down, self.trading_size, True)
                self.write_log(
                    f"下多单:{bar.datetime}, {self.kk_down}, {self.trading_size}")

        elif self.pos > 0:
            close_long = self.current_close > self.last_close > self.front_close
            if close_long:
                self.ema_length_new -= 1
                self.ema_length_new = max(self.ema_length_new, 5)

            ema_mid_new = self.am_xminute.sma(self.ema_length_new, True)
            self.current_ema_mid = ema_mid_new[-1]
            self.last_ema_mid = ema_mid_new[-2]
            # 仓位是long 时,如果价格下穿新布林中轨
            con1 = bar.close_price < self.current_ema_mid
            con2 = bar.close_price >= self.last_ema_mid
            if con1 and con2:
                self.exit_long_nex = bar.close_price  # 保存当前收盘价

                if self.exit_long_last == 0 or self.exit_long_nex > self.exit_long_last:
                    self.exit_long_last = self.exit_long_nex
                    self.ema_length_new = self.kk_length

                    # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损
                    self.exit_long = self.ema_mid

                else:
                    # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单
                    if bar.close_price > (
                        (self.ema_mid + self.current_ema_mid) / 2):
                        self.exit_long = bar.close_price

                    elif bar.close_price < self.ema_mid:
                        self.exit_long = bar.close_price

                    else:
                        self.exit_long = self.ema_mid
            # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},")
            else:
                self.exit_long = self.ema_mid
            self.long_stop = max(self.exit_long, self.long_stop_trade)
            self.sell(self.long_stop, abs(self.pos), True)

        elif self.pos < 0:
            close_short = self.current_close < self.last_close < self.front_close
            if close_short:
                self.ema_length_new -= 1
                self.ema_length_new = max(self.ema_length_new, 5)

            ema_mid_new = self.am_xminute.sma(self.ema_length_new, True)
            self.current_ema_mid = ema_mid_new[-1]
            self.last_ema_mid = ema_mid_new[-2]

            # 仓位是short 时,如果价格上穿新布林中轨
            con1 = bar.close_price > self.current_ema_mid
            con2 = bar.close_price <= self.last_ema_mid
            if con1 and con2:
                self.exit_short_nex = bar.close_price
                if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last:
                    self.exit_short_last = self.exit_short_nex
                    self.ema_length_new = self.kk_length

                    self.exit_short = self.ema_mid

                else:
                    if bar.close_price < (self.ema_mid +
                                          self.current_ema_mid / 2):
                        self.exit_short = bar.close_price

                    elif bar.close_price < self.ema_mid:
                        self.exit_short = bar.close_price

                    else:
                        self.exit_short = self.ema_mid
            else:
                self.exit_short = self.ema_mid

            self.short_stop = min(self.exit_short, self.short_stop_drade)
            self.cover(self.short_stop, abs(self.pos), True)

        self.sync_data()
        self.put_event()

    def on_xminute_bar(self, bar: BarData):
        """
		:param bar:
		:return:
		"""
        self.am_xminute.update_bar(bar)
        if not self.am_xminute.inited:
            return

        ema_array = talib.EMA(self.am_xminute.close, self.rsi_length)
        std_array = talib.EMA(self.am_xminute.close, self.rsi_length)

        dev_array = abs(self.am_xminute.close[:-1] -
                        ema_array[:-1]) / std_array[:-1]
        dev_max = max(dev_array[-self.rsi_length:])

        rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length)
        rsi_up_array = rsi_array + rsi_array * dev_max
        rsi_dow_array = rsi_array - rsi_array * dev_max

        rsi_value_array = self.am_xminute.rsi(self.rsi_length, True)
        self.rsi_up = rsi_up_array[-1]
        self.rsi_dow = rsi_dow_array[-1]

        self.rsi_value = rsi_value_array[-1]
        current_rsi = rsi_value_array[-1]
        last_rsi = rsi_value_array[-2]
        current_rsi_up = rsi_up_array[-1]
        last_rsi_up = rsi_up_array[-2]
        current_rsi_down = rsi_dow_array[-1]
        last_rsi_down = rsi_dow_array[-2]

        con1 = current_rsi > current_rsi_up
        con2 = last_rsi <= last_rsi_up
        con3 = current_rsi < current_rsi_down
        con4 = last_rsi >= last_rsi_down

        if con1 > con2:
            self.rsi_entry = 1
        elif con3 and con4:
            self.rsi_entry = -1

        self.sync_data()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price  # 成交最高价
            self.long_stop_trade = self.long_entry - 2 * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop_drade = self.short_entry + 2 * self.atr_value

        self.sync_data()

    def on_order(self, order: OrderData):
        """
		订单更新回调
		Callback of new order data update.
		"""

        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
		Callback of stop order update.
		"""
        self.put_event()
示例#17
0
class DoubleDayM30M1Strategy(CtaTemplate):
    """
    使用1m线合成 日线、30分钟、1分钟三种数据,并根据各自ma叠加进行卖卖的策略
    """
    author = "fsksf"
    window_mn = 30  # n分钟线
    fast_window_day = 3
    fast_window_m30 = 3
    fast_window_m1 = 3
    slow_window_day = 5
    slow_window_m30 = 5
    slow_window_m1 = 5

    fast_ma_day = 0.0
    fast_ma_m30 = 0.0
    fast_ma_m1 = 0.0

    slow_ma_day = 0.0
    slow_ma_m30 = 0.0
    slow_ma_m1 = 0.0

    parameters = [
        "fast_window_day", "fast_window_m30", "fast_window_m1",
        "slow_window_day", "slow_window_m30", "slow_window_m1", "window_mn"
    ]
    variables = [
        "fast_ma_day", "slow_ma_day", "fast_ma_m30", "slow_ma_m30",
        "fast_ma_m1", "slow_ma_m1"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.day_bar_gen = BarGenerator(lambda x: None,
                                        interval=Interval.DAILY,
                                        window=1,
                                        on_window_bar=self.on_day_bar)
        self.m30_bar_gen = BarGenerator(self.on_bar,
                                        interval=Interval.MINUTE,
                                        window=self.window_mn,
                                        on_window_bar=self.on_m30_bar)
        self.day_am = ArrayManager(size=self.slow_window_day + 1)
        self.m30_am = ArrayManager(size=self.slow_window_m30 + 1)
        self.m1_am = ArrayManager(size=self.slow_window_m1 + 1)

    def on_m30_bar(self, bar):
        self.m30_am.update_bar(bar)

    def on_day_bar(self, bar):
        print(bar.__dict__)
        self.day_am.update_bar(bar)

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(100)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

        self.put_event()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.m30_bar_gen.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        # if self.cta_engine.gateway_name == "BACKTESTING":
        # update window
        self.m30_bar_gen.update_bar(bar)
        self.day_bar_gen.update_bar(bar)
        self.m1_am.update_bar(bar)
        if not (self.day_am.inited and self.m30_am.inited
                and self.m1_am.inited):
            return

        # 最后一个bar实时更新的,计算ma后删除
        # self.day_am.update_bar(self.day_bar_gen.last_bar)
        fast_ma_day = self.day_am.sma(self.fast_window_day, array=True)
        slow_ma_day = self.day_am.sma(self.slow_window_day, array=True)

        # self.m30_am.update_bar(self.m30_bar_gen.last_bar)
        fast_ma_m30 = self.m30_am.sma(self.fast_window_m30, array=True)
        slow_ma_m30 = self.m30_am.sma(self.slow_window_m30, array=True)

        fast_ma_m1 = self.m1_am.sma(self.fast_window_m1, array=True)
        slow_ma_m1 = self.m1_am.sma(self.slow_window_m1, array=True)

        self.fast_ma_day = fast_ma_day[-1]
        self.fast_ma_m30 = fast_ma_m30[-1]
        self.fast_ma_m1 = fast_ma_m1[-1]

        self.slow_ma_day = slow_ma_day[-1]
        self.slow_ma_m30 = slow_ma_m30[-1]
        self.slow_ma_m1 = slow_ma_m1[-1]

        cross_over = fast_ma_day[-2] < slow_ma_day[-2] and fast_ma_day[-1] > slow_ma_day[-1] and \
            fast_ma_m30[-2] < slow_ma_m30[-2] and fast_ma_m30[-1] > slow_ma_m30[-1] and \
            fast_ma_m1[-2] < slow_ma_m1[-2] and fast_ma_m1[-1] > slow_ma_m1[-1]
        cross_below = fast_ma_day[-2] > slow_ma_day[-2] and fast_ma_day[-1] < slow_ma_day[-1] and \
            fast_ma_m30[-2] > slow_ma_m30[-2] and fast_ma_m30[-1] < slow_ma_m30[-1] and \
            fast_ma_m1[-2] > slow_ma_m1[-2] and fast_ma_m1[-1] < slow_ma_m1[-1]

        if cross_over:
            self.write_log(f'触发买入:{str(bar.datetime)}')
            # print(f'触发买入:{str(bar.datetime)}')
            self.write_log(
                f'day: ma_fast: {fast_ma_day[-2:]}, slow: {slow_ma_day[-2:]} close_price: {self.day_am.close_array}'
            )
            self.write_log(
                f'30m: ma_fast: {fast_ma_m30[-2:]}, slow: {slow_ma_m30[-2:]} close_price: {self.m30_am.close_array}'
            )
            self.write_log(
                f'1m: ma_fast: {fast_ma_m1[-2:]}, slow: {slow_ma_m1[-2:]} close_price: {self.m1_am.close_array}'
            )
            if self.pos == 0:
                self.buy(bar.close_price, 1)
            elif self.pos < 0:
                self.cover(bar.close_price, 1)
                self.buy(bar.close_price, 1)

        elif cross_below:
            if self.pos == 0:
                self.short(bar.close_price, 1)
            elif self.pos > 0:
                self.sell(bar.close_price, 1)
                self.short(bar.close_price, 1)

        # self.day_am.remove_last_bar()
        # self.m30_am.remove_last_bar()

        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
示例#18
0
class TurtleFluidSizeStrategy(CtaTemplate):
    """"""
    # 改版海龟信号-ma出场-rsi过滤-atr浮动手数
    author = "turtle_fluid_size"

    entry_window = 50
    exit_window = 20
    atr_window = 20
    stop_multiple = 10
    long_rsi = 50
    short_rsi = 50
    fixed_size = 1

    entry_up = 0
    entry_down = 0
    exit_up = 0
    exit_down = 0
    atr_value = 0

    long_entry = 0
    short_entry = 0
    long_stop = 0
    short_stop = 0

    fluid_size = 1
    symbol_size = 1
    risk_percent = 0.002
    risk_capital = 1000000

    parameters = [
        "entry_window", "exit_window", "atr_window", "fixed_size",
        "stop_multiple", "long_rsi", "short_rsi", "symbol_size",
        "risk_percent", "risk_capital"
    ]
    variables = [
        "entry_up", "entry_down", "exit_up", "exit_down", "atr_value",
        "fluid_size"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)
        print(self.symbol_size, self.risk_percent, self.risk_capital)

        self.bg = BarGenerator(self.on_bar)
        self.am = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(20)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.cancel_all()

        self.am.update_bar(bar)
        if not self.am.inited:
            return

        # Only calculates new entry channel when no position holding
        if not self.pos:
            self.entry_up, self.entry_down = self.am.donchian(
                self.entry_window)

        self.exit_up = self.exit_down = self.am.sma(self.exit_window)
        self.rsi_value = self.am.rsi(self.entry_window)

        if not self.pos:
            self.atr_value = self.am.atr(self.atr_window)

            risk_amount = self.risk_capital * self.risk_percent
            atr_amount = self.atr_value * self.symbol_size
            self.fluid_size = round(risk_amount / atr_amount) * self.fixed_size

            self.long_entry = 0
            self.short_entry = 0
            self.long_stop = 0
            self.short_stop = 0

            if self.fluid_size and self.rsi_value > self.long_rsi:
                self.send_buy_orders(self.entry_up)
            if self.fluid_size and self.rsi_value <= self.short_rsi:
                self.send_short_orders(self.entry_down)
        elif self.pos > 0:
            sell_price = max(self.long_stop, self.exit_down)
            self.sell(sell_price, abs(self.pos), True)
        elif self.pos < 0:
            cover_price = min(self.short_stop, self.exit_up)
            self.cover(cover_price, abs(self.pos), True)

        self.put_event()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price
            self.long_stop = self.long_entry - self.stop_multiple * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop = self.short_entry + self.stop_multiple * self.atr_value

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass

    def send_buy_orders(self, price):
        """"""
        self.buy(price, self.fluid_size, True)

    def send_short_orders(self, price):
        """"""
        self.short(price, self.fluid_size, True)
示例#19
0
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()
示例#20
0
 def _update_k_data(self, code, k_data):
     # 注意:所有的数据库数据和列表数据都按照日期的正序排序(从小到大)
     """
     更新股票,股指每日数据(行情,K线,市值等0)
     @:param code  股票(指数)代码                
     @:param k_data  ts中获取的最新df数据
     """        
     if len(k_data) != 0:
         k_data = k_data.sort_values(by='trade_date')            
         cl_stock_code = self.db[code]
         cl_stock_code.create_index([('trade_date', ASCENDING)], unique=True)
         # 更新k线数据
         # 1、新增日K线入库
         # 2、遍历数据库找出最近的500+22(必须保证更新数据操作在22天以内进行)条数据并更新最后的22条的ma和最高 最低价
         for ix, row in k_data.iterrows():
             d = row.to_dict()
             d['ts_code'] = d['ts_code'].replace('.', '_')
             if self._is_in_vnpy_db(d['ts_code'], update=True):
                 # 更新vnpy数据库数据                    
                 self._build_db_vnpy(d)
             flt = {'trade_date': d['trade_date']}
             cl_stock_code.replace_one(flt, d, upsert=True)
         rec = list(cl_stock_code.find({}).sort("trade_date", DESCENDING).limit(522))
         rec.reverse()
         am = ArrayManager(size=600)
         last_5_vol = deque([0.0] * 5)
         last_5_amount = deque([0.0] * 5)
         for d in rec:                
             if 0.0 not in last_5_vol:
                 vol_rate = d['vol'] / (sum(last_5_vol) / 5.0)               
                 amount_rate = d['amount'] / (sum(last_5_amount) / 5.0)   
                 d['vol_rate'] = vol_rate
                 d['amount_rate'] = amount_rate 
             else:
                 d['vol_rate'] = 0.0
                 d['amount_rate'] = 0.0
             last_5_vol.popleft()
             last_5_amount.popleft()
             last_5_vol.append(d['vol'])
             last_5_amount.append(d['amount'])                                       
             if d['ts_code'][-3:] == '_SH':
                 exchange = Exchange.SSE
                 d['exchange'] = 'SSE'
             else:
                 exchange = Exchange.SZSE
                 d['exchange'] = 'SZSE'                
             bar = BarData(
                 gateway_name='ctp', symbol=d['ts_code'],
                 exchange=exchange,
                 datetime=string_to_datetime(d['trade_date']))
             bar.symbol = d['ts_code']
             bar.volume = d['vol']
             bar.open_price = d['open']
             bar.high_price = d['high']
             bar.low_price = d['low']
             bar.close_price = d['close']
             am.update_bar(bar)
             if d['trade_date'] >= self.db_date:
                 d['ma_5'] = am.sma(5)
                 d['ma_10'] = am.sma(10)
                 d['ma_20'] = am.sma(20)
                 d['ma_30'] = am.sma(30)
                 d['ma_60'] = am.sma(60)
                 d['ma_120'] = am.sma(120)
                 d['ma_250'] = am.sma(250)
                 d['ma_500'] = am.sma(500)
                 d['high_5'] = np.max(am.high[-5:])
                 d['high_10'] = np.max(am.high[-10:])
                 d['high_20'] = np.max(am.high[-20:])
                 d['high_30'] = np.max(am.high[-30:])
                 d['high_60'] = np.max(am.high[-60:])
                 d['high_120'] = np.max(am.high[-120:])
                 d['high_250'] = np.max(am.high[-250:])
                 d['high_500'] = np.max(am.high[-500:])
                 d['low_5'] = np.min(am.low[-5:])
                 d['low_10'] = np.min(am.low[-10:])
                 d['low_20'] = np.min(am.low[-20:])
                 d['low_30'] = np.min(am.low[-30:])
                 d['low_60'] = np.min(am.low[-60:])
                 d['low_120'] = np.min(am.low[-120:])
                 d['low_250'] = np.min(am.low[-250:])
                 d['low_500'] = np.min(am.low[-500:])
                 flt = {'trade_date': d['trade_date']}
                 cl_stock_code.replace_one(flt, d, upsert=True)
示例#21
0
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()
示例#22
0
class MultiTimeframeStrategyHNTest(CtaTemplate):
    """"""
    author = "Huang Ning"

    parameters = []

    variables = []

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.pricetick = self.get_pricetick()

        self.bg1 = XminBarGenerator(self.on_bar, self.bar_window1,
                                    self.on_Xmin1_bar)
        self.am1 = ArrayManager()

        self.bg2 = XminBarGenerator(self.on_bar, self.bar_window2,
                                    self.on_Xmin2_bar)
        self.am2 = ArrayManager()

        self.buy_vt_orderids = []
        self.sell_vt_orderids = []
        self.short_vt_orderids = []
        self.cover_vt_orderids = []

        self.buy_price = 0
        self.sell_price = 0
        self.short_price = 0
        self.cover_price = 0

    def on_init(self):
        """"""
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """"""
        self.write_log("策略启动")

    def on_stop(self):
        """"""
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """"""
        self.bg1.update_tick(tick)

    def on_bar(self, bar: BarData):
        """"""
        # 注意:不同周期K线合成的顺序对结果是有影响的
        self.bg1.update_bar(bar)
        self.bg2.update_bar(bar)

        if self.buy_vt_orderids:
            for vt_orderid in self.buy_vt_orderids:
                self.cancel_order(vt_orderid)
            self.buy_vt_orderids = self.buy(
                bar.close_price + self.pricetick * self.pricetick_multilplier2,
                self.fixed_size, True)

        elif self.sell_vt_orderids:
            for vt_orderid in self.sell_vt_orderids:
                self.cancel_order(vt_orderid)
            self.sell_vt_orderids = self.sell(
                bar.close_price - self.pricetick * self.pricetick_multilplier2,
                self.fixed_size, True)

        elif self.short_vt_orderids:
            for vt_orderid in self.short_vt_orderids:
                self.cancel_order(vt_orderid)
            self.short_vt_orderids = self.short(
                bar.close_price - self.pricetick * self.pricetick_multilplier2,
                self.fixed_size, True)

        elif self.cover_vt_orderids:
            for vt_orderid in self.cover_vt_orderids:
                self.cancel_order(vt_orderid)
            self.cover_vt_orderids = self.cover(
                bar.close_price + self.pricetick * self.pricetick_multilplier2,
                self.fixed_size, True)

    def on_Xmin1_bar(self, bar: BarData):
        """"""
        self.am1.update_bar(bar)
        if not self.am1.inited:
            return

        if not self.ma_trend:
            return

        self.rsi_value = self.am1.rsi(self.rsi_window)

        if self.pos == 0:
            self.buy_price = bar.close_price + self.pricetick * self.pricetick_multiplier1
            self.sell_price = 0
            self.short_price = bar.close_price - self.pricetick * self.pricetick_multiplier1
            self.cover_price = 0

        elif self.pos > 0:
            self.buy_price = 0
            self.sell_price = bar.close_price - self.pricetick * self.pricetick_multiplier1
            self.short_price = 0
            self.cover_price = 0

        else:
            self.buy_price = 0
            self.sell_price = 0
            self.short_price = 0
            self.cover_price = bar.close_price + self.pricetick * self.pricetick_multiplier1

        if self.pos == 0:
            if not self.buy_vt_orderids:
                if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                    self.buy(self.buy_price, self.fixed_size, True)
                    self.buy_price = 0
            else:
                for vt_orderid in self.buy_vt_orderids:
                    self.cancel_order(vt_orderid)

            if not self.short_vt_orderids:
                if self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                    self.short(self.short_price, self.fixed_size, True)
                    self.short_price = 0
            else:
                for vt_orderid in self.short_vt_orderids:
                    self.cancel_order(vt_orderid)

        elif self.pos > 0:
            if not self.sell_vt_orderids:
                if self.ma_trend < 0 or self.rsi_value < 50:
                    self.sell(self.sell_price, abs(self.pos), True)
                    self.sell_price = 0
            else:
                for vt_orderid in self.sell_vt_orderids:
                    self.cancel_order(vt_orderid)

        else:
            if not self.cover_vt_orderids:
                if self.ma_trend > 0 or self.rsi_value > 50:
                    self.cover(self.cover_price, abs(self.pos), True)
                    self.cover_price = 0
            else:
                for vt_orderid in self.cover_vt_orderids:
                    self.cancel_order(vt_orderid)

    def on_Xmin2_bar(self, bar: BarData):
        """"""
        self.am2.update_bar(bar)
        if not self.am2.inited:
            return

        self.fast_ma = self.am2.sma(self.fast_window)
        self.slow_ma = self.am2.sma(self.slow_window)

        if self.fast_ma > self.slow_ma:
            self.ma_trend = 1
        elif self.fast_ma < self.slow_ma:
            self.ma_trend = -1
        else:
            self.ma_trend = 0

    def on_stop_order(self, stop_order: StopOrder):
        """"""
        if stop_order.status == StopOrderStatus.WAITING:
            return

        for buf_orderids in [
                self.buy_vt_orderids, self.sell_vt_orderids,
                self.short_vt_orderids, self.cover_vt_orderids
        ]:
            if stop_order.stop_orderid in buf_orderids:
                buf_orderids.remove(stop_order.stop_orderid)
示例#23
0
class BollVix(CtaTemplate):
    """"""
    author = "yunya"

    open_window = 15
    boll_length = 530
    fixed_size = 1

    boll_mid_current = 0
    boll_mid_last = 0
    boll_up_current = 0
    boll_up_last = 0
    boll_down_current = 0
    boll_down_last = 0
    target_pos = 0
    pos_inited = 0
    boll_mid = 0

    # 画图专用
    time_list = []
    open_list = []
    high_list = []
    low_list = []
    close_list = []
    volume_list = []
    up_list = []
    down_list = []
    mid_list = []
    mid_new_list = []
    bias_value_list = []
    bias_list = []
    singnal_plot = []
    singnal_list = None
    singnal = None

    plot_echarts = {}

    parameters = [
        "open_window",
        "boll_length",
        "fixed_size",
    ]

    variables = [
        "boll_mid_current", "boll_mid_last", "boll_up_current", "boll_up_last",
        "boll_down_current", "boll_down_last", "pos_inited", "target_pos"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.bg = NewBarGenerator(self.on_bar,
                                  self.open_window,
                                  self.on_minute_bar,
                                  interval=Interval.MINUTE)
        self.am = ArrayManager(self.boll_length * 2)

        self.up_array: np.ndarray = np.zeros(5)
        self.down_array: np.ndarray = np.zeros(5)
        self.boll_inited = False
        self.boll_count = 0

        self.engine_type = self.get_engine_type()
        self.vt_orderids = []
        self.order_price = 0

        self.pos_inited = 0

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(12)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")
        self.put_event()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

        # 只有实盘交易才使用BestLimit算法
        if self.engine_type != EngineType.LIVE:
            return

        #  当前没有仓位
        order_volume_open = self.target_pos - self.pos

        if not order_volume_open:
            return

        if order_volume_open > 0:
            if not self.vt_orderids:
                self.order_price = tick.bid_price_1
                vt_orderids = self.buy(self.order_price,
                                       abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.bid_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

        elif order_volume_open < 0:
            if not self.vt_orderids:
                self.order_price = tick.ask_price_1
                vt_orderids = self.short(self.order_price,
                                         abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.ask_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_minute_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        # 计算布林
        sma_array = self.am.sma(self.boll_length, True)
        std_array = self.am.std(self.boll_length, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_length:].max()
        up = sma_array + std_array * dev_max
        down = sma_array - std_array * dev_max

        boll_mid_array = self.am.sma(self.boll_length, True)

        # 计算数组
        self.boll_mid = boll_mid_array[-2]
        self.boll_up_current = up[-1]
        self.boll_up_last = up[-2]
        self.boll_down_current = down[-1]
        self.boll_down_last = down[-2]

        if not self.pos:
            self.pos_inited = 0

            if self.am.close[-1] > self.boll_up_current and self.am.close[
                    -2] <= self.boll_up_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.buy(bar.close_price, self.fixed_size)
                else:
                    self.target_pos = self.fixed_size
                    print("没有仓位,我开多")

            elif self.am.close[-1] < self.boll_down_current and self.am.close[
                    -2] >= self.boll_down_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.short(bar.close_price, self.fixed_size)
                else:
                    self.target_pos = -self.fixed_size
                    print("没有仓位,我开空")

        elif self.pos > 0:
            self.sell(self.boll_mid, abs(self.pos), True)

        elif self.pos < 0:
            self.cover(self.boll_mid, abs(self.pos), True)

        # 画图专用
        if self.singnal != self.singnal_list:
            plot = self.singnal
        else:
            plot = None

        self.time_list.append(bar.datetime)
        self.open_list.append(bar.open_price)
        self.high_list.append(bar.high_price)
        self.low_list.append(bar.low_price)
        self.close_list.append(bar.close_price)
        self.volume_list.append(bar.volume)
        self.up_list.append(self.boll_up_current)
        self.down_list.append(self.boll_down_current)
        self.mid_list.append(self.boll_mid)
        self.singnal_plot.append(plot)

        self.plot_echarts = {
            "datetime": self.time_list,
            "open": self.open_list,
            "high": self.high_list,
            "low": self.low_list,
            "close": self.close_list,
            "volume": self.low_list,
            "boll_up": self.up_list,
            "boll_down": self.down_list,
            "boll_mid": self.mid_list,
            "signal": self.singnal_plot
        }
        self.singnal_list = self.singnal

        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        self.put_event()
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction.value == Direction.LONG.value:
            if trade.offset.value == Offset.OPEN.value:
                self.singnal = 1

            elif trade.offset.value == Offset.CLOSE.value:
                self.singnal = 0

            else:
                self.singnal = None

        elif trade.direction.value == Direction.SHORT.value:
            if trade.offset.value == Offset.OPEN.value:
                self.singnal = -1

            elif trade.offset.value == Offset.CLOSE.value:
                self.singnal = 0

            else:
                self.singnal = None

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass

    def boll_calculate(self):
        """
        计算布林
        :return:
        """

        if not self.boll_inited:
            self.boll_count += 1
            if self.boll_count >= 6:
                self.boll_inited = True

        self.up_array[:-1] = self.up_array[1:]
        self.down_array[:-1] = self.down_array[1:]

        sma_array = self.am.sma(self.boll_length, True)
        std_array = self.am.std(self.boll_length, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_length:].max()
        up = sma_array[-1] + std_array[-1] * dev_max
        down = sma_array[-1] - std_array[-1] * dev_max

        self.up_array[-1] = up
        self.down_array[-1] = down
    def reverse2_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}):
        length = 30
        offset1 = -30
        offset2 = int(-10)
        close = am.close
        deg1 = calc_regress_deg(close[-30:-8], False)
        deg2 = calc_regress_deg(close[-8:], False)
        

        if deg1 > 0 and deg2 > 0 or \
           deg1 < 0 and deg2 < 0:
            return
        
        if not (abs(deg1) > 0.15 and abs(deg2) > 0.15 and (abs(deg1) + abs(deg2)) > 0.35) :
            return

        close = am.close[-length:]
        min_val = np.min(close)
        max_val = np.max(close)
        mid_val =  max_val if deg1 > 0 else min_val
        mid_pos = np.where(close == mid_val)[0][0]

        if mid_pos < setting["mid_sign"][0] or mid_pos > setting["mid_sign"][1]:
            return

        start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(close[:mid_pos])
        start_pos = np.where(close == start_val)[0][0]
        l = mid_pos - start_pos

        # pos2 = np.where(close == min_val)[0][0]
        kdj = am.kdj()
        k = kdj["k"][-1]
        d = kdj["d"][-1]
        j = kdj["j"][-1]
        x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True)
        deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False)
        y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True)
        deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False)
        # print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val)
        cci = am.cci(20)
        ma60 = am.sma(60)
        if deg2 < 0:
            # if k < 20 and d < 10 and j < 10:
            # if kdj[2] < 10:
            
            if cci < -100 and bar.close_price < ma60:
                if self.pos == 0:
                   calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci)
                   return self.short(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos > 0:
                   calc_data["trade_close"] = "平多后做空仓,deg={},cci={}".format(deg2, cci)
                   order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                   order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET)
                   return order_id_cover.extend(order_id_buy)
        else:
            # if k > 80 and d > 90 and j > 90:
            # if kdj[2] > 90:
            if cci > 100 and bar.close_price > ma60:
                
                if self.pos == 0:
                    calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci)
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos < 0:
                    calc_data["trade_close"] = "平空后多仓,deg={},cci={}".format(deg2, cci)
                    order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                    order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET)
                    return order_id_cover.extend(order_id_buy)
示例#25
0
 def _init_k_data(self, code, k_data):
     # 注意:所有的数据库数据和列表数据都按照日期的正序排序(从小到大)
     """
     初始化股票数据库数据
     @:param code  股票(指数)代码                
     """     
     if len(k_data) != 0:
         last_5_vol = deque([0.0] * 5)
         last_5_amount = deque([0.0] * 5)
         k_data = k_data.sort_values(by='trade_date')            
         cl_stock_code = self.db[code]
         cl_stock_code.create_index([('trade_date', ASCENDING)], unique=True)
         am = ArrayManager(size=600)
         for ix, row in k_data.iterrows():
             d = row.to_dict()              
             d['ts_code'] = d['ts_code'].replace('.', '_')
             if 0.0 not in last_5_vol:
                 vol_rate = d['vol'] / (sum(last_5_vol) / 5.0)                
                 amount_rate = d['amount'] / (sum(last_5_amount) / 5.0)   
                 d['vol_rate'] = vol_rate
                 d['amount_rate'] = amount_rate 
             else:
                 d['vol_rate'] = 0.0
                 d['amount_rate'] = 0.0
             last_5_vol.popleft()
             last_5_amount.popleft()
             last_5_vol.append(d['vol'])
             last_5_amount.append(d['amount'])                   
             if self._is_in_vnpy_db(d['ts_code'], update=False):
                 # 构建vnpy股票数据库数据
                 self._build_db_vnpy(d)                               
             if d['ts_code'][-3:] == '_SH':
                 exchange = Exchange.SSE
                 d['exchange'] = 'SSE'
             else:
                 exchange = Exchange.SZSE                
                 d['exchange'] = 'SZSE'
             bar = BarData(
                 gateway_name='ctp', symbol=d['ts_code'],
                 exchange=exchange,
                 datetime=string_to_datetime(d['trade_date']))
             bar.symbol = d['ts_code']
             bar.volume = d['vol']
             bar.open_price = d['open']
             bar.high_price = d['high']
             bar.low_price = d['low']
             bar.close_price = d['close']
             am.update_bar(bar)
             try:
                 d['ma_5'] = am.sma(5)
             except:
                 traceback.print_exc()                    
                 LOG.error('************************')
                 LOG.error(d['ts_code'])
                 LOG.error(d['trade_date'])
                 LOG.error(bar)
             d['ma_10'] = am.sma(10)
             d['ma_20'] = am.sma(20)
             d['ma_30'] = am.sma(30)
             d['ma_60'] = am.sma(60)
             d['ma_120'] = am.sma(120)
             d['ma_250'] = am.sma(250)
             d['ma_500'] = am.sma(500)
             d['high_5'] = np.max(am.high[-5:])
             d['high_10'] = np.max(am.high[-10:])
             d['high_20'] = np.max(am.high[-20:])
             d['high_30'] = np.max(am.high[-30:])
             d['high_60'] = np.max(am.high[-60:])
             d['high_120'] = np.max(am.high[-120:])
             d['high_250'] = np.max(am.high[-250:])
             d['high_500'] = np.max(am.high[-500:])
             d['low_5'] = np.min(am.low[-5:])
             d['low_10'] = np.min(am.low[-10:])
             d['low_20'] = np.min(am.low[-20:])
             d['low_30'] = np.min(am.low[-30:])
             d['low_60'] = np.min(am.low[-60:])
             d['low_120'] = np.min(am.low[-120:])
             d['low_250'] = np.min(am.low[-250:])
             d['low_500'] = np.min(am.low[-500:])
             flt = {'trade_date': d['trade_date']}
             cl_stock_code.replace_one(flt, d, upsert=True)
示例#26
0
class PatternScoreStrategy(CtaTemplate):
    author = "用Python的交易员"

    ma_level = [10, 20, 30, 60, 120]
    ma_tag = []
    bd = []
    fast_ma0 = 0.0
    fast_ma1 = 0.0

    slow_ma0 = 0.0
    slow_ma1 = 0.0
    request_order = []
    bar_identify = []

    score = Score()
    count = 0
    interval = 6

    parameters = ["ma_level"]
    variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(PatternScoreStrategy, self).__init__(cta_engine, strategy_name,
                                                   vt_symbol, setting)
        self.bg = BarGenerator(self.on_bar)
        self.am = ArrayManager(400)
        self.am3 = ArrayManager(150)
        self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar)
        self.am5 = ArrayManager(120)
        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.order_data = None
        self.positions = Position(self)
        self.std_range = IntervalGen(np.std, 5)
        self.std_range3 = IntervalGen(np.std, 5)
        self.std_range5 = IntervalGen(np.std, 5)
        self.pattern_record = PatternRecord()
        # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3)
        self.pattern_record.set_expiry(list(KlinePattern), 1)

        self.open_strategy = [self.open_kline1]
        self.offset = 40
        self.min = 0
        self.max = 0

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

        self.put_event()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)
        self.bg3.update_tick(tick)
        self.bg5.update_tick(tick)

    def on_3min_bar(self, bar: BarData):
        self.am3.update_bar(bar)
        self.std_range3.update(self.am3.range[-1])
        if not self.am.inited or not self.trading:
            return
            # deg = calc_regress_deg(self.am3.close[-20:])

    def calc_score(self):
        score = 0
        score += self.score.base

        for item in self.pattern_record.values():
            score += item["value"]

        return score

    def on_5min_bar(self, bar: BarData):

        self.std_range5.update(self.am5.range[-1])
        self.am5.update_bar(bar)
        if not self.am.inited or not self.trading:
            return
        diff_time = bar.datetime - self.am.time_array[-1]
        if diff_time.total_seconds() > 3600 or self.count > self.interval:
            self.count = 0
            self.score.base = calc_regress_deg(self.am.close[-self.interval:],
                                               False) * 1000
            print("score:", self.score.base, self.min, self.max)
        else:
            self.count += 1

        # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR]
        pattern = self.am5.pattern(list(KlinePattern))
        if len(pattern) > 0:
            print(
                list(
                    map(lambda x: (KLINE_PATTERN_CHINESE[x[0]], x[1]),
                        pattern)))
            self.pattern_record.add_pattern(pattern)
            deg_full = calc_regress_deg(self.am.close[-40:], False)
            print("deg:", deg_full)

        self.pattern_record.update()

    def open_kline1(self, bar: BarData, calc_data):

        score = self.calc_score()
        if score < self.min:
            self.min = score
        if score > self.max:
            self.max = score

        if abs(calc_data["range_sum"]) < 0.001 or abs(score) < 300:
            return

        # if std_val2 < 0.2:
        if score > 0 and calc_data["range_sum"] > 0:
            return self.buy(bar.close_price,
                            1,
                            type=OrderType.MARKET,
                            extra={
                                "reason":
                                "开多,score={}, rang_sum={}".format(
                                    score, calc_data["range_sum"])
                            })
        if score < 0 and calc_data["range_sum"] < 0:
            return self.short(bar.close_price,
                              1,
                              type=OrderType.MARKET,
                              extra={
                                  "reason":
                                  "开多,score={}, rang_sum={}".format(
                                      score, calc_data["range_sum"])
                              })

    def generate_data(self, bar: BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(self.am.range[-30:-10]))
        ma = self.ma_tag[-1]

        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        kdj_val = self.am.kdj()

        deg1 = calc_regress_deg(self.am.close[offset:offset_m], False)
        deg2 = calc_regress_deg(self.am.close[offset_m:], False)
        deg3 = calc_regress_deg(self.am.close[-10:], False)
        deg_full = calc_regress_deg(self.am.close[offset:], False)

        calc_data = (dict(kdj=[
            round(kdj_val["k"][-1], 2),
            round(kdj_val["d"][-1], 2),
            round(kdj_val["j"][-1], 2)
        ],
                          deg40_20=round(deg1, 2),
                          deg20=round(deg2, 2),
                          deg10=round(deg3, 2),
                          deg_f=round(deg_full, 2),
                          time=bar.datetime,
                          price=bar.close_price,
                          ma=round(ma, 2),
                          std_40=round(std_val, 2),
                          mean40=round(mean_val, 2),
                          std_10=round(std_val2, 2),
                          mean30_10=round(mean_val4, 2),
                          mean10=round(mean_val2, 2),
                          vol=self.am.volume[-1],
                          std_range=self.std_range.data[-1:-5:-1],
                          range=self.am.range[-1:-5:-1].tolist(),
                          range_sum=np.sum(self.am.range[-5:]),
                          atr=self.am.atr(10),
                          tr=self.am.atr(1, length=2),
                          pattern=list(
                              map(lambda x: KLINE_PATTERN_CHINESE[x],
                                  self.pattern_record.keys()))))

        return calc_data

    def on_strategy(self, bar: BarData):
        calc_data = self.generate_data(bar)

        order_id = None

        if self.pos == 0:
            for open_strategy in self.open_strategy:
                if order_id is not None:
                    break
                order_id = open_strategy(bar, calc_data)
        else:
            order_id = self.positions.on_strategy(bar, calc_data)

        if order_id is not None:
            offset = -self.offset
            offset_m = int(offset / 2)
            self.tracker["trade_info"].append(
                (self.am.time_array[offset], self.am.time_array[offset_m],
                 bar.datetime, calc_data["deg40_20"], calc_data["deg20"]))
            self.request_order.extend(order_id)

        if self.tracker is not None:
            self.tracker["ma_tag_ls"].append(calc_data)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg3.update_bar(bar)
        self.bg5.update_bar(bar)
        am = self.am
        self.am.update_bar(bar)
        max_len = self.ma_level[-1] + 20
        data = self.am.close[-max_len:-1]
        ma_lvl = []
        for i in self.ma_level:
            ma = self.am.sma(i, True)[-1]
            ma_lvl.append(ma)

        l = len(ma_lvl)
        ma_lvl_tag = []
        now = bar.close_price
        direction = 1 if now > ma_lvl[0] else 0
        ma_lvl_tag.append(direction)
        for i in range(l - 1):
            val = 1 if ma_lvl[i] > ma_lvl[i + 1] else 0
            ma_lvl_tag.append(val)
        bincount_val = np.bincount(np.array(ma_lvl_tag))
        tag_val = 0
        if len(bincount_val) == 2:
            tag_val = bincount_val[1]

        if len(self.ma_tag) < 200:
            self.ma_tag.append(tag_val)
        else:
            self.ma_tag[:-1] = self.ma_tag[1:]
            self.ma_tag[-1] = tag_val
        if self.tracker is not None:
            self.tracker["bar_data"].append(bar)
        self.std_range.update(self.am.range[-1])

        if not self.am.inited or not self.trading:
            return

        self.on_strategy(bar)
        # median_val = np.median(calc_nums)

        self.put_event()

    # def init_order_data(self):
    #     self.order_data = np.array([])

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        print("{}产生了{},价格为{},交易{},".format(
            order.datetime.strftime("%m/%d %H:%M:%S"),
            order.offset.value + order.direction.value, order.price,
            order.status.value))

        if order.vt_orderid in self.request_order:
            self.positions.on_order(order)
            if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED:
                self.request_order.remove(order.vt_orderid)
        # if order.status == Status.ALLTRADED or order.status == Status.PARTTRADED:
        #     if order.direction == Direction.LONG:
        #         if self.positions.volumn == 0:
        #             self.positions.close_price = round(order.price * 0.995)
        #         self.positions.volumn += order.volume
        #     elif order.direction == Direction.SHORT:
        #         self.positions.volumn -= order.volume
        #     elif order.direction == Direction.NET:
        #         self.positions.volumn = order.volume

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
示例#27
0
class BollVixSignal(CtaSignal):
    """
    布林 vix
    """
    sma_array = 0
    boll_up_array = 0
    boll_down_array = 0
    entry_crossover = 0
    atr_value = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0

    def __init__(self, open_window, boll_window: int):
        """"""
        super().__init__()
        self.open_window = open_window
        self.boll_window = boll_window

        self.bg = BarGenerator(self.on_bar, self.open_window, self.on_xmin_bar)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_xmin_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)
        if not self.am.inited:
            self.set_signal_pos(0)

        # Calculate array  计算数组
        self.sma_array = self.am.sma(self.boll_window, True)
        std_array = self.am.sma(self.boll_window, True)
        dev = abs(self.am.close[:-1] - self.sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_window:].max()
        self.boll_up_array = self.sma_array[:-1] + std_array[:-1] * dev_max
        self.boll_down_array = self.sma_array[:-1] - std_array[:-1] * dev_max

        # Get current and last index
        last_sma = self.sma_array[-2]
        current_sma = self.sma_array[-1]
        last_close = self.am.close[-2]
        current_boll_up = self.boll_up_array[-1]
        last_boll_up = self.boll_up_array[-2]
        current_boll_down = self.boll_down_array[-1]
        last_boll_down = self.boll_down_array[-2]

        # Get crossover
        if last_close <= last_boll_up and current_boll_up < bar.close_price:
            self.set_signal_pos(1)

        elif last_close >= last_boll_down and current_boll_down > bar.close_price:
            self.set_signal_pos(-1)

        exit_long = last_close >= last_sma and current_sma > bar.close_price
        exit_short = last_close <= last_sma and current_sma < bar.close_price

        if exit_long and exit_short:
            self.set_signal_pos(0)
示例#28
0
class BollVix(CtaTemplate):
    """"""
    author = "yunya"

    open_window = 15
    boll_window = 80
    fixed_size = 1

    boll_mid_current = 0
    boll_mid_last = 0
    boll_up_current = 0
    boll_up_last = 0
    boll_down_current = 0
    boll_down_last = 0
    target_pos = 0
    pos_inited = 0

    parameters = [
        "open_window",
        "boll_window",
        "fixed_size",
    ]

    variables = [
        "boll_mid_current",
        "boll_mid_last",
        "boll_up_current",
        "boll_up_last",
        "boll_down_current",
        "boll_down_last",
        "pos_inited",
        "target_pos"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.bg = NewBarGenerator(self.on_bar, self.open_window, self.on_minute_bar, interval=Interval.MINUTE)
        self.am = ArrayManager(self.boll_window * 2)

        self.up_array: np.ndarray = np.zeros(5)
        self.down_array: np.ndarray = np.zeros(5)
        self.boll_inited = False
        self.boll_count = 0

        self.engine_type = self.get_engine_type()
        self.vt_orderids = []
        self.order_price = 0

        self.pos_inited = 0

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(12)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        self.put_event()

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")
        self.put_event()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

        # 只有实盘交易才使用BestLimit算法
        if self.engine_type != EngineType.LIVE:
            return

        #  当前没有仓位
        order_volume_open = self.target_pos - self.pos

        if not order_volume_open:
            return

        if order_volume_open > 0:
            if not self.vt_orderids:
                self.order_price = tick.bid_price_1
                vt_orderids = self.buy(self.order_price, abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.bid_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

        elif order_volume_open < 0:
            if not self.vt_orderids:
                self.order_price = tick.ask_price_1
                vt_orderids = self.short(self.order_price, abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.ask_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_minute_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        # 计算布林
        self.boll_calculate()
        if not self.boll_inited:
            return

        boll_mid_array = self.am.sma(self.boll_window, True)

        # 计算数组
        self.boll_mid = boll_mid_array[-2]
        self.boll_up_current = self.up_array[-1]
        self.boll_up_last = self.up_array[-2]
        self.boll_down_current = self.down_array[-1]
        self.boll_down_last = self.down_array[-2]

        if not self.pos:
            self.pos_inited = 0

            if self.am.close[-1] > self.boll_up_current and self.am.close[-2] <= self.boll_up_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.buy(self.boll_up_current, self.fixed_size)
                else:
                    self.target_pos = self.fixed_size
                    print("没有仓位,我开多")

            elif self.am.close[-1] < self.boll_down_current and self.am.close[-2] >= self.boll_down_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.short(self.boll_down_current, self.fixed_size)
                else:
                    self.target_pos = -self.fixed_size
                    print("没有仓位,我开空")

        elif self.pos > 0:
            self.sell(self.boll_mid, abs(self.pos), True)

        elif self.pos < 0:
            self.cover(self.boll_mid, abs(self.pos), True)

        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        self.put_event()
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        pass

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass

    def boll_calculate(self):
        """
        计算布林
        :return:
        """

        if not self.boll_inited:
            self.boll_count += 1
            if self.boll_count >= 6:
                self.boll_inited = True

        self.up_array[:-1] = self.up_array[1:]
        self.down_array[:-1] = self.down_array[1:]

        sma_array = self.am.sma(self.boll_window, True)
        std_array = self.am.std(self.boll_window, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_window:].max()
        up = sma_array[-1] + std_array[-1] * dev_max
        down = sma_array[-1] - std_array[-1] * dev_max

        self.up_array[-1] = up
        self.down_array[-1] = down
示例#29
0
class MultiTimeframeStrategy(CtaTemplate):
    """"""
    author = '用Python的交易员'

    rsi_signal = 20
    rsi_window = 14
    fast_window = 5
    slow_window = 20
    fixed_size = 1

    rsi_value = 0
    rsi_long = 0
    rsi_short = 0
    fast_ma = 0
    slow_ma = 0
    ma_trend = 0

    parameters = ['rsi_signal', 'rsi_window',
                  'fast_window', 'slow_window',
                  'fixed_size']

    variables = ['rsi_value', 'rsi_long', 'rsi_short',
                 'fast_ma', 'slow_ma', 'ma_trend']

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(MultiTimeframeStrategy, self).__init__(
            cta_engine, strategy_name, vt_symbol, setting
        )

        self.rsi_long = 50 + self.rsi_signal
        self.rsi_short = 50 - self.rsi_signal

        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am5 = ArrayManager()

        self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        self.am15 = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg5.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg5.update_bar(bar)
        self.bg15.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        self.am5.update_bar(bar)
        if not self.am5.inited:
            return

        if not self.ma_trend:
            return

        self.rsi_value = self.am5.rsi(self.rsi_window)

        if self.pos == 0:
            if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                self.buy(bar.close_price + 5, self.fixed_size)
            elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                self.short(bar.close_price - 5, self.fixed_size)

        elif self.pos > 0:
            if self.ma_trend < 0 or self.rsi_value < 50:
                self.sell(bar.close_price - 5, abs(self.pos))

        elif self.pos < 0:
            if self.ma_trend > 0 or self.rsi_value > 50:
                self.cover(bar.close_price + 5, abs(self.pos))

        self.put_event()

    def on_15min_bar(self, bar: BarData):
        """"""
        self.am15.update_bar(bar)
        if not self.am15.inited:
            return

        self.fast_ma = self.am15.sma(self.fast_window)
        self.slow_ma = self.am15.sma(self.slow_window)

        if self.fast_ma > self.slow_ma:
            self.ma_trend = 1
        else:
            self.ma_trend = -1

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
示例#30
0
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