• C#
  • Java
  • VB
  • C++
  • Python
Contact us
Placing Orders

The Next Valid Identifier

Perhaps the most important event received after successfully connecting to the TWS is the IBApi.EWrapper.nextValidId, which is also triggered after invoking the IBApi.EClient.reqIds method. As its name indicates, the nextValidId event provides the next valid identifier needed to place an order. This identifier is nothing more than the next number in the sequence. This means that if there is a single client application submitting orders to an account, it does not have to obtain a new valid identifier every time it needs to submit a new order. It is enough to increase the last value received from the nextValidId method by one. For example, if the valid identifier for your first API order is 1, the next valid identifier would be 2 and so on.

However if there are multiple client applications connected to one account, it is necessary to use an order ID with new orders which is greater than all previous order IDs returned to the client application in openOrder or orderStatus callbacks. For instance, if the client is set as the Master client, it will automatically receive order status and trade callbacks from orders placed from other clients. In such a case, any orderID used in placeOrder must be greater than the orderIDs returned in these status callbacks. Alternatively if the function reqAllOpenOrders is used by a client, subsequent orders placed by that client must have order IDs greater than the order IDs of all orders returned because of that function call. You can always use the IBApi.EClient.reqIds method in the event that your client application loses track of the sequence.

  • //The parameter is always ignored.
    client.reqIds(-1);
  • //The parameter is always ignored.
    client.reqIds(-1);
  • 'The parameter Is always ignored.
    client.reqIds(-1)
  • //The parameter is always ignored.
    m_pClient->reqIds(-1);
  • 1  # The parameter is always ignored.
    2  self.reqIds(-1)

The above will result in IBApi.EWrapper.nextValidId callback being invoked:

  • public class EWrapperImpl : EWrapper
    {
    ...
    public virtual void nextValidId(int orderId)
    {
    Console.WriteLine("Next Valid Id: "+orderId);
    NextOrderId = orderId;
    }
  • public class EWrapperImpl implements EWrapper {
    ...
    @Override
    public void nextValidId(int orderId) {
    System.out.println(EWrapperMsgGenerator.nextValidId(orderId));
    currentOrderId = orderId;
    }
  • Public Class EWrapperImpl
    Implements EWrapper
    ...
    Public Sub nextValidId(orderId As Integer) Implements IBApi.EWrapper.nextValidId
    Console.WriteLine("NextValidId - OrderId [" & orderId & "]")
    nextOrderId = orderId
    End Sub
  • class TestCppClient : public EWrapper
    {
    ...
    void TestCppClient::nextValidId( OrderId orderId)
    {
    printf("Next Valid Id: %ld\n", orderId);
    m_orderId = orderId;
  • 1 class TestWrapper(wrapper.EWrapper):
    ...
    1  def nextValidId(self, orderId: int):
    2  super().nextValidId(orderId)
    3 
    4  logging.debug("setting nextValidOrderId: %d", orderId)
    5  self.nextValidOrderId = orderId
    6  print("NextValidId:", orderId)

The next valid identifier is persistent between TWS sessions.

If necessary, you can reset the order ID sequence within the API Settings dialogue. Note however that the order sequence Id can only be reset if there are no active API orders.

order_id_reset.png

Placing Orders

Orders are submitted via the IBApi.EClient.placeOrder method. From the snippet below, note how a variable holding the nextValidId is incremented automatically:

  • client.placeOrder(nextOrderId++, ContractSamples.USStock(), OrderSamples.TrailingStopLimit("BUY", 1, 5, 5, 110));
  • client.placeOrder(nextOrderId++, ContractSamples.USStock(), OrderSamples.LimitOrder("SELL", Decimal.ONE, 50));
  • client.placeOrder(increment(nextOrderId), ContractSamples.USStock(), OrderSamples.LimitOrder("SELL", 1, 50))
  • m_pClient->placeOrder(m_orderId++, ContractSamples::USStock(), OrderSamples::LimitOrder("SELL", DecimalFunctions::stringToDecimal("1"), 50));
  • 1  self.simplePlaceOid = self.nextOrderId()
    2  self.placeOrder(self.simplePlaceOid, ContractSamples.USStock(),
    3  OrderSamples.LimitOrder("SELL", 1, 50))

Immediately after the order was submitted correctly, the TWS will start sending events concerning the order's activity via IBApi.EWrapper.openOrder and IBApi.EWrapper.orderStatus

  • Advisors executing allocation orders will receive execution details and commissions for the allocation order itself. To receive allocation details and commissions for a specific subaccount IBApi.EClient.reqExecutions can be used.
  • An order can be sent to TWS but not transmitted to the IB server by setting the IBApi.Order.Transmit flag in the order class to False. Untransmitted orders will only be available within that TWS session (not for other usernames) and will be cleared on restart. Also, they can be cancelled or transmitted from the API but not viewed while they remain in the "untransmitted" state.

Advanced order rejection

With TWS 10.14 and TWS API 10.14 there have been added IBApi.Order advancedErrorOverride and IBApi.EWrapper.error advancedOrderRejectJson properties. They have been introduced to extend Cryptocurrency offerings across other regions.

  • advancedErrorOverride accepts a comma-separated list with parameters containing error tags. This list will override the mentioned errors and proceed with the order placement.
  • advancedOrderRejectJson returns order reject description in JSON format. The JSON responses can be used to add fields to advancedErrorOverride.
    The response your API client will receive from our back end via reject message will contain a FIX Tag 8230. This FIX Tag is for order rejection message.
    For example, the response will contain code 8229=IBDBUYTX which can be passed in 8229 (advancedErrorOverride) field in IBApi::EClient::placeOrder method.
    The tag values of 8229 can contain a comma-separated list of advanced error override codes. For example, 8229=IBDBUYTX,MOBILEPH, will override both of the rejections.
  • Additionally, a new API Setting has been introduced: Show advanced order reject in UI always
    If checked, the order reject will not be sent to API.

The openOrder callback

The IBApi.EWrapper.openOrder method delivers an IBApi.Order object representing an open order within the system. In addition, IBApi.EWrapper.openOrder returns an an IBApi.OrderState object that is used to return estimated pre-trade margin and commission information in response to invoking IBApi.EClient.placeOrder with a IBApi.Order object that has the flag IBApi.Order.WhatIf flag set to True. See also: Checking Margin Changes.

  • public class EWrapperImpl : EWrapper
    {
    ...
    public virtual void openOrder(int orderId, Contract contract, Order order, OrderState orderState)
    {
    Console.WriteLine("OpenOrder. PermID: " + Util.IntMaxString(order.PermId) + ", ClientId: " + Util.IntMaxString(order.ClientId) + ", OrderId: " + Util.IntMaxString(orderId) +
    ", Account: " + order.Account + ", Symbol: " + contract.Symbol + ", SecType: " + contract.SecType + " , Exchange: " + contract.Exchange + ", Action: " + order.Action +
    ", OrderType: " + order.OrderType + ", TotalQty: " + Util.DecimalMaxString(order.TotalQuantity) + ", CashQty: " + Util.DoubleMaxString(order.CashQty) +
    ", LmtPrice: " + Util.DoubleMaxString(order.LmtPrice) + ", AuxPrice: " + Util.DoubleMaxString(order.AuxPrice) + ", Status: " + orderState.Status +
    ", MinTradeQty: " + Util.IntMaxString(order.MinTradeQty) + ", MinCompeteSize: " + Util.IntMaxString(order.MinCompeteSize) +
    ", CompeteAgainstBestOffset: " + (order.CompeteAgainstBestOffset == Order.COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID ? "UpToMid" : Util.DoubleMaxString(order.CompeteAgainstBestOffset)) +
    ", MidOffsetAtWhole: " + Util.DoubleMaxString(order.MidOffsetAtWhole) + ", MidOffsetAtHalf: " + Util.DoubleMaxString(order.MidOffsetAtHalf) +
    ", FAGroup: " + order.FaGroup + ", FAMethod: " + order.FaMethod);
    }
  • public class EWrapperImpl implements EWrapper {
    ...
    @Override
    public void openOrder(int orderId, Contract contract, Order order, OrderState orderState) {
    System.out.println(EWrapperMsgGenerator.openOrder(orderId, contract, order, orderState));
    }
  • Public Class EWrapperImpl
    Implements EWrapper
    ...
    Public Sub openOrder(orderId As Integer, contract As IBApi.Contract, order As IBApi.Order, orderState As IBApi.OrderState) Implements IBApi.EWrapper.openOrder
    Console.WriteLine("OpenOrder. PermID: " & Util.IntMaxString(order.PermId) & ", ClientId: " & Util.IntMaxString(order.ClientId) & ", OrderId: " & Util.IntMaxString(orderId) &
    ", Account: " & order.Account & ", Symbol: " & contract.Symbol & ", SecType: " & contract.SecType & " , Exchange: " & contract.Exchange & ", Action: " & order.Action &
    ", OrderType: " & order.OrderType & ", TotalQty: " & Util.DecimalMaxString(order.TotalQuantity) & ", CashQty: " & Util.DoubleMaxString(order.CashQty) & ", LmtPrice: " &
    Util.DoubleMaxString(order.LmtPrice) & ", AuxPrice: " & Util.DoubleMaxString(order.AuxPrice) & ", Status: " & orderState.Status &
    ", MinTradeQty: " & Util.IntMaxString(order.MinTradeQty) & ", MinCompeteSize: " & Util.IntMaxString(order.MinCompeteSize) &
    ", CompeteAgainstBestOffset: " & If(order.CompeteAgainstBestOffset = Order.COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID, "UpToMid", Util.DoubleMaxString(order.CompeteAgainstBestOffset)) &
    ", MidOffsetAtWhole: " & Util.DoubleMaxString(order.MidOffsetAtWhole) & ", MidOffsetAtHalf: " & Util.DoubleMaxString(order.MidOffsetAtHalf) &
    ", FAGroup: " & order.FaGroup & ", FAMethod: " & order.FaMethod)
    End Sub
  • class TestCppClient : public EWrapper
    {
    ...
    void TestCppClient::openOrder( OrderId orderId, const Contract& contract, const Order& order, const OrderState& orderState) {
    printf( "OpenOrder. PermId: %s, ClientId: %s, OrderId: %s, Account: %s, Symbol: %s, SecType: %s, Exchange: %s:, Action: %s, OrderType:%s, TotalQty: %s, CashQty: %s, "
    "LmtPrice: %s, AuxPrice: %s, Status: %s, MinTradeQty: %s, MinCompeteSize: %s, CompeteAgainstBestOffset: %s, MidOffsetAtWhole: %s, MidOffsetAtHalf: %s, "
    "FAGroup: %s, FAMethod: %s\n",
    Utils::intMaxString(order.permId).c_str(), Utils::longMaxString(order.clientId).c_str(), Utils::longMaxString(orderId).c_str(), order.account.c_str(), contract.symbol.c_str(),
    contract.secType.c_str(), contract.exchange.c_str(), order.action.c_str(), order.orderType.c_str(), DecimalFunctions::decimalStringToDisplay(order.totalQuantity).c_str(),
    Utils::doubleMaxString(order.cashQty).c_str(), Utils::doubleMaxString(order.lmtPrice).c_str(), Utils::doubleMaxString(order.auxPrice).c_str(), orderState.status.c_str(),
    Utils::intMaxString(order.minTradeQty).c_str(), Utils::intMaxString(order.minCompeteSize).c_str(),
    order.competeAgainstBestOffset == COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID ? "UpToMid" : Utils::doubleMaxString(order.competeAgainstBestOffset).c_str(),
    Utils::doubleMaxString(order.midOffsetAtWhole).c_str(), Utils::doubleMaxString(order.midOffsetAtHalf).c_str(),
    order.faGroup.c_str(), order.faMethod.c_str());
    }
  • 1 class TestWrapper(wrapper.EWrapper):
    ...
    1  def openOrder(self, orderId: OrderId, contract: Contract, order: Order,
    2  orderState: OrderState):
    3  super().openOrder(orderId, contract, order, orderState)
    4  print("OpenOrder. PermId:", intMaxString(order.permId), "ClientId:", intMaxString(order.clientId), " OrderId:", intMaxString(orderId),
    5  "Account:", order.account, "Symbol:", contract.symbol, "SecType:", contract.secType,
    6  "Exchange:", contract.exchange, "Action:", order.action, "OrderType:", order.orderType,
    7  "TotalQty:", decimalMaxString(order.totalQuantity), "CashQty:", floatMaxString(order.cashQty),
    8  "LmtPrice:", floatMaxString(order.lmtPrice), "AuxPrice:", floatMaxString(order.auxPrice), "Status:", orderState.status,
    9  "MinTradeQty:", intMaxString(order.minTradeQty), "MinCompeteSize:", intMaxString(order.minCompeteSize),
    10  "competeAgainstBestOffset:", "UpToMid" if order.competeAgainstBestOffset == COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID else floatMaxString(order.competeAgainstBestOffset),
    11  "MidOffsetAtWhole:", floatMaxString(order.midOffsetAtWhole),"MidOffsetAtHalf:" ,floatMaxString(order.midOffsetAtHalf),
    12  "FAGroup:", order.faGroup, "FAMethod:", order.faMethod)
    13 
    14  order.contract = contract
    15  self.permId2ord[order.permId] = order

The orderStatus callback

The IBApi.EWrapper.orderStatus method contains all relevant information on the current status of the order execution-wise (i.e. amount filled and pending, filling price, etc.).

  • public class EWrapperImpl : EWrapper
    {
    ...
    public virtual void orderStatus(int orderId, string status, decimal filled, decimal remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, string whyHeld, double mktCapPrice)
    {
    Console.WriteLine("OrderStatus. Id: " + orderId + ", Status: " + status + ", Filled: " + Util.DecimalMaxString(filled) + ", Remaining: " + Util.DecimalMaxString(remaining)
    + ", AvgFillPrice: " + Util.DoubleMaxString(avgFillPrice) + ", PermId: " + Util.IntMaxString(permId) + ", ParentId: " + Util.IntMaxString(parentId) +
    ", LastFillPrice: " + Util.DoubleMaxString(lastFillPrice) + ", ClientId: " + Util.IntMaxString(clientId) + ", WhyHeld: " + whyHeld + ", MktCapPrice: " + Util.DoubleMaxString(mktCapPrice));
    }
  • public class EWrapperImpl implements EWrapper {
    ...
    @Override
    public void orderStatus(int orderId, String status, Decimal filled, Decimal remaining, double avgFillPrice, int permId, int parentId,
    double lastFillPrice, int clientId, String whyHeld, double mktCapPrice) {
    System.out.println(EWrapperMsgGenerator.orderStatus( orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice));
    }
  • Public Class EWrapperImpl
    Implements EWrapper
    ...
    Public Sub orderStatus(orderId As Integer, status As String, filled As Decimal, remaining As Decimal, avgFillPrice As Double, permId As Integer, parentId As Integer, lastFillPrice As Double, clientId As Integer, whyHeld As String, mktCapPrice As Double) Implements IBApi.EWrapper.orderStatus
    Console.WriteLine("OrderStatus. Id: " & orderId & ", Status: " & status & ", Filled: " & Util.DecimalMaxString(filled) & ", Remaining: " & Util.DecimalMaxString(remaining) &
    ", AvgFillPrice: " & Util.DoubleMaxString(avgFillPrice) & ", PermId: " & Util.IntMaxString(permId) & ", ParentId: " & Util.IntMaxString(parentId) &
    ", LastFillPrice: " & Util.DoubleMaxString(lastFillPrice) & ", ClientId: " & Util.IntMaxString(clientId) & ", WhyHeld: " & whyHeld & ", mktCapPrice: " & Util.DoubleMaxString(mktCapPrice))
    End Sub
  • class TestCppClient : public EWrapper
    {
    ...
    void TestCppClient::orderStatus(OrderId orderId, const std::string& status, Decimal filled,
    Decimal remaining, double avgFillPrice, int permId, int parentId,
    double lastFillPrice, int clientId, const std::string& whyHeld, double mktCapPrice){
    printf("OrderStatus. Id: %ld, Status: %s, Filled: %s, Remaining: %s, AvgFillPrice: %s, PermId: %s, LastFillPrice: %s, ClientId: %s, WhyHeld: %s, MktCapPrice: %s\n",
    orderId, status.c_str(), DecimalFunctions::decimalStringToDisplay(filled).c_str(), DecimalFunctions::decimalStringToDisplay(remaining).c_str(), Utils::doubleMaxString(avgFillPrice).c_str(), Utils::intMaxString(permId).c_str(),
    Utils::doubleMaxString(lastFillPrice).c_str(), Utils::intMaxString(clientId).c_str(), whyHeld.c_str(), Utils::doubleMaxString(mktCapPrice).c_str());
    }
  • 1 class TestWrapper(wrapper.EWrapper):
    ...
    1  def orderStatus(self, orderId: OrderId, status: str, filled: Decimal,
    2  remaining: Decimal, avgFillPrice: float, permId: int,
    3  parentId: int, lastFillPrice: float, clientId: int,
    4  whyHeld: str, mktCapPrice: float):
    5  super().orderStatus(orderId, status, filled, remaining,
    6  avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice)
    7  print("OrderStatus. Id:", orderId, "Status:", status, "Filled:", decimalMaxString(filled),
    8  "Remaining:", decimalMaxString(remaining), "AvgFillPrice:", floatMaxString(avgFillPrice),
    9  "PermId:", intMaxString(permId), "ParentId:", intMaxString(parentId), "LastFillPrice:",
    10  floatMaxString(lastFillPrice), "ClientId:", intMaxString(clientId), "WhyHeld:",
    11  whyHeld, "MktCapPrice:", floatMaxString(mktCapPrice))

Automatic Order Status Messages (without invoking reqOpenOrders or reqAllOpenOrders)

  • Clients with the ID of the client submitting the order will receive order status messages indicating changes in the order status.
  • The client with Master Client ID (set in TWS/IBG) will receive order status messages for all clients.
  • Client ID 0 will receive order status messages for its own (client ID 0) orders and also for orders submitted manually from TWS.

Possible Order States

  • ApiPending - indicates order has not yet been sent to IB server, for instance if there is a delay in receiving the security definition. Uncommonly received.
  • PendingSubmit - indicates the order was sent from TWS, but confirmation has not been received that it has been received by the destination. Most commonly because exchange is closed.
  • PendingCancel - indicates that a request has been sent to cancel an order but confirmation has not been received of its cancellation.
  • PreSubmitted - indicates that a simulated order type has been accepted by the IB system and that this order has yet to be elected. The order is held in the IB system until the election criteria are met. At that time the order is transmitted to the order destination as specified.
  • Submitted - indicates that your order has been accepted at the order destination and is working.
  • ApiCancelled - after an order has been submitted and before it has been acknowledged, an API client can request its cancellation, producing this state.
  • Cancelled - indicates that the balance of your order has been confirmed cancelled by the IB system. This could occur unexpectedly when IB or the destination has rejected your order. For example, if your order is subject to price checks, it could be cancelled, as explained in Order Placement Considerations
  • Filled - indicates that the order has been completely filled.
  • Inactive - indicates an order is not working, possible reasons include:
    • it is invalid or triggered an error. A corresponding error code is expected to the error() function.
    • the order is to short shares but the order is being held while shares are being located.
    • an order is placed manually in TWS while the exchange is closed.
    • an order is blocked by TWS due to a precautionary setting and appears there in an untransmitted state

Important notes concerning IBApi.EWrapper.orderStatus :

  • Typically there are duplicate orderStatus messages with the same information that will be received by a client. This corresponds to messages sent back from TWS, the IB server, or the exchange.
  • There are not guaranteed to be orderStatus callbacks for every change in order status. For example with market orders when the order is accepted and executes immediately, there commonly will not be any corresponding orderStatus callbacks. For that reason it is recommended to monitor the IBApi.EWrapper.execDetails function in addition to IBApi.EWrapper.orderStatus.
  • Beginning in API v973.04, a parameter mktCapPrice is included in the orderStatus callback. If an order has been price-capped, mktCapPrice will indicate the price at which it has been capped.

Attaching Orders

Advanced orders such as Bracket Orders or Hedging involve attaching child orders to a parent. This can be easily done via the IBApi.Order.ParentId attribute by assigning a child order's IBApi.Order.ParentId to an existing order's IBApi.Order.OrderId. When an order is attached to another, the system will keep the child order 'on hold' until its parent fills. Once the parent order is completely filled, its children will automatically become active.

Important: When attaching orders and to prevent accidental executions it is a very good idea to make use of the IBApi.Order.Transmit flag as demonstrated in Bracket Orders