vnpy源码阅读学习(5):关于MainEngine的代码阅读

在入口文件中,我们看到了除了窗体界面的产生,还有关于 MainEngineEventEngin部分。今天来学习下 MainEngine的代码。

首先在run代码中,我们看到以下的代码

main_engine.add_gateway(DeribitGateway)
main_engine.add_app(OptionMasterApp)

从上述代码可以基本猜测所有的网管,设置,甚至策略引擎行情,都跟MainEngine有关系,MainEngine应该是一个主线,把所有的组件穿插起来了。想必MainEngine一定是一条重要的大鱼。下面我们进入MainEngin开始学习 位置: \vnpy\trader\engine.py

MainEngine的大概脉络

class MainEngine:

    #初始化
    def __init__(self, event_engine: EventEngine = None):
        pass

    #添加引擎
    def add_engine(self, engine_class: Any):
        pass
    #添加网管
    def add_gateway(self, gateway_class: Type[BaseGateway]):
        pass

    #添加app
    def add_app(self, app_class: Type[BaseApp]):
        pass

    #初始化引擎
    def init_engines(self):
        pass

    #写入日志
    def write_log(self, msg: str, source: str = ""):
        pass

    #获得引擎
    def get_engine(self, engine_name: str):
        pass
    #获得默认设置
    def get_default_setting(self, gateway_name: str):
        pass

    #获得所有引擎的名字
    def get_all_gateway_names(self):
        pass
    #获得所有的APP
    def get_all_apps(self):
        pass
    #获得所有的交易所
    def get_all_exchanges(self):
        pass
    #连接到行情
    def connect(self, setting: dict, gateway_name: str):
        pass

    #合约订阅
    def subscribe(self, req: SubscribeRequest, gateway_name: str):
        pass

    #下单
    def send_order(self, req: OrderRequest, gateway_name: str):
        pass

    #取消订单
    def cancel_order(self, req: CancelRequest, gateway_name: str):
        pass

    #批量下单
    def send_orders(self, reqs: Sequence[OrderRequest], gateway_name: str):
        pass

    #批量取消订单
    def cancel_orders(self, reqs: Sequence[CancelRequest], gateway_name: str):
        pass

    #历史查询
    def query_history(self, req: HistoryRequest, gateway_name: str):
        pass

    #关闭
    def close(self):
        pass

我把所有的方法体都去掉,仅仅保留方法名称和参数,从上面的结构基本上能看出来 MainEngine几乎是一个把各个组件(GateWay, App, Engin)都连接在一起,同时提供了跟交易相关的连接、订阅、下单、撤单、历史记录等都相关的柔和在一起的大杂烩。接下来我们就一个一个方法的阅读学习。

__init__

    def __init__(self, event_engine: EventEngine = None):
""""""
        if event_engine:
            self.event_engine = event_engine
        else:
            self.event_engine = EventEngine()
        self.event_engine.start()

        self.gateways = {}
        self.engines = {}
        self.apps = {}
        self.exchanges = []

        os.chdir(TRADER_DIR)    # Change working directory
        self.init_engines()     # Initialize function engines

初始化的代码基本上就是实例化事件引擎(EventEngin),然后启动,同时为 getways, engines, apps, exchange建立一个字典,同时调用init_engines()的方法。

各种add方法,AddEngine, AddGateWay, AddApp

    def add_engine(self, engine_class: Any):
"""
        Add function engine.

"""
        engine = engine_class(self, self.event_engine)
        self.engines[engine.engine_name] = engine
        return engine

    def add_gateway(self, gateway_class: Type[BaseGateway]):
"""
        Add gateway.

"""
        gateway = gateway_class(self.event_engine)
        self.gateways[gateway.gateway_name] = gateway

        # Add gateway supported exchanges into engine
        for exchange in gateway.exchanges:
            if exchange not in self.exchanges:
                self.exchanges.append(exchange)

        return gateway

    def add_app(self, app_class: Type[BaseApp]):
"""
        Add app.

"""
        app = app_class()
        self.apps[app.app_name] = app

        engine = self.add_engine(app.engine_class)
        return engine

上述3个Add方法比较简单,基本上都是把添加各种APP、Engine、Gateway的话,都把它们的实例化和name形成键值对放入map中去。唯一我们可以得到的线索是gateway 和Exchanges之间应该是有对应关系的话,话一句话说,gateway就是交易场所的API对接网管。所以每次添加一个gateway,就添加了一个交易所名称。

    def get_gateway(self, gateway_name: str):
"""
        Return gateway object by name.

"""
        gateway = self.gateways.get(gateway_name, None)
        if not gateway:
            self.write_log(f"找不到底层接口:{gateway_name}")
        return gateway

    def get_engine(self, engine_name: str):
"""
        Return engine object by name.

"""
        engine = self.engines.get(engine_name, None)
        if not engine:
            self.write_log(f"找不到引擎:{engine_name}")
        return engine

    def get_default_setting(self, gateway_name: str):
"""
        Get default setting dict of a specific gateway.

"""
        gateway = self.get_gateway(gateway_name)
        if gateway:
            return gateway.get_default_setting()
        return None

基本上是从map中根据指定的名字获得对象的方法。一目了然。 get_default_setting方法应该属于get_gateway的一个下属方法,获得gateway的setting.

get_all方法

    def get_all_apps(self):
"""
        Get all app objects.

"""
        return list(self.apps.values())

    def get_all_exchanges(self):
"""
        Get all exchanges.

"""
        return self.exchanges

也是对add进入的对象进行全局获取的方法。

connect

    def connect(self, setting: dict, gateway_name: str):
"""
        Start connection of a specific gateway.

"""
        gateway = self.get_gateway(gateway_name)
        if gateway:
            gateway.connect(setting)

基本上可以理解connect是对gateway的一种装饰方法。通过add可以插入gateway,然后调用connect方法的话,可以通过gateway_name获得接口,然后再调用gateway的connect方法。不出意料下面的订阅行情、下单、撤单、批量撤单都是类似的作用。

gateway的其他类似方法

    def subscribe(self, req: SubscribeRequest, gateway_name: str):
"""
        Subscribe tick data update of a specific gateway.

"""
        gateway = self.get_gateway(gateway_name)
        if gateway:
            gateway.subscribe(req)

    def send_order(self, req: OrderRequest, gateway_name: str):
"""
        Send new order request to a specific gateway.

"""
        gateway = self.get_gateway(gateway_name)
        if gateway:
            return gateway.send_order(req)
        else:
            return ""

    def cancel_order(self, req: CancelRequest, gateway_name: str):
"""
        Send cancel order request to a specific gateway.

"""
        gateway = self.get_gateway(gateway_name)
        if gateway:
            gateway.cancel_order(req)

    def send_orders(self, reqs: Sequence[OrderRequest], gateway_name: str):
"""
"""
        gateway = self.get_gateway(gateway_name)
        if gateway:
            return gateway.send_orders(reqs)
        else:
            return ["" for req in reqs]

    def cancel_orders(self, reqs: Sequence[CancelRequest], gateway_name: str):
"""
"""
        gateway = self.get_gateway(gateway_name)
        if gateway:
            gateway.cancel_orders(reqs)

    def query_history(self, req: HistoryRequest, gateway_name: str):
"""
        Send cancel order request to a specific gateway.

"""
        gateway = self.get_gateway(gateway_name)
        if gateway:
            return gateway.query_history(req)
        else:
            return None

init_engine

    def init_engines(self):
"""
        Init all engines.

"""
        self.add_engine(LogEngine)
        self.add_engine(OmsEngine)
        self.add_engine(EmailEngine)

把日志, OMSEngin, EmialEngin装配进来

close 方法

 def close(self):
"""
        Make sure every gateway and app is closed properly before
        programme exit.

"""
        # Stop event engine first to prevent new timer event.

        self.event_engine.stop()

        for engine in self.engines.values():
            engine.close()

        for gateway in self.gateways.values():
            gateway.close()

基本上是程序退出以后的善后工作罢了。

通过对MainEngin代码的梳理,我们看到其实MainEngine本身没有什么深奥之处。就是一个适配器的模式,把所有的操作抽象成了APP,Gateway, Engine。并且提供了一个统一的操作入口,这样可以方便实现扩展。

Original: https://www.cnblogs.com/bbird/p/12237637.html
Author: bbird2018
Title: vnpy源码阅读学习(5):关于MainEngine的代码阅读

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/685133/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • window三种程序自启动方式

    原文:https://blog.csdn.net/qq_41538097/article/details/106498966 大家可能会有一些需求,想要开机自启动一些项目程序之类,…

    技术杂谈 2023年5月31日
    0102
  • PYTORCH: 60分钟 | TORCH.AUTOGRAD

    torch.autograd 是PyTorch的自动微分引擎,用以推动神经网络训练。在本节,你将会对autograd如何帮助神经网络训练的概念有所理解。 背景 神经网络(NNs)是…

    技术杂谈 2023年7月25日
    0117
  • 基于cefsharp的用户浏览器

    一、前言 使用cefSharp制作浏览器主要是一些页面无法通过自己的接口去控制,又不可能通过第三方去解决的时候,只能通过自己做的浏览器去分析界面,然后给出响应. 例如: xx的网页…

    技术杂谈 2023年5月31日
    0107
  • 论文中如何描述系统

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/hxsyl/p/6512794.htmlAuthor: …

    技术杂谈 2023年5月31日
    0110
  • 苞米面Paddle助手介绍

    自己用的百度飞桨 Paddle,PaddleX 项目模板和小工具。My Paddle PaddleX project templates. 适用系统 一些脚本使用 shell 编写…

    技术杂谈 2023年7月23日
    0102
  • tcpip详解-读书笔记

    TCP/IP详解 卷一 第一版读书笔记 第一章: 应用层关心是应用程序的细节,而不是数据在网络中对的传输活动,下三层对应用程序一无所知,但他们要处理所有的通信细节。 七层代理可以根…

    技术杂谈 2023年7月11日
    0145
  • 递归

    总结: 递归是一个思想,自己调用自己的一个过程 要点: 分析: 3.书写递归就是 ​ 找出什么时候不再 调用自己本身的条件 和 书写需要循环执行的代码 代码需要逻辑严密 4.注意事…

    技术杂谈 2023年6月21日
    0108
  • NAS私人云盘

    https://cloudreve.org/ Cloudreve 可助你即刻构建出兼备自用或公用的网盘服务,通过多种存储策略的支持、虚拟文件系统等特性实现灵活的文件管理体验。 部署…

    技术杂谈 2023年5月31日
    0110
  • 应用程序现代化权威指南

    什么是应用程序现代化 简单来说,软件现代化、老旧系统现代化或老旧应用现代化都是指替换或升级旧软件的过程。根据系统的情况和公司的情况,对软件进行现代化改造的方案从轻微修改到完全更换都…

    技术杂谈 2023年6月21日
    0110
  • 记一次base64转MultipartFile的坑

    记一次base64转MultipartFile的坑 现在有个需求是接收base64编码的图片,然后上传到文件服务器上,由于文件服务的代码是固定的代码不能修改,所以只能适配接口。文件…

    技术杂谈 2023年7月25日
    080
  • Launch Shopify主题模板设置修改

    Launch是Kickstarter风格的Shopify主题,旨在将初创公司变成成功的商店。展示细节并讲述您的产品故事。支持OS 2.0,适合‎健康与美容, 家庭与园艺, 运动与休…

    技术杂谈 2023年5月30日
    0115
  • 良好的API接口

    挑战 API是软件系统的核心,而我们在设计API接口的时候会面临着非常多的挑战: 场景上来看,它是多样的,如何设计一个随处适用的API? 我们所参与的业务不断演进的,如何设计一个有…

    技术杂谈 2023年5月31日
    098
  • 为指定的XML文件生成类并反序列化

    webservice的那种不说了,vs会自动生成客户端访问的类, 遇到这样一种情况:XML已知,要你处理 读取到DataSet里后发现不成,XML是多级的,根,子节点,子子节点,子…

    技术杂谈 2023年6月1日
    0124
  • springboot应用中使用CommandLineRunner

    在springboot应用中,存在这样的使用场景,在springboot ioc容器创建好之后根据业务需求先执行一些操作,springboot提供了两个接口可以实现该功能: Com…

    技术杂谈 2023年7月11日
    097
  • 部署-docker资源踩坑

    docker资源踩坑 博主在自己的电脑上,使用docker运行gitlab镜像的时候,发现docker命令失去了响应。但是根据网上的资料显示,gitlab最低配置只需要2核,4GB…

    技术杂谈 2023年7月23日
    080
  • 给王心凌打Call的,原来是神奇的智能湖仓

    图文原创:谭婧(王❤凌老粉) “爷青回” “我们只是老了,并没有死。” 谭老师作为老粉,热烈庆祝”甜心教主”…

    技术杂谈 2023年5月31日
    085
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球