# rustdx [github](https://github.com/zjp-CN/rustdx) [github](https://github.com/zjp-CN/rustdx/issues) [crates.io](https://crates.io/crates/rustdx) [docs.rs](https://docs.rs/rustdx) [crates.io](https://crates.io/crates/rustdx-cmd) [build status](https://github.com/zjp-CN/rustdx/actions) [![](https://img.shields.io/crates/d/rustdx.svg?label=downloads+rustdx&style=social)](https://crates.io/crates/rustdx) [![](https://img.shields.io/crates/dv/rustdx.svg?label=downloads@latest+rustdx&style=social)](https://crates.io/crates/rustdx) [![](https://img.shields.io/crates/d/rustdx-cmd.svg?label=downloads+rustdx-cmd&style=social)](https://crates.io/crates/rustdx-cmd) [![](https://img.shields.io/crates/dv/rustdx-cmd.svg?label=downloads@latest+rustdx-cmd&style=social)](https://crates.io/crates/rustdx-cmd) 受 [pytdx](https://pypi.org/project/pytdx/1.28) 启发的 A 股数据获取工具,包含: 1. 一个 Rust 通用库 [rustdx](https://crates.io/crates/rustdx); 2. 一个命令行工具 [rustdx-cmd](https://crates.io/crates/rustdx-cmd)。 命令行工具(统计数据基于笔者的单核 CPU Ubuntu 系统 release build,以实际速度为准): 1. 解析所有最新股票列表的历史 A 股数据(包含复权数据)不到 30s ,解析后的 csv 大小 1G 多; 2. 将解析后的 csv 数据插入到 ClickHouse (20s,表 268 M) 或 MongoDB (7 分钟,表超过 700 M); 3. 东财日线增量更新(包括复权),2s 更新完。 关于复权: 1. 使用涨跌幅复权算法,无需修改(重算)历史复权信息; 2. 只计算收盘价前复权,其他价格复权只需基于收盘价和相对价格即可计算出来(这在 ClickHouse 中很快)。 具体文档待补充。 ## rustdx-cmd ### 安装 使用以下一种方式即可: 1. 下载 [已编译的 release 版本](https://github.com/zjp-CN/rustdx/releases/latest) 2. cargo install: ```console cargo install rustdx-cmd ``` 3. cargo build: ```console $ git clone https://github.com/zjp-CN/rustdx.git $ cd rustdx $ cargo build -p rustdx-cmd --release # 编译(二进制在 target/release 下) $ cargo install --path rustdx-cmd # 安装(二进制在全局 .cargo/bin 下) ``` ### 子命令 - day:解析通达信 day 文件,具体查看帮助 `rustdx day --help`、`rustdx day -h o -h l`。 - east:获取东方财富当日 A 股数据,具体查看帮助 `rustdx east --help`。 ### 完整使用例子 准备好 day 文件、gbbq 文件和 ClickHouse 数据库: p.s. 请勿使用本项目 `assets/` 中的 gbbq 文件,因为那对你来说是过时的。 > 注意: > > 此工具的主要目的就是快速补齐历史日线数据,但**没有**校验交易日数据连续或者清空数据库的功能。 > > 因没有每天记录日线导致日线不完整(或者其他原因导致数据有问题),请**重新**解析和存储所有历史数据。 > > 重新存储数据之前,使用以下 sql 命令(以 ClickHouse 为例)删除历史数据: > > ```sql > TRUNCATE TABLE rustdx.factor; > ``` > > 如果发现历史数据不正确,请提交 [issue](https://github.com/zjp-CN/rustdx/issues)。 ```console # 解析所有最新股票的历史日线数据,且计算复权数据 $ rustdx day /vdb/tmp/tdx/sh/ /vdb/tmp/tdx/sz/ -l official -g ../assets/gbbq -t rustdx.factor # 写入 ClickHouse 数据库 $ clickhouse-client --query "INSERT INTO rustdx.factor FORMAT CSVWithNames" < stocks.csv # 有了历史日线数据之后,每个交易日收盘之后,更新当天数据 $ rustdx east -p factor.csv -t rustdx.factor # 写入 ClickHouse 数据库 $ clickhouse-client --query "INSERT INTO rustdx.factor FORMAT CSVWithNames" < eastmoney.csv ``` 其中 factor.csv 来自数据库中,前一天的复权数据,ClickHouse 的导出命令: ```sql SELECT yesterday() AS date, code, last_value(close) AS close, last_value(factor) AS factor FROM rustdx.factor GROUP BY code INTO OUTFILE 'factor.csv' FORMAT CSVWithNames; ``` --- 或者: ```console # 解析所有最新股票的历史日线数据,且计算复权数据,写入 ClickHouse 数据库 $ rustdx day /vdb/tmp/tdx/sh/ /vdb/tmp/tdx/sz/ -l official -g ../assets/gbbq -o clickhouse -t rustdx.factor # 有了历史日线数据之后,每个交易日收盘之后,更新当天数据 $ rustdx east -p clickhouse -o clickhouse -t rustdx.factor ``` ## CHANGELOG [更新记录](https://github.com/zjp-CN/rustdx/blob/main/CHANGELOG.md) ## 使用示例 ### 计算任何周期的涨跌幅 ```sql SELECT code, toYYYYMM(date) AS m, -- 这里以月周期为例 ((LAST_VALUE(factor) / FIRST_VALUE(factor)) * FIRST_VALUE(close)) / FIRST_VALUE(preclose) AS mgrowth FROM rustdx.factor -- 命令行参数中所写入的表名,假设你按照我上面给的命令行示例运行,那么原始数据在这个表 GROUP BY code, m -- 按照月聚合 ORDER BY code ASC, m DESC; ``` 为什么 `mgrowth` 是那样计算,见 [涨跌幅复权与前复权](https://zjp-cn.github.io/posts/qfq/)。 ### 计算前复权价格 注意,上面计算涨幅时没有计算前复权价格,但大部分情况下必须知道前复权价格来计算价格相关的指标。 那么可以每日数据成功入库之后,运行一次以下脚本,注意: * 这基于最新价来计算所有股票的所有历史前复权价格(在我的单核机器上需要 11 秒) * 每次运行脚本会把之前的计算结果清空 * 前复权的结果在 `rustdx.qfq` 这个表(只有股票代码和价格) ```sql -- 计算前复权价格 DROP TABLE IF EXISTS rustdx.qfq_x; -- 临时表 CREATE TABLE rustdx.qfq_x ( code FixedString(6), x Float64, PRIMARY KEY(code) ) ENGINE = MergeTree AS WITH qfq AS ( SELECT code, LAST_VALUE(close) / LAST_VALUE(factor) AS qfq_multi FROM rustdx.factor GROUP BY code ORDER BY code ) SELECT * FROM qfq; DROP TABLE IF EXISTS rustdx.qfq; -- 前复权价格 CREATE TABLE rustdx.qfq ( date Date, code FixedString(6), close Float64, open Float64, high Float64, low Float64, PRIMARY KEY(date, code) ) ENGINE = MergeTree AS WITH qfq_x AS (SELECT * FROM rustdx.qfq_x), fct AS ( SELECT date, code, open/close AS open, high/close AS high, low/close AS low, factor FROM rustdx.factor ), raw AS ( SELECT * FROM fct LEFT JOIN qfq_x ON qfq_x.code = fct.code ) SELECT date, code, factor*x AS close, open*close AS open, high*close AS high, low*close AS low FROM raw ORDER BY date, code ```