Bracket orders
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.
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.
By default, an order or position can have only one bracket order per side (one stop-loss and one take-profit).
However, if the supportMultipleExitLevels flag is enabled, users can add multiple exit levels.
UI interactions
Users can add brackets to a new or existing order or to a position.
- Place order with brackets
- Add brackets via buttons
- Add brackets via Protect position



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:
- For limit order, the
limitPricefield. - For stop order, the
stopPricefield.
Example
Consider the following example: a user places a market order with two 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.
-
The first call provides the
PlacedOrderobject that contains information about the parent order. The status of the parent order should beWorking. Other object values must be identical to the data provided within theplaceOrdermethod.{
"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
}
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.
-
The second call provides the
BracketOrderobject that contains information about the take-profit order. The status of the take-profit order should beInactive, and theqtyandsymbolvalues must be identical to the parent order values. The data object must also include:- The
parentIdfield with a value equal to theidvalue of the parent order. - The
parentTypefield, indicating that the parent type is order. - The
sidefield with a value opposite to thesidevalue of the parent order. - The
limitPricefield with a value equal to thetakeProfitvalue of the parent order. - The
typevalue, 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
} - The
-
The third call provides the
BracketOrderobject that contains information about the stop-loss order. The status of the stop-loss order should beInactive, and theqtyandsymbolvalues must be identical to the parent order values. The data object must also include:- The
parentIdfield with a value equal to theidvalue of the parent order. - The
parentTypefield, indicating that the parent type is order. - The
sidefield with a value opposite to thesidevalue of the parent order. - The
stopPricefield with a value equal to thestopLossvalue of the parent order. - The
typevalue, 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
} - The
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:
parentIdshould be equal to theidvalue of the position that resulted from the execution of the parent order.parentTypeshould be changed to2, 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.
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.
-
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
} -
The second call provides the
BracketOrderobject 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
parentIdfield with a value equal to theidvalue of the position (NasdaqNM:AAPLin this example). - The
parentTypefield, indicating that the parent type is position. - The
statusvalue, 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
} - The
-
The third call provides the
BracketOrderobject 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
parentIdfield with a value equal to theidvalue of the position. - The
parentTypefield, indicating that the parent type is position. - The
statusvalue, 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
} - The
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, configure the appropriate flags based on the position type (regular or individual). For more details on configuration flags, check the Trading features configuration section.
- For regular positions, set
supportPositionBracketstotrue. - For individual positions, set
supportIndividualPositionBracketstotrue.
When supportPositionBrackets is true, the library prioritizes net positions.
This hides individual position lines on the chart, even if position netting is enabled.
If you want to display individual positions on the chart, ensure that:
supportPositionBracketsisfalsesupportIndividualPositionBracketsistrue
Add and modify 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.
Whether adding new brackets or modifying existing ones, the library relies on specific Broker API methods. Implement the method that corresponds to your position type:
- For regular positions, implement
editPositionBrackets. - For individual positions: implement
editIndividualPositionBrackets.
In these methods, the library provides the stopLoss and takeProfit fields.
After that, the library expects you to call the positionUpdate (or individualPositionUpdate) 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.
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.
-
The
positionUpdatecall updates aPositionobject with thestopLossandtakeProfitfields.{
"id": "NasdaqNM:AAPL",
"qty": 100,
"side": 1, // Side.Buy
"symbol": "NasdaqNM:AAPL",
"takeProfit": 174.5,
"stopLoss": 173.32
} -
The first
orderUpdatecall provides theBracketOrderobject that contains information about the take-profit order. The status of the take-profit order should beWorking, and theqtyandsymbolvalues must be identical to the parent position values. The data object must also include:- The
parentIdfield with a value equal to theidvalue of the parent position. - The
parentTypefield, indicating that the parent type is position. - The
sidefield with a value opposite to thesidevalue of the parent position. - The
limitPricefield with a value equal to thetakeProfitvalue of the parent position. - The
typevalue, 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
} - The
-
The second
orderUpdatecall provides theBracketOrderobject that contains information about the stop-loss order. The status of the stop-loss order should beWorking, and theqtyandsymbolvalues must be identical to the parent position values. The data object must also include:- The
parentIdfield with a value equal to theidvalue of the parent position. - The
parentTypefield, indicating that the parent type is position. - The
sidefield with a value opposite to thesidevalue of the parent position. - The
stopPricefield with a value equal to thestopLossvalue of the parent position. - The
typevalue, 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
} - The
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.
Your Broker API implementation then calls two consequent orderUpdate methods and then positionUpdate.
-
The first
orderUpdatecall provides information about the executed stop-loss order. The status of the order should beFilled.{
"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
} -
The second
orderUpdatecall provides information about the canceled stop-loss order. The status of the order should beCanceled.{
"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
} -
The
positionUpdatecall changes theqtyproperty to0.{
"id": "NasdaqNM:AAPL",
"qty": 0,
"side": 1, // Side.Buy
"symbol": "NasdaqNM:AAPL",
"takeProfit": 174.5,
"stopLoss": 173.32
}
Multiple exit levels
When supportMultipleExitLevels is enabled, users can protect orders and positions with multiple brackets at different price levels and quantities.
They can add levels using the Add level button in the Order Ticket or position dialog.
Data structure
When this feature is enabled, the library uses the exitLevels property on order and position-related objects (PreOrder, PlacedOrder, Position, BracketOrder).
This property contains an array of ExitLevel objects.
Each object represents a separate bracket level with its own quantity and stop-loss/take-profit prices.
To distinguish between the different brackets, the BracketOrder object includes an exitLevelId property.
This ID should correspond to the id of the level defined in the exitLevels array.
Limit number of levels
You can limit the maximum number of exit levels a user can create by returning the maxExitLevelsCount property from the getOrderDialogOptions method.