Reputation: 140
The IBKR TWS (Trader Workstation) is a tool for managing stock orders in the stock market, by Interactive Brokers. They provide an API to automate orders, like placing orders, cancelling orders, and more.
I'm creating a program to handle executed orders in my Trader Workstation using the Interactive Brokers Java API.
I'm having trouble detecting when an order fills.
The documentation describes that the execDetails callback (which is an EWrapper method, see code below) is invoked when an order is filled, but I tried using that and the execDetails callback was never invoked (I tested this by logging the reqid int in that callback, and I never got any log).
I have also researched about the completedOrder callback, which I'm not sure if that's the callback that will be invoked when an order is filled, because I tested both callbacks with a simple log, and nothing was outputting in the console.
I don't understand the reqExecutions function and whether I need that. I have already read the documentation on this callback, and I don't understand what I'm doing wrong. I want to know I how can detect when an order fills, or executes in the TWS using their API.
Here is my current code:
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
...
*/
}
I am placing the orders by hand while this code is running, and the order fills fairly quickly (while the code is running), so the code should detect it, but (my problem -->)none of the callbacks are being invoked. What am I supposed to be doing to detect order executions? (Note: I'm placing the orders by hand and by code in the TWS as of now).
Upvotes: 4
Views: 2297
Reputation: 10989
Here is code that works, I tested with api 9.81.
Note that if you're using clientID 0 then you should also get callbacks from trades place in TWS. I've never tried, but the docs are clear.
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
...
*/
}
Here is bit of my api.Day.0.log file
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
Upvotes: 3