Closed praditik closed 4 months ago
oh wow this actually explains a lot.
So the library assumes UNSET_DOUBLE
is the universal float_max value of 1.7976931348623157e+308
but sometimes we get an un-parsed IBKR value directly of 1.7976931348623157E308
instead, so the wrong "unset" value is causing early exit of some requests by mistake.
I've always wondered why some order previews work (limit orders) and others just refuse to show any details (relative orders, midprice orders, etc).
Looking through my logs, it appears the library is parsing IBKR's unset value to 1.7976931348623157e+308
when missing account or instrument data:
icli-id=4-2023-12-13 00:29:17.244095-05:00-ibkr.log
12:2023-12-12 21:29:17,405 updatePortfolio: PortfolioItem(marketPrice=1.7976931348623157e+308, marketValue=1.7976931348623157e+308, averageCost=1.7976931348623157e+308, unrealizedPNL=0.0, realizedPNL=0.0, account='XX')
13:2023-12-12 21:29:17,405 updatePortfolio: PortfolioItem(marketPrice=1.7976931348623157e+308, marketValue=1.7976931348623157e+308, averageCost=1.7976931348623157e+308, unrealizedPNL=0.0, realizedPNL=0.0, account='XX')
But IBKR gives us 1.7976931348623157E308
when requesting order details and we weren't parsing it correct for the "wait until all data has arrived" check:
icli-id=0-2024-03-04 22:23:27.759024-05:00-icli-color.log
2946: initMarginBefore='1.7976931348623157E308',
2947: maintMarginBefore='1.7976931348623157E308',
2948: equityWithLoanBefore='1.7976931348623157E308',
2949: initMarginChange='1.7976931348623157E308',
2950: maintMarginChange='1.7976931348623157E308',
2951: equityWithLoanChange='1.7976931348623157E308',
2952: initMarginAfter='1.7976931348623157E308',
2953: maintMarginAfter='1.7976931348623157E308',
2954: equityWithLoanAfter='1.7976931348623157E308',
So, an even simpler fix is probably just parsing the string float back into a standard float we expect as:
if float(orderState.initMarginChange) != UNSET_DOUBLE:
because python knows enough to convert the float E
syntax into the other number we expect:
In [1]: import sys
In [2]: sys.float_info.max
Out[2]: 1.7976931348623157e+308
In [3]: float("1.7976931348623157E308")
Out[3]: 1.7976931348623157e+308
In [4]: float("1.7976931348623157E308") == sys.float_info.max
Out[4]: True
I added this change to my own dev tools version and it's working correctly for me now (non-market hours though), but I'll also run this fix for a day or two to confirm then add it to a new release.
Thanks for tracking this down! I had always just assumed the order preview system was broken for non limit orders.
Thanks for getting back. You are welcome and I would be happy to help maintain the library/write examples as I have been using ib_insync for more than 2 years extensively.
Thanks for the simpler fix using float conversion.
Looking back further, the previous incorrect fix was from https://github.com/erdewit/ib_insync/issues/403 which was also trying to fix https://github.com/erdewit/ib_insync/issues/380 so this has been around for years and hopefully is finally fixed properly now.
Their primary confusion was the IBKR value being compared against wasn't parsed to the native python type yet, so it would never match the check as expected because the problem wasn't only "comparing number against string." Essentially str(UNSET_DOUBLE)
is never correct to use (because the value compared against should be parsed into a proper native type before the comparison). I double checked all other source files and str(UNSET_DOUBLE)
isn't being used anywhere else now.
This if statement is changed as UNSET_DOUBLE and orderState.initMarginChange were not equal to start with. Hence the request would get dropped even without the orderState being populated. I have been using this library with this modification for more than a month now and this fix works to solve the issue for whatIfOrder feature