Skip to main content

Complex Orders

Overview

This document describes how system supports complex orders. For example, trader wants to open LONG position (using “enter” BUY order) but immediately protect this position with a pair of take profit and stop loss SELL orders.

Complex Orders API provides an ability to transmit such complex orders into OMS using a sequence of API calls. However, grouping these orders together allows “all or none” semantic. If one of the orders in a group fails OMS validation, then entire group will be rejected.

Terminology

There is some confusion with terminology that this section would like to clarify:

  • There are two somewhat similar order types - OCO (Order Cancels Order) and OUO (Order Updates Order).
  • Term “Bracket order” is a synonym of Order-Updates-Order (OUO). Any references to OCO in context of Bracket order discussion is a mistake.

Complex Order types

Restrictions/Limitations

  • All orders in group must be for the same symbol (contract).
  • All orders in the group must have the same quantity.
  • Nested groups are not supported. There is one exception – 3-legged group of Entry+Bracket Exit orders.

Bracket Orders (OUO)

A bracket order is a special instance of an OUO (Order Updates Order). Bracket orders are used to exit an existing position. They are designed to limit loss and lock in profit by “bracketing” an order with a simultaneous stop and limit order.

Bracket orders are limited so that the orders are all for the same symbol and are on the same side of the market (either all to sell or all to cover), and they are restricted to closing transactions. The reason that they follow these rules is - the orders need to be able to auto decrements when a partial fill occurs with one of the orders. For example, if the customer has a sell limit order for 1000 shares and a sell stop order for 1000 shares, and the limit order is partially filled for 500 shares, then the customer would want the stop to remain open, but it should automatically decrement the order to 500 shares to match the remaining open position.

Exit Bracket

Bracket Exit Order

Sell Stop (Stop Loss) & Sell Limit (Take Profit) - Requires the user to already have a position and enables the user to box their position. These orders should be vetted against current balances when used as an exit bracket. In the future, we will support shorts and would like to allow this as an entry order. It's acceptable to use a Stop Market order, in the future we would like to use Stop Limits.

Entry - Breakout/Fade Buy OUO

Bracket Entry Order The Entry - Breakout/Fade Buy OUO template consists of a Buy Stop order above the current market and a Buy Limit order below the current market. The Entry - Breakout/Fade Buy OUO order can be used when you want to enter a long position, but you are not sure if the market will breakout up or retrace to a lower support level and then move up.

Order submit Order (OSO)

OSO orders are typically used to enter protected position (LONG or SHORT). This complex order consists of a entry order and one or more Exit orders, activated when the entry order is filled.  

For example, let’s consider an OSO order consisting of three legs:

  1. Entry order: is a limit BUY 1000 order, and attached to it are two other SELL orders (OUO):
  2. Exit bracket order consisting of two legs:
  • a limit SELL 1000 (take profit) order
  • a stop SELL 1000 (stop loss) order.

After the Entry order completes, the Exit order(s) are sent to the market.  Quantity of Exit orders is set to the cumulative filled quantity of the Entry order. Obviously if Entry order is cancelled without a fill or rejected, then the Exit orders are not sent. NOTE: To avoid complexity and prevent self-trading Exit orders wait till Entry order is complete. A partially filled entry orders result in unprotected (naked) position until entry order is active.

OSO can trigger a single Exit order (e.g. LIMIT or STOP) or an OUO order bracket consisting of two legs.

Partially filled Entry order with GTC or GOOD_TILL_DATE time in force condition will be converted to DAY.

Implementation Approach 1: Linked orders

General idea

This approach followed by venues like Integral FX and Interactive Brokers. Under this approach bracket is represented as a pair of linked order requests. The process of bracket order submission is the following:

  1. You submit the first component order with ContingencyType(1385)=OUO. The order’s TimeInForce(59) expiry must be something other than IOC or FOK.

  2. Receive an Execution Report message indicating that the first component order is valid with the OrdStatus(39) field set to PendingNew(A).

  3. Submit the second component order with ContingencyType(1385)=OUO and the ClOrdLinkID (583) set to the client order ID ClOrdID (11) of the first component order.

  4. The system performs the following validation:

  5. Ensures that the first component order is still in the Pending New state (has not expired, cancelled, or filled).

  6. Checks that the TimeInForce (#59) expiry of the second component order is not IOC or FOK.

  7. If the second component order passes validation. You receive two Execution Reports indicating that both orders are working for the first component order. Each report message will have field OrderStatus = New(0).

  8. If either one of the component orders is filled or partially filled, then the system adjusts the other component order (by cancelling or reducing effective size).

  9. If one component order is expired or cancelled, then the other order is not cancelled and remains in effect until it is filled, expired, or cancelled. In all other aspects (execution, expiry, status), each component order behaves the same as any other order with the same expiry and execution characteristics.

Special order attributes

Summary of custom order attributes used by bracket order pair:

Name (FIX tag)RequiredTypeDescription
ContingencyType(1385)YEnum1 = OCO (One cancels other)
2 = OTO (One triggers other, also known as OSO)
3 = OUO, Absolute (One updates other) ← BRACKET ORDER
100 = OSO,OUO
ClOrdLinkID(583)CTextID of the previous order in group. This attribute is skipped on the first order but required on subsequent orders of the group.

Diagrams

The following diagrams illustrate this approach: Complex Order diagram

Notes

  • Orders can be submitted in rapid sequence (fire and forget). API client doesn’t have to wait for acknowledgement of the first order.
  • Each order destination that supports group orders must wait for all legs to arrive before starting execution of the first leg.
  • Each order destination that supports group orders is responsible for cancelling partially submitted orders after a configurable timeout. For example, when the second leg is lost in transmission.
  • Under some abnormal condition legs may be delivered to the destination out of order. Destination should be able to handle this.

Disadvantages of this approach:

  • No way to implement atomic modification of order quantity of group order. Clients must cancel each leg resubmit new bracket order with new quantity.

Enrichment

Once the entire group of orders is assembled Deltix OMS will enrich each order with additional information that will simplify reporting.

Name (FIX tag)RequiredTypeDescription
LegRole(7101)EnumTextRole of this leg. For Example:
ENTRY - order enters into long or short position
UPPER_BRACKET part of bracket order with higher price
LOWER_BRACKET
This attribute is placed to simplify reporting and dashboards that have to display grouped orders.
NumLegs(7102)YIntDefines how many legs are in order group. Also marks start of repeating group of ClOrdLinkID(583) entries for each leg.

The following diagram shows attributes applied to a group of three orders: Complex Order Diagram 2

Bracket Order Lifecycle Events

As far as order events bracket orders behave as if both legs are independent orders. That is for each leg client will receive order acknowledgement, cancellation, fills, etc. events.

Example 1

  • Client submits the first leg of the bracket order.
  • System confirms it using Order Pending New Event.
  • Client submits the second leg of the bracket order. Let’s imagine that this leg is invalid.
  • System rejects the second leg using Order Reject Event and cancels the first leg using Order Cancel Event.

Example 2

  • Client submits the first leg of the bracket order.
  • System confirms it using Order Pending New Event (order is received but not working).
  • Client submits the second leg of the bracket order.
  • System confirms the second order using Order New Event
  • System confirms that the first order is now working using Order New Event.
  • One of the orders is completely filled.
  • Order Filled Event (trade quantity reflects entire order amount).
  • Order Cancel Event for the other leg.

System uses Order Restated Event to signal order quantity reduction of one leg when the other leg is partially filled.

Example 3

  • Client submits the first leg of the bracket order.
  • System confirms it using Order Pending New Event (order is received but not working).
  • Client submits the second leg of the bracket order.
  • System confirms the second leg using Order New Event.
  • System confirms that the first order is now working using Order New Event.
  • The second leg is partially filled.
  • Order Filled Event for the second leg (trade quantity reflects fill amount)
  • Order Restated Event for the first leg (order quantity reflects new reduced amount)

REST API Samples

This section describes REST API request that can be used to submit complex orders.

Sample 1: POST request for bracket order

The first order:

{
"order_id": "Order A",
"destination": "TSSR",
"expire_time": 1580247316000,
"price": "3000",
"quantity": "0.1239",
"security_id": "BTCUSD",
"side": "buy",
"submission_time": 1579200906345,
"time_in_force": 1,
"type": "limit",
"attributes": {
{ 1385, 3 } // Contingency Type=OUO
}
}

The second order:

{
"order_id": "Order B",
"destination": "TSSR",
"expire_time": 1580247316000,
"price": "4000",
"quantity": "0.1239",
"security_id": "BTCUSD",
"side": "sell",
"submission_time": 1579200906345,
"time_in_force": 1,
"type": "limit",
"attributes": {
{ 1385, 3 }, // Contingency Type=OUO
{ 583 = "Order A"} // LinkedOrderID
}
}

Sample 2: POST request for 3-legged order group

The first order:

{
"order_id": "Order A",
"destination": "TSSR",
"expire_time": 1580247316000,
"price": "3000",
"quantity": "0.1239",
"security_id": "BTCUSD",
"side": "buy",
"submission_time": 1579200906345,
"time_in_force": 1,
"type": "limit",
"attributes": {
{ 1385, 100 } // ContingencyType=OSO,OCO
}
}

The second order:

{
"order_id": "Order B",
"destination": "TSSR",
"expire_time": 1580247316000,
"price": "4000",
"quantity": "0.1239",
"security_id": "BTCUSD",
"side": "sell",
"submission_time": 1579200906345,
"time_in_force": 1,
"type": "limit",
"attributes": {
{ 1385, 100 }, // Contingency Type=OSO,OCO
{ 583 = "Order A"} // LinkedOrderID
}
}

The third order:

{
"order_id": "Order C",
"destination": "TSSR",
"expire_time": 1580247316000,
"price": "4000",
"quantity": "0.1239",
"security_id": "BTCUSD",
"side": "sell",
"submission_time": 1579200906345,
"time_in_force": 1,
"type": "limit",
"attributes": {
{ 1385, 100 }, // Contingency Type=OSO,OCO
{ 583 = "Order B"} // LinkedOrderID
}
}

Sample 3: Order response for bracket order

{
orderId = "Order A"
side = "BUY"
quantity = 10
attributes: {
{ 1385, 3 } // 3 = One-Updates-Other
{ 7101, "UPPER_BRACKET" }, // Do you need this?
{ 7102, 2 }, // number of legs to follow
{ 583, "Order A" }, // Sequence of orders in this list is not important
{ 583, "Order B" }, // for Bracket, but very important for OSO and others
}
}


{
orderId = "Order B"
side = "BUY"
quantity = 10
attributes: {
{ 1385, 3 } // 3 = One-Updates-Other
{ 7101, "LOWER_BRACKET" }, // Do you need this?
{ 7102, 2 }, // number of legs to follow
{ 583, "Order A" },
{ 583, "Order B" },
}
}

5.5    Ember CLI Example

The following example 3-legged order submission can be used with ember-cli tool:

set destinationId TSSR
set sourceId TRADER-CLI

set orderId OSOENTRY2
set side BUY
set quantity 1
set symbol BTC/USD
set instrumentType FX
set timeInForce DAY
set orderType LIMIT
set limitPrice 6700
set attributes 1385=100
unset stopPrice
submit -f

set orderId OSOBRACKETPROFIT2
set side SELL
set orderType LIMIT
set limitPrice 6705
set attributes 1385=100,583=OSOENTRY2
submit -f

set orderId OSOBRACKETLOSS1
set side SELL
set orderType STOP
set stopPrice 6680
set attributes 1385=100,583=OSOBRACKETPROFIT2
unset limitPrice
submit -f