受 pytdx / mootdx 启发的 A 股数据获取工具(Rust 实现):
- 一个 Rust 通用库 rustdx-complete:通达信行情协议 + 本地数据文件解析 + 技术指标;
- 一个命令行工具 rustdx-cli:解析通达信 day 文件、东财日线增量更新、ClickHouse 写入。
- 行情协议全覆盖:实时行情(含五档盘口)、K线、指数K线、当日/历史分时、当日/历史逐笔、财务信息、除权除息、F10 公司资料、板块文件(概念/指数/风格)
- 连接可靠性:40 台服务器协议级自动故障转移、心跳保活、失败自动重连重试、超时可配置
- 数据正确性:全部协议按 pytdx 源码逐字节对照并经交易时段实盘验证;解析异常时返回空数据而非垃圾数据
- 本地 day 文件并发解析:rustdx-cli 多线程并行解析(线程数=逻辑核心数),并支持带字母的特殊品种代码(如深市板块指数
sz200b07) - 技术指标:SMA/EMA/MACD/RSI/布林带/KDJ
- 辅助能力:交易日历、智能缓存、连接池、Builder 模式 API、数据验证
- 229 个测试(含真实抓包字节的回归测试),clippy 零警告
[dependencies]
rustdx-complete = "1.8.0"或 cargo add rustdx-complete。
use rustdx_complete::tcp::stock::{market_of, Adj, Client};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 连接(内置 40 台服务器故障转移、心跳与重试)
let mut client = Client::new()?;
// 实时行情(代码自动推断市场)
let code = "600519";
let quotes = client.quotes(&[(market_of(code).unwrap(), code)])?;
for q in "es {
println!("{}: {:.2} (昨收 {:.2}, {:+.2}%)", q.code, q.price, q.last_close, q.change_percent);
}
// 按日期区间拉取日K线
let bars = client.k(1, "600519", Some(20260801), Some(20260904))?;
for b in &bars {
println!("{}-{:02}-{:02} 收{:.2}", b.dt.year, b.dt.month, b.dt.day, b.close);
}
// 批量拉取多只日K(内部连接池并行,顺序返回;单只失败不影响其他)
let batch = client.k_batch(&[(1, "600000"), (0, "000001"), (1, "600519")],
Some(20260101), None, 4)?;
for row in &batch {
println!("{}: {} 根", row.code, row.result?.len());
}
// 复权日K(前复权:最新价 = 实际价;服务器不提供复权,本地按除权除息计算)
let qfq = client.k_adjusted(1, "600519", Adj::Qfq, Some(20240101), Some(20261231))?;
let hfq = client.k_adjusted(1, "600519", Adj::Hfq, Some(20240101), Some(20261231))?;
// 概念板块(服务器真实数据,269 个板块)
let blocks = client.block("block_gn.dat")?;
let lidian: Vec<_> = blocks.iter().filter(|r| r.blockname == "锂电池").collect();
println!("锂电池板块 {} 只成分股", lidian.len());
Ok(())
}| mootdx 方法 | rustdx API | 说明 |
|---|---|---|
quotes |
Client::quotes / SecurityQuotes |
实时行情快照,含五档盘口、内外盘、服务器时间 |
bars |
Client::bars / Kline |
股票K线(5m/15m/30m/1h/日/周/月…,category 0-11) |
index / index_bars |
Client::index_bars / IndexKline |
指数K线,含上涨/下跌家数 |
k |
Client::k |
按日期区间拉日K线,自动翻页 |
| —(rustdx 新增) | Client::bars_range |
任意周期(5m/15m/…)K线区间回补:自动翻页+去重+乱码年份终止 |
| —(rustdx 新增) | Client::k_batch |
批量日K,内部连接池并行,单只失败不影响其他 |
| —(rustdx 新增) | Client::k_adjusted |
前/后复权日K,本地按除权除息计算 |
minute |
Client::minute / MinuteTime |
当日分时(2026 新协议已支持,异常时自动回退历史分时) |
minutes |
Client::history_minute / HistoryMinuteTime |
历史分时 |
transaction |
Client::transaction / Transaction |
当日逐笔成交 |
transactions |
Client::history_transaction / HistoryTransaction |
历史逐笔成交 |
finance |
Client::finance / FinanceInfo |
35 个财务字段 |
xdxr |
Client::xdxr / Xdxr |
除权除息/送配股等股本变迁 |
F10C / F10 |
Client::f10_categories / Client::f10 |
公司资料栏目与内容 |
block |
Client::block / get_block_info |
板块文件(block_gn/zs/fg.dat) |
stocks / stock_count |
Client::stocks / stock_count |
全量证券列表(自动分页) |
bestip / check_server |
tcp::ip::check_alive / check_alive_protocol |
服务器连通性探测(TCP/协议级) |
| heartbeat / auto_retry | Tcp::heartbeat / Tcp::retry |
心跳保活、失败自动重连重试 |
不计划支持:mootdx
ExtQuotes扩展市场(官方标注已失效)。
每个协议对应一个请求结构体,实现统一的 Tdx trait(send / recv / parse / recv_parsed):
use rustdx_complete::tcp::{Tcp, Tdx};
use rustdx_complete::tcp::stock::SecurityQuotes;
let mut tcp = Tcp::new()?; // 故障转移 + 握手
let mut quotes = SecurityQuotes::new(vec![(0, "000001"), (1, "600000")]);
quotes.recv_parsed(&mut tcp)?;
for q in quotes.result() {
println!("{}: 买一 {:.2}×{:.0} 卖一 {:.2}×{:.0}",
q.code, q.bid1, q.bid1_vol, q.ask1, q.ask1_vol);
}连接层能力:
use rustdx_complete::tcp::{ip, Tcp, TcpConfig};
use std::time::Duration;
// 指定服务器与超时
let cfg = TcpConfig { timeout: Duration::from_secs(5), ip: Some(ip::STOCK_IP[0]), ..Default::default() };
let mut tcp = Tcp::with_config(&cfg)?;
// 心跳 / 重连 / 自动重试
tcp.heartbeat()?;
tcp.reconnect()?;
// 断线自动重连:0 = 关闭(默认,保持旧行为);1~2 = 请求失败时自动重连并重发
// 行情请求是幂等的,长时运行的策略程序建议开启,避免偶发断线后整条链路失败
let cfg = TcpConfig {
timeout: Duration::from_secs(5),
auto_reconnect: 2,
..Default::default()
};
let mut tcp = Tcp::with_config(&cfg)?;所有
Client方法(quotes/k/k_batch/k_adjusted/minute/xdxr等)出错时, 错误信息都会附带接口名 + 市场/代码 + 字段上下文(如k(1, 600519): 服务器无响应),保留原始错误类型,便于直接定位是哪个请求、哪只股票失败。
indicators:SMA/EMA/MACD/RSI/布林带/KDJ,与K线数据无缝衔接calendar:A股交易日历(法定节假日,数据源 trade_date_a)limit:涨跌停域规则——板块判定(主板/创业板/科创/北交)、涨跌停价(四舍五入到分,ST 5%/20%/30% 规则齐)、封板/炸板判型、连板高度cache:内存/文件缓存(TTL 过期)pool:TCP 连接池builder:KlineBuilder 链式 APItcp::stock::validator:K线连续性/财务一致性验证、异常值检测file:通达信本地文件解析(.day 日线、.lc1/.lc5 分钟线、gbbq 股本变迁)
- 历史逐笔的买卖方向:实测除 0=买、1=卖、2=中性外还会出现 5、8 等值 (疑似集合竞价标记),服务器语义未公开,请谨慎使用该字段。
- 东财接口(rustdx-cli 的
east命令):在代理/VPN(fake-IP DNS)环境下会被 断开,需要直连网络。
历史问题:2026 年通达信变更了当日分时响应格式(pytdx/mootdx 亦无法解析, 见 pytdx #148),rustdx 已于 v1.7.0 完成新协议逆向并直接支持(含可变长度盘口快照头 + 数据块定位), 并保留「今日历史分时接口」自动回退作为兜底。
$ cargo install rustdx-cli# ① 一键模式(推荐):自动下载官网日线完整包 → 解压 → 解析
# 数据源:https://data.tdx.com.cn/vipdoc/hsjday.zip(沪深京全市场,A股/B股/指数/基金/可转债)
$ rustdx day
# ② 指定下载地址(镜像 / 自定义源)
$ rustdx day https://mirror.example.com/hsjday.zip
# ③ 使用本地已下载的 zip 包
$ rustdx day /path/to/hsjday.zip
# ④ 直接解析本机通达信 day 目录(原有模式,与上面互不影响)
$ rustdx day /path/tdx/sh/ /path/tdx/sz/ -l official -g gbbq -o clickhouse -t rustdx.factor
# ⑤ 常用可选参数
$ rustdx day -n 100 # 每个目录只解析前 100 个文件(快速测试)
$ rustdx day -l official # 只解析沪深交易所官网股票列表内的代码
$ rustdx day -e sz -c 0000 # 只解析 sz 市场 0000 开头的代码
$ rustdx day -o out.csv # 输出到指定 csv(默认 stocks.csv)自动下载模式说明:
- ①③ 的 zip 与解压数据放在系统临时目录(
$TMPDIR/rustdx_hsjday/),不污染当前目录; - 缓存跳过:按 ETag/大小比对服务器文件,未变化则跳过下载与解压(二次运行约 1 秒);
- 断点续传:下载中断后重跑,从已下载位置继续(无需从头);
- 失败自动重试:下载失败自动重试 3 次(带退避),仍失败才交互询问备选下载地址 (URL)或本地 zip 文件路径,输入后自动继续;
- 下载进度每 32 MiB 打印一次;完整包约 523 MiB,解压后约 12,394 个
.day文件; - 解析后自动输出校验报告(文件数 / 行数 / 输出大小 / 耗时);
- 输出 CSV 的 code 列含市场前缀(
sh600000/sz000001/sz200b07),合并多市场不会混叠。
# 每个交易日收盘后,用东财数据增量更新(需直连网络)
$ rustdx east -p clickhouse -o clickhouse -t rustdx.factorday 命令输出说明(v1.2.0 起):
- code 列含市场前缀:
sh600000/sz000001/sz200b07,合并多市场(sh/sz/bj) 输出时不会发生同代码混叠(例如sh000001上证指数与sz000001平安银行可区分); - 支持带字母代码:深市板块指数等特殊品种(如
sz200b07)不再被过滤跳过; - 并发解析:多线程并行(线程数 = 逻辑核心数),单核串行 → 并发后全市场
日线(12,394 个
.day)解析由约 3 分钟降至约 1 分 48 秒。
⚠️ 破坏性变更:v1.1.x 输出 code 为 6 位裸数字,v1.2.0 起带市场前缀; 复权-p的前一日 factor CSV 的 code 列也需为带前缀格式。
历史日线统计(上游数据,单核 release build):解析全部 A 股历史 < 30s; 东财日线增量更新约 2s。涨跌幅复权算法无需重算历史复权信息, 详见涨跌幅复权与前复权。
$ cargo test --workspace # 235 个测试(含实盘网络验证)
$ cargo clippy --workspace --all-targets # 零警告协议解析的正确性通过「真实抓包字节 → 期望结构」回归测试保障(与 pytdx 同连接抓包逐字段对照),协议再变化时能第一时间发现。
- pytdx / tdxpy:协议逆向参考
- mootdx:服务器列表维护与 API 设计参考
- zjp-CN/rustdx:本项目 fork 的上游(本地文件解析与复权计算)
- 通达信:提供行情服务
MIT,见 LICENSE。