Close Navigation
Learn more about IBKR accounts

Complex Orders

Lesson 7 of 11
Duration 8:15
Level Intermediate
Close Navigation

In this lesson, we will be discussing how to place more complex orders using the client portal API. This lesson will be largely predicated on our prior lesson, Placing Orders. We will be building on those fundamentals to discuss placing Bracket and Combo/Spread orders using the CPAPI.

Study Notes:

Hello, and welcome to this lesson on Complex Orders in the Interactive Brokers Client Portal API. In this lesson, we will be discussing how to place bracket and spread orders using the Client Portal API.

Bracket Order

To begin, let’s first discuss how to create a bracket order for using the CPAPI. Given the starting point is the same, I will present the same foundation as my previous lesson for discussing order placement. Here we can see I will still be using the iserver/account/{accountId}/orders endpoint. We will still be using the same json_body value for my request, and using the standard post request and json.dumps method I have use through the series.

Now can start moving into newer territory. You may have noticed that our body references ‘orders’ rather than just submitting a single ‘order’. That is because multiple legs can be sent in a single request. We can start with my original AAPL MKT order I had made before, but now I can add a slight tweak. I will simply implement the field, ‘cOID’, which stands for ‘customer order identifier.’ While you are welcome to place orders sequentially like before and retrieve the order id before placing the next, we are able to pre-define an orderId that can be used to attach multiple legs together. I will set my ‘cOID’ variable equal to ‘AAPL_BRACKET-MMDD’. Though you can set this to any simple identifier that would help you.

With our parent order set and our cOID defined, we can move on to our first child order. I can copy my parent array as a starting point. I’m still going to keep most of my fields the same, but with a few tweaks. I will change my orderType to LMT, and create a price field of 190. Then, I will change my cOID to ‘AAPL_BRACKET-MMDD-PT’ to signify a profit taker. Finally, I can introduce a new field, ‘parentId’ and set it equal to the original ‘cOID’, ‘AAPL_BRACKET-MMDD’. So now we have a profit taker built.

I can copy this, and then change my orderType again, now to ‘STP’. Then I will drop my price down to 185. Finally, I’ll change the ‘cOID’ from “-PT” to “-SL”. Now I have a full bracket order with the parent, profit taker and stop loss legs attached.

I would note that the Client Portal API maintains the same limitations as Trader Workstation, with maximum of 6 legs per order.

With everything built, I will run my code to send all three of my orders. Just like in standard orders, you might encounter a precautionary setting form an order. If I utilize my reply endpoint, I can confirm this order, and we will see all three order confirmations. 

Combo or Spread Orders

Combination orders or spread orders may also be placed using the same orders endpoint. However, these are a bit different than how bracket orders are handled. Let’s start with a basic limit order again. In the case of combo orders, we will be replacing the conid field with ‘conidex’ instead. The conidex field is a string representation of our combo order parameters. This will follow the format of: ‘{spread_conid};;;{leg_conid1}/{ratio},{leg_conid2}/{ratio}‘

Let’s go ahead and break this down. First, spread_conid is a unique identified used to denote a spread order.  For US combos, the spread_conid is set to 28812380. For all other countries, you will need to use the format ‘spread_conid@exchange’.

Other countries spread_conid: {AUD – 61227077, CAD – 61227082 ,CHF – 61227087 ,CNH – 136000441,EUR – 58666491,GBP – 58666494,HKD – 61227072,INR – 136000444 ,JPY – 61227069 ,KRW – ,136000424,MXN – 136000449,SEK – 136000429,SGD – 426116555 ,USD – 28812380}

Following our spread_conid, we will then follow with 4 semicolnons, and then introduce our first leg_coind. This will be the first contract to trade. In my case, I will use 497222760, which is the coming ES Futures contract. You will need to follow this with ‘/’, and then your spread ratio.

            The ratio indicates two parts. The first is the sign of the ratio, whether it is positive or negative. Positive signs indicate a ‘Buy’ side, while a negative value represents a ‘Sell’ side. This could also be explained as a state of ‘Long’ and ‘Short’ respectively, depending on your current position and intention.

Moving on from the sign, we have the actual ratio. These are multipliers of your quantity value. For example, we are using a quantity of ‘3’ in our order today. If I use a ratio on my first leg of a positive ‘1’, then I will be buying 3 contracts. However, in options you may choose to have 1 options contract per 100 shares of the underlying stock. In that case, your options leg would use a ratio of 1, while your stock leg would use a ratio of 100.

Now that we have the spread_conid and our first leg, we can now comma-separate any additional legs for our order. I will add a comma after our last ratio, followed by the conid for the ES back month, 495512552, and set my ratio to a -1. This means that I will be buying the front month and shorting the back. You are welcome to sell both legs, buy both, or change which leg is bought and which is sold.

The only remaining outlier would involve the ‘price’ field. This price is the combined value of both legs, including their ratio. Given I have a long and a short leg, I will need to subtract the value of my back month from my front month to find my price. Given I know my values are as follows:


Front month     =          ( 1) * 4493.00

Back month      =          (-1) * 4543.00

Total                 =          -50.00

With all of my values set, I can go ahead and place my order. After receiving my 200 OK response, I can see my order submitted successfully from the “submitted” field.

Thank you for watching this lesson on complex orders in the Client Portal API. If you find this lesson helpful, please check out our other lessons in the Client Portal API tutorial series.

Code Snippet – bracketOrder

import requests
import json
import urllib3

# Ignore insecure error messages
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def orderRequest():
  
    base_url = "https://localhost:5000/v1/api/"
    endpoint = "iserver/account/DU5240685/orders"

    json_body = {
        "orders": [
            {
            "cOID": "AAPL_BRACKET_MMDD",
            "conid": 265598,
            "orderType": "MKT",
            "side": "BUY",
            "tif": "DAY",
            "quantity": 10
            },
            {
            "parentId":"AAPL_BRACKET_MMDD",
            "cOID": "AAPL_BRACKET_MMDD-PT",
            "conid": 265598,
            "orderType": "LMT",
            "price":190,
            "side": "SELL",
            "tif": "DAY",
            "quantity": 10
            },
            {
            "parentId":"AAPL_BRACKET_MMDD",
            "cOID": "AAPL_BRACKET_MMDD-SL",
            "conid": 265598,
            "orderType": "STP",
            "price":185,
            "side": "SELL",
            "tif": "DAY",
            "quantity": 10
            }
        ]
    }
    
    order_req = requests.post(url=base_url+endpoint, verify=False, json=json_body)
    order_json = json.dumps(order_req.json(), indent=2)

    print(order_req.status_code)
    print(order_json)

if __name__ == "__main__":
    orderRequest()

Code Snippet – comboOrder.py

import requests
import json
import urllib3

# Ignore insecure error messages
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def orderRequest():
  
    base_url = "https://localhost:5000/v1/api/"
    endpoint = "iserver/account/DU5240685/orders"

    json_body = {
        "orders": [
            {
            "conidex":"28812380;;;497222760/1,495512552/-1",
            "orderType": "LMT",
            "price": -50,
            "side": "BUY",
            "tif": "DAY",
            "quantity": 3
            }
        ]
    }
    
    order_req = requests.post(url=base_url+endpoint, verify=False, json=json_body)
    order_json = json.dumps(order_req.json(), indent=2)

    print(order_req.status_code)
    print(order_json)

if __name__ == "__main__":
    orderRequest()

Join The Conversation

If you have a general question, it may already be covered in our FAQs. If you have an account-specific question or concern, please reach out to Client Services.

4 thoughts on “Complex Orders”

    • Hello, thank you for pointing this out. This is now reflected in the article. We hope you continue to engage with IBKR Campus!

  • In your example of an bracket order is a error. look at the sides.
    It is: ‘BUY’, ‘BUY’, ‘BUY’.
    It should be: ‘BUY’, ‘SELL, ‘SELL’.

    • Hello Daniel, thank you for pointing this out. This should now be reflected in the article. We hope you continue to engage with IBKR Campus!

Leave a Reply

Your email address will not be published. Required fields are marked *

Disclosure: Interactive Brokers

The analysis in this material is provided for information only and is not and should not be construed as an offer to sell or the solicitation of an offer to buy any security. To the extent that this material discusses general market activity, industry or sector trends or other broad-based economic or political conditions, it should not be construed as research or investment advice. To the extent that it includes references to specific securities, commodities, currencies, or other instruments, those references do not constitute a recommendation by IBKR to buy, sell or hold such investments. This material does not and is not intended to take into account the particular financial conditions, investment objectives or requirements of individual customers. Before acting on this material, you should consider whether it is suitable for your particular circumstances and, as necessary, seek professional advice.

The views and opinions expressed herein are those of the author and do not necessarily reflect the views of Interactive Brokers, its affiliates, or its employees.

Disclosure: API Examples Discussed

Throughout the lesson, please keep in mind that the examples discussed are purely for technical demonstration purposes, and do not constitute trading advice. Also, it is important to remember that placing trades in a paper account is recommended before any live trading.

IBKR Campus Newsletters

This website uses cookies to collect usage information in order to offer a better browsing experience. By browsing this site or by clicking on the "ACCEPT COOKIES" button you accept our Cookie Policy.