434d7cb357
根因三层(全案=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>
109 lines
4.1 KiB
Python
109 lines
4.1 KiB
Python
"""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)
|