CTP出现4097、8193报错

记录学习CTP出现4097、8193报错,原文参考https://zhuanlan.zhihu.com/p/89263750

追根溯源

在客户端程序与期货公司行情、交易前置建立连接之后,服务器会定时发送心跳包确认连接是否正常。当网络连接出现异常,客户端可以在回调函数OnFrontDisconnected中收到通知:

///当客户端与交易后台通信连接断开时,该方法被调用。当发生这个情况后,API会自动重新连接,客户端可不做处理。
///@param nReason 错误原因
/// 0x1001 网络读失败 4097
/// 0x1002 网络写失败 4098
/// 0x2001 接收心跳超时 8193
/// 0x2002 发送心跳失败 8194
/// 0x2003 收到错误报文 8195
void OnFrontDisconnected(int nReason) {};

交易者最常遇到的就是4097(十六进制:0x1001)和8193(十六进制:0x2001)报错。

如果网络异常,很容易发现问题。

但是初次使用CTP的交易者会发现,在网络正常情况下,也会报这个错误。究竟是哪里出了问题呢?

其实,这是不熟悉CTP异步执行特性导致的。

CTP所有的方法都是异步执行的,也就是说,调用一个方法返回时,该方法并没有执行完成,而是刚开始执行。如果主线程没有等待子线程执行完成就结束了,会触发OnFrontDisconnected错误。

网络正常情况下使用AlgoPlus重现该问题

from AlgoPlus.CTP.MdApi import MdApi


class TickEngine(MdApi):
    #5-8行
    # def __init__(self, md_server, broker_id, investor_id, password, app_id, auth_code
    #              , instrument_id_list, md_queue_list=None
    #              , page_dir='', using_udp=False, multicast=False):
    #     self.Join()

    # ///深度行情通知
    def OnRtnDepthMarketData(self, pDepthMarketData):
        print(pDepthMarketData)


if __name__ == '__main__':
    import sys
    sys.path.append("..")

    from account_info import my_future_account_info_dict

    future_account = my_future_account_info_dict['SimNow']
    tick_engine = TickEngine(future_account.server_dict['MDServer']
                             , future_account.broker_id
                             , future_account.investor_id
                             , future_account.password
                             , future_account.app_id
                             , future_account.auth_code
                             , future_account.instrument_id_list
                             , None
                             , future_account.md_page_dir)

# 30行
# tick_engine.Join()

网络正常情况下的解决方案

解决办法很简单,就是在主线程结束之前调用Join方法,等待子线程执行。

将以上5-8行代码的注释取消,或者在30行之后调用tick_engine的Join方法,就正常了。

网络异常情况下的解决方案

无需做其他处理,等待CTP自动重连,重连成功后自动登录账户,然后就可以正常使用了。

MdApi同样会自动重连,且重连成功后自动登录账户,但是需要重新订阅行情,否则不会收到断开前订阅的行情数据。

AlgoPlus已封装了MdApi重连成功时订阅合约的功能。