刚接触CTP开发,博主用的是VNPY的接口和simnow的仿真账户,用的是python开发。
有时会出现simnow的前置机中途宕机的情况,然后程序就崩溃了。一直在找更换前置机重连的方法,现在找到了,就是在一开始init()之前,同时注册很多个前置机,这样,init()之后,ctp会自己找一个最快的,宕机重连后,ctp会在我们之前注册的一系列前置机中逐个尝试重连。
以下是博主自己再封装的ctp类的登录方法,因为登录后起始要确认结算单,才可以下单,所以我也封在里面了。其中那段循环就是同时注册很多个前置机。
def Login(self):
i = 0
stat = 1
self.reqid = 0
# 在C++环境中创建MdApi对象,传入参数是希望用来保存.con文件的地址,测试通过
self.api.createFtdcTraderApi("")
# 设置数据流重传方式,测试通过,私有通讯方式
self.api.subscribePrivateTopic(2)
self.api.subscribePublicTopic(2)
# 注册前置机地址,测试通过
for i in range(len(self.registFront)):
self.api.registerFront(self.registFront[i])
# 初始化api,连接前置机,测试通过
self.api.init()
sleep(1)
# # 登陆,测试通过,如果如果心跳超时就不会是0而是8193,8193下会自动登录
if self.api.onFrontDisconnectedCode == 0:
loginReq = {} # 创建一个空字典
# loginReq['UserID'] = '' # 参数作为字典键值的方式传入
loginReq['UserID'] = self.userid
# loginReq['Password'] = '' # 键名和C++中的结构体成员名对应
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:
self.SettlementInfoConfirm()
return stat
接下来的博主还不肯定,但是问过其他开发人员,基本是这样操作的:
断连后再登录新的前置机后,应该要重新登录才可以,也就是说,在回调函数onFrontConnected里面加入断连后重新登录的判断,是否断连可以从onFrontDistconnected函数里面返回的n判断。
以下是博主自己在回调函数里写的方法,大家可以拿来参考:
def onFrontDisconnected(self,n):
print(n)
# n = 8193
# 登出状态
if self.logoutCode == 1:
self.onFrontDisconnectedCode = 0
else:
self.onFrontDisconnectedCode = n
# 如果不是手动退出,那么就先登出
if self.onFrontDisconnectedCode != 0:
self.errorLogOut()
def errorLogOut(self):
logoutReq = {}
logoutReq['BrokerID'] = self.brokerID
logoutReq['UserID'] = self.userID
self.reqid = self.reqid + 1
self.reqUserLogout(logoutReq,self.reqid)
sleep(1)
def onFrontConnected(self):
"""服务器连接"""
if self.onFrontDisconnectedCode != 0:
# 重新登录
self.auotoLogin()
print('relogin')
def auotoLogin(self):
loginReq = {}
loginReq['UserID'] = self.userID
loginReq['Password'] = self.password
loginReq['BrokerID'] = self.brokerID
self.reqid = self.reqid + 1
self.reqUserLogin(loginReq,self.reqid)
sleep(1)
其中的self.onFrontDisconnectedCode 是我自己封装的logout函数中赋值的,也就是自己主动登出的时候,不会再次重连。
def logOut(self,userID,borkerID):
logoutReq = {}
logoutReq['BrokerID'] = borkerID
logoutReq["UserID"] = userID
self.reqid = self.reqid + 1
# 传递登出状态
self.api.logoutCode = 1
#
self.api.reqUserLogout(logoutReq, self.reqid)
sleep(1)
我是从这个帖子里获得启发的: