Skip to main content

Bracket orders

Overview

Bracket orders (brackets) are orders that protect positions. In other words, brackets help users limit their losses and secure their profits by bracketing positions with two opposing stop-loss and take-profit orders.

The term parent refers to an order or position for which brackets are created. Bracket orders are linked to the parent order/position via the parentId and parentType properties. The quantity of the bracket order always matches the parent quantity.

Brackets always have the opposite side compared to their parent, for example:

  • A buy order is bracketed by a sell-limit order or a sell-stop order.
  • A sell order is bracketed by a buy-stop order or a buy-limit order.

Brackets can exist either in a pair as stop-loss and take-profit or independently. This means that an order or position can have only one bracket order: stop-loss or take-profit.

caution

This article requires a thorough understanding of the Trading Platform components and their interactions. Before continuing with this article, we recommend reading the Core concepts article for a better understanding.

UI interactions

Users can add brackets to a new or existing order or to a position.

Placing order with brackets

Order brackets

To enable adding order brackets in the UI, set the supportOrderBrackets flag to true. Refer to the Trading features configuration section for more information about configuration flags.

Place order with brackets

Users can place orders with two brackets or only one — either a stop-loss or take-profit. When users place orders with brackets, the library calls the placeOrder method and passes a PreOrder object as a parameter. This object contains the stopLoss and takeProfit fields.

Additionally, if a user places a limit order or stop orders, the PreOrder object should contain the following fields:

Example

Consider the following example: a user places a market order with two brackets.

Expand to view the diagram illustrating the process of placing a market order with brackets.
Diagram illustrating placing an order with bracketsDiagram illustrating placing an order with brackets

The library calls the placeOrder method, requesting to create an order. You should implement this method within the Broker API. Refer to the Order creation section for a detailed explanation.

After your backend server handles the order creation, it responds to your Broker API implementation with updated information. Your Broker API implementation then calls the orderUpdate method three times.

  1. The first call provides the PlacedOrder object that contains information about the parent order. The status of the parent order should be Working. Other object values must be identical to the data provided within the placeOrder method.

    {
    "id": "1",
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "side": 1, // Side.Buy
    "status": 6, // Status.Working
    "type": 2, // Type.Market
    "takeProfit": 174.5,
    "stopLoss": 173.32
    }
    info

    For limit and stop orders, make sure to include the limitPrice and stopPrice fields respectively in the PlacedOrder object when updating the parent order using the orderUpdate method.

  2. The second call provides the BracketOrder object that contains information about the take-profit order. The status of the take-profit order should be Inactive, and the qty and symbol values must be identical to the parent order values. The data object must also include:

    • The parentId field with a value equal to the id value of the parent order.
    • The parentType field, indicating that the parent type is order.
    • The side field with a value opposite to the side value of the parent order.
    • The limitPrice field with a value equal to the takeProfit value of the parent order.
    • The type value, indicating that the order type is limit.

    {
    "id": "2",
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "parentId": "1",
    "parentType": 1, // ParentType.Order
    "side": -1, // Side.Sell
    "status": 3, // Status.Inactive
    "type": 1, // Type.Limit
    "limitPrice": 174.5
    }
  3. The third call provides the BracketOrder object that contains information about the stop-loss order. The status of the stop-loss order should be Inactive, and the qty and symbol values must be identical to the parent order values. The data object must also include:

    • The parentId field with a value equal to the id value of the parent order.
    • The parentType field, indicating that the parent type is order.
    • The side field with a value opposite to the side value of the parent order.
    • The stopPrice field with a value equal to the stopLoss value of the parent order.
    • The type value, indicating that the order type is stop.

    {
    "id": "3",
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "parentId": "1",
    "parentType": 1, // ParentType.Order
    "side": -1, // Side.Sell
    "status": 3, // Status.Inactive
    "type": 3, // Type.Stop
    "stopPrice": 173.32
    }

Execute parent order

Bracket orders are linked to the parent order by the Order-Sends-Order (OSO) condition. This means that once the parent order is executed and its status transitions to Filled, the bracket order statuses should change to Working.

When the parent order is executed, it turns into a position. Therefore, you should update the parentId and parentType fields in the bracket order objects to be associated with this new parent position. Along with changing the order statuses, change the values of the following fields:

  • parentId should be equal to the id value of the position that resulted from the execution of the parent order.
  • parentType should be changed to 2, indicating that the parent type is position.

Example

Consider the following example: a user has placed a market order with two brackets. Following this, your backend server is responsible for executing the order, creating a position, and updating the information within the bracket orders.

Expand to view the diagram illustrating the process of executing parent order.
Diagram illustrating executing the parent order and updating bracket ordersDiagram illustrating executing the parent order and updating bracket orders

Your Broker API implementation calls the executionUpdate and positionUpdate methods. Refer to the Execution update section for a detailed explanation for these methods.

Then, your Broker API implementation calls the orderUpdate method three times to provide the library with updated information.

  1. The first call provides updated information about the parent order. Its status should be Filled.

    {
    "id": "1",
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "side": 1, // Side.Buy
    "status": 2, // Status.Filled
    "type": 2, // Type.Market
    "takeProfit": 174.5,
    "stopLoss": 173.32
    }
  2. The second call provides the BracketOrder object that contains updated information about the take-profit order. The data object must contain the following changed values, while other fields should remain the same:

    • The parentId field with a value equal to the id value of the position (NasdaqNM:AAPL in this example).
    • The parentType field, indicating that the parent type is position.
    • The status value, indicating that the order status is working.

    {
    "id": "2",
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "parentId": "NasdaqNM:AAPL",
    "parentType": 2, // ParentType.Position
    "status": 6, // Status.Working
    "side": -1, // Side.Sell
    "type": 1, // Type.Limit
    "limitPrice": 174.5
    }
  3. The third call provides the BracketOrder object that contains information about the stop-loss order. The data object must contain the following changed values, while other fields should remain the same:

    • The parentId field with a value equal to the id value of the position.
    • The parentType field, indicating that the parent type is position.
    • The status value, indicating that the order status is working.

    {
    "id": "3",
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "parentId": "NasdaqNM:AAPL",
    "parentType": 2, // ParentType.Position
    "status": 6, // Status.Working
    "side": -1, // Side.Sell
    "type": 3, // Type.Stop
    "stopPrice": 173.32
    }
tip

To keep the UI data up-to-date, you should constantly provide updates of users' entity and P&L values whenever changes occur. Refer to the Equity update section for more information.

Position brackets

To enable adding position brackets in the UI, set the supportPositionBrackets or supportIndividualPositionBrackets flag to true. This activates buttons for creating brackets on the chart and enables the Protect position button. For more details on configuration flags, check the Trading features configuration section.

Add position brackets

By default, users can add two brackets at the same time or only one of them. However, you can set the supportOnlyPairPositionBrackets flag to true, so users can add two brackets together only.

When users add brackets to the existing position, the library calls the editPositionBrackets method. In this method, the library provides the stopLoss and takeProfit fields. After that, the library expects you to call the positionUpdate method within 10 seconds. Note that the library will return a timeout issue if it fails to receive a timely position update.

Example

Consider the following example: the user has an APPL position and decides to place two bracket orders for this position.

Expand to view the diagram illustrating the process of adding two bracket orders to the position.
Diagram illustrating adding position bracketsDiagram illustrating adding position brackets

The library calls the editPositionBrackets method, providing the stopLoss and takeProfit fields. You should implement this method within your Broker API implementation and handle the user's request to add bracket orders. Note that the position update and order creation might be processed on external sources, such as exchanges. However, your backend server is expected to manage this information and provide it in the format required by the library.

After your backend server handles the position update and order creation, it responds to your Broker API implementation with updated information. Your Broker API implementation then calls the positionUpdate and orderUpdate methods.

  1. The positionUpdate call updates a Position object with the stopLoss and takeProfit fields.

    {
    "id": "NasdaqNM:AAPL",
    "qty": 100,
    "side": 1, // Side.Buy
    "symbol": "NasdaqNM:AAPL",
    "takeProfit": 174.5,
    "stopLoss": 173.32
    }
  2. The first orderUpdate call provides the BracketOrder object that contains information about the take-profit order. The status of the take-profit order should be Working, and the qty and symbol values must be identical to the parent position values. The data object must also include:

    • The parentId field with a value equal to the id value of the parent position.
    • The parentType field, indicating that the parent type is position.
    • The side field with a value opposite to the side value of the parent position.
    • The limitPrice field with a value equal to the takeProfit value of the parent position.
    • The type value, indicating that the order type is limit.

    {
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "id": "2",
    "parentId": "NasdaqNM:AAPL",
    "parentType": 2, // ParentType.Position
    "side": -1, // Side.Sell
    "status": 6, // Status.Working
    "type": 1, // Type.Limit
    "limitPrice": 174.5
    }
  3. The second orderUpdate call provides the BracketOrder object that contains information about the stop-loss order. The status of the stop-loss order should be Working, and the qty and symbol values must be identical to the parent position values. The data object must also include:

    • The parentId field with a value equal to the id value of the parent position.
    • The parentType field, indicating that the parent type is position.
    • The side field with a value opposite to the side value of the parent position.
    • The stopPrice field with a value equal to the stopLoss value of the parent position.
    • The type value, indicating that the order type is stop.

    {
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "id": "3",
    "parentId": "NasdaqNM:AAPL",
    "parentType": 2, // ParentType.Position
    "side": -1, // Side.Sell
    "status": 6, // Status.Working
    "type": 3, // Type.Stop
    "stopPrice": 173.32
    }

Execute bracket order

Bracket orders are linked to each other by the One-Cancels-the-Other (OCO) condition. This means that when one of the bracket orders is executed, the other one gets canceled. In this case, the position linked to the executed bracket order should change its quantity to zero, closing the position.

Example

Consider the following example: the user has a position with two bracket orders. You broker server executes a stop-loss order and returns updated information.

Expand to view the diagram illustrating the process of executing a bracket order.
Diagram illustrating executing the stop-loss orderDiagram illustrating executing the stop-loss order

Your Broker API implementation then calls two consequent orderUpdate methods and then positionUpdate.

  1. The first orderUpdate call provides information about the executed stop-loss order. The status of the order should be Filled.

    {
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "id": "3",
    "parentId": "NasdaqNM:AAPL",
    "parentType": 2, // ParentType.Position
    "side": -1, // Side.Sell
    "status": 2, // Status.Filled
    "type": 3, // Type.Stop
    "stopPrice": 173.32
    }
  2. The second orderUpdate call provides information about the canceled stop-loss order. The status of the order should be Canceled.

    {
    "symbol": "NasdaqNM:AAPL",
    "qty": 100,
    "id": "3",
    "parentId": "NasdaqNM:AAPL",
    "parentType": 2, // ParentType.Position
    "side": -1, // Side.Sell
    "status": 1, // Status.Canceled
    "type": 1, // Type.Limit
    "limitPrice": 174.5
    }
  3. The positionUpdate call changes the qty property to 0.

    {
    "id": "NasdaqNM:AAPL",
    "qty": 0,
    "side": 1, // Side.Buy
    "symbol": "NasdaqNM:AAPL",
    "takeProfit": 174.5,
    "stopLoss": 173.32
    }