问题描述
解决方案
在 QMT 量化交易平台中,对一篮子股票(组合)下单主要通过 passorder 函数实现。控制下单金额或数量的核心在于选择正确的 orderType(下单方式) 参数以及对应的 volume(下单数量) 参数。
以下是关于如何控制总金额/数量的方法,以及三种不同下单模式的区别详解。
1. 核心函数:passorder
针对组合交易,passorder 函数的关键参数设置如下:
- opType (操作类型):
25:组合买入26:组合卖出
- orderCode (下单代码):填写在 QMT 客户端中预先创建好的篮子名称(字符串)。
- orderType (下单方式):决定了是按数量、金额还是比例下单(详见下文)。
- volume (下单数量):根据
orderType的不同,代表份数、金额或百分比。
2. 三种下单模式的区别与控制方法
在 QMT 的 passorder 函数中,通过设置不同的 orderType(通常为四位数,如 2101, 2102, 2103)来实现不同的控制逻辑。
(1) 按数量下单 (Basket Volume / Units)
- 对应 orderType:
2101(单账号) /2201(账号组) - 含义:按“篮子份数”下单。
- 逻辑:在创建篮子时,你定义了 1 份篮子包含哪些股票以及每只股票的具体股数(例如:1 份篮子 = 100 股平安银行 + 200 股万科)。
- 控制方式:
volume参数代表买入多少份篮子。 - 适用场景:ETF 套利、固定比例配对交易,关注的是成分股之间的绝对数量关系。
(2) 按金额下单 (Total Value / Weight)
- 对应 orderType:
2102(单账号) /2202(账号组) - 含义:按“总金额”下单,系统根据篮子权重分配。
- 逻辑:在创建篮子时,你定义了每只股票的权重(例如:平安银行占 30%,万科占 70%)。
- 控制方式:
volume参数代表总计划使用的金额(元)。 - 计算过程:系统会根据总金额 × 个股权重 ÷ 个股最新价,自动计算出每只股票需要买入的股数(通常向下取整到 100 股)。
- 适用场景:资产配置策略,例如“我要买入 100 万元的沪深 300 权重股”。
(3) 按比例下单 (Percentage of Available Cash)
- 对应 orderType:
2103(单账号) /2203(账号组) - 含义:按“账号可用资金的比例”下单。
- 逻辑:同样基于篮子内股票的权重进行分配。
- 控制方式:
volume参数代表占用可用资金的比例(范围 0 ~ 1,例如 0.5 代表 50%)。 - 计算过程:系统先计算:当前可用资金 × 比例 = 总金额,然后再按“按金额下单”的逻辑分配给各只股票。
- 适用场景:动态仓位管理,例如“用当前账户剩余资金的 50% 买入该组合”。
3. 代码实现示例
假设你已经在 QMT 客户端的【策略交易】-【篮子交易】中创建了一个名为 "MyStrategyBasket" 的篮子。
# -*- coding: gbk -*-
def init(ContextInfo):
# 设置资金账号
ContextInfo.accID = '6000000000'
ContextInfo.set_account(ContextInfo.accID)
def handlebar(ContextInfo):
# 获取当前 K 线索引
index = ContextInfo.barpos
# 获取当前时间
realtime = ContextInfo.get_bar_timetag(index)
# 仅在最后一根 K 线运行,避免历史回测重复下单(视策略需求而定)
if not ContextInfo.is_last_bar():
return
# 篮子名称 (需要在 QMT 客户端预先建立好)
basket_name = "MyStrategyBasket"
# ------------------------------------------------------------------
# 场景 1:按数量下单 (买入 5 份篮子)
# ------------------------------------------------------------------
# opType=25(组合买入), orderType=2101(按数量), volume=5(份)
# prType=11(市价/模型价,组合交易通常建议用市价或对手价), price=-1(市价时无效)
passorder(25, 2101, ContextInfo.accID, basket_name, 14, -1, 5, ContextInfo)
print("已发送按数量组合买单:5份")
# ------------------------------------------------------------------
# 场景 2:按金额下单 (买入总市值 100,000 元的组合)
# ------------------------------------------------------------------
# opType=25(组合买入), orderType=2102(按金额), volume=100000(元)
# 系统会根据篮子里的权重分配这 10 万元
passorder(25, 2102, ContextInfo.accID, basket_name, 14, -1, 100000, ContextInfo)
print("已发送按金额组合买单:10万元")
# ------------------------------------------------------------------
# 场景 3:按比例下单 (使用当前可用资金的 30% 买入组合)
# ------------------------------------------------------------------
# opType=25(组合买入), orderType=2103(按可用比例), volume=0.3(30%)
passorder(25, 2103, ContextInfo.accID, basket_name, 14, -1, 0.3, ContextInfo)
print("已发送按比例组合买单:可用资金的30%")
# ------------------------------------------------------------------
# 场景 4:组合卖出 (卖出 100% 的持仓)
# ------------------------------------------------------------------
# opType=26(组合卖出), orderType=2103(按可用/持仓比例), volume=1.0(100%)
# 注意:卖出时 2103 通常指卖出该篮子持仓的百分比
passorder(26, 2103, ContextInfo.accID, basket_name, 14, -1, 1.0, ContextInfo)
print("已发送组合清仓卖单")
4. 总结对照表
| 下单模式 | orderType | volume 参数含义 | 依赖的篮子属性 | 典型用途 |
|---|---|---|---|---|
| 按数量 | 2101 | 份数 (如 10 份) | 股票的具体股数 (绝对数量) | 套利、对冲、固定数量交易 |
| 按金额 | 2102 | 总金额 (如 100000 元) | 股票的权重比例 | 资产配置、定投 |
| 按比例 | 2103 | 比例 (如 0.5 代表 50%) | 股票的权重比例 | 满仓轮动、动态资金管理 |
常见问题 Q&A
Q: 如果我没有在界面创建篮子,可以在代码里动态定义一篮子股票下单吗?
A: passorder 的组合交易功能依赖于 QMT 系统内的篮子对象。如果你想完全通过代码动态定义一篮子股票(例如每次运行股票列表都不同),通常有两种做法:
- 循环下单:在 Python 代码中遍历股票列表,使用
order_value或order_target_value对每一只股票单独下单。这是最灵活的方式,但下单速度比原生组合交易稍慢。 - 动态修改篮子文件:通过
ContextInfo.load_stk_list或load_stk_vol_list接口读取文件来更新篮子,或者直接操作 QMT 的篮子文件(较复杂),然后调用passorder。
Q: 按金额下单时,如果某只股票分配的金额不足买 100 股怎么办?
A: QMT 会根据交易所规则(通常是 A 股 100 股为 1 手)进行处理。如果分配金额不足 1 手的金额,该股票通常不会下单,或者根据具体的算法交易设置进行零股处理(如果是科创板等支持零股的板块)。
Q: 组合交易支持限价吗?
A: 支持。在 passorder 的 prType 参数中设置限价类型(如 11),并在 price 参数中填入价格。但要注意,组合交易通常涉及多只股票,设置单一的绝对价格(如 10.5 元)通常没有意义(除非所有股票价格都一样)。组合交易中的限价通常指“模型价”或“最新价”等相对价格策略,或者使用算法交易(algo_passorder)来更精细地控制成交价格。一般建议组合交易使用 14 (对手价) 或 5 (最新价) 以保证成交。