3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 QMT (Quantitative Trading Platform) 平台中,策略运行出现错误时,可以通过以下几个步骤和方法进行排查和定位。主要依赖于平台提供的日志输出面板、Python 标准的打印调试以及特定的回调函数。
以下是详细的排查步骤:
这是最直接的排查方式。当策略运行出错(如语法错误、运行时异常)时,报错信息会直接显示在 QMT 界面下方的 “日志输出” 面板中。
Traceback,指出错误发生的文件行号(Line number)和具体的错误类型(如 NameError, SyntaxError, KeyError 等)。由于 QMT 的 Python 策略是由 C++ 底层调用的,使用 IDE 的断点调试可能不便,最常用且有效的方法是在关键代码段插入 print() 语句。
init() 或 handlebar() 中打印关键变量的值,确认数据是否获取成功。print("Step 1 reached")),以确定代码执行到了哪一步中断。handlebar 会在每根 K 线或每个 Tick 触发,打印过多会导致日志刷新过快,建议配合 ContextInfo.barpos 或 ContextInfo.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}")
如果在回测模式下,可以通过设置 ContextInfo.data_info_level 来控制系统日志的详细程度,以便过滤无用信息或查看更详细的警告。
参数说明:
0: 信息 (Info) - 最详细1: 警告 (Warning)2: 错误 (Error)3: 致命 (Fatal) - 仅显示严重错误代码示例:
def init(ContextInfo):
# 设置为 0 可以看到所有级别的日志,有助于排查逻辑细节
ContextInfo.data_info_level = 0
很多运行时错误(如 AttributeError: 'NoneType' object has no attribute... 或 KeyError)是由于数据获取失败导致的。
get_market_data 或 get_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
# 正常逻辑...
如果是交易环节出错(例如下单后未成交、废单),单纯看代码逻辑无法发现问题,需要使用 orderError_callback 来捕获柜台或验资验券端的拒绝原因。
def init(ContextInfo):
ContextInfo.set_account('您的资金账号')
def orderError_callback(ContextInfo, orderArgs, errMsg):
# 当下单异常时,会触发此函数
print("下单出现错误!")
print(f"错误信息: {errMsg}")
print(f"涉及订单参数: {orderArgs}")
init 中定义且未加 global 声明的全局变量。ContextInfo 拼写错误,或者获取的对象为空(None)。Q: 为什么我的 print 输出在日志面板里看不到?
A: 请检查策略是否正在运行。如果是回测模式,确保回测进度条已经开始走动。如果是实盘/模拟模式,确保行情连接正常。另外,检查是否在 handlebar 中加了限制条件导致代码未执行到 print 语句处。
Q: 报错提示 "global name 'xxxx' is not defined",但我明明在 init 里定义了?
A: 在 QMT 的 Python 框架中,init 和 handlebar 是两个独立的作用域。如果你想在 handlebar 中使用 init 里定义的变量,建议将变量绑定到 ContextInfo 对象上(例如 ContextInfo.my_var = 1),这样它就在全局生命周期内可用了。
Q: 策略没有报错,但是不下单,怎么排查?
A:
ContextInfo.set_account() 是否正确设置。passorder 或 order_shares 等交易函数的参数是否正确(如 opType)。ContextInfo.is_last_bar() 判断中(实盘通常只在最新 K 线交易)。orderError_callback 查看是否有柜台拒单信息(如资金不足、非交易时间等)。