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.
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.
- 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
limitPrice
field. - For stop order, the
stopPrice
field.
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
PlacedOrder
object 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 theplaceOrder
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
}infoFor limit and stop orders, make sure to include the
limitPrice
andstopPrice
fields respectively in thePlacedOrder
object when updating the parent order using theorderUpdate
method.The second call provides the
BracketOrder
object that contains information about the take-profit order. The status of the take-profit order should beInactive
, and theqty
andsymbol
values must be identical to the parent order values. The data object must also include:- The
parentId
field with a value equal to theid
value of the parent order. - The
parentType
field, indicating that the parent type is order. - The
side
field with a value opposite to theside
value of the parent order. - The
limitPrice
field with a value equal to thetakeProfit
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
}- The
The third call provides the
BracketOrder
object that contains information about the stop-loss order. The status of the stop-loss order should beInactive
, and theqty
andsymbol
values must be identical to the parent order values. The data object must also include:- The
parentId
field with a value equal to theid
value of the parent order. - The
parentType
field, indicating that the parent type is order. - The
side
field with a value opposite to theside
value of the parent order. - The
stopPrice
field with a value equal to thestopLoss
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
}- 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:
parentId
should be equal to theid
value of the position that resulted from the execution of the parent order.parentType
should 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
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 theid
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
}- The
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 theid
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
}- 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, 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.
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
positionUpdate
call updates a Position object with thestopLoss
andtakeProfit
fields.{
"id": "NasdaqNM:AAPL",
"qty": 100,
"side": 1, // Side.Buy
"symbol": "NasdaqNM:AAPL",
"takeProfit": 174.5,
"stopLoss": 173.32
}The first
orderUpdate
call provides theBracketOrder
object that contains information about the take-profit order. The status of the take-profit order should beWorking
, and theqty
andsymbol
values must be identical to the parent position values. The data object must also include:- The
parentId
field with a value equal to theid
value of the parent position. - The
parentType
field, indicating that the parent type is position. - The
side
field with a value opposite to theside
value of the parent position. - The
limitPrice
field with a value equal to thetakeProfit
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
}- The
The second
orderUpdate
call provides theBracketOrder
object that contains information about the stop-loss order. The status of the stop-loss order should beWorking
, and theqty
andsymbol
values must be identical to the parent position values. The data object must also include:- The
parentId
field with a value equal to theid
value of the parent position. - The
parentType
field, indicating that the parent type is position. - The
side
field with a value opposite to theside
value of the parent position. - The
stopPrice
field with a value equal to thestopLoss
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
}- 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
orderUpdate
call 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
orderUpdate
call 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
positionUpdate
call changes theqty
property to0
.{
"id": "NasdaqNM:AAPL",
"qty": 0,
"side": 1, // Side.Buy
"symbol": "NasdaqNM:AAPL",
"takeProfit": 174.5,
"stopLoss": 173.32
}