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

Bracket Orders are designed to help limit your loss and lock in a profit by "bracketing" an order with two opposite-side orders. A BUY order is bracketed by a high-side sell limit order and a low-side sell stop order. A SELL order is bracketed by a high-side buy stop order and a low side buy limit order. Note how bracket orders make use of the TWS API's Attaching Orders mechanism.

One key thing to keep in mind is to handle the order transmission accurately. Since a Bracket consists of three orders, there is always a risk that at least one of the orders gets filled before the entire bracket is sent. To avoid it, make use of the IBApi.Order.Transmit flag. When this flag is set to 'false', the TWS will receive the order but it will not send (transmit) it to the servers. In the example below, the first (parent) and second (takeProfit) orders will be send to the TWS but not transmitted to the servers. When the last child order (stopLoss) is sent however and given that its IBApi.Order.Transmit flag is set to true, the TWS will interpret this as a signal to transmit not only its parent order but also the rest of siblings, removing the risks of an accidental execution.

  • public static List<Order> BracketOrder(int parentOrderId, string action, decimal quantity, double limitPrice,
    double takeProfitLimitPrice, double stopLossPrice)
    {
    //This will be our main or "parent" order
    Order parent = new Order();
    parent.OrderId = parentOrderId;
    parent.Action = action;
    parent.OrderType = "LMT";
    parent.TotalQuantity = quantity;
    parent.LmtPrice = limitPrice;
    //The parent and children orders will need this attribute set to false to prevent accidental executions.
    //The LAST CHILD will have it set to true,
    parent.Transmit = false;
    Order takeProfit = new Order();
    takeProfit.OrderId = parent.OrderId + 1;
    takeProfit.Action = action.Equals("BUY") ? "SELL" : "BUY";
    takeProfit.OrderType = "LMT";
    takeProfit.TotalQuantity = quantity;
    takeProfit.LmtPrice = takeProfitLimitPrice;
    takeProfit.ParentId = parentOrderId;
    takeProfit.Transmit = false;
    Order stopLoss = new Order();
    stopLoss.OrderId = parent.OrderId + 2;
    stopLoss.Action = action.Equals("BUY") ? "SELL" : "BUY";
    stopLoss.OrderType = "STP";
    //Stop trigger price
    stopLoss.AuxPrice = stopLossPrice;
    stopLoss.TotalQuantity = quantity;
    stopLoss.ParentId = parentOrderId;
    //In this case, the low side order will be the last child being sent. Therefore, it needs to set this attribute to true
    //to activate all its predecessors
    stopLoss.Transmit = true;
    List<Order> bracketOrder = new List<Order>();
    bracketOrder.Add(parent);
    bracketOrder.Add(takeProfit);
    bracketOrder.Add(stopLoss);
    return bracketOrder;
    }
    ...
    List<Order> bracket = OrderSamples.BracketOrder(nextOrderId++, "BUY", 100, 30, 40, 20);
    foreach (Order o in bracket)
    client.placeOrder(o.OrderId, ContractSamples.EuropeanStock(), o);
  • public static List<Order> BracketOrder(int parentOrderId, String action, Decimal quantity, double limitPrice, double takeProfitLimitPrice, double stopLossPrice) {
    //This will be our main or "parent" order
    Order parent = new Order();
    parent.orderId(parentOrderId);
    parent.action(action);
    parent.orderType("LMT");
    parent.totalQuantity(quantity);
    parent.lmtPrice(limitPrice);
    //The parent and children orders will need this attribute set to false to prevent accidental executions.
    //The LAST CHILD will have it set to true.
    parent.transmit(false);
    Order takeProfit = new Order();
    takeProfit.orderId(parent.orderId() + 1);
    takeProfit.action(action.equals("BUY") ? "SELL" : "BUY");
    takeProfit.orderType("LMT");
    takeProfit.totalQuantity(quantity);
    takeProfit.lmtPrice(takeProfitLimitPrice);
    takeProfit.parentId(parentOrderId);
    takeProfit.transmit(false);
    Order stopLoss = new Order();
    stopLoss.orderId(parent.orderId() + 2);
    stopLoss.action(action.equals("BUY") ? "SELL" : "BUY");
    stopLoss.orderType("STP");
    //Stop trigger price
    stopLoss.auxPrice(stopLossPrice);
    stopLoss.totalQuantity(quantity);
    stopLoss.parentId(parentOrderId);
    //In this case, the low side order will be the last child being sent. Therefore, it needs to set this attribute to true
    //to activate all its predecessors
    stopLoss.transmit(true);
    List<Order> bracketOrder = new ArrayList<>();
    bracketOrder.add(parent);
    bracketOrder.add(takeProfit);
    bracketOrder.add(stopLoss);
    return bracketOrder;
    }
    ...
    List<Order> bracket = OrderSamples.BracketOrder(nextOrderId++, "BUY", Decimal.ONE_HUNDRED, 30, 40, 20);
    for(Order o : bracket) {
    client.placeOrder(o.orderId(), ContractSamples.EuropeanStock(), o);
    }
  • 'This will be our main Or "parent" order
    Dim parent As Order = New Order
    parent.OrderId = parentOrderId
    parent.Action = action
    parent.OrderType = "LMT"
    parent.TotalQuantity = quantity
    parent.LmtPrice = limitPrice
    'The parent And children orders will need this attribute set to false to prevent accidental executions.
    'The LAST CHILD will have it set to true,
    parent.Transmit = False
    Dim takeProfit As Order = New Order
    '
    takeProfit.OrderId = parent.OrderId + 1
    If action.Equals("BUY") Then takeProfit.Action = "SELL" Else takeProfit.Action = "BUY"
    takeProfit.OrderType = "LMT"
    takeProfit.TotalQuantity = quantity
    takeProfit.LmtPrice = takeProfitLimitPrice
    takeProfit.ParentId = parentOrderId
    takeProfit.Transmit = False
    Dim stopLoss As Order = New Order
    stopLoss.OrderId = parent.OrderId + 2
    If action.Equals("BUY") Then stopLoss.Action = "SELL" Else stopLoss.Action = "BUY"
    stopLoss.OrderType = "STP"
    'Stop trigger price
    stopLoss.AuxPrice = stopLossPrice
    stopLoss.TotalQuantity = quantity
    stopLoss.ParentId = parentOrderId
    'In this case, the low side order will be the last child being sent. Therefore, it needs to set this attribute to true
    'to activate all its predecessors
    stopLoss.Transmit = True
    Dim orders As List(Of Order) = New List(Of Order)
    orders.Add(parent)
    orders.Add(takeProfit)
    orders.Add(stopLoss)
    ...
    Dim bracket As List(Of Order) = OrderSamples.BracketOrder(increment(nextOrderId), "BUY", 100, 30, 40, 20)
    For Each o As Order In bracket
    client.placeOrder(o.OrderId, ContractSamples.EuropeanStock(), o)
    Next
  • void OrderSamples::BracketOrder(int parentOrderId, Order& parent, Order& takeProfit, Order& stopLoss, std::string action, Decimal quantity, double limitPrice, double takeProfitLimitPrice, double stopLossPrice){
    //This will be our main or "parent" order
    parent.orderId = parentOrderId;
    parent.action = action;
    parent.orderType = "LMT";
    parent.totalQuantity = quantity;
    parent.lmtPrice = limitPrice;
    //The parent and children orders will need this attribute set to false to prevent accidental executions.
    //The LAST CHILD will have it set to true,
    parent.transmit = false;
    takeProfit.orderId = parent.orderId + 1;
    takeProfit.action = (action == "BUY") ? "SELL" : "BUY";
    takeProfit.orderType = "LMT";
    takeProfit.totalQuantity = quantity;
    takeProfit.lmtPrice = takeProfitLimitPrice;
    takeProfit.parentId = parentOrderId;
    takeProfit.transmit = false;
    stopLoss.orderId = parent.orderId + 2;
    stopLoss.action = (action == "BUY") ? "SELL" : "BUY";
    stopLoss.orderType = "STP";
    //Stop trigger price
    stopLoss.auxPrice = stopLossPrice;
    stopLoss.totalQuantity = quantity;
    stopLoss.parentId = parentOrderId;
    //In this case, the low side order will be the last child being sent. Therefore, it needs to set this attribute to true
    //to activate all its predecessors
    stopLoss.transmit = true;
    }
    ...
    OrderSamples::BracketOrder(m_orderId++, parent, takeProfit, stopLoss, "BUY", DecimalFunctions::stringToDecimal("100"), 30, 40, 20);
    m_pClient->placeOrder(parent.orderId, ContractSamples::EuropeanStock(), parent);
    m_pClient->placeOrder(takeProfit.orderId, ContractSamples::EuropeanStock(), takeProfit);
    m_pClient->placeOrder(stopLoss.orderId, ContractSamples::EuropeanStock(), stopLoss);
  • 1  @staticmethod
    2  def BracketOrder(parentOrderId:int, action:str, quantity:Decimal,
    3  limitPrice:float, takeProfitLimitPrice:float,
    4  stopLossPrice:float):
    5 
    6  #This will be our main or "parent" order
    7  parent = Order()
    8  parent.orderId = parentOrderId
    9  parent.action = action
    10  parent.orderType = "LMT"
    11  parent.totalQuantity = quantity
    12  parent.lmtPrice = limitPrice
    13  #The parent and children orders will need this attribute set to False to prevent accidental executions.
    14  #The LAST CHILD will have it set to True,
    15  parent.transmit = False
    16 
    17  takeProfit = Order()
    18  takeProfit.orderId = parent.orderId + 1
    19  takeProfit.action = "SELL" if action == "BUY" else "BUY"
    20  takeProfit.orderType = "LMT"
    21  takeProfit.totalQuantity = quantity
    22  takeProfit.lmtPrice = takeProfitLimitPrice
    23  takeProfit.parentId = parentOrderId
    24  takeProfit.transmit = False
    25 
    26  stopLoss = Order()
    27  stopLoss.orderId = parent.orderId + 2
    28  stopLoss.action = "SELL" if action == "BUY" else "BUY"
    29  stopLoss.orderType = "STP"
    30  #Stop trigger price
    31  stopLoss.auxPrice = stopLossPrice
    32  stopLoss.totalQuantity = quantity
    33  stopLoss.parentId = parentOrderId
    34  #In this case, the low side order will be the last child being sent. Therefore, it needs to set this attribute to True
    35  #to activate all its predecessors
    36  stopLoss.transmit = True
    37 
    38  bracketOrder = [parent, takeProfit, stopLoss]
    39  return bracketOrder
    40 
    ...
    1  bracket = OrderSamples.BracketOrder(self.nextOrderId(), "BUY", 100, 30, 40, 20)
    2  for o in bracket:
    3  self.placeOrder(o.orderId, ContractSamples.EuropeanStock(), o)
    4  self.nextOrderId() # need to advance this we'll skip one extra oid, it's fine