VNPY 自帶跨時間週期交易策略MultiTimeframeStrategy 分析

張國平發表於2018-06-13
之前寫了bollchannel布林線軌道策略,感覺自己也有收穫,趁熱打鐵,分析下另一個時間週期策略。
其實原理很簡單,就是15分鐘週期分析現在多頭還是空頭市場,再結合rsi指標,在5分鐘線K線級別下單。非常簡單,也很有效。

class MultiTimeframeStrategy(CtaTemplate):
    """跨時間週期交易策略"""
    className = 'MultiTimeframeStrategy'
    author = u'用Python的交易員'


    # 策略引數
    rsiSignal = 20          # RSI訊號閾值
    rsiWindow = 14          # RSI視窗
    fastWindow = 5          # 快速均線視窗
    slowWindow = 20         # 慢速均線視窗
#這裡RSI指標,Relative Strength Index的縮寫, 一般r認為50是平衡市場,大於50傾向多頭,小於50空頭傾向;這裡20是一個閾#值,實際就是50+20 = 70 確立多頭,50-20 = 30 確認空頭。
#rsiWondow 是計算rsiValue的週期引數。
#fastWindow 和slowWindow都是計算均線的週期引數,其中fastWindow是計算5日,slowWindow是20日,如果fast 均價大於slow,一般認為向上趨勢,反之向下。
    initDays = 10           # 初始化資料所用的天數
    fixedSize = 1           # 每次交易的數量
#參考bollchannel文章

    # 策略變數
    rsiValue = 0                        # RSI指標的數值
    rsiLong = 0                         # RSI買開閾值
    rsiShort = 0                        # RSI賣開閾值
    fastMa = 0                          # 5分鐘快速均線
    slowMa = 0                          # 5分鐘慢速均線
    maTrend = 0                         # 均線趨勢,多頭1,空頭-1
  #參考bollchannel文章
    # 引數列表,儲存了引數的名稱
    paramList = ['name',
                 'className',
                 'author',
                 'vtSymbol',
                 'rsiSignal',
                 'rsiWindow',
                 'fastWindow',
                 'slowWindow']    

#參考bollchannel文章
    # 變數列表,儲存了變數的名稱
    varList = ['inited',
               'trading',
               'pos',
               'rsiValue',
               'rsiLong',
               'rsiShort',
               'fastMa',
               'slowMa',
               'maTrend']  
    #參考bollchannel文章,其中maTrend是根據快慢均值的高低,如果fastMa > slowMa 為向上,maTrend > 0; 反之向下。

    # 同步列表,儲存了需要儲存到資料庫的變數名稱
    syncList = ['pos']
 #參考bollchannel文章,這裡只同步倉位。

    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(MultiTimeframeStrategy, self).__init__(ctaEngine, setting)
        
        self.rsiLong = 50 + self.rsiSignal
        self.rsiShort = 50 - self.rsiSignal
    #如上文,rsi 大於70為多頭,rsi小於30為空頭。    
        # 建立K線合成器物件
        self.bg5 = BarGenerator(self.onBar, 5, self.on5MinBar)
        self.am5 = ArrayManager()
        
        self.bg15 = BarGenerator(self.onBar, 15, self.on15MinBar)
        self.am15 = ArrayManager()
    #實現兩個K線合成器和AM,來合成並計算5分鐘和15分鐘K線和對應指標。    
    #----------------------------------------------------------------------
    def onInit(self):
        """初始化策略(必須由使用者繼承實現)"""
        self.writeCtaLog(u'%s策略初始化' %self.name)
    
        # 載入歷史資料,並採用回放計算的方式初始化策略數值
        initData = self.loadBar(self.initDays)
        for bar in initData:
            self.onBar(bar)


        self.putEvent()
 #參考bollchannel文章

    #----------------------------------------------------------------------
    def onStart(self):
        """啟動策略(必須由使用者繼承實現)"""
        self.writeCtaLog(u'%s策略啟動' %self.name)
        self.putEvent()


    #----------------------------------------------------------------------
    def onStop(self):
        """停止策略(必須由使用者繼承實現)"""
        self.writeCtaLog(u'%s策略停止' %self.name)
        self.putEvent()
 #參考bollchannel文章

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """收到行情TICK推送(必須由使用者繼承實現)"""
        # 只需要要在一個BarGenerator中合成1分鐘K線
        self.bg5.updateTick(tick)
 #參考bollchannel文章, 根據tick交易行情,合成1分鐘K線,並更新bg5中onBar。一般這個是針對實盤;通常歷史資料下載來都是不到tick級別,而且一分鐘k線;可能券商本身會有。這裡感覺應該吧bg15放在一起更合適吧。。。

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """收到Bar推送(必須由使用者繼承實現)"""
        # 基於15分鐘判斷趨勢過濾,因此先更新
        self.bg15.updateBar(bar)
        
        # 基於5分鐘判斷
        self.bg5.updateBar(bar)
   #參考bollchannel文章,當一分鐘K線到達後,湊夠時間,合成對應時間K線,包括15分鐘和5分鐘
    #----------------------------------------------------------------------
    def on5MinBar(self, bar):
        """5分鐘K線"""
        self.cancelAll()
 #參考bollchannel文章,清空未成交。

        # 儲存K線資料
        self.am5.updateBar(bar)
        if not self.am5.inited:
            return
   #參考bollchannel文章,取得AM指標計算是否有100個bar的資料來計算。      
        # 如果15分鐘資料尚未初始化完畢,則直接返回
        if not self.maTrend:
            return
 #15分鐘K線,計算快慢線fastMa,slowM和maTrend; 如果maTrend沒有值,說明15分鐘K線還沒有到100,所以推出函式。

        # 計算指標數值
        self.rsiValue = self.am5.rsi(self.rsiWindow)
#根據risWindos計算出5分鐘rsi現在值。

        # 判斷是否要進行交易
        
        # 當前無倉位
        if self.pos == 0:
            if self.maTrend > 0 and self.rsiValue >= self.rsiLong:
                self.buy(bar.close+5, self.fixedSize)
                
            elif self.maTrend < 0 and self.rsiValue <= self.rsiShort:
                self.short(bar.close-5, self.fixedSize)
#如果空,maTrend 和rsiValue都是多頭,下多單,這個是市價單,其實價格沒有什麼意思,都會按照漲停發出。同理相反,如果都是空頭,下空單。

        # 持有多頭倉位
        elif self.pos > 0:
            if self.maTrend < 0 or self.rsiValue < 50:
                self.sell(bar.close-5, abs(self.pos))
            
        # 持有空頭倉位
        elif self.pos < 0:
            if self.maTrend > 0 or self.rsiValue > 50:
                self.cover(bar.close+5, abs(self.pos))
#如果有多頭倉位,但是空頭趨勢,平倉,反之持有空頭也是一樣。

        # 發出狀態更新事件
        self.putEvent()        
    
    #----------------------------------------------------------------------
    def on15MinBar(self, bar):
        """15分鐘K線推送"""
        self.am15.updateBar(bar)
        
        if not self.am15.inited:
            return
        
        # 計算均線並判斷趨勢
        self.fastMa = self.am15.sma(self.fastWindow)
        self.slowMa = self.am15.sma(self.slowWindow)
        
        if self.fastMa > self.slowMa:
            self.maTrend = 1
        else:
            self.maTrend = -1
#這個不說了,計算快慢均線價格,和對應趨勢。

    #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委託變化推送(必須由使用者繼承實現)"""
        pass


    #----------------------------------------------------------------------
    def onTrade(self, trade):
        # 發出狀態更新事件
        self.putEvent()


    #----------------------------------------------------------------------
    def onStopOrder(self, so):
        """停止單推送"""
        pass

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22259926/viewspace-2156080/,如需轉載,請註明出處,否則將追究法律責任。

相關文章