使用IBApi reqWshEventData获取财报日期失败求助
问题排查与修复方案
问题根源拆解
你的脚本能正常连接TWS、拿到合约ID和WSH元数据,但就是触发不了wshEventData回调,主要问题出在这几个地方:
1. 请求参数不符合IB官方要求
IB文档明确规定,reqWshEventData不能只传conId或者只传过滤JSON,必须同时指定有效的conId和明确的过滤条件。你当前的两种请求方式都踩了坑:
- 只传conId+空过滤:TWS不知道你要抓什么类型的事件数据,直接忽略请求
- 只传过滤JSON+conId=0:没指定具体合约,TWS找不到对应的数据
2. 过滤JSON格式错误
你写的过滤条件有几个硬伤:
wsh_ed应该用布尔值true,不是字符串"true"limit_region是无效字段,IB文档里根本没有这个参数- 没在过滤条件里关联目标合约,得用
conids数组指定合约ID
3. 权限或TWS配置遗漏
- 确认TWS/IB Gateway的API设置里,已经勾选了
Allow WebSocket Socket Clients - 检查账户权限,部分账户类型可能没开放WSH事件数据的访问权限
修复后的完整代码
import json from ibapi.client import EClient from ibapi.wrapper import EWrapper from ibapi.contract import Contract import threading import time class IBApiApp(EWrapper, EClient): def __init__(self): EClient.__init__(self, self) self.contract_id = None self.metadata_received = False self.event_data_received = False def nextValidId(self, orderId: int): print("已连接IBKR,正在请求合约详情...") self.request_contract_details() def error(self, reqId: int, errorCode: int, errorString: str, advancedOrderRejectJson=""): print(f"错误. ReqId: {reqId}, 代码: {errorCode}, 信息: {errorString}") def contractDetails(self, reqId, contractDetails): self.contract_id = contractDetails.contract.conId print(f"获取到合约ID (conId): {self.contract_id}") def contractDetailsEnd(self, reqId): if self.contract_id: print("合约ID获取成功,正在请求WSH元数据...") self.request_wsh_metadata() else: print("未获取到合约ID,请检查API设置和权限。") self.disconnect() def wshMetaData(self, reqId: int, data: str): print(f"收到WSH元数据 (请求ID {reqId}): {data}") self.metadata_received = True # 修复:同时传入conId和正确的过滤JSON self.request_wsh_event_data() def wshEventData(self, reqId: int, dataJson: str): print(f"收到WSH事件数据 (请求ID {reqId}): {dataJson}") self.event_data_received = True # 解析数据,提取财报日期 data = json.loads(dataJson) if "events" in data: for event in data["events"]: if event.get("type") == "wshe_eps": print(f"财报发布日期: {event.get('date')}") def request_contract_details(self): contract = Contract() contract.symbol = "TSLA" contract.secType = "STK" contract.exchange = "SMART" contract.currency = "USD" self.reqContractDetails(1, contract) def request_wsh_metadata(self): if self.contract_id: print("正在请求WSH元数据...") self.reqWshMetaData(1) else: print("合约ID未设置,无法请求WSH元数据。") def request_wsh_event_data(self): """修复:同时传入conId和正确的过滤JSON""" filter_json = json.dumps({ "wsh_ed": True, # 用布尔值,不是字符串 "conids": [self.contract_id], # 指定目标合约ID "event_type": {"wshe_eps": True} # 明确要财报事件 }) print(f"请求WSH事件数据,过滤条件: {filter_json}") try: # 同时传有效的reqId、conId和过滤JSON self.reqWshEventData(2, self.contract_id, filter_json) except Exception as e: print(f"请求WSH事件数据出错: {e}") def run_loop(app): app.run() app = IBApiApp() # 注意:端口要和你的TWS/IB Gateway匹配,paper账户TWS默认7497,IB Gateway默认4002 app.connect("127.0.0.1", 4001, clientId=1) api_thread = threading.Thread(target=run_loop, args=(app,)) api_thread.start() metadata_timeout = 30 event_data_timeout = 30 start_time = time.time() while not app.metadata_received and time.time() - start_time < metadata_timeout: time.sleep(1) if app.metadata_received: start_time = time.time() while not app.event_data_received and time.time() - start_time < event_data_timeout: time.sleep(1) else: print("WSH元数据未在超时时间内收到。") if app.event_data_received: print("WSH事件数据获取成功。") else: print("WSH事件数据未找到或超时。") app.disconnect() api_thread.join()
额外注意点
- 端口核对:确保连接的端口和你的TWS/IB Gateway配置一致,别连错了
- 超时调整:财报数据可能有延迟,可适当调大
event_data_timeout的数值 - 错误排查:如果还是拿不到数据,仔细看
error回调的错误码,IB官方文档有每个错误码的具体说明
内容的提问来源于stack exchange,提问作者m.eder
相关产品推荐
相关产品推荐

