ValueError: cannot convert float NaN to integer - after Start of calculating target positions.
robby28-11 opened this issue · 11 comments
Thetagang gets portfolio positions but the it kind of crashes. Was working wonderful, haven't changed anything. Wonder what might have influenced this. Already switched back to 1.9.1 and 1.9.2 with the same issue.
Any ideas?
`│ T │ │ │ │ │ │ │ │ │ │ │ │ │
│ │ P │ -1 │ $0… │
│ │ P │ -5 │ $0… │
└─────┴───┴─────┴─────┴─────┴─────┴──────┴─────┴──────┴─────┴──────┴─────┴─────┘
Calculating target positions... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0% -:--:--
╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /usr/local/lib/python3.10/dist-packages/thetagang/portfolio_manager.py:591 │
│ in manage │
│ │
│ 588 │ │ │ │ positions_table, │
│ 589 │ │ │ │ put_actions_table, │
│ 590 │ │ │ │ puts_to_write, │
│ ❱ 591 │ │ │ ) = self.check_if_can_write_puts(account_summary, portfol │
│ 592 │ │ │ │
│ 593 │ │ │ # Look for lots of stock that don't have covered calls │
│ 594 │ │ │ (call_actions_table, calls_to_write) = self.check_for_unc │
│ │
│ /usr/local/lib/python3.10/dist-packages/thetagang/portfolio_manager.py:1005 │
│ in check_if_can_write_puts │
│ │
│ 1002 │ │ │ targets[symbol] = round( │
│ 1003 │ │ │ │ self.config["symbols"][symbol]["weight"] * total_buyi │
│ 1004 │ │ │ ) │
│ ❱ 1005 │ │ │ self.target_quantities[symbol] = math.floor( │
│ 1006 │ │ │ │ targets[symbol] / ticker.marketPrice() │
│ 1007 │ │ │ ) │
│ 1008 │
╰──────────────────────────────────────────────────────────────────────────────╯
ValueError: cannot convert float NaN to integer
** Press ANY KEY to close this window ** `
Was the market open when you ran this? The ticker is not returning a price, hence the error.
Yes. Also at this moment same error. Even with 1.8.1
Odd. Does IBKR return a price for the same symbol? There are some weird edge cases (like things with very low liquidity) where sometimes it doesn't return data. It should normally return the midpoint price, or the last trade price if that's not available. This is a tricky case because it's not safe to keep going if you can't get a valid price for the symbol, it will lead to undefined behaviour.
See here: https://ib-insync.readthedocs.io/api.html#ib_insync.ticker.Ticker.marketPrice
Argh, yes there was one option with a price of 0.00. Just bought it for 0.01 to close that position. Fixed the issue instantly. Thanks for the hint.
That's odd, I guess there must have been no bids or asks, and no trades. Maybe I will have it handle that one particular case more gracefully by skipping over contracts with no price, but I want to think about it for a bit to make sure I don't inadvertently introduce a footgun. I think it's probably safe to just ignore this specific case, but that means it won't be able to roll the contract (ideally it would expire worthless).
The put option (T Feb16 14Put) was sold with a very low commission. Unfortunately, I hadn't used minimum_credit yet, which could probably have prevented it (which is btw just working in the latest tag, not main).
As a result, the option was too far out of the money.
Of course, the option would have simply expired - that's not a problem. The problem, however, is that all other options were set to "pause" because the script was always interrupted as a result.
So maybe it's not such a bad idea to distinguish whether the option price is 0.00 or does not return a value at all?
What's especially confusing to me is that it's actually failing on getting the market price for the stock, not the option itself. That should certainly not be returning 0 or NaN. It should already gracefully handle cases where the option has no price, usually it'll print an error and continue anyway.
So, I'm either failing to understand the problem, or I've missed some key piece of information.
Was there any other detail in the stack trace from before? I'm thinking that stack trace is actually a red herring and the error is somewhere else.
If I were to guess, it's failing after this function (which tries to handle this as gracefully as possible, but could still return a 0 or NaN in some cases):
Lines 207 to 222 in 42af123
The error itself is caused by a failed type conversion from a float to an integer, which doesn't quite make sense because the prices are handled as floats. I will make a tiny correction so that in the case that ticker.marketPrice()
is NaN, it'll return 0.0 instead.
Something odd is happening here:
Log from yesterday attached. It just happens in my paper account. The live account does not have any issues.
I'm using the cash management in the paper only. Currently the paper only have SGOV in account.
It somehow fails to caluclate target positions.
Maybe this helps to find whats happening.
Error.txt
One of those two values (either the market price, or the weights) has to be NaN. It's not the weight, because it prints that earlier (showing 20%), so it must be the market price.
What do you have this setting set to:
Line 386 in dfd37f4
The only thing I can think of, is that if ib_insync.api_response_wait_time
is too small, it won't wait long enough for the API to get the market prices. Anything less than 5 is probably going to frequently cause problems.
In any case, I'll make one more tweak to this code, which will hopefully handle this situation better.
api_response_wait_time = 60
for both paper/live
Now it is just working. Haven't changed anything. But thanks for digging into this rare issue.