
简介《同花顺level-2全推行情Python API操作手册》面向从事高频交易、量化投资及涨停板策略的证券开发者系统讲解如何通过Python API获取并处理沪深市场Level-2高频行情数据。手册围绕TDS系统的C/S架构展开涵盖五档与十档行情快照、逐笔成交、逐笔委托、委托队列及极速盘口等核心数据的订阅与解析并完整梳理了从V2.0.0到V2.1.9的版本演进包括多连接模式、级联功能、异步订阅接口、离线调试及字段精度优化等关键更新。资源包为1个PDF文件约850KB内容紧凑、查阅方便。目前已有2825人学习下载适合希望深入掌握Level-2行情接入、回调函数注册与运行环境配置的量化交易者可帮助读者快速理解API接口用法、版本差异与数据结构变化为构建低延迟交易策略提供扎实的数据支撑。1. 拆开一份 Level-2 行情 SDK从涨停板策略到逐笔委托的落地路径做涨停板策略的人大多有过这种体验盘口五档刚看到封单下一秒就被砸开回放录像才发现关键信息藏在逐笔委托里。普通 Level-1 快照三秒一推等你拿到数据板早就封死了。这份《同花顺 level-2 全推行情 Python API 操作手册》解决的正是这个问题——它把沪深两市的 Level-2 高频行情包括十档盘口、逐笔成交、逐笔委托、委托队列和极速盘口通过一个 Python SDK 全推给本地程序。适合谁做量化交易、高频策略、盘口行为分析尤其是盯着涨停板封单变化和撤单节奏的开发者。整套东西是 C/S 架构SDK 直连行情服务器回调式推数据不是轮询拉取延迟压得很低。下面按“能干什么 → 怎么跑 → 怎么改”的顺序把这份手册里的接口、字段和踩坑点拆一遍。2. 环境搭建与初始化从 pip 安装到回调注册的完整链路2.1 运行环境与安装步骤这套 SDK 对机器有硬性门槛不是随便一台笔记本就能跑顺的。官方给的配置是 64 位双核以上 CPU、8G 以上内存、下行 100Mb 以上带宽。带宽这条容易被忽略——Level-2 全推行情在开盘时段数据量很大带宽不够会直接堵包回调函数迟迟不触发你还以为是代码写错了。操作系统支持 Windows 7 及以上和 CentOS 7 等常见 Linux 发行版Python 要求 3.5 64 位及以上。安装分两种方式Linux 下需要 root 权限# 方式一直接 pip 安装 tar.gz 包 pip install ./L2-tdsapi-python-X.X.X-XXXXXXXX.tar.gz # 方式二解压后源码安装 python setup.py install装完之后验证是否成功进 Python 环境导入模块# 导入不报异常说明安装成功 import datafeed这里有个细节包名是datafeed但实际用的类是datafeed.tds_api里的TDS。导入datafeed只是验证安装完整性真正写代码时导入路径要写全。2.2 创建实例与回调函数定义整个 SDK 的工作模式是回调驱动。你不需要写循环去拉数据而是注册一堆回调函数行情到了 SDK 自动调你的函数。先创建实例from datafeed.tds_api import TDS # 创建 TDS 实例 tds TDS()然后定义行情推送回调。这个回调会被多种数据类型共用参数固定三个data_list是数据列表一次可能推多条、count是条数、stats是链路时间戳字典def fnc_data(data_list: list, count: int, stats: dict): SDK 回调函数接收处理行情数据 param data_list: 列表包含订阅的行情数据可能多条 param count: data_list 中数据的条数 param stats: 数据包在传输链路中到达各节点的时间戳字典 {produce_time: 服务接收到行情的时间(微秒), send_time: 服务发送行情的时间(微秒), recv_time: sdk接收到行情的时间(微秒)} passstats这个参数值得单独说。它给的是三个微秒级 Unix 时间戳分别对应行情到达服务端、服务端发出、SDK 收到。做延迟分析的时候用recv_time - produce_time就能算出端到端延迟用send_time - produce_time能看出服务端处理耗时。很多人拿到数据只看价格忽略了这个时间戳字典做高频策略时对延迟没有量化感知这是很吃亏的。除了行情回调还有两个回调必须了解。一个是断线通知回调SDK 多次重连失败后会停止工作通过这个回调告诉你def func_notify(msg_notify): 断线通知回调函数 机制断线后多次重连失败的反馈结果此时 SDK 已停止工作 响应用户应重新调用 Login 函数以及 sub 订阅事件 param msg_notify: 字典 {code: int, msg: str} code: 1网络断开, 2网卡不正常, 3重复登录被T下线 print(disconnect! notify: {}.format(msg_notify[msg]))另一个是订阅回调在异步订阅、断线重连后自动重发订阅时触发def func(data_type, op_type, market, code_list, statuscode, callback_type): 订阅回调函数 触发场景1、调用异步订阅函数2、断线重连成功或手动登录成功自动重发订阅请求 param data_type: 订阅数据类型 index/stock/queue/order/trans param op_type: 操作 1全新订阅 2取消订阅 3增加订阅代码 4取消订阅代码 param market: 市场代码 param code_list: 订阅的代码列表 param statuscode: 订阅状态0 为成功其余为失败 param callback_type: 1异步订阅请求, 2重连后自动重发订阅 print(statuscode)2.3 set_env 环境参数设置创建实例后、登录前必须先调set_env。这个函数把回调函数和环境参数一次性注册进去。参数很多但大部分有默认值一般只需要指定回调函数tds.set_env( fnctickstockcallback_stock, # 证券快照回调 fnctickindexcallback_index, # 指数快照回调 fnctransactoncallback_trans, # 逐笔成交回调 fncorderdatacallback_order, # 逐笔委托回调 fncorderqueuecallback_queue, # 委托队列回调 fncsuperstockcallback_super, # 极速盘口回调 fncnotifyfunc_notify, # 断线通知回调 fucsubscribefunc, # 异步订阅回调 m_heartbeat_interval10, # 心跳间隔(秒)最小 1 m_reconn_count5, # 断线重试次数1 不重连 m_reconn_interval3, # 重连间隔(秒)1 立即重连 m_timeout5000, # 同步请求超时(毫秒)默认 5000 m_connectmarketUSH;USZ, # 连接市场默认沪深都连 m_logpath./logs, # 日志路径默认 datafeed 安装目录 m_loglevelwarn, # 日志级别 m_connectsubscribe1 # 1断线重连后重发订阅 )几个参数需要根据场景调。m_connectmarket如果你只做沪市策略填USH就行少连一个市场能省带宽和资源。m_connectsubscribe建议设成 1否则断线重连后订阅全丢行情静默你都不知道。m_reconn_count和m_reconn_interval配合用网络抖动频繁的环境可以把重试次数调大、间隔调短。注意回调函数里不要做耗时操作。SDK 是单线程回调你在回调里写个数据库插入或者复杂计算直接导致后续行情堵包。正确做法是回调里只做数据入队另起线程消费。3. 登录、查询与订阅把行情数据拉到手的三板斧3.1 登录与返回值排查环境设好之后调login传入账号密码返回 int。成功返回 0失败返回负数# 登录成功返回 0失败返回 0 ret tds.login(test1, 123456) if ret ! 0: print(登录失败错误码:, ret)错误码是排查问题的第一手线索手册里列了完整的对照表。几个高频的-1004用户名密码错误-1005无法连接服务器通常是网络或域名端口问题-1016重复登录同一账号在别处登了-1018版本太低需要更新程序。特别说一下-1018这个错误码是 V2.1.3 才加上的之前版本过低时返回的是模糊错误排查起来很费劲。如果你拿到-1018别折腾代码了直接换新版 SDK。还有一个容易踩的-1014级联模式下主 IP 连接异常-1015级联模式下必须是同一局域网。这两个只在级联模式出现下面会单独讲。3.2 同步查询接口登录成功后可以先不订阅用同步查询接口拉一把数据验证链路通不通。查询接口是阻塞的调了等返回# 获取 USHI 市场所有代码列表 codes tds.get_code_list(USHI) # 获取 USHI 市场所有指数快照[] 表示全市场 index_data tds.get_tick_index(USHI, []) # 获取 USHA 市场 600000 的证券快照 stock_data tds.get_tick_stock(USHA, code_list[600000]) # 获取 USHA 市场 600000 的极速盘口需额外产品权限 super_data tds.get_super_stock(USHA, code_list[600000])市场代码是个必须记牢的东西填错了返回空列表或者报-1007错误市场。沪深两市的对应关系如下市场号对应市场市场号对应市场USHI上海指数USZI深圳指数USHA上海A股USZA深圳A股USHB上海B股USZB深圳B股USHD上海债券USZD深圳债券USHJ上海基金USZJ深圳基金USHP上海退市整理USZP深圳退市整理USHT上海ST风险警示板注意上证 A 股还包括 USHT风险警示板做全市场扫描的时候别漏了这个市场否则 ST 股的行情拿不到。3.3 订阅接口与异步订阅查询是拉模式订阅是推模式。实盘策略用订阅数据到了自动回调。订阅接口有四个同步的加一个异步的# 订阅 USHA 全市场证券快照[] 表示全市场 tds.sub(stock, USHA, []) # 取消 USHA 快照的所有订阅 tds.unsub(stock, USHA) # 增加 USHA 全市场逐笔成交订阅 tds.add_sub(trans, USHA, []) # 取消 USHA 全市场快照订阅 tds.del_sub(stock, USHA)sub和add_sub的区别要搞清楚sub是取消该市场该类型的所有订阅然后重新订阅add_sub是在已有订阅基础上追加代码。如果你先sub了 600000再add_sub600001结果是两个都在订阅里但如果你再调一次sub只传 600002那 600000 和 600001 的订阅全被清掉只剩 600002。这个语义差异在动态调整订阅列表时特别容易翻车。异步订阅接口async_sub是 V2.1.4 加的适合订阅量大、不想阻塞主线程的场景# 异步订阅结果通过 fucsubscribe 回调通知 tds.async_sub(stock, 1, USHA, [600000, 600001])参数op_type对应操作类型1 全新订阅、2 取消订阅、3 增加订阅代码、4 取消订阅代码。异步订阅的结果不在返回值里而是在你注册的fucsubscribe回调里通过statuscode判断成功失败。3.4 级联模式配置级联模式解决的是局域网内多实例分发的场景。比如你有一台机器专门接行情另外几台跑策略不想每台都去连行情服务器就用级联主 SDK 连服务器从 SDK 连主 SDK。配置靠一个tool.ini文件放在程序文件同级目录Python 版本# 主 SDK 的 tool.ini mastertrue socket_port9999 # 从 SDK 的 tool.ini masterfalse socket_port9998socket_port如果主从在同一台机器上端口必须不同。端口号后面要接换行符否则配置读取会失败——这个坑很隐蔽文件末尾没换行参数就是读不进去。从 SDK 在登录前要调register_addr注册主 SDK 地址# 从 SDK 注册连接的主 SDK IP 和端口 tds.register_addr(master, 192.168.1.100, 9999) # 从 SDK 的账号密码需要与主 SDK 保持一致 tds.login(test1, 123456)顺序不能错主 SDK 先连接登录成功从 SDK 再register_addr然后登录。register_addr必须在login之前调。4. 数据字段与离线调试快照、逐笔和本地回放4.1 证券快照字段解析证券快照是策略里用得最多的数据。Level-2 快照比 Level-1 多了十档盘口、委托笔数、撤单统计等字段。核心字段如下字段类型含义marketstr市场codestr代码codenamestr代码名称statusstr当前状态集合竞价、休市等dateintYYYYMMDDtimeintHHMMSSssspre_pricefloat昨收价open_pricefloat开盘价high_pricefloat最高价low_pricefloat最低价new_pricefloat最新价volumeint成交量股票股债券张turnoverfloat成交金额trade_numint成交笔数bidorder_pricelist申买价买一到买十bidorder_volumelist申买量买一到买十bid_numorderslist委托笔数买一到买十askorder_pricelist申卖价卖一到卖十askorder_volumelist申卖量卖一到卖十ask_numorderslist委托笔数卖一到卖十totalbid_volumeint总委买量totalask_volumeint总委卖量avgbid_pricefloat加权平均委买价avgask_pricefloat加权平均委卖价withdraw_buynumint买入撤单笔数沪withdraw_buyvolumeint买入撤单数量沪withdraw_buyturnoverfloat买入撤单金额沪withdraw_sellnumint卖出撤单笔数沪withdraw_sellvolint卖出撤单数量沪withdraw_sellturnoverfloat卖出撤单金额沪totalbid_numint买入总笔数沪totalask_numint卖出总笔数沪bidorder_numint买方委托价位数沪askorder_numint卖方委托价位数沪inner_volumeint内盘成交量outer_volumeint外盘成交量aftermarket_volumeint盘后成交量aftermarket_volmountint盘后成交次数matching_volumeint匹配成交量深matching_turnoverfloat匹配成交金额深matching_pricefloat匹配成交价深deal_modeint成交方式深mode_statestr各交易方式状态深status字段的编码规则要单独记。上证第一位S启动、C开盘集合竞价、T连续交易、E闭市、P停牌、M可恢复熔断、N不可恢复熔断、U收盘集合竞价。第二位0不可正常交易、1可正常交易。第三位0未上市、1已上市。第四位0不接受订单申报、1可接受订单申报。深证第一位S启动、O开盘集合竞价、T连续竞价、B休市、C收盘集合竞价、E已闭市、H临时停牌、A盘后交易、V波动性中断。第二位0正常、1全天停牌。deal_mode是深市 2022.5.16 之后新增的字段1匹配成交、2协商成交、3点击成交、4询价成交、5竞买成交。快照里的deal_mode表示最近一笔成交的成交方式。mode_state格式是“交易方式1交易状态1交易方式2交易状态2...”比如1T2T3T4T5T表示五种交易方式都处于连续竞价状态。4.2 离线调试模式离线调试是 V2.1.0 加的功能对策略回测和开发阶段特别有用。没有实时行情的时候SDK 读本地 CSV 文件来驱动回调完全模拟实时推送的行为。数据文件命名有严格要求必须是这几个之一stock.csv、index.csv、order.csv、queue.csv、trans.csv、superstock.csv、codelist.ini。SDK 根据文件名判断数据类型命名不对就不读。CSV 表头字段名参照模板顺序不限。# 进入离线调试模式 tds.start_offline_debug( pathD:\\datafeed, # 数据文件路径 subtype[stock, index, order, queue, trans, superstock], push_space3000, # 回放推送间隔(ms) push_count5000, # 单次推送条数 playback_times1 # 数据文件遍历次数 ) # 登录不会连接线上服务器直接返回成功 tds.login(test1, 123456)离线调试的规则有几个关键点。调用查询市场代码函数时读codelist.ini里对应市场的数据文件不存在返回空。调用查询快照函数时读对应数据文件的前 3000 条指数前 300 条剔除重复代码后生成查询数据集。订阅接口在离线模式下直接返回成功SDK 按文件名顺序读取每次读指定条数间隔指定时间再读文件遍历完切换下一个文件所有文件完成指定循环次数后调试结束。start_offline_debug必须在实例创建之后、登录之前调用。如果已经登录了这个函数不生效。级联模式下父节点支持离线调试启动后子节点能获取数据子节点不支持离线调试调了也没用。5. 避坑与排查那些手册没明说但一定会遇到的问题5.1 回调堵包导致行情延迟现象开盘后行情回调越来越慢最后几秒才收到一批数据stats里的recv_time和produce_time差距越来越大。原因回调函数里做了耗时操作。SDK 回调是单线程的你在回调里写数据库、做复杂计算、甚至print大量日志都会阻塞后续行情处理。解决回调里只做数据入队用queue.Queue或者collections.deque把数据丢进去另起消费线程处理。日志级别设成warn别用debugdebug级别在开盘时会产生海量日志拖慢速度。5.2 断线重连后订阅丢失现象网络抖动后行情突然没了程序没报错但回调不触发。原因m_connectsubscribe没设成 1断线重连后 SDK 不会自动重发订阅请求。解决set_env时把m_connectsubscribe1。同时注册fncnotify回调收到断线通知后主动检查订阅状态。如果m_reconn_count设得太小重连失败后 SDK 直接停止工作这时候必须重新login和sub。5.3 级联模式端口配置不生效现象从 SDK 调register_addr后连接失败或者主 SDK 根本没监听。原因tool.ini里socket_port后面没接换行符配置读取失败SDK 用了默认端口或者没进级联模式。解决确保tool.ini每个配置项后面都有换行符文件末尾也要有。主从 SDK 在同一台机器时socket_port必须不同。从 SDK 的register_addr必须在login之前调顺序错了连不上。5.4 市场代码填错导致数据为空现象get_tick_stock返回空列表或者订阅后回调不触发。原因市场代码填错。比如把USHA写成USAH或者做全市场扫描时漏了USHT风险警示板。解决对照市场代码表逐一核对。上证 A 股要同时订阅USHA和USHT才能覆盖全部 A 股。查询接口返回空列表时先检查市场代码再检查代码是否属于该市场。5.5 离线调试文件不读取现象start_offline_debug返回成功但回调不触发。原因CSV 文件名不符合规范或者表头字段名和模板不一致。SDK 按文件名判断数据类型命名不对直接跳过。解决文件名严格用stock.csv、index.csv、order.csv、queue.csv、trans.csv、superstock.csv、codelist.ini。表头字段名参照模板顺序可以不同但名称必须匹配。start_offline_debug必须在login之前调登录后再调不生效。6. 二次开发改造从能跑到好用的几个关键动作拿到这份 SDK 跑通 demo 只是第一步真正用到策略里还得做几层封装。我一般会先包一个数据分发层把 SDK 的回调数据按类型路由到不同的处理队列避免所有逻辑堆在一个回调里。具体做法是定义一个DataDispatcher类内部维护多个queue.Queuefnc_data回调只负责判断数据类型然后入队消费线程各自处理。import queue import threading from datafeed.tds_api import TDS class DataDispatcher: def __init__(self): self.queues { stock: queue.Queue(maxsize100000), trans: queue.Queue(maxsize100000), order: queue.Queue(maxsize100000), } self.running True def on_stock(self, data_list, count, stats): # 回调里只入队不做任何耗时操作 for item in data_list: try: self.queues[stock].put_nowait(item) except queue.Full: # 队列满说明消费跟不上丢弃并告警 pass def consume(self, qtype, handler): q self.queues[qtype] while self.running: try: item q.get(timeout1) handler(item) except queue.Empty: continue队列设maxsize很关键。不设上限的话消费跟不上时内存会一直涨最后 OOM。设了上限队列满时丢弃数据并告警至少程序不会崩。丢弃策略看策略需求涨停板策略可能更在意最新数据丢老数据比丢新数据好。第二层改造是断线自愈。SDK 的fncnotify回调告诉你断线了但重连和重新订阅的逻辑得自己写。我的做法是维护一个订阅状态表记录当前订阅了哪些市场、哪些类型、哪些代码。收到断线通知后起一个重连线程按状态表重新login和sub。class SubscriptionManager: def __init__(self, tds): self.tds tds self.subs {} # {(data_type, market): set(code_list)} def subscribe(self, data_type, market, code_list): key (data_type, market) if key not in self.subs: self.subs[key] set() self.subs[key].update(code_list) self.tds.sub(data_type, market, list(self.subs[key])) def restore_all(self): # 断线重连后调用恢复所有订阅 for (data_type, market), codes in self.subs.items(): self.tds.sub(data_type, market, list(codes))第三层是离线调试和实盘的切换。开发阶段用离线调试跑历史数据验证策略逻辑上线前切到实盘用同一套回调处理代码。关键是回调函数的签名和数据处理逻辑完全一致这样离线验证过的逻辑直接能用。我一般会在配置里加一个mode字段offline时调start_offline_debuglive时正常login上层策略代码不用改。验证方法上我习惯先跑离线调试用一小段历史数据确认回调触发、字段解析、策略信号都正常然后连实盘但只订阅一两只票观察stats里的延迟数据确认端到端延迟在可接受范围最后逐步扩大订阅范围同时盯着队列长度和内存占用。这套流程走下来基本能避免上线后才发现堵包或者订阅丢失的问题。从那以后我每次接新的行情 SDK都强制先跑一遍离线调试把字段解析和回调逻辑验证完再连实盘。这个习惯帮我省了很多次开盘时手忙脚乱排查的麻烦。希望帮到你。本文还有配套的精品资源点击获取