rustdx-complete 1.5.0

功能完整的 A 股数据获取库,完全对标 pytdx
docs.rs failed to build rustdx-complete-1.5.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

rustdx

pytdx / mootdx 启发的 A 股数据获取工具(Rust 实现):

  1. 一个 Rust 通用库 rustdx-complete:通达信行情协议 + 本地数据文件解析 + 技术指标;
  2. 一个命令行工具 rustdx-cli:解析通达信 day 文件、东财日线增量更新、ClickHouse 写入。

✨ 特性

  • 行情协议全覆盖:实时行情(含五档盘口)、K线、指数K线、当日/历史分时、当日/历史逐笔、财务信息、除权除息、F10 公司资料、板块文件(概念/指数/风格)
  • 连接可靠性:40 台服务器协议级自动故障转移、心跳保活、失败自动重连重试、超时可配置
  • 数据正确性:全部协议按 pytdx 源码逐字节对照并经交易时段实盘验证;解析异常时返回空数据而非垃圾数据
  • 本地 day 文件并发解析:rustdx-cli 多线程并行解析(线程数=逻辑核心数),并支持带字母的特殊品种代码(如深市板块指数 sz200b07
  • 技术指标:SMA/EMA/MACD/RSI/布林带/KDJ
  • 辅助能力:交易日历、智能缓存、连接池、Builder 模式 API、数据验证
  • 197 个测试(含真实抓包字节的回归测试),clippy 零警告

📦 安装

[dependencies]
rustdx-complete = "1.3.0"

cargo add rustdx-complete

🚀 快速开始(Client 高层 API)

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 &quotes {
        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(())
}

📖 功能对照(rustdx ↔ mootdx/pytdx)

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::k_batch 批量日K,内部连接池并行,单只失败不影响其他
—(rustdx 新增) Client::k_adjusted 前/后复权日K,本地按除权除息计算
minute Client::minute / MinuteTime 当日分时 ⚠️ 见已知问题
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 扩展市场(官方标注已失效)。

🔧 底层 API(细粒度控制)

每个协议对应一个请求结构体,实现统一的 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]) };
let mut tcp = Tcp::with_config(&cfg)?;

// 心跳 / 重连 / 自动重试
tcp.heartbeat()?;
tcp.reconnect()?;

📊 附加模块

  • indicators:SMA/EMA/MACD/RSI/布林带/KDJ,与K线数据无缝衔接
  • calendar:A股交易日历(法定节假日,数据源 trade_date_a)
  • cache:内存/文件缓存(TTL 过期)
  • pool:TCP 连接池
  • builder:KlineBuilder 链式 API
  • tcp::stock::validator:K线连续性/财务一致性验证、异常值检测
  • file:通达信本地文件解析(.day 日线、.lc1/.lc5 分钟线、gbbq 股本变迁)

⚠️ 已知问题(诚实声明)

  1. 当日分时Client::minute):2026 年起部分通达信服务器变更了分时响应格式, pytdx/mootdx 同样无法解析。rustdx 内置自动回退——当日分时接口解析异常时 自动改用今日历史分时接口HistoryMinuteTime,协议稳定、实测 240 点完整) 取数;非交易日返回空数据。逆向进展见 pytdx #148
  2. 历史逐笔的买卖方向:实测除 0=买、1=卖、2=中性外还会出现 5、8 等值 (疑似集合竞价标记),服务器语义未公开,请谨慎使用该字段。
  3. 东财接口(rustdx-cli 的 east 命令):在代理/VPN(fake-IP DNS)环境下会被 断开,需要直连网络。

🖥 rustdx-cli 命令行

安装

$ cargo install rustdx-cli

1️⃣ day — 解析通达信日线数据

# ① 一键模式(推荐):自动下载官网日线完整包 → 解压 → 解析
#    数据源: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),合并多市场不会混叠。

2️⃣ east — 东财日线增量更新

# 每个交易日收盘后,用东财数据增量更新(需直连网络)
$ rustdx east -p clickhouse -o clickhouse -t rustdx.factor

day 命令输出说明(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   # 197 个测试(含实盘网络验证)
$ cargo clippy --workspace --all-targets   # 零警告

协议解析的正确性通过「真实抓包字节 → 期望结构」回归测试保障(与 pytdx 同连接抓包逐字段对照),协议再变化时能第一时间发现。

📝 CHANGELOG

更新记录

🙏 致谢

  • pytdx / tdxpy:协议逆向参考
  • mootdx:服务器列表维护与 API 设计参考
  • zjp-CN/rustdx:本项目 fork 的上游(本地文件解析与复权计算)
  • 通达信:提供行情服务

许可证

MIT,见 LICENSE