使用IB TWS API C#批量获取Level II数据触发309错误咨询
解决IB API Level II数据请求触发309错误的问题
问题原因
你遇到的309错误核心原因是:IB API的reqMarketDepth和cancelMktDepth是异步操作。在你的同步循环中,调用cancelMktDepth后,服务器并不会立即终止对应请求——它需要先处理取消指令,再通过updateMktDepthEnd回调通知客户端取消完成。而你的循环在极短时间内连续发送多个请求,此时前一个请求的取消操作还未生效,并发请求数直接突破了IB限制的3个上限,触发了错误。
解决方案
必须改用异步回调驱动的串行/可控并发处理,确保只有在当前请求的取消确认(或数据接收完成)后,再发起下一个标的的请求。以下是具体实现思路和代码示例:
1. 改用队列+回调的串行处理模式
维护一个待处理标的队列,每次在收到当前标的的updateMktDepthEnd回调后,再发起下一个请求:
// 存储待处理的标的队列 private Queue<string> _symbolQueue = new Queue<string>(); // 当前使用的ticker ID private int _currentTicker = 1; // 复用合约对象 private IBApi.Contract _contract = new IBApi.Contract(); // 初始化标的队列并启动第一个请求 public void StartMarketDepthRequests(string filePath) { // 读取所有标的到队列 foreach (var line in File.ReadLines(filePath)) { _symbolQueue.Enqueue(line); } // 发起第一个请求 ProcessNextSymbol(); } // 处理队列中的下一个标的 private void ProcessNextSymbol() { if (_symbolQueue.Count == 0) { // 所有标的处理完成 return; } var targetSymbol = _symbolQueue.Dequeue(); // 配置合约参数 _contract.Symbol = targetSymbol; _contract.SecType = "STK"; _contract.Exchange = "SMART"; _contract.Currency = "GBP"; // 发起市场深度请求 ibClient.ClientSocket.reqMarketDepth(_currentTicker, _contract, 5, true, new List<IBApi.TagValue>()); } // 重写IB API的updateMktDepthEnd回调(需继承EWrapper接口) public override void updateMktDepthEnd(int tickerId) { // 确认当前请求完成,执行取消操作 ibClient.ClientSocket.cancelMktDepth(tickerId, false); // 更新ticker ID _currentTicker++; // 处理下一个标的 ProcessNextSymbol(); }
2. 补充说明
- 若你的账户支持最多3个并发请求,也可以调整为同时发起3个请求,每个请求完成后补充新的,但串行处理是最稳妥的方式,避免触发限制。
- 必须确保正确实现IB API的
EWrapper接口,覆盖所有必要的回调方法,否则无法接收请求完成的通知。
内容的提问来源于stack exchange,提问作者Marc Jone
相关产品推荐
相关产品推荐

