Close Navigation
Learn more about IBKR accounts

Placing Orders using TWS Python API

Lesson 6 of 10
Duration 13:09
Level Intermediate
Close Navigation

In this lesson we discuss how orders can be placed, monitored, modified, and cancelled from the TWS API. To demonstrate the essential components necessary to place an order, a simple Python program is introduced which places an AAPL order to a paper account, and then prints order status messages to the console. Important topics associated with placing and monitoring orders from the API, including the master client ID, and the API maximum message rate are introduced.

Study Notes:

A common reason to use the Trader Workstation API is to place an order to an Interactive Brokers’ account from a third party or custom software. This might be part of an automated strategy or caused by a manual user interaction in an API client’s graphical user interface.

In this lesson we will discuss the placeOrder function in the API EClient class, describe how it is used for order placement, as well as describing those functions which were used to monitor order stats and execution information.

Essentially, any order type which we place from TWS can also be placed from the API. This includes advanced order types such as IB Algos, bracket orders and conditional orders. Most order attributes from TWS can also be used with the TWS API. In general, order attributes must be set from the API by defining different fields within the API order class when an order is sent. However, there are also some attributes which will be read from the presets in the session of TWS or the IB Gateway to which the API client is connected.

Interactive Brokers offers an array of orders and attributes and provides access to more than 100 exchanges worldwide. This leads to numerable combinations of order types, instruments and exchanges. The best tool to use and check if a particular combination of order type, instrument and attribute is valid is in TWS itself.

Before creating a particularly complex order from the API, it is always recommended to first check if the same order can be created in TWS Then, if the combination isn’t valid, this will be indicated by TWS because either the order type will be greyed out or not displayed for the combination.

For a simple demonstration of invoking the placeOrder function and receiving the associated callbacks for monitoring orders, we will show how to place an order in the paper account for AAPL stock using a simple program.

Before placing any order to a live account, it is recommended to first place the order in the paper account to verify your order is being placed as intended.

Paper accounts are offered to all Interactive Brokers account holders and demo accounts can be accessed even before a live account is opened.  

Here, I’ve created a file called placeOrder.py which demonstrates how to place the AAPL order through the API.

In this file, we will create the test class which drives from both EClient and EWrapper. But instead of overriding the functions as we did previously, we will override functions related in EWrapper for placing and monitoring orders. Namely nextValidId, orderStatus, openOrder and execDetails or execution details.

The callback nextValidID located at the top is used to receive the next valid order ID for the API client to place a new order.

The next valid ID callback is invoked in response to the API client either by calling the function’s reqIds in the EClient class or invoked after the initial connection is completed.

For this lesson, we will continue using AAPL as our contract. And while I could type out my contract object and put it directly into my order request later, this example can show off some benefit of using a combined class for EClient and EWrapper. I can use my returned contractDetails variable from EWrapper.contractDetails, and specify “contractdetails.contract” to use the contract object directly.

We will start the lesson by placing a simple market order. To get started, I will need to start a process similar to our contracts by creating an order object. I will call this “myorder”. Next, we will need to cover a few attributes that will always need to be included in our orders. I will start with myorder.orderId and set this equal to the orderId variable from the nextValidId method.

Next, I will dictate my action, using myorder.action. In this case, I will set the value to BUY, though you may enter SELL here if that is preferred. Then, I will include my order type, and set this equal to “MKT” for market order.

And then we will end by specifying my quantity. To do so, we will enter myorder.totalQuantity and set this equal to 10. And those are all the required values to place a simple order. We will discuss additional flags later, but this is simply the minimum.

Now that we have our contract object, and our order object, we are ready to move on to our order placement. Here we can make a request to EClient’s placeOrder method. To do so, I will type self.placeOrder. Then in parentheses, I will reuse my orderId as my requestId, then I will specify my contract object, then my order object.

That is all that is needed to place an order. Unlike requesting market data or contract details, we technically do not require that any EWrapper method be called. I can look in Trader Workstation and see that this order has been placed.

However, I think we may want to see details on our orders returned to us after we submit them. Let’s first create a limit order to better showcase these fields.

I will keep most of my order object the same as before, with a few key exceptions. First, I will change my action to “SELL” instead of “BUY”.

After that I will move on to Time in Force, or TIF. I will be using “GTC”, though this field has the same options as TWS, such as MOC for market on close. I would note that if no TIF is specified, it will use DAY order by default.

Then, I can change my order type to LMT instead of MKT.

And finally, I will use myorder.lmtPrice to specify my limit value. For AAPL, I will specify 144.80

As we could see from our contract details request, all contracts have a minimum tick value. For AAPL stock, for instance, this is one cent min tick, so orders can’t have prices specified with more than two decimal places or less than one cent. There is more information about finding the minimum increment for different instruments in the API reference guide.

Now that we have the order ID, the contract object and the order object, we can invoke place order. After TWS receives a valid order, it will begin sending back messages to the callback functions, order status, open order and execution details to indicate an order status as well as any changes in the order status, which occur.

Open Orders

The openOrder method will show us details whenever an order is placed. We will see the full order and contract details of a given order after it has been placed. For instance, in this case we would expect to see an AAPL limit order there with a time in force of GTC and an order price of 144.80 USD.

It is important to note that openOrder also returns the orderState object. orderState will include values such as commission, initial margin, and maintenance margin. Just like we did with contractDetails before, we can review the order_state.py file in the source code to see what other flags can be requested specifically.

Now, in addition to the openOrder function, we will also want to include the orderStatus method. While openOrder provides information on an order once it is placed, orderStatus provides information on the order thereafter. After every submission of an order, as soon as the order is valid usually you would see an order status callback which would be either pre-submitted, submitted or filled. Sometimes there will be duplicates which might need to be filtered out by the API client.

Order Executions

If the order executes there will always be execDetails or execution details for every partial fill. This can be thought of as the summary of the order. We can review the orderId, the executionId, information on the contract, information on the average price, and so on.

So, if there is more than one fill for a particular order you would see multiple callbacks for exec details. The callback would have information such as the order ID, which would be different than the API order ID. This is an order ID which is unique in the account and generated by TWS.

You would see the number of shares which have executed. You would also see a last liquidity flag which would tell us if this execution either added or removed liquidity from the market.

I will go ahead and run the script and that should immediately place the order for AAPL stock. A sell order for ten shares at the limit price of 144.00.

When we scroll down to the bottom, we can see that we receive an immediate execution. That’s because the current price of AAPL is at about 144.75 and this is during market hours, so the order immediately became active.

Before that occurred, the callback we received was open order. Open order callback let us know the details of the order.

The next orderStatus we receive will be a filled status because the order filled pretty much immediately, at least in the paper trading simulation engine and that tells us how many shares filled, how many are remaining, and also the fill price.

We also received execution details more or less simultaneously with that order status so there’s information like the exact execution details ID as well as the same information about the number of shares which filled and the filled price.

Modify Orders

Now let’s say we want to modify an order. Because we included the EWrapper callbacks for our order, we can receive our order ID, and easily modify this order whenever we need. We can simply return to our order object with our problematic orderId, change our orderId from nextValidId’s orderId, and use it here. Now, any changes applied to this order submission will modify our original order.

While I may be using a very simple example here with very human error, I would like to emphasize that this process can all be done programmatically for on-the-fly adjustments to your orders to coincide with the market, or other more complex examples.

Let’s go ahead and walk through this process. Let’s say I placed an order for $1490.00 instead of my $149.00 example. Just a simple typo with very big repercussions all because I missed the decimal place. Because I have the orderId from that request in my callback from before, I can modify this order. I can change my order to use orderId 15 again, then put in the correct price. Now, if I go ahead and put $149.00 in my limit price value and then resubmit the order, I can run my code again, and we can see that this order updated. And if you had any doubts, we can return to Trader Workstation and see that this order has updated there as well.

These are just some order types that Interactive Brokers offers through the Trader Workstation, and you are welcome to explore our wide array of available offerings notated in our documentation.

This concludes our video on Basic Orders and Order Modification in the TWS API. Thank you for watching, and we look forward to having you join us for more TWS Python API lessons.

TWS API Online Documentation

Available Order Types & Algos using TWS API

Retrieving current active Orders

Order Management

Minimum Price Increment

Checking Margin Changes

Order Efficiency Ratio (OER)

from ibapi.client import *
from ibapi.wrapper import *

class TestApp(EClient, EWrapper):
	def __init__(self):
		EClient.__init__(self, self)

	def nextValidId(self, orderId: OrderId):

		mycontract = Contract()
		mycontract.symbol = "AAPL"
		mycontract.secType = "STK"    
		mycontract.exchange = "SMART"
		mycontract.currency = "USD"

		self.reqContractDetails(orderId, mycontract)

	def contractDetails(self, reqId: int, contractDetails: ContractDetails):
		print(contractDetails.contract)

		myorder = Order()
		myorder.orderId = reqId
		myorder.action = "SELL"
		myorder.tif = "GTC"
		myorder.orderType = "LMT"
		myorder.lmtPrice = 144.80
		myorder.totalQuantity = 10

		self.placeOrder(myorder.orderId, contractDetails.contract, myorder)


	def openOrder(self, orderId: OrderId, contract: Contract, order: Order, orderState: OrderState):
		print(f"openOrder. orderId: {orderId}, contract: {contract}, order: {order}")

	def orderStatus(self, orderId: OrderId, status: str, filled: Decimal, remaining: Decimal, avgFillPrice: float, permId: int, parentId: int, lastFillPrice: float, clientId: int, whyHeld: str, mktCapPrice: float):
		print(f"orderId: {orderId}, status: {status}, filled: {filled}, remaining: {remaining}, avgFillPrice: {avgFillPrice}, permId: {permId}, parentId: {parentId}, lastFillPrice: {lastFillPrice}, clientId: {clientId}, whyHeld: {whyHeld}, mktCapPrice: {mktCapPrice}")

	def execDetails(self, reqId: int, contract: Contract, execution: Execution):
		print(f"reqId: {reqId}, contract: {contract}, execution: {execution}")

app = TestApp()
app.connect("127.0.0.1", 7497, 100)
app.run()

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.

34 thoughts on “Placing Orders using TWS Python API”

    • Thank you for asking, Manfred. To submit an order to work outside of regular trading hours (Outside RTH) you can either specify it at the time of order creation or define it as an order preset to be used automatically when available. Please review this step-by-step FAQ on how to trade outside RTH on TWS: https://www.ibkr.com/faq?id=27271538. It is also possible to make these orders in Client Portal (https://www.ibkr.com/faq?id=102543637) and IBKR Mobile (https://www.ibkr.com/faq?id=29088910). We hope this helps!

      If your question is specific to an API and this response did not answer it completely, please create a web ticket. The best category to choose is “API.” Our API experts will be able to help you out from there!

  • Hello, I put this example code to teste and I received this following error:
    ‘TypeError: EClient.__init__() missing 1 required positional argument: ‘wrapper’.
    Can you help please?

    • Hello Paulo, we appreciate your question. For this inquiry, please open a web ticket in Client Portal (click the “Help?” in the upper right menu, then “Secure Message Center”). The best category to choose is “API.” Our API experts will be able to help you out from there!

  • hi! while using def displayGroupUpdated(self, reqId: int, contractInfo: str):

    contract info will give me a number@exchange 8314 for IBM how do i translate the 8314 to IBM ?

    or is there a way to just create an order with the unique
    number for the corresponding stock?

    thanks and have a good one !

    • Hello Snir, we appreciate your question. For this inquiry, please open a web ticket in Client Portal (click the “Help?” in the upper right menu, then “Secure Message Center”). The best category to choose is “API.” Our API experts will be able to help you out from there!

  • Hi,
    I get this error:
    Name “Decimal” is not found! How can I resolve this?
    Is there a way to place orders keep track of our balance over time on the paper account?

    • Daniel, for this inquiry, please open a web ticket in Client Portal (click the “Help?” in the upper right menu, then “Secure Message Center”). The best category to choose is “API.” Our API experts will be able to help you out from there!

  • Hello,

    maybe not the right topic, but after a successful verification with IB (of epic proportions :)), I would like to create some kind of RSI based applications with DCA trading method, with which we determine the deal start condition according to the RSI. I am actually interested in whether such applications or other trading strategies can be implemented.
    Thanks for the reply.
    Best regards

    • Good question, Miroslav. Please direct this question to our API experts by creating a web ticket in Client Portal with “API” as the category.

  • Hello, I am trying to run the code as posted above, but am receiving the error:

    File “c:\TWS API\source\pythonclient\ibOrder.py”, line 30, in
    app = TestApp()
    ^^^^^^^^^
    TypeError: EClient.__init__() missing 1 required positional argument: ‘wrapper’

    Could you advise at all what I might change? Thank you!

    • Hello CMH, we appreciate your question. For this inquiry, please open a web ticket in Client Portal (click the “Help?” in the upper right menu, then “Secure Message Center”). The best category to choose is “API.” Our API experts will be able to help you out from there!

  • Same problem:
    “Hello, I put this example code to teste and I received this following error:
    ‘TypeError: EClient.__init__() missing 1 required positional argument: ‘wrapper’.
    Can you help please?”
    –> General hint for this?

    • Hello Thomas, we appreciate your question. For this inquiry, please open a web ticket in Client Portal (click the “Help?” in the upper right menu, then “Secure Message Center”). The best category to choose is “API.” Our API experts will be able to help you out from there!

    • Hello David, thank you for asking. I am not sure what you mean by “OrderID,” however, you cannot reset your username or account number. The only thing you can reset is the dollar amount in the simulation account. Please review this FAQ for more information: https://www.ibkr.com/faq?id=32644862

  • Hi, I tried placing order thru IB gateway but it showed error: can’t write – with server and client version 156. I am using linux and the latest IB gateway api build 10.25, settings and pre

    However, when I tried it on windows – same setup. It works and it showed server and client version 172.

    May I know why is there a difference in the server and client versions between the two different OS? and if this is the reason why I wasn’t able to place order?

  • Hello,
    These two topics are not discussed in the video, is there a separate video?
    Checking Margin Changes
    Order Efficiency Ratio (OER)

    Thanks,
    Sam

  • How to place order quantity beyond exchange freeze quantity ?
    Max 50 orders per second is allowed , i would like to place more than 50X Freeze qty

    • Hello Sanjay, thank you for reaching out. Freeze quantity is a limitation of each exchange and is not something that can be resolved through the API or Interactive Brokers.

  • I’m attempting to place a trailing stop order either for long position or short position depending on trading parameters. I’m using the trailingpercent method in the code and wanted to know if using the trailing stop on a short position will work? I had a simulated short sell order with a trailing stop and the stock price was $213 but when I looked at the trailing stop which should have been a “BUY” because I was short selling, it appeared the trailing “BUY” was lower then stock purchase price; which would be incorrect because it should be the inverse on a short sell. Can you provide guidance on this?

    • Hello, thank you for reaching out. For users looking to trade with Trailing Stop Limit orders, you will need to include both the “price” and “auxPrice” fields to complete a successful order. You can find an example of this order here under the CURL tab ( https://ibkrcampus.com/ibkr-api-page/order-types/#trailing-stop-limit-order ). We are looking to expand our available tutorials and will look to add the trailing orders in our expansion. Thank you for your feedback.

  • How to identify the list of open orders that can be canceled? Can I cancel a voidable order, based on its name and order type?
    I can’t find anything on the internet. Can you give me the code in detail?
    THANKS

    • Hello, thank you for reaching out. Generally speaking, calling EClient.reqAllOpenOrders() or EClient.reqOrderStatus() will return the current status of an order, be it submitted, canceled, filled, or otherwise. You can reference this status if the order can be canceled or not. Orders can only be canceled based on orderId. Please reach out via web ticket with any more questions or concerns: https://www.interactivebrokers.com/sso/resolver?action=NEW_TICKET. Our API experts would love to guide you!

  • I followed the instructions on trailing stop limit orders. Therefore, I defined action, orderType, totalQuantity, trailStopPrice, limitPriceOffset and the trailing amount. I placed several orders in my paper trading account via API and manually in the TWS and played with the values. In the end there was no difference in outcome. Sooner or later every order was executed at the original stop price **without any trailing** and after all gains were eaten up. Either I miss something e. g. in the settings or there is a bug on IB’s side. Please advice. Thank you in advance.

    • Hello, we appreciate your question. Both of Interactive Brokers’ APIs support OVERNIGHT trading.

      In the case of TWS API, you must use TWS and the API Latest releases (10.26 and above). Then, you must specify the OVERNIGHT exchange while submitting the order. One example of this contract would look like this:

      contract = Contract()

      contract.symbol = “AAPL”

      contract.secType = “STK”

      contract.currency = “USD”

      contract.exchange = “OVERNIGHT”

      contract.primaryExchange = “NASDAQ”

      The client portal API is similar, in that the listingExchange must be specified in the same manner. Any example order body to mirror the above AAPL contract would be something like this:

      {

      “conid”:265598,

      “listingExchange”: “OVERNIGHT”

      }

      We hope this helps!

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.