【问题标题】:How can I detect when an order fills using the Interactive Brokers Java API?如何使用 Interactive Brokers Java API 检测订单何时成交?
【发布时间】:2021-05-02 14:05:16
【问题描述】:

问题

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

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

我无法检测订单何时成交

documentation 描述了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
    ...
    */
}

我在此代码运行时手动下订单,并且订单完成得相当快(在代码运行时),所以代码应该检测到它,但是(我的问题 -->)没有正在调用回调。 我应该怎么做才能检测订单执行? (注意:我现在是在 TWS 中手动和代码下单)。

【问题讨论】:

  • 您在这些链接上对您不了解的内容的描述有点模糊。就目前而言,还不清楚要向您解释什么。
  • 在那张纸条上,您说文档描述了在事件发生时调用回调。但是,你刚才说它不起作用,这是什么意思?它不编译吗?是这样,但只是不调用回调?绝不?您是否在回调中放了一个 print ,从未调用过?您能否详细说明并显示您尝试的代码版本?
  • @Zabuzard 我已经编辑了我的问题,是否更有意义?
  • 如果您可以与您的尝试分享代码并更详细地详细说明正在发生的事情,这将有所帮助,正如解释的那样。
  • @Zabuzard 感谢您迄今为止的帮助。我已经修改了我的问题和代码,这样回答我的问题是否更有意义?

标签: java interactive-brokers


【解决方案1】:

这是有效的代码,我使用 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

【讨论】:

  • 看起来好像我没有电子阅读器来获取订单消息,这可能是没有调用回调的原因。现在可以使用了,谢谢!
  • 这就是为什么您应该使您的示例代码尽可能完整和可运行。我明白省略了所有的接口 impl。但看起来您只是将代码片段复制到问题中,因为它无法运行。另外,尽管您可以使用私有 m_ 字段,但有一个带有公共字段且没有 readerSignal 的早期 api 版本,因此它看起来像来自 2 个不兼容版本的代码。
猜你喜欢
  • 2022-11-28
  • 2020-01-26
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 2022-08-24
  • 1970-01-01
相关资源
最近更新 更多