Files
sanguo_vnpy_v2/sanguo_qmt_bridge/check_xtquant.py
T
claude_dev 434d7cb357
CI/CD / test (push) Failing after 7s
CI/CD / nas-deploy (push) Has been cancelled
CI/CD / nas-verify (push) Has been cancelled
feat(config): QMT 部署身份单一权威源 config/qmt_identity.json——P2-18 账号硬编码根治(⚖️-2 用户拍板:确认永为模拟号+令根治硬编码)
根因三层(全案=audit/20261005_qmt_identity_env_plan.md): schtask 无 per-task env+机器级 env 未设→wrapper 被迫字面量;「部署身份」无单一权威源(env 名分裂三个);模拟号零安全压力致 32 文件 88 处 copy-paste 扩散。

- qmt_gate_common.load_identity 正典装载器(:14-59): env SANGUO_QMT_ACCOUNT/BIGQMT_ACCOUNT_ID(兼容别名)>json>RuntimeError fail-loud;SANGUO_IDENTITY_JSON 显式指路不存在=立即报错;查找=repo 相对>C:\sanguo_vnpy_v2\config\(生产副本回退位)
- 灾备腿同源: relogin/qmt_bridge_probe/setclip 改 from qmt_gate_common import ACCOUNT
- 桥腿镜像同链: xt_gateway._qmt_account/qmt_gateway_client._identity_default_account/is_price_source_vps/bridge_switch_ops(3 处 env 注入+1 处内嵌探针串)/check_xtquant——env 带默认的硬编码默认值全数退役
- xt_eod_wrapper.ps1 改 Get-Content identity json(保持 ASCII);码内 docstring 字面量→占位符(engine/runner/runner_live/live.yaml 注释/README)
- .gitignore 白名单 !config/qmt_identity.json(全局 *.json 曾吞之,git check-ignore 实证)
- tests/trader/test_qmt_identity.py 五钉: 装载链语义(env 双名覆盖/显式指路 fail)+单源一致性(identity≡live.yaml≡watch_accounts≡gate_common≡各腿镜像,休市表 CI 同步测先例)+码面字面量 grep-pin(生产码面零 66639661,只 config 三件套可含)
- 监控 spec: §3.2 账号来源 bullet/§9.A-18 坑条/§12 行数+行号勘正(插入块致 bridge_ping/calendar_probe/relogin_running 引用行号推移);runbook: 非代码资产两行(副本回退路径+生产 wrapper 待改清单=10-08 窗口后 §五③)

生产 wrapper(C:\sanguo_bigqmt 库外)字面量收尾=10-08 复市验证窗口后非代码资产流程;VPS 班车同窗口(护 10-08 07:50 relogin 首班旧码纯净)。trader+api 620 绿。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-05 17:32:42 +08:00

109 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""xtquant 可用性验证(D-1 bridge 开发前置)。
在 Windows 上跑,分 3 步确认 xtquant 能 import + 连 miniQMT + 查询账户/持仓。
miniQMT 客户端必须先登录并保持运行(极简模式)。
用法:填下面三个参数,python check_xtquant.py
若某步 API 报错,参考 miniQMT 自带 xtquant 文档 dict.thinktrader.net
或 NAS github-repos/OSkhQuant 源码调整签名(xtquant 版本可能有差异)。
"""
import json
import os
import sys
# ===== 用户填写(开始)=====
# 1. miniQMT 安装目录下的 userdata_mini 文件夹绝对路径
MINIQMT_USERDATA = r"D:\国金QMT交易端模拟\userdata_mini"
# 2. miniQMT 模拟账户 ID(客户端登录后可见的数字账号)
# 默认取部署身份单一权威源 config/qmt_identity.json(P2-18), env 可覆盖
_ACC_ENV = (os.environ.get("SANGUO_QMT_ACCOUNT")
or os.environ.get("BIGQMT_ACCOUNT_ID"))
if not _ACC_ENV:
_ident_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "..", "config",
"qmt_identity.json")
with open(_ident_path, encoding="utf-8") as _f:
_ACC_ENV = json.load(_f)["default_account"]
ACCOUNT_ID = _ACC_ENV
# 3. xtquant 所在的 site-packages 路径(miniQMT 安装目录\bin.x64\Lib\site-packages)
# 若 import 失败,在此目录找不到 xtquant,改 pip install xtquant 后填 None
XTQUANT_SITE_PACKAGES = r"D:\国金QMT交易端模拟\bin.x64\Lib\site-packages"
# ===== 用户填写(结束)=====
SESSION_ID = 20260710 # 任意 int,每个程序实例唯一
def step1_import():
"""[1/3] 验证 xtquant 能 import。"""
print("[1/3] 验证 import xtquant ...")
if XTQUANT_SITE_PACKAGES:
sys.path.insert(0, XTQUANT_SITE_PACKAGES)
try:
from xtquant import xttrader, xtdata
print(" ✅ import 成功")
return xttrader, xtdata
except Exception as e:
print(f" ❌ import 失败: {e}")
print(" → 检查 XTQUANT_SITE_PACKAGES 路径是否含 xtquant,或 pip install xtquant")
return None, None
def step2_connect(xttrader):
"""[2/3] 连接 miniQMT 客户端。"""
print("[2/3] 连接 miniQMT 客户端 ...")
try:
xt = xttrader.XtQuantTrader(MINIQMT_USERDATA, SESSION_ID)
xt.start()
ret = xt.connect()
if ret != 0:
print(f" ❌ connect 返回 {ret}(确认 miniQMT 客户端已登录运行 + userdata 路径正确)")
return None
print(" ✅ connect 成功")
return xt
except Exception as e:
print(f" ❌ connect 异常: {e}")
print(" → 确认 MINIQMT_USERDATA 路径 + miniQMT 客户端在运行")
return None
def step3_query(xt, xttrader):
"""[3/3] 查询模拟账户资金 + 持仓。"""
from xtquant.xttype import StockAccount # 账户类型本版不在 xttrader.STOCK_ACCOUNT,改用 StockAccount 对象
print("[3/3] 查询模拟账户 ...")
account = StockAccount(ACCOUNT_ID)
try:
xt.subscribe(account)
except Exception as e:
print(f" ⚠️ subscribe 异常(可忽略,继续): {e}")
asset = xt.query_stock_asset(account)
if not asset:
print(" ❌ query_stock_asset 返回空(账户ID/权限问题,或 miniQMT 未切到模拟账户)")
return False
print(f" ✅ 资金: cash={getattr(asset,'cash',None)} "
f"frozen={getattr(asset,'frozen_cash',None)} "
f"total={getattr(asset,'total_asset',None)}")
try:
pos = xt.query_stock_positions(account) or []
print(f" ✅ 持仓 {len(pos)} 只: {[getattr(p,'stock_code',None) for p in pos[:5]]}")
except Exception as e:
print(f" ⚠️ query_stock_positions 异常(资金通即可): {e}")
print("\n🎉 xtquant 全部可用 → D-1 bridge 可开发。把上面输出贴回来。")
return True
if __name__ == "__main__":
print(f"配置: userdata={MINIQMT_USERDATA}\n account={ACCOUNT_ID}\n")
xttrader, _ = step1_import()
if not xttrader:
sys.exit(1)
xt = step2_connect(xttrader)
if not xt:
sys.exit(1)
ok = step3_query(xt, xttrader)
sys.exit(0 if ok else 1)