ib-async
/g/ib-async
The goal of the ib_async library is to make working with the Trader Workstation API from Interactive Brokers as easy as possible.
This group replaces the former ib_insync forum.
You may also check out the Discord server at: https://discord.gg/8xsy8a2r2c
The main features are:
An easy to use linear style of programming;
An IB component that automatically keeps in sync with the TWS or IB Gateway application;
A fully asynchonous framework based on asyncio and eventkit for advanced users;
Interactive operation with live data in Jupyter notebooks.
Be sure to take a look at the notebooks, the recipes and the API docs.
Installationpip install ib_async
Requirements:
Python 3.10 or higher
We plan to support Python releases 2 years back which allows us to continue adding newer features and performance improvements over time.
A running IB Gateway application (or TWS with API mode enabled)
stable gateway 鈥� updated every few months
latest gateway 鈥� updated weekly
Make sure the API port is enabled and 'Download open orders on connection' is checked.
You may also want to increase the Java memory usage under Configure->Settings->Memory Allocation to 4096 MB minimum to prevent gateway crashes when loading bulk data.
The ibapi package from IB is not needed. ib_async implements the full IBKR API protocol internally.Mon, 29 Apr 2024 15:03:35 -0700Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.
/g/ib-async/message/307
<p>Okay, MktDataType 2 may be the answer. Parts of the documentation say it is the quotes recorded at the last closing, which is not what I want, but part of it says it is the last quotes seen by their system, which is what I want. Since the market is closed, I have to find out on Monday. Thank you for your help.</p>
<p>There are still some pending questions that I need to investigate:</p>
<ol>
<li>Does MkDataType 2 provide the last quotes recorded at closing or just the last recorded quotes?</li>
<li>Do I need to call reqMktData twice for each contract, once with type 2 and a second time with type 1, to get both the last recorded quotes and the live updates?</li>
<li>If I do this, it may mask the problem that a bid is in fact "stuck" and is never updated, which means I have to write extra monitoring code to see if quotes do update.</li>
</ol>3n5uf1mq3@... (Little Trader)Fri, 04 Apr 2025 17:47:45 -0700Re: Determining which stock is bringing my portfolio into a loss
/g/ib-async/message/306
<html><head><meta http-equiv="Content-Type"/></head><body><div>I'm curious, does it work during regular trading hours?</div><div><br/></div><div><br/></div><div><br/></div><div id="composer_signature"><div style="font-size: 12px; color: #575757"></div></div><div><br/></div><div><br/></div>climbermel@... (Mel)Fri, 04 Apr 2025 17:04:27 -0700Re: Determining which stock is bringing my portfolio into a loss
/g/ib-async/message/305
<html><head><meta http-equiv="Content-Type"/><meta name="Generator"/></head><body lang="EN-US"><div class="WordSection1"><p class="MsoNormal">Hi,</p><p class="MsoNormal">聽</p><p class="MsoNormal">Yes, setting the market data type to 2 solved the problem. </p><p class="MsoNormal">聽</p><p class="MsoNormal">Pranav</p><div style="border: none; border-top: solid #E1E1E1 1.0pt"><p class="MsoNormal"></p></div></div>pranav@... (Pranav Lal)Fri, 04 Apr 2025 16:37:43 -0700Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.
/g/ib-async/message/304
<p>Type 2 is the last data recorded at market close, which is not what I want.</p>
<p>Also, "live" does not usually just mean that I will only get the data when there are new updates. It also means that I will get the most recent quote when there are no new updates.</p>
<p>If it were to only get the data when there is an update, then all the snapshot functions wouldn't work. Also, it is not really consistent with my experience. I find that sometimes it is missing a bid and sometimes the close. Note that a market maker rarely only send the ask and not the bid when updating their quotes. Missing the close is even harder to explain. The fact that I never experienced this on the initial connection to a freshly started gateway also means that this is perhaps not the reason.</p>3n5uf1mq3@... (Little Trader)Fri, 04 Apr 2025 11:38:42 -0700Re: Determining which stock is bringing my portfolio into a loss
/g/ib-async/message/303
<div>Have a look at my reply to another topic, I think it is closely related to your issue because you are requesting after close: /g/ib-async/message/302</div>biney59@...Fri, 04 Apr 2025 10:48:59 -0700Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.
/g/ib-async/message/302
<div>From my understanding, <strong>ib.reqMktData(contract)</strong> requests LIVE updates, meaning updates will be sent if changes occur after your request. Meaning if your contract is not active, there is chance it may not get populated right away. The documentation:</div>
<div>
<ul style="color: #000000; font-family: Roboto, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-transform: none; word-spacing: 0px; background-color: #ffffff">
<li>Beginning in TWS<span>聽</span><strong>v970</strong>, a<span>聽</span><a class="el" style="color: #a02200; font-weight: bold; text-decoration: none" href="https://interactivebrokers.github.io/tws-api/classIBApi_1_1EClient.html#ae03b31bb2702ba519ed63c46455872b6" rel="nofollow noopener" target="_blank" target="_blank">IBApi.EClient.reqMarketDataType</a><span>聽</span>callback of<span>聽</span><strong>1</strong><span>聽</span>will occur automatically after invoking reqMktData if the user has live data permissions for the instrument.</li>
</ul>
<div><a href="https://interactivebrokers.github.io/tws-api/market_data_type.html" target="_blank" rel="nofollow noopener">https://interactivebrokers.github.io/tws-api/market_data_type.html</a></div>
<div>聽</div>
<div>You might need to request different type of market data if you always want data, for example, set type to 2:聽</div>
<div>
<table class="doxtable">
<tbody>
<tr>
<td>Frozen</td>
<td>2</td>
<td>Frozen market data is the last data recorded at market close. In TWS, Frozen data is displayed in gray numbers. When you set the market data type to Frozen, you are asking TWS to send the last available quote when there is not one currently available. For instance, if a market is currently closed and real time data is requested, -1 values will commonly be returned for the bid and ask prices to indicate there is no current bid/ask data available. TWS will often show a 'frozen' bid/ask which represents the last value recorded by the system. To receive the last know bid/ask price before the market close, switch to market data type 2 from the API before requesting market data. API frozen data requires TWS/IBG v.962 or higher and the same market data subscriptions necessary for real time streaming data.</td>
</tr>
</tbody>
</table>
</div>
</div>biney59@...Fri, 04 Apr 2025 10:47:32 -0700ib.reqMktData() does not get certain fields when connecting to the gateway the second time.
/g/ib-async/message/301
<p>I am having an odd problem. Everything works as expected when my client makes an initial connection to the gateway. However, if I restart the client process, sometimes <code>reqMktData()</code>won't get all the fields. Specifically, if I do the below, I find everything in the <code>ticker</code> object are filled except for <code>bid</code> and <code>bidSize</code>, which are <code>nan</code>. Sometimes, it is the <code>close</code> price that is <code>nan</code>.</p>
<pre class="prettyprint"><code class="language-python">
ticker = ib.reqMktData(contract)
asyncio.sleep(0.5)
# ticker.bid, ticker.bidSize, ticker.close may be nan
</code></pre>
<p>I have logic to retry the subscription as follows, but it rarely does anything:</p>
<pre class="prettyprint"><code class="language-python">
ib.cancelMktData(contract)
asyncio.sleep(0.1)
ib.reqMktData(contract)
</code></pre>
<p>When this happens, the same few contracts out of 30 have this problem no matter how many times I retry (like the above). The other contracts are completely fine.</p>
<p>This does not happen every time. Occasionally, restarting the client to make a new connection the second time is okay, and when the second time is okay, it tends to be okay for subsequent connections. Over 50% of the time, however, making the connection the second time will have the above-described problem. If the second time fails, all subsequent connections will also fail.</p>
<p>The problem is not limited to the gateway. Connecting with TWS has exactly the same problem.</p>
<p>Restarting the gateway fixes this problem. I have never seen this happening to the initial connection to the gateway instance. This seems to say that the gateway has to be restarted every time I restart my client, which is tedious.</p>
<p>Has anyone encountered similar issues?</p>3n5uf1mq3@... (Little Trader)Fri, 04 Apr 2025 10:27:37 -0700Determining which stock is bringing my portfolio into a loss
/g/ib-async/message/300
Hi all,<br /><br />I am trying to write some code to determine which stock is bringing my<br />portfolio into a loss.<br /><br />My logic is to see if the averageCost is greater than the current market<br />price for each stock in the portfolio.<br /><br />The problem is that the current market price is nan. I am running this code<br />after market close. Here is the relevant snippet. What am I missing?<br />ib.connect('127.0.0.1', 4001, clientId=999990)<br />positions=ib.positions()<br />lc=0<br />for p in positions:<br /> <br /> [ticker] = ib.reqTickers(p.contract)<br /> print(p.contract.symbol)<br /> <br /> print("number of shares=" + str(p.position))<br /> print("Cost per share=",ib.portfolio()[lc].averageCost)<br /> print("Current price per share=",ticker.marketPrice())<br /><br /> lc+=1<br /> ib.sleep(1)<br />Pranavpranav@... (Pranav Lal)Thu, 03 Apr 2025 18:26:27 -0700Re: Clicking an override button
/g/ib-async/message/299
<html><head><meta http-equiv="Content-Type"/><meta name="Generator"/></head><body lang="EN-US"><div class="WordSection1"><p class="MsoNormal">Hi,</p><p class="MsoNormal">聽</p><p class="MsoNormal">I do not use as sophisticated an approach. I have just set the property for all orders. There is no harm in setting it that I have seen.</p><p class="MsoNormal">聽</p><p class="MsoNormal">Pranav</p><p class="MsoNormal">聽</p><div><div style="border: none; border-top: solid #E1E1E1 1.0pt"><p class="MsoNormal"></p></div></div></div>pranav@... (Pranav Lal)Sat, 29 Mar 2025 11:52:47 -0700Re: Clicking an override button
/g/ib-async/message/298
<html><head><meta http-equiv="content-type"/></head><body>Thanks for your reply<div><br/></div><div>So if I follow you correctly,聽</div><div><br/></div><div><ul class="MailOutline"><li>you submit an order,聽</li><li>it fails,聽</li><li>you check your Trade.log for the error message,聽</li><li>and in a future order, you set Order.advancedErrorOverride based on the error message on previous point</li></ul></div><div><br/></div><div><br/></div><span><span></span></span><span><br/></span><div><br id="lineBreakAtBeginningOfMessage"/><div><br/></div></div>yo@... (Gonzalo Saenz)Sat, 29 Mar 2025 07:54:01 -0700Re: Clicking an override button
/g/ib-async/message/297
<html><head><meta http-equiv="Content-Type"/><meta name="Generator"/></head><body lang="EN-US"><div class="WordSection1"><p class="MsoNormal">Hi <span style="font-family: sans-serif">Gonzalo</span>,</p><p class="MsoNormal">聽</p><p class="MsoNormal">Documentation is sketchy to say the least. See the below link. </p><p class="MsoNormal"><a href="https://interactivebrokers.github.io/tws-api/order_submission.html" rel="nofollow noopener" target="_blank">https://interactivebrokers.github.io/tws-api/order_submission.html</a></p><p class="MsoNormal">聽</p><p class="MsoNormal">The rest of it was trial and error. </p><p class="MsoNormal">聽</p><p class="MsoNormal">Pranav</p></div>pranav@... (Pranav Lal)Thu, 27 Mar 2025 16:53:24 -0700Re: Clicking an override button
/g/ib-async/message/296
<html><head><meta http-equiv="Content-Type"/></head><body><div style="font-family: Verdana, Arial, Helvetica, sans-serif; color: #000000"><div><div>Where did you get this information? Is there any documentation for this?</div><div><br/></div><div>From time to time my orders are canceled, this might help聽</div><div><br/></div><div><br/></div><div><br/></div><div></div> <br/> </div><div class="zmail_extra_hr" style="height: 0px; margin-top: 10px; margin-bottom: 10px; line-height: 0px"></div> <br/> <div class="replyHeader">---- On Thu, 27 Mar 2025 17:41:35 +0100 Pranav Lal<pranav@...> wrote ----</div><div><br/></div></div>yo@... (Gonzalo Saenz)Thu, 27 Mar 2025 13:55:48 -0700Re: Clicking an override button
/g/ib-async/message/295
Hi all,<br /><br /><br />Problem solved. I had to use a key value pair when specifying the string in<br />the advancedErrorOverride property.<br />advancedErrorOverride="8229,SURVEILLANCE"<br /><br />I initially thought that ib_async did not support this property which is why<br />I switched to the tws API.<br />Pranavpranav@... (Pranav Lal)Thu, 27 Mar 2025 09:41:42 -0700Re: Trying to load data asynchronously and struggling with asyncio again
/g/ib-async/message/294
<p><code>ib.reqHistoricalDataAsync</code> takes timeout parameter, set it to 0 and this method will not time out.</p>tomasz2605@... (t1user)Wed, 26 Mar 2025 03:40:00 -0700Re: ib.reqTickers() conflicts with ib.reqTickByTickData()
/g/ib-async/message/293
<p>thank you for replying,
I have identified the problem: the reqTickers was nested in the reqTickByTickData, so I changed the App structure.
BTW do you know the function to use for nested call (even though I remember that nested asyncio and blocking was not recommended)?
best</p>rmln@... (barone)Tue, 25 Mar 2025 09:40:13 -0700Re: Live and paper data mixed
/g/ib-async/message/292
<p>What seems to be happening is the instance of IB() is keeping data and not actually sending a request to TWS. The API logs only show one request being sent per connection, not the two I was expecting from the code above.</p>
<p>If I have two instances of IB(), and switch between those, I get correct data. Just disconnecting, changing port, and reconnecting within the same instance of IB() seems to be causing the confusion.</p>
<p>Any delay between disconnect and reconnect, makes no difference as long as it's still the same instance of IB().
Could someone who maintains the library investigate?</p>bmore@... (Glenn)Tue, 25 Mar 2025 07:56:58 -0700Re: Live and paper data mixed
/g/ib-async/message/291
<html><head><meta http-equiv="Content-Type"/><meta name="Generator"/></head><body lang="EN-US"><div class="WordSection1"><p class="MsoNormal">Hi Glen,</p><p class="MsoNormal">聽</p><p class="MsoNormal">I have a similar setup but do not switch programmatically between the 2 gateways. However, how about adding a delay between the switching? This would ensure connection closure.</p><p class="MsoNormal">聽</p><p class="MsoNormal">Pranav<span style="color: white"></span></p></div>pranav@... (Pranav Lal)Mon, 24 Mar 2025 10:12:08 -0700Live and paper data mixed
/g/ib-async/message/290
<p>I have a program that will place trades in either the paper or live account. I run both platforms simultaneously on the same machine. It crashes when I try get my account value after switching from one to the other because I get the first result over again. I have a support ticket in with IB, but they keep suggesting it's my code. Can anyone here create the problem to help me sort this out?</p>
<p>With two instances of TWS open, one paper and one live, here's the simplest code I've run to show the problem:</p>
<p>from ib_async import *</p>
<p>def ensure_connection(ib: IB, host: str, desired_port: int, client_id: int):
"""Ensure IB is connected to the desired port. Reconnect if necessary."""</p>
<pre class="prettyprint"><code class="language-unknown"># Check if IB is connected and if the port matches
if ib.isConnected() and ib.client.port == desired_port:
print(f"Already connected on the desired port: {desired_port}")
return
# If connected but on the wrong port, disconnect
if ib.isConnected():
print(f"Connected on wrong port {ib.client.port}, disconnecting...")
ib.disconnect()
ib.sleep(1)
# Reconnect on the correct port
print(f"Connecting to port {desired_port}...")
ib.connect(host, desired_port, client_id)
print(f"Connected on port: {ib.client.port}")
</code></pre>
<p>ib = IB()</p>
<p>IBPort = 7496</p>
<p>ensure_connection(ib, "127.0.0.1", IBPort, 33)
print(ib.isConnected())
print(ib.client.port)</p>
<p>SummaryAccountValue = ib.accountSummary()
print(SummaryAccountValue)</p>
<p>IBPort = 7497</p>
<p>ensure_connection(ib, "127.0.0.1", IBPort, 33)
print(ib.isConnected())
print(ib.client.port)</p>
<p>SummaryAccountValue = ib.accountSummary()
print(SummaryAccountValue)</p>
<p>ib.disconnect()</p>
<p>print(ib.isConnected())
print(ib.client.port)</p>
<p>IBPort = 7497</p>
<p>ensure_connection(ib, "127.0.0.1", IBPort, 33)
print(ib.isConnected())
print(ib.client.port)</p>
<p>SummaryAccountValue = ib.accountSummary()
print(SummaryAccountValue)</p>
<p>IBPort = 7496</p>
<p>ensure_connection(ib, "127.0.0.1", IBPort, 33)
print(ib.isConnected())
print(ib.client.port)</p>
<p>SummaryAccountValue = ib.accountSummary()
print(SummaryAccountValue)</p>
<p>ib.disconnect()
'''
ib.fills also seems to have problems. For the first connection, it will show correct information, but on the second connection, it will show the first plus the second.</p>
<p>Is there a problem somewhere in the ib_async library or is this an IB issue? Can anyone reproduce this or suggest how I can fix it?</p>
<p>Glenn</p>bmore@... (Glenn)Mon, 24 Mar 2025 09:29:06 -0700Re: Clicking an override button
/g/ib-async/message/289
Hi all,<br /><br />I am answering my own question. I suspect I need to specify order conditions<br />and allow the advancedErrorOverride flag. <br /><br />How do I do this?<br />Pranavpranav@... (Pranav Lal)Mon, 24 Mar 2025 06:42:45 -0700Clicking an override button
/g/ib-async/message/288
Hi all,<br /><br />I have recently begun getting messages that a security is under<br />surveillance.<br />The exact entry in my program's log is below.<br />2025-03-24 06:59:15,321 ib_async.wrapper ERROR Error 201, reqId 7: Order<br />rejected - reason:Security is under Surveillance Measure - The scrip PE is<br />greater than 50 for the previous 4 trailing quarters.<br><br><br>Would you<br />like to continue?.<br /><br />How do I click yes programmatically?<br />Pranavpranav@... (Pranav Lal)Mon, 24 Mar 2025 01:06:06 -0700