vnpy目录下的gateway封装了各种交易接口,以ctp为例,从源码开始,看看vnpy是如何将c++接口一步步转化为python接口,并且具有强大的可拓展性。
初始材料:交易所提供的c++版本dll以及头文件
ThostFtdcMdApi.h和ThostFtdcTraderApi.h分别是ctp的行情和交易接口,我们就拿行情接口研究(交易接口原理一样)
头文件中定义了2个类 CThostFtdcMdSpi(简称spi)和CThostFtdcMdApi(简称api),他们的具体实现封装在thostmduserapi_se.dll中,api包含主动请求接口,spi是api请求接口的具体实现中会去回调的函数,可以理解为:调用api的ReqUserLogin方法时,ReqUserLogin方法内部会去调用spi的OnRspUserLogin方法。
为了实现c++到python的接口转换,首先构造一个新的C++类:MdApi
MdApi继承自spi,成员变量包含api,以及负责处理回调数据的任务队列task_queue,spi回调函数OnRspMethod此处overwrite,将回调数据封装为task格式推送到task_queue中,最后根据task类型分发给各自的processRspMethod方法进行处理,processRspMethod方法中调用MdApi的onRspMethod方法(on为小写 spi的OnRspMethod为大写)。将api的请求函数统称为Method,其运行流程如下:
MdApi.Method()--->api.Method()--->spi.OnRspMethod()--->回调产生的task--->task_queue.push(task)--->task_queue.pop()--->-MdApi.processRspMethod()-->MdApi.onRspMethod()
将上述c++对象通过pybind11模块编译为python的MdApi类,CtpMdApi继承MdApi,重载onRspMethod方法(实现回调函数逻辑代码),按需求实现接口函数。
到这一步,就完成了接口封装的所有任务,剩下的就是看看vnpy是怎么让交易模块具有良好的可拓展性。
vnpy所有交易接口都是继承自BaseGateway这个抽象类,这个类定义了所有行情以及交易接口,所以很简单,CtpGateway通过内部成员CtpMdApi去实现父类的抽象函数边可以满足系统需求,而当接口变更时,因为vnpy上层逻辑都是通过BaseGateway去实现,所以需要不同接口实现行情交易等功能时,只需要通过反射寻找到相匹配的Gateway即可。