mootdx 通达信数据接入实战手册:七步吃透行情、财务与离线数据三大能力
【免费下载链接】mootdx通达信数据读取的一个简便使用封装项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx
你是否遇到过这样的困境:写量化回测时,历史 K 线要用通达信本地数据;盯盘时又需要毫秒级的实时行情;做基本面分析时还差一套顺手的历史财报数据——三个需求,三套对接方案,光是协议解析就能耗掉一个周末。
mootdx正是为终结这种"数据三线作战"而生的通达信数据封装库:它把通达信的离线文件读取、线上行情请求、财务数据下载解析收敛成三个统一入口,几行代码即可拿到干净的 pandas DataFrame,让你把时间留给策略本身,而不是协议本身。
第一步:十分钟搭好可直接运行的环境
先明确一件事:mootdx 支持 Windows / macOS / Linux,Python 3.8 及以上,唯一硬依赖是 pandas 和 numpy。安装没有任何魔法,建议直接安装全量扩展,省得后面用到命令行工具或复权功能时再补依赖:
# 推荐:不清楚依赖关系就装全量 pip install -U 'mootdx[all]'装完验证一下,能看到版本号就说明环境已通:
import pandas as pd import numpy as np from mootdx import __version__ print(f"mootdx 版本: {__version__}") # 例如 0.11.7 print(f"pandas 版本: {pd.__version__}")小提示:若你是从源码参与开发,也可以通过
git clone https://gitcode.com/GitHub_Trending/mo/mootdx拉取仓库后用pip install -e .安装开发模式。
第二步:从"为什么日线少了一段"说起——离线数据读取的正确姿势
很多本地化策略失败的起点,其实是数据文件本身:通达信安装目录下的.day、.lc1、.lc5二进制文件有一套自定义协议,手写解析极易踩坑(字节序、字段偏移、复权标记一错全错)。mootdx 的Reader帮你把这条链路彻底封装好了。
Reader.factory()是一个典型的工厂方法:传入market='std'读沪深股票,传入'ext'则面向扩展市场。你只需告诉它通达信安装目录tdxdir:
from mootdx.reader import Reader # tdxdir 指向通达信安装目录(即包含 vipdoc 子目录的那一层) reader = Reader.factory(market='std', tdxdir='C:/new_tdx') # 日线:返回包含 open/high/low/close/vol 等字段的 DataFrame df_daily = reader.daily(symbol='600036') # 1 分钟线 / 5 分钟线(fzline 是 5 分钟的别名) df_min = reader.minute(symbol='600036', suffix=1) # 1 分钟 df_fz = reader.fzline(symbol='600036') # 5 分钟你不需要关心600036到底落在sh还是sz目录——Reader内部通过get_stock_market()自动判定市场并拼接前缀;连通达信特有的88开头板块指数存放在sh目录这种"潜规则",它也已替你处理。
把离线读取封装成一个可复用类,批量拉取时还会更省心:
from mootdx.reader import Reader from pathlib import Path class LocalDataHub: def __init__(self, tdxdir: str): if not Path(tdxdir).is_dir(): raise ValueError("通达信数据目录不存在,请检查路径") self.reader = Reader.factory(market='std', tdxdir=tdxdir) def daily_since(self, symbol: str, start: str = '2023-01-01'): """读取指定日期之后的日线""" df = self.reader.daily(symbol=symbol) if df is not None and 'date' in df.columns: return df[df['date'] >= start] return df这里刻意做了一个目录存在性校验——Reader构造时同样会校验,尽早暴露路径错误比数据读到一半再报错要友好得多。
第三步:实时行情不卡壳——Quotes 的三种高频用法
离线数据解决"历史",实时数据解决"当下"。Quotes走的是通达信行情服务器协议,同样用工厂方法创建,但多了一组生产级参数值得留意:
from mootdx.quotes import Quotes # multithread 开启多线程,heartbeat 保持心跳防断连 client = Quotes.factory(market='std', multithread=True, heartbeat=True, timeout=10)三个最常用的能力,覆盖绝大多数盘中场景:
1. 批量实时报价
# 传入列表即可一次请求多只股票 df = client.quotes(symbol=['000001', '600000', '000858'])2. 任意周期的 K 线
# frequency 与通达信约定一致:9=日线,0=5分钟,7=1分钟,5=周线,6=月线 df_k = client.bars(symbol='600036', frequency=9, offset=800) df_i = client.index(symbol='000001', frequency=9) # 指数3. 分时与逐笔
df_today = client.minute(symbol='000001') # 当日分时 df_trans = client.transactions(symbol='000001', date='20240115') # 历史分笔成交值得一提的还有client.k(symbol, begin, end)这个"日期区间友好"接口:它内部会自动按 800 条分页翻取、剔除节假日占比,直接返回按日期排序的完整区间数据,做回测取数时比手动拼 offset 优雅得多。
第四步:财报数据一键同步——Affair 与 Financial 的分工
基本面数据是很多人的痛点:通达信财务文件是gpcwYYYYMMDD.zip这种历史归档,手动下载、解压、解析二进制字段,步骤繁琐且容易漏季度。mootdx 把这套流程拆成两个角色:
- Affair:负责"清单 + 下载",解决数据从哪来的问题
- Financial:负责"解压 + 解析",解决二进制怎么读的问题
from mootdx.affair import Affair # 1. 拉取远程财务文件清单(含文件名、hash、大小) files = Affair.files() # 2. 按需下载单个文件到本地目录 Affair.fetch(downdir='./fin_data', filename='gpcw20231231.zip') # 3. 解析为 DataFrame(zip / dat 自动识别) df = Affair.parse(downdir='./fin_data', filename='gpcw20231231.zip')Affair.fetch在下载时会自动校验文件是否已存在且 hash 一致,避免重复下载;解析后拿到的是带标准化列名的财务宽表,配合mootdx.financial.columns中的字段定义即可对齐报表口径。
一个实用的增量同步思路:用files()的清单与本地目录比对,只下载缺失季度,天然形成"增量更新"机制:
import os from mootdx.affair import Affair def sync_finance(download_dir: str = './fin_data'): os.makedirs(download_dir, exist_ok=True) local = set(os.listdir(download_dir)) for item in Affair.files(): if item['filename'] not in local: print(f"增量下载: {item['filename']}") Affair.fetch(downdir=download_dir, filename=item['filename'])第五步:生产级健壮性——缓存、重试与服务器选择的组合拳
数据接口跑在真实环境里,要面对三个现实问题:慢、断、不稳。对应三个解法:
5.1 慢 → 用 pd_cache 做磁盘缓存
mootdx 内置了pd_cache装饰器,把函数的计算结果序列化到.pkl文件,并按函数源码 + 参数生成缓存键,天然支持"改了代码自动失效":
from mootdx.utils.pandas_cache import pd_cache @pd_cache(cache_dir='./cache', expired=600) # 600 秒过期 def load_daily(symbol: str): client = Quotes.factory(market='std') return client.bars(symbol=symbol, frequency=9)盘中反复取同一批股票的日线时,命中缓存后直接从磁盘读 pickle,耗时从秒级降到毫秒级。
5.2 断 → 学会利用内置重试
Quotes底层基于tenacity实现了自动重连与重试:返回空数据时会reconnect()重连服务器,auto_retry=True默认开启。因此你的业务代码里,普通的临时性失败大多已被吞掉;只有业务级错误才需要自己兜底。如果你要更强的控制力,可以在自己函数上叠加tenacity装饰器:
from tenacity import retry, stop_after_attempt, wait_random @retry(stop=stop_after_attempt(3), wait=wait_random(min=1, max=3)) def fetch_quotes_safe(symbol: str): client = Quotes.factory(market='std') df = client.quotes(symbol=symbol) if df is None or df.empty: raise ValueError("返回空数据") return df5.3 不稳 → 用 bestip 挑选最优服务器
行情服务器有好坏之分。mootdx 的server模块提供了测速选优能力,启动时花几秒探测,后续全程享用低延迟连接:
from mootdx.server import bestip servers = bestip(limit=5, timeout=5) # 测速,返回最优服务器列表 client = Quotes.factory(market='std', server=servers[0], timeout=10)第六步:综合实战——把三大能力串成一个"盯盘 + 复盘"工具
到这里,前五步的知识点已经足够拼装一个完整工具了。下面这个MarketAssistant把离线日线、实时行情、财务快照三类数据统一收口,并加入了缓存与重试,可以直接跑:
import logging from mootdx.quotes import Quotes from mootdx.reader import Reader from mootdx.affair import Affair from mootdx.utils.pandas_cache import pd_cache logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s') class MarketAssistant: """综合数据助手:离线历史 + 实时行情 + 财务概览""" def __init__(self, tdxdir: str): self.reader = Reader.factory(market='std', tdxdir=tdxdir) self.client = Quotes.factory(market='std', multithread=True, heartbeat=True) self.log = logging.getLogger('assistant') @pd_cache(cache_dir='./cache', expired=300) def history(self, symbol: str): """本地日线优先,缺失时回退到线上行情""" df = self.reader.daily(symbol=symbol) if df is None or df.empty: self.log.warning(f"{symbol} 本地无数据,回退线上拉取") df = self.client.bars(symbol=symbol, frequency=9) return df def realtime(self, symbols): """批量实时报价""" return self.client.quotes(symbol=symbols) def financial_overview(self, filename: str): """解析指定季度的财务快照""" df = Affair.parse(downdir='./fin_data', filename=filename) return df.head() def snapshot(self, symbol: str, symbols, filename: str): """一次调用,输出三种数据的状态""" return { 'history_rows': len(self.history(symbol)), 'realtime': self.realtime(symbols), 'finance_cols': list(self.financial_overview(filename).columns), } if __name__ == '__main__': tool = MarketAssistant(tdxdir='C:/new_tdx') print(tool.snapshot('600036', ['000001', '600000'], 'gpcw20231231.zip'))这个例子想传达的工程习惯有三点:入口统一(一个类暴露全部能力)、降级策略(本地缺失回退线上)、结果缓存(重复查询不浪费网络)。这也是把库用好与用精的分水岭。
第七步:避坑清单——九个"我当初踩过的坑"
最后按实战频率整理一份避坑清单,每一条背后都是一个真实报错:
| 坑 | 现象 | 解法 |
|---|---|---|
tdxdir路径写错 | 构造即抛tdxdir 目录不存在 | 指向包含vipdoc的顶层目录,而非vipdoc本身 |
| 服务器连不上 | 请求超时 / 连接被重置 | 用bestip()重新测速,或换timeout更宽容的配置 |
| 批量请求一次太多 | 返回被截断或超时 | bars/quotes分批请求,单批控制在合理数量内 |
| K 线数量超上限 | 结果莫名缺失 | offset超过 800 会被钳制到 800,超长历史用k()或自行分页 |
| 财务文件 hash 不匹配 | 反复重复下载 | 不要改动下载目录里的 zip 文件名 |
| 本地没有某只股票数据 | daily()返回 None | 先用线上bars()回退,或检查通达信客户端是否下载过该股日线 |
| 扩展市场接口异常 | market='ext'报错 | 扩展行情接口当前不稳定,生产依赖请以std为主 |
| 缓存不生效 | 每次仍重新拉取 | 检查expired参数与缓存目录权限,pd_cached_delete()可清缓存 |
| 日志看不到过程 | 排查困难 | mootdx基于标准logging,设置level=logging.DEBUG即可看到连接细节 |
收尾:你已经握住了通达信数据的完整链路
回头看看这条学习路径:从离线二进制文件的本地读取,到线上行情的高频请求,再到财报数据的下载解析,最后用缓存、重试、服务器选择把它们打磨成生产可用的形态——这正是"数据工程"在量化场景下的完整闭环。mootdx 的价值在于把这三条链路收敛成三个工厂入口,让你用最少的协议知识拿到最干净的数据。
下一步建议这样走:先用Reader把本地数据全部验证一遍,再跑通Quotes的实时请求,最后加上pd_cache与bestip做性能加固。官方文档位于项目docs/目录(API 说明、CLI 用法、FAQ 一应俱全),sample/目录下还有basic_quotes.py、basic_affairs.py、fq.py等可直接运行的示例脚本,配合本文循序渐进,一周内你就能拥有一套自给自足的数据底座。
【免费下载链接】mootdx通达信数据读取的一个简便使用封装项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考