🚀 AI 一键生成 qmt 策略代码

我的 QMT 策略报错了怎么办?Python 策略常见错误与调试技巧

qmt | 发布时间: 2025/11/26
以下内容由 EasyQuant 生成。

问题描述

我的策略运行时出现错误,应该如何查找问题原因?

解决方案

在 QMT (Quantitative Trading Platform) 平台中,策略运行出现错误时,可以通过以下几个步骤和方法进行排查和定位。主要依赖于平台提供的日志输出面板、Python 标准的打印调试以及特定的回调函数。

以下是详细的排查步骤:

QMT 策略运行报错排查指南

1. 查看日志输出面板 (Log Output)

这是最直接的排查方式。当策略运行出错(如语法错误、运行时异常)时,报错信息会直接显示在 QMT 界面下方的 “日志输出” 面板中。

  • 操作方法
    1. 在策略编辑器界面,找到底部的“日志输出”标签页。
    2. 查看红色的报错信息。通常会包含 Traceback,指出错误发生的文件行号(Line number)和具体的错误类型(如 NameError, SyntaxError, KeyError 等)。
    3. 根据行号回到代码中检查对应的逻辑。

2. 使用 print() 进行断点调试

由于 QMT 的 Python 策略是由 C++ 底层调用的,使用 IDE 的断点调试可能不便,最常用且有效的方法是在关键代码段插入 print() 语句。

  • 操作方法
    • init()handlebar() 中打印关键变量的值,确认数据是否获取成功。
    • 打印标记字符串(如 print("Step 1 reached")),以确定代码执行到了哪一步中断。
    • 注意handlebar 会在每根 K 线或每个 Tick 触发,打印过多会导致日志刷新过快,建议配合 ContextInfo.barposContextInfo.is_last_bar() 使用。
def handlebar(ContextInfo):
    # 仅在最后一根K线打印,避免刷屏
    if ContextInfo.is_last_bar():
        index = ContextInfo.barpos
        price = ContextInfo.get_market_data(['close'], stock_code=['600000.SH'])
        print(f"当前Bar索引: {index}, 获取到的价格数据: {price}")

3. 调整日志显示级别

如果在回测模式下,可以通过设置 ContextInfo.data_info_level 来控制系统日志的详细程度,以便过滤无用信息或查看更详细的警告。

  • 参数说明

    • 0: 信息 (Info) - 最详细
    • 1: 警告 (Warning)
    • 2: 错误 (Error)
    • 3: 致命 (Fatal) - 仅显示严重错误
  • 代码示例

def init(ContextInfo):
    # 设置为 0 可以看到所有级别的日志,有助于排查逻辑细节
    ContextInfo.data_info_level = 0

4. 检查数据获取返回值

很多运行时错误(如 AttributeError: 'NoneType' object has no attribute...KeyError)是由于数据获取失败导致的。

  • 常见原因
    • 未下载本地数据(QMT 很多接口依赖本地数据)。
    • get_market_dataget_market_data_ex 返回了空值或空 DataFrame。
    • 引用了不存在的字段名。
  • 排查建议
    在使用数据前,务必判断数据是否为空。
def handlebar(ContextInfo):
    data = ContextInfo.get_market_data_ex(['close'], ['600000.SH'], period='1d')
    # 检查数据是否为空
    if '600000.SH' not in data or data['600000.SH'].empty:
        print("警告:未获取到 600000.SH 的数据,请检查是否已补充数据")
        return
    # 正常逻辑...

5. 利用异常下单回调函数 (orderError_callback)

如果是交易环节出错(例如下单后未成交、废单),单纯看代码逻辑无法发现问题,需要使用 orderError_callback 来捕获柜台或验资验券端的拒绝原因。

  • 代码示例
def init(ContextInfo):
    ContextInfo.set_account('您的资金账号')

def orderError_callback(ContextInfo, orderArgs, errMsg):
    # 当下单异常时,会触发此函数
    print("下单出现错误!")
    print(f"错误信息: {errMsg}")
    print(f"涉及订单参数: {orderArgs}")

6. 常见错误类型速查

  • NameError: 变量名拼写错误,或者使用了未在 init 中定义且未加 global 声明的全局变量。
  • IndentationError: 缩进错误,Python 对缩进敏感,请确保统一使用空格或 Tab。
  • KeyError: 尝试访问字典中不存在的键,通常发生在行情数据获取失败或字段名拼写错误时。
  • AttributeError: 尝试调用对象不存在的方法,例如 ContextInfo 拼写错误,或者获取的对象为空(None)。

Q&A: QMT 策略调试常见问题

Q: 为什么我的 print 输出在日志面板里看不到?
A: 请检查策略是否正在运行。如果是回测模式,确保回测进度条已经开始走动。如果是实盘/模拟模式,确保行情连接正常。另外,检查是否在 handlebar 中加了限制条件导致代码未执行到 print 语句处。

Q: 报错提示 "global name 'xxxx' is not defined",但我明明在 init 里定义了?
A: 在 QMT 的 Python 框架中,inithandlebar 是两个独立的作用域。如果你想在 handlebar 中使用 init 里定义的变量,建议将变量绑定到 ContextInfo 对象上(例如 ContextInfo.my_var = 1),这样它就在全局生命周期内可用了。

Q: 策略没有报错,但是不下单,怎么排查?
A:

  1. 检查 ContextInfo.set_account() 是否正确设置。
  2. 检查 passorderorder_shares 等交易函数的参数是否正确(如 opType)。
  3. 检查是否处于 ContextInfo.is_last_bar() 判断中(实盘通常只在最新 K 线交易)。
  4. 使用 orderError_callback 查看是否有柜台拒单信息(如资金不足、非交易时间等)。