CTP程序化交易入门系列之二:API基本架构及初始化

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/yishuihan1212/article/details/90760353

上节讲了CTP程序化交易的入门工作:下载API,准备账号密码地址等。这节我们来讲API基本架构及初始化。

一、 CTP API基本架构

 这里为了便于大家理解API的相关函数,我简略地讲一下API的基本架构。如上图所画,左边部分是客户的交易程序,中间是封装好的API动态库底层;右边是CTP系统。以客户登录为例,顺序逻辑如下:
  1. 客户程序里调用API的函数ReqUserLogin写入动态库底层维护的缓存中;
  2. 动态库内置线程读取缓存内容通过tcp链接发往CTP前置;
  3. 动态库内置线程通过tcp链接读取CTP的回复,然后回调SPI中的函数OnRspUserLogin;
  4. 客户在继承重写OnRspUserLogin函数,在其中处理自己的业务逻辑;

 其实这也是国内市场上(包括交易所)大部分异步API的基本架构。

二、接口文件清单

 以win64为例:

thosttraderapi.py  //交易头文件
_thosttraderapi.pyd  //交易库转换文件
thosttraderapi.dll  //交易官方动态库,穿透式版为thosttraderapi_se.dll
thostmduserapi.py  //行情头文件
_thostmduserapi.pyd  //行情库转换文件
thostmduserapi.dll  //行情官方动态库,穿透式版为thostmduserapi_se.dll

 可以看到API分为交易3个文件,主要负责认证,登录,报单,撤单,查资金,查持仓等功能;行情3个文件,主要负责订阅收取行情。两部分可以独立运行。

三、初始化函数说明

 API在调用前需要初始化,初始化的流程都是固定的(详细参考td_demo.py):

import thosttraderapi as api

//创建API实例
tradeapi=api.CThostFtdcTraderApi_CreateFtdcTraderApi()  

//创建SPI实例。CTradeSpi是继承自头文件中CThostFtdcTraderSpi的类型,
//用于收从CTP的回复,可以重写父类中的函数来实现自己的逻辑
tradespi=CTradeSpi(tradeapi)  

//将创建的SPI实例注册进实例,这样该API实例发出的请求对应的回报就会回调到对应的SPI实例的函数
tradeapi.RegisterSpi(tradespi) 

//订阅共有流与私有流。订阅方式主要有三种,分为断点续传,重传和连接建立开始传三种。
tradeapi.SubscribePrivateTopic(api.THOST_TERT_QUICK) 
tradeapi.SubscribePublicTopic(api.THOST_TERT_QUICK)

// 注册前置地址,是指将CTP前置的IP地址注册进API实例内
tradeapi.RegisterFront(FrontAddr) 

//API启动,init之后就会启动一个内部线程读写,并去连CTP前置
tradeapi.Init()

//Join函数是使得函数阻塞在这里,等待api实例创建的内部线程的结束。
//内部线程需要release才会释放结束
tradeapi.Join()

四、请求及回复函数说明

 以交易为例,从头文件(thosttraderapi.py)底部可以看到有两个类class CThostFtdcTraderApi和class CThostFtdcTraderSpi。CThostFtdcTraderApi类中是所有的请求函数,例如请求登录:

def ReqUserLogin(self, pReqUserLoginField: 'CThostFtdcReqUserLoginField', nRequestID: 'int') -> "int":

 投资者只需要用该函数所要求的参数类型声明一个变量,并将变量中相应成员赋值,再调用函数发送出去就可。如下:

loginfield = api.CThostFtdcReqUserLoginField()
loginfield.BrokerID="0000"
loginfield.UserID="00001"
loginfield.Password="123456"
tradeapi.ReqUserLogin(loginfield,0)

 这样就会将登录请求发送到CTP的前置。
 而该请求对应的回复我们怎么得到呢?这就需要靠SPI实例了。在第三节中可以看到通过RegisterSpi函数,API的实例和SPI的实例是一一对应的。所以如果CTP发回来回复,底层dll就保证了将回调到对应的SPI中登陆回复函数:

def OnRspUserLogin(self, pRspUserLogin: 'CThostFtdcRspUserLoginField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":

 该函数对应的参数便是CTP回复的信息,我们可以继承CThostFtdcTraderSpi类,然后重写该函数,将相应的信息答应出来,也可以在该函数中实现其他的逻辑,例如demo中就在该函数中继续去查结算单信息。

 细心的读者一定发现了,CThostFtdcTraderApi类中的请求函数和CThostFtdcTraderSpi类中的回复函数命名存在一一对应关系。这种对应关系可以借用官方文档中一张图:

五、初始化时序图

 最后我们以官方文档中的初始化时序图收尾。

下节预告:
如何使用CTP API获取实时行情

关注公众号,一起学习程序化交易!
关注公众号,一起学习程序化交易!

猜你喜欢

转载自blog.csdn.net/yishuihan1212/article/details/90760353