🚀 AI 一键生成 qmt 策略代码

QMT 量化交易:将 passorder 写入自定义函数并在 handlebar 中调用的正确方法

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

问题描述

关于在QMT内将passorder函数写入自定义函数中的问题

各位老师

您好

想请教一下将 passorder 函数写入自定义函数并在 handlebar 中调用的解决方法。

(烦请老师给个示例)谢谢!

import pandas as pd
import numpy as np
import talib

def init(ContextInfo):
#hs300成分股中sh和sz市场各自流通市值最大的前3只股票
ContextInfo.trade_code_list=['600570.SH']
ContextInfo.set_universe(ContextInfo.trade_code_list)
ContextInfo.accID = '620000178329'
ContextInfo.buy = True
ContextInfo.sell = False

def handlebar(ContextInfo):

open = True
if open == True:
buy()
open = False

def buy():

passorder(23,1101,ContextInfo.accID,ContextInfo.trade_code_list,4,-1,100,'ceshi',1,'测试下单',ContextInfo)
print('买入啦')
import pandas as pd
import numpy as np
import talib

def init(ContextInfo):
#hs300成分股中sh和sz市场各自流通市值最大的前3只股票
ContextInfo.trade_code_list=['600570.SH']
ContextInfo.set_universe(ContextInfo.trade_code_list)
ContextInfo.accID = '620000178329'
ContextInfo.buy = True
ContextInfo.sell = False

def handlebar(ContextInfo):

open = True
if open == True:
buy()
open = False

def buy():

passorder(23,1101,ContextInfo.accID,ContextInfo.trade_code_list,4,-1,100,'ceshi',1,'测试下单',ContextInfo)
print('买入啦')

解决方案

您好!在 QMT 平台中,将 passorder 封装到自定义函数中是非常常见的做法,可以提高代码的可读性和复用性。

您提供的代码主要存在两个问题:

  1. 作用域问题(缺少 ContextInfo 传递)ContextInfo 是 QMT 策略运行的全局上下文对象,passorder 函数依赖它来执行。您的自定义函数 buy() 没有接收 ContextInfo 参数,导致在函数内部调用 passorder 时找不到 ContextInfo 对象。
  2. 参数类型问题:您使用的下单模式是 1101(单股、单账号、普通、股/手方式下单),该模式下 orderCode 参数需要是一个字符串(如 '600570.SH'),而您传入的是一个列表 ContextInfo.trade_code_list
  3. 逻辑控制问题:在 handlebar 中,open = True 每次都会被重新赋值,导致 open = False 无法阻止后续 K 线继续下单。建议将状态变量存入 ContextInfo 中。

修改后的正确示例

下面是为您修正并优化后的代码示例:

#encoding:gbk
import pandas as pd
import numpy as np

def init(ContextInfo):
    # 设置股票池
    ContextInfo.trade_code_list = ['600570.SH']
    ContextInfo.set_universe(ContextInfo.trade_code_list)
    
    # 设置资金账号
    ContextInfo.accID = '620000178329'
    
    # 使用 ContextInfo 存储全局状态,控制是否已经买入
    ContextInfo.has_bought = False
  
def handlebar(ContextInfo):
    # 如果还没有买入,则执行买入逻辑
    if not ContextInfo.has_bought:
        # 调用自定义函数时,必须将 ContextInfo 作为参数传入
        my_custom_buy(ContextInfo)
        # 更新状态,防止重复下单
        ContextInfo.has_bought = True

# 自定义函数,必须接收 ContextInfo 参数
def my_custom_buy(ContextInfo):
    # 遍历股票池中的代码进行下单
    for stock_code in ContextInfo.trade_code_list:
        # passorder 参数解析:
        # 23: 股票买入
        # 1101: 单股、单账号、普通、股/手方式下单
        # ContextInfo.accID: 资金账号
        # stock_code: 股票代码(字符串格式,不能是列表)
        # 11: 指定价模型价 (这里用 11 配合后面的 -1,或者直接用 5 最新价)
        # -1: 价格 (prType为11时有效,这里填-1表示无效,建议根据需求填写真实价格或改用市价)
        # 100: 下单数量 (100股)
        # 'ceshi': 策略名
        # 1: quickTrade 快速交易
        # '测试下单': 投资备注
        # ContextInfo: 上下文对象
        
        # 建议:如果想按最新价买入,prType 可以设为 5,price 设为 -1
        passorder(23, 1101, ContextInfo.accID, stock_code, 5, -1, 100, 'ceshi', 1, '测试下单', ContextInfo)
        
        print(f'已发送买入指令: {stock_code}')

关键修改点解析:

  1. def my_custom_buy(ContextInfo)::在定义自定义函数时,增加 ContextInfo 作为形参。
  2. my_custom_buy(ContextInfo):在 handlebar 中调用时,将当前的 ContextInfo 实参传递进去。
  3. for stock_code in ContextInfo.trade_code_list::因为 1101 模式只接受单个股票代码,所以需要遍历列表,将字符串格式的 stock_code 传给 passorder
  4. 状态控制:将 open 变量替换为 ContextInfo.has_bought。因为 handlebar 在每根 K 线(或每个 tick)都会被调用一次,局部变量会被重置,只有挂载在 ContextInfo 上的变量才能跨周期保存状态。