🚀 AI 一键生成 qmt 策略代码
立即体验
👉 AI 生成代码 👈

QMT回测中调用passorder触发买入但无持仓数据怎么办?

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

问题描述

求问passorder方法,在回测的时候已经成功调用,却无法在回测中有持仓数据

在策略实现中,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 个参数的位置,系统会将其识别为 ContextInfo,而中间的可选参数(strategyName, quickTrade, userOrderId)全部使用了默认值(quickTrade 默认为 0)。

默认机制(quickTrade=0)下:信号在当前 K 线的最后一个 tick 确认,在下一根 K 线的第一个 tick 才会触发下单。如果您的买入信号发生在回测时间段的最后一根 K 线,或者下一根 K 线没有数据,就不会产生实际交易。

修改建议
补全可选参数,显式传入 quickTrade=1

# 补全 strategyName, quickTrade, userOrderId
passorder(23, 1123, C.account_id, i, 5, -1, 1, "MyStrategy", 1, "Order001", C)

2. orderType=1123(按可用资金比例下单)的资金问题

您使用的 orderType1123,代表单股、单账号、可用资金、比例下单。此时 volume=1 代表使用 100% 的可用资金

  • 初始资金未设置:如果在 init 中没有设置 ContextInfo.capital,或者回测界面初始资金过小,导致 100% 的可用资金不足以买入 1 手(100股)该股票,QMT 会直接忽略该订单,且不会报错。
  • 资金已被占用:如果前面的代码已经触发了买入,可用资金变为 0,后续的 passorder 即使调用了,按 100% 比例计算出的买入量也是 0。

排查方法
在下单前打印一下当前可用资金,确认资金是否足够:

print(f"当前可用资金: {C.capital}") # 或者通过 get_trade_detail_data 获取真实可用资金

3. 股票代码格式不规范

QMT 严格要求股票代码必须包含市场后缀,例如平安银行必须是 '000001.SZ',贵州茅台必须是 '600519.SH'。如果您的变量 i 只是 '000001',底层 C++ 接口会解析失败,导致无法生成委托。

排查方法
打印变量 i,确保其格式为 代码.市场

4. 回测选价类型(prType)的限制

您使用的 prType=5(最新价)。根据 QMT 官方文档:

注意:回测时,除了指定价(11),其他下单选价类型均以当期 K 线收盘价结算。

虽然 prType=5 在回测中通常会自动转为收盘价撮合,但为了避免某些极端行情(如一字涨停导致无法买入),建议在回测中明确使用**指定价(11)**进行测试。

💡 终极修改方案

建议您将下单代码修改为如下形式,增加容错和明确的参数传递:

def handlebar(C):
    # 假设 i 是股票代码,例如 '000001.SZ'
    i = '000001.SZ'
    
    # 获取当前 K 线的收盘价作为指定价
    close_price = C.get_market_data(['close'], [i], period='1d', count=1)['close'][0]
    
    # 使用 1101 (按股数/手数下单) 或 1123 (按比例下单)
    # 这里演示修复后的 1123 按比例下单,明确传入 quickTrade=1
    # 参数顺序: opType, orderType, accountID, orderCode, prType, price, volume, strategyName, quickTrade, userOrderId, ContextInfo
    passorder(23, 1123, C.account_id, i, 11, close_price, 1, "StrategyA", 1, "BuyOrder", C)
    
    print(f"{C.get_bar_timetag(C.barpos)}——{i}触发买入,指定价格:{close_price}")

总结检查清单

  1. 检查 passorder 参数个数,确保 quickTrade=1 传在了正确的位置(第 9 个参数)。
  2. 检查回测初始资金是否足够买入 1 手标的。
  3. 检查股票代码 i 是否带有 .SH.SZ 后缀。
  4. 确保触发信号的 K 线之后,还有至少一根 K 线的数据(如果未使用 quickTrade=1)。