问题描述
解决方案
在 QMT 平台中,要在一个策略里同时操作多个资金账户并下达不同的指令,核心在于以下两个步骤:
- 初始化绑定:在
init函数中,必须对每一个涉及的资金账户调用ContextInfo.set_account(accountID)。这一步是为了将策略与账户绑定,以便接收交易回报(成交、委托状态等)。 - 指定账户下单:在调用交易函数(如
passorder、order_shares、buy_open等)时,显式传入具体的accountID参数。
以下是具体的代码实现和详细说明。
策略代码示例
# -*- coding: gbk -*-
def init(ContextInfo):
# 1. 定义需要操作的账户列表
# 假设有两个账户,一个是股票账户,一个是信用账户或另一个股票账户
ContextInfo.acc_1 = '600000001' # 账户A
ContextInfo.acc_2 = '600000002' # 账户B
# 2. 分别绑定账户
# 注意:必须在init中设置,否则无法接收该账户的交易回报
ContextInfo.set_account(ContextInfo.acc_1)
ContextInfo.set_account(ContextInfo.acc_2)
# 设置一些策略运行变量
ContextInfo.trade_flag = False
def handlebar(ContextInfo):
# 仅在最后一根K线(实时行情)运行交易逻辑
if not ContextInfo.is_last_bar():
return
# 示例:仅运行一次,避免重复下单
if not ContextInfo.trade_flag:
# --- 对账户 A 下达指令:买入平安银行 ---
# 使用 order_shares (指定股数交易)
# 参数说明: 代码, 数量, 价格类型, 价格, ContextInfo, 账号ID
print(f"正在对账户 {ContextInfo.acc_1} 下单买入...")
order_shares('000001.SZ', 100, 'LATEST', 0, ContextInfo, ContextInfo.acc_1)
# --- 对账户 B 下达指令:卖出贵州茅台 ---
# 使用 passorder (综合交易下单) 以展示更精细的控制
# opType 24: 卖出
# orderType 1101: 单股单账号普通股/手下单
# accountID: 传入账户B
print(f"正在对账户 {ContextInfo.acc_2} 下单卖出...")
passorder(24, 1101, ContextInfo.acc_2, '600519.SH', 5, -1, 100, ContextInfo)
# 标记已交易
ContextInfo.trade_flag = True
print("多账户指令发送完毕")
# 交易回报回调(可选),用于监控不同账户的状态
def order_callback(ContextInfo, orderInfo):
# orderInfo.m_strAccountID 可以区分是哪个账户的回报
print(f"收到委托回报 - 账户: {orderInfo.m_strAccountID}, 代码: {orderInfo.m_strInstrumentID}, 状态: {orderInfo.m_nOrderStatus}")
关键点解析
1. ContextInfo.set_account() 的作用
虽然下单函数可以直接传账号 ID,但 set_account 是必不可少的。
- 功能:它告诉 QMT 系统,当前策略实例需要订阅这些账号的资金、持仓和委托变动推送。
- 多账户处理:你可以多次调用该函数,或者在逻辑中循环调用,将所有需要管理的账号都注册进去。
2. 下单函数中的 accountID 参数
QMT 的所有主要下单函数都支持指定账号。
-
passorder函数:- 原型:
passorder(opType, orderType, accountid, ...) - 这是最底层的下单接口,第三个参数即为
accountid。通过改变这个参数,你可以控制任意绑定的账户。
- 原型:
-
封装函数(如
order_shares,buy_open等):- 原型:
order_shares(stockcode, shares, style, price, ContextInfo, accId) - 注意:在这些简便函数中,
accId通常是最后一个可选参数。如果不传,系统会默认使用set_account设置的最后一个账号,或者导致多账户逻辑混乱。因此,在多账户策略中,务必显式传入该参数。
- 原型:
常见问题 (Q&A)
Q: 如果我在 init 中没有调用 set_account,直接在 passorder 中传账号ID会怎样?
A: 委托可能会发送成功(取决于柜台连接状态),但是你的策略将无法收到该笔委托的成交回报(deal_callback)或委托状态更新(order_callback)。这意味着你无法在策略代码中自动确认订单是否成交。
Q: 可以同时操作股票账户和期货账户吗?
A: 可以。只要在 init 中分别 set_account 绑定了股票账号和期货账号,在下单时分别传入对应的账号 ID,并使用正确的合约代码(如股票用 xxxxxx.SH,期货用 IFxxxx.IF)和对应的下单指令(股票用 order_shares 或 passorder opType 23/24,期货用 buy_open 等)即可。
Q: 如何对一组账户下达相同的指令(批量下单)?
A: 如果指令完全相同,可以使用账号组功能。
- 在 QMT 交易终端界面建立一个“账号组”。
- 在
passorder的accountid参数位置填入账号组名称。 - 将
orderType参数调整为支持账号组的类型(例如1201代表单股、账号组、普通下单)。
这样一次调用即可对组内所有账号下单。但如果指令不同(如题目要求),则必须在代码中循环或分别调用单账号下单接口。