Tengo un problema para obtener datos de opciones con la API de IB. Los datos parecen no ser correctos. En mi código estoy obteniendo algunas opciones de compra 0DTE para el contrato Mini SP500 March Futures e imprimiendo su oferta, demanda y delta. Para ello estoy utilizando el ib_sync que simplifica enormemente el desarrollo. Este es el código:
from datetime import datetime
from ib_insync import *
import pandas as pd
import math
from datetime import datetime, time
def week_of_month(dt):
""" Returns the week of the month for the specified date.
"""
first_day = dt.replace(day=1)
dom = dt.day
adjusted_dom = dom + first_day.weekday()
return int(math.ceil(adjusted_dom/7.0))
def get_trading_class(dt: datetime):
week = week_of_month(dt)
day = dt.weekday()
res = 'E' + str(week)
if day == 4:
return 'EW' + str(week)
else:
return 'E' + str(week) + chr(60+day)
ib = IB().connect('winhost', 7496, clientId=123, timeout=15)
es = Future('ES', '202303', 'CME')
print(ib.qualifyContracts(es))
ib.reqMarketDataType(1)
[ticker] = ib.reqTickers(es)
# spx current price
spxValue = ticker.marketPrice()
print('es futue value: ', spxValue)
chains = ib.reqSecDefOptParams(es.symbol, 'CME', es.secType, es.conId)
# chainsDf = util.df(chains)
# print(chainsDf.to_string(max_colwidth=10))
# chainsDf = chainsDf[(chains.exchange == 'SMART') & (chains.tradingClass == 'SPXW')]
print('week of the month:', week_of_month(datetime.now()))
trading_cls = get_trading_class(datetime.now())
print('trading class:', trading_cls)
chain = next(c for c in chains if c.tradingClass == trading_cls and c.exchange == 'CME')
expiration = chain.expirations[0]
print('expiration:',expiration)
call_strikes = [strike for strike in chain.strikes
if strike % 5 == 0
and spxValue - 10 < strike < spxValue + 30]
put_strikes = [strike for strike in chain.strikes
if strike % 5 == 0
and spxValue - 30 < strike < spxValue]
rights = ['P', 'C']
contracts = [Option('SPX', expiration, strike, 'C', 'SMART', tradingClass='SPXW') for strike in call_strikes]
contracts = ib.qualifyContracts(*contracts)
tickers = ib.reqTickers(*contracts)
for ticker in tickers:
print('call strike', ticker.contract.strike, 'bid:', ticker.bid, 'ask:', ticker.ask, 'delta:', ticker.lastGreeks.delta)
ib.disconnect()
Y este es el resultado:
[Future(conId=495512572, symbol='ES', lastTradeDateOrContractMonth='20230317', multiplier='50', exchange='CME', currency='USD', localSymbol='ESH3', tradingClass='ES')]
es futue value: 4061.75
week of the month: 3
trading class: EW3
expiration: 20230217
call strike 4055.0 bid: 10.1 ask: 10.3 delta: 0.472330335007325
call strike 4060.0 bid: 7.9 ask: 8.1 delta: 0.3769870767527141
call strike 4065.0 bid: 6.1 ask: 6.3 delta: 0.29022751622672416
call strike 4070.0 bid: 4.6 ask: 4.8 delta: 0.212861073049887
call strike 4075.0 bid: 3.4 ask: 3.6 delta: 0.1491749774504159
call strike 4080.0 bid: 2.55 ask: 2.6 delta: 0.09797399088652259
call strike 4085.0 bid: 1.85 ask: 1.95 delta: 0.06485900831271653
call strike 4090.0 bid: 1.35 ask: 1.4 delta: 0.04255032736417017
He vuelto a comprobar el precio del contrato y es correcto: 4061,75.
Ahora, mirando la TWS en el momento en que hago esta petición, los bid asks y los deltas de las opciones son incorrectos. Mire la imagen adjunta.
Creo que estoy recibiendo datos retrasados, porque si el precio del contrato de futuros es 4061,75, la primera opción de compra ITM con un delta superior a 50 debería ser la 4060, pero en mi salida, el delta para esa opción es 0,37. Ni siquiera la opción 4055 es ITM. Ni siquiera la opción de compra 4055 es ITM.
Así que mi pregunta es. ¿Cómo es posible que esté viendo datos en tiempo real en la TWS pero que esté recibiendo datos con retraso a través de la API? ¿Me falta una suscripción de datos en tiempo real para la API? En ese caso, ¿cuál?
Estas son mis suscripciones de datos de mercado:
Gracias