After the vnpy_ctp source code is downloaded, it is converted into a python usable processing process.

Table of Contents

write in front

Download the source code and unzip it

Create python project

environment

process

Compile vnpy_ctp source code

Verify availability


Write in front

Visual Studio must be installed in the window system, and C++ compilation is required when installing the source code later.

Download the source code and unzip

GitHub – vnpy/vnpy_ctp: CTP transaction interface for VeighNa framework

Download zip package

Unzip

To be executable in python, there must be a .pyd file. There is no .pyd file in the decompressed folder.

Create python project

Create a new python project and execute it in a new virtual environment.

environment

Operating system: window10 64 bit

Development tools: pycharm

python version: python3.8.10

process

Compile vnpy_ctp source code

Open the terminal panel below the project

cd to the folder where setup.py is located after decompression

Execute python setup.py build

In about 2 to 3 minutes, the compilation is completed, and there will be an extra build folder under the folder where setup.py is located.

Find the operating system and python version under build The corresponding folder, taking this article as an example, the operating system is 64-bit, then the folder name will contain amd64, python version 3.8, and the folder name will contain 3.8, so the folder name of this article is lib.win- amd64-3.8

What we need is the api folder under the build>lib.win-amd64-3.8>vnpy_ctp folder. We copy the api folder to the project directory.

Verify Availability

Create a class called by Md and a class called by Td

import datetime,sys,os,time,pytz
from api import (
    TdApi,
    MdApi
)
class CtpMdApi(MdApi):
    def __init__(self)->None:
        super().__init__()

        self.reqid:int = 0
        self.connect_status: bool = False
        self.login_status: bool = False
        self.subscribed: set = set()

        self.userid: str = ""
        self.password: str = ""
        self.brokerid: str = ""

        self.current_date: str = datetime.date.today().strftime('%Y%m%d')
        pass
    def connect(self, address: str, userid: str, password: str, brokerid: str)->None:
        self.userid = userid
        self.password = password
        self.brokerid = brokerid

        if not self.connect_status:
            con_body_path = CTP_MD_CON_DIR
            con_body_path = con_body_path.replace('/','')
            self.createFtdcMdApi(con_body_path)
            self.registerFront(address)
            self.init()

            self.connect_status = True
            pass
        pass

    def login(self)->None:
        ctp_req: dict = {
            'UserID':self.userid,
            'Password':self.password,
            'BrokerID':self.brokerid
        }
        self.reqid + = 1
        self.reqUserLogin(ctp_req,self.reqid)
        pass
    def subscribe(self,req:dict):
        if self.login_status:
            self.subscribeMarketData(req['symbol'])
        self.subscribed.add(req['symbol'])
        pass
    def close(self)->None:
        if self.connect_status:
            self.exit()
        pass
    def update_date(self)->None:
        self.current_date = datetime.date.today().strftime('%Y%m%d')
        pass
    def onFrontConnected(self)->None:
        self.login()
        pass
    def onFrontDisconnected(self,reason:int)->None:
        self.login_status = False
        pass
    def onRspUserLogin(self,data:dict,error:dict,reqid:int,last:bool)->None:
        if not error['ErrorID']:
            self.login_status = True
            for symbol in self.subscribed:
                self.subscribeMarketData(symbol)
            pass
        else:
            print(f"Login to the quotation server failed. {error['ErrorID']}.{error['ErrorMsg']}")
        pass
    def onRspError(self, error: dict, reqid: int, last: bool)->None:
        print('The market interface reported an error.', error['ErrorID'], error['ErrorMsg'])
        pass
    def onRspSubMarketData(self, data: dict, error: dict, reqid: int, last: bool):
        if not error or not error['ErrorID']:
            return
        print('Quote subscription failed.',error['ErrorID'],error['ErrorMsg'])
        pass
    def onRtnDepthMarketData(self,data:dict)->None:
        if not data['UpdateTime']:
            return
        print('tick returns',data['InstrumentID'],data['LastPrice'])
        pass
    pass

class CtpTdApi(TdApi):
    def __init__(self)->None:
        super().__init__()
        self.reqid: int = 0
        self.order_ref: int = 0

        self.connect_status: bool = False
        self.login_status: bool = False
        self.auth_status: bool = False
        self.login_failed: bool = False
        self.auth_failed: bool = False
        self.contract_inited: bool = False

        self.userid: str = ""
        self.password: str = ""
        self.brokerid: str = ""
        self.auth_code: str = ""
        self.appid: str = ""

        self.frontid: int = 0
        self.sessionid: int = 0
        pass
    def connect(self,address:str,userid:str,password:str,brokerid:str,auth_code:str,appid:str)->None:
        self.userid = userid
        self.password = password
        self.brokerid = brokerid
        self.auth_code = auth_code
        self.appid = appid

        if not self.connect_status:
            con_body_path = CTP_TD_CON_DIR + self.userid + os.path.sep
            if not os.path.exists(con_body_path):
                os.mkdir(con_body_path)
            con_body_path = con_body_path.replace('/','')
            self.createFtdcTraderApi(con_body_path)

            self.subscribePrivateTopic(0)
            self.subscribePublicTopic(0)
            self.registerFront(address)
            self.init()

            self.connect_status = True
            pass
        else:
            self.authenticate()
        pass

    def authenticate(self)->None:
        if self.auth_failed:
            return
        ctp_req: dict = {
            "UserID": self.userid,
            "BrokerID": self.brokerid,
            "AuthCode": self.auth_code,
            "AppID": self.appid
        }

        self.reqid + = 1
        self.reqAuthenticate(ctp_req, self.reqid)
        pass
    def login(self)->None:
        if self.login_failed:
            return
        ctp_req: dict = {
            "UserID": self.userid,
            "Password": self.password,
            "BrokerID": self.brokerid,
            "AppID": self.appid
        }

        self.reqid + = 1
        self.reqUserLogin(ctp_req, self.reqid)
        pass
    def close(self)->None:
        if self.connect_status:
            self.exit()
        pass
    def onFrontConnected(self)->None:
        if self.auth_code:
            self.authenticate()
        else:
            self.login()
        pass
    def onFrontDisconnected(self,reason:int)->None:
        self.login_status = False
        pass
    def onRspAuthenticate(self, data: dict, error: dict, reqid: int, last: bool)->None:
        if not error['ErrorID']:
            self.auth_status = True
            self.login()
        else:
            self.auth_failed = True
            print('Trading server verification failed.',error['ErrorID'],error['ErrorMsg'])
        pass
    def onRspUserLogin(self,data: dict, error: dict, reqid: int, last: bool)->None:
        if not error["ErrorID"]:
            self.frontid = data["FrontID"]
            self.sessionid = data["SessionID"]
            self.login_status = True

            # Automatically confirm the settlement document
            ctp_req: dict = {
                "BrokerID": self.brokerid,
                "InvestorID": self.userid
            }
            self.reqid + = 1
            self.reqSettlementInfoConfirm(ctp_req, self.reqid)
        else:
            self.login_failed = True
            print("Trading server login failed", error['ErrorID'], error['ErrorMsg'])
        pass
    def onRspSettlementInfoConfirm(self,data: dict, error: dict, reqid: int, last: bool)->None:
        while True:
            self.reqid + = 1
            n: int = self.reqQryInstrument({}, self.reqid)
            if not n:
                break
            else:
                time.sleep(1)
        pass
    def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool) -> None:
        print(data['ProductClass'],data['InstrumentID'],data['ProductID'],reqid,last)
        if last:
            self.contract_initiated = True
            print('Contract information query completed')
        pass
    pass

Execute code

if __name__ == '__main__':
    investorid = ""
    brokerid=""
    password= ""
    appid= ""
    auth_code= "0000000000000000"
    md_ip= "180.168.146.187:10211"
    trader_ip= "180.168.146.187:10201"

    temp_api = CtpTdApi()
    address = f"tcp://{trader_ip}"
    temp_api.connect(address,investorid,password,brokerid,auth_code,appid)

    import keyboard
    keyboard.wait('esc')
    sys.exit()
    pass

Can log in to the td server and query the contract normally, available