我如何使用 Interactive Brokers Java API 检测订单何时成交?

How can I detect when an order fills using the Interactive Brokers Java API?

问题

IBKR TWS(交易者工作站)是 Interactive Brokers 用于管理股票市场股票订单的工具。他们提供 API 来自动执行订单,例如下订单、取消订单等。

我正在使用 Interactive Brokers Java [=48= 创建一个程序来 在我的 Trader Workstation 中处理已执行的订单 ].

我在检测订单何时成交时遇到问题

documentation describes that the execDetails 回调(这是一个 EWrapper 方法,见下面的代码)在订单完成时被调用,但我尝试使用它并且 execDetails 回调从未被调用(我通过记录reqid int 在那个回调中,我从来没有得到任何日志)。

我还研究了 completedOrder 回调,我不确定这是否是订单成交时将调用的回调,因为我用一个简单的日志测试了这两个回调,但没有正在控制台输出。

我不明白 reqExecutions 功能以及我是否需要它。我已经阅读了有关此回调的文档,但我不明白我做错了什么。我想知道我如何使用他们的 API.

检测订单何时填充或在 TWS 中执行

代码

这是我当前的代码:

import com.ib.client.*;

import java.util.*;

public class Main implements EWrapper {
    private static EClientSocket clientSocket;
    private static EJavaSignal readerSignal;

    public static void main(String[] args) throws InterruptedException, IOException {
        readerSignal = new EJavaSignal();
        clientSocket = new EClientSocket(this, readerSignal);
        clientSocket.eConnect("127.0.0.1", 7497, 0);
    }
    
    clientSocket.placeOrder(orderidE, contractFill("CUSIP", "USD", tickSymbol, "STK", "SMART"), orderFill(lmtPriceDouble, actionString, "LMT", "GTC", orderQuantity, account,  0));
    //Order executes successfully after sometime
    public static Order orderFill(double lmtPrice, String action, String orderType, String tif, int totalQuantity, String account, int clientId){
        Order order = new Order();
        order.m_lmtPrice = lmtPrice;
        order.m_action = action;
        order.m_orderType = orderType;
        order.m_tif = tif;
        order.m_totalQuantity = totalQuantity;
        order.m_account = account;
        order.m_clientId = clientId;
        return order;
    }
    public static Contract contractFill(String secIdType, String currency, String symbol, String secType, String exchange){
        Contract contract = new Contract();
        contract.m_secIdType = secIdType;
        contract.m_currency = currency;
        contract.m_symbol = symbol;
        contract.m_secType = secType;
        contract.m_exchange = exchange;
        return contract;
    }
    /*Implemented EWrapper methods
    ...
    */
    @Override
    public void execDetails(int reqId, Contract contract, Execution execution) {
        System.out.println(execution + " " + contract + " " + reqId);
    }

    @Override
    public void execDetailsEnd(int reqId) {
        System.out.println(reqId);
    }
    /*Implemented EWrapper methods
    ...
    */
    @Override
    public void completedOrder(Contract contract, Order order, OrderState orderState) {
        System.out.println(contract);
        System.out.println(order);
        System.out.println(orderState);
    }
    @Override
    public void completedOrdersEnd() {
        System.out.println("cOE");
    }/*Implemented rest of EWrapper methods
    ...
    */
}

我在代码为 运行 时手动下单,订单成交相当快(代码为 运行),因此代码应检测到它,但是(我的问题 -->)none 的回调被调用。 我应该做什么来检测订单执行情况? (注意:我现在在 TWS 中手动和代码下订单)。

这是有效的代码,我用 api 9.81.

测试过

请注意,如果您使用的是 clientID 0,那么您还应该从 TWS 中的交易地点获得回调。我从未尝试过,但文档很清楚。

import com.ib.client.*;
import java.io.IOException;

import java.util.*;

public class MainIB implements EWrapper {
    private EClientSocket clientSocket;
    private EJavaSignal readerSignal;
    
    public static void main(String[] args) throws IOException {
        new MainIB().connect();
        System.in.read();//press enter to exit
        System.exit(0);
    }
    
    private void connect() {
        readerSignal = new EJavaSignal();
        clientSocket = new EClientSocket(this, readerSignal);
        clientSocket.eConnect("127.0.0.1", 7497, 0);
        //Create a reader to consume messages from the TWS. The EReader will consume the incoming messages and put them in a queue
        EReader reader = new EReader(clientSocket, readerSignal);
        reader.start();
        //Once the messages are in the queue, an additional thread can be created to fetch them
        Thread processer = new Thread(() -> {
            while ( clientSocket.isConnected() ) { 
                readerSignal.waitForSignal();
                try {
                    reader.processMsgs();
                } catch (IOException ex) {}
            }
        });
        processer.setDaemon(true);
        processer.start();
    }
    
    public Order orderFill(double lmtPrice, String action, String orderType, String tif, int totalQuantity, String account, int clientId){
        Order order = new Order();
        order.lmtPrice(lmtPrice);
        order.action(action);
        order.orderType(orderType);
        order.tif(tif);
        order.totalQuantity(totalQuantity);
        //order.account(account);
        //order.clientId(clientId);
        return order;
    }
    public Contract contractFill(String secIdType, String currency, String symbol, String secType, String exchange){
        Contract contract = new Contract();
        //contract.secIdType(secIdType);
        contract.currency(currency);
        contract.symbol(symbol);
        contract.secType(secType);
        contract.exchange(exchange);
        return contract;
    }

    @Override
    public void error(int id, int errorCode, String errorMsg) {
        System.out.println(errorCode + " " + errorMsg);
    }

    @Override
    public void nextValidId(int i) {
        int orderidE = i;
        clientSocket.placeOrder(orderidE++, contractFill("", "CAD", "USD", "CASH", "IDEALPRO"), 
                                          orderFill(0, "SELL", "MKT", "GTC", 100000, "",  0));
    }

    @Override
    public void orderStatus(int i, String status, double d, double d1, double d2, int i1, int i2, double d3, int i3, String string1, double d4) {
        System.out.println("status " + status);
    }

    @Override
    public void execDetails(int reqId, Contract contract, Execution execution) {
        System.out.println(execution + " " + contract + " " + reqId);
    }
    
    /*Implemented rest of EWrapper methods
    ...
    */
}

这是我的 api.Day.0.log 文件

的一部分
t:ms <-> msg#                        #  desc  
9:064 -> 15-1-DU123456-              15 my account #
9:065 -> 9-1-2-                      9 next valid id
9:065 -> 4-2--1-2104-Market da       4 errors(or info) 
9:065 -> 4-2--1-2104-Market da
9:072 <- 3-45-2-0-USD-CASH--0.       <- 3 means an order I sent   
9:671 -> 5-34-2-15016062-USD-C       5 order status
9:722 -> 11--1-2-15016062-USD-       11 exec 
9:724 -> 5-34-2-15016062-USD-C       more status
9:727 -> 5-34-2-15016062-USD-C
9:728 -> 59-1-0000e215.60b94f1       59 commission report