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

QMT回测无成交记录、报告空白原因排查与下单函数详解

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

问题描述

【求助】QMT内置Python策略回测无成交记录,已按文档操作仍失败

大家好,我是从聚宽迁移过来的用户,在开发 QMT 内置 Python 策略时遇到几个问题,已经折腾了几天了,客服让我来社区求助。

一、核心问题:回测无成交记录

现象:

策略运行后,日志中有 [BUY] 和 [SELL] 打印
但回测报告窗口是空白的(只有框子,没有内容)
用 get_trade_detail_data('test', 'stock', 'deal') 获取成交记录,返回空
用 get_trade_detail_data('test', 'stock', 'position') 获取持仓,也返回空
回测参数设置:

已按文档要求以"副图模式"执行
最大成交比例设置为 100
回测时间:2024-01-01 到 2024-12-31
初始资金:500000
问题:

回测报告空白是什么原因?策略到底有没有实际成交?
如何确认回测是否成交?有没有可靠的查看方式?
"当日买入"和"持仓明细"面板在回测中是否本来就没有内容?
二、下单函数选择疑问

我看到两种下单方式,不确定哪个对:

方式 1(网上找的,8 个参数):
passorder(23, 1101, accountid, stock, 11, price, volume, ContextInfo)

方式 2(官方文档,11 个参数):
passorder(opcode, ordertype, accountid, stock, price_type, price, volume, strategy_name, quicktrade, remark, C)

问题:

passorder() 到底是 8 个参数还是 11 个参数?
官方文档写的是 11 个参数,但网上大部分示例是 8 个参数,哪个是对的?
回测中应该用哪种下单方式?
三、其他疑问

order_target_value() 在回测中是否能用?官方文档没有提到这个函数
get_bar_timetag(barpos) 在回测中返回 0,这是正常的吗?有没有其他获取时间的方法?
代码中已经加了 #coding:gbk,还有哪里需要注意?
四、测试代码(简化版)

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

def init(C):
C.accountid = "testS"
C.set_universe(['000820.SZ', '601700.SH'])
C.positions = {}
print('Strategy initialized')

def handlebar(C):
barpos = C.barpos

# Get current time
timetag = C.get_bar_timetag(barpos)
if timetag > 0:
import datetime
timestamp_sec = timetag / 1000.0
dt = datetime.datetime.fromtimestamp(timestamp_sec)
current_time = dt.hour * 100 + dt.minute
else:
current_time = 0

# Check buy signal at 14:50
if current_time == 1450:
for code in C.get_universe():
# Buy logic (simplified)
passorder(23, 1101, C.accountid, code, 5, -1, 100, C)
print('BUY %s' % code)

# Check sell signal at 14:30
if current_time == 1430:
for code in C.get_universe():
if code in C.positions:
passorder(24, 1101, C.accountid, code, 5, -1, 100, C)
print('SELL %s' % code)

日志输出:
Strategy initialized
BUY 000820.SZ
BUY 601700.SH
SELL 000820.SZ
SELL 601700.SH

但回测报告空白,get_trade_detail_data 返回空。

请问各位大佬,这是哪里做错了?是下单函数参数不对,还是回测配置有问题?

感谢!

解决方案

欢迎来到 QMT 量化平台!从云端平台(如聚宽)迁移到本地端平台(如 QMT),最容易遇到的坑通常集中在本地数据补充回测/实盘接口差异上。针对你遇到的问题,以下是详细的排查指南和解答:

一、 核心问题:回测无成交记录与报告空白

1. 为什么 get_trade_detail_data 返回空?
在 QMT 中,get_trade_detail_data 是专门用于实盘和模拟盘获取真实账户柜台数据的接口。在回测模式下,该函数无效且返回空。回测时,交易函数调用的是虚拟账号,记录保存在内存中。
👉 正确做法:在回测模式下,必须使用 get_result_records(recordtype, index, ContextInfo) 函数来获取回测面板中的虚拟成交和持仓记录。例如:

# 获取当前K线的买入记录
buys = get_result_records('buys', C.barpos, C)
# 获取当前持仓
holdings = get_result_records('holdings', C.barpos, C)

2. 为什么回测报告窗口是空白的?

  • 原因 A:没有下载本地历史数据。QMT 是本地终端,回测前必须在【数据管理】->【补充数据】中下载对应时间段(2024全年)、对应周期(如1分钟线)的 K 线数据。如果没有数据,撮合引擎无法获取价格,导致无法成交。
  • 原因 B:点击了“运行”而不是“回测”。策略编辑器上方有【运行】和【回测】两个按钮。【运行】是模拟实时行情驱动(不生成回测报告),【回测】才是基于历史数据生成绩效报告。
  • 原因 C:价格设置无法撮合。回测时,除了指定价(prType=11),其他下单选价类型均以当期 K 线收盘价结算。如果你的资金不足或价格超出涨跌停,也会导致废单。

二、 下单函数 passorder 参数疑问

passorder() 到底是 8 个参数还是 11 个参数?
两者都对! passorder 的基础必填参数是 8 个,另外 3 个是可选参数。

  • 8 参数基础版passorder(opType, orderType, accountID, orderCode, prType, price, volume, ContextInfo)
  • 11 参数完整版:在 volumeContextInfo 之间,可以插入三个可选参数 [strategyName, quickTrade, userOrderId]
    👉 回测建议:直接使用 8 个参数的版本即可,完全满足回测需求。你代码中的 passorder(23, 1101, C.accountid, code, 5, -1, 100, C) 语法是完全正确的。

三、 其他疑问解答

1. order_target_value() 在回测中是否能用?
完全可以。官方文档中明确提供了 order_lotsorder_valueorder_target_value 等封装好的股票快捷下单函数。它们在底层也是调用 passorder,在回测和实盘中均受支持,推荐新手优先使用这些快捷函数,比手写 passorder 更不容易出错。

2. get_bar_timetag(barpos) 在回测中返回 0 正常吗?
不正常! 返回 0 100% 是因为本地缺少该品种的历史数据。请立即前往【数据管理】补充数据。只要数据补充完整,该函数会正确返回毫秒级时间戳。

3. 代码其他注意事项

  • 账号绑定:建议在 init 中使用 C.set_account("testS") 显式绑定账号。
  • 滑点与手续费:建议在 init 中使用 C.set_slippage()C.set_commission() 设置回测费率,否则默认费率可能与你的预期不符。

四、 总结与下一步建议

你的代码逻辑基本没问题,核心症结在于未补充本地数据以及误用了实盘查询接口。请按照以下步骤操作:

  1. 打开 QMT 终端 -> 数据管理 -> 补充数据 -> 勾选你的股票池品种 -> 选择 1分钟线和日线 -> 补充 2024 年全年数据。
  2. 确保点击的是【回测】按钮。
  3. 如果需要在代码中打印持仓,将 get_trade_detail_data 替换为 get_result_records