VNPY使用一個方法處理多個事件EVENT,來計算期貨單個合約資金比率

張國平發表於2021-11-08

最近想到個需求,針對期貨CTP介面,比如持有三個合約,每個合約佔用的資金比率。


這個需求分解下,就是資金佔用,這個在期貨中就是保證金金額。

在CTP介面中,OnRspQryTradingAccount 方法是返回查詢賬戶資金資訊,可以返回賬號總保證金金額。

而onRspQryInvestorPosition方法是返回查詢持倉情況,持倉情況包括對應合約的保證金金額,這裡要注意的地方是,CTP 系統將持倉明細記錄按合約,持倉方向,開倉日期(針對上期所,區分昨倉、今倉)進行彙總,而vnpy是隻區分合約和合約方向,vnpy會將不同開倉時間返回的進行二次彙總。


這裡處理流程就和明確了,首先增強PositionData和 AccountData 這兩個資料類,加入保證金屬性;然後增強ctp_gateway的對應方法中獲取保證金資料;這兩步比較簡單,程式碼略。

第三步增強倉位報表PositionMonitor,增加保證金相關header資料列。然後除了預設的“EVENT_POSITION”, 還要訂閱註冊“EVENT_ACCOUNT",這裡要重寫父類方法regist_event;其實vnpy中事件註冊時多對多關係,一個方法可以處理多個事件,雖然預設不鼓勵。

def register_event(self):
    super(PositionMonitor,self).register_event()
    if self.event_type_account:
        self.signal.connect(self.process_event)
        self.event_engine.register(self.event_type_account, self.signal.emit)


然後複寫父類方法process_event,來處理這兩個事件,如果是Account事件,就更新總保證金資料,如果是合約事件,就計算對應保證金金額和總保證金百分比。

def process_event(self, event: Event) -> None:
    """
    Process new data from event and update into table.
    """
    # Disable sorting to prevent unwanted error.
    if self.sorting:
        self.setSortingEnabled(False)
    # Update data into table.
    if event.type == self.event_type_account:
        self.total_margin = event.data.CurrMargin
    else:
        data = event.data
        if self.total_margin!=0:
            data.useMarginRate = '{:.2%}'.format(data.useMargin/self.total_margin)
        if not self.data_key:
            self.insert_new_row(data)
        else:
            key = data.__getattribute__(self.data_key)
            if key in self.cells:
                self.update_old_row(data)
            else:
                self.insert_new_row(data)
        # Enable sorting
        if self.sorting:
            self.setSortingEnabled(True)


其實修改邏輯很簡單,就是一個方法處理多個事件要考慮下。實現效果如下圖:

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

相關文章