4. 开发环境搭建
CTP行情接入的第一步不是写代码,而是把“能编译、能连上、能收到行情”这条链路打通。很多初学者卡在环境阶段:头文件找不到、动态库加载失败、SimNow登录返回“不合法的登录”、行情前置连不上。本章按“获取—编译—依赖—账户—连接”的顺序,把每个环节的关键动作和常见坑讲清楚。
一、核心原理:CTP行情API的组成与运行机制
CTP行情API(MdApi)本质上是一套C++动态库,由交易所前置通过TCP推送行情,客户端通过API回调接收。它由三部分构成:
- 头文件:
ThostFtdcMdApi.h、ThostFtdcUserApiStruct.h、ThostFtdcUserApiDataType.h,定义接口与数据结构。 - 动态库:Linux下为
libthostmduserapi_se.so,Windows下为thostmduserapi_se.dll,是实际通信与回调的载体。 - 回调接口:
CThostFtdcMdSpi,开发者继承并实现OnFrontConnected、OnRspUserLogin、OnRtnDepthMarketData等方法。
行情API与交易API是两套独立库,行情只负责订阅与推送,不涉及报单。理解这一点,能避免把交易账户和行情账户混用。
二、方法流程:从获取到编译的完整步骤
以Linux环境为例,标准流程如下:
- 获取API包:从期货公司官网或SimNow下载对应版本的CTP API压缩包,注意区分Linux/Windows、32/64位。
- 解压并规划目录:将头文件放入
include/,动态库放入lib/,保持工程结构清晰。 - 编写最小可运行程序:创建MdApi实例、注册Spi、连接前置、登录、订阅。
- 编译链接:指定头文件路径与库路径,链接
thostmduserapi_se。 - 配置运行时库路径:通过
LD_LIBRARY_PATH或rpath让程序找到.so。
# 目录结构示例
ctp_demo/
├── include/
│ ├── ThostFtdcMdApi.h
│ ├── ThostFtdcUserApiStruct.h
│ └── ThostFtdcUserApiDataType.h
├── lib/
│ └── libthostmduserapi_se.so
└── main.cpp
# 编译命令
g++ main.cpp -o md_demo \
-I./include \
-L./lib \
-lthostmduserapi_se \
-Wl,-rpath,./lib \
-lpthread -std=c++11
# 运行
./md_demo
使用
-Wl,-rpath,./lib 可以把库搜索路径写进可执行文件,避免每次手动设置 LD_LIBRARY_PATH,在部署时更省心。三、依赖库配置与账户申请
CTP API依赖系统基础库,常见缺失包括libpthread、libstdc++、libcrypto等。若运行时报error while loading shared libraries,可用ldd检查依赖:
ldd ./md_demo | grep "not found"
# 若提示 libthostmduserapi_se.so => not found
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/lib
账户方面,SimNow是官方模拟环境,注册后获得InvestorID、密码和BrokerID。行情前置地址通常为tcp://180.168.146.187:10131(具体以官网为准)。生产环境则由期货公司提供,需签署协议并开通行情权限。
| 项目 | SimNow模拟 | 生产环境 |
|---|---|---|
| BrokerID | 9999 | 期货公司分配 |
| 行情前置 | tcp://180.168.146.187:10131 | 期货公司提供 |
| 账户来源 | 官网自助注册 | 临柜/线上开通 |
| 费用 | 免费 | 按交易所标准 |
| 适用阶段 | 开发调试 | 实盘交易 |
四、模拟环境连接与常见误区复盘
连接SimNow的典型代码片段如下,重点在于RegisterFront与Init的调用顺序:
CThostFtdcMdApi* api = CThostFtdcMdApi::CreateFtdcMdApi("./flow/");
api->RegisterSpi(&spi);
api->RegisterFront("tcp://180.168.146.187:10131");
api->Init();
api->Join(); // 阻塞等待回调
登录成功后,OnRspUserLogin会返回交易日;随后调用SubscribeMarketData订阅合约,行情通过OnRtnDepthMarketData持续推送。
常见误区:
1. 把行情前置地址写成交易前置,导致连接失败;
2. 未实现
3. 在
4. 忽略
1. 把行情前置地址写成交易前置,导致连接失败;
2. 未实现
OnFrontDisconnected,断线后无重连逻辑;3. 在
OnRtnDepthMarketData中做耗时操作,阻塞回调线程;4. 忽略
Join()或未正确释放API,导致进程退出异常。复盘建议:先用官方Demo跑通,再逐步替换为自己的封装。每次连接失败,优先检查前置地址、BrokerID、InvestorID和密码四项,再排查网络与库路径。环境打通后,后续的行情标准化才有稳定的数据来源。