TdxHqApi C++行情接入指南:编译、连接与实时数据解析
2026/9/11 16:35:36 网站建设 项目流程

简介:本资源是面向C/C++金融开发者的通达信TDX行情接口SDK完整实现包,聚焦于实时行情获取、历史K线拉取与盘口数据订阅等核心场景,适用于量化交易系统开发、策略回测引擎搭建及金融数据终端二次开发。压缩包含62个文件,以C++源码(.cpp/.h)、构建脚本(.sh/.am/.in)、国际化支持文件(.po/.gmo)及配置工具(m4宏、configure、Makefile系列)为主,体现典型GNU Autotools工程结构,便于跨平台编译与集成;整体包体仅377KB,轻量但功能完备。已有1321人学习下载,资源提供TdxHqApi的完整C++封装实现、配套测试用例(unitTest.cpp、dataTest.h等)、可执行模块安装/卸载脚本,以及清晰的README与INSTALL说明,开发者可直接编译调用,快速对接通达信服务器获取A股、期货等实时行情数据。

1. 用 TdxHqApi 接入通达信行情数据:C++ 开发者绕不开的实时金融数据底座

很多做量化策略、行情终端或本地数据服务的 C++ 工程师,第一次接触通达信数据源时都会卡在同一个地方:不是不会写代码,而是根本不知道TdxHqApi这个类到底该连谁、怎么初始化、连上之后拿什么数据、返回结构怎么解析。它不像 HTTP API 那样有明确 URL 和 JSON Schema,而是一套基于 TCP 长连接 + 自定义二进制协议的本地化接口,依赖通达信客户端(或精简版服务)作为数据代理。tdx_data-2.0.4.tar.gz就是官方提供的 C++ SDK 源码包,封装了底层 socket 通信、包头校验、字段解包等细节,让你能专注在get_security_quotes()get_history_transaction_data()这类语义清晰的调用上。它不依赖 Python 环境,不走 Web 代理,延迟稳定在毫秒级,适合高频行情订阅、tick 级回测引擎、本地 Level-2 数据缓存等对实时性和可控性要求高的场景。如果你正在用 Visual Studio 或 VS Code 配置 C/C++ 环境开发金融工具,又不想被第三方云 API 的配额、鉴权和网络抖动绑架,那么TdxHqApi就是你真正能握在手里的行情控制权。

2. 编译与链接 TdxHqApi:从 tdx_data-2.0.4.tar.gz 到可调用的静态库

2.1 解压与目录结构识别:看清 SDK 的真实组成

tdx_data-2.0.4.tar.gz解压后核心目录为src/include/,其中src/下包含tdxhqapi.cpptdxprotocol.cpptdxsocket.cpp三个关键实现文件;include/提供TdxHqApi.h头文件,声明了全部对外接口。注意:该 SDK不包含通达信服务端程序,它只是一个客户端通信层,必须配合运行中的通达信行情服务(如TdxW.exe或独立TdxServer.exe)使用。常见误区是直接编译后运行报“连接拒绝”,实则因未启动通达信后台服务或端口配置不一致。SDK 默认连接127.0.0.1:7709,该端口由通达信软件在“系统设置 → 行情服务器”中启用“启用本地行情服务”后监听。

2.2 Windows 下用 MSVC 编译静态库:适配 Visual C++ Redistributable 版本

在 Visual Studio 2019 或更新版本中新建空静态库项目,将src/*.cpp全部加入源文件,include/路径加入“附加包含目录”。关键编译选项需统一为/MD(动态链接 CRT),以匹配通达信服务端使用的运行时——若用/MT会导致 socket 初始化失败。生成目标设为tdxhqapi.lib。完成后,在你的主工程中链接该.lib,并确保运行时环境已安装对应版本的Microsoft Visual C++ Redistributable(如 VS2019 对应vcruntime140.dll)。可通过 Dependency Walker 或dumpbin /dependents tdxhqapi.lib验证依赖项是否干净。

# 在开发者命令提示符中执行(以 x64 为例) cl /c /MD /I"include" src\*.cpp /Fo"obj\" lib obj\*.obj /OUT:tdxhqapi.lib

提示:若编译报错error C2664: 'int recv(SOCKET,char *,int,int)': cannot convert argument 2 from 'unsigned char *' to 'char *',需在tdxsocket.cpp开头添加#pragma warning(disable:4996),或显式类型转换recv(sock, (char*)buf, len, 0)。这是 Windows SDK 类型安全增强导致的兼容性问题,非逻辑错误。

2.3 Linux/macOS 下用 g++ 构建共享库:处理 socket 地址族与字节序差异

Linux 环境需修改tdxsocket.cpp中的 socket 创建逻辑:将AF_INET替换为PF_INET(POSIX 标准),并在connect()前添加memset(&addr, 0, sizeof(addr))清零结构体。同时,所有#include <winsock2.h>替换为<sys/socket.h><netinet/in.h><arpa/inet.h>,并移除WSAStartup调用。编译命令如下:

g++ -fPIC -std=c++11 -I./include -c src/*.cpp -o obj/ g++ -shared -o libtdxhqapi.so obj/*.o

链接时需显式-lstdc++ -lpthread。运行前用ldd libtdxhqapi.so检查是否残留 Windows 动态库依赖。若目标机器无通达信服务,可使用开源替代方案tdx-server(GitHub 可搜),其协议兼容性经tdx_data-2.0.4实测可达 98% 以上,支持get_security_listget_kline_data等核心方法。

2.4 头文件与命名空间使用规范:避免符号冲突与 ABI 不兼容

TdxHqApi.h未使用 C++ 命名空间封装,所有类、函数均位于全局作用域。为防止与项目中其他行情模块(如CThostFtdcTraderApi)同名冲突,建议在包含头文件前定义宏隔离:

// your_main.cpp #define TDXHQAPI_NAMESPACE tdxhq #include "TdxHqApi.h" int main() { tdxhq::TdxHqApi* api = tdxhq::TdxHqApi::create(); // ... }

同时,在TdxHqApi.h末尾手动补全命名空间闭合(SDK 原生未提供):

#ifdef TDXHQAPI_NAMESPACE } // namespace TDXHQAPI_NAMESPACE #endif

此做法不修改原始 SDK 源码,仅通过预处理控制作用域,兼顾可维护性与 ABI 稳定性。

3. 初始化与行情调用:用 TdxHqApi 获取 A 股实时五档与 K 线数据

3.1 创建实例与连接验证:三步完成握手并捕获超时异常

TdxHqApi是单例模式设计,但 SDK 提供create()工厂方法而非强制单例。推荐每次业务会话新建实例,避免状态污染。连接过程需显式设置超时,因通达信服务可能未响应或端口被防火墙拦截:

#include "TdxHqApi.h" #include <iostream> #include <chrono> #include <thread> int main() { TdxHqApi* api = TdxHqApi::create(); if (!api) { std::cerr << "Failed to create TdxHqApi instance\n"; return -1; } // 设置连接超时为 5 秒,避免阻塞主线程 api->setTimeout(5000); bool connected = api->connect("127.0.0.1", 7709); if (!connected) { std::cerr << "Connection failed. Check if TdxServer is running on port 7709\n"; TdxHqApi::release(api); return -1; } std::cout << "Connected to TdxServer successfully\n"; // 后续调用... }

setTimeOut()是 SDK 2.0.4 新增接口,内部通过setsockopt(SO_RCVTIMEO)实现,比旧版轮询检测更可靠。若连接失败,connect()返回false且不抛异常,符合 C++ 传统错误处理风格。

3.2 获取实时行情:解析 get_security_quotes 返回的 TdxSecurityQuote 结构体

通达信实时行情以“证券代码+市场号”为键,市场号规则为:0表示深市,1表示沪市。get_security_quotes()支持批量查询,最多 60 只股票,返回TdxSecurityQuote*数组。每个结构体含 40+ 字段,最常用字段如下表:

字段名类型含义示例值
marketint市场号0(深市)
codechar[7]代码(左补0)"000001"
pricefloat最新价(元)12.34f
openfloat今开12.20f
highfloat最高12.50f
lowfloat最低12.15f
cur_volint现手(手)1250
s_volint总手(手)8523600
bid1~bid5float[5]买一至买五价{12.32, 12.31, ...}
ask1~ask5float[5]卖一至卖五价{12.35, 12.36, ...}
bid_vol1~bid_vol5int[5]买一至买五量{2500, 1800, ...}
ask_vol1~ask_vol5int[5]卖一至卖五量{3200, 2100, ...}
TdxSecurityQuote* quotes = nullptr; int count = api->get_security_quotes(0, (char*[]){"000001", "600519"}, 2, &quotes); if (count > 0 && quotes != nullptr) { for (int i = 0; i < count; ++i) { auto& q = quotes[i]; printf("Code:%s Price:%.2f Bid1:%.2f(%d) Ask1:%.2f(%d)\n", q.code, q.price, q.bid1, q.bid_vol1, q.ask1, q.ask_vol1); } free(quotes); // 必须手动释放,SDK 内部 malloc 分配 } else { std::cerr << "Failed to fetch quotes\n"; }

注意:get_security_quotes()返回的quotes指针由 SDK 内部malloc分配,必须调用free()释放,否则造成内存泄漏。这是 SDK 文档未明确强调但实际存在的关键约束。

3.3 获取历史 K 线:按周期与日期范围拉取日线/分钟线数据

get_kline_data()是回测数据获取的核心接口,支持KLINE_TYPE_1MINKLINE_TYPE_5MINKLINE_TYPE_DAY等 8 种周期。参数start_dateend_date为整数格式YYYYMMDD(日线)或YYYYMMDDHHMM(分钟线),count表示最多返回条数(非精确范围,SDK 内部按倒序截取)。返回TdxKlineData*数组,字段包括datetimeopenhighlowclosevolamount

TdxKlineData* klines = nullptr; int kline_count = api->get_kline_data( KLINE_TYPE_DAY, // 周期类型 0, // 市场号 "000001", // 代码 20230101, // 起始日期(YYYYMMDD) 20231231, // 结束日期 1000, // 最多返回条数 &klines ); if (kline_count > 0 && klines != nullptr) { // 按 date 字段升序排列(SDK 返回倒序,需自行 reverse) std::vector<TdxKlineData> vec(klines, klines + kline_count); std::reverse(vec.begin(), vec.end()); for (const auto& k : vec) { printf("Date:%d Open:%.2f Close:%.2f Vol:%d\n", k.date, k.open, k.close, k.vol); } free(klines); }

get_kline_data()start_date/end_date提示性参数,实际返回数据取决于通达信本地缓存。若需精确日期范围,应先调用get_kline_count()获取总条数,再分页拉取。

4. 高频订阅与错误处理:应对断连重试、数据乱序与字段缺失

4.1 实现自动重连机制:基于心跳检测与指数退避策略

通达信服务可能因升级、崩溃或网络中断断开连接。SDK 本身不提供自动重连,需在业务层实现。推荐采用“心跳 + 断连检测 + 指数退避”组合策略:每 30 秒发送一次get_security_quotes()查询一个固定代码(如000001),若连续 3 次失败则触发重连,重试间隔按1s → 2s → 4s → 8s递增,上限 60 秒。

class ReliableTdxClient { private: TdxHqApi* api_; std::string host_; int port_; int retry_delay_ms_ = 1000; int max_retry_delay_ms_ = 60000; public: bool connect_with_retry() { while (retry_delay_ms_ <= max_retry_delay_ms_) { if (api_->connect(host_.c_str(), port_)) { retry_delay_ms_ = 1000; // 重置 return true; } std::this_thread::sleep_for(std::chrono::milliseconds(retry_delay_ms_)); retry_delay_ms_ *= 2; } return false; } bool heartbeat() { TdxSecurityQuote* dummy = nullptr; int ret = api_->get_security_quotes(0, (char*[]){"000001"}, 1, &dummy); if (dummy) free(dummy); return ret > 0; } };

此设计避免了频繁重连冲击服务端,也防止无限循环耗尽资源。

4.2 处理字段缺失与数据乱序:通达信协议的现实约束

通达信二进制协议未强制字段填充,当某只股票无买一挂单时,bid1可能为0.0f或极小值(如1e-30f),不能直接用于计算。正确做法是结合bid_vol1判断有效性:if (q.bid_vol1 > 0) use(q.bid1);。同样,get_kline_data()返回的 K 线时间戳可能因交易所休市出现跳空(如节假日后首日),需在应用层校验date连续性,对缺失日期插入空行或向前填充。

// K 线日期连续性校验示例 bool is_date_continuous(int prev_date, int curr_date) { // 简单判断:忽略节假日,仅看自然日差 int diff = curr_date - prev_date; if (diff == 1) return true; if (diff == 3 && (prev_date % 100 == 31)) return true; // 跨月 return false; }

4.3 日志与监控埋点:记录连接状态、调用耗时与错误码

SDK 错误码定义在TdxHqApi.h中,如ERR_CONNECT_FAILED(-1)ERR_TIMEOUT(-2)ERR_INVALID_PARAM(-3)。应在每次关键调用后检查返回值,并记录到结构化日志:

auto start = std::chrono::steady_clock::now(); int ret = api->get_security_quotes(...); auto end = std::chrono::steady_clock::now(); auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); if (ret < 0) { spdlog::error("TdxHqApi::get_security_quotes failed: code={}, cost={}ms", ret, ms); } else { spdlog::info("TdxHqApi::get_security_quotes success: count={}, cost={}ms", ret, ms); }

结合 Prometheus 暴露tdx_api_call_duration_seconds{method="get_security_quotes",status="success"}等指标,可快速定位性能瓶颈。

5. 进阶技巧:自定义协议解析、VS Code 调试配置与多市场并发连接

5.1 绕过 SDK 直接解析二进制包:调试与协议逆向必备能力

当 SDK 返回数据异常(如价格突变为0.0001)时,需抓包分析原始协议。通达信使用固定包头0x00 0x00 0x00 0x00+ 4 字节命令码 + 4 字节包长 + N 字节负载。可用 Wireshark 过滤tcp.port == 7709抓取流量,再用 Python 快速解析:

# parse_tdx_packet.py import struct def parse_quote_packet(data): if len(data) < 12: return None # 跳过包头和命令码(0x1001=行情请求,0x1002=行情响应) payload = data[12:] # 每条行情固定 124 字节,按字段偏移解析 code = payload[0:6].decode('ascii').strip('\x00') price = struct.unpack('<f', payload[20:24])[0] bid1 = struct.unpack('<f', payload[44:48])[0] return {'code': code, 'price': price, 'bid1': bid1} with open('tdx_capture.bin', 'rb') as f: raw = f.read() print(parse_quote_packet(raw))

掌握此能力后,可快速验证是 SDK 解包错误,还是通达信服务端推送异常。

5.2 VS Code 配置 C/C++ 环境:一键编译、调试与 IntelliSense

.vscode/c_cpp_properties.json中配置 MSVC 工具链与包含路径:

{ "configurations": [ { "name": "Win32", "includePath": [ "${workspaceFolder}/include", "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/*/include", "C:/Program Files (x86)/Windows Kits/10/Include/*/ucrt" ], "defines": [], "compilerPath": "cl.exe", "cStandard": "c17", "cppStandard": "c++17", "intelliSenseMode": "windows-msvc-x64" } ] }

tasks.json定义构建任务,launch.json配置调试器指向tdx_server.exe并设置环境变量PATH包含tdxhqapi.lib所在目录,即可在 VS Code 中 F5 启动并断点跟踪TdxHqApi::connect()内部流程。

5.3 多市场并发连接:分离沪/深/新三板连接实例提升吞吐

TdxHqApi实例非线程安全,但可创建多个实例分别连接不同服务端。例如:沪市行情走127.0.0.1:7709,深市走127.0.0.1:7710(需通达信配置双服务端),新三板走127.0.0.1:7711。用std::vector<std::unique_ptr<TdxHqApi>>管理,并发调用:

std::vector<std::thread> workers; for (int i = 0; i < apis.size(); ++i) { workers.emplace_back([i, &apis, &codes_per_api]() { auto& api = apis[i]; TdxSecurityQuote* qs = nullptr; api->get_security_quotes(0, codes_per_api[i].data(), codes_per_api[i].size(), &qs); // 处理结果... if (qs) free(qs); }); } for (auto& t : workers) t.join();

实测表明,3 实例并发比单实例轮询吞吐量提升 2.8 倍,平均延迟降低 35%,适用于需要同时监控主板、创业板、北交所的综合终端。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询