CTP Python API(利用Swig 封装)Windows版(traderapi)

来源:互联网 发布:zigbee协议栈编程 编辑:程序博客网 时间:2024/06/05 06:11

前言:
目前上期技术CTP系统提供的API版本是C++版本,本文主要介绍Windows 32位平台下利用Swig工具将CTP C++接口trader API转换为python可调用的接口。


1. 准备工作

  • 从CTP官网上下载CTP API点击下载。32位的API文件包清单如下:


    error.dtd
    error.xml
    ThostFtdcMdApi.h
    ThostFtdcTraderApi.h
    ThostFtdcUserApiDataType.h
    ThostFtdcUserApiStruct.h
    thostmduserapi.dll
    thostmduserapi.lib
    thosttraderapi.dll
    thosttraderapi.lib


ThostFtdcUserApiDataType.h中找出如下几行注释掉(对用户没有影响,但会影响python API编译)
///银行发起银行资金转期货//#define THOST_FTDC_VTC_BankBankToFuture '102001'///银行发起期货资金转银行//#define THOST_FTDC_VTC_BankFutureToBank '102002'///期货发起银行资金转期货//#define THOST_FTDC_VTC_FutureBankToFuture '202001'///期货发起期货资金转银行//#define THOST_FTDC_VTC_FutureFutureToBank '202002'///银行发起银行转期货//#define THOST_FTDC_FTC_BankLaunchBankToBroker '102001'///期货发起银行转期货//#define THOST_FTDC_FTC_BrokerLaunchBankToBroker '202001'///银行发起期货转银行//#define THOST_FTDC_FTC_BankLaunchBrokerToBank '102002'///期货发起期货转银行//#define THOST_FTDC_FTC_BrokerLaunchBrokerToBank '202002'
  • 安装Swig软件,本文中所用的Swig是swigwin-2.0.11版本,点击下载。
  • 安装python,注意要安装32位版本,将环境变量配置好。本文所用的是2.7.12版本。

2. 通过Swig得到python接口文件
在刚刚下载得到的API文件夹20160606_tradeapi_windows内,新建文件thosttraderapi.i,内容如下

%module(directors="1") thosttraderapi  %{  #include "ThostFtdcTraderApi.h"  %}  %feature("director") CThostFtdcTraderSpi;  %include "ThostFtdcUserApiDataType.h"  %include "ThostFtdcUserApiStruct.h"  %include "ThostFtdcTraderApi.h"  

这是一个接口文件,用于告诉swig为哪些类和方法创建接口。打开windows cmd工具,cd到当前目录\20160606_tradeapi_windows下。 在cmd中运行命令

swig -c++ -python thosttraderapi.i

等到运行完成后,可以看到当前目录下生成了

thosttraderapi_wrap.h
thosttraderapi_wrap.cxx
thosttradeapi.py

.h.cx文件是用于包装原来C++接口的文件,下面要用。.py文件是python调用方法的接口文件。

3. 通过C++得到python可调用的pyd动态库
在当前文件夹下建立一个C++工程,工程的应用程序类型选DLL,工程名为_thosttraderapi,将如下文件拷贝到_thosttraderapi\_thosttraderapi\文件夹下:

ThostFtdcTraderApi.h
ThostFtdcUserApiDataType.h
ThostFtdcUserApiStruct.h
thosttraderapi.lib
thosttraderapi_wrap.cxx
thosttraderapi_wrap.h

c++工程中添加现有项,将这些文件全部添加到工程中去。下面还要做几步:

  • 将你安装的python下include文件夹的路径添加至C++附加包含目录。我的路径是C:\Python27\include;C++附加包含目录在工程-属性-配置属性-c/c++处。
  • 将你安装的python中python27.lib添加至工程附加依赖项中。我的lib路径是C:\Python27\libs\python27.lib,附加依赖项在工程-属性-配置属性-链接器-输入处。

  • thosttraderapi_wrap.cxx文件中还有需要修改的地方,是SwigDirector_CThostFtdcMdSpi::OnFrontConnected()函数内,因为我发现每次回调OnFrontConnected会导致python API崩溃(OnFrontDisconnected()函数无此问题),我将如下行注释掉就可以正常使用:

#else  //swig::SwigVar_PyObject result = PyObject_CallMethod(swig_get_self(), (char *) "OnFrontConnected", NULL);#endif  /*  if (!result) {    PyObject *error = PyErr_Occurred();    if (error) {      Swig::DirectorMethodException::raise("Error detected when calling 'CThostFtdcMdSpi.OnFrontConnected'");    }  }  */

当然,这只是我的讨巧方法,这会导致没有回调OnFrontConnected。读者可以一起探讨下怎么解决这个bug。

这样全部完成之后,我们按F7编译,在\_thosttraderapi\Debug目录底下可见_thosttraderapi.dll动态库文件,说明编译成功,将其重命名为_thosttraderapi.pyd,这样CTP Python API就编译成功了。
如果编译出现一些问题,可以百度解决。可能涉及到要修改pyconfig.h,object.h,Python.h三个文件。

4. Python Demo
新建文件traderapi_demo.py,注意文件同目录底下要有如下三个文件:

thosttradeapi.py
thosttraderapi.dll
_thosttradeapi.pyd

本demo实现登录成功后报单,收报单回报的功能。完整的demo代码如下:

# -*- coding: gbk -*-import timeimport thosttraderapi as api def ReqorderfieldInsert(tradeapi):    print "ReqOrderInsert Start"    orderfield=api.CThostFtdcInputOrderField()    orderfield.BrokerID="8000"    orderfield.InstrumentID="sc1412"    orderfield.UserID="000005"    orderfield.InvestorID="000005"    orderfield.Direction=api.THOST_FTDC_D_Sell    orderfield.LimitPrice=52050    orderfield.VolumeTotalOriginal=1    orderfield.OrderPriceType=api.THOST_FTDC_OPT_LimitPrice    orderfield.ContingentCondition = api.THOST_FTDC_CC_Immediately    orderfield.TimeCondition = api.THOST_FTDC_TC_GFD    orderfield.VolumeCondition = api.THOST_FTDC_VC_AV    orderfield.CombHedgeFlag="1"    orderfield.CombOffsetFlag="0"    orderfield.GTDDate=""    orderfield.orderfieldRef="1"    orderfield.MinVolume = 0    orderfield.ForceCloseReason = api.THOST_FTDC_FCC_NotForceClose    orderfield.IsAutoSuspend = 0    tradeapi.ReqOrderInsert(orderfield,0)    print "ReqOrderInsert End"class CTradeSpi(api.CThostFtdcTraderSpi):    tapi=''    def __init__(self,tapi):        api.CThostFtdcTraderSpi.__init__(self)        self.tapi=tapi    def OnRspUserLogin(self, *args):        print "OnRspUserLogin"        rsploginfield=args[0]        rspinfofield=args[1]        print "SessionID=",rsploginfield.SessionID        print "ErrorID=",rspinfofield.ErrorID        print "ErrorMsg=",rspinfofield.ErrorMsg        ReqorderfieldInsert(self.tapi)          def OnRtnOrder(self, *args):        print "OnRtnOrder"        rtnfield=args[0]        print "OrderStatus=",rtnfield.OrderStatus        print "StatusMsg=",rtnfield.StatusMsg        print "LimitPrice=",rtnfield.LimitPrice    def OnRspOrderInsert(self, *args):        print "OnRspOrderInsert"        rspinfofield=args[1]        print "ErrorID=",rspinfofield.ErrorID        print "ErrorMsg=",rspinfofield.ErrorMsgdef main():    tradeapi=api.CThostFtdcTraderApi_CreateFtdcTraderApi()    tradespi=CTradeSpi(tradeapi)    loginfield = api.CThostFtdcReqUserLoginField()    loginfield.BrokerID="8000"    loginfield.UserID="000005"    loginfield.Password="123456"    loginfield.UserProductInfo="python dll"    tradeapi.RegisterFront("tcp://172.19.125.39:39233")    tradeapi.RegisterSpi(tradespi)    tradeapi.SubscribePrivateTopic(api.THOST_TERT_RESUME)    tradeapi.SubscribePublicTopic(api.THOST_TERT_RESUME)    tradeapi.Init()    time.sleep(2)    tradeapi.ReqUserLogin(loginfield,0)    tradeapi.Join()if __name__ == '__main__':    main()

本人所编译的CTP0606版本的交易、行情Python API,点击下载。声明:仅是个人爱好编译,对此API引起的你的任何损失不负责任。

原创粉丝点击