91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

VNPY 交易所返回委托和交易狀態到策略的源代碼分析

發布時間:2020-08-08 19:45:48 來源:ITPUB博客 閱讀:1078 作者:張國平 欄目:編程語言
  1. 主要分析兩個在類策略模型ctaTemplate的中的函數,onTrade和onOrder,其實兩個很相似,被別的其他實例調用,推入更新的Trade和Order實例,并執行函數內的代碼。對于Tick級別的交易,還是還是會經常用到這兩個。下面是在ctaTemplate中的定義。

    def onOrder(self, order):
        """收到委托變化推送(必須由用戶繼承實現)"""
        # 對于無需做細粒度委托控制的策略,可以忽略onOrder
        pass
 
    # ----------------------------------------------------------------------
    def onTrade(self, trade):
        """收到成交推送(必須由用戶繼承實現)"""
        # 對于無需做細粒度委托控制的策略,可以忽略onOrder
        pass
  1. 2.  先去看看 order trade 是什么樣的類,兩個都在 vtObject.py 里面。理論上來說,在 tick 級別中高頻策略,當 order trade 發生變化后,使用 onOrder/onTrade 傳遞更新給策略;函數 onOrder/onTrade 里面一般定義一些對應不同狀態進行的對應操作。

  2. 1) VtTradeData包含是成交的數據,其中最關鍵就是vtOrderID,可以和之前發送交易返回的vtOrderID做對應,用來對應的交易訂單。其他諸如direction/offset/price/volume都是很重要;可以用來更新postion數據。

  3. 2) 類VtOrderData和之前VtQrderReq很像,但是不一樣,這個是記錄委托信息狀態,req是交易請求,其中最關鍵的就是status,訂單狀態;這里有四個狀態(ALLTRADED全部成交,PARTTRADED部分成交, NOTTRADED未成交,和CANCLLED拒單),這些屬性在ctpGateway.py定義的。

  4. class VtTradeData(VtBaseData):
        """成交數據類"""
     
        #----------------------------------------------------------------------
        def __init__(self):
            """Constructor"""
            super(VtTradeData, self).__init__()
                    # 代碼編號相關
            self.symbol = EMPTY_STRING              # 合約代碼
            self.exchange = EMPTY_STRING            # 交易所代碼
            self.vtSymbol = EMPTY_STRING            # 合約在vt系統中的唯一代碼,通常是 合約代碼.交易所代碼
            self.tradeID = EMPTY_STRING             # 成交編號
            self.vtTradeID = EMPTY_STRING           # 成交在vt系統中的唯一編號,通常是 Gateway名.成交編號
           
            self.orderID = EMPTY_STRING             # 訂單編號
            self.vtOrderID = EMPTY_STRING           # 訂單在vt系統中的唯一編號,通常是 Gateway名.訂單編號
               # 成交相關
            self.direction = EMPTY_UNICODE          # 成交方向
            self.offset = EMPTY_UNICODE             # 成交開平倉
            self.price = EMPTY_FLOAT                # 成交價格
            self.volume = EMPTY_INT                 # 成交數量
            self.tradeTime = EMPTY_STRING           # 成交時間
      
     
    ########################################################################
    class VtOrderData(VtBaseData):
        """訂單數據類"""
     
        #----------------------------------------------------------------------
        def __init__(self):
            """Constructor"""
            super(VtOrderData, self).__init__()
           
            # 代碼編號相關
            self.symbol = EMPTY_STRING              # 合約代碼
            self.exchange = EMPTY_STRING            # 交易所代碼
            self.vtSymbol = EMPTY_STRING            # 合約在vt系統中的唯一代碼,通常是 合約代碼.交易所代碼
            self.orderID = EMPTY_STRING             # 訂單編號
            self.vtOrderID = EMPTY_STRING           # 訂單在vt系統中的唯一編號,通常是 Gateway名.訂單編號
           
            # 報單相關
            self.direction = EMPTY_UNICODE          # 報單方向
            self.offset = EMPTY_UNICODE             # 報單開平倉
            self.price = EMPTY_FLOAT                # 報單價格
            self.totalVolume = EMPTY_INT            # 報單總數量
            self.tradedVolume = EMPTY_INT           # 報單成交數量
            self.status = EMPTY_UNICODE             # 報單狀態   
            self.orderTime = EMPTY_STRING           # 發單時間
            self.cancelTime = EMPTY_STRING          # 撤單時間
           
            # CTP/LTS相關
            self.frontID = EMPTY_INT                # 前置機編號
            self.sessionID = EMPTY_INT              # 連接編號
    

     3. 之前提到數次通過 onOrder/onTrade 傳遞最新 Order/Trade 狀態,這個負責處理的是一個系列過程,上層推手就是類 ctaEngine ,下面主要說下函數 processOrderEvent ,處理委托推送。其中傳入的 event 是一個事件對象,由一個 type_ 說明類型,和一個字典 dict_ 存儲具體的事件數據組成。可以理解為是上面 vtObject 的一個包裝盒, event Engine只要根據標簽 type_ ,就可以把具體數據傳給對應的下層處理者。這個關于 event 具體的后面再分析.

       這個函數,首先讀取了event字典中包好的order,因為存在手動發起交易情況 , 如果這個vtOrder是之前通過策略發出的,則調用callStrategyFunc來把這個order回傳到對應strategy . onOrder方法,如果是手動發出指令就算了。同時也分析狀態,如果在委托完成狀態,也更新strategyOrderDict字典,移除這個

def processOrderEvent(self, event):
        """處理委托推送"""
        order = event.dict_['data']
        vtOrderID = order.vtOrderID
       
        if vtOrderID in self.orderStrategyDict:
            strategy = self.orderStrategyDict[vtOrderID]           
           
            # 如果委托已經完成(拒單、撤銷、全成),則從活動委托集合中移除
            if order.status in self.STATUS_FINISHED:
                s = self.strategyOrderDict[strategy.name]
                if vtOrderID in s:
                    s.remove(vtOrderID)
           
            self.callStrategyFunc(strategy, strategy.onOrder, order)

4.  在往上追溯就到eventEngine,首先在 ctaEngine 初始化時候,會分配eventEngine實例,再通過下面代碼注冊處理事件,當某類事件收到時候,調用對應的方法,比如事件類型EVENT_ORDER, 對應的方法是self.processOrderEvent。

   class ctaEngine
    def registerEvent(self):
        """注冊事件監聽"""
        self.eventEngine.register(EVENT_TICK, self.processTickEvent)
        self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
        self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
 
class eventEngine
    def register(self, type_, handler):
        """注冊事件處理函數監聽"""
        # 嘗試獲取該事件類型對應的處理函數列表,若無defaultDict會自動創建新的list
        handlerList = self.__handlers[type_]
       
        # 若要注冊的處理器不在該事件的處理器列表中,則注冊該事件
        if handler not in handlerList:
            handlerList.append(handler)

eventEngine 中的 register函數就是處理的方法通過 __handlers字典來對應,__handlers是defaultdict(list),是一種特殊的字典,最大特點就是如果同一個 key 值插入不同 value ,他不會像就普通 dict 用新的替代,而且變成 {key:[value1,value2 ……]} 這樣存儲。這樣就可以讓同一個 type ,可以有對應多個接收 handler

這里有兩個event Engine, 按照官方說法,

  • EventEngine類使用了PyQt中的QTimer來實現定時器功能,由PyQt應用主線程中的Qt事件循環來定時觸發(無需新開單獨的線程),適合在帶有圖形界面的應用程序中使用(如examples/VnTrader);

  • EventEngine2類則是使用了一個單獨的線程來實現定時器功能,適合在無圖形界面的應用程序中使用(如examples/CtaTrading)。

來自 < https://github.com/vnpy/vnpy/wiki/%E4%BA%8B%E4%BB%B6%E5%BC%95%E6%93%8E >


5.  上面說了 eventEngine的組成 Event ,然后還有一個后面處理函數def __process(self, event)。 在一個內部隊列__queue中不停抓起 event ,通過檢索字典 __handlers來分配到對應的函數處理。那么誰放入新的event呢,就是一個調用put(event)函數向事件隊列插入事件。這個時候發現一個特殊的 EVENT_TIMER ,看了半天,感覺可以理解為是一個節奏控制器,每一秒去做一次 process ;那么對于高頻來說,可能換成 500 毫秒更合適。

下面是VNPY定義的EVENT事件。

# 系統相關
EVENT_TIMER = 'eTimer'                  # 計時器事件,每隔1秒發送一次
EVENT_LOG = 'eLog'                      # 日志事件,全局通用
 
# Gateway相關
EVENT_TICK = 'eTick.'                   # TICK行情事件,可后接具體的vtSymbol
EVENT_TRADE = 'eTrade.'                 # 成交回報事件
EVENT_ORDER = 'eOrder.'                 # 報單回報事件
EVENT_POSITION = 'ePosition.'           # 持倉回報事件
EVENT_ACCOUNT = 'eAccount.'             # 賬戶回報事件
EVENT_CONTRACT = 'eContract.'           # 合約基礎信息回報事件
EVENT_ERROR = 'eError.'                 # 錯誤回報事件

6.  現在想著是誰在不停的給這個內部隊列放入 order/trick 狀態的 event , 而在 ctp G ate 這個類中,在其父類 vtGate 中有 on Or de r 方法,很規范的打包 order evet ,然后放到隊列里面。還有分析后發現在 Mainengine 對整個 eventEngine 進行管理,并通過 addGateway 通過中把在事件引擎和交易接口管理。

    def onOrder(self, order):
        """訂單變化推送"""
        # 通用事件
        event1 = Event(type_=EVENT_ORDER)
        event1.dict_['data'] = order
        self.eventEngine.put(event1)
       
        # 特定訂單編號的事件
        event2 = Event(type_=EVENT_ORDER+order.vtOrderID)
        event2.dict_['data'] = order
        self.eventEngine.put(event2)

7. 在至上是 class CtpTdApi(TdApi) 這個類的,讀取 data 中的 order 相關數據,創建 order ,推送到上面的這個 onOrder 里面 ; 在往上就有點頭大了,這個 data 信息應該是從編譯底層返回的。

 def onRtnOrder(self, data):
        """報單回報"""
        # 更新最大報單編號
        newref = data['OrderRef']
        self.orderRef = max(self.orderRef, int(newref))
       
        # 創建報單數據對象
        order = VtOrderData()
        order.gatewayName = self.gatewayName
       
        # 保存代碼和報單號
        order.symbol = data['InstrumentID']
        order.exchange = exchangeMapReverse[data['ExchangeID']]
        order.vtSymbol = order.symbol #'.'.join([order.symbol, order.exchange])
       
        order.orderID = data['OrderRef']
        # CTP的報單號一致性維護需要基于frontID, sessionID, orderID三個字段
        # 但在本接口設計中,已經考慮了CTP的OrderRef的自增性,避免重復
        # 唯一可能出現OrderRef重復的情況是多處登錄并在非常接近的時間內(幾乎同時發單)
        # 考慮到VtTrader的應用場景,認為以上情況不會構成問題
        order.vtOrderID = '.'.join([self.gatewayName, order.orderID])       
       
        order.direction = directionMapReverse.get(data['Direction'], DIRECTION_UNKNOWN)
        order.offset = offsetMapReverse.get(data['CombOffsetFlag'], OFFSET_UNKNOWN)
        order.status = statusMapReverse.get(data['OrderStatus'], STATUS_UNKNOWN)           
           
        # 價格、報單量等數值
        order.price = data['LimitPrice']
        order.totalVolume = data['VolumeTotalOriginal']
        order.tradedVolume = data['VolumeTraded']
        order.orderTime = data['InsertTime']
        order.cancelTime = data['CancelTime']
        order.frontID = data['FrontID']
        order.sessionID = data['SessionID']
       
        # 推送
        self.gateway.onOrder(order)

總體來看,eventEngine這個是一個總的驅動,在內部queue這個傳送帶,分發做了字典里面類型標記的Event實例給對應的處理對象;ctpGateway這個通過put把新的event放入queue中。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

囊谦县| 曲松县| 邳州市| 萨嘎县| 凤阳县| 汽车| 谷城县| 增城市| 天津市| 凌云县| 太仆寺旗| 泸定县| 木兰县| 卫辉市| 阿合奇县| 荥阳市| 莱芜市| 万州区| 敦煌市| 温宿县| 外汇| 松原市| 静乐县| 徐汇区| 信阳市| 晋江市| 佳木斯市| 富锦市| 永胜县| 三亚市| 新丰县| 乌兰浩特市| 石河子市| 德格县| 句容市| 甘肃省| 桐柏县| 读书| 江西省| 习水县| 兴和县|