跳到主要内容

TDX 通达信数据源

概述​

通达信是实时盘口与资金流的主源(K线/指数为第一备胎),使用 TCP 协议(端口 7709)直连通达信行情服务器,不经过 HTTP 层,因此不存在封IP风险。

自 v2.0 起改为项目内自包含协议实现(data_sources/tdx/ 包),已彻底移除 easy_tdx / mootdx / pytdx 等第三方 TDX 库依赖(python/requirements.txt 中不再出现), 随包分发、零外部依赖。

架构设计​

┌─────────────────────────────────────────────────────────┐
│ tdx/ (自包含协议实现) │
│ ├── codec — 协议编解码原语(帧头/价格/成交量/日期)│
│ ├── connection — TCP 连接管理(握手/心跳/测速/健康评分)│
│ ├── commands — 全部协议命令(请求构造+响应解析→dict) │
│ ├── client — 高层客户端(韧性执行/故障转移/业务方法)│
│ ├── adjust — 复权因子(0x000f 批量 GBBQ → qfq/hfq) │
│ └── f10 — F10 公司资料(官方 7615 TQLEX HTTP 网关)│
├─────────────────────────────────────────────────────────┤
│ tdx_client.py (对外门面/兼容适配层,26 个 get_* 函数) │
├─────────────────────────────────────────────────────────┤
│ tdx_client_compat.py(兼容层,re-export tdx_client) │
├─────────────────────────────────────────────────────────┤
│ tdx_client_backup_pool.py(降级路径:独立服务器池的第二条连接)│
└─────────────────────────────────────────────────────────┘

主备切换策略​

层级文件说明
协议实现tdx/ 包codec/connection/commands/client/adjust/f10,纯标准库
对外门面tdx_client.py26 个 get_* 函数(25 个数据接口 + 1 个内部辅助)
兼容层tdx_client_compat.pyre-export tdx_client,旧代码无需修改
降级路径tdx_client_backup_pool.py自带 _TDX_SERVERS 独立服务器池,主客户端所选主机异常时备用

实现文件​

  • 协议实现: backend/app/services/data_sources/tdx/(codec / connection / commands / client / adjust / f10)
  • 对外门面: backend/app/services/data_sources/tdx_client.py
  • 兼容层: backend/app/services/data_sources/tdx_client_compat.py
  • 降级路径: backend/app/services/data_sources/tdx_client_backup_pool.py

连接管理​

两阶段韧性连接​

自实现客户端内置两阶段故障转移机制:

  1. 同主机重试:指数退避 4 次,延迟序列 _RETRY_DELAYS = (0.5, 1.0, 2.0, 3.0) 秒
  2. 跨主机切换:当前主机连续失败后自动切换到下一台(find_verified_hosts() 并发测速优选)
# 自动选择延迟最低的服务器 + 自动重连 + 心跳保活(15s)
# timeout/budget 由生产调用方给保守值:超时 5s、韧性恢复总预算 5s,
# TDX 不可达时快速抛错降级(实测最坏曾达 ~75s)
client = TdxDataClient.from_best_host(
timeout=5.0,
auto_reconnect=True,
heartbeat_interval=15.0, # 15 秒心跳,连续 20 次失败判定连接失效
budget=5.0,
)
client.connect()

共享故障冷却(轻量熔断)​

tdx/client.py 在韧性执行层之上再做一层进程级冷却:连续失败达 _TDX_FAIL_THRESHOLD=2 次即进入冷却,期间所有 TDX 操作快速失败,由上层降级链(腾讯/东财)立即兜底; 冷却时长指数退避 30 → 60 → 120 → 240 → 300 秒封顶,任一成功即复位。 (避免 TDX 主机不可达时每个请求各自重走 5s 韧性预算,把 stocks/{code} 拖到 10s+、行业对比拖到 17~27s。)

健康评分系统​

  • 每次成功请求:record_success() 加分
  • 每次失败:record_failure() 降权
  • 服务器选择时优先使用健康分高的节点

空数据故障转移​

当某台服务器返回空数据时,自动逐台实测其他服务器,直到找到有效数据源。

连接复用​

全局单例 + 冷却机制,避免频繁 TCP 握手:

# tdx/client.py 单例管理(模块级)
_client: TdxDataClient | None = None
_client_lock = threading.Lock()
_last_fail: float = 0.0
_RETRY_INTERVAL = 30.0 # 初始化失败后的冷却期(秒)

def get_client() -> TdxDataClient:
"""获取全局 TdxDataClient 单例(失败后 30s 冷却)。"""
...

提供的数据(26 个 get_* 函数)​

基础行情接口​

功能函数说明
K线数据get_kline(code, category, offset)日/周/月/分钟K线
日K线get_daily_kline(code, count)日K线快捷方法
五档盘口get_quotes(codes)实时买卖五档 + 涨跌停价
全市场快照get_all_a_share_quotes()全A股实时快照(涨跌分布分桶用,覆盖不足 3000 只判不可用)
单股行情get_single_quote(code)单只股票完整行情
指数行情get_index_quotes()上证/深证/创业板/科创50(腾讯主源后的补齐源)
分时数据get_minute_data(code)当日240点分时走势
逐笔成交get_transactions(code, date)当日/历史逐笔
涨跌停价快照get_limits(code="")协议 0x0452,全市场或单股
集合竞价get_auction(code, count)协议 0x056A,竞价撮合序列(⚠️ 返回不含日期,见下方注意事项)

财务与基本面​

功能函数说明
财务快照get_finance_snapshot(code)30字段完整财务数据
财务信息get_finance_info(code)同 get_finance_snapshot
除权除息get_xdxr_info(code)分红送转、股本变动历史
复权因子get_adjustment_factors(codes)0x000f 批量 GBBQ → 本地 qfq/hfq 系数
F10资料get_f10(code, category)公司概况/财务分析等文本
F10结构化get_f10_company_profile_structured(code)公司概况键值对(写入 fox_company_profile)

市场与板块​

功能函数说明
全A股列表get_security_list_all()5000+股票,含行业映射
板块数据get_block_info(block_type)行业/概念/风格板块+成分股
市场统计get_market_stat()涨跌家数、涨停跌停、总市值
板块排行get_board_ranking(board_type)行业/概念涨跌排行
个股板块get_belong_board(code)个股所属板块列表

资金流向​

功能函数说明
当日资金流get_fund_flow(code)四级资金流(超大/大/中/小)
历史资金流get_history_fund_flow(code, days)日线资金流序列(0x0ffc 覆盖时用真实主力口径)
主力资金流get_money_flow_daily(code)0x0ffc 主站原生日线资金流(约最近 5 日)
MAC资金流get_capital_flow(code)多日主力/小单/中单/大单

与历史第三方库实现的差异​

早期版本用 mootdx / easy_tdx 等第三方库;现已全部由 tdx/ 包自实现, 能力覆盖已超过原库(数据源丰富化参考 eltdx 3.1.3 / 1.2.0):

特性自实现 tdx/(当前)早期第三方库
依赖纯标准库,零第三方依赖需额外安装,版本兼容受限
连接管理两阶段韧性+心跳+健康评分+共享冷却熔断单例缓存,无重连
故障转移协议级验证优选 + 跨主机自动切换无(或仅 TCP 连通性)
财务数据30 字段10 字段
行业映射通达信+申万行业代码无
板块数据行业/概念/风格无
市场统计涨跌/涨停/市值无
资金流向四级+历史+0x0ffc 原生主力无
复权K线前复权/后复权(GBBQ 因子本地化)无
除权除息完整历史无
F10官方 7615 TQLEX HTTP 网关(结构化)无

在降级链中的位置​

指数行情: 腾讯指数(主) → TDX 补齐缺失指数(双源互补,非故障切换)
K线数据: 腾讯K线(主) → TDX K线(备胎) → 东财 push2his(兜底)
北交所特例:新浪 → 东财(腾讯仅返最新 1 根、TDX 不覆盖北交所)
财务数据: TDX 财务快照 + 新浪利润表 → 快照构造单条兜底
涨跌分布: TDX 全市场快照统计(880005/880006,覆盖 ≥3000 只) → 东财区间统计(filter 已失效,恒判不可用)
→ fox_stock_wide 宽表(仅非交易时段) → 放弃分段保留实时家数
资金概况: TDX 实时成交额(880005) → fox_market_daily 上一日成交额兜底
涨跌分布/资金概况数据源说明

首页涨跌分布和资金概况优先使用 TDX TCP 实时统计(基于 880005/880001/880006 统计指数), 而非已移除的 stock_base_info 表聚合。DB 聚合路径自 2026-08-22 起已废弃 (db_market_breadth 等恒返回 None),仅剩「上一日总成交额」走 fox_market_daily。 这确保了首页始终展示当日实时市场广度。

两条「静默错值」防线(详见 数据源总览):

  • TDX 证券列表分页中断会只返回部分市场(实测沪市 2000 只后失败、深市整体跳过), tdx_market_breadth_full 以 _MIN_FULL_MARKET_QUOTES=3000 为覆盖下限,低于即判不可用;
  • 东财 push2 filter 参数自 2026-09-22 起被服务端忽略(15 路不同 filter 全部返回全量总数), em_market_breadth 用「2 路探针 + 家数/分段自洽校验」直接判不可用,不再把全等分段交给下游。

注意事项​

警告
  • TDX 客户端为同步阻塞实现,需在 ThreadPoolExecutor 中执行,避免阻塞 asyncio 事件循环
  • 连接可能因网络波动断开,客户端内置自动重连(同主机指数退避 4 次 0.5/1/2/3s + 跨主机切换)
  • 主机持续不可达时进入共享冷却(30→300s 退避),期间 TDX 操作快速失败并由上层降级链兜底
  • 非交易时段数据为上一交易日收盘数据
  • 批量命令逐只回退带连续失败熔断(_FINANCE_FALLBACK_MAX_STREAK=5), 避免 TDX 故障时全市场同步白耗数分钟并刷数千条 warning
get_auction(0x056A)返回的撮合序列不带日期 —— 必须自己设闸门

返回的每行只有 index / time(HH:MM:SS)/ hour / minute / second / price / matched_vol / unmatched_vol / unmatched_direction 等时段内字段,没有交易日字段。于是:

  • 非交易日、以及交易日 09:15(集合竞价开始)之前请求时, 它给出的是上一交易日的撮合序列;
  • 数值看着完全正常(如昨涨停股 +10% 开盘),调用方无从分辨;
  • 直接展示就等于把昨日行情标成「今日竞价」—— 静默口径错误,比报错危险得多。

正确用法:调用方按交易日历 + 窗口起点判定,无今日数据时不要取数。 参考实现 services/abnormal_moves._auction_session_state():

状态条件处理
ready交易日且 ≥ 09:15正常取数
pre_auction交易日但 < 09:15返回空,不触 TDX
non_trading_day周末 / 法定休市返回空,不触 TDX

另注:09:25 最终撮合价落定后,该序列当日冻结(不再变化), 故 09:30 之后可以给很长的缓存 TTL。

降级到 legacy 连接路径

自实现主客户端若出现不可预期的兼容性问题,可手动切到独立服务器池的备用路径:

# tdx_client_backup_pool.py 自带 _TDX_SERVERS 池,与主客户端互不影响
from .tdx_client_backup_pool import get_kline, get_quotes, ...

相关文档​