pytdxdata
通达信(TongDaXin)行情数据客户端:动态连接池 + 双层TTL缓存 + 3连接并发分页(纯 asyncio,零运行时依赖)。
A股(沪/深/北) + 港股 + 美股 + 期货 + 期权,一套接口全市场。
参照 easy-tdx 重新实现,解决其三大短板(无连接池、串行分页、单连接单锁),协议层独立实现(不依赖 easy-tdx 包,仅参照其字节级格式)。
特性
| 特性 | 说明 |
|---|---|
| 🧩 动态连接池 | 启动时对服务器真实K线探测选优(剔除握手正常但数据返回空的坏节点),按等待队列/空闲时长动态扩缩容,健康分(失败×0.5/成功+0.2/冷却120s)+EWMA延迟选路,跨服务器故障转移 |
| 🗄️ 双层TTL缓存 | 内存LRU + 磁盘SQLite(WAL),TTL分级:报价5s / 分钟K线60s / 日线当天 / 复权K线1天 / 历史逐笔永久;single-flight 并发同键去重(只回源一次);缓存"已解析记录"(重复请求0网络0解析) |
| ⚡ 3连接并发分页 | 单请求拆N页(每页显式start偏移→无状态可并行),3连接并行拉取、按序拼接、失败换连接重试 |
| 🔀 双通道整合 | 标准通道(经典行情)+ MAC通道(逐笔/复权),按命令自动选路 |
| 📦 零重型依赖 | 纯 asyncio + stdlib(socket/zlib/struct/sqlite3),返回 list[dataclass],pandas 由调用方按需转换 |
安装
pip install pytdxdata # 或 uv add pytdxdata
从源码开发:
git clone <repo-url>
cd pytdxdata
uv sync # 创建虚拟环境 + 安装CLI
uv run python -c "import pytdxdata"
可选加速(uvloop):
uv add --optional uvloop uvloop
注:数据来自通达信公开行情服务器(无需账号),服务器清单由
server_probe.py导入时自动探测可用性与延时,存于servers.json。
CLI 命令行工具
pip install -e . # 或 uv sync,注册 tdx 命令
tdx quotes sz000001 # 行情报价(五档) / hk00700 / usAAPL
tdx kline sz000001 --period day --count 30 --adjust qfq
tdx kline cffex:IFL0 --count 30 # 期货K线(hk/us/zz/dl/shf/cffex/gz)
tdx transactions sz000001 --count 50 # 逐笔(含成交笔数)
tdx minute sz000001 # 分时
tdx index 000001 --count 30 # 指数K线
tdx board list / members 881001 / ranking / change --days 5
tdx info sz000001 # 个股快照
tdx list --market sz --count 100 # 证券列表
tdx auction sz000001 / unusual / xdxr / finance / flow
tdx server-info / market-stat
快速开始
import asyncio
from pytdxdata import TdxData
from pytdxdata.models import KlinePeriod, Market, Adjust
async def main():
async with TdxData() as td: # 自动建标准池(52台)+MAC池(3台)+缓存
# 日K线(count>800 自动3连接并发分页)
bars = await td.get_kline(1, "600000", KlinePeriod.DAY, count=2400)
# 分钟K线(复权走MAC通道)
m1 = await td.get_kline(0, "300308", KlinePeriod.MIN_1, count=240)
# 五档报价(TTL 5s 缓存,重复请求0网络)
q = await td.get_quotes([(1, "600000"), (0, "000001")])
# 逐笔成交(MAC通道,含 trade_count=成交笔数,支持历史回溯)
t = await td.get_transactions(0, "000001", date=20260811)
total_trades = sum(r.trade_count for r in t) # 当天总成交笔数
# 证券列表/数量
n = await td.get_security_count(0)
lst = await td.get_security_list(1, start=0, count=1000)
# 分时/除权除息/财务
minute = await td.get_minute(1, "600000")
xdxr = await td.get_xdxr(1, "600000")
fin = await td.get_finance(1, "600000")
asyncio.run(main())
API 参考
统一入口 TdxData(async with TdxData() as td: 自动 start/close)。
连接管理
| 方法 | 说明 |
|---|---|
start() / close() |
启动(服务器探测+预建连接+缓存)/ 关闭 |
__aenter__ / __aexit__ |
异步上下文管理器 |
行情接口
| 方法 | 返回 | 说明 |
|---|---|---|
get_kline(market, code, period, *, start, count, adjust) |
list[SecurityBar] |
K线(count>800自动并发分页;adjust≠NONE走MAC复权;88/000/399指数走指数命令) |
get_index_kline(market, code, period, *, start, count) |
list[SecurityBar] |
指数K线(多涨跌家数字段已处理) |
get_quotes(stocks) |
list[SecurityQuote] |
五档报价(>80只自动切批,缓存键=规范化股票集) |
get_transactions(market, code, *, date, start, count) |
list[TransactionRecord] |
逐笔成交(MAC,含 trade_count 成交笔数),支持历史回溯 |
get_minute(market, code, *, date) |
list[MinuteBar] |
分时(今日/历史) |
get_security_count(market) |
int |
市场证券数量 |
get_security_list(market, *, start, count) |
list[SecurityInfo] |
证券列表(count=None=全部,先查总数分页) |
get_security_list_all(market) |
list[SecurityInfo] |
全市场列表(缓存1天) |
get_xdxr(market, code) |
list[XdxrRecord] |
除权除息历史(标准) |
get_finance(market, code) |
FinanceRecord | None |
财务快照(标准) |
板块/竞价/异动(MAC)
| 方法 | 返回 | 说明 |
|---|---|---|
get_board_list(board_type, count) |
list[BoardInfo] |
板块列表(0=全部 1=行业 2=概念) |
get_board_members(board_symbol, count, sort_type) |
list[MemberQuote] |
板块成分股报价(自定义字段) |
get_board_summary(board_symbol) |
dict |
板块汇总(成分数/成交额/主力净流入/涨跌家数) |
get_board_ranking(board_type, top_n) |
list[dict] |
板块涨跌幅排行 |
get_board_change_ranking(board_type, days, top_n) |
list[dict] |
板块N日涨跌幅排行(板块指数K线) |
get_belong_board(market, code) |
list[BelongBoard] |
个股所属板块 |
get_auction(market, code) |
list[AuctionItem] |
集合竞价 |
get_unusual(market, start, count) |
list[UnusualItem] |
市场异动 |
get_capital_flow(market, code) |
CapitalFlow |
资金流向 |
快照/服务器/扩展(MAC)
| 方法 | 返回 | 说明 |
|---|---|---|
get_symbol_info(market, code) |
SymbolSnapshot |
个股特征快照 |
get_stock_quotes(stocks, bits) |
list[MemberQuote] |
MAC自定义字段报价 |
get_stock_quotes_list(category, count) |
list[MemberQuote] |
市场分类报价列表(0沪A/6全A/8科创/14创业) |
get_stock_kline_with_indicators(market, code, indicators, ...) |
dict |
K线+指标(MACD/KDJ/RSI/BOLL/MA/EMA) |
get_goods_list(market, start, count) |
list[GoodsItem] |
扩展市场商品(期货/期权) |
get_server_info() |
ServerInfo |
服务器交易时段 |
get_kline_offset(offset, count) |
tuple[int,int] |
K线偏移 |
get_chart_sampling(market, code) |
list[float] |
分时采样(扩展市场命令,A股不适用) |
文件/信息(标准+MAC)
| 方法 | 返回 | 说明 |
|---|---|---|
get_company_info_category/content(...) |
list / str |
F10公司信息(标准) |
get_block_info(filename) |
bytes |
板块文件下载(标准) |
get_report_file(filename) |
bytes |
报告/财务文件下载(标准) |
get_financial_file_list() |
list[str] |
财务文件列表(tdxfin/gpcw.txt) |
get_financial_records(filename) |
bytes |
财务文件内容(gpcw*.zip) |
get_file_meta(filename) / download_file(filename) |
FileMeta / bytes |
远程文件(MAC) |
get_price_limits(market, code, name, pre_close, listed_days) |
tuple |
涨跌停价(本地计算) |
get_market_stat() |
MarketStat |
全市场统计(涨跌家数/总额/市值/涨跌停数) |
数据模型(dataclass)
| 模型 | 关键字段 |
|---|---|
SecurityBar |
market/code/open/high/low/close/vol/amount/year/month/day/hour/minute + datetime属性 |
SecurityQuote |
price/pre_close/OHLC/vol/amount/s_vol/b_vol/bid[5]/ask[5]/server_time/trading_status |
TransactionRecord |
time/price/vol/trade_count/bs_flag |
SecurityInfo |
code/name(GBK)/volunit/decimal_point/pre_close |
XdxrRecord |
category/分红送转/缩股/行权等(除权除息) |
MinuteBar |
price/vol |
FinanceRecord |
股本/资产/营收/利润(万元/万股) |
枚举
Market:SZ=0 / SH=1 / BJ=2(北交所)KlinePeriod:MIN_5=0 / MIN_15=1 / MIN_30=2 / MIN_60=3 / DAY=4 / WEEK=5 / MONTH=6 / MIN_1=7 / MIN_3=8 / YEAR=9 / SEASON=10(与通达信协议字节一致)Adjust:NONE / QFQ(前复权)/ HFQ(后复权)
通道路由
| 命令 | 默认通道 | 说明 |
|---|---|---|
| K线(复权) | MAC | 支持QFQ/HFQ |
| K线(不复权)/指数 | 标准 | 价格小数位规则已验证 |
| 报价 | 标准 | 股票2位/指数ETF转债3位 |
| 逐笔成交 | MAC | 含trade_count,支持历史日期 |
| 列表/数量/分时/除权/财务 | 标准 | 仅标准通道提供 |
架构
src/pytdxdata/
├── api.py # 统一接口 TdxData(对外唯一入口)
├── router.py # 标准/MAC 通道选路
├── config.py # 服务器清单加载(servers.json + 环境变量覆盖)
├── protocol/ # 独立协议层(帧/变长整数/差分还原/自定义浮点/命令)
│ └── commands/ # kline/quotes/list/transaction/minute/xdxr/finance/mac
├── pool/ # 动态连接池(connection/health/pool)
├── cache/ # 双层TTL缓存(key/ttl/memory/disk/manager)
├── scheduler/ # 并发分页调度器(Paginator,3连接并行)
├── models/ # dataclass 模型 + 枚举
└── codec/ # 缓存载荷序列化(pickle+zlib)
扩展市场(EX通道:港股/美股/期货/期权)
get_kline 的 market 参数接受 ExMarket 枚举(港股/美股/期货/期权等52个市场):
from pytdxdata.models import ExMarket, KlinePeriod
# 港股(HK_MAIN_BOARD=31,代码5位)
bars = await td.get_kline(ExMarket.HK_MAIN_BOARD, '00700', KlinePeriod.DAY, count=700)
# 美股(US_STOCK=74)
bars = await td.get_kline(ExMarket.US_STOCK, 'AAPL', KlinePeriod.DAY, count=700)
# 期货(CFFEX=47 / 郑28 / 大29 / 上30,合约如 IFL0/rb2610)
bars = await td.get_kline(ExMarket.CFFEX_FUTURES, 'IFL0', KlinePeriod.DAY, count=700)
# 股票期权(沪8/深9,合约代码8位)
bars = await td.get_kline(ExMarket.SH_STOCK_OPTION, '10010971', KlinePeriod.DAY, count=700)
- 端口 7727,统一走 pytdx EX 协议(0x23FF K线 / 0x23FA 报价 / 0x23F4 市场列表)
- 4台EX服务器:MAC EX 2台(116.205.135.205 / 121.37.232.167,0x2454 login)+ pytdx EX 2台(通达信扩展市场 116.205.143.214 / 国泰君安 103.221.142.82,0x2454 setup)
- EX 辅助接口:get_goods_list / get_goods_count / get_goods_quotes / get_goods_tick_chart / get_goods_transaction 等
- 实测:腾讯00700=466.6 / AAPL=332.8 / IFL0=4683.2 / 沪期权10010971=0.192
- 美股/港股期权:通达信协议无数据(美股期权可用 CBOE 公开接口,见 quantdata/scripts/import/cboe_options.py)
与 easy-tdx 对比
| 维度 | easy-tdx | pytdxdata |
|---|---|---|
| 并发分页 | ❌ 串行 while 循环 | ✅ 3连接并行 |
| 连接池 | ❌ 单连接单锁 | ✅ 动态池+故障转移 |
| 缓存 | 仅证券列表(1天) | ✅ 双层TTL+single-flight |
| 数据正确性 | 基准 | ✅ K线6字段/报价7字段逐字段一致(实测) |
| 2400根日K耗时 | 0.31s | 0.16s(1.97x) |
| 缓存命中重取 | — | 0.016s(0网络) |
| 接口覆盖 | 基准 | 36/36 全覆盖 |
| 依赖 | pandas等 | 零运行时依赖 |
实测对比报告:examples/compare_report.md
已知限制
- 标准通道K线
count<100部分服务器返回空 → 分页器已强制min_page=100规避 - 标准当日逐笔的笔数字段协议中有但 easy-tdx 模型丢弃(pytdxdata 已显式解析);历史逐笔无笔数字段
- 报价价格小数位按品种推断(股票2位/指数ETF转债3位),同代码不同市场含义不同(SH 000001=指数 vs SZ 000001=股票)
- 行情数据来自通达信公开服务器,15分钟延时;需实时数据请使用券商行情
- 港股/美股/期货/期权数据走通达信 EX 通道(7727),部分市场(美股/港股期权)协议内无数据
- 服务器可用性随时间变化,可用
python -m pytdxdata.server_probe重新探测
免责声明
本包仅用于技术研究与教育目的。行情数据来自通达信公开接口,不保证实时性与准确性;作者不对任何投资决策负责。使用前请遵守通达信服务条款及相关法律法规。
测试
uv run pytest tests/ # 48个测试:协议/池/缓存/分页/API
目录
examples/quickstart.py— 快速示例examples/tdx_update_minute.py— 全市场分钟K线更新(含北交所,45s拉完5,539只)examples/compare_easy_tdx.py— 与 easy-tdx 对比脚本
Metadata
Release files for pytdxdata 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pytdxdata-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Release files / pytdxdata-0.3.0-py3-none-any.whl
| Download URL | pytdxdata-0.3.0-py3-none-any.whl |
|---|---|
| Size | 87.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ff45c2d93a8b4f4a6c96d9a6e091f9e54ba55bee86812631f5e691f2a9cee408
|
|
BLAKE2b-256 checksum How to use checksums |
62cc38e44d950f59d4ec6103c5d9978c7613fbca30ce5d519b9bc7b4ea54cb0f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|