Skip to main content

English

Mootdx2

PyPI version Python Version License: MIT Language

通达信行情与历史数据读取工具包,支持标准股票与扩展市场在线实时行情、离线历史文件(日线/分钟线/分时线/板块)极速解析、财务数据下载解析、90天长效缓存除权因子管理、跨进程文件锁保护及股票与 ETF 统一前复权/后复权精准计算。


核心特性

  • 在线行情获取:基于 TDX 原生协议,支持股票、指数、ETF、期权、期货等多品种实时五档行情、历史 K 线、分时线、逐笔成交与财务摘要查询。
  • 高可用双轨驱动与自动容灾 (Failover):内置纯 Python 原生协议驱动(driver='native')与经典 tdxpy 双轨制;配合最优服务器测速(bestip)、线程安全连接池(RLock 保护)与 300 秒自适应冷却黑名单,异常时自动触发跨驱动平滑降级与节点重试,重试耗尽时返回语义化空对象降级,杜绝程序崩溃。
  • 现代资源管理协议:全面支持上下文管理器协议(with Quotes.factory(...) as client:),任务结束或异常时自动释放底层连接与套接字,防止长效运行中的句柄泄漏(FD exhaustion)。
  • 本地离线数据解析与反向回写:高效解析本地通达信数据目录文件(.day / .lc1 / .lc5 / 板块 .dat),支持 Windows、macOS、Linux 默认路径识别,内置 ETF 与指数价格系数自动推断,并支持将 DataFrame 重新序列化打包回写为标准通达信 .day 二进制文件。
  • 原子落盘与长效跨进程缓存:除权除息数据(XDXR)与本地缓存采用纳秒级临时文件与 os.replace 原子落盘,90 天长效 .plk 缓存集成 filelock 跨进程互斥锁,杜绝高并发多进程环境下的文件损坏与重复网络拉取。
  • 统一精准复权算法:原生支持股票现金分红/送转股(category=1)及 ETF 份额折算(category=11),复权失败严格抛出 ReversionError,杜绝未复权脏数据流入量化系统。
  • 巨潮官方公告与财报下载:内置基于标准库零三方依赖的 CninfoClient,支持按 6 位代码检索上市公司公告与一键下载官方 PDF 财报原件。
  • 按需批量预同步:提供带请求节流(Rate Limiting)的多线程除权数据批量预下载接口与 CLI 命令,提供进度跟踪并记录 .plk 文件路径。
  • 多格式导出与 CLI 支持:支持命令行一键导出 CSV、Excel、HDF5、JSON 等格式。

安装说明

使用 pip 安装

pip install mootdx2

安装完整命令行增强依赖:

pip install "mootdx2[all]"

开发环境安装

# 克隆仓库
git clone https://github.com/mootdx/mootdx.git
cd mootdx

# 使用 uv 同步依赖
uv sync --all-groups

# 执行单元测试
uv run pytest

快速上手与 API 说明

1. 在线行情读取 (mootdx2.quotes.Quotes)

Quotes 客户端支持标准市场(market='std')与扩展市场(market='ext'),推荐使用 上下文管理器 (with),任务结束或异常时会自动释放底层 TCP Socket 连接,杜绝长效量化任务中的连接句柄泄漏:

from mootdx2.quotes import Quotes

# 推荐:使用上下文管理器安全释放资源 (支持心跳维护、多线程连接与自动最优 IP)
with Quotes.factory(market='std', multithread=True, heartbeat=True, bestip=True) as client:
    # 1. 获取 K 线数据 (frequency: 9=日线, 8=1分钟, 0=5分钟; 支持前复权 adjust='qfq')
    df_bars = client.bars(symbol='600036', frequency=9, offset=500, adjust='qfq')
    print(df_bars.tail())

    # 2. 获取指数 K 线
    df_index = client.index(symbol='000001', frequency=9, offset=100)

    # 3. 获取实时多股五档报价
    df_quotes = client.quotes(symbols=['600000', '000001', '600519'])

    # 4. 获取分时数据与历史分时
    df_minute = client.minute(symbol='600036')
    df_hist_minute = client.minutes(symbol='600036', date='2024-01-15')

    # 5. 获取分笔成交明细
    df_trans = client.transaction(symbol='600036', start=0, offset=800)
    df_hist_trans = client.transactions(symbol='600036', start=0, offset=800, date='2024-01-15')

    # 6. 获取除权除息原始数据 (XDXR)
    df_xdxr = client.xdxr(symbol='600036')

    # 7. 获取板块分类与股票数量
    df_block = client.block()
    stock_count = client.stock_count(market=1)  # 0: 深圳, 1: 上海, 2: 北京

    # 8. 批量安全获取日 K 线 (防封节流 + 离线优先 + 自动落盘缓存)
    # 针对几百只股票批量下载场景,默认 80ms 节流、每 50 只批次缓冲休眠、网络抖动指数退避,优先读本地通达信 vipdoc
    batch_results = client.batch_bars(
        symbols=['600000', '000001', '600519'],
        frequency=9,
        offset=800,
        delay=0.08,          # 单次在线请求间隔 (秒)
        batch_size=50,       # 批次大小
        batch_delay=1.0,     # 批次间休息 (秒)
        offline_first=True,  # 优先检查并读取本地通达信 vipdoc (0 网络开销)
        cache=True,          # 在线获取成功后自动缓存至本地磁盘 (24h 有效)
        show_progress=True,  # 显示 tqdm 进度条
    )

2. 本地离线文件读取 (mootdx2.reader.Reader)

自动识别本地通达信安装目录(亦可显式指定 tdxdir),快速读取本地二进制数据文件:

from mootdx2.reader import Reader

# 初始化 Reader (默认匹配系统路径: Windows C:/new_tdx, macOS ~/new_tdx, Linux ~/.local/share/new_tdx)
reader = Reader.factory(market='std', tdxdir=None)

# 1. 读取日线数据 (支持直接返回前复权/后复权)
df_daily_raw = reader.daily(symbol='600036')
df_daily_qfq = reader.daily(symbol='600036', adjust='qfq')
df_daily_hfq = reader.daily(symbol='600036', adjust='hfq')

# 2. 读取 1 分钟 / 5 分钟线数据
df_min1 = reader.minute(symbol='600036', suffix='1')
df_min5 = reader.minute(symbol='600036', suffix='5')

# 3. 读取分时线数据
df_fzline = reader.fzline(symbol='600036')

# 4. 读取板块数据
df_blocks = reader.block(name='block_gn.dat') # 概念板块
df_custom_blocks = reader.block_new()         # 自定义板块

3. 除权除息与长效缓存工具 (mootdx2.sync / mootdx2.utils.adjust)

针对量化高频调用、防封禁与多进程安全设计的除权数据管理体系:

from mootdx2 import get_xdxr, get_xdxr_cache_path, read_xdxr_cache, sync_xdxr
from mootdx2.tools.reversion import reversion
from mootdx2.exceptions import ReversionError

# 1. 获取除权除息数据 (自动走 90 天长效缓存与跨进程锁,refresh=True 可强制刷新)
df_xdxr = get_xdxr('600036', refresh=False)

# 2. 查询与读取本地缓存 .plk 文件路径
cache_path = get_xdxr_cache_path('600036')
print(f'Cache Path: {cache_path}')
df_cached = read_xdxr_cache('600036')

# 3. 统一复权计算 (支持股票与 ETF 分红/折算; 失败抛出 ReversionError)
try:
    df_qfq = reversion(symbol='600036', stock_data=raw_df, xdxr=df_xdxr, type_='qfq')
except ReversionError as err:
    print(f'复权计算失败: {err}')

# 4. 批量预同步除权数据 (支持并发、请求间隔延时节流防封、进度显示与 .plk 汇总)
sync_result = sync_xdxr(
    symbols=['600000', '000001', '600519'], # 或指定 file='stocks.txt'
    force=False,                             # 跳过有效缓存
    workers=4,                               # 线程数
    delay=0.05,                              # 单请求间隔秒数
    show_progress=True,
)
print(f"总计: {sync_result['total']}, 成功: {sync_result['success']}, 跳过: {sync_result['skipped']}")
print(f"缓存文件路径列表: {sync_result['files']}")

4. 量化库集成与增量前复权最佳实践

外部量化回测或数据系统(如 kdata-quant 等)在本地持久化行情并需要增量更新和**前复权(QFQ)时,推荐采用“持久化未复权原始行情 + 独立维护除权信息 + 查询时内存动态复权”**的标准架构。

为什么不能直接追加(Append)前复权数据?

前复权以最新价格为基准,一旦标的除权除息(送转/分红),历史所有前复权价格均会联动重算。直接在本地追加前复权数据会导致历史基准未调整,产生虚假的跳空暴跌缺口。

快速集成代码示例

import pandas as pd
from mootdx2.quotes import Quotes
from mootdx2.utils.adjust import get_xdxr, to_adjust

client = Quotes.factory("std")

# 1. 增量获取未复权原始日线 (例如从本地最新日期的下一天拉取)
raw_df = client.k(symbol="600036", begin="2024-01-01")

# 2. 刷新或读取本地除权除息缓存 (内置 90 天文件锁长效缓存)
xdxr_df = get_xdxr(symbol="600036", refresh=False)

# 3. 数据规整并设置以 DatetimeIndex 为索引
raw_df["date"] = pd.to_datetime(raw_df.get("date", raw_df.get("datetime", raw_df.index)))
raw_df = raw_df.set_index("date").sort_index()

# 4. 内存动态执行前复权 (必须基于包含最新价格的完整未复权序列计算)
df_qfq = to_adjust(temp_df=raw_df, symbol="600036", adjust="qfq")

# 5. 按照策略实际需要的时间区间切片
df_target = df_qfq.loc["2024-01-01":"2024-06-01"]

5. 巨潮资讯公告检索与 PDF 财报下载 (mootdx2.data.CninfoClient)

基于 Python 标准库零额外依赖实现的官方公告与财报下载接口:

from mootdx2 import CninfoClient

client = CninfoClient()

# 1. 检索上市公司最新公告明细
df_announcements = client.get_announcements(code='600519', count=20)
print(df_announcements[['date', 'title', 'type', 'pdf_url']].head())

# 2. 一键下载官方 PDF 财报原件到指定目录
if not df_announcements.empty and df_announcements.iloc[0]['pdf_url']:
    pdf_path = client.download_pdf(df_announcements.iloc[0], dest_dir='./reports')
    print(f'财报原件已保存至: {pdf_path}')

6. 财务数据下载与解析 (mootdx2.affair.Affair)

from mootdx2.affair import Affair

# 获取远程财务文件列表
file_list = Affair.files()

# 下载指定季度的财务压缩包
Affair.fetch(downdir='download_dir', filename='gpcw19960630.zip')

# 解析已下载的财务文件为 DataFrame
df_financial = Affair.parse(downdir='download_dir', filename='gpcw19960630.zip')

命令行工具 (CLI)

安装后可直接在终端使用 mootdx2 命令:

# 查看帮助与版本
mootdx2 --help
mootdx2 -V

# 1. 测速并更新最优行情服务器
mootdx2 bestip -l 5 -v

# 2. 批量同步除权因子 (90天长效缓存 + 并发节流防封)
mootdx2 sync -s "600000,000001,600519" -w 4 -d 0.05
mootdx2 sync -f stocks.txt --force

# 3. 获取实时行情并导出
mootdx2 quotes -s 600036 -a daily -o output.csv

# 4. 读取本地通达信数据文件
mootdx2 reader -s 600036 -a daily -o daily_600036.xlsx

# 5. 批量下载历史数据
mootdx2 bundle -s 600000,000001 -a daily -o bundle_dir -e csv

# 6. 下载并列出财务文件
mootdx2 affair -l
mootdx2 affair -f gpcw20230930.zip -d ./data

许可证

本项目基于 MIT License 开源发布。

Release files for mootdx2 1.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mootdx2 1.4.0
File Size Uploaded
mootdx2-1.4.0.tar.gz 11.9 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for mootdx2 1.4.0
File Interpreter ABI Platform
mootdx2-1.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 12.1 MB

Release files / mootdx2-1.4.0.tar.gz

Download URL mootdx2-1.4.0.tar.gz
Size 11.9 MB
Tags Source
SHA-256 checksum
How to use checksums
e157d16518dbf04bf85185afab21cf831c929eaa3fb325ea5a80063e40c9280d
BLAKE2b-256 checksum
How to use checksums
e6030b82ff3cde83fb96f23559e17a357f3d9adb3253f30fb96ee61451f2ed41
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.15 {"installer":{"name":"uv","version":"0.9.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / mootdx2-1.4.0-py3-none-any.whl

Download URL mootdx2-1.4.0-py3-none-any.whl
Size 198.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0ff03b9b83f20330f55ffc8b71419693068160990bdb053f2ce9a5aee0351185
BLAKE2b-256 checksum
How to use checksums
a6cd8fc97d57f792e773be3003c3b838b98a2d1d73e4409a02937527dc33d345
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.15 {"installer":{"name":"uv","version":"0.9.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

1.6.3

2 release files

1.6.2

2 release files

1.6.1

2 release files

1.6.0

2 release files

1.5.5

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.3

2 release files

1.4.2

2 release files

1.4.1

2 release files

This release

1.4.0 This release

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page