feat(qmt): 添加策略权重配置功能

- 在 qmt_engine.py 中增加权重计算逻辑
- 下单金额公式改为: target_amt = total_equity * weight / total_weighted_slots
- 更新 qmt_config.md 添加 weight 字段配置说明
- 保持向后兼容,不配置 weight 时默认为 1
This commit is contained in:
2026-01-27 01:06:34 +08:00
parent 4607555eaf
commit ec41783155
2 changed files with 119 additions and 6 deletions

379
qmt/qmt_config.md Normal file
View File

@@ -0,0 +1,379 @@
# QMT 模块配置说明
本文档详细介绍 NewStock 量化交易系统中 QMT 模块的配置文件格式和所有配置项的含义。
## 配置文件概述
QMT 模块使用 JSON 格式的配置文件来管理 MiniQMT 终端连接、多个交易策略的执行配置。配置文件通常命名为 `config.json`,位于项目根目录或 `qmt/` 目录下。
## 完整配置示例
```json
{
"redis": {
"host": "localhost",
"port": 123,
"password": "123",
"db": 0
},
"qmt_terminals": [
{
"qmt_id": "gj",
"alias": "国金证券",
"path": "D:\\QMT\\国金证券QMT交易端\\userdata_mini",
"account_id": "123",
"account_type": "STOCK"
}
],
"strategies": {
"ST_Strategy": {
"qmt_id": "gj",
"total_slots": 5,
"execution": {
"buy_drift_pct": 0.005,
"sell_drift_fixed": -0.01,
"max_adjust_limit": 0.05
}
},
"XSZ_Strategy": {
"qmt_id": "gj",
"total_slots": 5,
"execution": {
"buy_drift_pct": 0.005,
"sell_drift_fixed": -0.01,
"max_adjust_limit": 0.05
}
}
}
}
```
## 配置项详解
### 1. Redis 配置redis
Redis 用于存储交易状态、缓存策略信号和实时行情数据。
| 配置项 | 类型 | 必选 | 默认值 | 说明 |
|--------|------|------|--------|------|
| `host` | 字符串 | 是 | - | Redis 服务器地址,支持 IP 地址或域名 |
| `port` | 整数 | 是 | - | Redis 服务端口,默认为 6379 |
| `password` | 字符串 | 否 | `null` | Redis 访问密码,如无密码则设为空字符串或 `null` |
| `db` | 整数 | 否 | 0 | Redis 数据库编号,范围 0-15 |
#### 详细说明
- **`host`**:配置 Redis 服务器的网络地址。本地开发环境通常使用 `localhost``127.0.0.1`;生产环境应使用服务器的实际 IP 地址或域名。
- **`port`**Redis 服务监听端口,标准端口为 6379。如果您的 Redis 使用非标准端口,请在此处修改。
- **`password`**Redis 认证密码。如果 Redis 服务器未启用密码认证,此项可设为空字符串 `""``null`。生产环境建议启用密码认证以保证安全性。
- **`db`**Redis 数据库编号。不同的应用可以使用不同的数据库来隔离数据,避免键名冲突。
#### 完整示例
```json
"redis": {
"host": "192.168.1.100",
"port": 6379,
"password": "your_password_here",
"db": 0
}
```
### 2. QMT 终端配置qmt_terminals
`qmt_terminals` 是一个数组,用于配置一个或多个 MiniQMT 交易终端。每个终端代表一个券商账户。
| 配置项 | 类型 | 必选 | 默认值 | 说明 |
|--------|------|------|--------|------|
| `qmt_id` | 字符串 | 是 | - | 终端唯一标识符,用于在策略中引用此终端 |
| `alias` | 字符串 | 否 | `qmt_id` | 终端别名,用于日志和界面显示 |
| `path` | 字符串 | 是 | - | MiniQMT 终端的 userdata_mini 目录路径 |
| `account_id` | 字符串 | 是 | - | 交易账户 ID通常为券商账号 |
| `account_type` | 字符串 | 是 | - | 账户类型,详见下方的可选值 |
#### account_type 可选值
| 账户类型 | 说明 |
|----------|------|
| `STOCK` | 股票账户(默认) |
| `FUTURES` | 期货账户 |
| `OPTIONS` | 期权账户 |
| `两融` | 融资融券账户 |
| `港股通` | 港股通账户 |
#### 详细说明
- **`qmt_id`**:终端的唯一标识符,建议使用简短的英文标识,如 `gj`(国金证券)、`yh`(银河证券)。此 ID 用于在策略配置中关联到具体的终端。
- **`alias`**:终端的友好名称,会在日志、仪表盘等界面中显示。建议使用中文券商名称,便于识别。
- **`path`**MiniQMT 终端的 `userdata_mini` 目录的绝对路径。此目录包含终端的配置文件和交易数据。注意:路径分隔符在 JSON 中需要使用双反斜杠 `\\` 或使用正斜杠 `/`
- **`account_id`**:您的券商交易账号。请确保此账号与 MiniQMT 终端登录的账号一致。
- **`account_type`**:账户类型决定了可以交易的品种范围。请根据实际账户类型填写。
#### 多终端配置示例
```json
"qmt_terminals": [
{
"qmt_id": "gj",
"alias": "国金证券",
"path": "D:\\QMT\\国金证券QMT交易端\\userdata_mini",
"account_id": "12345678",
"account_type": "STOCK"
},
{
"qmt_id": "yh",
"alias": "银河证券",
"path": "D:\\QMT\\银河证券QMT交易端\\userdata_mini",
"account_id": "87654321",
"account_type": "两融"
}
]
```
### 3. 策略配置strategies
`strategies` 是一个对象,用于定义一个或多个交易策略。每个策略有自己的执行参数和关联的 QMT 终端。
#### 策略顶级配置
| 配置项 | 类型 | 必选 | 默认值 | 说明 |
|--------|------|------|--------|------|
| `qmt_id` | 字符串 | 是 | - | 策略绑定的 QMT 终端 ID必须在 `qmt_terminals` 中定义 |
| `total_slots` | 整数 | 是 | - | 策略可用的交易仓位总数 |
| `weight` | 整数 | 否 | 1 | 策略权重,用于按权重分配下单金额 |
| `execution` | 对象 | 是 | - | 策略执行参数,详见下方说明 |
#### execution 执行参数配置
| 配置项 | 类型 | 必选 | 默认值 | 说明 |
|--------|------|------|--------|------|
| `buy_drift_pct` | 浮点数 | 是 | - | 买入时价格漂移百分比,用于滑点控制 |
| `sell_drift_fixed` | 浮点数 | 是 | - | 卖出时固定漂移值,用于滑点控制 |
| `max_adjust_limit` | 浮点数 | 是 | - | 最大调仓限制,范围 0-1 表示仓位调整比例上限 |
#### 详细说明
**策略顶级配置**
- **`qmt_id`**:策略绑定的 QMT 终端标识符。一个策略只能绑定到一个终端,但多个策略可以绑定到同一个终端。
- **`total_slots`**:策略可用的总仓位数量。例如设为 5 表示策略最多同时持有 5 只股票。此参数用于仓位管理和风险控制。
- **`weight`**:策略权重,用于按权重分配下单金额。当不配置时,默认为 1表示等权分配。可用于实现策略间的资金分配比例控制。
- **`execution`**:包含策略的具体执行参数,这些参数控制订单的提交方式。
**执行参数详解**
- **`buy_drift_pct`**:买入时允许的价格漂移百分比。例如设置为 `0.005`0.5%)表示买入时允许以高于基准价 0.5% 的价格成交,用于应对行情快速上涨的情况。计算公式为:买入价 = 基准价 × (1 + buy_drift_pct)。
- **`sell_drift_fixed`**:卖出时的固定漂移值。例如设置为 `-0.01`-1%)表示卖出时允许以低于基准价 1% 的价格成交,用于应对行情快速下跌的情况。计算公式为:卖出价 = 基准价 × (1 + sell_drift_fixed)。
- **`max_adjust_limit`**:单次调仓的最大比例限制。例如设置为 `0.05`5%)表示每次调仓不超过总仓位的 5%。此参数用于控制换手率和交易成本。
#### 权重配置示例
通过 `weight` 字段可以控制策略间的资金分配比例。下单金额计算公式为:
**下单金额 = 可用资金 × 策略权重 / Σ(各策略槽位数 × 权重)**
##### 基础配置(无权重,等权分配)
不配置 `weight` 时,所有策略默认为权重 1实现等权分配
```json
"strategies": {
"strategy_a": {
"qmt_id": "gj",
"total_slots": 5,
"execution": {
"buy_drift_pct": 0.005,
"sell_drift_fixed": -0.01,
"max_adjust_limit": 0.05
}
},
"strategy_b": {
"qmt_id": "gj",
"total_slots": 5,
"execution": {
"buy_drift_pct": 0.005,
"sell_drift_fixed": -0.01,
"max_adjust_limit": 0.05
}
}
}
```
**计算示例**A(权重1×5) + B(权重1×5) = 10可用资金 100 万时A 和 B 各分配 50 万。
##### 加权配置(按权重分配)
配置 `weight` 字段可以实现差异化的资金分配:
```json
"strategies": {
"strategy_a": {
"qmt_id": "gj",
"total_slots": 5,
"weight": 1,
"execution": {
"buy_drift_pct": 0.005,
"sell_drift_fixed": -0.01,
"max_adjust_limit": 0.05
}
},
"strategy_b": {
"qmt_id": "gj",
"total_slots": 5,
"weight": 2,
"execution": {
"buy_drift_pct": 0.005,
"sell_drift_fixed": -0.01,
"max_adjust_limit": 0.05
}
}
}
```
**计算示例**A(权重1×5) + B(权重2×5) = 15可用资金 100 万时A 分配 100×1/15 ≈ 6.67 万B 分配 100×2/15 ≈ 13.33 万。
##### 不同槽位数的加权配置
```json
"strategies": {
"conservative_strategy": {
"qmt_id": "gj",
"total_slots": 3,
"weight": 1,
"execution": {
"buy_drift_pct": 0.003,
"sell_drift_fixed": -0.01,
"max_adjust_limit": 0.03
}
},
"aggressive_strategy": {
"qmt_id": "gj",
"total_slots": 8,
"weight": 3,
"execution": {
"buy_drift_pct": 0.008,
"sell_drift_fixed": -0.02,
"max_adjust_limit": 0.1
}
}
}
```
**计算示例**:保守策略(权重1×3) + 激进策略(权重3×8) = 27可用资金 100 万时,保守策略分配 100×1/27 ≈ 3.7 万,激进策略分配 100×3/27 ≈ 11.1 万。
```json
"strategies": {
"ST_Strategy": {
"qmt_id": "gj",
"total_slots": 5,
"execution": {
"buy_drift_pct": 0.005,
"sell_drift_fixed": -0.01,
"max_adjust_limit": 0.05
}
},
"XSZ_Strategy": {
"qmt_id": "gj",
"total_slots": 5,
"execution": {
"buy_drift_pct": 0.003,
"sell_drift_fixed": -0.015,
"max_adjust_limit": 0.03
}
},
"FUTURES_Strategy": {
"qmt_id": "yh",
"total_slots": 3,
"execution": {
"buy_drift_pct": 0.002,
"sell_drift_fixed": -0.005,
"max_adjust_limit": 0.1
}
}
}
```
## 配置验证清单
在启动 QMT 模块之前,请确保完成以下检查:
### Redis 配置检查
- [ ] `host` 指向正确的 Redis 服务器地址
- [ ] `port` 与 Redis 服务端口一致
- [ ] 如果 Redis 启用了密码认证,`password` 已正确设置
- [ ] 确保 Redis 服务器已启动且可访问
### QMT 终端配置检查
- [ ] 每个 `qmt_id` 在配置文件中唯一
- [ ] `path` 指向正确的 `userdata_mini` 目录
- [ ] `account_id` 与 MiniQMT 终端登录账号一致
- [ ] `account_type` 与实际账户类型匹配
- [ ] 确保 MiniQMT 终端已启动并登录成功
### 策略配置检查
- [ ] 每个策略的 `qmt_id` 已在 `qmt_terminals` 中定义
- [ ] `total_slots` 设置合理,建议根据资金规模和风险管理需求设置
- [ ] `buy_drift_pct` 设置合理,通常 0.3%-1% 之间
- [ ] `sell_drift_fixed` 设置合理,通常 -0.5% 到 -2% 之间
- [ ] `max_adjust_limit` 设置合理,通常 3%-10% 之间
## 常见问题
### Q如何添加新的券商终端
A按照以下步骤操作
1. 在 MiniQMT 终端中登录您的账户
2. 复制终端的 `userdata_mini` 目录路径
3. 在配置文件的 `qmt_terminals` 数组中添加新的终端配置
4. 保存配置文件后重启 QMT 模块
### Q如何为一个策略绑定多个终端
A当前设计不支持一个策略直接绑定多个终端。如果需要跨券商交易建议创建多个策略分别绑定不同的终端。
### Q执行参数如何影响交易
A
- `buy_drift_pct` 越大,买入时允许的价格溢价越高,利于快速成交但可能增加滑点成本
- `sell_drift_fixed` 越负(绝对值越大),卖出时允许的价格折价越高,利于快速成交但可能减少收益
- `max_adjust_limit` 越小,换手率越低,交易成本降低但灵活性也降低
### QRedis 连接失败怎么办?
A请检查以下几点
1. Redis 服务是否已启动
2. `host``port` 配置是否正确
3. 防火墙是否允许 Redis 端口访问
4. 如果设置了密码,`password` 是否正确
### Q如何配置策略的资金分配权重
A通过 `weight` 字段可以配置策略的资金分配权重:
- `weight` 是可选字段,不配置时默认为 1
- 下单金额计算公式:可用资金 × 策略权重 / Σ(各策略槽位数 × 权重)
- 示例两个策略A 的 weight=1、total_slots=5B 的 weight=2、total_slots=5则 A 分配 1/(1×5+2×5)=1/15B 分配 2/(1×5+2×5)=2/15
- 现有配置无需修改即可兼容,不配置 weight 时按等权分配
## 配置文件路径说明
配置文件应放置在以下位置之一:
| 路径 | 说明 |
|------|------|
| `qmt/config.json` | 推荐位置,专门存放 QMT 模块配置 |
| `./config.json` | 项目根目录 |
| 环境变量 `QMT_CONFIG_PATH` 指定的路径 | 通过环境变量自定义配置路径 |
系统启动时会按上述顺序查找配置文件,找到第一个存在的配置文件后即停止搜索。
## 相关文件
| 文件 | 路径 | 说明 |
|------|------|------|
| QMT 交易引擎 | `qmt/qmt_trader.py` | 负责与 MiniQMT 终端通信 |
| QMT 引擎核心 | `qmt/qmt_engine.py` | 策略执行引擎 |
| API 服务 | `qmt/api_server.py` | 提供 REST API 接口 |
| 仪表盘 | `qmt/dashboard.html` | 交易状态可视化界面 |

View File

@@ -528,14 +528,24 @@ class MultiEngineManager:
asset = unit.xt_trader.query_stock_asset(unit.acc_obj)
# 计算该终端的总槽位之和
terminal_strategies = self.get_strategies_by_terminal(unit.qmt_id)
total_slots = sum(self.config['strategies'][s]['total_slots'] for s in terminal_strategies)
if not asset or total_slots <= 0: return
# 计算加权槽位总和(支持策略权重配置)
# 权重默认为 1支持通过 weight 字段调整资金分配比例
# 示例strategies = {"strategy_a": {"total_slots": 5, "weight": 1}, "strategy_b": {"total_slots": 5, "weight": 2}}
total_weighted_slots = sum(
self.config['strategies'][s].get('total_slots', 1) * self.config['strategies'][s].get('weight', 1)
for s in terminal_strategies
)
if not asset or total_weighted_slots <= 0: return
# 3. 资金等权分配 (基于该终端总资产)
# 获取当前策略的权重
weight = strat_cfg.get('weight', 1)
# 4. 资金加权分配 (基于该终端总资产)
total_equity = asset.cash + asset.market_value
target_amt = total_equity / total_slots
actual_amt = min(target_amt, asset.cash * 0.98) # 预留手续费滑点
target_amt = total_equity * weight / total_weighted_slots
actual_amt = min(target_amt, asset.cash * 0.98) # 预留手续费滑点
if actual_amt < 2000:
self.logger.warning(f"[{strategy_name}] 单笔预算 {actual_amt:.2f} 不足 2000 元,取消买入")