Interactive Broker Java API获取有效orderId替代Thread.sleep的优雅方案咨询
优化实现方案
方案1:基于CountDownLatch实现阻塞等待(直接匹配需求)
第一步:修改EWrapperImpl实现
public class EWrapperImpl implements EWrapper { protected int currentOrderId = -1; // 新增用于同步等待的CountDownLatch private CountDownLatch orderIdLatch; public int getCurrentOrderId() { return currentOrderId; } public void nextValidId(int orderId) { System.out.println("Next Valid Id: ["+orderId+"]"); currentOrderId = orderId; // 回调收到id后,释放等待线程 if (orderIdLatch != null) { orderIdLatch.countDown(); } } // 新增阻塞获取orderId的方法,超时时间可自定义,避免无限等待 public int waitForValidOrderId(long timeoutMs) throws InterruptedException, TimeoutException { orderIdLatch = new CountDownLatch(1); boolean received = orderIdLatch.await(timeoutMs, TimeUnit.MILLISECONDS); if (!received) { throw new TimeoutException("等待orderId超时"); } return currentOrderId; } ... }
第二步:修改业务调用代码
// 下第一笔订单 ib_client.reqIds(-1); // 阻塞等待最多2秒获取id,比固定sleep更高效 int currentOrderId = ib_wrapper.waitForValidOrderId(2000); placeNewOrder(currentOrderId, orderDetails); // 下第二笔订单 ib_client.reqIds(-1); currentOrderId = ib_wrapper.waitForValidOrderId(2000); placeNewOrder(currentOrderId, orderDetails);
方案2:更高效率的优化(无需每次请求orderId)
根据IB官方API规则,你拿到第一个有效orderId后,后续的orderId只要按顺序+1就是合法的,不需要每次调用reqIds申请,可大幅简化逻辑:
// 程序初始化时只请求一次orderId ib_client.reqIds(-1); int currentOrderId = ib_wrapper.waitForValidOrderId(2000); // 后续下单直接复用id,每次自增即可 placeNewOrder(currentOrderId++, orderDetails); // 第一单 placeNewOrder(currentOrderId++, orderDetails); // 第二单 placeNewOrder(currentOrderId++, orderDetails); // 第三单 // ... 后续所有订单都可以直接自增使用
注意事项
- 若你的程序是多线程下单,需要对
currentOrderId的自增操作加锁,或者用AtomicInteger类型代替int保证线程安全 - 若触发了订单重复提交、连接断开重连的场景,需要重新调用
reqIds获取最新的有效orderId,避免id冲突
内容的提问来源于stack exchange,提问作者user1769197
相关产品推荐
相关产品推荐

