跳转到内容

取消逐笔数据

逐笔数据是实时订阅。只要不再需要,就应该调用 cancelTickByTickData() 取消。

官方参考:Tick-by-Tick Data

app.cancelTickByTickData(reqId)

reqId 必须和 reqTickByTickData() 请求时使用的编号一致。

app.reqTickByTickData(97901, aapl_stock(), "Last", 0, False)
# 不再需要成交逐笔数据时取消。
app.cancelTickByTickData(97901)
场景说明
用户关闭行情页面取消对应逐笔订阅。
策略停止运行取消所有策略使用的逐笔订阅。
切换标的取消旧标的,再请求新标的。
收到权限错误订阅通常没有建立,可从程序状态中移除。
准备换用历史逐笔先取消实时逐笔,避免同一合约重复订阅和限频问题。

AAPL 逐笔行情权限不足时,请求没有真正建立。随后取消时 TWS 可能返回:

ERROR=reqId=97901;type=Last;code=300;msg=无法使用tickerId找到EId::97901
ERROR=reqId=97902;type=BidAsk;code=300;msg=无法使用tickerId找到EId::97902
ERROR=reqId=97903;type=MidPoint;code=300;msg=无法使用tickerId找到EId::97903
ERROR=reqId=97904;type=AllLast;code=300;msg=无法使用tickerId找到EId::97904

这里的 300 要和前面的 1018910089 一起理解:根因通常是行情权限不足、产品不支持该逐笔类型,或订阅没有建立;取消未建立的订阅时,就可能找不到对应 ticker。

维护本地订阅状态时,收到权限错误后应把该 reqId 标记为失败:

active_tick_by_tick = set()
def request_last_ticks(req_id, contract):
app.reqTickByTickData(req_id, contract, "Last", 0, False)
active_tick_by_tick.add(req_id)
def cancel_last_ticks(req_id):
if req_id in active_tick_by_tick:
app.cancelTickByTickData(req_id)
active_tick_by_tick.discard(req_id)

如果 error() 收到 1018910089200 等明确失败原因,也应从活跃订阅集合中移除。