中文 | English
给 QMT / XtQuant 装一层稳定的 JSON 接口,让任何语言、任何 Agent 都能安全调用它。
写过 QMT 自动化的人都懂那种别扭:xtquant 只塞在券商客户端安装目录里,直接 import 意味着
你的脚本、Notebook、Agent 全得绑死在那一个 Python 环境上。想换成 Rust/Go 写的行情引擎?想接一个
LLM Agent 帮你盯盘、判断异常、写交易日志?DataFrame 怎么序列化、NaN 怎么处理、每个字段该信谁的
编码,全变成你自己的事。
qmtcli 就是为了把这些活一次做完:本机起一个小进程,喂 JSON 进去,吐 JSON 出来,背后连的还是
你已经登录的那个 QMT 客户端。迅投官方 QMT/XtQuant API(见
新手教程)提供的环境诊断、行情查询、账户
查询和带基础保护的股票委托能力,都能通过这份稳定的 stdin/stdout JSON 契约一一调到。
qmtcli 不安装或启动 QMT 交易客户端本身,不保存凭据,不绕过券商风控,也不启动网络服务——但
它会自动探测并接好本机已安装的 XtQuant SDK 环境(优先用 venv/pip 里的 xtquant,找不到再退回
QMT 自带的那份,见安装)。使用前需要先在本机安装并登录 QMT。
- 想让 LLM Agent(Claude、GPT、本地模型)直接查行情、看持仓、甚至下单的人——
qmtcli mcp一条 命令接进 MCP,工具从能力清单自动生成,不用手写第二套注册表。 - 想用 Rust、Go、Node.js 写量化系统,又不想专门为了调 QMT 起一个 Python 侧车服务的人。
- 想要一份稳定的 JSON 契约,而不是每次券商升级 QMT 就得重新猜
xtquant参数和字段变化的人。 - 需要在 CI 里跑测试,但构建机上根本没装 QMT 的人——测试套件 fake 了
xtquant,CI 不用真实 券商环境也能跑通。
发现命令能力:
qmtcli capabilities
qmtcli schema
qmtcli examples执行一次 JSON 请求:
Get-Content examples\status.json | qmtcli rpc启动给 Agent 或脚本使用的 JSONL 循环:
qmtcli server成功响应:
{"ok":true,"data":{}}失败响应:
{"ok":false,"error":"message"}如果请求里带 id,响应会原样带回。
QMT 把 xtquant 放在券商客户端安装目录里。直接在交易机上写 Python 脚本时还算方便,但对 Agent
或基于进程的自动化程序来说,直接 import SDK 并不稳定——依赖 QMT 自带的 numpy/pandas 版本,
一次静默升级就可能改变 DataFrame 的序列化方式,或者悄悄丢掉一个字段。qmtcli 把这些不稳定
留在本机、留给一个可以随时重启的子进程,对外只提供一份简单、可测试、跨版本稳定的 JSON 合约:
capabilities、schema、examples用于能力发现;rpc用于 stdin/stdout 单请求;server用于逐行 JSON 请求;- 对只读调用、escape hatch、下单、撤单做明确标记;
- 测试里 fake
xtquant,CI 不需要真实券商环境。
只要一个运行时能启动本地进程并交换 JSON,就能使用它——Python、Rust、Go、Node.js、Shell 脚本, 或 LLM Agent,都能直接对接,不需要任何语言专属的 SDK 或绑定。
- 自动发现常见 Windows QMT SDK 路径;优先使用已安装在当前环境(venv/pip)的
xtquant,而不是 QMT 自带的那份(见安装)。 status和doctor环境诊断,包含 SDK 来源(environment/qmt_bundled/missing)、xtquant版本号、xtdc 可用性。- 行情命令:交易日历、交易日期、板块、tick、K 线、本地缓存 K 线(
local-data)、全推 K 线 (full-kline)、L2 数据、合约/ETF/可转债/新股/指数权重元数据、财务数据。 sector命令族:创建、填充、删除本地自定义板块(create-folder、create、add、remove-stocks、remove、reset)。watch:仅 CLI 的实时行情流式推送(JSONL 输出到 stdout),基于subscribe_quote/subscribe_whole_quote,阻塞直到 Ctrl+C——见CLI 流式推送。mcp:stdio MCP 服务,把 qmtcli 命令暴露成 MCP 工具,从AGENT_CAPABILITIES生成——见 MCP Server。fields:从文档附录提取的静态 xtdata 字段名参考字典(tick、kline、balance 等),完全离线, 不需要 QMT 环境。- 感知 pandas 的 JSON 输出:xtdata 返回的 DataFrame/Series 会序列化成逐行记录(时间索引会保留成
普通列),NaN/NaT/
pd.NA/numpy 标量都会转成合法的 JSON 值,而不是非法的NaNtoken 或读不懂的 对象转储。 download命令用于把数据下载进本地 QMT 缓存(历史行情、财务数据、板块、指数权重、可转债、 ETF 信息、节假日、合约信息)。- 账户查询:资产、持仓、委托(支持
--cancelable-only)、成交。 - 交易查询命令:持仓统计、信用/融资融券查询、新股额度与数据、账号信息/状态、普通柜台资金/持仓 查询——见交易查询命令。
- 固定价 A 股
buy、sell、cancel。 data-call调用公开的xtquant.xtdata方法。trade-call调用公开的XtQuantTrader方法。- 可选的独立 xtdatacenter(xtdc)数据模式,通过
--xtdc-token开启(实验性)——见 独立数据模式。 - Agent / 脚本协议命令:
capabilities、schema、examples、rpc、server。 - 定时运行的
doc-driftGitHub Action(每周一次,也支持手动触发)会对照官方文档页面重新核对下面 的对齐矩阵,一旦文档新增的函数还没体现在矩阵里就自动开 issue;见scripts/check_doc_drift.py。
完整的函数对命令覆盖矩阵(对照官方
xtdata 文档和
xttrader 文档)见
docs/xtdata-alignment.md和
docs/xttrader-alignment.md。
推荐:用 sdk extra 安装,让 xtquant/pandas/numpy 来自当前环境而不是 QMT 自带的
site-packages;这样券商 QMT 客户端只需要提供本地交易/行情服务,不必再提供 Python SDK 本身:
uv sync --extra dev --extra sdk
pip install -e ".[dev,sdk]"不装 sdk extra 时的兜底方案仍然可用——找不到已安装的 SDK 时,qmtcli 会回退到 QMT 安装目录自带
的 xtquant/numpy/pandas——但自带版本可能比当前文档旧(比如部分自带版本缺少
get_period_list),而且绝不能让它自带的 numpy 盖过 venv 自己的 numpy。qmtcli doctor 会
报告最终生效的来源,字段是 sdk_source。详见
Runtime caveats(英文)。
本地开发:
uv sync --extra dev
uv run qmtcli statuseditable pip 安装:
pip install -e .[dev]
qmtcli status发现能力:
qmtcli capabilities
qmtcli schema
qmtcli examples单次 RPC:
Get-Content examples\status.json | qmtcli rpc
Get-Content examples\data_call.json | qmtcli rpcJSONL 循环:
.\examples\jsonl_server.ps1通用集成说明见 examples/agent_tool.md。录制演示的脚本见
docs/demo_storyboard.md。
所有行情命令(calendar、bars、sector-stocks、download 等)现在也能通过 rpc/server
调用,不再局限于 CLI;把对应的 CLI 参数名当 JSON 字段发送即可,例如
{"command":"bars","symbols":["600519.SH"],"period":"1d"}。命令名支持短横线或下划线两种写法
(sector-stocks 或 sector_stocks)。
只有 server 模式支持 subscribe、subscribe_whole、unsubscribe,分别包装了回调式的
xtdata.subscribe_quote、subscribe_whole_quote、unsubscribe_quote:
{"command":"subscribe","symbol":"600519.SH","period":"1d"}
{"command":"subscribe_whole","symbols":["600519.SH","000001.SZ"]}
{"command":"unsubscribe","seq":1}订阅成功会返回 {"ok":true,"data":{"seq":1}},此后 xtquant 每次推送行情都会单独打印一行 JSONL,
带 event 字段而不是 ok,和普通响应交替出现在同一个 stdout 流里:
{"ok":true,"data":{"seq":1}}
{"event":"quote","seq":1,"symbol":"600519.SH","data":{"600519.SH":{"lastPrice":1500.0}}}单次的 rpc 命令和 CLI 都会拒绝订阅命令,返回
{"ok":false,"error":"subscribe commands require server mode"},因为订阅只有在 server 让进程
常驻时才有意义。
watch 是 server 模式 subscribe/subscribe_whole 的仅 CLI 替代方案:直接发起订阅,然后
阻塞在 xtdata.run() 里,每次行情推送打印一行 JSONL,直到被中断(Ctrl+C 会干净地以退出码 0
结束)。不支持通过 rpc/server 调用。
qmtcli watch 600519.SH
qmtcli watch 600519.SH 000001.SZ --period 1m
qmtcli watch 600519.SH 000001.SZ --whole{"event":"quote","symbol":"600519.SH","data":{"600519.SH":{"lastPrice":1500.0}}}qmtcli mcp 会启动一个 stdio MCP(Model Context Protocol)服务,把 qmtcli 命令暴露成 MCP
工具。以能力元数据为唯一事实来源:所有工具都从 AGENT_CAPABILITIES 生成,每次工具调用都
走和 rpc/server 相同的 rpc 派发逻辑——没有第二套命令注册表。
安装 mcp extra:
uv sync --extra mcp直接运行(走 stdio 上的 JSON-RPC;除此之外不会再向 stdout 打印任何内容):
qmtcli mcp注册进 Claude Code:
claude mcp add qmt -- uv run --directory D:/projects/qmtcli --extra mcp qmtcli mcp工具名是 qmt_<name>,短横线会替换成下划线,例如 qmt_full_tick、qmt_sector_stocks、
qmt_account_infos。这里没有像 CLI 那样常驻的 --account/--path——每个交易查询/账户类工具
都在每次调用时接受可选的 path/account/account_type 参数。
以下按设计被排除:buy、sell、cancel(下单/撤单)和 trade_call(直接暴露完整
XtQuantTrader 方法面的非受控 escape hatch)——需要下单交易请直接使用 CLI。watch 以及
subscribe/subscribe_whole/unsubscribe 三件套也被排除(分别是仅 CLI、仅 server 的流式推送,
不适合一次性的工具调用)。其余的——status、doctor、data_call、fields、download、所有
行情命令,以及所有交易查询(asset、positions、orders、trades 等)——都可以使用。
没有安装 mcp extra 时,qmtcli mcp 会打印
{"ok":false,"error":"mcp extra is not installed; pip install 'qmtcli[mcp]'"} 并以退出码 1 结束。
可以传 QMT 安装根目录,也可以传 userdata_mini 目录:
qmtcli --path D:\DFZQxtqmt_client_real_win64 doctor
qmtcli --path D:\DFZQxtqmt_client_real_win64\userdata_mini --account ACCOUNT_ID asset如果不传 --path,会检查这些默认路径:
D:\DFZQxtqmt_client_real_win64D:\DFZQxtqmt_client_test_win64C:\DFZQxtqmt_client_real_win64C:\DFZQxtqmt_client_test_win64
预期 SDK 位置:
<QMT root>\bin.x64\Lib\site-packages\xtquant
诊断:
qmtcli status
qmtcli doctor
python -m qmtcli status行情:
qmtcli calendar SH
qmtcli trading-dates SH --count 5
qmtcli sector-list
qmtcli sector-stocks 沪深A股
qmtcli full-tick 600519.SH 000001.SZ
qmtcli bars 600519.SH --period 1d --count 100
qmtcli local-data 600519.SH --period 1d --count 100
qmtcli full-kline 600519.SH --period 1m
qmtcli instrument-detail 600519.SH
qmtcli instrument-type 600519.SH
qmtcli divid-factors 600519.SH
qmtcli holidays
qmtcli period-list
qmtcli ipo-info
qmtcli cb-info 123001.SZ
qmtcli etf-info
qmtcli index-weight 000300.SH
qmtcli financials 600519.SH --tables Balance静态字段名参考字典(完全离线,不需要 QMT 环境):
qmtcli fields
qmtcli fields tick
qmtcli fields balanceL2 命令需要券商的 Level-2 行情权限,且不在官方 xtdata 文档页范围内:
qmtcli l2-quote 600519.SH
qmtcli l2-order 600519.SH
qmtcli l2-transaction 600519.SH把数据下载进本地 QMT 缓存;这些命令在 SDK 下载完成后返回,本身不会打印行情数据—— 行情数据请用上面的读取命令:
qmtcli download history 600519.SH --period 1d
qmtcli download financials 600519.SH --tables Balance
qmtcli download sectors
qmtcli download index-weight
qmtcli download cb
qmtcli download etf
qmtcli download holidays
qmtcli download history-contracts管理本地自定义板块(只修改本地板块定义;danger: mutates_local_data):
qmtcli sector create-folder MyGroup --parent 我的自定义板块
qmtcli sector create MySector --parent 我的自定义板块
qmtcli sector add MySector 600519.SH 000001.SZ
qmtcli sector remove-stocks MySector 600519.SH
qmtcli sector reset MySector 600519.SH
qmtcli sector remove MySector账户和交易命令需要 --account:
qmtcli --account ACCOUNT_ID asset
qmtcli --account ACCOUNT_ID positions
qmtcli --account ACCOUNT_ID orders
qmtcli --account ACCOUNT_ID orders --cancelable-only
qmtcli --account ACCOUNT_ID trades
qmtcli --account ACCOUNT_ID buy 600519.SH 100 1500.00
qmtcli --account ACCOUNT_ID sell 600519.SH 100 1500.00
qmtcli --account ACCOUNT_ID cancel ORDER_ID这些命令包装了具名的 XtQuantTrader 查询方法;完整映射见
docs/xttrader-alignment.md(英文)。大部分需要 --account:
qmtcli --account ACCOUNT_ID position-statistics
qmtcli --account ACCOUNT_ID credit-detail
qmtcli --account ACCOUNT_ID stk-compacts
qmtcli --account ACCOUNT_ID credit-subjects
qmtcli --account ACCOUNT_ID credit-slo-code
qmtcli --account ACCOUNT_ID credit-assure
qmtcli --account ACCOUNT_ID ipo-limit
qmtcli --account ACCOUNT_ID com-fund
qmtcli --account ACCOUNT_ID com-positionipo-data、account-infos、account-status 包装的 XtQuantTrader 方法本身不带账户参数,所以这
三个命令的 --account 是可选的——qmtcli 仍会连接 QMT 会话,只是跳过订阅账户:
qmtcli ipo-data
qmtcli account-infos
qmtcli account-statusdata-call 调用公开的 xtquant.xtdata 方法:
qmtcli data-call get_stock_list_in_sector --args "[\"沪深A股\"]"
qmtcli data-call get_cb_info --args "[\"123001.SZ\"]"trade-call 在连接账户后调用公开的 XtQuantTrader 方法。默认会把 StockAccount 对象
放在位置参数最前面:
qmtcli --account ACCOUNT_ID trade-call query_stock_orders
qmtcli --account ACCOUNT_ID trade-call some_method --args "[1,2]" --kwargs "{\"flag\":true}"
qmtcli --account ACCOUNT_ID trade-call method_without_account --no-account_ 开头的私有方法名会被阻止。
--xtdc-token(或环境变量 QMTCLI_XTDC_TOKEN)会开启独立 xtdatacenter 数据模式:在执行任何命令
之前,qmtcli 会先调用 xtquant.xtdatacenter.set_token() 和 .init(),这样 xtdata 调用就能走
迅投投研的独立数据服务,而不必依赖本地 QMT 客户端:
$env:QMTCLI_XTDC_TOKEN = "YOUR_TOKEN"
qmtcli calendar SH
qmtcli --xtdc-token YOUR_TOKEN --xtdc-port 58620 calendar SH这需要有效的迅投投研数据 token,且目前是实验性功能——只验证到 init() 调用成功,还没有走通
端到端的真实数据链路。--xtdc-port(默认 58620)已经接入命令行,但还没有对接到具体的
xtdatacenter 调用上。qmtcli doctor 会用 xtdc_available 字段报告 xtquant.xtdatacenter 模块本身
是否可导入。详见 Runtime caveats(英文)。
{"command":"status"}
{"command":"data_call","method":"get_stock_list_in_sector","args":["沪深A股"]}
{"command":"buy","account":"ACCOUNT_ID","symbol":"600519.SH","volume":100,"price":1500.0}server 模式下一行输入对应一行输出。请求里的 id 会被带回。
- 本地使用:
server只读 stdin、写 stdout,不打开 socket。 - 不下载或自动安装券商软件。
- 不保存账号密码或登录凭据。
- 不自动重试下单。
capabilities会标记下单和撤单能力为危险动作;download因为写入本地 QMT 缓存,被标记为downloads_data;sector因为创建/修改本地自定义板块,被标记为mutates_local_data。- A 股委托数量必须是正的 100 倍数。
- 委托价格必须大于 0。
- 阻止调用
_开头的xtdata/XtQuantTrader方法。 - 账户权限、风控检查和最终成交仍由 QMT 和券商控制。
qmtcli --help
qmtcli capabilities --help
qmtcli schema --help
qmtcli examples --help
qmtcli data-call --help
qmtcli download --help
qmtcli sector --help
qmtcli fields --help
qmtcli trade-call --help
qmtcli watch --help
qmtcli rpc --help
qmtcli server --help
qmtcli mcp --helpuv run --extra dev pytest -q
uv run --extra dev ruff check .
uv build从文档附录重新生成静态 fields 字典,并检查对齐矩阵是否和官方文档产生了漂移(CI 里每周也会自动
跑一次,见 .github/workflows/doc-drift.yml):
python scripts/extract_doc_fields.py
python scripts/check_doc_drift.py给代码 Agent 的项目说明见 AGENTS.md。
当前仓库保留了 PyPI 打包元数据,但不在当前工作流中发布。
如果 qmtcli 帮你省下了对接 QMT 的麻烦,欢迎点个 star——这是让更多人发现它最直接的方式。
用出问题、缺了什么命令、想接的 Agent 框架不顺手,也欢迎开 issue 或直接提 PR。
