Orders

OrderRequest allows placing different orders.

The response is returned as an OrderStatus (see Scope: Orders). To receive these updates, the client must be subscribed to the TradeSubscription order scope.

If the order request is invalid or the client lacks entitlements, the system may return an OrderRequestReject instead of an OrderStatus with a REJECTED status. The rejection can be matched to the original request using the request_id.

Note: Before placing a new order, you may use OrderEntitlementRequest to check if such a combination of order type, order duration, and execution instructions is allowed for a contract on the account.

There are also user-wide order requests (with an optional account filter):

      CancelAllOrders

      LiquidateAll

      GoFlat

They have a special acknowledgment message OrderRequestAck, and for GoFlat - per account GoFlatStatus.

Note: For price field conversion, use How To Interpret Scaled Prices? article. For time/date fields, see How Are Time Fields Encoded?.

Note: Some exchanges require additional parameters for order requests. Use the extra_attribute field in Order to pass them. Fields are described in ExchangeExtraAttributesForOrders.adoc, which is delivered along with proto files.

An example of order placement is available here.

Compound Orders

The WebAPI protocol allows setting order relationships.

Type of Relationship:

      OPO (Order Places Order): After the fill of the main order (first in the list), the others are placed.

      OCO (Order Cancels Order): After any order in the list is filled, the others are canceled.

      Independent: No special actions are applied to other orders after order fill.

To create a compound order, use NewCompoundOrder. A chain can be created with a new simple order (CompoundOrderEntry.order), another compound order (CompoundOrderEntry.compound_order), or an already existing order (CompoundOrderEntry.use_order).

Bracket Orders

A bracket order is a special case of a compound order: when the main order is filled (OPO), target and/or stop-loss orders are placed (OCO). When either the target or stop-loss order is filled, the other is canceled.

This setup delegates some responsibility to the server, such as basic checks for bracket order validity (correct side, quantity, and type). If offsets are present, the server calculates the result limit and stop-limit prices and if the main order price changes, the target and stop-loss order prices are recalculated.

To enable this mode, use the profit_tick_offset, loss_tick_offset, and stop_limit_tick_offset fields in CompoundOrder. Additionally, set is_bracket=true to remove ambiguity.

Example

An example is provided for a bracket order. For a regular compound order, you need to fill the correct price fields and skip profit_tick_offset, loss_tick_offset, and is_bracket fields.

Client Message:

{
  "order_requests": [
    {
      "request_id": 21,
      "new_compound_order": {
        "compound_order": {
          "type": 1,
          "cl_compound_id": "compound order",
          "compound_order_entries": [
            {
              "order": {
                "account_id": 12345,
                "contract_id": 1,
                "cl_order_id": "main order",
                "order_type": 2,
                "duration": 1,
                "side": 2,
                "scaled_limit_price": 593800,
                "when_utc_timestamp": {
                  "seconds": 1741201778,
                  "nanos": 421000000
                },
                "qty": {
                  "significand": 1,
                  "exponent": 0
                }
              }
            },
            {
              "compound_order": {
                "type": 2,
                "cl_compound_id": "OCO target and stop loss orders",
                "compound_order_entries": [
                  {
                    "order": {
                      "account_id": 12345,
                      "contract_id": 1,
                      "cl_order_id": "target order",
                      "order_type": 2,
                      "duration": 1,
                      "side": 1,
                      "scaled_limit_price": 0,
                      "when_utc_timestamp": {
                        "seconds": 1741201778,
                        "nanos": 422000000
                      },
                      "qty": {
                        "significand": 1,
                        "exponent": 0
                      }
                    }
                  },
                  {
                    "order": {
                      "account_id": 12345,
                      "contract_id": 1,
                      "cl_order_id": "stop loss order",
                      "order_type": 3,
                      "duration": 1,
                      "side": 1,
                      "scaled_stop_price": 0,
                      "when_utc_timestamp": {
                        "seconds": 1741201778,
                        "nanos": 422000000
                      },
                      "qty": {
                        "significand": 1,
                        "exponent": 0
                      }
                    }
                  }
                ]
              }
            }
          ],
          "profit_tick_offset": 5,
          "loss_tick_offset": 5,
          "is_bracket": true
        }
      }
    }
  ]
}

Server Responses:

Status for main order

{
  "order_statuses": [
    {
      "subscription_ids": [
        1
      ],
      "is_snapshot": false,
      "status": 1,
      "order_id": "1501730078",
      "chain_order_id": "1501730078",
      "status_utc_time": 40118177,
      "submission_utc_time": 40118177,
      "fill_cnt": 0,
      "scaled_avg_fill_price": 0,
      "order": {
        "account_id": 12345,
        "when_utc_time": 40118032,
        "contract_id": 1,
        "cl_order_id": "main order",
        "order_type": 2,
        "duration": 1,
        "side": 2,
        "scaled_limit_price": 594975,
        "is_manual": true,
        "is_user_attribute_checked": false,
        "when_utc_timestamp": {
          "seconds": 1741201778,
          "nanos": 421000000
        },
        "qty": {
          "significand": 1
        },
        "execution_source_code": "Y",
        "is_care_order": false
      },
      "transaction_statuses": [
        {
          "status": 1,
          "trans_id": 12502967552,
          "trans_utc_time": 40118177,
          "cl_order_id": "main order",
          "trans_utc_timestamp": {
            "seconds": 1741201778,
            "nanos": 521000000
          },
          "mifid_execution_decision": "NORE",
          "execution_source_code": "Y",
          "is_automated": false,
          "mifid_execution_decision_is_algo": false,
          "username": "username"
        }
      ],
      "entered_by_user": "username",
      "first_statement_date": 47359000,
      "account_id": 12345,
      "compound_order_structure": {
        "type": 1,
        "cl_compound_id": "compound order",
        "compound_order_entries": [
          {
            "chain_order_id": "1501730078"
          },
          {
            "compound_order_structure": {
              "type": 2,
              "cl_compound_id": "OCO target and stop loss orders",
              "compound_order_entries": [
                {
                  "chain_order_id": "1501730079"
                },
                {
                  "chain_order_id": "1501730080"
                }
              ]
            }
          }
        ],
        "profit_offset": 5,
        "loss_offset": 5
      },
      "status_utc_timestamp": {
        "seconds": 1741201778,
        "nanos": 521000000
      },
      "submission_utc_timestamp": {
        "seconds": 1741201778,
        "nanos": 521000000
      },
      "avg_fill_price_correct": 0,
      "fill_qty": {
        "significand": 0
      },
      "remaining_qty": {
        "significand": 1
      },
      "mifid_execution_decision": "NORE",
      "mifid_execution_decision_is_algo": false,
      "operator_id": "123"
    }
  ]
}

Status for target order (it is parked)

{
  "order_statuses": [
    {
      "subscription_ids": [
        1
      ],
      "is_snapshot": false,
      "status": 9,
      "order_id": "1501730079",
      "chain_order_id": "1501730079",
      "status_utc_time": 40118177,
      "submission_utc_time": 40118176,
      "fill_cnt": 0,
      "scaled_avg_fill_price": 0,
      "order": {
        "account_id": 12345,
        "when_utc_time": 40118033,
        "contract_id": 1,
        "cl_order_id": "dae38bb0-2eb3-4294-a7d7-f585a35f9f79",
        "order_type": 2,
        "duration": 1,
        "side": 1,
        "scaled_limit_price": 594850,
        "is_manual": true,
        "is_user_attribute_checked": false,
        "when_utc_timestamp": {
          "seconds": 1741201778,
          "nanos": 451000000
        },
        "qty": {
          "significand": 1
        },
        "execution_source_code": "Y",
        "is_care_order": false
      },
      "transaction_statuses": [
        {
          "status": 1,
          "trans_id": 12502967808,
          "trans_utc_time": 40118177,
          "cl_order_id": "dae38bb0-2eb3-4294-a7d7-f585a35f9f79",
          "trans_utc_timestamp": {
            "seconds": 1741201778,
            "nanos": 471000000
          },
          "mifid_execution_decision": "NORE",
          "execution_source_code": "Y",
          "is_automated": false,
          "mifid_execution_decision_is_algo": false,
          "username": "username"
        }
      ],
      "entered_by_user": "username",
      "first_statement_date": 47359000,
      "account_id": 12345,
      "compound_order_structure": {
        "type": 1,
        "cl_compound_id": "a65d5580-cd7c-48bb-a351-fb5202e99b8e",
        "compound_order_entries": [
          {
            "chain_order_id": "1501730078"
          },
          {
            "compound_order_structure": {
              "type": 2,
              "cl_compound_id": "6c56022b-a63e-4d66-8f6f-5bfd6f19bdff",
              "compound_order_entries": [
                {
                  "chain_order_id": "1501730079"
                },
                {
                  "chain_order_id": "1501730080"
                }
              ]
            }
          }
        ],
        "profit_offset": 5,
        "loss_offset": 5
      },
      "status_utc_timestamp": {
        "seconds": 1741201778,
        "nanos": 471000000
      },
      "submission_utc_timestamp": {
        "seconds": 1741201778,
        "nanos": 471000000
      },
      "avg_fill_price_correct": 0,
      "fill_qty": {
        "significand": 0
      },
      "remaining_qty": {
        "significand": 1
      },
      "mifid_execution_decision": "NORE",
      "mifid_execution_decision_is_algo": false,
      "operator_id": "123"
    }
  ]
}

Status for stop loss order (it is parked)

{
  "order_statuses": [
    {
      "subscription_ids": [
        1
      ],
      "is_snapshot": false,
      "status": 9,
      "order_id": "1501730080",
      "chain_order_id": "1501730080",
      "status_utc_time": 40118200,
      "submission_utc_time": 40118176,
      "fill_cnt": 0,
      "scaled_avg_fill_price": 0,
      "order": {
        "account_id": 12345,
        "when_utc_time": 40118033,
        "contract_id": 1,
        "cl_order_id": "bfb297db-f46a-4525-9bbc-3ba8e16410e4",
        "order_type": 3,
        "duration": 1,
        "side": 1,
        "scaled_stop_price": 595100,
        "is_manual": true,
        "is_user_attribute_checked": false,
        "when_utc_timestamp": {
          "seconds": 1741201778,
          "nanos": 421000000
        },
        "qty": {
          "significand": 1
        },
        "execution_source_code": "Y",
        "is_care_order": false
      },
      "transaction_statuses": [
        {
          "status": 1,
          "trans_id": 12502968064,
          "trans_utc_time": 40118200,
          "cl_order_id": "bfb297db-f46a-4525-9bbc-3ba8e16410e4",
          "trans_utc_timestamp": {
            "seconds": 1741201778,
            "nanos": 451000000
          },
          "mifid_execution_decision": "NORE",
          "execution_source_code": "Y",
          "is_automated": false,
          "mifid_execution_decision_is_algo": false,
          "username": "username"
        }
      ],
      "entered_by_user": "username",
      "first_statement_date": 47359000,
      "account_id": 12345,
      "compound_order_structure": {
        "type": 1,
        "cl_compound_id": "a65d5580-cd7c-48bb-a351-fb5202e99b8e",
        "compound_order_entries": [
          {
            "chain_order_id": "1501730078"
          },
          {
            "compound_order_structure": {
              "type": 2,
              "cl_compound_id": "6c56022b-a63e-4d66-8f6f-5bfd6f19bdff",
              "compound_order_entries": [
                {
                  "chain_order_id": "1501730079"
                },
                {
                  "chain_order_id": "1501730080"
                }
              ]
            }
          }
        ],
        "profit_offset": 5,
        "loss_offset": 5
      },
      "status_utc_timestamp": {
        "seconds": 1741201778,
        "nanos": 471000000
      },
      "submission_utc_timestamp": {
        "seconds": 1741201778,
        "nanos": 471000000
      },
      "avg_fill_price_correct": 0,
      "fill_qty": {
        "significand": 0
      },
      "remaining_qty": {
        "significand": 1
      },
      "mifid_execution_decision": "NORE",
      "mifid_execution_decision_is_algo": false,
      "operator_id": "123"
    }
  ]
}

Allocation Orders

WebAPI provides the ability to use Pre-Trade allocation functionality. For that one should:

      Place allocation order, containing pre-allocated instructions inside allocated_accounts field;

      Wait when it becomes completely filled;

      Send AllocationRequest for the order to allocate its fills between accounts accordingly to pre-allocated instructions;

      Wait for new filled orders for allocated accounts.

Example

In this example allocation order has two allocated accounts (456 and 789) and placed for 123 account.

Note that sum of allocated accounts quantities must be equal to order quantity. Otherwise order request will be rejected.

Client Message:

{
  "order_requests": [
    {
      "request_id": 12,
      "new_order": {
        "order": {
          "account_id": 123,
          "contract_id": 1,
          "cl_order_id": "allocation order",
          "order_type": 1,
          "duration": 1,
          "side": 1,
          "scaled_limit_price": 571750,
          "when_utc_timestamp": {
            "seconds": 1749476335
          },
          "qty": {
            "significand": 3,
            "exponent": 0
          },
          "allocated_accounts": [
            {
              "account_id": 456,
              "qty": {
                "significand": 2
              }
            },
            {
              "account_id": 789,
              "qty": {
                "significand": 1
              }
            }
          ]
        }
      }
    }
  ]
}

It’s necessary to wait for FILLED order status.

Server Responses:

Note: some unimportant fields are omitted.

{
  "order_statuses": [
    {
      "status": 8,
      "order_id": "1530820003",
      "fill_qty": {
        "significand": 3
      },
      "remaining_qty": {
        "significand": 0
      },
      "order": {
        "account_id": 123,
        "cl_order_id": "allocation order",
        "qty": {
          "significand": 3
        },
        "allocated_accounts": [
          {
            "account_id": 456,
            "qty": {
              "significand": 2
            }
          },
          {
            "account_id": 789,
            "qty": {
              "significand": 1
            }
          }
        ]
      },
      "transaction_statuses": [
        {
          "status": 11,
          "cl_order_id": "allocation order",
          "fill_qty": {
            "significand": 3
          },
        }
      ],
      "allocated_qty": {
        "significand": 0
      }
    }
  ]
}

After that one should send AllocationRequest for 123 account as an example.

Client Message:

{
  "allocation_requests": [
    {
      "allocation_id": "allocation_1",
      "allocation_order_refs": [
        {
          "account_id": 123,
          "order_id": "1530820003"
        }
      ]
    }
  ]
}

Server Responses:

{
  "allocation_reports": [
    {
      "allocation_id": "allocation_1",
      "status_code": 0,
      "when": {
        "seconds": 1749549381,
        "nanos": 719805000
      }
    }
  ]
}

After that allocation order will get new transaction with FILLS_ALLOCATION status and allocated_qty field.

Server Responses (without unimportant fields):

{
  "order_statuses": [
    {
      "status": 8,
      "order_id": "1530820003",
      "order": {
        "account_id": 123,
        "allocated_accounts": [
          {
            "account_id": 456,
            "qty": {
              "significand": 2
            },
            "is_required": false
          },
          {
            "account_id": 789,
            "qty": {
              "significand": 1
            },
            "is_required": false
          }
        ]
      },
      "transaction_statuses": [
        {
          "status": 30,
          "cl_order_id": "allocation order",
        }
      ],
      "allocated_qty": {
        "significand": 3
      }
    }
  ]
}

And finally new orders will be created for allocated accounts.

Server Responses (without unimportant fields):

{
  "order_statuses": [
    {
      "status": 8,
      "order_id": "1530710002",
      "fill_qty": {
        "significand": 2
      },
      "order": {
        "account_id": 456,
        "cl_order_id": "CQG_1530710002",
        "extra_attributes": [
          {
            "name": "AllocationOrderID",
            "value": "1530820003",
            "deleted": false
          }
        ],
      },
      "transaction_statuses": [
        {
          "status": 11,
        }
      ],
    }
  ]
}

{
  "order_statuses": [
    {
      "status": 8,
      "order_id": "1530710003",
      "fill_qty": {
        "significand": 1
      },
      "order": {
        "account_id": 789,
        "cl_order_id": "CQG_1530710003",
        "extra_attributes": [
          {
            "name": "AllocationOrderID",
            "value": "1530820003",
            "deleted": false
          }
        ],
      },
      "transaction_statuses": [
        {
          "status": 11,
        }
      ],
    }
  ]
}

They contain extra-attribute with “AllocationOrderID” name referring to the allocation order.