跳转到内容

请求 IB 公告

reqNewsBulletins() 用来订阅 IB 公告。公告不是普通新闻行情,也不是订单通知,而是 IB 通过 TWS API 推送的系统公告或交易所可用性提示。

app.reqNewsBulletins(allMsgs)

返回结果通过 updateNewsBulletin() 回调接收。

def reqNewsBulletins(self, allMsgs: bool):
...
参数中文含义说明
allMsgs是否返回当天已有公告True 表示返回当天已有公告和新公告;False 表示只接收新公告

如果你只是做连通性验证,建议先用 True。这样如果当天有公告,更容易收到历史公告回调。

注意:allMsgs=True 不代表一定会收到回调。当天没有公告、会话没有可见公告或公告源没有推送时,回调行数可能是 0。

连接 TWS / IB Gateway
-> 等待 nextValidId()
-> reqNewsBulletins(True)
-> updateNewsBulletin(...)
-> cancelNewsBulletins()

公告接口是订阅型接口,不需要 reqId。取消时也不传请求编号。

import threading
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
INFO_CODES = {2103, 2104, 2105, 2106, 2107, 2108, 2158}
class RequestBulletinsApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.ready = threading.Event()
self.bulletin_ready = threading.Event()
self.rows = []
self.info_codes = []
self.errors_seen = []
def nextValidId(self, orderId):
self.ready.set()
def updateNewsBulletin(self, msgId, msgType, newsMessage, originExch):
self.rows.append({
"msgId": msgId,
"msgType": msgType,
"messageLength": len(newsMessage or ""),
"originExchange": originExch or "EMPTY",
})
self.bulletin_ready.set()
def error(self, reqId, errorTime, errorCode, errorString, advancedOrderRejectJson=""):
if errorCode in INFO_CODES:
self.info_codes.append(errorCode)
else:
self.errors_seen.append((reqId, errorCode, errorString))
app = RequestBulletinsApp()
try:
app.connect("127.0.0.1", 7497, clientId=130)
thread = threading.Thread(target=app.run, daemon=True)
thread.start()
if not app.ready.wait(8):
raise RuntimeError("等待 nextValidId 超时")
app.reqNewsBulletins(True)
callback_received = app.bulletin_ready.wait(6)
finally:
if app.isConnected():
app.cancelNewsBulletins()
app.disconnect()
print("ALL_MSGS=True")
print("REQUEST_SENT=True")
print(f"BULLETIN_CALLBACK_RECEIVED={callback_received}")
print(f"BULLETIN_ROW_COUNT={len(app.rows)}")
print("INFO_CODES=" + (",".join(map(str, sorted(set(app.info_codes)))) if app.info_codes else "NONE"))
print(f"NON_INFO_ERROR_COUNT={len(app.errors_seen)}")
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。请求后仍然应调用 cancelNewsBulletins(),让程序状态保持清楚。

不一定。公告不是固定会返回的数据源。判断请求链路是否异常,要结合连接状态、错误码和是否成功取消订阅。

allMsgs=True 会返回所有历史公告吗?

Section titled “allMsgs=True 会返回所有历史公告吗?”

不会。官方说明它返回当天已有公告和新的公告,不是长期历史公告查询。

不能。普通新闻标题、新闻文章和新闻提供商属于 News 目录下的接口,不是 Bulletins。