I am currently trying to pull implied volatility data for a list of stocks via the IBKR API using the ib_async (formerly ib_insync) python library. Problem is that no matter what I try, the values for implied volatility always remain nan while they can be received within the TWS itself. I am subscribed to live data incl. options data.
I tried two ways for requesting ticker data:
- Requesting data only once via ib.reqTickers function:
from ib_async import * #importing the ib_async classes and functions
import pandas as pd
ib = IB()
#use this for TWS
ib.connect('127.0.0.1', 7497, clientId=1, readonly=True)
# Set market data type to delayed data
ib.reqMarketDataType(1) # 3 = delayed data
#Define simple collection of test symbols
symbols = ['GME', 'AAPL', 'RIVN']
contracts = []
contractdata = []
for symbol in symbols:
contract = Stock(symbol, 'SMART', 'USD')
contracts.append(contract)
# Qualify contracts and fetch market data once
contracts = ib.qualifyContracts(*contracts)
tickers = ib.reqTickers(*contracts)
for t in tickers:
try:
# Store Tick data
data = {
"Symbol": t.contract.symbol,
"Last": t.last,
"Volume": t.volume,
"Implied Volatility": t.impliedVolatility,
}
contractdata.append(data)
except Exception:
pass # Skip any invalid data
# Convert Data into Pandas DataFrames
data_df = pd.DataFrame(contractdata)
print(data_df)
ib.disconnect()
returns:
Symbol Last Volume Implied Volatility
0 GME 22.94 20481.0 NaN
1 AAPL 212.65 270901.0 NaN
2 RIVN 10.64 94368.0 NaN
- Requesting a live feed of ticker data via ib.reqMktData
from ib_async import *
ib = IB()
#use this for TWS
ib.connect('127.0.0.1', 7497, clientId=1, readonly=True)
ib.reqMarketDataType(1)
#Define simple collection of test symbols
symbols = ['GME', 'AAPL', 'RIVN']
#Subscribe to live data for a list of symbols
for symbol in symbols:
contract = Stock(symbol, 'SMART', 'USD')
ib.reqMktData(contract, '', False, False)
def onPendingTickers(tickers):
print('pending tickers event received')
for t in tickers:
print(t.contract.symbol, t.last, t.volume, t.impliedVolatility)
#Event Subscription: The pendingTickersEvent is an event that gets triggered when there are new tickers data available.
ib.pendingTickersEvent += onPendingTickers
ib.sleep(30)
#Event Unsubscription
ib.pendingTickersEvent -= onPendingTickers
ib.disconnect()
returns
GME 22.89 20182.0 nan
pending tickers event received
AAPL 212.61 262905.0 nan
pending tickers event received
AAPL 212.61 262905.0 nan
pending tickers event received
RIVN 10.65 91547.0 nan
[...]
As it can be seen, for both methods, impliedVolatility is always returned nan, even for very long subscription durations for the live feed (tried till duration 1800s with same result). The only hints I found focused on the fact, that not every ticker is filled instantly so one must sometimes just wait long enough. However, via subscribing to the the live data feed and updating on every ticker event, this should be covered as a potential cause?
Thanks for any hint what I might miss here!