跳转到内容

取消公告请求

cancelNewsBulletins() 用来停止接收 IB 公告。

app.cancelNewsBulletins()

它没有参数。因为 reqNewsBulletins() 本身也没有 reqId,所以取消时不需要请求编号。

reqNewsBulletins(True)
-> updateNewsBulletin(...)
-> cancelNewsBulletins()

公告订阅不是特别高频,但程序退出、页面关闭或不再需要公告时,仍建议显式取消。

import threading
import time
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
class CancelBulletinsApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.ready = threading.Event()
self.bulletin_count = 0
self.errors_seen = []
def nextValidId(self, orderId):
self.ready.set()
def updateNewsBulletin(self, msgId, msgType, newsMessage, originExch):
self.bulletin_count += 1
def error(self, reqId, errorTime, errorCode, errorString, advancedOrderRejectJson=""):
if errorCode not in {2100, 2103, 2104, 2105, 2106, 2107, 2108, 2158}:
self.errors_seen.append((reqId, errorCode, errorString))
app = CancelBulletinsApp()
cancel_sent = False
try:
app.connect("127.0.0.1", 7497, clientId=131)
thread = threading.Thread(target=app.run, daemon=True)
thread.start()
if not app.ready.wait(8):
raise RuntimeError("等待 nextValidId 超时")
app.reqNewsBulletins(True)
time.sleep(6)
rows_before_cancel = app.bulletin_count
app.cancelNewsBulletins()
cancel_sent = True
time.sleep(1)
rows_after_cancel = app.bulletin_count
finally:
if app.isConnected():
app.disconnect()
print(f"CANCEL_SENT={cancel_sent}")
print(f"ROWS_BEFORE_CANCEL={rows_before_cancel}")
print(f"ROWS_AFTER_CANCEL_WAIT={rows_after_cancel}")
print(f"NON_INFO_ERROR_COUNT={len(app.errors_seen)}")
print(f"IS_CONNECTED_AFTER_DISCONNECT={app.isConnected()}")
CONNECTED=True
ALL_MSGS=True
REQUEST_SENT=True
BULLETIN_CALLBACK_RECEIVED=False
BULLETIN_ROW_COUNT=0
MSG_TYPE_COUNTS=NONE
ORIGIN_EXCH_COUNTS=NONE
MESSAGE_LENGTHS=EMPTY
CANCEL_SENT=True
ROWS_BEFORE_CANCEL=0
ROWS_AFTER_CANCEL_WAIT=0
INFO_CODES=2104,2106,2158
NON_INFO_ERROR_COUNT=0
IS_CONNECTED_AFTER_DISCONNECT=False

没有公告回调时,取消前后行数都是 0。取消动作没有产生非信息类错误。

建议取消。没有公告回调不代表订阅没有建立。

不需要。allMsgs 只用于请求阶段,取消方法没有参数。

建议取消。显式取消可以让程序状态和日志更清晰。