vn.py source interpretation (V. main engine code analysis module ---- CTP)

        On an article about the initialization function MainEngine the focus is DataEngine explanation. With the processing of market data, but also need to have sources of market data. In the back of the initialization function MainEngine of a function is addGateway function. vnpy authors have a lot of pattern, hope that their work can be compatible with a lot of data transaction interface, so it is more common here ctp put this kind of interface, called Gateway, and later to write more complex, the purpose is to integrate, or very admirable. Here we have to analyze the data transaction interface here is how to hang on MainEngine, and how it works.

1.addGateway

    def addGateway(self, gatewayModule):
        """添加底层接口"""
        gatewayName = gatewayModule.gatewayName
        
        # 创建接口实例
        self.gatewayDict[gatewayName] = gatewayModule.gatewayClass(self.eventEngine, 
                                                                   gatewayName)
        
        # 设置接口轮询
        if gatewayModule.gatewayQryEnabled:
            self.gatewayDict[gatewayName].setQryEnabled(gatewayModule.gatewayQryEnabled)
                
        # 保存接口详细信息
        d = {
            'gatewayName': gatewayModule.gatewayName,
            'gatewayDisplayName': gatewayModule.gatewayDisplayName,
            'gatewayType': gatewayModule.gatewayType
        }
        self.gatewayDetailList.append(d)

        This method is very simple, it is easy, in the beginning of the name is called to get a gatewayModule then instantiate an interface through which gatewayModule, then set the polling, and then save the data to an interface for storing a list of interface information .

        Well, then we look at a step by step. First, what is gatewayModule, then this is what is obtained is the interface instance? Polling is how set up?

2.gatewayModule

        Let's review the runCtangTrading code.

me.addGateway(ctpGateway)

        ctpGateway here is the so-called gatewayModule. Here, ctpGateway in fact, is the name of a folder, we all know that in python, a folder below if you have a __init__.py file, then this folder is not a simple folder, but a package while __init__.py file in a sense can be considered an initialization of this package (say here is not particularly accurate, in order to facilitate understanding). So, we find this folder, and open the __init__.py look.

from __future__ import absolute_import
from vnpy.trader import vtConstant
from .ctpGateway import CtpGateway

gatewayClass = CtpGateway
gatewayName = 'CTP'
gatewayDisplayName = 'CTP'
gatewayType = vtConstant.GATEWAYTYPE_FUTURES
gatewayQryEnabled = True

        Here, we know what is passed in the gatewayModule, it means the package.

Example 3. Interface

# 创建接口实例
self.gatewayDict[gatewayName] = gatewayModule.gatewayClass(self.eventEngine, 
                                                                   gatewayName)

        We found that, plus down procedures for the use of our gatewayModule to build an interface instance, to co-exist inside a dictionary. Obviously, gatewayName here is above init file gatewayName, and

gatewayModule.gatewayClass (self.eventEngine, gatewayName), init is actually inside CtpGateway (self.eventEngine, gatewayName), then we look at is how to write this CtpGateway know how this thing is an example of a.

class CtpGateway(VtGateway):
    """CTP接口"""

    #----------------------------------------------------------------------
    def __init__(self, eventEngine, gatewayName='CTP'):
        """Constructor"""
        super(CtpGateway, self).__init__(eventEngine, gatewayName)
        
        self.mdApi = CtpMdApi(self)     # 行情API
        self.tdApi = CtpTdApi(self)     # 交易API
        
        self.mdConnected = False        # 行情API连接状态,登录完成后为True
        self.tdConnected = False        # 交易API连接状态
        
        self.qryEnabled = False         # 循环查询
        
        self.fileName = self.gatewayName + '_connect.json'
        self.filePath = getJsonPath(self.fileName, __file__)       

        First of all, this class inherits from VtGateway, and secondly, we simply look at the initialization function, it is quite easy to understand, and the stock market are initialized ctp Front (MarketFront) and transaction Front (TradeFront), author called the API market and transaction API, can be. Then initialize the address of the control constants and some of ctp ctp profile.

        We do not look at what this class below there are other, we first look at its parent VtGateway it.

class VtGateway(object):
    """交易接口"""

    #----------------------------------------------------------------------
    def __init__(self, eventEngine, gatewayName):
        """Constructor"""
        self.eventEngine = eventEngine
        self.gatewayName = gatewayName

        Nothing special, initialization time, and the name of the event engine to hang. But behind other methods are particularly important.

    def onTick(self, tick):
        """市场行情推送"""
        # 通用事件
        event1 = Event(type_=EVENT_TICK)
        event1.dict_['data'] = tick
        self.eventEngine.put(event1)
        
        # 特定合约代码的事件
        event2 = Event(type_=EVENT_TICK+tick.vtSymbol)
        event2.dict_['data'] = tick
        self.eventEngine.put(event2)

        We look at this onTick method, first of all, this method takes is a tick, and then created two events, one EVENT_TICK type of event, one for event-specific transaction code. The parent of which there are many other ways such as onTrade, is such a function for accepting a variable, then this variable is packaged into an event put out, which is the release event.

    def onTrade(self, trade):
        """成交信息推送"""
        # 通用事件
        event1 = Event(type_=EVENT_TRADE)
        event1.dict_['data'] = trade
        self.eventEngine.put(event1)
        
        # 特定合约的成交事件
        event2 = Event(type_=EVENT_TRADE+trade.vtSymbol)
        event2.dict_['data'] = trade
        self.eventEngine.put(event2)        
    
    #----------------------------------------------------------------------
    def onOrder(self, order):
        """订单变化推送"""
        # 通用事件
        event1 = Event(type_=EVENT_ORDER)
        event1.dict_['data'] = order
        self.eventEngine.put(event1)
        
        # 特定订单编号的事件
        event2 = Event(type_=EVENT_ORDER+order.vtOrderID)
        event2.dict_['data'] = order
        self.eventEngine.put(event2)

        So, here we understand, who calls these functions, who is in the release event.

        We return to the initialization function, of which there are two categories of API, CtpMdApi and CtpTdApi, then we look,

class CtpMdApi(MdApi):
    """CTP行情API实现"""

    #----------------------------------------------------------------------
    def __init__(self, gateway):
        """Constructor"""
        super(CtpMdApi, self).__init__()
        
   
class CtpTdApi(TdApi):
    """CTP交易API实现"""
    
    #----------------------------------------------------------------------
    def __init__(self, gateway):
        """API对象的初始化函数"""
        super(CtpTdApi, self).__init__()
       

        We note that both classes inherit their parent MdApi and TdApi, and these two classes of code, we can not see, it is after ctp compiler, use only import, without knowing its code. We look at the init of vnpy / api / ctp following code:

from __future__ import absolute_import
from .vnctpmd import MdApi
from .vnctptd import TdApi
from .ctp_data_type import defineDict

        The vnctpmd folder there is no MdApi the py file. Followed by the opportunity to speak ctp package when to explain this.

        Talk so much, a bit chaotic, we are back to the beginning of addGateway,

self.gatewayDict[gatewayName].setQryEnabled(gatewayModule.gatewayQryEnabled)

        Let's look at this setQryEnabled method, which is CtpGateway class this method, we found that a modified control amount only, this control amount is set to init file inside qryEnabled, which is True.

   def setQryEnabled(self, qryEnabled):
        """设置是否要启动循环查询"""
        self.qryEnabled = qryEnabled

        This just nothing special.

        Then we look at the other and gateway function MainEngine related.

    def getGateway(self, gatewayName):
        """获取接口"""
        if gatewayName in self.gatewayDict:
            return self.gatewayDict[gatewayName]
        else:
            self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName))
            return None

        It is clear, in fact, the CtpGateway this instantiated class return out.

4. The interface connector

        Then connect function interface, which is connected to the function

    def connect(self, gatewayName):
        """连接特定名称的接口"""
        gateway = self.getGateway(gatewayName)
        
        if gateway:
            gateway.connect()
            
            # 接口连接后自动执行数据库连接的任务
            self.dbConnect()    

        We have seen, it is to call the connect method CtpGateway class. We come back to see what this method is kind of how.

    def connect(self):
        """连接"""
        try:
            f = file(self.filePath)
        except IOError:
            log = VtLogData()
            log.gatewayName = self.gatewayName
            log.logContent = text.LOADING_ERROR
            self.onLog(log)
            return
        
        # 解析json文件
        setting = json.load(f)
        try:
            userID = str(setting['userID'])
            password = str(setting['password'])
            brokerID = str(setting['brokerID'])
            tdAddress = str(setting['tdAddress'])
            mdAddress = str(setting['mdAddress'])
            
            # 如果json文件提供了验证码
            if 'authCode' in setting: 
                authCode = str(setting['authCode'])
                userProductInfo = str(setting['userProductInfo'])
                self.tdApi.requireAuthentication = True
            else:
                authCode = None
                userProductInfo = None

        except KeyError:
            log = VtLogData()
            log.gatewayName = self.gatewayName
            log.logContent = text.CONFIG_KEY_MISSING
            self.onLog(log)
            return            
        
        # 创建行情和交易接口对象
        self.mdApi.connect(userID, password, brokerID, mdAddress)
        self.tdApi.connect(userID, password, brokerID, tdAddress, authCode, userProductInfo)
        
        # 初始化并启动查询
        self.initQuery()

        Most of it is to get in front of a parameter ctp connection settings, needless to say, we look at the last few lines:

# 创建行情和交易接口对象
        self.mdApi.connect(userID, password, brokerID, mdAddress)
        self.tdApi.connect(userID, password, brokerID, tdAddress, authCode, userProductInfo)
        
        # 初始化并启动查询
        self.initQuery()

        We see that kind of method call connect directly encapsulated ctp said earlier, we look at these two methods is how. To MdApi, that is, pre-market, for example, we look at.

    def connect(self, userID, password, brokerID, address):
        """初始化连接"""
        self.userID = userID                # 账号
        self.password = password            # 密码
        self.brokerID = brokerID            # 经纪商代码
        self.address = address              # 服务器地址
        
        # 如果尚未建立服务器连接,则进行连接
        if not self.connectionStatus:
            # 创建C++环境中的API对象,这里传入的参数是需要用来保存.con文件的文件夹路径
            path = getTempPath(self.gatewayName + '_')
            self.createFtdcMdApi(path)
            
            # 注册服务器地址
            self.registerFront(self.address)
            
            # 初始化连接,成功会调用onFrontConnected
            self.init()
            
        # 若已经连接但尚未登录,则进行登录
        else:
            if not self.loginStatus:
                self.login()

        The same is done in front of a large section of the setup, although I personally think that this is really no need to be so complicated, too much internal class variable. We look at the process, if the connection status is not connected, then start connecting path to get the temp folder, nothing special storage for subsequent documents. Then call the createFtdcMdApi method.

        CreateFtdcMdApi this method we can not find the definition, description is provided by the parent class in the class, subclass inherits nothing came. So, what we need to know, need to know this line of code is to create an API object for later use ctp. Several methods are also behind the definition in the parent class, we only need to know the function. Which, init () method calls onFrontConnected, we look at this method:

    def onFrontConnected(self):
        """服务器连接"""
        self.connectionStatus = True
    
        self.writeLog(text.TRADING_SERVER_CONNECTED)
        
        if self.requireAuthentication:
            self.authenticate()
        else:
            self.login()

        We found that, in this method, namely when a write connection state update, log, and if the codes adopted (this generally do not), then sign.

        Pre-transaction is the same reason, in the CTP market transaction interface and the interface are separate. So we finished the connection interface.

        Similarly, the market structure is also subscribe to such a similar, here is not to go into details.

 

 

 

 

 

Published 205 original articles · won praise 236 · views 980 000 +

Guess you like

Origin blog.csdn.net/qtlyx/article/details/84865972