VeighNa量化社区
你的开源社区量化交易平台
Member
avatar
加入于:
帖子: 419
声望: 164

网关接口的状态感知

1 行情和交易服务器的接口状态

网关分很多种,如CTP,XTP等 。其中CTP中又包含行情(MD)接口和交易(TD)接口。它们在连接和断开的时候,都有推送接口。这些接口是:
MD的onFrontConnected()和onFrontDisconnected(),TD的onFrontConnected()和onFrontDisconnected()。行情和交易服务器的接口状态,vnpy已经做了log输出,用户是可以阅读的,可是不方便软件使用,于是对接口和主引擎做了如下修改,以便于上层应用可以使用这些消息,编写出针对行情服务器通断情况的处理方法,也可以编写针对交易服务器连接的处理方法。

2 实现步骤

下面的代码修改时,需要相互引用的部分,如from... import... 之类的,就不再逐一指出了,太基础了。

2.1 在vnpy\trader\event.py添加如下消息类型:

EVENT_CONNECT = "eConnected"             # hxxjava add
EVENT_DISCONNECT = "eDisconnected"   # hxxjava add

2.2 在vnpy\trader\object.py添加如下数据类型:

@dataclass
class GatewayData():     # hxxjava add
    """
    Gateway data
    """
    name:str = ""     # 网关名称,如 'CTP'
    type:str = ""     # 接口类型,如 'TD','MD'
    reason:int = 0      # 状态或者原因

2.3 在vnpy\trader\gateway.py 中为BaseGateway添加如下函数:

    def on_connect(self,gateway:GatewayData) -> None:    # hxxjava add   
        """
        gateway connect enent
        """
        self.on_event(EVENT_CONNECT, gateway)

    def on_disconnect(self,gateway:GatewayData) -> None:    # hxxjava add   
        """
        gateway disconnect enent
        """
        self.on_event(EVENT_DISCONNECT, gateway)

2.4 在vnpy\app\ctp\ctp_gateway.py 中修改如下4个函数:

1 CtpMdApi类的两个函数:

    def onFrontConnected(self):
        """
        Callback when front server is connected.
        """
        self.gateway.on_connect(GatewayData("CTP",'MD'))    # hxxjava add

        self.gateway.write_log("行情服务器连接成功")
        self.login()

    def onFrontDisconnected(self, reason: int):
        """
        Callback when front server is disconnected.
        """
        self.login_status = False
        self.gateway.on_disconnect(GatewayData(name="CTP",type='MD',reason=reason)) # hxxjava add
        self.gateway.write_log(f"行情服务器连接断开,原因{reason}")

2 CtpTdApi类的两个函数:

    def onFrontConnected(self):
        """"""
        self.gateway.on_connect(GatewayData("CTP",'TD')) # hxxjava add
        self.gateway.write_log("交易服务器连接成功")

        if self.auth_code:
            self.authenticate()
        else:
            self.login()

    def onFrontDisconnected(self, reason: int):
        """"""
        self.login_status = False
        self.gateway.on_disconnect(GatewayData(name="CTP",type='TD',reason=reason)) # hxxjava add
        self.gateway.write_log(f"交易服务器连接断开,原因{reason}")

2.5 修改vnpy\trader\engine.py中的主引擎MainEngine

修改register_event()函数:

    def register_event(self):
        ... ...
        # 添加下面两句 
        self.event_engine.register(EVENT_CONNECT, self.process_connect_event)
        self.event_engine.register(EVENT_DISCONNECT, self.process_disconnect_event)

添加下面两个消息处理函数:

    def process_connect_event(self, event: Event) -> None:
        gateway:GatewayData = event.data
        print(f"gateway connect event {gateway}")

    def process_disconnect_event(self, event: Event) -> None:
        gateway:GatewayData = event.data
        print(f"gateway disconnect_event {gateway}")

3 如何测试

在VN Studio Prompt窗口输入python - m vnstation命令,启动vnpy系统后,选择连接CTP接口,输入用户名和密码等信息后,连接CTP网关后可以在VN Studio Prompt窗口见到如下:

gateway connect event GatewayData(name='CTP', type='TD', reason=0)
gateway connect event GatewayData(name='CTP', type='MD', reason=0)

当然你也可以制造一下CTP网关的故障,如故意拔掉你的路由器的电,或者网线,你应该可以看到

gateway disconnect event GatewayData(name='CTP', type='TD', reason=?)   
gateway disconnect event GatewayData(name='CTP', type='MD', reason=?)

上面使用问号,是因为我不知道你软件会提示什么错误原因。

Member
avatar
加入于:
帖子: 42
声望: 4

看了楼主几个帖子,感觉为vnpy做了很多非常有价值的缺憾补全,同时也难以想象,一个发展多年的框架居然连这些最基础的东西都还需要用户来做补充。想当年写个简单的通信库,这些都是首要考虑的功能。

Member
avatar
加入于:
帖子: 5
声望: 0

很好的想法,更简单的方法是在EVENT_LOG的处理函数里面同时把信息也打印出来,这样同时在log file和 窗口都有输出。

Member
avatar
加入于:
帖子: 126
声望: 13

远山 wrote:

看了楼主几个帖子,感觉为vnpy做了很多非常有价值的缺憾补全,同时也难以想象,一个发展多年的框架居然连这些最基础的东西都还需要用户来做补充。想当年写个简单的通信库,这些都是首要考虑的功能。

很多时候跟你有相同的感触。

Member
加入于:
帖子: 12
声望: 0

我個人是寫一個watch_dog的app。只要timeout就把所有gateway重啟

Member
加入于:
帖子: 12
声望: 0

VNPY真的太陽春了。而且內定綁死RQDATA。對於國外用戶根本是個超大障礙!
我卡在RQDATA這邊卡好久

Member
avatar
加入于:
帖子: 8
声望: 0

jerrychen wrote:

我個人是寫一個watch_dog的app。只要timeout就把所有gateway重啟

能否分享一下这个功能,因为ctp经常隔夜断联,需要重新连接!你的重启是在引擎里重启?

Member
avatar
加入于:
帖子: 419
声望: 164

jerrychen wrote:

VNPY真的太陽春了。而且內定綁死RQDATA。對於國外用戶根本是個超大障礙!
我卡在RQDATA這邊卡好久

vnpy可以提供多种DataFeed的选择,例如:

Member
avatar
加入于:
帖子: 419
声望: 164

少林寺猫猫 wrote:

jerrychen wrote:

我個人是寫一個watch_dog的app。只要timeout就把所有gateway重啟

能否分享一下这个功能,因为ctp经常隔夜断联,需要重新连接!你的重启是在引擎里重启?

方法有二:

  1. 可以通过一楼帖子中MdAPI和TdAPI的onFrontConnected()和 onFrontDisconnected()感知连接的通断,在CtpGateway内部实现断开后的自动重连
  2. 可以用脚本定时启动整个系统和策略,再定时关闭策略和系统,只在交易时段才启动和连接网关,这样也是比较可靠的做法。
Member
avatar
加入于:
帖子: 8
声望: 0

hxxjava wrote:

少林寺猫猫 wrote:

jerrychen wrote:

我個人是寫一個watch_dog的app。只要timeout就把所有gateway重啟

能否分享一下这个功能,因为ctp经常隔夜断联,需要重新连接!你的重启是在引擎里重启?

方法有二:

  1. 可以通过一楼帖子中MdAPI和TdAPI的onFrontConnected()和 onFrontDisconnected()感知连接的通断,在CtpGateway内部实现断开后的自动重连
  2. 可以用脚本定时启动整个系统和策略,再定时关闭策略和系统,只在交易时段才启动和连接网关,这样也是比较可靠的做法。

老师您好,感谢回复。
我之前用了老师您提供的条件单功能,但是因为隔夜CTP断联,我不得不重启策略和系统重新链接CTP,但是重启系统导致系统中原有 “等待中的条件单”会消失,才发现等待中的条件单没有保存到本地。
一、我尝试给条件单增加一个本地储存的功能,修改很多次代码还是有异常,放弃增加本地储存的功能。
二、我再尝试在CtpGateway内部增加一个临近开盘前重连的动作,这还得请教老师能否提供在CtpGateway内部实现断开后临近开盘前自动重连的方法,以达到相对无人值守以及顺便也能解决了条件单消失的问题。

Member
avatar
加入于:
帖子: 419
声望: 164

答复:

  1. 其实vnpy系统中自带的本地停止单和我的条件单一样都是运行在内存中的,只要一关机就没有了。
  2. 如果希望再次启动系统,运行策略,还能再次调出停止单和条件单,需要比较复杂的设计。因为要启动旧的条件单,就必须再次初始化、启动其所关联的策略,而这个时间是不受条件单控制的。
  3. 要实现这样的要求也是可以的,需要比较周全的考虑,等我有时间了再设计一个可以缓存、重新加载和鉴别条件单是否有效的恢复条件单功能,当然此功能也对本地停止单有效。
Member
avatar
加入于:
帖子: 8
声望: 0

hxxjava wrote:

答复:

  1. 其实vnpy系统中自带的本地停止单和我的条件单一样都是运行在内存中的,只要一关机就没有了。
  2. 如果希望再次启动系统,运行策略,还能再次调出停止单和条件单,需要比较复杂的设计。因为要启动旧的条件单,就必须再次初始化、启动其所关联的策略,而这个时间是不受条件单控制的。
  3. 要实现这样的要求也是可以的,需要比较周全的考虑,等我有时间了再设计一个可以缓存、重新加载和鉴别条件单是否有效的恢复条件单功能,当然此功能也对本地停止单有效。

感谢老师回复

因为我发现交易服务器在收盘后会不稳定,在收盘时间内ctpgateway有机率出现连入交易服务器成功,但卡死在登入交易服务器的步骤。从而出现早上开盘前ctpgateway无法自动重连并登入交易服务器。
目前我找到的解决方案是 晚上收盘后就立马用防火墙把python(ctpgateway)的访问网络的权限关闭掉。等开盘前10分钟再打开访问网络的权限。就规避了ctpgateway在不稳定时间出现上述连入服务器无法登录进而卡死的情况。也就不用重启策略和系统,条件单也不会消失了。
当然这个解决方案还没经过长时间的实践,可能还会存在一些奇怪的问题。

Member
avatar
加入于:
帖子: 6
声望: 1

hxxjava wrote:

答复:

  1. 其实vnpy系统中自带的本地停止单和我的条件单一样都是运行在内存中的,只要一关机就没有了。
  2. 如果希望再次启动系统,运行策略,还能再次调出停止单和条件单,需要比较复杂的设计。因为要启动旧的条件单,就必须再次初始化、启动其所关联的策略,而这个时间是不受条件单控制的。
  3. 要实现这样的要求也是可以的,需要比较周全的考虑,等我有时间了再设计一个可以缓存、重新加载和鉴别条件单是否有效的恢复条件单功能,当然此功能也对本地停止单有效。

还不如由策略那边去处理,相对来说会更简单一些,策略检测一下没有挂单,重新进行挂单就是了。

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】