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

View File

@@ -140,6 +140,7 @@ Redis 用于存储交易状态、缓存策略信号和实时行情数据。
|--------|------|------|--------|------| |--------|------|------|--------|------|
| `qmt_id` | 字符串 | 是 | - | 策略绑定的 QMT 终端 ID必须在 `qmt_terminals` 中定义 | | `qmt_id` | 字符串 | 是 | - | 策略绑定的 QMT 终端 ID必须在 `qmt_terminals` 中定义 |
| `total_slots` | 整数 | 是 | - | 策略可用的交易仓位总数 | | `total_slots` | 整数 | 是 | - | 策略可用的交易仓位总数 |
| `weight` | 整数 | 否 | 1 | 策略权重,用于按权重分配下单金额 |
| `execution` | 对象 | 是 | - | 策略执行参数,详见下方说明 | | `execution` | 对象 | 是 | - | 策略执行参数,详见下方说明 |
#### execution 执行参数配置 #### execution 执行参数配置
@@ -156,6 +157,7 @@ Redis 用于存储交易状态、缓存策略信号和实时行情数据。
- **`qmt_id`**:策略绑定的 QMT 终端标识符。一个策略只能绑定到一个终端,但多个策略可以绑定到同一个终端。 - **`qmt_id`**:策略绑定的 QMT 终端标识符。一个策略只能绑定到一个终端,但多个策略可以绑定到同一个终端。
- **`total_slots`**:策略可用的总仓位数量。例如设为 5 表示策略最多同时持有 5 只股票。此参数用于仓位管理和风险控制。 - **`total_slots`**:策略可用的总仓位数量。例如设为 5 表示策略最多同时持有 5 只股票。此参数用于仓位管理和风险控制。
- **`weight`**:策略权重,用于按权重分配下单金额。当不配置时,默认为 1表示等权分配。可用于实现策略间的资金分配比例控制。
- **`execution`**:包含策略的具体执行参数,这些参数控制订单的提交方式。 - **`execution`**:包含策略的具体执行参数,这些参数控制订单的提交方式。
**执行参数详解** **执行参数详解**
@@ -164,7 +166,100 @@ Redis 用于存储交易状态、缓存策略信号和实时行情数据。
- **`sell_drift_fixed`**:卖出时的固定漂移值。例如设置为 `-0.01`-1%)表示卖出时允许以低于基准价 1% 的价格成交,用于应对行情快速下跌的情况。计算公式为:卖出价 = 基准价 × (1 + sell_drift_fixed)。 - **`sell_drift_fixed`**:卖出时的固定漂移值。例如设置为 `-0.01`-1%)表示卖出时允许以低于基准价 1% 的价格成交,用于应对行情快速下跌的情况。计算公式为:卖出价 = 基准价 × (1 + sell_drift_fixed)。
- **`max_adjust_limit`**:单次调仓的最大比例限制。例如设置为 `0.05`5%)表示每次调仓不超过总仓位的 5%。此参数用于控制换手率和交易成本。 - **`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 ```json
"strategies": { "strategies": {
@@ -254,6 +349,14 @@ A请检查以下几点
3. 防火墙是否允许 Redis 端口访问 3. 防火墙是否允许 Redis 端口访问
4. 如果设置了密码,`password` 是否正确 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 时按等权分配
## 配置文件路径说明 ## 配置文件路径说明
配置文件应放置在以下位置之一: 配置文件应放置在以下位置之一:

View File

@@ -528,14 +528,24 @@ class MultiEngineManager:
asset = unit.xt_trader.query_stock_asset(unit.acc_obj) asset = unit.xt_trader.query_stock_asset(unit.acc_obj)
# 计算该终端的总槽位之和 # 计算该终端的总槽位之和
terminal_strategies = self.get_strategies_by_terminal(unit.qmt_id) 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 total_equity = asset.cash + asset.market_value
target_amt = total_equity / total_slots target_amt = total_equity * weight / total_weighted_slots
actual_amt = min(target_amt, asset.cash * 0.98) # 预留手续费滑点 actual_amt = min(target_amt, asset.cash * 0.98) # 预留手续费滑点
if actual_amt < 2000: if actual_amt < 2000:
self.logger.warning(f"[{strategy_name}] 单笔预算 {actual_amt:.2f} 不足 2000 元,取消买入") self.logger.warning(f"[{strategy_name}] 单笔预算 {actual_amt:.2f} 不足 2000 元,取消买入")