Contract can't be hashed
Closed this issue · 6 comments
when placing orders, it returned "ValueError: Contract Contract(secType='STK', symbol='AAPL', exchange='SMART/AMEX', currency='USD') can't be hashed"
but i tried to do the same using the orignal ib_insync, i successfully put in the order. please look into it when you have time, thanks!
my code as follows:
stock = Stock(symbol='AAPL', exchange='SMART/AMEX', currency='USD')
action = MarketOrder(action='buy', totalQuantity=1, tif='DAY')
order = ib.placeOrder(stock, action)
Experiencing the same issue
Are we sure this is a new problem? We had various "can't be hashed" issues on the old repo too.
This one is probably caused by the hash requiring the contractId to be populated (so contracts must be qualified using qualifyContracts
or qualifyContractsAsync
before you can use them):
def isHashable(self) -> bool:
"""
See if this contract can be hashed by conId.
Note: Bag contracts always get conId=28812380, so they're not hashable.
"""
return bool(self.conId and self.conId != 28812380 and self.secType != "BAG")
I'll at least add some better error messages plus some automated tests around this later today.
In [1]: import ib_async
In [2]: s = ib_async.Stock(symbol='AAPL', exchange='SMART/AMEX', currency='USD')
In [3]: {s: "test"}
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[3], line 1
----> 1 {s: "test"}
File ~/repos/ibkr/ib_insync/ib_async/contract.py:156, in Contract.__hash__(self)
154 def __hash__(self):
155 if not self.isHashable():
--> 156 raise ValueError(f"Contract {self} can't be hashed")
158 if self.secType == "CONTFUT":
159 # CONTFUT gets the same conId as the front contract, invert it here
160 h = -self.conId
ValueError: Contract Stock(symbol='AAPL', exchange='SMART/AMEX', currency='USD') can't be hashed
In [4]: s_qualified = ib_async.Stock(conId=999999999999999999, symbol='AAPL', exchange='SMART/AMEX', currency='USD')
In [5]: {s_qualified: "test"}
Out[5]: {Stock(conId=999999999999999999, symbol='AAPL', exchange='SMART/AMEX', currency='USD'): 'test'}
Are we sure this is a new problem? We had various "can't be hashed" issues on the old repo too.
I've checked various "can't be hashed" issues on the old repo before commenting here. However, it really seems like smth new as the topic starter mentioned with old ib_insync everything works as it should. With ib_async I can not retrieve OHLCV, keep getting hash error.
import pandas as pd
#Symbols list
symbols = ['AMZN', 'TSLA']
#Method to get OHLCV
def get_OHLCV(symbol, endDateTime='', durationStr='30 D', barSizeSetting = '1 hour', whatToShow='TRADES', useRTH=False, formatDate=1):
bars = ib.reqHistoricalData(symbol, endDateTime, durationStr, barSizeSetting, whatToShow, useRTH, formatDate)
df = util.df(bars)
df["date"] = df["date"].dt.tz_convert("America/New_York")
df = df.drop(columns=['average', 'barCount'])
df.set_index('date', inplace=True)
#df = df.iloc[::-1]
df.to_csv('{}.csv'.format(symbol.symbol))
df = pd.read_csv('{}.csv'.format(symbol.symbol))
df.columns = ['date','open', 'high', 'low', 'close', 'volume']
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
print(f'Data for {symbol.symbol} downloaded OK with OLD')
return df
for symbol_str in symbols:
symbol = Stock(symbol_str, 'SMART', 'USD')
df = get_OHLCV(symbol)
Thanks for the details of how to reproduce it (I added part of your example as a new test case we can keep tracking going forward).
Fixed the error with a larger cleanup which I think looks better overall and is probably a little faster (now it's using a direct lookup table for each type instead of crawling through up to 8 if-else statements for each field).
Added fix as new version 1.0.1
and updated pypi package too.