说明
- vnpy官方目前仍是python2的版本,群主有提到将在2.0版本升级python3。大佳老师在vnpy的基础上自己fork了一个python3版本。还有不少其他用户也自行魔改python3版本。
- vnpy集成了众多交易接口,包括期货、IB等。本文仅针对期货CTP接口在ubuntu、python3环境下的编译安装。
- ubuntu16自带python2.7和python3.5,如果不介意,可以直接用系统的python3.5来编译和运行。如果服务器还有其他任务,可能用到不同的环境,或者希望使用其他版本的python,常用的一种解决方案是安装最新的anaconda3,然后用其创建独立的python虚拟环境,例如python3.6的环境。
sudo apt-get install libboost-all-dev
这个方式安装的boost库是python2版本的,安装python3版本应下载boost源代码在编译时指定python3.- 本文参考大佳老师github的安装流程以及各种搜索结果。
- 本文也发在我的博客我的博客。
以下是直接使用ubuntu16系统python3.5来编译安装的流程
下载python3版本的ctpapi代码
建议使用git,直接克隆整个仓库下来,然后将其中的vnpy/api/ctp/文件夹复制到用户目录下。
git clone https://github.com/msincenselee/vnpy.git
安装编译工具
更新apt-get的软件列表
sudo apt-get update
安装编译相关软件
sudo apt-get install gcc build-essential cmake
安装python相关软件
sudo apt-get install python-dev python-pip python3 python3-dev python3-pip
安装boost依赖的软件
sudo apt-get install mpi-default-dev libicu-dev libbz2-dev
安装boost
下载boost安装包
wget http://sourceforge.net/projects/boost/files/boost/1.66.0/boost_1_66_0.tar.gz/download
重命名
mv download boost_1_66_0.tar.gz
解压缩
tar -xvzf boost_1_66_0.tar.gz
修改 boost_1_66_0/tools/build/example/user-config.jam,指定使用python3.5。然后把user-config.jam复制到用户目录,例如/home/ubuntu/
using python : 3.5 : /usr/bin/python3 : /usr/include/python3.5m : /urs/lib/x86_64-linux-gnu ;
回到 boost_1_66_0/,运行bootstrap.sh,指定使用pyhton3.5。此处只编译ctpapi需要的库,如过希望编译所有的库则修改参数为--with-libraries=all
./bootstrap.sh --with-python=/usr/bin/python3 --with-python-version=3.5 --with-libraries=python,locale,thread,date_time,system,chrono
编译,安装
sudo ./b2 install
安装完成检查 /usr/local下, include/boost, lib/libboos_python3.so等是否存在
配置CMakeLists.txt
主要是修改一些路径在具体服务器上的实际位置,并去掉了windows的部分
cmake_minimum_required(VERSION 2.8) # 版本要求
project(vn_ctp_api) # 项目名称
# 设置使用的编译器
set(CMAKE_BUILD_TYPE "Release") # 编译类型为release,即发布
if (CMAKE_COMPILER_IS_GNUCXX) # 原为if (CMAKE_COMPILER_IS_GNUC OR CMAKE_COMPILER_IS_GNUCXX),其中的CMAKE_COMPILER_IS_GNUC疑为CMAKE_COMPILER_IS_GNUCC,少了个C
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++11") # C++编译器加上c++11支持选项
# -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),
# 则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意
# 位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
endif ()
# 设置输出目录
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) # CMAKE_BINARY_DIR 如果是 in source 编译,指得就是工程顶层目录,如果是 out-of-source 编译,指的是工程编译发生的目录
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
# 使用64位编译
option(USE_64BITS "comiple 64bits" ON) # option命令为用户提供了一个在ON和OFF中做出选择的选项。如果没有指定初始值,将会使用OFF作为初值。
if (USE_64BITS)
add_definitions(-DUSE_64BITS) # 为源文件的编译添加由-D引入的define flag
endif()
# 设置C++ API源文件的所在目录
message("Under unix: " ${CMAKE_SIZEOF_VOID_P})
if (CMAKE_SIZEOF_VOID_P MATCHES "8") # 检查当前电脑是否是64位的
set(CTPAPI_PATH ctpapi/x64_linux) # 设置ctpapi的搜索路径
endif()
include_directories(${CTPAPI_PATH}) # 添加到include文件的搜索路径
set(CTPAPI_LIBRARY )
find_library(CTPAPI_MD_LIBRARY # 在CTPAPI_PATH目录查找库文件thostmduserapi,保存在名为CTPAPI_MD_LIBRARY的变量中
NAMES thostmduserapi
PATHS ${CTPAPI_PATH})
find_library(CTPAPI_TD_LIBRARY # 在CTPAPI_PATH目录查找库文件thosttraderapi,保存在名为CTPAPI_TD_LIBRARY的变量中
NAMES thosttraderapi
PATHS ${CTPAPI_PATH})
# 设置编译源文件
set (vnctpmd )
set (vnctptd )
option(BUILD_CTP_MD "build ctp md" ON) # 增加选项BUILD_CTP_MD,初始值为ON。
if (BUILD_CTP_MD)
add_definitions(-DBUILD_CTP_MD)
set(CTP_MD_PATH vnctpmd/vnctpmd) # 设置CTP_MD_PATH变量,即CTP_MD头文件的路径
include_directories(CTP_MD_PATH)
set(VN_CTP_MD_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/vnctpmd/vnctpmd/vnctpmd.cpp) # 设置VN_CTP_MD_SOURCE变量,即其cpp源代码的位置
add_library(vnctpmd SHARED ${VN_CTP_MD_SOURCE}) # 使用指定的源文件向工程中添加一个库。vnctpmd是名称。SHARED库会被动态链接,在运行时被加载。
endif()
option(BUILD_CTP_TD "build ctp td" ON) # 选项BUILD_CTP_TD 同上
if (BUILD_CTP_TD)
add_definitions(-DBUILD_CTP_TD)
set(CTP_TD_PATH vnctptd/vnctptd)
include_directories(CTP_TD_PATH)
set(VN_CTP_TD_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/vnctptd/vnctptd/vnctptd.cpp)
add_library(vnctptd SHARED ${VN_CTP_TD_SOURCE})
endif()
# 设置Python所在的目录,这里使用系统的python3.5
# 如果使用anaconda虚拟环境,lib和include的目录相应修改
set(PYTHON_LIBRARY )
set(PYTHON_INCLUDE_PATH /usr/include/python3.5m)
find_library(PYTHON_LIBRARY
NAMES python3.5m
PATHS /urs/lib/x86_64-linux-gnu)
include_directories(${PYTHON_INCLUDE_PATH})
# 链接boost库
set(Boost_USE_MULTITHREADED ON) # Boost多线程
find_package(Boost 1.66.0 COMPONENTS python thread date_time system chrono REQUIRED) # 如果boost库没有完全编译,需要将编译的库明确地指出,否者message(${Boost_LIBRARIES})会出错.这里指出了依赖的boost组件
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
endif()
# 去掉生成的so文件名中前缀的lib
set_target_properties(vnctpmd PROPERTIES PREFIX "")
set_target_properties(vnctptd PROPERTIES PREFIX "")
# 链接生成.so文件
target_link_libraries(vnctpmd ${Boost_LIBRARIES} ${PYTHON_LIBRARY} ${CTPAPI_MD_LIBRARY})
target_link_libraries(vnctptd ${Boost_LIBRARIES} ${PYTHON_LIBRARY} ${CTPAPI_TD_LIBRARY})
配置build.sh
如果目录结构没有变化,build.sh可以完全照搬,不需要修改。
#!/bin/bash
# Written by Suzhengchun on 20160213
set -e
BUILDDIR=build
rm -rf $BUILDDIR
if [ ! -f $BUILDDIR ]; then
mkdir -p $BUILDDIR
fi
pushd $BUILDDIR
cmake ..
make VERBOSE=1 -j 1
ln -fs `pwd`/lib/vnctpmd.so ../vnctpmd/test/vnctpmd.so
ln -fs `pwd`/lib/vnctptd.so ../vnctptd/test/vnctptd.so
cp ../vnctpmd/test/vnctpmd.* ../
cp ../vnctptd/test/vnctptd.* ../
popd
开始编译
./build.sh
编译完成可以在CMakeLists.txt的同一目录以及build/lib/目录下看到vnctpmd.so和vnctptd.so。使用test下的mdTest.py和tdTest.py可以进行测试。
以下是直接使用python3.6虚拟环境来编译安装的流程(仅列出不同的部分)
安装anaconda
下载anaconda安装包
wget -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-5.3.0-Linux-x86_64.sh
使安装包可执行
chmod a+x Anaconda3-5.3.0-Linux-x86_64.sh
开始安装anaconda
./Anaconda3-5.3.0-Linux-x86_64.sh
如果希望之后在命令行直接输入conda就能运行而不需要加具体路径,在安装过程提示Do you wish the installer to initialize Anaconda3 in your /home/ubuntu/.bashrc [yes|no]时选择yes,然后运行source .bashrc
使配置生效。
配置为国内的镜像
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
创建虚拟python3.6环境
conda create --name py36 python=3.6
激活虚拟python3.6环境
source activate py36
安装boost
修改 boost_1_66_0/tools/build/example/user-config.jam,指定使用虚拟环境的python3.6
using python : 3.6 : /home/ubuntu/anaconda3/envs/py36/bin/python3 : /home/ubuntu/anaconda3/envs/py36/include/python3.6m : /home/ubuntu/anaconda3/envs/py36/lib ;
回到 boost_1_66_0/,运行bootstrap.sh,指定使用虚拟环境的pyhton3.6。此处只选择需要的库,如过希望编译所有的库则改为--with-libraries=all
./bootstrap.sh --with-python=/home/ubuntu/anaconda3/envs/py36/bin/python3 --with-python-version=3.6 --with-python-root=/home/ubuntu/anaconda3/envs/py35 --with-libraries=python,locale,thread,date_time,system,chrono
配置CMakeLists.txt
# 设置Python所在的目录,此处使用的是anaconda创建的python3.6虚拟环境
set(PYTHON_LIBRARY )
set(PYTHON_INCLUDE_PATH /home/ubuntu/anaconda3/envs/py36/include/python3.6m)
find_library(PYTHON_LIBRARY
NAMES python3.6m
PATHS /home/ubuntu/anaconda3/envs/py36/lib/)
include_directories(${PYTHON_INCLUDE_PATH})
以下是编译过程碰到的一些问题的解决方案,供参考
内存不足问题
如果配置太低内存不足,编译会出现Memory exhausted错误,需设置swap文件,相当于虚拟内存。
创建swap挂载点
mkdir /opt/images/
rm -rf /opt/images/swap
设置挂载swap的大小,64M*32=2GB
dd if=/dev/zero of=/opt/images/swap bs=64M count=32
mkswap /opt/images/swap
开启swap
swapon /opt/images/swap
这个时候,可以执行之前内存不足时的命令了,正常情况下,执行时间会比较长,但是能过去
使用完毕后可以考虑关闭swap并删除挂载文件
swapoff swap
rm -f /opt/images/swap