开云体育

ctrl + shift + ? for shortcuts
© 2025 开云体育

Re: reqCurrentTimeAsync() mystery

 

I added some code so that my code calls reqCurrentTimeAsync every few seconds. I use it to make sure the network is properly connected, so this should be fine.

Yeah, my code was locking up periodically and it took me a while to realize that it was because sometimes reqCurrentTimeAsync never received a response.


Re: reqCurrentTimeAsync() mystery

 

This did bit me a few years ago, this was a change by IB about the semantics for reqCurrentTime().? For unknown reasons, IB decided that if you requested the time more than once in the same second to TWS or the gateway, there would be *no* answer provided at all.? The IB own python binding solves that by maintaining a local copy of the time, so reqCurrentTime() is not forwarded to TWS (or the gateway) twice per second.
?
Not responding at all is highly problematic, some of my ib_insync() code started to fully hang depending on when exactly call to reqCurrentTime() were done.? I did correspond with Ewald at the time, but he considered that a brain dead decision by IB (I concur on that) and did not want to code some caching solution similar to IB code (I am less sure about that).? You can modify the library code on your own, or simply make sure that you never call reqCurrentTime() too fast.? I follow the second approach in my own code.
?
You must ask yourself who in his right mind will add code to explicitly check the amount of time between requests, then not answering at all if that happens, not even an error, instead of the previous behavior where you simply always return the current time.? I think this is the only case where a request is not associated with a response in the whole API.


Re: reqCurrentTimeAsync() mystery

 

Although I can't find it in the document, I believe IB may has restrictions no to have two calls within a second, similar to this:


reqCurrentTimeAsync() mystery

 

I am having some very strange problems with reqCurrentime().

Look at the below script, which simply gets the current time and the remote time, compares them, waits for a little bit, and then tries again.

async def main2():
    N = 300
    times = np.zeros(N)
    ib = ibs.IB()
    await ib.connectAsync("gateway", 4004, clientId=20, timeout=60)

    for i in range(300):
        local_tm = datetime.datetime.now(datetime.UTC)
        try:
            server_tm = await asyncio.wait_for(ib.reqCurrentTimeAsync(), 10.0)
        except TimeoutError:
            print(f"{i} :Timeout!")
            times[i] = 1.0
        else:
            times[i] = (server_tm - local_tm).total_seconds()
        t2 = datetime.datetime.now(datetime.UTC)
        processing = (t2 - local_tm).total_seconds()
        await asyncio.sleep(0.5)
        print(f"{i} : diff = {times[i]:.2f} sec, processing = {processing:.2f} sec")

    print(f"Avg = {np.mean(times)}, std = {np.std(times)}")

asyncio.run(main2())

The strange thing here is that if I await asyncio.sleep(1) or longer, the program works more or less as expected. Below is an example of such normal output:

0 : diff = -0.88 sec, processing = 0.00 sec
1 : diff = -0.88 sec, processing = 0.00 sec
2 : diff = -0.88 sec, processing = 0.00 sec
3 : diff = -0.88 sec, processing = 0.00 sec
4 : diff = -0.89 sec, processing = 0.00 sec
5 : diff = -0.89 sec, processing = 0.00 sec
6 : diff = -0.89 sec, processing = 0.00 sec

However, once I await asyncio.sleep(0.5) or anything below 1, I see something as follows:

0 : diff = -0.94 sec, processing = 0.00 sec
1 :Timeout!
1 : diff = 1.00 sec, processing = 10.01 sec
2 : diff = -0.95 sec, processing = 0.00 sec
3 :Timeout!
3 : diff = 1.00 sec, processing = 10.01 sec
4 : diff = -0.97 sec, processing = 0.00 sec
5 :Timeout!
5 : diff = 1.00 sec, processing = 10.01 sec
6 : diff = -0.98 sec, processing = 0.00 sec
7 :Timeout!
7 : diff = 1.00 sec, processing = 10.01 sec
8 : diff = -1.00 sec, processing = 0.00 sec

In other words, reqCurrentTimeAsync() times out every other time, even though I have set the timeout to be 10 seconds! If I wait for 0.5 second between each call of reqCurrentTime(), I am only sending 2 messages per second.

(I was debugging some strange freezing up in production and finally produced this minimal example to reproduce the problem.)

Does anything know what might be going on?


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

Yeah, this does seem new. This thread seems to have a similar symptom: /g/twsapi/topic/88795216#msg48912 .

It doesn't feel that fields are missing randomly. In the most recent instance, all the bids of a bunch of stocks are missing, no matter how long I wait or retry. Statistically, this cannot be explained by the field not being updated because there is no new data.

Being a hassle aside, I am also worried that updates for some fields may suddenly stop and cause my program to silently consume wrong data. I have never tested this possibility, but it seems possible.

I would really appreciate if people could share about the problem/solution.


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

I have the same problem. Its been happening for months now, i just havent tried to figure out what is wrong. I follow the same steps as you outline, and atleast 50% of the time some stocks (usually 2 or 3) have Nan data. I also wrote code to auto stop and restart but that didnt work. Strangely what does work and is what i do each day is go to TWS refresh a quote screen for each stock that is Nan'ing, then restart the reqMktData call.....and wulla it works.....no idea why. Im keen to hear what the problem/solution might be.....


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

Sorry for the multipe email (as I can't edit my response). Just want to add that currently the output of the script is:

Retrying... 1
Retrying... 2
Retrying... 3
Failed to get data after 3 retries
PSA PRF nan 20.91 nan 800.0 20.98
PSA PRG nan 20.63 nan 1000.0 20.63


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

The sequence is simply: 1. Connect to TWS 2. reqMktData() 3. Give it some time to get data. 4. If some fields are NaN or None, cancelMktData(), and retry.

Below is a minimal example. When the problem happens, the bid is NaN. (Note the bid should usually be 20 some dollars. It's not a penny option where there can be no bid.) The problem can happen during market hours. After the gateway or TWS restarts, running the client the first time is always fine. But running it a second or more times can cause this. The problem is illusive. When it doesn't happen, it tends not to happen as long as I don't restart the gateway. If it happens, then it happens almost every subsequent time until I restart the gateway.

import asyncio
import math

import ib_async as ibs

tickers_list = ["PSA PRF", "PSA PRG"]

async def subscribe(ib, contracts):
    ib.reqMarketDataType(1)
    tickers = []
    for c in contracts:
        ticker = ib.reqMktData(c, "456,375")
        tickers.append(ticker)
        await asyncio.sleep(0.1)
    return tickers

def is_ok(ticker):
    attributes = ["bid", "ask", "bidSize", "askSize", "close"]
    def is_null(x):
        if isinstance(x, float):
            return math.isnan(x)
        return x is None

    return all(not is_null(getattr(ticker, attr, None)) for attr in attributes)


async def main():
    ib = ibs.IB()
    await ib.connectAsync("gateway", 4004, clientId=1, timeout=60)
    contracts = list(ibs.Stock(sym, "SMART", "USD") for sym in tickers_list)
    contracts2 = await ib.qualifyContractsAsync(*contracts)

    for i_retry in range(1, 4):
        tickers = await subscribe(ib, contracts2)
        await asyncio.sleep(5)
        if all(is_ok(ticker) for ticker in tickers):
            print("success")
            break
        print("Retrying...", i_retry)
        for c in contracts2:
            ib.cancelMktData(c)

    else:
        print("Failed to get data after 3 retries")
        for ticker in tickers:
            print(ticker.contract.symbol, ticker.bid, ticker.ask, ticker.bidSize,
                  ticker.askSize, ticker.close)

asyncio.run(main())


Re: ib.reqTickers() conflicts with ib.reqTickByTickData()

 

Looking for this: ?


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

Can you outline the steps that reproduce the problem like;
  1. Connect TWS.
  2. Connect client.
  3. Subscribe reqMktData
  4. ...
Only because original post had two issues, so I'm confused since it was partially fixed.


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

I tested it. It does seem that type 2 will give me the most recent quote and price when the market is open. However, even if I use type 2, the problem I described in the original email persisted, namely, some fields are missing if the client is not connected to the gateway the first time the gateway restarts.


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

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.

There are still some pending questions that I need to investigate:

  1. Does MkDataType 2 provide the last quotes recorded at closing or just the last recorded quotes?
  2. 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?
  3. 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.


Re: Determining which stock is bringing my portfolio into a loss

 

开云体育

I'm curious, does it work during regular trading hours?





-------- Original message --------
From: "Pranav Lal via groups.io" <pranav@...>
Date: 2025-04-03 6:26 p.m. (GMT-08:00)
Subject: [ib-async] Determining which stock is bringing my portfolio into a loss

Hi all,

I am trying to write some code to determine which stock is bringing my
portfolio into a loss.

My logic is to see if the averageCost is greater than the current market
price for each stock in the portfolio.

The problem is that the current market price is nan. I am running this code
after market close. Here is the relevant snippet. What am I missing?
ib.connect('127.0.0.1', 4001, clientId=999990)
positions=ib.positions()
lc=0
for p in positions:

[ticker] = ib.reqTickers(p.contract)
print(p.contract.symbol)

print("number of shares=" + str(p.position))
print("Cost per share=",ib.portfolio()[lc].averageCost)
print("Current price per share=",ticker.marketPrice())

lc+=1
ib.sleep(1)
Pranav







Re: Determining which stock is bringing my portfolio into a loss

 

开云体育

Hi,

?

Yes, setting the market data type to 2 solved the problem.

?

Pranav

From: [email protected] <[email protected]> On Behalf Of biney59 via groups.io
Sent: Friday, April 4, 2025 11:19 PM
To: [email protected]
Subject: Re: [ib-async] Determining which stock is bringing my portfolio into a loss

?

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


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

Type 2 is the last data recorded at market close, which is not what I want.

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.

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.


Re: Determining which stock is bringing my portfolio into a loss

 

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


Re: ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

From my understanding, ib.reqMktData(contract) 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:
  • Beginning in TWS?v970, a??callback of?1?will occur automatically after invoking reqMktData if the user has live data permissions for the instrument.
?
You might need to request different type of market data if you always want data, for example, set type to 2:?
Frozen 2 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.


ib.reqMktData() does not get certain fields when connecting to the gateway the second time.

 

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 reqMktData()won't get all the fields. Specifically, if I do the below, I find everything in the ticker object are filled except for bid and bidSize, which are nan. Sometimes, it is the close price that is nan.


ticker  = ib.reqMktData(contract)
asyncio.sleep(0.5)
# ticker.bid, ticker.bidSize, ticker.close may be nan

I have logic to retry the subscription as follows, but it rarely does anything:


ib.cancelMktData(contract)
asyncio.sleep(0.1)
ib.reqMktData(contract)

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.

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.

The problem is not limited to the gateway. Connecting with TWS has exactly the same problem.

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.

Has anyone encountered similar issues?


Determining which stock is bringing my portfolio into a loss

 

Hi all,

I am trying to write some code to determine which stock is bringing my
portfolio into a loss.

My logic is to see if the averageCost is greater than the current market
price for each stock in the portfolio.

The problem is that the current market price is nan. I am running this code
after market close. Here is the relevant snippet. What am I missing?
ib.connect('127.0.0.1', 4001, clientId=999990)
positions=ib.positions()
lc=0
for p in positions:

[ticker] = ib.reqTickers(p.contract)
print(p.contract.symbol)

print("number of shares=" + str(p.position))
print("Cost per share=",ib.portfolio()[lc].averageCost)
print("Current price per share=",ticker.marketPrice())

lc+=1
ib.sleep(1)
Pranav


Re: Clicking an override button

 

开云体育

Hi,

?

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.

?

Pranav

?

From: [email protected] <[email protected]> On Behalf Of Gonzalo Saenz via groups.io
Sent: Saturday, March 29, 2025 8:24 PM
To: [email protected]
Subject: Re: [ib-async] Clicking an override button

?

Thanks for your reply

?

So if I follow you correctly,?

?

  • you submit an order,?
  • it fails,?
  • you check your Trade.log for the error message,?
  • and in a future order, you set Order.advancedErrorOverride based on the error message on previous point

?

?

?

?



On 28 Mar 2025, at 00:53, Pranav Lal <pranav@...> wrote:

?

Hi?Gonzalo,

?

Documentation is sketchy to say the least. See the below link.?

?

The rest of it was trial and error.?

?

Pranav

?