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前置机不稳定而宕机是最关键的。

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

猜你喜欢

转载自blog.csdn.net/mooncrystal123/article/details/83894659