chore: init qmt_bridge repo (HTTP+WS bridge, MCP endpoint, docs, references)
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
# xtquant_big_convert 实现原理调研(基于协议线索 + 官方API还原)
|
||||
|
||||
调研日期:2026-08-19
|
||||
仓库:https://github.com/litaolemo/xtquant_big_convert
|
||||
⚠️ 注意:本机出网受限(GitHub/镜像/Bing/Baidu 全部不通),无法抓取真实源码。
|
||||
本文基于方案文档中的协议线索 + 迅投官方API文档(已核实)还原实现原理。
|
||||
协议线索:请求 RPUSH bigqmt:rpc:queue:{账号} / 响应 BLPOP bigqmt:rpc:respq:{账号}:{reqId}
|
||||
|
||||
---
|
||||
|
||||
## 一、它解决什么问题
|
||||
|
||||
**目标**:让外部 Python 程序(没有 MiniQMT/XtQuantServer 权限)直接调用"大QMT"的交易和行情能力。
|
||||
|
||||
**背景约束**(官方文档核实):
|
||||
- xtquant 外部库的 XtQuantTrader / xtdata **本质是和 MiniQMT 建立连接**(官方原文)
|
||||
- 大QMT(完整交易端)不提供 MiniQMT 的 userdata_mini 连接通道 → 外部 xtquant 直连大QMT 失败
|
||||
- 但大QMT 的策略编辑器(内置 Python 3.6)能跑策略,能调 passorder / get_trade_detail_data
|
||||
|
||||
**解法**:把"桥"跑在大QMT 进程内(策略里),外部程序通过 Redis 发 RPC 请求,桥在 QMT 策略线程里执行并回写结果。
|
||||
|
||||
---
|
||||
|
||||
## 二、核心架构
|
||||
|
||||
```
|
||||
┌─ 外部Python进程(无QMT权限) ─┐ ┌─ Redis ─┐ ┌─ 大QMT进程内(策略) ─┐
|
||||
│ 你的量化脚本 / sfgrid(TS) │ │ │ │ qmt_big_convert.py │
|
||||
│ │ ①RPUSH │ │ ②BLPOP │ │
|
||||
│ redis_client.rpush( ├───────►│ queue ├───────►│ bridge_loop(): │
|
||||
│ 'bigqmt:rpc:queue:{acct}',│ │ {acct} │ │ 解析请求 │
|
||||
│ json.dumps(req)) │ │ │ │ passorder(...) │
|
||||
│ │ │ │ │ get_trade_detail │
|
||||
│ ⑤BLPOP(respq) ←─────────────┼────────┤ respq │◄───────┤ ④RPUSH 结果 │
|
||||
│ reqId → 结果 │ │ {acct}: │ │ │
|
||||
└──────────────────────────────┘ │ {reqId} │ └──────────────────────┘
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
**关键**:Redis 是"队列桥接"的中枢,不是 HTTP server。这正好绕开官方"QMT 内置 Python 不能多线程"的约束——QMT 侧不需要开监听线程,用一个循环/定时器消费队列即可。
|
||||
|
||||
---
|
||||
|
||||
## 三、Redis 协议设计(从 key 命名还原)
|
||||
|
||||
### 3.1 请求通道
|
||||
```
|
||||
Key: bigqmt:rpc:queue:{accountID}
|
||||
Type: LIST
|
||||
操作: 外部进程 RPUSH, QMT桥 BLPOP
|
||||
Value: JSON 请求体
|
||||
```
|
||||
|
||||
### 3.2 响应通道
|
||||
```
|
||||
Key: bigqmt:rpc:respq:{accountID}:{reqId}
|
||||
Type: LIST
|
||||
操作: QMT桥 RPUSH, 外部进程 BLPOP(带超时)
|
||||
Value: JSON 响应体
|
||||
```
|
||||
|
||||
### 3.3 推断的请求/响应结构(基于常见 RPC 桥设计 + 协议命名)
|
||||
```jsonc
|
||||
// 请求(外部 → QMT)
|
||||
{
|
||||
"reqId": "uuid或自增id", // 用于关联响应队列
|
||||
"method": "order | cancel | query_position | query_asset | kline | ...",
|
||||
"params": {
|
||||
// order: {"code":"000001.SZ","opType":23,"volume":100,"priceType":5,"price":-1,...}
|
||||
// kline: {"code":"600000.SH","period":"1d","count":100}
|
||||
}
|
||||
}
|
||||
|
||||
// 响应(QMT → 外部)
|
||||
{
|
||||
"reqId": "同上",
|
||||
"code": 0, // 0成功, 非0错误
|
||||
"data": {...} | [...], // 查询结果 / 下单结果
|
||||
"msg": "error message"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、QMT 侧桥程序的关键实现
|
||||
|
||||
### 4.1 入口:策略生命周期
|
||||
```python
|
||||
#coding:gbk
|
||||
import json, redis # 或自实现极简RESP客户端
|
||||
|
||||
def init(ContextInfo):
|
||||
ContextInfo.run_time("bridge", "200nMilliSecond", "2019-01-01 00:00:00")
|
||||
# 或:
|
||||
# 起一个 while 循环线程(若实测线程可用)
|
||||
|
||||
def bridge(ContextInfo):
|
||||
# 定时/循环:BLPOP 队列
|
||||
req = redis_client.blpop('bigqmt:rpc:queue:%s' % ACCOUNT, timeout=0.1)
|
||||
if req:
|
||||
result = dispatch(req) # 在策略上下文执行
|
||||
redis_client.rpush('bigqmt:rpc:respq:%s:%s' % (ACCOUNT, req['reqId']),
|
||||
json.dumps(result))
|
||||
|
||||
def dispatch(req):
|
||||
method = req['method']
|
||||
if method == 'order':
|
||||
return passorder(req['params']) # 必须传 ContextInfo
|
||||
elif method == 'cancel':
|
||||
return cancel(...)
|
||||
elif method == 'query':
|
||||
return get_trade_detail_data(...)
|
||||
elif method == 'kline':
|
||||
return ContextInfo.get_market_data_ex(...)
|
||||
```
|
||||
|
||||
### 4.2 必须处理的点(官方文档核实)
|
||||
1. **passorder 无返回** → 下单结果要 order_callback/deal_callback 或轮询委托回写
|
||||
2. **回调仅实盘模式 + 需 set_account** → init 里 `ContextInfo.set_account(account)`
|
||||
3. **状态不能挂 ContextInfo**(会回滚) → 用模块级全局 class
|
||||
4. **行情函数**:内置 Python 用 `ContextInfo.get_market_data_ex`(不能直接在 init 跑)
|
||||
5. **定时器用 run_time**(官方无 adjust)
|
||||
|
||||
---
|
||||
|
||||
## 五、为什么它和你的 HTTP 桥方案是"同构"的
|
||||
|
||||
| 维度 | xtquant_big_convert | 你的 qmt_http_bridge 方案 |
|
||||
|------|--------------------|--------------------------|
|
||||
| 桥的位置 | 大QMT 策略内 | 大QMT 策略内 |
|
||||
| 外部入口 | Redis LIST(RPUSH/BLPOP) | HTTP server |
|
||||
| 队列桥接 | Redis 队列 | 内存 ORDER_QUEUE |
|
||||
| 结果回写 | Redis respq + reqId | ORDER_RESULTS[rid] |
|
||||
| QMT 侧执行 | 策略线程(定时消费) | adjust() 定时消费 |
|
||||
| 解决的问题 | 外部无 xtquant 权限 | 外部脚本零改动复用8610 |
|
||||
|
||||
**本质相同**:都是"大QMT 进程内桥 + 队列 + 策略线程执行 + 结果回写"。
|
||||
|
||||
---
|
||||
|
||||
## 六、Redis vs HTTP 的取舍(你的方案该参考什么)
|
||||
|
||||
### xtquant_big_convert 用 Redis 的动机(推断)
|
||||
- 官方"不能多线程"→ 无法开 HTTP server 线程
|
||||
- Redis BLPOP 天然适配单线程轮询:一个 run_time 定时器就能消费
|
||||
- 外部 redis-py 客户端成熟,不碰 QMT
|
||||
|
||||
### 但它引入的问题
|
||||
1. **需要 Redis 服务** → 多一个运维组件(虽然轻量)
|
||||
2. **QMT 内置 Python 3.6 是否有 redis 库?** → 大概率没有,要自己实现极简 RESP 客户端(纯 socket,~100行)
|
||||
3. **BLPOP 阻塞语义** → 若桥循环里阻塞,会卡住策略主线程,需要 timeout 参数
|
||||
|
||||
### 对你 HTTP 桥方案的启示
|
||||
- 如果实测 QMT 里**线程可用** → HTTP 方案可行,但必须加请求超时保护(慢客户端卡死策略)
|
||||
- 如果**线程不可用** → 你的 HTTP 方案需要改成"单线程事件循环",或者借鉴 Redis 思路:QMT 侧只做定时轮询,HTTP 监听放外部进程(方向B)
|
||||
|
||||
---
|
||||
|
||||
## 七、待验证项(拿到真实源码后核对)
|
||||
|
||||
- [ ] 桥是否用 redis-py 还是自写 RESP 客户端
|
||||
- [ ] 请求/响应 JSON 的确切字段名
|
||||
- [ ] 下单结果如何回写(回调 or 轮询)
|
||||
- [ ] 是否处理了 order_callback / deal_callback
|
||||
- [ ] 定时器用的 run_time 还是线程
|
||||
- [ ] 是否支持行情(kline)还是只做交易
|
||||
- [ ] 是否内置了 token/鉴权
|
||||
@@ -0,0 +1,190 @@
|
||||
# QMT 官方接口核实报告(迅投知识库 dict.thinktrader.net)
|
||||
|
||||
核实日期:2026-08-19
|
||||
资料来源:迅投官方知识库 http://dict.thinktrader.net(所有页面已存为 docs_ref/*.txt 供查阅)
|
||||
|
||||
---
|
||||
|
||||
## 一、结论速览
|
||||
|
||||
| # | 方案假设 | 官方文档核实结果 | 影响 |
|
||||
|---|---------|----------------|------|
|
||||
| 1 | `adjust()` 是 QMT 定时回调 | ❌ **不存在**。官方定时回调是 `ContextInfo.run_time(funcName, period, startTime)`(支持 `500nMilliSecond`)或新版 `ContextInfo.schedule_run` | 骨架代码要改 |
|
||||
| 2 | HTTP 线程(daemon)+ 队列桥接 | ❌ **官方明确:内置 Python 无法使用多线程和多进程,所有策略在同一线程执行** | 方案核心架构要重新设计 |
|
||||
| 3 | `xtdata.get_market_data_ex` 任意线程直调 | ⚠️ **xtdata 模块主动获取接口是 `get_market_data`,不是 `get_market_data_ex`**(后者是 ContextInfo 方法)。且 xtdata 文档写明"本质是和 MiniQmt 建立连接" | 函数名要改;能否连大 QMT 需实测 |
|
||||
| 4 | `passorder` 下单 → 结果回写 | ✅ 确认 `passorder(opType, orderType, accountid, orderCode, prType, price, volume, strategyName, quickTrade, userOrderId, ContextInfo)`,**返回无**,真实状态靠 `order_callback`/`deal_callback` 主推(仅实盘模式生效,需先 `set_account`) | 你的判断正确,补充细节 |
|
||||
| 5 | 下单须在策略线程执行 | ✅ 正确,必须。所有交易函数依赖 ContextInfo 和策略上下文 | 成立 |
|
||||
| 6 | Python 3.6.8 | ✅ 官方确认:"内置了 3.6 版本的 python 运行环境" | 成立 |
|
||||
| 7 | `# coding:gbk` | ✅ 官方明确要求 | 成立 |
|
||||
| 8 | `cancel(orderId, accountId, ContextInfo)` | ⚠️ 实际签名是 `cancel(orderId, accountId, accountType, ContextInfo)`,**有 accountType 参数** | 修正 |
|
||||
|
||||
---
|
||||
|
||||
## 二、逐项核实详情
|
||||
|
||||
### 2.1 内置 Python 运行环境(快速开始页)
|
||||
|
||||
> "QMT 极速策略交易系统...内置了 **3.6 版本**的 python 运行环境,提供行情数据与交易下单两大核心功能。"
|
||||
|
||||
- 确认方案 4.3 的"Python 3.6.8"判断正确(官方口径 3.6)。
|
||||
- 三种运行机制(官方明确):
|
||||
1. 逐 K 线驱动 `handlebar`
|
||||
2. 事件驱动 `subscribe`(订阅推送)
|
||||
3. **定时任务 `run_time`(固定间隔触发)**
|
||||
|
||||
### 2.2 ⚠️ 关于线程(使用须知页)—— 最关键发现
|
||||
|
||||
> "**QMT中,python 无法使用多线程和多进程,而且所有策略都在同一线程中执行**,所以策略中应该尽量避免阻塞类的写法,否则会影响其他策略的执行。"
|
||||
|
||||
**这是对整个方案的颠覆性约束**:
|
||||
- 方案假设的"init() 里启动 HTTP 服务线程(daemon)"**很可能直接失败**——多线程不可用
|
||||
- 队列桥接(HTTP线程入队 → adjust 出队)的双线程前提不成立
|
||||
- 需要找到"单线程事件循环"形态的替代架构(见下文第三节)
|
||||
|
||||
### 2.3 系统函数(系统函数页)—— 没有 adjust
|
||||
|
||||
- 官方系统函数列表:`ContextInfo`对象、`init`、`after_init`、`handlebar`、`ContextInfo.schedule_run`、`ContextInfo.cancel_schedule_run`、`ContextInfo.run_time`、`stop`、`ContextInfo.is_last_bar`、`ContextInfo.is_new_bar` 等。
|
||||
- **全文没有 `adjust` 函数**。
|
||||
- 替代:定时回调用
|
||||
```python
|
||||
# 500ms 定时器
|
||||
ContextInfo.run_time("f", "500nMilliSecond", "2019-10-14 13:20:00")
|
||||
# 或新版
|
||||
ContextInfo.schedule_run(func, time_point, repeat_times, interval, name)
|
||||
```
|
||||
|
||||
### 2.4 交易下单函数(交易函数页)
|
||||
|
||||
**passorder 完整签名**:
|
||||
```python
|
||||
passorder(opType, orderType, accountid, orderCode, prType, price, volume,
|
||||
strategyName, quickTrade, userOrderId, ContextInfo)
|
||||
```
|
||||
- **返回:无**(不是布尔/错误码!下单是否成功只能靠回调或查询委托)
|
||||
- opType:23=股票买入, 24=股票卖出(期货另有开平仓)
|
||||
- orderType:1101=按股数(深沪通用), 1102=沪市按股, 1202=按金额(对账号组)
|
||||
- prType:5=最新价, 11=限价, 14=模型价(跟价), 12=市价
|
||||
- quickTrade:0=逐K线生效(默认), 1=最后一根K线立即, **2=调用即下单(不判bar状态)**
|
||||
- userOrderId:用户自设委托ID,会进入 order/deal 对象的 **m_strRemark** 字段
|
||||
- **编译器界面执行的下单函数不会产生实际委托**(必须策略交易界面运行)
|
||||
- 下单真实结果靠 `get_trade_detail_data` 查询或回调主推
|
||||
|
||||
**cancel 实际签名**:
|
||||
```python
|
||||
cancel(orderId, accountId, accountType, ContextInfo)
|
||||
```
|
||||
- accountType: 'FUTURE'/'STOCK'/'CREDIT'/'HUGANGTONG'/'SHENGANGTONG'/'STOCK_OPTION'
|
||||
- 返回 bool(是否发出撤单信号)
|
||||
- 注意:撤单参数是 **orderId(委托号, m_strOrderSysID)**,不是 userOrderId
|
||||
|
||||
**其他下单**:algo_passorder(拆单)、smart_algo_passorder(VWAP等,需权限)、cancel_task/pause_task/resume_task(任务级)、get_basket/set_basket(篮子)。
|
||||
|
||||
### 2.5 交易查询函数(交易函数页)
|
||||
|
||||
```python
|
||||
get_trade_detail_data(accountID, strAccountType, strDatatype[, strategyName])
|
||||
```
|
||||
- strDatatype: 'ACCOUNT'/'POSITION'/'POSITION_STATISTICS'/'ORDER'/'DEAL'/'TASK'
|
||||
- 返回 list 对象,字段以 m_ 开头,如:
|
||||
- 账号: `m_dBalance`(总资产) `m_dAssureAsset`(净资产) `m_dAvailable`(可用) `m_dInstrumentValue`(市值) `m_dPositionProfit`(盈亏)
|
||||
- 持仓: `m_strInstrumentID` `m_nVolume`(持仓量) `m_nCanUseVolume`(可用) `m_dOpenPrice`(成本) `m_dInstrumentValue` `m_dPositionProfit`
|
||||
- 委托: `m_strOrderSysID`(委托号) `m_nOrderStatus`(状态) `m_strRemark`(userOrderId) `m_nVolumeTraded`
|
||||
- 成交: `m_strOrderSysID` `m_dPrice` `m_nVolume` `m_dTradeAmount`
|
||||
|
||||
**get_value_by_order_id(orderId, accountID, accountType)** 按委托号取委托/成交信息。
|
||||
**get_last_order_id(accountID, accountType, 'order'/'deal')** 取最新委托号。
|
||||
|
||||
### 2.6 成交回报主推回调(回调函数页)
|
||||
|
||||
| 回调 | 签名 | 说明 |
|
||||
|------|------|------|
|
||||
| account_callback | (ContextInfo, accountInfo) | 资金账号状态变化 |
|
||||
| task_callback | (ContextInfo, taskInfo) | 任务状态变化 |
|
||||
| **order_callback** | (ContextInfo, orderInfo) | **委托状态变化主推** |
|
||||
| **deal_callback** | (ContextInfo, dealInfo) | **成交状态变化主推** |
|
||||
| position_callback | (ContextInfo, positionInfo) | 持仓状态变化 |
|
||||
| orderError_callback | (ContextInfo, orderArgs, errMsg) | 异常下单 |
|
||||
|
||||
**重要提示(官方)**:
|
||||
- 回调**仅在实盘运行模式下生效**
|
||||
- 需要先在 init 里调用 **`ContextInfo.set_account(account)`**
|
||||
- order 对象的 `m_strRemark` = userOrderId, `m_strOrderSysID` = 委托号
|
||||
|
||||
### 2.7 行情数据(行情函数页 + XtQuant 文档)
|
||||
|
||||
**内置 Python(策略内)**:
|
||||
```python
|
||||
ContextInfo.get_market_data_ex(fields=[], stock_code=[], period='1d',
|
||||
start_time='', end_time='', count=-1, dividend_type='follow',
|
||||
fill_data=True, subscribe=True)
|
||||
```
|
||||
- 返回 {stock_code: pd.DataFrame},index 为 time,columns 为 fields(open/high/low/close/volume/amount...)
|
||||
- 注意:该函数**不建议在 init 中运行**(init 中只能取本地数据)
|
||||
- 周期: 'tick' '1m' '5m' '15m' '30m' '1h' '1d' '1w' '1mon' '1q' '1hy' '1y'
|
||||
- 其他: `ContextInfo.get_full_tick`(全推) `ContextInfo.subscribe_quote`(订阅) `ContextInfo.get_history_data`(不推荐) `ContextInfo.get_local_data`(不推荐)
|
||||
|
||||
**XtQuant 原生(外部 Python)**:
|
||||
```python
|
||||
xtdata.get_market_data(field_list=[], stock_list=[], period='1d',
|
||||
start_time='', end_time='', count=-1, dividend_type='none', fill_data=True)
|
||||
```
|
||||
- **注意:xtdata 的主动获取接口是 `get_market_data`(不是 `get_market_data_ex`!)** `get_market_data_ex` 是内置 Python 的 ContextInfo 方法
|
||||
- xtdata 返回:period 为 K 线时 {field: pd.DataFrame}(index 为 stock_list, columns 为 time_list)——与内置 Python 的返回结构**不同**(内置是 {stock: df},xtdata 是 {field: df})!
|
||||
- **运行逻辑(官方原文)**: "xtdata提供和MiniQmt的交互接口,本质是**和MiniQmt建立连接**,由MiniQmt处理行情数据请求"
|
||||
|
||||
### 2.8 XtQuant 交易模块(xttrader 文档)
|
||||
|
||||
- 外部 Python 可用 `XtQuantTrader(path, session_id)` 连接,**文档明确绑定 MiniQMT**(`userdata_mini` 路径)
|
||||
- 完整 API:order_stock(同步)/order_stock_async(异步)、cancel_order_stock、query_stock_asset/orders/trades/positions、回调 on_stock_order/on_stock_trade/on_order_error 等
|
||||
- **这印证了方案判断:外部 xtquant 依赖 miniQMT,大 QMT 不适用,必须走桥策略**
|
||||
|
||||
### 2.9 ContextInfo 使用注意(使用须知页)
|
||||
|
||||
> "由于底层机制的限制,ContextInfo 中存储的变量值将会回滚...请避免在其中存储任何变量。"
|
||||
|
||||
- 官方推荐用 `class G(): pass; g = G()` 全局对象存状态
|
||||
- 桥策略的队列/结果字典等必须用模块级全局变量,不能挂 ContextInfo
|
||||
|
||||
---
|
||||
|
||||
## 三、对方案的修正建议(基于官方文档)
|
||||
|
||||
### 3.1 核心架构问题:单线程约束
|
||||
|
||||
官方明确"python 无法使用多线程"。这意味着方案的核心机制(HTTP 线程收请求 + 队列 + adjust 线程执行)需要重新设计。可选方向:
|
||||
|
||||
**方向 A:单线程异步 HTTP(推荐验证)**
|
||||
- 用 `asyncore`/`selectors` 实现非阻塞 HTTP,或
|
||||
- 用 `BaseHTTPRequestHandler` 但**不开线程**——利用 run_time 定时器轮询处理 socket
|
||||
- 但 HTTP 长连接/慢客户端会阻塞整个策略,风险仍在
|
||||
|
||||
**方向 B:桥只做"指令中继",HTTP 放外部(推荐)**
|
||||
- 把 HTTP 服务放在**外部独立进程**(Linux 侧或 Windows 侧 Python 3.14),不占用 QMT 策略线程
|
||||
- QMT 策略内只保留一个轻量"指令执行器":run_time 定时轮询一个本地指令源(文件/命名管道/端口)
|
||||
- 外部 HTTP 桥收到 /order → 写指令文件/管道 → QMT 定时器取指令 → passorder → 回写结果文件
|
||||
- 这样 QMT 内零线程、零阻塞,完全符合官方约束;HTTP 的并发/超时/安全都在外部处理
|
||||
|
||||
**方向 C:验证"线程是否真的不可用"**
|
||||
- 官方文档说不可用,但社区有说法"能起线程但会阻塞主线程/不稳定"
|
||||
- 建议在国金 GJQMT 上做个 10 分钟实测:init 里 `threading.Thread(target=...).start()` 看是否报错、是否影响 handlebar
|
||||
- **如果实测线程能跑**,原方案(方向A变体)可保留,但必须加超时保护,避免慢请求卡死策略
|
||||
|
||||
### 3.2 函数修正清单
|
||||
|
||||
1. ~~adjust()~~ → `ContextInfo.run_time("on_bridge_timer", "500nMilliSecond", "...")`
|
||||
2. ~~xtdata.get_market_data_ex~~ → 内置 Python 用 `ContextInfo.get_market_data_ex`;若用 xtdata 模块则 `xtdata.get_market_data`
|
||||
3. ~~cancel(orderId, accountId, ContextInfo)~~ → `cancel(orderId, accountId, 'STOCK', ContextInfo)`
|
||||
4. 下单状态:passorder **无返回** → 必须 `order_callback` + `deal_callback`(实盘模式 + set_account)或轮询 `get_trade_detail_data`
|
||||
5. 状态存储:不能挂 ContextInfo → 用模块级全局 class 实例
|
||||
|
||||
### 3.3 必须实测的三个点(写码前)
|
||||
|
||||
1. **线程可用性**:init 里起 daemon 线程是否真的失败(决定方向A还是B)
|
||||
2. **set_account**:实盘模式回调是否需要、如何配置账号
|
||||
3. **xtdata 在大 QMT 内能否 import 并取数**:若大 QMT 无 miniQMT 的 userdata_mini 连接,xtdata 可能连不上——则行情一律走 `ContextInfo.get_market_data_ex`
|
||||
|
||||
### 3.4 仍成立的设计
|
||||
|
||||
- 队列桥接思路(若线程可用)、复权/周期参数、GBK 编码、8610 端口复用、脚本零改动目标
|
||||
- passorder 必须在策略上下文执行(官方:下单函数需要 ContextInfo,且编译器环境不下单)
|
||||
- 实盘模式登录才能收完整回报(官方:回调仅实盘生效)
|
||||
Reference in New Issue
Block a user