1. 程式人生 > >python CTP 8193 心跳超時程式崩潰解決方法——8193錯誤

python CTP 8193 心跳超時程式崩潰解決方法——8193錯誤

終於,終於,終於!!!!

博主千辛萬苦把CTP 8193心跳超時導致程式崩潰的問題解決了!!!!!經歷了一天一夜的測試後,第二天親眼看到CTP返回了8193錯誤後,我的程式沒有崩潰!第二天早上9:00一到,又自己正常運行了。敲開心~~~

博主的血淚史,就是搜遍國內外全網,不止博主一個人遇到8193後程序崩潰,但只有提問8193錯誤的,沒有一個回答8193錯誤的解決方法。所以博主就決定了,一旦等到博主解決8193錯誤那一日,就一定要把解決方法公諸於世!

先說一說博主的8193錯誤導致崩潰的原因。

眾所周知,8193錯誤就是CTP當中的,一旦引發,ctp就會呼叫回撥函式“onFrontDisconnected”,返回錯誤碼(目前博主見得最多的就是4097和8193)。

這個時候根據上期所官方CTP_API介面原文,API會自動重新連線,客戶端理論上可以不做任何處理。

但是!!博主要說,這邊所謂的不做處理,是指不用做任何重新連線前置機的處理。

CTP雖然會幫我們自動重連前置機(前提是,你之前註冊的前置列表裡的前置機可以連線得上,註冊多個前置機方法詳見博主的另外一篇文章:https://blog.csdn.net/mooncrystal123/article/details/83269296),但是CTP不會幫我們重新登入!

然而,CTP的業務API必須要登陸後才能使用!登入後才能使用!!登陸後才能使用!!!

重要的事情說三遍。

業務API就是下單啊,查詢賬戶餘額啊,查詢市場最新tick行情啊等等等…………

所以博主的崩潰來自於兩個方面

1. 前期

只註冊了一個前置機,前置機壞掉後,無法重連,導致下單查詢的業務執行緒無法獲得必須的返回結果屬性,導致後續業務邏輯報attributeError失敗,崩潰。

2. 後期

註冊了一堆前置機,但是重連後沒登入,導致業務邏輯執行緒進入死迴圈,執行緒無法自動停止。

註冊了一堆前置機,但是登陸方法寫在了CTP的回撥函式當中,然後登陸失敗,導致程式崩潰。

 

所以,綜上所述,博主經過多番實驗找到了辦法。

首先,最重要的就是在回撥函式中不加任何重新登入的方法,只負責列印或者記錄CTP斷連後onFrontDisconnected返回的錯誤碼,然後等待CTP自動重連,重連成功後CTP會呼叫onFrontConnected。

注:self.logoutCode是博主自設的用來鑑別是手動登出時導致的斷連還是CTP自身原因導致的斷連。

    def onFrontDisconnected(self,n):
        # n的type是int
        print(n)
        # 手動登出
        if self.logoutCode == 1:
            self.onFrontDisconnectedCode = 0
        else:
            self.onFrontDisconnectedCode = n
    def onFrontConnected(self):
        """伺服器連線"""
        print("onFrontDisconnectedCode: " + str(self.onFrontDisconnectedCode))

CTP呼叫回撥函式的時候,會自動開啟一個新執行緒來處理,我們稱之為A執行緒。

然後,我們要做的就是把重新登入的方法寫在我們程式執行的執行緒裡面,預設就是B執行緒。

下面就是我自己封裝的CTP類的斷連檢查+重新登入的方法。

# 斷連狀態檢查:給所有的業務類方法前加上去
    def reloginCheck(self):
        stat = 0
        # 檢視前置機是不是自己斷連過
        if self.api.onFrontDisconnectedCode != 0:
            loginReq = {}  # 建立一個空字典
            loginReq['UserID'] = self.userid
            loginReq['Password'] = self.password
            # loginReq['BrokerID'] = '9999'
            loginReq['BrokerID'] = self.brokerid
            self.reqid = self.reqid + 1  # 請求數必須保持唯一性
            self.api.reqUserLogin(loginReq, self.reqid)
            sleep(1)
            if hasattr(self.api,'loginErrorID'):
                if self.api.loginErrorID == 0:
                    stat = 1
        # 前置機沒有斷連過
        else:
            stat = 1
        print('relogstat: '+str(stat))
        return stat

這個方法在業務邏輯中插入的位置:


# 判斷simnow是否開啟
if simnowStat == 1:
    frontStat = sarProjectTest.Api.reloginCheck()
    # 檢查CTP是否斷連
    if frontStat == 1:
        while optSuccess == 0:
            sarProjectTest.Api.BuyOpen(self.id, num)
            orderResult = self.ordertools.orderInsertJudge(sarProjectTest.Api.api,num,1)
            optSuccess = orderResult['optSuccess']
            if optSuccess == 0:
                print('下單失敗')
                self.apptools.logGenerate('買開下單失敗')
# 未開啟simnow
    else:
        optSuccess = 1
--------------------- 
作者:mooncrystal123 
來源:CSDN 
原文:https://blog.csdn.net/mooncrystal123/article/details/83269296 
版權宣告:本文為博主原創文章,轉載請附上博文連結!

通過這樣的處理,即使CTP報8193或者4097,我們的程式也不會崩潰,可以等待CTP重連。

一般來說,CTP前置機最不穩定的時間為傍晚4:30-7:00,這段時間是各方前置機維護關機時段,如果程式要過夜的話,這段時間不能因為CTP前置機不穩定而宕機是最關鍵的。

 

好啦,今日份的分享完畢~~