☰
Level-2行情SDK部署避坑指南:环境对齐、回调配置与离线调试
2026/10/29 5:45:34 网站建设 项目流程

简介:面向高频交易与量化投资者的同花顺Level-2全推行情Python API操作手册,聚焦沪深市场深度行情获取与涨停板策略等实战场景,适合具备Python基础、希望接入逐笔成交与委托数据的中高级证券开发者。压缩包共1个文件,为PDF格式,约850KB,集中呈现SDK版本迭代记录与接口使用说明。手册梳理了从V2.0.0多连接模式改造、上证逐笔委托支持,到V2.1.9逐笔委托序号字段的完整演进,涵盖级联功能、离线调试、异步订阅接口及快照字段精度优化等细节;同时说明TDS系统的C/S架构、运行环境要求与初始化流程,并给出指数快照、证券快照、委托队列、逐笔委托、逐笔成交、极速盘口六类回调函数的注册方式与参数含义。已有2833人学习,可帮助读者快速理解行情订阅机制、字段变更影响与低延迟数据接入要点,为量化策略开发提供参考。

1. 装 Level-2 行情 SDK 前,先把版本和运行环境对齐

去年帮一个做涨停板策略的团队排查问题,对方在 Windows 上跑得好好的 Python 脚本,挪到一台 CentOS 7 的机器上,import datafeed直接报 ImportError,折腾了一下午才发现装的是 32 位 Python。这类翻车在 Level-2 全推行情 SDK 的部署里太常见了——行情数据本身对延迟敏感,环境差一点,回调里堵一次包,策略信号就慢半拍。同花顺这套 TDS 的 Python API 走 C/S 结构,SDK 直连行情网关,用回调把沪深 Level-1、Level-2 的十档快照、逐笔成交、逐笔委托、委托队列和极速盘口推上来,做量化、盯涨停板、算盘口失衡的开发者基本绕不开它。这篇笔记按我实际装过的顺序,把版本选择、依赖、安装、回调配置、级联和离线调试、排错验证一路写下来,新手能照着走通,熟手能对着版本差异和参数取舍少踩几个坑。

2. 版本选择与运行环境:Python 3.5 起步,64 位是硬门槛

2.1 从修订记录里挑一个能用的版本

这套 SDK 从 V2.0.0 到 V2.1.9 迭代了两年多,每个版本改的东西不一样,装之前先想清楚自己要用哪些能力,再倒推版本。下面这张表是我从修订说明里摘出来的关键节点,装的时候对着看:

版本关键变化什么时候必须升到它
V2.0.0单连接改多连接,支持上证逐笔委托,快照加买卖委托笔数、证券名称需要逐笔委托或十档委托笔数
V2.0.1支持级联,逐笔加业务序号,支持 Level-1,提供 Linux 支持要跑 Linux 或做局域网分发
V2.0.4新增极速盘口查询与订阅策略依赖极速盘口
V2.0.6withdraw_buyturnover、withdraw_sellturnover由 int 改 float算撤单金额,精度不能丢
V2.1.0增加离线调试,环境设置加m_connectmarket、m_timeout无行情时想本地回放调试
V2.1.3登录返回 -1018 版本过低;通知回调参数由 int 改 dict老代码升级要改回调签名
V2.1.4异步订阅async_sub,加m_connectsubscribe,快照加匹配成交相关字段要断线重连后自动重发订阅
V2.1.9逐笔委托增加委托序号逐笔委托要排序去重

我一般会直接上 V2.1.9,除非对接方明确要求某个旧版本。要注意 V2.1.3 是个分水岭:消息通知回调函数的入参从 int 变成了 dict,如果你从 V2.1.2 及以前升上来,fncnotify里取参数的方式必须改,否则运行时报类型错误。另外 V2.0.6 把两个撤单金额字段从 int 改成 float,历史代码里如果拿它做整数运算,升级后结果会变,这点在涨停板撤单率统计里尤其容易翻车。

2.2 硬件、系统和 Python 版本对照

官方给的运行环境不算苛刻,但每一条都有实际意义,别当摆设:

项目要求实际含义
CPU64 位双核及以上32 位 Python 装不上,这是最常见的 ImportError 来源
内存8G 及以上全市场订阅时回调数据量大,内存小容易堆积
带宽下行 100Mb 及以上全推行情是持续流,带宽不够会堵包
操作系统Windows 7 及以上、CentOS 7 等常用 LinuxLinux 下安装需要 root 权限
PythonPython 3.5(64 位)及以上低于 3.5 或 32 位一律不行

这里有个反直觉的点:很多人以为 Python 版本越高越好,实际上这套 SDK 的 tar.gz 包是按特定 Python 版本编译的,装之前先确认包名里的版本标识和本机 Python 对得上。我见过在 Python 3.11 上硬装 3.5 编译的包,import datafeed报的是符号未定义,不是简单的版本不匹配。稳妥做法是先用python -c "import platform; print(platform.architecture())"确认是 64 位,再看python --version是否 ≥ 3.5,两个条件都满足再往下走。

2.3 装之前先确认的三件事

第一,确认你有可用的行情账号和密码,SDK 登录走的是账号认证,没有账号装完也连不上。第二,确认网络能到行情网关,这套系统是 C/S 结构,SDK 要连服务端,公司内网如果有出站限制,提前找网络同事放行。第三,Linux 下准备好 root 权限,安装步骤里明确写了需要 root。这三件事任何一件没落实,后面装得再顺也是白装。

3. 安装 SDK:tar.gz 包两种装法,Linux 要 root

3.1 用 pip 装 tar.gz 包

拿到手的安装包长这样:L2-tdsapi-python-X.X.X-XXXXXXXX.tar.gz,X 是版本号,后面是编译标识。最省事的方式是 pip 直接装本地包:

# 进入安装包所在目录,确认 Python 是 64 位且 >= 3.5 python -c "import platform; print(platform.architecture())" python --version # 用 pip 安装本地 tar.gz 包,Linux 下前面加 sudo pip install ./L2-tdsapi-python-X.X.X-XXXXXXXX.tar.gz

pip install ./xxx.tar.gz会把包解压、编译、装进当前 Python 环境的 site-packages。这里的关键是「当前 Python 环境」——如果你机器上有多个 Python,一定要用which python和which pip确认两者指向同一个解释器,否则会出现 pip 装到了 A 环境、脚本跑在 B 环境、import 找不到的经典问题。Linux 下不加 sudo 通常会因为写 site-packages 权限不足失败,报 Permission denied,加上 sudo 即可。

3.2 用 setup.py 装

有些分发包不带 pip 元数据,或者你想指定安装参数,就走 setup.py:

# 解压安装包 tar -zxvf L2-tdsapi-python-X.X.X-XXXXXXXX.tar.gz cd L2-tdsapi-python-X.X.X-XXXXXXXX # Linux 下需要 root 权限 sudo python setup.py install

setup.py install和 pip 装的是同一个东西,区别在于前者不经过 pip 的依赖解析和缓存,适合离线环境或需要看安装日志的场景。装完会在输出里看到Finished processing dependencies,如果中途报编译错误,多半是 Python 版本或位数不对,回到 2.2 节重新核对。

3.3 验证导入是否成功

装完别急着写业务代码,先验证包能不能导入:

python -c "import datafeed; print('datafeed import ok')"

没有异常输出datafeed import ok就说明安装成功。如果报ModuleNotFoundError: No module named 'datafeed',先查pip show能不能看到包,看不到就是装错环境;能看到但导入失败,多半是位数或版本不匹配,卸载重装对应版本的包。这一步是整个部署的地基,地基不稳后面全是玄学问题。

4. 初始化与回调配置:set_env 的参数决定后面顺不顺

4.1 创建实例并注册行情回调

SDK 的工作方式是回调驱动:你注册函数,行情来了 SDK 调你的函数。最小可用骨架是这样:

from datafeed.tds_api import TDS # 创建实例 tds = TDS() # 行情推送回调,三个参数固定:数据列表、条数、链路时间戳 def callback_stock(data_list: list, count: int, stats: dict): # 不要在回调里做耗时操作,否则会堵包 print("receive count:", count) # 注册回调并设置环境参数 tds.set_env(fnctickstock=callback_stock)

set_env必须在创建实例之后、登录之前调用,而且必须先调它才能调后续的注册和登录。fnctickstock对应证券快照,另外还有fnctickindex(指数快照)、fncorderqueue(委托队列)、fncorderdata(逐笔委托)、fnctransaction(逐笔成交)、fncsuperstock(极速盘口)五个数据回调,以及fncnotify(断线通知)和fucsubscribe(异步订阅回调)。每个数据回调都必须接受(data, count, stats)三个参数,stats里是produce_time、send_time、recv_time三个微秒级时间戳,做延迟分析时直接拿它算链路耗时。

4.2 set_env 里值得改的几个参数

set_env的参数大多有默认值,但有几个我建议显式设置:

tds.set_env( fnctickstock=callback_stock, m_heartbeat_interval=5, # 心跳间隔,秒,最小 1 m_reconn_count=10, # 断线重试次数,<1 不重连 m_reconn_interval=3, # 重连间隔,秒 m_timeout=5000, # 同步请求超时,毫秒 m_connectmarket="USH;USZ", # 连接市场,可只填 USH 或 USZ m_connectsubscribe=1, # 重连成功后自动重发订阅 m_logpath="/var/log/tds", # 日志路径,默认在包安装目录 m_loglevel="warn" # 日志级别 )

m_connectmarket是 V2.1.0 加的,只做单市场时填USH或USZ能少连一条链路;m_connectsubscribe是 V2.1.4 加的,设成 1 后断线重连成功会自动重发订阅请求,不设的话重连后订阅全丢,行情静默,这个坑我在实盘环境里踩过一次,排查了半天才发现是订阅没恢复。m_logpath建议指到一个有写权限的独立目录,默认装在包目录下,升级或重装时日志容易被覆盖。

4.3 登录与返回值判读

登录接口很简单,但返回值必须判:

ret = tds.login('your_account', 'your_password') if ret != 0: print("login failed, code:", ret)

成功返回 0,失败返回负数。常见的几个:-1004 用户名密码错误、-1005 无法连接服务器、-1016 重复登录、-1018 版本太低需要更新程序。V2.1.3 起专门加了 -1018,意思是客户端版本低于服务端要求,遇到它别怀疑账号,直接换新包。另外 -1014 是级联模式下主 IP 连接异常,-1015 是级联模式要求同一局域网,这两个只在级联场景出现,普通模式不用管。

5. 订阅、查询与级联模式:把数据真正拉起来

5.1 同步订阅与查询接口

登录成功后,用sub订阅、unsub取消、add_sub加代码、del_sub删代码,都是同步接口,返回 0 表示成功:

# 订阅 USHA 全市场证券快照,[] 表示全市场 tds.sub('stock', 'USHA', []) # 增加 USHA 全市场逐笔成交订阅 tds.add_sub('trans', 'USHA', []) # 取消 USHA 快照订阅 tds.unsub('stock', 'USHA')

data_type支持index、stock、queue、order、trans、superstock六种。查询接口是同步拉取,适合补数据或做快照校验:get_code_list('USHI')拿代码表,get_tick_index('USHI', [])拿指数快照,get_tick_stock('USHA', ['600000'])拿指定证券快照,get_super_stock拿极速盘口。市场代码要记准,上交所 A 股是USHA,深交所 A 股是USZA,上证风险警示板是USHT,填错市场返回空列表,不报错,很容易误以为没数据。

5.2 异步订阅与订阅回调

V2.1.4 加了async_sub,订阅结果通过fucsubscribe回调通知,适合订阅量大、不想阻塞主线程的场景:

def on_subscribe(data_type, op_type, market, code_list, statuscode, callback_type): # statuscode 为 0 表示成功,其余为失败 print(data_type, market, statuscode) tds.set_env(fucsubscribe=on_subscribe) tds.async_sub('stock', 1, 'USHA', []) # op_type=1 全新订阅

op_type的取值:1 全新订阅、2 取消订阅、3 增加订阅代码、4 取消订阅代码。callback_type为 1 表示异步订阅触发,为 2 表示断线重连或手动登录后自动重发订阅触发。注意 V2.1.6 调整过订阅回调的参数,如果你对接的是旧版本文档,回调签名可能对不上,以实际包的接口为准。

5.3 级联模式:主从 SDK 的配置与注册

级联模式用于局域网内多个 SDK 实例共享一份行情:主 SDK 连行情服务器,从 SDK 连主 SDK。开启分两步,先建tool.ini,Python 版本放在程序文件同级目录:

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

socket_port后必须带换行符,否则配置读取失败,这是文档里专门提醒的细节。主从在同一台机器上时端口必须不同。然后从 SDK 在登录前注册主 SDK 地址:

tds.register_addr('master', '192.168.1.10', 9999) tds.login('your_account', 'your_password')

register_addr是级联模式下从 SDK 专用,主 SDK 不用调;必须在主 SDK 登录成功后,从 SDK 才能连;而且它位于登录前,顺序错了连不上。从 SDK 的账号密码要和主 SDK 保持一致。

5.4 离线调试:没有行情也能把流程跑通

V2.1.0 加的离线调试对开发阶段特别有用,没有实时行情时读本地 CSV 驱动回调:

tds.start_offline_debug( path='D:\\datafeed', subtype=['stock', 'index', 'order', 'queue', 'trans', 'superstock'], push_space=3000, # 推送间隔,毫秒 push_count=5000, # 单次推送条数 playback_times=1 # 遍历次数 ) tds.login('test1', '123456') # 不连线上网关,直接返回成功

数据文件命名必须是stock.csv、index.csv、order.csv、queue.csv、trans.csv、superstock.csv、codelist.ini之一,SDK 靠文件名判断数据类型,命名不规范直接不读。这个函数要在实例创建之后、登录之前调用,已经登录了再调不生效。级联模式下只有父节点支持离线调试,子节点调了无效。

6. 避坑与排查:这几条都是实打实踩出来的

6.1 导入报 ModuleNotFoundError

现象:import datafeed报找不到模块。原因:pip 装到了另一个 Python 环境,或者装的是 32 位包。解决:用which python和which pip确认指向同一解释器,python -c "import platform; print(platform.architecture())"确认 64 位,不匹配就卸载重装对应版本。

6.2 登录返回 -1018

现象:账号密码确认无误,登录返回 -1018。原因:客户端版本低于服务端要求,V2.1.3 起专门用这个码提示版本过低。解决:换最新版安装包重装,别在旧包上改配置。

6.3 断线重连后行情静默

现象:网络抖动后 SDK 重连成功,但回调不再触发。原因:没设m_connectsubscribe=1,重连后订阅没重发。解决:set_env里显式设m_connectsubscribe=1,或者用async_sub配合订阅回调自己重发。

6.4 回调里做耗时操作导致堵包

现象:行情延迟越来越大,stats里recv_time和produce_time差距持续拉大。原因:回调函数里做了数据库写入、复杂计算等耗时操作,SDK 推送被阻塞。解决:回调里只做入队,把处理逻辑放到独立线程或进程,回调保持轻量。

6.5 级联从节点连不上主节点

现象:从 SDKregister_addr后登录失败。原因:主 SDK 没先登录成功、端口配错、tool.ini的socket_port后缺换行符,或者主从不在同一局域网。解决:按顺序确认主 SDK 已登录、端口一致、ini 文件末尾有换行、网络同网段。

7. 装完怎么验证跑通:用离线回放做一次端到端自检

装完 SDK、配好回调,最怕的是「以为通了其实没通」。我的习惯是不管多急,都先用离线调试做一次端到端自检,因为它不依赖实时行情和网络,能把「实例创建 → set_env → 回调注册 → 数据推送 → 回调触发」整条链路走一遍。准备一个最小数据集:stock.csv放几行证券快照,表头按文档字段来,market、code、new_price、bidorder_price这些列名别写错,顺序不限但名字要对。然后跑下面这段:

from datafeed.tds_api import TDS received = [] def callback_stock(data_list, count, stats): # 只记录,不做耗时处理 received.append(count) print("count:", count, "first code:", data_list[0].get("code")) tds = TDS() tds.set_env(fnctickstock=callback_stock) tds.start_offline_debug( path='/data/offline', subtype=['stock'], push_space=1000, push_count=100, playback_times=1 ) ret = tds.login('test1', '123456') print("login ret:", ret)

判断标准有三条:login ret为 0;callback_stock被触发且count大于 0;data_list里能取到code字段。三条都满足,说明安装、回调注册、数据解析这条主链路是通的,再切到实时行情只需要换掉start_offline_debug和账号。如果回调没触发,先查 CSV 文件名是不是stock.csv、表头字段名是否和文档一致、subtype里有没有写stock;如果login ret非 0,回到第 4 章对返回码。

实时环境下的验证再加一步:订阅一个你熟悉的代码,比如tds.sub('stock', 'USHA', ['600000']),观察回调里stats的recv_time减produce_time,正常应该在毫秒级,如果持续在几百毫秒以上,多半是回调堵包或带宽不够。我一般会把这个延迟值打到日志里,跑一天看分布,比单次观察靠谱。

从那以后我每次部署这套 SDK,都强制先跑一遍离线回放再连实时,哪怕对接方催得再急也不跳过——有一次省了这一步,上线后发现回调签名和文档对不上,白白多排查两个小时。希望这套流程能帮到你,少走几个我踩过的坑。

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

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

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

立即咨询