1. 程式人生 > >CTP Python API(利用Swig 封裝)Windows版(traderapi)

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

前言:
目前上期技術CTP系統提供的API版本是C++版本,本文主要介紹Windows 32位平臺下利用Swig工具將CTP C++介面trader API轉換為python可呼叫的介面。此版本是在原先版本上的升級,解決了onfrontconnected回撥的宕機問題。感謝知乎網友@warlock 一起探討。

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 -threads -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,附加依賴項在工程-屬性-配置屬性-連結器-輸入處。

這樣全部完成之後,我們按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 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 OnFrontConnected(self):
        print "OnFrontConnected"
        loginfield = api.CThostFtdcReqUserLoginField()
        loginfield.BrokerID="8000"
        loginfield.UserID="000005"
        loginfield.Password="123456"
        loginfield.UserProductInfo="python dll"
        self.tapi.ReqUserLogin(loginfield,0)
    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.ErrorMsg

def main():
    tradeapi=api.CThostFtdcTraderApi_CreateFtdcTraderApi()
    tradespi=CTradeSpi(tradeapi)
    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()
    tradeapi.Join()

if __name__ == '__main__':
    main()

本人所編譯的CTP0606版本的交易、行情Python API點選下載。宣告:僅是個人愛好編譯,對此API引起的你的任何損失不負責任。