问题描述
策略在正常的跑的,没有问题,但QMT一直弹出出错警告,每秒都有错误弹出。
但我策略的执行间隔是3秒才执行一次。
请大佬帮忙看看是程序bug,还是我代码问题?
解决方案
你好!这通常是**代码逻辑不够严谨(代码问题)**导致的,而不是 QMT 平台的 bug。
为什么会报 'NoneType' object is not iterable?
这个错误的意思是:你尝试对一个 None(空值)进行迭代操作(比如使用了 for 循环,或者进行了解包赋值 a, b = result)。
在 QMT 中,很多查询 API(例如查询持仓、委托、成交明细等)在没有查询到数据或者查询失败时,可能会返回 None 而不是一个空的列表 []。如果你直接对返回值进行 for 循环,就会触发这个报错。
为什么策略是3秒执行一次,但每秒都在报错?
QMT 的 handlebar(ContextInfo) 函数是由行情 tick 驱动的。在实盘或模拟盘中,只要有最新的行情 tick 推送过来(通常每秒都有),handlebar 就会被调用一次。
虽然你的核心交易逻辑可能是通过定时器(如 run_time)或者时间判断控制在 3 秒执行一次,但引发报错的那行代码,很可能写在了时间判断的外面,导致每个 tick 进来时都会执行到那行错误代码。
常见引发此报错的场景与解决方法
场景 1:查询账户信息/持仓/委托时未做判空
最常见的是使用 get_trade_detail_data 函数:
错误写法:
def handlebar(ContextInfo):
# 如果当前没有持仓,或者查询过快导致失败,positions 可能为 None
positions = get_trade_detail_data(ContextInfo.accID, 'stock', 'position')
# 直接迭代 None 会报错:'NoneType' object is not iterable
for pos in positions:
print(pos.m_strInstrumentID)
正确写法(增加判空):
def handlebar(ContextInfo):
positions = get_trade_detail_data(ContextInfo.accID, 'stock', 'position')
# 增加判空逻辑
if positions is not None:
for pos in positions:
print(pos.m_strInstrumentID)
场景 2:获取行情数据时未做判空
使用 get_market_data 或 get_market_data_ex 时,如果传入的股票代码不正确或停牌,可能返回空结果。
正确写法:
data = ContextInfo.get_market_data_ex(['close'], ['000001.SZ'], period='1d')
if data is not None and '000001.SZ' in data:
# 继续处理数据
pass
排查建议
- 查看日志定位行数:QMT 的报错日志通常会提示具体是哪一行代码引发的错误,找到那一行。
- 检查该行的变量:看看是哪个函数返回的值,在这个值被
for循环遍历或解包之前,加上if xxx is not None:的判断。 - 检查缩进:确认你的 3 秒执行一次的逻辑(
if判断)是否正确包裹了所有的查询和处理代码,避免某些查询代码暴露在每次 tick 都会执行的层级。