🚀 AI 一键生成 qmt 策略代码

QMT 策略中如何高效管理多个交易账户并实现差异化下单?

qmt | 发布时间: 2025/12/5
以下内容由 EasyQuant 生成。

问题描述

如何在一个策略里同时操作多个资金账户,并给它们下不同的指令?

解决方案

在 QMT 平台中,要在一个策略里同时操作多个资金账户并下达不同的指令,核心在于以下两个步骤:

  1. 初始化绑定:在 init 函数中,必须对每一个涉及的资金账户调用 ContextInfo.set_account(accountID)。这一步是为了将策略与账户绑定,以便接收交易回报(成交、委托状态等)。
  2. 指定账户下单:在调用交易函数(如 passorderorder_sharesbuy_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_sharespassorder opType 23/24,期货用 buy_open 等)即可。

Q: 如何对一组账户下达相同的指令(批量下单)?
A: 如果指令完全相同,可以使用账号组功能。

  1. 在 QMT 交易终端界面建立一个“账号组”。
  2. passorderaccountid 参数位置填入账号组名称
  3. orderType 参数调整为支持账号组的类型(例如 1201 代表单股、账号组、普通下单)。
    这样一次调用即可对组内所有账号下单。但如果指令不同(如题目要求),则必须在代码中循环或分别调用单账号下单接口。