关于在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 封装到自定义函数中是非常常见的做法,可以提高代码的可读性和复用性。
您提供的代码主要存在两个问题:
- 作用域问题(缺少 ContextInfo 传递):
ContextInfo是 QMT 策略运行的全局上下文对象,passorder函数依赖它来执行。您的自定义函数buy()没有接收ContextInfo参数,导致在函数内部调用passorder时找不到ContextInfo对象。 - 参数类型问题:您使用的下单模式是
1101(单股、单账号、普通、股/手方式下单),该模式下orderCode参数需要是一个字符串(如'600570.SH'),而您传入的是一个列表ContextInfo.trade_code_list。 - 逻辑控制问题:在
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}')
关键修改点解析:
def my_custom_buy(ContextInfo)::在定义自定义函数时,增加ContextInfo作为形参。my_custom_buy(ContextInfo):在handlebar中调用时,将当前的ContextInfo实参传递进去。for stock_code in ContextInfo.trade_code_list::因为1101模式只接受单个股票代码,所以需要遍历列表,将字符串格式的stock_code传给passorder。- 状态控制:将
open变量替换为ContextInfo.has_bought。因为handlebar在每根 K 线(或每个 tick)都会被调用一次,局部变量会被重置,只有挂载在ContextInfo上的变量才能跨周期保存状态。