Files
Docker df0b4b5f57 chore: trim reference/ to docs only (5.8MB -> 1.0MB)
- thinktrader_docs: keep .txt (extracted text), drop .html duplicates (36->18 files)
- xtquant_big_convert: keep README/LICENSE/CHANGELOG/.gitignore + docs/, drop src/tests/examples/benches/qmt-trader (project code, not referenced by bridge)
- un-ignore reference/xtquant_big_convert/.gitignore (now a normal tracked file)
2026-08-26 17:03:29 +08:00
..

xtquant_big_convert

PyPI Python License: MIT

大 QMT 运行环境里的 RPC 桥接包:把大 QMT 内置 Python(行情查询、交易、持仓)封装成可远程调用的服务,并兼容一组 MiniQMT 方法名,让外部程序无需 XtQuantServer 权限就能驱动大 QMT。

支持 Redis / ZMQ / MySQL / 共享内存 四种可插拔传输,切换只需改一个配置字段。

已发布 PyPI,客户端一行安装:pip install xtquant-big-convert(详见下文「环境要求与依赖安装」)。

另附 qmt-trader skill:让 Claude Code / ZCode / Cursor 等 AI 助手通过统一 CLI(46 个子命令)直接查行情、查持仓、下单撤单,详见下文「AI 助手 Skillqmt-trader」。


功能一览

RPC 接口(远程可调用)

通过 RPC 可调用的大 QMT 能力(白名单 117 个只读方法 + 2 个下单方法 + 12 个 MiniQMT 风格别名,覆盖官方文档全部交易/查询函数):

类别 方法
系统 ping
行情快照 get_ticks / get_full_tick(五档盘口)
K线/历史 get_market_data / get_market_data_ex / get_local_data / get_close_price / get_index_weight
L2 行情 get_l2_quote / get_l2_order / get_l2_transaction / subscribe_l2thousand(需 L2 权限)
板块 get_stock_list_in_sector / get_sector_list* / get_sector_info / create_sector / add_sector / remove_sector
交易日历/时段 get_trading_dates / get_holidays* / get_markets* / get_market_last_trade_date* / get_date_location / get_trading_calendar / get_trade_times
数据下载 download_history_data / download_history_data2 / download_holiday_data / download_etf_info / download_cb_data / download_history_contracts / download_index_weight / download_sector_data
财务/因子 get_financial_data / download_financial_data / download_financial_data2 / get_raw_financial_data / get_factor_data
ETF/期权/期货 get_etf_info / get_ipo_info / get_option_list / get_his_option_list / get_his_option_list_batch / get_option_detail_data / get_option_undl_data / get_option_undl / get_ETF_list / get_main_contract / get_his_contract_list
期权定价 bsm_price / bsm_iv / get_option_iv
龙虎榜/股东 get_longhubang / get_top10_share_holder / get_holder_num / get_turnover_rate(区间换手率)/ get_industry / get_his_st_data / get_his_index_data
资金流 get_north_finance_change(北向)/ get_hkt_statistics(港股通)/ get_hkt_details / get_hkt_exchange_rate
因子/模型 call_formula / subscribe_formula / unsubscribe_formula / get_formula_result / gen_factor_index
时间转换 datetime_to_timetag / timetag_to_datetime / timetagToDateTime(纯本地计算)
账户查询 get_asset(资金)/ get_positions(持仓)/ query_stock_position(单股持仓)/ query_orders(委托)/ query_trades(成交)/ get_history_trade_detail_data(历史成交)/ get_value_by_order_id / get_last_order_id
新股/打新 get_ipo_data / get_new_purchase_limit
融资融券 get_assure_contract(担保品)/ get_enable_short_contract(融券标的)/ get_unclosed_compacts(未平仓)/ get_closed_compacts(已平仓)/ get_debt_contract(负债)—— 需两融权限,普通账户降级为空
期权持仓 get_option_subject_position(标的持仓)/ get_comb_option(组合期权)
持仓同步 sync_positions(写回 Redis 供客户端缓存)
下单/撤单 submit_order / cancel_order(默认关闭,需显式开启)

客户端兼容层 BigQmtXtData 对常用方法有显式封装(xtdata.get_longhubang(...)xtdata.bsm_price(...) 等),其余通过万能入口 xtdata.call_method("get_float_caps", stockcode="000001.SZ") 调用。

* 标记的方法在大 QMT(完整交易端)环境下用 fallback 实现(非原生数据):get_sector_list 返回常用板块名清单,get_holidays 从交易日历反推,get_markets 返回固定市场集合,get_market_last_trade_date 从日历派生。详见 docs/RPC_API_REFERENCE.md 第 8 节「大 QMT 环境的能力边界」。

客户端兼容层

  • bigqmt_signal_trader.xtquant_compat:把旧代码的 xt_trader / xtdata 调用转成 RPC,无需改业务代码。
  • 兼容 MiniQMT 方法名:query_stock_asset / query_stock_positions / query_stock_orders / get_full_tick / order_stock 等。
  • 完整 xtconstant 枚举(91 个常量,对齐原生 MiniQMT):账号类型、委托类型(股票/期货/信用/期权)、报价类型、委托状态、账号状态、ORDER_TYPE_SET
# 旧代码零改动(自动命中 shim
from xtquant.xtconstant import STOCK_BUY, FIX_PRICE, ORDER_SUCCEEDED

# 或直接从 compat 导入
from bigqmt_signal_trader.xtquant_compat import (
    SECURITY_ACCOUNT, STOCK_BUY, FIX_PRICE, CREDIT_FIN_BUY,
    FUTURE_OPEN, ACCOUNT_STATUS_OK, ORDER_SUCCEEDED,
)

异步回报回调(MiniQMT 风格,实盘验证)

客户端注册 XtQuantTraderCallback 子类,connect()/subscribe() 后实时接收委托/成交/错误回报(通过 Redis pubsub 推送):

from bigqmt_signal_trader.xtquant_compat import (
    StockAccount, XtQuantTraderCallback, configure, xt_trader,
)

class MyCallback(XtQuantTraderCallback):
    def on_stock_order(self, order):
        print("委托回报:", order.stock_code, order.order_status, order.order_sysid)

    def on_stock_trade(self, trade):
        print("成交回报:", trade.stock_code, trade.order_id, trade.traded_volume, trade.traded_price)

    def on_order_error(self, order_error):
        print("委托失败:", order_error.order_id, order_error.error_id, order_error.error_msg)

    def on_cancel_error(self, cancel_error):
        print("撤单失败:", cancel_error.order_id, cancel_error.error_id, cancel_error.error_msg)

    def on_order_stock_async_response(self, response):
        print("异步下单回报:", response.account_id, response.order_id, response.seq)

    def on_account_status(self, status):
        print("账户状态:", status.account_id, status.account_type, status.status)

configure()
xt_trader.register_callback(MyCallback())
acc = StockAccount(xt_trader.client.account_id, "STOCK")
xt_trader.connect()
xt_trader.subscribe(acc)

# 异步下单(返回 seq,回报走回调)
seq = xt_trader.order_stock_async(acc, "600654.SH", 23, 100, 11, 2.95, "rpc_test", "备注")

完整的回调链(对齐 MiniQMT 原生语义,实盘验证):

回调 触发时机 已验证
on_account_status connect()/subscribe()
on_order_stock_async_response(seq, resp) 异步下单提交成功 (实盘)
on_stock_order(order) 委托状态变化(已报 50 / 已成 56 / 废单 57 (实盘)
on_stock_trade(trade) 成交回报
on_order_error(err) 废单/拒单(服务端检测 status=57 推送) (实盘)
on_cancel_error(err) 撤单失败
on_cancel_order_stock_async_response 异步撤单回报

*_async 查询方法(对齐 MiniQMT 签名,callback 可选):

# 方式 1callback 接收结果(MiniQMT 原生语义,返回 None
xt_trader.query_stock_asset_async(acc, lambda asset: print(asset.cash, asset.total_asset))
xt_trader.query_stock_positions_async(acc, lambda positions: print(len(positions)))

# 方式 2:不传 callback,返回 seq(我们的扩展)
seq = xt_trader.query_stock_orders_async(acc)

注意QMT 必须运行在实盘模式(非模拟/模型交易)才能收到完整回报。模拟模式下委托进 QMT 界面但不在真实委托队列,query_orders 查不到、order_stock 返回 -1(触发 on_order_error)。

全推行情订阅(subscribe_whole_quote 真推送)

subscribe_whole_quote服务端真推送——对齐 MiniQMT 全推行情订阅。服务端引用计数管理 ContextInfo.subscribe_whole_quote 回调,通过独立 PUB/SUB 通道向客户端增量推送行情(不是一次性快照):

架构(三通道)

  1. 控制面 RPC——subscribe_whole_quote / unsubscribe_whole_quote / quote_keepalive 方法(复用现有 transport
  2. 数据面推送——QuotePushChannel 单向 PUB/SUBredis pub/sub 或 zmq PUB/SUB,按部署 transport 选择;msgpack 编码 + json 兜底)
  3. Big-QMT 行情源——QuoteSubscriptionManager 按组合键归一化共享(大写/去空格/排序),多客户端共享一个底层订阅

关键设计

  • 组合键去重:不同客户端订阅相同标的组合,只占一个 big-QMT 订阅
  • 引用计数:按 (client_id, sub_id) 计数,全部退订或 30s keepalive 超时才销毁
  • 客户端心跳:周期 quote_keepalive;检测推送静默(默认 10 轮心跳)自动重放订阅,服务端重启后自动恢复
  • 初始快照:客户端用 get_full_tick 预拉快照(big-QMT 回调是增量的)

用法

from bigqmt_signal_trader.xtquant_compat import configure, xtdata

configure()

# 订阅全推行情(callback 收到增量推送)
def on_quote(data):
    for code, tick in data.items():
        print(code, tick.get("lastPrice"))

seq = xtdata.subscribe_whole_quote(["600000.SH", "000001.SZ"], callback=on_quote)

# 退订
xtdata.unsubscribe_quote(seq)

验证:实盘交易日验证 1/20/50/100 只标的,3s 推送节奏稳定,零丢失零乱序;多客户端共享/退订隔离/同客户端多 sub_id 全过;服务端重启恢复(42s 中断后验证两次)。详见 docs/SUBSCRIBE_WHOLE_QUOTE_PUSH.mddocs/SUBSCRIBE_WHOLE_QUOTE_LIVE_VERIFICATION.md

可插拔传输层

传输 同机 p50 跨机 适用场景
redis(默认) ~13ms 生产默认,稳定
zmq ~0.7ms* 同机低延迟
mysql ~105ms 兼容兜底
shm 接口预留(未实现)

*zmq fast-path;约 30% 请求会撞 QMT 的 GIL 调度尖峰(~500ms)。

FormulaServer 直连快速路径(只读行情,默认开启)

大 QMT 的 58600 端口是 FormulaServer——QMT 内置的 C++ 行情/参考数据服务(端口取自 config/formulaserver/formulaserver.ini[server_formula] address)。QMT 自带 Python 的 qmt_api 包就是它的客户端。

客户端对这些方法会绕开整条 RPC 链路(不经过 QMT 的 python 策略线程,也不抢 GIL), 实测 p50 0.07ms,穿过完整客户端栈是 0.145ms/次

对比 p50
redis RPC ~13ms
zmq RPC ~0.7ms30% 撞 500ms GIL 尖峰)
FormulaServer 直连 0.07ms(无 GIL 竞争)

直连覆盖 10 个方法:get_instrument / get_instrument_detail / get_instrumentdetail / get_last_volume / get_total_share / get_contract_multiplier / get_main_contract / get_weight_in_index / get_stock_list_in_sector / get_market_data_ex

能力边界(重要)FormulaServer 只有行情/参考数据。所有账户、持仓、委托、成交、下单 方法一律返回 ErrorID 200005 未找到该服务getFullTick/getQuote 也不存在。所以它是 只读快速路径,不是 RPC 桥的替代品——交易、账户查询、五档盘口仍然走 RPC。

以下方法刻意不走直连,因为参数语义与我们的调用方不一致,宁慢勿错:

  • get_trading_dates —— FormulaServer 要股票代码000001.SZ),传市场代码(SH)静默返回 [],而我们的调用方传的是市场。
  • get_divid_factors / get_risk_free_rate —— 参数语义不同(区间 vs 单日、index vs timetag)。
  • 复权 K 线 —— 实测 dividendTypenonefront 返回完全相同,复权未生效。因此只有 dividend_type="none" 才走直连,其余回退 RPC,避免静默返回未复权价格。 (复权数据还需先在服务端下载原始数据,见下文「复权数据下载陷阱」。)

配置(客户端侧,默认就是开启,通常不用写):

BIGQMT_REDIS_CONFIG = {
    "formula_server": {
        "enabled": True,              # 或环境变量 BIGQMT_FORMULA_ENABLED=0 关闭
        # "host": "127.0.0.1",        # 默认本机;FormulaServer 绑 0.0.0.0,跨机需放行防火墙
        # "port": 58600,              # 不写则从 qmt_root 的 ini 读,再退回 58600
        # "qmt_root": r"D:\国金证券QMT交易端",
        # "timeout_seconds": 3.0,
        # "methods": ["get_instrument"],       # 只路由白名单里的方法
        # "failure_cooldown_seconds": 30.0,    # 连不上后停用多久再重试
    },
}

失败一律自动回退 RPC:方法未映射、参数translate 不了、服务没起、连接断——都退回原路径, 所以连不上 58600 的客户端行为与改动前完全一致。BSON 编解码内置了无依赖实现(可选用 pymongo 的 bson,两者输出实测逐字节一致),客户端不需要额外装包。

QMT 启停 / 自动重启(qmt_launcher

大 QMT 基本每天早上要重启一次,卡点在登录框。两条路绕过它:

python -m bigqmt_signal_trader.qmt_launcher status  --dir "D:\国金证券QMT交易端_lemo"
python -m bigqmt_signal_trader.qmt_launcher restart --dir "D:\国金证券QMT交易端_lemo"
mode 做什么 需要登录框交互
linkmini(默认优先) XtMiniQmt.exe linkMiniMiniQMT 免密启动
bat 跑指定批处理(如 免密登录qmt.bat
exe 直接起 XtItClient.exe,靠终端自身恢复会话
login 起 exe 后向登录框输入账号密码 是,需 pywin32

关于「pywinauto/pyautogui 要求 Windows 处于登录状态」login 模式用的是 win32api.SendMessage 直接投递到窗口句柄,不是 pyautogui 那种按屏幕坐标重放物理输入。 前者不要求窗口置于前台,锁屏下也能工作(会话还在即可,完全注销则不行)。密码从 环境变量 BIGQMT_LOGIN_USER / BIGQMT_LOGIN_PASSWORD 读,不走命令行参数——argv 对同机任何进程可见。

两个设计要点:

  • 按安装目录隔离。同机常并行跑多个 QMTtaskkill /im XtItClient.exe 会误杀别人的 实盘。这里只终结 --dir 对应 bin.x64 下的进程;拿不到 exe 路径的进程直接跳过而不是 猜。
  • 等就绪而不是 sleep 固定秒数。启动完成的判据是 FormulaServer 端口(58600)能接受连接, 超时抛 QmtLauncherError 而不是静默返回,避免定时任务在没起来的终端上继续跑。

restart 默认在关闭后等 5 秒再启动:ZMQ 传输是精确绑定配置端口(不扫描),socket 没 完全释放就重启会绑定失败。

独立 ZMQ 回测桥接

bigqmt_backtest 与实盘 RPC 桥接完全分离,提供两个明确隔离的后端:

  • QMT_NATIVEBIGQMT_ZMQ_BACKTEST.py 运行在 QMT 回测进程内。QMT 负责历史 行情推进、资金持仓、passorder/cancel 和原生撮合;ZMQ 只桥接 Bar、订单意图及 QMT 委托/成交结果。
  • LOCAL_SIM:端口 16661 的独立 CSV 工具,仅用于脱离 QMT 验证协议和策略逻辑, 使用本地撮合并输出本地结果文件。

QMT 原生入口使用独立端口 16662、独立 run_id/client_id,强制验证 ContextInfo.do_back_test=true,固定 live_ready=false,不会导入或修改 bigqmt_signal_trader

启动 CSV 独立测试服务:

python -m pip install -e .
python -m bigqmt_backtest.server `
  --data examples/backtest_bars.example.csv `
  --config examples/backtest_config.example.json `
  --run-id demo-001 `
  --bind tcp://127.0.0.1:16661

另开一个终端运行外部策略:

python examples/zmq_backtest_strategy.py `
  --endpoint tcp://127.0.0.1:16661 `
  --run-id demo-001 `
  --symbol 600000.SH `
  --fast 2 `
  --slow 3

QMT 原生安装、逐 Bar 同步协议、CSV 备用模式和安全边界见 docs/ZMQ_BACKTEST_BRIDGE.md

无 redis 版本(QMT 沙箱拒绝 import redis 时用)

如果你的 QMT 环境拒绝 import redis(券商白名单拦截),用 bigqmt_no_redis/ 目录下的无 redis 版本:

  • bigqmt_no_redis/zmq_transport.py — 自包含的 ZMQ transport,内联所有编码函数,完全不 import redis_common/redis_rpc,去掉 redis 服务发现(用静态派生端口)
  • bigqmt_no_redis/DRYRUN_no_redis.py — 无 redis 的 DRYRUN 入口,强制 transport=zmq + background_threads=True,只加载 zmq transport

用法QMT 策略编辑器加载 BIGQMT_DRYRUN_NO_REDIS.py(同步到 QMT 目录时用这个文件名),RPC 走纯 ZMQ,零 redis 依赖。其余功能(行情/交易/持仓查询)与标准版一致。

委托/成交查询的 strategy_name 陷阱(重要)

get_trade_detail_datastrategy_name 过滤委托/成交——下单时用的 strategy_name 必须和查询时一致,否则查不到。

  • 下单时传 strategy_name="rpc_test" → 委托记在 rpc_test
  • 查询时传 strategy_name="bigqmt_signal_trader" → 返回空(不匹配)

修复query_orders / query_trades 默认传空字符串 "",返回该账户的全部委托/成交(不按 strategy_name 过滤)。如需过滤,显式传 strategy_name

实测验证(get_trade_detail_data 探测):

  • st="" → ORDER=9, DEAL=9(全部)
  • st="rpc_test" → ORDER=3, DEAL=1(只有 rpc_test 的)
  • st="bigqmt_signal_trader" → ORDER=0, DEAL=0(空)

复权数据下载陷阱(重要)

前/后复权 K 线必须先在服务端下载原始数据,否则返回全 0

Big QMT 的复权(dividend_type='front'/'back')是服务端现场计算的——需要原始 K 线 + 除权因子已经在服务端存在。直接请求 front 而服务端没下载过原始数据时,返回的 close 全是 0.0(只有最后一根有价)。

实测复现(600654.SH / 600227.SH):

  • 直接 get_market_data_ex(dividend_type='front') → 634 行全 0
  • download_history_data 后再请求 → 真实复权价(front ≠ none,复权生效)

已修复xtdata.download_history_data2(codes, period, dividend_type='front') 现在会自动先触发服务端原始数据下载(拉原始 K 线 + 除权因子),再拉复权数据到本地缓存。用法不变:

# 前复权下载(自动先服务端下载原始数据 + 除权因子)
xtdata.download_history_data2(["600654.SH"], period="1d",
                               start_time="20240101", dividend_type="front")

# 之后本地读取(零 RPC
xtdata.get_local_data(["close"], ["600654.SH"], period="1d",
                      start_time="20240101", dividend_type="front")

读取类 API 也自愈get_market_data_ex / get_market_data 带复权参数时,若检测到返回全 0(服务端缺原始数据),会自动触发服务端下载、等待落盘、重试一次,拿到真实复权价。get_local_data 的 fallback 拉取同样受益。无需手动等待。

注意:QMT 服务端下载是异步落盘的,自愈路径内置了等待 + 一次重试;极端大区间若一次重试仍全 0,可稍后重读或先显式 download_history_data2

实盘卖出方向误判修复(exec_events

实盘发现:QMT 回调里 m_nDirection 恒为 48(即使是卖出),导致卖出被误判为买入。

修复(exec_events._extract_direction)改为仲裁链:

  1. m_nOffsetFlag(最可靠,匹配 query_orders
  2. m_nDirection(传统 EEntrustBS,但实盘可能恒为 48
  3. 当 direction≠offset(期货:卖+开仓=49+48),用 m_nOpType23=买/24=卖)仲裁
  4. m_nOpType/order_type(兜底)

对股票现货,direction=offset48=买/49=卖);对期货,direction≠offset,仲裁保正确。

多账号使用(股票+期货 / 普通+信用)

当前架构是单账号单实例——一个 QMT 策略进程绑定一个账号,RPC channel 按 account_id 隔离(bigqmt:rpc:req:{account_id})。多账号场景(如股票+期货、普通+信用账户同时交易)的推荐方案是在 QMT 里跑多个策略实例,每个实例绑一个账号。

方案:多策略实例(推荐,不改代码)

服务端(QMT 内):为每个账号创建一个独立的配置文件和 DRYRUN 入口。

# bigqmt_signal_trader_local_config_stock.py  — 股票账号
BIGQMT_ACCOUNT_ID = "你的股票账号"
BIGQMT_REDIS_CONFIG = {
    "host": "...", "port": 6379, "db": 5, "password": "...",
    "transport": "redis",          # 或 "zmq"
    "account_type": "STOCK",       # 股票
    # ...
}

# bigqmt_signal_trader_local_config_credit.py  — 信用账号
BIGQMT_ACCOUNT_ID = "你的信用账号"
BIGQMT_REDIS_CONFIG = {
    "host": "...", "port": 6379, "db": 5, "password": "...",
    "transport": "redis",
    "account_type": "CREDIT",      # 信用(两融)
    # ...
}

然后在 QMT 策略编辑器里加载两个 DRYRUN 文件(每个指向不同的配置),分别运行。两个实例的 RPC channel 自动隔离(按 account_id)。

zmq 模式注意:每个实例的 zmq 端口从 account_id 派生(15560 + account_id mod 100),不同账号自动不冲突。

客户端(外部程序):为每个账号创建独立的 client/trader 对象。

from bigqmt_signal_trader.xtquant_compat import BigQmtRpcClient, BigQmtXtTrader, StockAccount

# 股票账号
stock_client = BigQmtRpcClient(account_id="股票账号", redis_config={...})
stock_trader = BigQmtXtTrader(account_id="股票账号", redis_client=stock_client.redis_client)
stock_acc = StockAccount("股票账号", "STOCK")

# 信用账号
credit_client = BigQmtRpcClient(account_id="信用账号", redis_config={...})
credit_trader = BigQmtXtTrader(account_id="信用账号", redis_client=credit_client.redis_client)
credit_acc = StockAccount("信用账号", "CREDIT")

# 分别查询/下单
stock_asset = stock_trader.query_stock_asset(stock_acc)
credit_positions = credit_trader.query_stock_positions(credit_acc)

跨账号隔离:每个账号的 RPC channel、持仓查询、委托回报完全隔离(按 account_id 路由),互不影响。


环境要求与依赖安装

本系统分两部分,各自需要自己的 Python 环境和依赖:

部分 运行位置 Python 装什么
客户端(外部程序) 你的开发机 3.8+(推荐) pip install xtquant-big-convert
服务端QMT 内) QMT 的 bin.x64/python.exe 3.6QMT 自带) 按传输装 1 个包

A. 客户端(外部程序,推荐 pip 安装)

客户端就是写策略/调接口的那台电脑(也叫「开发机」)。直接 pip 安装:

# 基础安装(含 pyzmq,zmq 传输必需)
pip install xtquant-big-convert

# 含 redis 支持(redis 传输)
pip install xtquant-big-convert[redis]

# 含 mysql 支持(mysql 传输)
pip install xtquant-big-convert[mysql]

# 开发环境(含测试工具)
pip install xtquant-big-convert[dev]

# 从源码安装(开发模式)
git clone https://github.com/litaolemo/xtquant_big_convert.git
cd xtquant_big_convert
pip install -e .

安装后可直接 import

from bigqmt_signal_trader.xtquant_compat import configure, xt_trader, xtdata
from bigqmt_signal_trader.transports.factory import build_transport

configure()
print(xtdata.get_full_tick(["000001.SZ"]))

B. 服务端(QMT 内 Python 3.6

QMT 自带 Python 3.6bin.x64/python.exe),只需按你选的传输装对应依赖

传输 服务端需要的包 客户端需要的包
redis(默认) redisQMT 通常已内置) redis
zmq pyzmq pyzmq(基础安装已含)
mysql pymysql + DBUtils pymysql + DBUtils

⚠️ 用 redis 传输就不需要装 pyzmq / pymysql / DBUtils——下面的安装说明是按需的,你用什么传输装什么。

安装到 QMT 的 Python(以 zmq / mysql 为例):

QMT 的 Python 3.6 用旧 OpenSSLpip 直连 HTTPS 镜像会报 SSL 错误。有两种方法:

# 方法 A:从开发机拷贝纯 Python 包(推荐,绕过 SSL 问题)
# pymysql / DBUtils 是纯 Python,可直接拷贝;在开发机(已装这些包)执行:
$QMT_SITE = "D:\国金证券QMT交易端\bin.x64\Lib\site-packages"
Copy-Item -Recurse "C:\Users\<你>\anaconda3\Lib\site-packages\pymysql" "$QMT_SITE\pymysql"
Copy-Item -Recurse "C:\Users\<你>\anaconda3\Lib\site-packages\dbutils" "$QMT_SITE\dbutils"

# 方法 B:用 QMT python pip 装(可能因 SSL 失败,需配置信任)
cd D:\国金证券QMT交易端
.\bin.x64\python.exe -m pip install --trusted-host mirrors.aliyun.com pymysql DBUtils

验证安装:

.\bin.x64\python.exe -c "import pymysql; from dbutils.pooled_db import PooledDB; print('OK')"

pyzmq 特殊说明:包含 C 扩展,不能直接拷贝。Python 3.6 需装 pyzmq==19.0.2(最后一个支持 3.6 的版本)。如果 SSL 装不上,可下载对应 wheel 手动 pip install xxx.whl


快速开始

前置:客户端已按上面「A. 客户端」装好包;服务端按「B. 服务端」装好所选传输的依赖。下面是从零跑通整套流程的步骤。

第 1 步:同步代码到 QMT 的 python 目录

把以下内容复制到大 QMT 的 python 目录(如 D:\国金证券QMT交易端\python\):

src/bigqmt_signal_trader/          (整个核心包,含 transports/
src/bigqmt_signal_trader_strategy.py
src/bigqmt_signal_trader_redis_rpc_runtime.py
src/BIGQMT_REDIS_DRYRUN.py         (★ QMT 编辑器入口,GBK 编码,在 QMT 里加载这个)

在 QMT 策略编辑器里只加载 BIGQMT_REDIS_DRYRUN.py 一个文件。它会自动 import 上面其余文件。其余 .pybigqmt_signal_trader_*)是它依赖的模块,不是直接运行的入口。

第 2 步:创建 QMT 端私有配置

在 QMT 的 python 目录创建 bigqmt_signal_trader_local_config.py不要提交此文件):

# coding: utf-8
BIGQMT_ACCOUNT_ID = "你的资金账号"        # 如 "1234567890"

BIGQMT_REDIS_CONFIG = {
    "host": "你的Redis地址",              # 如 "192.168.1.100"
    "port": 6379,
    "db": 5,
    "password": "你的Redis密码",

    # === 传输选择(默认 redis,生产推荐)===
    # "transport": "redis",              # 不写就是 redis
    # 切 zmq(同机低延迟,实测 p50~0.3ms):装了 pyzmq 后只需这一行。
    #   非 redis 传输会自动开 background_threads;端口按账号派生 127.0.0.1:1556x。
    # "transport": "zmq",
    # 切 mysql(兼容兜底):需装 pymysql+DBUtils,同样自动开 background_threads。
    # "transport": "mysql",
    # "mysql": {"driver":"pymysql","host":"...","port":3306,"user":"root",
    #           "password":"...","database":"bigqmt_rpc","charset":"utf8mb4"},

    "rpc_allow_order_methods": False,    # 下单默认关闭
    "rpc_process_in_listener": True,     # 只读请求在收包线程直接处理(低延迟)
    "rpc_listener_methods": ("*",),      # * = 所有只读方法
    "rpc_background_threads": False,     # redis 用 QMT adjust 线程 drain
    "schedule_adjust": True,
    "schedule_adjust_interval": "500nMilliSecond",
}

重要:切到 zmq 或 mysql 时,必须同时设 "rpc_background_threads": True(这两种传输用自己的后台线程,不走 QMT 回调 drain)。

第 3 步:在 QMT 里运行策略(BIGQMT_REDIS_DRYRUN.py

入口文件是 src/BIGQMT_REDIS_DRYRUN.py(GBK 编码,QMT 友好)。在 QMT 策略编辑器加载并运行它。

这个文件做什么

它是 QMT 编辑器入口的"外壳"(shell),按顺序做 5 件事:

  1. 定位 python 目录:把 QMT 的 python 目录加到 sys.path,让 bigqmt_signal_trader 包能 import。
  2. reload 模块importlib.reload 刷新 redis_common / redis_rpc / strategy / runtime —— QMT 在编辑器里重跑策略时,进程不退出,reload 确保新代码立即生效。
  3. 注入 Redis 配置:读 bigqmt_signal_trader_local_config.py 里的 BIGQMT_REDIS_CONFIG,调 configure_runtime_redis()
  4. 注入账号:读 BIGQMT_ACCOUNT_ID,调 configure_runtime_account()。如果配置没给,fallback 用 QMT 全局变量 account
  5. 绑定 QMT 原生 API:把 QMT 内置的 passorder / cancel / get_trade_detail_data 函数绑进 runtime(用 try/except NameError 包住,因为这些名字只在大 QMT 进程内存在)。
  6. 导出 QMT 回调init = _runtime.init / handlebar = _runtime.handlebar / adjust = _runtime.adjust 等,让 QMT 能回调到我们的策略逻辑。

⚠️ 硬编码路径(重要)

BIGQMT_REDIS_DRYRUN.py 里有一处写死的 QMT python 目录路径,作为 __file__ 找不到时的 fallback

def _known_qmt_python_dir():
    root = "".join(chr(value) for value in (0x56fd, 0x91d1, 0x8bc1, 0x5238))   # 国金证券
    suffix = "".join(chr(value) for value in (0x4ea4, 0x6613, 0x7aef))          # 交易端
    return "D:\\" + root + "QMT" + suffix + "\\python"
    # 解码后 = D:\国金证券QMT交易端\python
  • chr() 编码是为了规避 QMT 用 GBK 保存策略文件时中文乱码(用 Unicode 码点拼出"国金证券交易端")。
  • 路径优先级:先用 __file__ 所在目录(脚本实际位置),找不到才用这个硬编码 fallback。
  • 如果你的 QMT 装在别的路径(比如 D:\华泰QMT\python):通常不用改,因为 __file__ 优先。但如果你用 exec 方式加载(__file__ 未定义),需要把 _known_qmt_python_dir() 改成你的路径,或直接硬编码:
    def _known_qmt_python_dir():
        return r"D:\你的券商QMT\python"
    

启动成功标志(QMT 输出面板)

[bigqmt_shell] reload entry paths=['D:\\国金证券QMT交易端\\python']
[bigqmt_shell] local redis config loaded keys=['host', 'port', 'db', ...]
[bigqmt_shell] local account config loaded=True
[bigqmt_rpc] transport=redis mode process_in_listener=True listener_methods=('*',) ...
[bigqmt_rpc] started channel=bigqmt:rpc:req:你的账号
[bigqmt_signal_trader] init ok

为什么是 GBK 编码? QMT 的策略编辑器用本地代码页(中文 Windows 是 GBK)保存文件。文件头 #coding:gbk 声明编码,避免 QMT 保存时破坏 UTF-8 内容。源码本身是 ASCII(中文用 chr() 拼),所以实际不会乱码。

为什么不直接用 bigqmt_signal_trader_redis_rpc_runtime.py 那个文件是纯逻辑入口,不包含 reload 和 QMT API 绑定。BIGQMT_REDIS_DRYRUN.py 是给 QMT 编辑器专用的外壳,处理了 QMT 进程不退出导致模块缓存、API 绑定等坑。在 QMT 里只加载 BIGQMT_REDIS_DRYRUN.py

第 4 步:客户端调用

方式 A:用兼容层(推荐,旧代码零改动)

客户端创建配置文件 bigqmt_signal_trader_client_config.py(与上面类似但用客户端视角),然后:

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

configure()

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

# 行情
ticks = xtdata.get_full_tick(["000001.SZ"])
print(ticks["000001.SZ"]["lastPrice"])

# 持仓 / 资金
positions = xt_trader.query_stock_positions(acc)
asset = xt_trader.query_stock_asset(acc)
print(asset.cash, asset.total_asset)

# K线(自动还原成 pandas DataFrame
klines = xtdata.get_market_data_ex(
    field_list=["close"], stock_list=["000001.SZ"], period="1d", count=5
)

方式 B:直接 RPC 调用

from bigqmt_signal_trader.redis_rpc import call_redis_rpc
import redis

r = redis.Redis(host="192.168.1.100", port=6379, db=5, password="...")
resp = call_redis_rpc(r, "你的账号", "get_full_tick", {"codes": ["000001.SZ"]})
print(resp["data"]["000001.SZ"]["lastPrice"])

方式 C:无缝替换旧 xtquant(最终切换)

把仓库 src 放到 PYTHONPATH 最前面,旧代码的 from xtquant import xtdata 自动命中本仓库 shim

$env:PYTHONPATH = "D:\gjzqqmt\xtquant_big_convert\src;$env:PYTHONPATH"
# 旧代码完全不改
from xtquant import xtdata
ticks = xtdata.get_full_tick(["600000.SH"])  # 走 RPC 到大 QMT

切换传输层

只需改一个字段

服务端 + 客户端的配置文件里,transport 字段保持一致即可:

BIGQMT_REDIS_CONFIG = {
    "transport": "zmq",                  # redis / zmq / mysql / shm
    "zmq": {"host": "127.0.0.1"},        # 各传输子配置
    # redis 配置保留(zmq 服务发现、mysql 不需要时的 fallback 都用它)
}

各传输配置示例

Redis(默认)

{"transport": "redis"}  # 或省略 transport 字段

ZMQ(同机低延迟,需 pyzmq):

{
    "transport": "zmq",
    "rpc_background_threads": True,        # 必须!
    "zmq": {
        "host": "127.0.0.1",              # 默认端口从 account_id 派生
        # "port": 5560,                   # 可显式指定
        # 端口冲突时自动找空闲端口 + 通过 Redis 服务发现告知客户端
    },
}

MySQL(兼容兜底,需 pymysql + DBUtils):

{
    "transport": "mysql",
    "rpc_background_threads": True,        # 必须!
    "mysql": {
        "driver": "pymysql",
        "host": "192.168.1.100", "port": 3306,
        "user": "root", "password": "...",
        "database": "bigqmt_rpc", "charset": "utf8mb4",
        "poll_interval_seconds": 0.01,
        "pool_config": {"mincached": 1, "maxcached": 3, "maxshared": 0, "maxconnections": 4},
    },
}

ZMQ 端口与服务发现

  • 默认端口从 account_id 派生:15560 + (账号数字 mod 100),不同账号自动不冲突。
  • 端口被占时,server 自动往上扫描找空闲端口,把真实地址写到 Redis key bigqmt:zmq:addr:{account_id}TTL 300s)。
  • 客户端连接时按优先级解析地址:显式 connect_address > Redis 服务发现 > 默认派生端口。
  • server 退出时自动清理 discovery key。
  • 服务发现是可选的(没配 Redis client 时退化为静态派生端口)。

完整传输层文档见 docs/RPC_TRANSPORTS.md


实测延迟对比(真实直连 QMT

三种传输全部实测,端到端连接真实 QMT 进程,n=15/方法:

传输 ping p50 get_full_tick p50 成功率 尖峰来源
Redis 13ms 15ms 100% 偶发 245ms(网络抖动)
ZMQ 0.7ms* 0.7ms* 100% 30% 撞 500msQMT adjust GIL
MySQL 104ms 110ms 100% 轮询开销

*ZMQ fast-path(避开 GIL 尖峰的请求);overall p90 ~498ms。

生产推荐 Redis:稳定、跨机、无 GIL 问题、QMT 端零额外依赖。ZMQ 理论最快但受 QMT 主线程 GIL 调度影响。MySQL 仅作兜底。

复现基准:

python bench_latency.py        # Redis 单传输延迟
python bench_transports.py -n 100  # Redis vs ZMQ 对比

目录结构

src/bigqmt_signal_trader/
├── transports/                    可插拔传输层
│   ├── base.py                    RpcTransport 抽象接口
│   ├── redis_transport.py         Redis(默认,rpush/blpop/brpop
│   ├── zmq_transport.py           ZMQROUTER/DEALER + 服务发现)
│   ├── mysql_transport.py         MySQL(轮询 + DBUtils 连接池)
│   ├── shm_transport.py           共享内存(stub
│   └── factory.py                 build_transport 工厂
├── adapters/                      QMT API 适配器
│   ├── market_bigqmt.py           行情(ContextInfo 封装)
│   ├── order_bigqmt.py            下单(passorder
│   ├── position_bigqmt.py         持仓(get_trade_detail_data
│   └── redis_common.py            Redis 连接/编解码
├── redis_rpc.py                   RPC 服务(handlers + service + transport 集成)
├── xtquant_compat.py              客户端兼容层(xt_trader / xtdata + 异步回调)
├── exec_events.py                 委托/成交/错误事件推送(Redis pubsub
├── quote_push_channel.py          全推行情推送通道(redis/zmq PUB/SUB
├── quote_subscription_manager.py  服务端全推订阅管理(引用计数 + 组合键去重)
├── whole_quote_session.py         客户端全推订阅会话(心跳 + 重启恢复)
├── full_tick_cache.py             全市场行情快照缓存(可选降载)
├── strategy.py 之类               策略骨架、风控、价格引擎等
bigqmt_no_redis/                   无 redis 版本(QMT 沙箱拒绝 import redis 时用)
│   ├── zmq_transport.py           自包含 ZMQ transport(内联编码,零 redis 依赖)
│   └── DRYRUN_no_redis.py         无 redis DRYRUN 入口
src/xtquant/                       可选 xtquant import shim
src/bigqmt_signal_trader_strategy.py        策略入口(init/handlebar/adjust + 启动诊断)
src/bigqmt_signal_trader_redis_rpc_runtime.py  Redis RPC runtime 入口
src/BIGQMT_REDIS_DRYRUN.py                  QMT 编辑器加载入口(GBK
src/BIGQMT_ZMQ_BACKTEST.py                  独立 QMT 回测 ZMQ 入口(GBK
src/bigqmt_backtest/                        独立历史驱动、模拟撮合、ZMQ 协议与客户端
tests/bigqmt_signal_trader/        单元测试(无 QMT 环境可跑)
tests/bigqmt_backtest/             回测、确定性、隔离和 ZMQ 往返测试
qmt-trader/                        AI 助手 Skill(大模型直接操作 QMT,见下文专节)
│   ├── SKILL.md                   skill 说明书(命令速查 + 工作流 + 安全须知)
│   ├── scripts/qmt.py             统一 CLI46 子命令 + rpc 兜底)
│   └── references/api_reference.md  完整 API 参考
docs/                              详细文档
test_all_apis.py                   端到端 API 测试(发现生产问题)
bench_latency.py / bench_transports.py  延迟基准脚本

本地测试

python -m pytest tests/bigqmt_signal_trader/ -q

当前覆盖 199 个用例(含传输层往返、Redis RPC、客户端兼容、持仓/行情/下单 handlers、异步回调、执行事件)。

端到端 API 测试(发现生产问题)

test_all_apis.py端到端验证测试——不只测「调用成功」,还测「结果正确」,能发现这些生产问题:

验证项 检测什么 为什么重要
客户端/服务端一致性 ping 超时 → transport 不匹配 Issue #24 根因:客户端 redis / 服务端 zmq 连不上
持仓查询 get_positions 返回空但账户有持仓 容错设计把「失败返回空」当成「正常」
委托查询 query_orders 返回空 strategy_name 不匹配(默认应为 "" 返回全部)
买入/卖出 submit_order 成功但委托没进系统 静默失败(passorder 被 QMT 拒绝但没报错)
server_error 显示 QMT 端拒绝原因 委托被 QMT 静默拒绝时返回具体原因

用法

# 方式 A:用环境变量
$env:BIGQMT_ACCOUNT_ID="你的账号"
$env:BIGQMT_REDIS_HOST="你的Redis地址"
$env:BIGQMT_REDIS_PORT="6379"
$env:BIGQMT_REDIS_DB="5"
$env:BIGQMT_REDIS_PASSWORD="你的密码"
python test_all_apis.py

# 方式 B:用 QMT 端配置(需 bigqmt_signal_trader_local_config.py 在 PYTHONPATH
$env:PYTHONPATH="D:\国金证券QMT交易端\python;$env:PYTHONPATH"
python test_all_apis.py

示例输出(发现问题时):

--- 端到端验证: 客户端/服务端一致性 ---
客户端配置 transport: redis
❌ ping 失败: redis rpc timeout: ping
   可能原因: 客户端 transport 和服务端不匹配
   - 客户端配置 transport=redis
   - 如果服务端是 zmq, 客户端也要设 transport=zmq

--- 端到端验证: 持仓查询 ---
⚠️  get_positions 返回空 — 账户可能真的没持仓, 或查询失败 (检查 QMT 上下文)

--- 端到端验证: 买入/卖出 ---
✅ submit_order OK
❌ 委托没进系统 — submit_order 成功但 query_orders 找不到
   这是静默失败 (passorder 被 QMT 拒绝但没报错)
   检查: 1) 价格是否超出范围 2) 账户权限 3) QMT 风控

日志与排错(出错去哪看)

系统自带文件日志——所有报错/异常同时写 QMT 输出面板和本地日志文件,重启/崩溃后也能回溯。

日志位置

环境 日志文件
QMT 内(服务端) <QMT python 目录>\logs\bigqmt.log(如 D:\国金证券QMT交易端_lemo\python\logs\bigqmt.log
外部客户端 ~\.cache\bigqmt\logs\bigqmt.log(用户目录下)
  • 按天轮转(午夜),默认保留最近 7 天
  • 每行带时间戳 + 级别 + 模块标签:2026-08-14 21:45:59 [ERROR] [bigqmt.quote_push] publisher start failed: ...

查看方式

# 实时跟踪日志
Get-Content "D:\国金证券QMT交易端\lempython\logs\bigqmt.log" -Wait -Tail 50

# 只看错误
Get-Content "D:\...\python\logs\bigqmt.log" | Select-String "ERROR|WARN"

配置

环境变量 默认 说明
BIGQMT_LOG_ENABLED 1 0 关闭文件日志
BIGQMT_LOG_TO_STDOUT 1 0 不输出到 QMT 面板
BIGQMT_LOG_RETENTION_DAYS 7 日志保留天数

排错首选看日志文件:QMT 面板内容重启/清空后丢失,日志文件保留 7 天,包含启动诊断([bigqmt_diag])、崩溃原因、端口冲突等。


安全默认值

  • rpc_allow_order_methods 默认 False:远程 order_stock / cancel_order 被拒绝。确认接入方、账号、风控后再显式开启。
  • 回测桥接永久 live_ready=false,协议中没有真实账户和实盘下单方法。
  • 配置文件含资金账号和密码,bigqmt_signal_trader_local_config.py / bigqmt_signal_trader_client_config.py 已在 .gitignore不要提交
  • 请求负载经过 base64 + 数字混淆编码(encode_rpc_request_payload),避免 QMT 的 Redis 客户端拦截含股票代码的明文。

AI 助手 Skillqmt-trader(大模型直接操作 QMT

仓库内置一个 Agent Skill——qmt-trader/,让支持 SKILL.md 约定的 AI 编程助手(Claude Code / ZCode / Cursor / Codex 等)直接用命令行驱动 QMT 的全部交易与行情能力,无需每次现场写 Python 调用代码。人也可以脱离 AI 手动执行其中的 CLI 脚本。

目录结构

qmt-trader/
├── SKILL.md                        skill 说明书(触发条件 + 命令速查 + 典型工作流 + 安全须知)
├── scripts/qmt.py                  统一 CLI 入口(46 个子命令 + 通用 rpc 兜底,约 1000 行)
└── references/api_reference.md     完整 API 参考(参数/返回值/常量/已知陷阱)

工作原理

  • AI 助手匹配到 SKILL.md 里的 description("查行情 / 查持仓 / 下单 / 龙虎榜 / 北向资金…时触发")后自动加载本 skill;
  • 之后助手调用 python qmt-trader/scripts/qmt.py <子命令> 执行确定性命令,不再临时生成 RPC 调用代码,避免参数写错;
  • 所有命令默认输出 JSONok / data / ts 三字段,便于模型解析),加 --table 切换人类可读表格;出错时返回 ok: false + error / detail / code,退出码 1
  • qmt.py 自动把仓库 src/ 加入 sys.path(开发模式免 pip install),并自动发现 QMT 的 python 目录读取客户端配置。

启用方式

方式 A:安装到 AI 助手的 skills 目录(推荐,全局生效):

# Claude Code
cp -r qmt-trader ~/.claude/skills/qmt-trader
# ZCode / 其他遵循 agents skills 约定的助手
cp -r qmt-trader ~/.agents/skills/qmt-trader

安装后正常提需求即可,例如"帮我看下工商银行最近的走势""我账户现在什么持仓",助手会自动触发。

方式 B:不安装,对话里显式指定

阅读 qmt-trader/SKILL.md,之后用里面的 qmt.py 命令帮我查行情 / 持仓 / 下单。

方式 C:纯手动(不经过 AI,人直接当 CLI 用):

python qmt-trader/scripts/qmt.py ping
python qmt-trader/scripts/qmt.py snapshot --table

前置条件

与「快速开始」的客户端一致:

  1. QMT 端 RPC 服务已启动(BIGQMT_REDIS_DRYRUN.py 运行中,输出面板/日志看到启动诊断 OK);
  2. 客户端配置就绪——环境变量(BIGQMT_ACCOUNT_ID / BIGQMT_REDIS_HOST / BIGQMT_REDIS_PORT / BIGQMT_REDIS_DB / BIGQMT_REDIS_PASSWORD)或配置文件;
  3. ping 确认连通:redis 约 13ms / zmq 约 0.7ms 为正常,超时说明 transport 或配置不匹配。

一分钟上手

# 0. 连通性检测(含延迟测量)
python qmt-trader/scripts/qmt.py ping

# 1. 账户全景:资产 + 持仓 + 委托 + 成交(一次往返)
python qmt-trader/scripts/qmt.py snapshot

# 2. 实时五档盘口(含涨跌幅)
python qmt-trader/scripts/qmt.py tick 600000.SH

# 3. 前复权日 K 60 根(含 MA5/20/60 统计)
python qmt-trader/scripts/qmt.py kline 600000.SH --period 1d --count 60 --dividend front

# 4. 干跑下单(只打印不提交,确认参数)
python qmt-trader/scripts/qmt.py buy 600000.SH 100 --price 7.50 --dry-run

命令概览

分类 命令
连通/全景 ping / snapshot
账户 account(资产)/ positions(持仓含浮动盈亏)/ orders(委托含语义化状态)/ trades(成交)
行情 tick / kline / instrument / sector / trading-dates / north(北向)/ longhubang(龙虎榜)/ financial(财务)/ download(历史数据下载)/ quote-subscribe(全推订阅)
扩展查询(25 个快捷命令) holiday / stock-name / instrument-type / divid-factors / market-times / trading-calendar / option-list / bsm-price / bsm-iv / hkt-stats / hkt-details / hkt-rate / top10-holder / holder-num / ipo / ipo-limit / credit-assure / credit-short / credit-debt / his-st / index-weight / industry / sector-info / local-data / timetag2dt / dt2timetag
交易 buy / sell / cancel(均支持 --dry-runbuy/sell 支持 --latest / --strategy / --remark
通用兜底 rpc <method> [json] — 调用白名单内任意方法(如 rpc get_l2_quote '{"stock_code":"600000.SH"}'),未列出的方法都能这样调

安全设计

  • 下单三命令(buy / sell / cancel)受服务端白名单控制,rpc_allow_order_methods 默认 False,未显式开启时返回 ORDER_DISABLED
  • 下单前先用 tick 看价 + --dry-run 确认参数;
  • ORDER_TIMEOUT不要直接重试,先 orders 查询确认委托是否已进系统,避免重复下单;
  • 下单的 --strategy 与查询的 --strategy 需一致;查全部委托用 orders --strategy ""(空 = 不过滤)。

完整命令表、四个典型工作流(行情分析 / 持仓监控 / 下单交易 / 批量分析)和 API 参数细节见 qmt-trader/SKILL.mdqmt-trader/references/api_reference.md


相关文档


为什么不直接连大 QMT

官方 xtquant.xttrader.XtQuantTrader 依赖客户端侧 XtQuantServer 通道。当前国金大 QMT 环境中直接连 connect() 返回 -1交易能力因此必须放在大 QMT 内部策略进程里,外部通过 RPC 驱动。

但只读行情不必走 RPC。 58600 是 FormulaServer,它同时就是行情/参考数据服务——QMT 自带 Python 里的 qmt_api 包(bin.x64/Lib/site-packages/qmt_api)正是它的客户端。本仓库已接入这条直连快速路径,见上文「FormulaServer 直连快速路径」。

如果后续券商开通 XtQuantServer 权限且 connect()==0,可再加交易直连模式。