问题描述
在策略实现中,python 调用 passorder 函数进行下单:
passorder(23, 1123, C.account_id, i, 5, -1, 1, C)
后跟 :
print(f"{bar_date}——{i}触发买入")
日志已经打印了“触发买入”
但是在副图和历史持仓里面并没有看到有任何下单操作。
已经用了快速下单 quicktrade = 1 ,并且回测时间在界面上和代码中都已经设置,而且两者保持一致。
历史日线数据也已经补充完毕。
解决方案
在 QMT 平台回测中,遇到 passorder 函数被成功调用(日志已打印)但没有产生实际持仓和交易记录的情况,通常是由参数传递错误、资金不足、或者撮合机制引起的。根据您提供的代码 passorder(23, 1123, C.account_id, i, 5, -1, 1, C),以下是几个最可能的原因及详细的排查解决方法:
1. quickTrade 参数传递位置错误(最核心原因)
您提到“已经用了快速下单 quicktrade = 1”,但在您提供的代码 passorder(23, 1123, C.account_id, i, 5, -1, 1, C) 中,并没有正确传入 quickTrade 参数。
根据 QMT API 文档,passorder 的完整参数顺序为:
passorder(opType, orderType, accountid, orderCode, prType, modelprice, volume[, strategyName, quickTrade, userOrderId], ContextInfo)
如果您直接把 C (ContextInfo) 放在第 8 个参数的位置,Python 会将其误认为 strategyName,而 quickTrade 依然是默认值 0。在回测中,如果信号发生在最后一根 K 线,且没有开启 quickTrade=1,订单会在下一根 K 线才撮合,导致最后一天的信号无法成交。
修改建议:
补全可选参数,将 quickTrade 放在正确的位置:
# 补全 strategyName, quickTrade, userOrderId
passorder(23, 1123, C.account_id, i, 5, -1, 1, "MyStrategy", 1, "BuyOrder", C)
2. orderType=1123 与初始资金(Capital)设置问题
您使用的 orderType 是 1123,其含义是:单股、单账号、可用资金、比例 [0 ~ 1] 方式下单。您传入的 volume 是 1,代表使用 100% 的可用资金 买入该股。
在回测模式下,如果没有正确设置初始资金,或者可用资金不足以买入该股票的 1 手(100股),订单会被风控直接废单,从而不会产生任何持仓。
修改建议:
确保在 init(ContextInfo) 函数中设置了足够的回测初始资金:
def init(C):
C.capital = 1000000 # 设置初始资金为 100 万
C.set_account(C.account_id) # 确保绑定了回测账号
3. 回测选价类型(prType)的限制
您使用的 prType 是 5(最新价)。根据 QMT 官方文档说明:
注意:回测时,除了指定价(11),其他下单选价类型均以当期 K 线收盘价结算。
虽然写 5 在回测中通常会自动按收盘价撮合,但为了严谨和避免某些极端情况(如涨停跌停无法买入),建议在回测中明确使用指定价(11)或直接依赖默认的收盘价撮合。
4. 账号绑定问题
在回测中,虽然使用的是虚拟账号,但依然需要在 init 中调用 C.set_account() 将账号注册到上下文中,否则底层交易主推可能无法正确记录该账号的委托。
总结:标准修正代码示例
请参考以下修正后的代码逻辑,替换您原有的下单部分:
def init(C):
C.account_id = '您的测试账号'
C.set_account(C.account_id) # 必须绑定账号
C.capital = 1000000 # 确保有足够的初始资金
def handlebar(C):
# ... 您的策略逻辑 ...
# 假设触发了买入条件,i 为股票代码
if 触发买入条件:
print(f"{bar_date}——{i}触发买入")
# 使用 1123 按比例下单,volume=1 代表 100% 仓位
# 依次传入: opType, orderType, account, code, prType, price, volume, strategyName, quickTrade, remark, ContextInfo
passorder(23, 1123, C.account_id, i, 5, -1, 1, "StrategyName", 1, "Buy", C)
排查小贴士:
如果修改后依然没有持仓,请在 QMT 底部的**“日志输出”**面板中,将日志级别调低,查看是否有类似“资金不足”、“废单”、“不在股票池”等底层 C++ 引擎抛出的警告信息。