Files
qmt_bridge/reference/xtquant_big_convert/docs/XTQUANT_COMPAT_REPLACEMENT.md
T

10 KiB
Raw Blame History

MiniQMT 无损替换兼容层

更新时间:2026-07-01

目标

把原来依赖 MiniQMT 的调用:

from xtquant.xttrader import XtQuantTrader
from xtquant.xttype import StockAccount
from xtquant import xtdata, xtconstant

替换为“大 QMT 策略进程 + Redis RPC”的远程调用,同时尽量保持业务代码继续使用:

xt_trader.query_stock_positions(acc)
xt_trader.query_stock_asset(acc)
xt_trader.query_stock_orders(acc)
xt_trader.query_stock_trades(acc)
xt_trader.order_stock(...)
xt_trader.order_stock_async(...)
xt_trader.cancel_order_stock_sysid(...)
xtdata.get_full_tick(...)

接入方式一:显式导入新包

适合先灰度,不影响机器上的真实 xtquant 包。

from bigqmt_signal_trader.xtquant_compat import (
    StockAccount,
    configure,
    xt_trader,
    xtdata,
)
from bigqmt_signal_trader import xtquant_compat as xtconstant

configure()

acc = StockAccount(xt_trader.client.account_id, "STOCK")
positions = xt_trader.query_stock_positions(acc)
ticks = xtdata.get_full_tick(["600000.SH"])

这类写法的优点是替换范围小,适合先在 core/trader.py 或独立测试脚本里验证查询链路。configure() 会原地更新已导入的 xt_trader / xtdata 对象,所以可以先 from ... import xt_trader,再调用 configure()

接入方式二:用 xtquant shim 替换老 import

适合最终切换。把本仓库的 src 放到 PYTHONPATH 最前面后,老代码里的:

from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
from xtquant import xtdata, xtconstant

会命中本仓库提供的 src/xtquant/ shim。这样主业务代码基本不用改,只需要在本地私有配置文件里设置 Redis 和账号:

# D:\gjzqqmt\xtquant_big_convert\src\bigqmt_signal_trader_client_config.py
BIGQMT_ACCOUNT_ID = "YOUR_ACCOUNT_ID"
BIGQMT_RPC_TIMEOUT_SECONDS = 6.0

BIGQMT_REDIS_CONFIG = {
    "host": "YOUR_REDIS_HOST",
    "port": 6379,
    "db": 5,
    "username": "",
    "password": "******",
}

BIGQMT_FULL_TICK_CACHE_CONFIG = {
    "enabled": False,
    "demand_ttl_seconds": 10,
    "cache_ttl_seconds": 10,
    "wait_seconds": 3.5,
}

然后启动前只需要确认本仓库的 srcPYTHONPATH 最前面:

$env:PYTHONPATH = "D:\gjzqqmt\xtquant_big_convert\src;$env:PYTHONPATH"

如果同一台机器仍然安装了真实 MiniQMT 的 xtquant 包,要确认 D:\gjzqqmt\xtquant_big_convert\src 位于 PYTHONPATH 最前面,否则 Python 会先加载真实 xtquant

推荐落地步骤

  1. 大 QMT 侧先运行 BIGQMT_REDIS_DRYRUN / bigqmt_signal_trader_redis_rpc_runtime.py,保持 rpc_allow_order_methods=False
  2. 原策略侧用显式导入方式跑查询自检:资产、持仓、单票五档行情、["SH","SZ"] 全市场行情。
  3. 查询链路稳定后,把原项目中 core/trader.py 的初始化切到兼容层,但仍保持远程下单关闭。
  4. 对比 MiniQMT 与大 QMT 返回的资产、持仓、委托、成交字段,确认业务字段都能读到。
  5. 只在确认风控、账号、委托价型都正确后,在大 QMT 私有配置里打开 rpc_allow_order_methods=True
  6. 最终切换时再使用 xtquant shim,让旧 import 保持不变。

当前已兼容的方法

MiniQMT 调用 兼容状态 说明
XtQuantTrader(path, session_id) 已兼容 构造本地 RPC 客户端,不连接 MiniQMT
register_callback() 已兼容 保存 callbackRPC 暂不推送回调
start() / connect() / subscribe() 已兼容 返回 0subscribe() 会补账号
query_stock_asset(acc) 已兼容 返回对象含 cashavailable_cashtotal_assetmarket_value
query_stock_positions(acc) 已兼容 返回对象列表,含 stock_codevolumecan_use_volumeavg_priceprice
query_stock_position(acc, code) 已兼容 返回单只持仓对象或 None
query_stock_orders(acc, cancelable_only=False) 已兼容 返回对象列表,含 order_typeorder_statusorder_volumetraded_volumeorder_sysid
query_stock_trades(acc) 已兼容 返回对象列表,含 order_typetraded_volumetraded_price
order_stock() / order_stock_async() 已兼容 需要大 QMT 本地配置打开 rpc_allow_order_methods=True
cancel_order_stock_sysid() 已兼容 需要大 QMT 本地配置打开 rpc_allow_order_methods=True
xtdata.get_full_tick(codes) 已兼容 默认直接 RPC 调用;支持单票、ETF、["SH", "SZ"] 全市场;可选打开 Redis 快照缓存
xtdata.get_instrument_detail(code) 已兼容 映射到大 QMT get_instrumentdetail()
xtdata.get_instrument_type(code) 已接入 优先调大 QMT;不支持时按代码前缀做基础判断
xtdata.subscribe_quote(...) / subscribe_whole_quote(...) Redis 订阅兼容 写入 bigqmt:quote_subscriptions:{account_id},并向 bigqmt:quote_events:{account_id} 发事件;callback 会收到一次当前快照/历史数据
xtdata.unsubscribe_quote(seq) Redis 事件兼容 不强依赖大 QMT 反订阅 API,直接删除 Redis 订阅表并推送 unsubscribe_quote 事件
xtdata.get_market_data(...) 已接入 RPC 透传到大 QMT ContextInfo.get_market_data,返回 DataFrame/字典结构会自动 JSON 化再还原
xtdata.get_market_data_ex(...) 已接入 RPC 大 QMT 不支持 get_market_data_ex 时回退到 get_market_data
xtdata.get_local_data(...) 已接入 RPC 大 QMT 不支持 get_local_data 时回退到 get_market_data
xtdata.get_stock_list_in_sector(...) 已接入 RPC 优先调大 QMT;失败时对 "沪深A股"get_full_tick(["SH","SZ"]) 过滤
xtdata.get_sector_list() / get_sector_info() 已接入 RPC 依赖大 QMT ContextInfo 是否支持
xtdata.get_divid_factors(...) 已接入 RPC 依赖大 QMT ContextInfo 是否支持
xtdata.download_history_data(...) / download_history_data2(...) 已接入 RPC 依赖大 QMT ContextInfo 是否支持
xtdata.get_trading_dates(...) / get_holidays() / download_holiday_data() 已接入 RPC 依赖大 QMT ContextInfo 是否支持
xtdata.get_ipo_info(...) 已接入 RPC 行情侧新股资料;交易侧 query_ipo_data() 仍是占位
xtdata.get_etf_info() / download_etf_info() 已接入 RPC 依赖大 QMT ContextInfo 是否支持
xtdata.get_option_list(...) / 历史期权列表 已接入 RPC 依赖大 QMT ContextInfo 是否支持
xtdata.get_financial_data(...) / download_financial_data(...) 已接入 RPC 支持 DataFrame 返回值序列化
xtdata.call_formula(...) / subscribe_formula(...) / unsubscribe_formula(...) / get_formula_result(...) 已接入 RPC 对应截图里的模型调用/订阅能力,依赖大 QMT ContextInfo 是否支持
xtdata.gen_factor_index(...) 已接入 RPC 对应生成因子数据,依赖大 QMT ContextInfo 是否支持
query_ipo_data() / query_new_purchase_limit() 占位兼容 当前返回空结果,打新需要后续补大 QMT 等价能力

下单开关

大 QMT 本地配置默认关闭远程下单。要真正替换 MiniQMT 下单,需要在 QMT 本地私有配置中显式开启:

BIGQMT_REDIS_CONFIG = {
    "host": "YOUR_REDIS_HOST",
    "port": 6379,
    "db": 5,
    "username": "",
    "password": "******",
    "rpc_allow_order_methods": True,
}

开启后,price_type 会从客户端透传到大 QMT passorder(),不会再固定成默认限价。

最小自检脚本

这个脚本只读,不会下单:

from bigqmt_signal_trader.xtquant_compat import StockAccount, configure, xt_trader, xtdata

configure()

acc = StockAccount(xt_trader.client.account_id, "STOCK")

asset = xt_trader.query_stock_asset(acc)
positions = xt_trader.query_stock_positions(acc)
tick = xtdata.get_full_tick(["600000.SH"])
all_a = xtdata.get_stock_list_in_sector("沪深A股")

print("cash:", asset.cash)
print("total_asset:", asset.total_asset)
print("positions:", len(positions), positions[:3])
print("bid5:", tick["600000.SH"]["bidPrice"])
print("ask5:", tick["600000.SH"]["askPrice"])
print("hs_a_count:", len(all_a))

如果想验证最终 shim 方式:

from xtquant.xttrader import XtQuantTrader
from xtquant.xttype import StockAccount
from xtquant import xtdata, xtconstant

trader = XtQuantTrader("", 12345)
acc = StockAccount(trader.client.account_id, "STOCK")

assert trader.connect() == 0
assert trader.subscribe(acc) == 0

print(xtconstant.STOCK_BUY)
print(trader.query_stock_asset(acc))
print(xtdata.get_full_tick(["600000.SH"]))

验证命令

cd D:\gjzqqmt\xtquant_big_convert
python -B -m unittest discover -s tests\bigqmt_signal_trader

实盘前建议先只跑查询链路:

from bigqmt_signal_trader.xtquant_compat import StockAccount, configure, xt_trader, xtdata

configure()

acc = StockAccount(xt_trader.client.account_id)
print(xt_trader.query_stock_asset(acc))
print(xt_trader.query_stock_positions(acc)[:3])
print(xtdata.get_full_tick(["600000.SH"]))

注意事项

  • subscribe_quote() / subscribe_whole_quote() 当前通过 Redis 记录订阅意图,并给 callback 推一次当前数据;持续行情推送需要独立的 Redis 行情生产者消费 bigqmt:quote_subscriptions:{account_id}
  • get_full_tick() 默认直接 RPC 现拉;如果全市场 payload 过大,再在客户端和 QMT 本地配置里打开 Redis 快照缓存。
  • unsubscribe_quote(seq) 当前按你的要求直接写 Redis:删除订阅表并推送 unsubscribe_quote 事件,不等待大 QMT 确认。
  • get_stock_list_in_sector("沪深A股") 的本地兜底会通过 get_full_tick(["SH", "SZ"]) 过滤 A 股,速度取决于大 QMT 全市场快照返回耗时。
  • 历史行情、财务、ETF、期权、模型/因子等接口已经接到 RPC,但实际是否可用取决于大 QMT 策略环境里的 ContextInfo 是否暴露同名方法。
  • query_ipo_data() / query_new_purchase_limit() 当前返回空结果,打新逻辑不能直接视为无损替换。
  • RPC 下单默认关闭;打开前必须确认大 QMT 页面正在运行正确账号的 RPC 策略。