XTP Python Api 接口編譯

下載xtp官方提供的python接口: https://github.com/ztsec/xtp_api_python

簡單介紹一下各個文件夾的作用(雖然里面有文檔介紹了)

bin: 編譯好的python接口和對應(yīng)的demo

doc: 編譯文檔

source: 編譯用到的代碼

XTP_API_20200824_2.2.25.5: cxx xtp 接口

因?yàn)槲也幌矚g官方對python api的命名,所以我要自己改,然后重新編譯

準(zhǔn)備工作


doc 文件夾里有對應(yīng)操作系統(tǒng)的編譯文檔,雖然不是很詳細(xì),但是也能看懂

我差不多把所有的 Python Api 都給修改了

對于非回調(diào)函數(shù),只需要修改其def的函數(shù)名即可,如果是回調(diào)函數(shù),則需要將C++中對應(yīng)的函數(shù)也給修改了,否則會找不到這個函數(shù)

編譯 boost python

按照文檔所說的,首先要編譯一份 boost python,直接去boost官網(wǎng)下載最新的boost源碼,然后只編譯python版本的。

生成b2編譯工具, 指定你python命令所在的路徑, 如果你不知道的話可以用 where python 來找到

$ ./bootstrap.sh --with-libraries=/usr/bin/python3

然后編譯.

toolset: 這里用的gcc,沒試過可不可以用clang

include: 因?yàn)橐玫絇ython.h,所以這里需要指定你在生成b2時設(shè)置的python對應(yīng)的頭文件路徑,一般在你安裝python的時候就會裝好,如果沒有裝好,在ubuntu、debian系統(tǒng)你可以這樣安裝: sudo apt-get install python-dev -y

$ ./b2 --toolset=gcc-10.2.0 --with-python include="/usr/include/python3.9" --with-thread --with-date_time --with-chrono

不出意外就編譯成功了,會在你stage文件夾里輸出編譯好的python lib

boost 這一步就算完成了

編譯 xtp python

source 文件夾里有編譯用到的源碼,使用對應(yīng)你系統(tǒng)版本的即可

編輯 CMakeLists.txt 修改幾個地方

1、修改你python 的lib和頭文件 所在目錄,和上面編譯boost時設(shè)置的一致

# 設(shè)置Python所在的目錄
set(PYTHON_LIBRARY /usr/local/python389/lib/)
set(PYTHON_INCLUDE_PATH /usr/local/python389/include/python3.8/)

2、然后是boost配置,主要修改boost所在路徑(BOOST_ROOT) 以及boost的版本(如find_package中的1.75.0),以及find_package中的python版本

# 鏈接boost庫,anaconda /python3用的是python3.6沒有用Anaconda
set(BOOST_ROOT )
set(Boost_USE_MULTITHREADED      ON)
set(BOOST_ROOT   /home/x2h1z/Downloads/boost_1_75_0_py389/)
find_package(Boost 1.75.0 COMPONENTS python3 thread date_time system chrono REQUIRED) # 如果boost庫沒有完全編譯,需要將編譯的庫明確地指出,否者message(${Boost_LIBRARIES})會出錯
if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS})
endif()

修改完cmake后,然后就直接編譯

$ mkdir build && cd build
$ cmake .. && make - -j 8

不出意外就會在lib文件夾中輸出編譯好的so

如果出意外了,那么就是find_package中python版本不對,或者你Boost版本不對之類的

反正就這幾個地方,一個個檢查就行了

測試

然后就寫個demo測試一下

import os
import sys
import time

from vnxtpquote import QuoteApi


CONFIG = {
    "ip": "120.27.164.138",
    "port": 6002,
    "user": "",
    "password": "",
    "local_ip": "0",
    "socket_type": 1
}


class MdApi(QuoteApi):
    
    def __init__(self):
        super(MdApi, self).__init__()
        
    def on_disconnected(self, error_id: int):
        pass
    
    def on_error(self, error_info: dict):
        pass
        
    def sub_market_data(self, symbols: list[dict], exchange_id: int):
        assert(exchange_id in [1, 2, 3])
        self.subscribe_market_data(symbols, len(symbols), exchange_id)
        
    def on_sub_market_data(self, ticker: dict, error_info: dict, is_last: bool):
        if error_info is None or error_info['error_id'] == 0:
            print(f"subscribe success tickers: {ticker}")
        else:
            print(f"subscribe error, id: {error_info['error_id']}, msg: {error_info['error_msg']}")
    
    def on_depth_market_data(self, data: dict, bid1_qty_list: list, bid1_counts: int, max_bid1_count: int,
                             ask1_qty_list: int, ask1_count: int, max_ask1_count: int):
        print(data)
        
        
if __name__ == '__main__':
    md_api = MdApi()
    md_api.create_quote_api(1, os.getcwd(), 4)

    # 設(shè)置心跳檢測時間間隔,單位為秒
    md_api.set_heart_beat_interval(2)
    # 設(shè)置采用UDP方式連接時的接收緩沖區(qū)大小
    md_api.set_udp_buffer_size(128)
    # 使用UDP接收行情時,設(shè)置接收行情線程綁定的cpu
    md_api.set_udp_recv_thread_affinity(2)
    # 使用UDP接收行情時,設(shè)置解析行情線程綁定的cpu
    md_api.set_udp_parse_thread_affinity(2)
    # 設(shè)定UDP收行情時是否輸出異步日志
    md_api.set_udp_seq_logout_put_flag(1)
    
    s = md_api.login(CONFIG['ip'], CONFIG['port'], CONFIG['user'], CONFIG['password'], CONFIG['socket_type'], CONFIG['local_ip'])
    if s != 0:
        print(f"login failed, status:{s}", end=", ")
        error = md_api.get_api_last_error()
        print("error: ", error)
        sys.exit(1)
        
    api_version = md_api.get_api_version()
    print(f"login success. api version: {api_version}")

    # 因?yàn)椴幻髟?,合在一起訂閱沒收到推送的行情
    md_api.subscribe_market_data([{"ticker": "000300"}], 1, 1)
    md_api.subscribe_market_data([{"ticker": "399905"}], 1, 2)
    md_api.subscribe_market_data([{"ticker": "000016"}], 1, 1)
    
    # sleep為了刪除接口對象前將回調(diào)數(shù)據(jù)輸出,不sleep直接刪除回調(diào)對象會自動析構(gòu),無法返回回調(diào)的數(shù)據(jù)
    try:
        while True:
            time.sleep(5)
    except:
        md_api.release()
        sys.exit(1)

你只需要把編譯好的so放在demo.py一起即可

你可能會疑惑,為什么python可以import so,那是因?yàn)榫幾g的時候使用到了Python.h

最后

blog: https://zckun.github.io/

公眾號: the2hcode

Mail: zckuna@163.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容