☰
同花顺Level-2全推行情Python API实战:涨停板策略落地与避坑指南
2026/10/15 9:47:37 网站建设 项目流程

简介:这份《同花顺level-2全推行情Python API操作手册》面向从事高频交易、量化投资及涨停板策略的开发者与交易者,系统讲解如何通过Python API获取并处理沪深市场Level-2高频行情数据。手册以PDF形式提供,压缩包内共1个文件,约850KB,内容紧凑、便于随查随用。目前已有2813人学习下载,在证券量化圈内具备一定参考热度。手册围绕TDS系统的C/S架构展开,涵盖五档与十档行情快照、逐笔成交、逐笔委托、委托队列及极速盘口等数据类型的订阅与回调处理,并完整梳理了从V2.0.0到V2.1.9的版本演进,包括多连接模式、级联功能、异步订阅接口、离线调试、通道号与委托序号字段、快照字段类型由int改为float等关键变更。读者可据此掌握初始化TDS实例、注册回调函数、设置连接市场与超时时间等实操要点,理解运行环境要求与安装验证流程,为搭建低延迟行情接入与量化策略提供清晰指引。

1. 拆开一份 Level-2 全推行情 Python 手册:涨停板策略到底能不能靠它落地

做涨停板排板的人最怕什么?不是选不到票,是行情慢半拍。你盯着五档盘口,看到封单突然撤了一大截,手速再快也来不及,因为数据到你这里已经隔了几百毫秒。这份《同花顺level-2全推行情Python API操作手册》要解决的,就是把这个延迟压下来,让 Python 直接吃到沪深两市的 Level-2 全推数据——十档盘口、逐笔成交、逐笔委托、委托队列,还有极速盘口。它适合两类人:一类是做高频或准高频策略的量化开发者,另一类是想把涨停板封单变化、撤单节奏做成可回测信号的交易系统搭建者。手册本身是 SDK 的接口说明加版本修订记录,从 V2.0.0 一路更到 V2.1.9,中间踩过的坑基本都写在修订说明里了。下面我按实际接入的顺序,把这份手册拆成能直接抄作业的步骤。

2. TDS 系统架构与 Python 环境落地:从 tar.gz 到 import datafeed

2.1 为什么是 C/S 结构而不是纯 Python 库

TDS 这套系统没有走纯 Python 实现的路子,而是 C/S 架构:底层用 C/C++ 从交易所 VDE 接入行情,做解码和订阅分发,Python 只是作为 API 的一层封装。这么设计的原因很直接——Python 的 GIL 在高频回调场景下会成为瓶颈,如果解码和分发都在 Python 层做,逐笔数据的吞吐根本扛不住。实际的数据流是:交易所 VDE → TDS 服务端(解码、订阅管理)→ SDK(C++ 动态库)→ Python API 回调。你拿到的data_list已经是解码后的结构化数据,Python 层只负责业务逻辑。

这个架构决定了两个事:第一,Python 端的回调函数里绝对不能做耗时操作,手册里专门警告了“否则很可能会导致接收实时行情堵包”;第二,SDK 的版本更新往往涉及底层协议变化,不是简单换个 py 文件就能解决的。

2.2 安装:root 权限和 import 验证

Linux 下安装需要 root 权限,这是第一个容易翻车的地方。很多人用普通用户pip install完了发现 import 报错,其实是动态库没写进系统路径。

# Linux 下需要 root 权限安装 sudo pip install ./L2-tdsapi-python-X.X.X-XXXXXXXX.tar.gz # 或者用 setup.py 方式 sudo python setup.py install

安装完成后必须做一步验证,手册里写得很清楚:

# 进入 Python 环境后执行 import datafeed # 没有异常抛出即为安装成功

如果这一步报ImportError,先检查 Python 版本是不是 3.5 以上 64 位,再检查动态库路径。Windows 下一般不会有权限问题,但要注意 SDK 的位数必须和 Python 解释器一致——64 位 Python 配 32 位 SDK 是经典翻车场景。

2.3 硬件和网络的门槛

手册给的运行环境要求是:64 位双核以上 CPU、8G 以上内存、下行 100Mb 以上带宽。这个配置看起来不高,但实际跑全市场订阅的时候,内存消耗主要来自回调函数里积压的数据。如果你在回调里做 DataFrame 拼接,8G 很快就不够了。我一般建议把回调里的数据处理逻辑做成“收到即入队列,另起线程消费”的模式,避免堵包。

网络方面,Level-2 全推的数据量在开盘时段非常密集,100Mb 下行是底线。如果同时订阅沪深两市的逐笔和快照,实际带宽占用会更高。手册里 V2.0.0 提到“SDK由单连接改为多连接模式,需要针对不同市场注册域名和端口”,这意味着沪深两市的连接是独立的,网络层面也要保证两条链路都稳定。

3. 回调注册与登录:set_env 的参数怎么填才不堵包

3.1 回调函数的定义规范

TDS 的所有行情数据都通过回调函数推送到应用层。手册里定义了 6 个行情回调加 1 个通知回调,每个行情回调的签名是固定的:

def fnc_data(data_list: list, count: int, stats: dict): """ @param data_list: 列表,包含订阅的行情数据,可能多条 @param count: data_list 中数据的条数 @param stats: 数据包在传输链路中到达各个节点的时间戳 {'produce_time': 服务接收到行情的时间, 'send_time': 服务发送行情的时间, 'recv_time': sdk接收到行情的时间} """ pass

stats这个参数很多人会忽略,但它其实是做延迟分析的关键。produce_time和recv_time的差值就是端到端延迟,如果你发现这个值在开盘时段突然变大,说明回调处理堵了。我一般会在回调里只做一件事:把data_list和stats一起塞进queue.Queue,然后立刻返回。

3.2 set_env 的参数详解

set_env是登录前必须调用的函数,它负责注册回调函数和设置环境参数。手册里列了十几个参数,但实际常用的就几个:

from datafeed.tds_api import TDS tds = TDS() def callback_stock(data, count, stats): # 只做入队,不做耗时处理 data_queue.put((data, count, stats)) tds.set_env( fnctickstock=callback_stock, # 证券快照回调 m_heartbeat_interval=10, # 心跳间隔,最小 1 秒 m_reconn_count=5, # 断线重试次数 m_reconn_interval=3, # 重连间隔秒数 m_timeout=5000, # 同步请求超时,默认 5000ms m_connectmarket="USH;USZ", # 连接市场,默认沪深都连 m_logpath="./tds_log", # 日志路径 m_loglevel="warn", # 日志级别 m_connectsubscribe=1 # 断线重连后自动重发订阅 )

几个关键参数的选择逻辑:m_heartbeat_interval不要设太小,1 秒是下限,实际用 5-10 秒比较稳;m_reconn_count设 0 或负数就是不重连,生产环境至少设 3 次以上;m_connectsubscribe=1是 V2.1.4 之后才有的,断线重连后自动重发订阅请求,省得自己写重连逻辑。

3.3 登录返回值与错误码排查

登录函数返回一个整数,0 表示成功,负数表示失败。手册里列了完整的错误码表,几个高频出现的:

返回值含义常见原因
-1004用户名密码错误账号配置问题
-1005无法连接至服务器网络不通或域名端口不对
-1014级联模式下主IP连接异常主SDK没启动或IP填错
-1016重复登录同一账号多处登录
-1018版本太低SDK 版本过旧,需更新
ret = tds.login('your_account', 'your_password') if ret != 0: print(f"登录失败,错误码: {ret}") # 根据错误码做对应处理

-1018这个错误码是 V2.1.3 才加进去的,之前版本遇到版本过低可能直接返回一个模糊的错误。如果你在旧版本上遇到登录失败但错误码对不上,优先考虑升级 SDK。

4. 订阅、查询与级联模式:多市场多实例的配置细节

4.1 同步订阅与异步订阅的选择

TDS 提供了两套订阅接口:同步的sub/unsub/add_sub/del_sub,和异步的async_sub。同步接口会阻塞直到服务端返回结果,异步接口通过fncsubscribe回调通知结果。

# 同步订阅:订阅 USHA 全市场证券快照 ret = tds.sub('stock', 'USHA', []) # 返回 0 表示成功,负数表示失败 # 异步订阅:V2.1.4 新增 ret = tds.async_sub('stock', 1, 'USHA', []) # op_type: 1-全新订阅 2-取消订阅 3-增加订阅代码 4-取消订阅代码

什么时候用异步?当你需要批量订阅多个市场多个数据类型的时候。同步接口每调一次都要等往返,批量操作会很慢。异步接口发出去就不管了,结果通过回调统一处理。但异步的代价是错误处理更麻烦——你得在fncsubscribe回调里根据statuscode判断哪些订阅成功了哪些失败了。

4.2 市场代码的坑

手册里列了完整的市场代码表,但有一个容易忽略的点:上证 A 股还包括 USHT(上证风险警示板)。如果你只订阅了 USHA,ST 股票的行情是收不到的。

市场号对应市场
USHI上海指数
USHA上海A股
USHB上海B股
USHD上海债券
USHJ上海基金
USHT上海ST风险警示板
USZI深圳指数
USZA深圳A股
USZB深圳B股
USZD深圳债券
USZJ深圳基金

做涨停板策略的话,USHT 必须单独订阅,否则 ST 股票的封单变化你完全看不到。

4.3 级联模式的配置

级联模式解决的是多实例场景下的数据分发问题。主 SDK 连接 datafeed 服务器,从 SDK 连接主 SDK 获取数据。配置分两步:

第一步,创建tool.ini文件,Python 版本放在程序文件同级目录:

# 主 SDK 的 tool.ini master=true socket_port=9999 # 从 SDK 的 tool.ini master=false socket_port=9998

注意socket_port后面必须接换行符,否则配置读取会失败——这是手册里专门提醒的坑。

第二步,从 SDK 调用register_addr注册主 SDK 的 IP 和端口:

tds = TDS() tds.set_env(fnctickstock=callback_stock) # 从 SDK 注册主 SDK 地址,必须在登录前调用 tds.register_addr('master', '192.168.1.100', 9999) tds.login('account', 'password')

级联模式有几个硬性约束:主 SDK 必须先登录成功,从 SDK 才能连接;主从必须在同一局域网;从 SDK 的账号密码要和主 SDK 一致。V2.0.8 对级联模式做了性能优化,如果用的是旧版本,多从节点场景下可能会有数据分发延迟。

5. 避坑排查:回调堵包、字段类型变更和离线调试的边界

5.1 回调函数里做耗时操作导致堵包

现象:开盘后一段时间,stats里的recv_time和produce_time差值越来越大,从几毫秒涨到几百毫秒甚至秒级,行情明显滞后。

原因:回调函数是在 SDK 的接收线程里同步执行的,如果你在回调里做 DataFrame 拼接、写数据库、发 HTTP 请求,接收线程就被阻塞了,后续数据包堆积。

解决:回调里只做入队操作,另起消费线程处理。队列用queue.Queue并设置合理的maxsize,满了就丢弃或落盘,不要无限堆积。

import queue import threading data_queue = queue.Queue(maxsize=10000) def callback_stock(data, count, stats): try: data_queue.put_nowait((data, count, stats)) except queue.Full: # 队列满了,记录丢弃计数 pass def consumer(): while True: data, count, stats = data_queue.get() # 在这里做数据处理 process(data) threading.Thread(target=consumer, daemon=True).start()

5.2 withdraw_buyturnover 类型从 int 变 float

现象:升级 SDK 后,原来用int接收撤单金额的代码报类型错误,或者数值精度丢失。

原因:V2.0.6 把证券快照的withdraw_buyturnover和withdraw_sellturnover从int改成了float。如果你在代码里做了强制类型转换或者用int做键,就会出问题。

解决:检查所有涉及这两个字段的计算逻辑,确保用float处理。如果数据要入库,确认数据库字段类型也改了。

5.3 离线调试模式不生效

现象:调用start_offline_debug后,登录仍然连接线上,或者回调不触发。

原因:手册里写得很清楚——离线调试函数必须在实例创建之后、登录之前调用。如果已经登录了,这个函数不生效。另外,数据文件的命名必须严格匹配stock.csv、index.csv、order.csv、queue.csv、trans.csv、superstock.csv、codelist.ini,命名不对 SDK 直接不读。

解决:确保调用顺序是TDS()→set_env()→start_offline_debug()→login()。数据文件放在指定路径下,文件名一字不差。

tds = TDS() tds.set_env(fnctickstock=callback_stock) # 必须在 login 之前调用 tds.start_offline_debug( path='D:\\datafeed', subtype=['stock', 'index', 'order', 'queue', 'trans', 'superstock'], push_space=3000, # 回放推送间隔 ms push_count=5000, # 单次推送条数 playback_times=1 # 遍历次数 ) tds.login('test', '123456') # 不会连接线上

5.4 消息通知回调参数类型变更

现象:V2.1.3 之前func_notify接收的是int,之后变成了dict,旧代码直接报错。

原因:V2.1.3 把消息通知回调函数的传入参数从int改成了dict,格式为{"code": int, "msg": str}。code的含义:1 表示网络断开,2 表示网卡不正常,3 表示重复登录被踢下线。

解决:更新回调函数签名,从def func_notify(code):改成def func_notify(msg_notify):,然后从msg_notify["code"]取错误码。

5.5 深交所交易方式字段的兼容问题

现象:2022.5.16 之后,深交所快照数据里出现了matching_volume、deal_mode、mode_state等新字段,旧代码解析时可能漏掉或者误读。

原因:2022.5.16 前深交所只有竞价交易数据,之后增加了协商成交、点击成交、询价成交、竞买成交等交易方式。原先快照字段的数值变成所有交易方式的汇总,同时额外提供 5 个字段来区分。

解决:如果你的策略依赖深交所快照的成交量字段,需要明确用的是汇总值还是匹配成交值。deal_mode为 1 表示匹配成交,mode_state的格式是“交易方式1交易状态1交易方式2交易状态2...”,解析时要按位拆。

6. 用离线调试做策略回放:一个可复现的验证流程

离线调试模式是这份手册里最被低估的功能。很多人只把它当“没行情的时候测试用”,但实际上它是做策略回测和回归验证的利器。你可以把历史逐笔数据整理成 CSV,用离线调试模式按真实的时间间隔回放,验证策略在历史行情下的表现。

具体做法:先从历史数据里导出某只股票某天的逐笔成交和快照,按手册要求的 CSV 格式整理好,表头字段名参照手册第 3 章的字段说明。然后启动离线调试,设置push_space和push_count来控制回放速度。

tds = TDS() def callback_trans(data, count, stats): for item in data: # 逐笔成交数据,包含通道号字段(V2.0.7 新增) print(item['code'], item['price'], item['volume']) tds.set_env(fnctransaction=callback_trans) tds.start_offline_debug( path='./historical_data', subtype=['trans', 'stock'], push_space=100, # 100ms 推送一次,模拟实时节奏 push_count=100, # 每次推 100 条 playback_times=1 ) tds.login('test', 'test')

这里有个细节:push_space和push_count的配合决定了回放速度。如果原始数据是每 3 秒一个快照,你可以设push_space=3000、push_count=1来精确模拟。但如果是逐笔数据,一天可能有几十万条,设push_space=100、push_count=100大概能在一小时内回放完一天的逐笔。

验证策略的时候,我习惯在回调里记录每笔数据的recv_time和策略信号时间戳,回放结束后对比两者的差值分布。如果差值在回放模式下很稳定,但在实盘模式下波动很大,说明实盘的瓶颈在网络或回调处理,不在策略逻辑本身。

还有一个容易忽略的点:级联模式下父节点支持离线调试,启动调试后子节点可以获取数据,子节点不需要开启离线调试。这意味着你可以在局域网里用一台机器做数据回放,多台机器同时消费,做分布式策略验证。

从那以后我每次接入新的行情 SDK,都强制走一遍“离线回放 → 延迟分布分析 → 实盘小规模验证”的流程,不再直接上实盘。希望帮到你。

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

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

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

立即咨询