跳转到内容

取消观察列表行情

流式一档行情会持续占用订阅资源。只要不再需要某个合约的行情,就应该调用 cancelMktData() 取消。

app.cancelMktData(tickerId)

tickerId 必须和请求时传给 reqMktData() 的编号一致。

# 请求 AAPL 一档行情。
app.reqMktData(97701, aapl_stock(), "", False, False, [])
# 不再需要时取消。
app.cancelMktData(97701)
场景是否取消
用户从观察列表移除合约需要取消。
页面关闭或切换账户需要取消。
策略停止运行需要取消。
快照请求通常不需要手动取消。
请求因为权限错误没有建立取消可能返回 300

请求 AAPL 流式一档行情后,因为行情权限不足,订阅没有真正建立。随后取消该 tickerId 时,TWS 返回:

ERROR=reqId=97701;name=streaming;code=300;msg=无法使用tickerId找到EId::97701

这通常表示要取消的行情请求并不存在或已经被拒绝。它要结合前面的错误一起看:

ERROR=reqId=97701;name=streaming;code=10089;msg=请求的市场数据对于API来说需要额外订阅...:AAPL NASDAQ.NMS/TOP/ALL

也就是说,根因是行情权限不足,300 是取消未建立订阅时的连带结果。

程序应维护订阅状态:

active_market_data = set()
def request_market_data(req_id, contract):
app.reqMktData(req_id, contract, "", False, False, [])
active_market_data.add(req_id)
def cancel_market_data(req_id):
if req_id in active_market_data:
app.cancelMktData(req_id)
active_market_data.discard(req_id)

如果 error() 收到明确的权限错误或合约错误,也可以把对应 reqId 从活跃订阅集合中移除。