取消实时 5 秒线
实时 5 秒线是持续订阅。只要不取消,它就可能一直占用行情行数和程序资源。页面关闭、策略停止、合约切换时,都应该主动调用取消接口。
Python 示例
Section titled “Python 示例”app.cancelRealTimeBars(97201) # 97201 必须和 reqRealTimeBars() 的 reqId 一致cancelRealTimeBars() 没有单独的成功回调。通常做法是在程序自己的订阅状态表里把 reqId 标记为已取消,并继续短时间接收可能已经在路上的回调。
| 场景 | 是否需要取消 |
|---|---|
| 用户关闭图表 | 需要 |
| 策略停止运行 | 需要 |
| 合约从 AAPL 切到 MSFT | 需要取消旧合约再订阅新合约 |
| 请求一开始就权限失败 | 可以调用取消,但可能收到 300 |
参考边界样例
Section titled “参考边界样例”请求 AAPL 5 秒线后主动取消:
CONNECTED=TrueREQUEST_SENT=TrueCANCEL_SENT=TrueBAR_ROWS=0ERROR=reqId=97201;code=420;msg=实时查询无效:No market data permissions for ISLAND STK. 请求的市场数据对于API来说需要额外订阅。点击“市场数据连接”对话框中的链接获取更多详情。ERROR=reqId=97201;code=300;msg=无法使用tickerId找到EId::97201这里的 300 不是新的连接问题,而是因为权限错误导致订阅没有真正建立,取消时 TWS 找不到这个 reqId 对应的有效订阅。
| 建议 | 原因 |
|---|---|
保存所有活跃 reqId | 方便页面退出或程序停止时批量取消 |
| 权限错误后标记订阅失败 | 避免重复取消同一个失败请求 |
| 取消后等待短时间确认无新回调 | 防止残留数据写入已关闭的图表 |
| 日志里记录取消动作 | 排查行情行数泄漏时很有用 |
订阅状态示例
Section titled “订阅状态示例”active_realtime_bars = set()
def subscribe_realtime_bars(req_id, contract): app.reqRealTimeBars(req_id, contract, 5, "TRADES", True, []) active_realtime_bars.add(req_id)
def cancel_realtime_bars(req_id): if req_id not in active_realtime_bars: return app.cancelRealTimeBars(req_id) active_realtime_bars.remove(req_id)
def error(self, reqId, code, message): if code in {200, 420, 10089}: active_realtime_bars.discard(reqId)这个示例的重点是:权限错误或合约错误出现后,程序要把订阅从活跃集合移除。这样页面关闭时不会对同一个失败请求反复取消,也更容易判断 300 是否只是跟随错误。