Rejig option chain schema to capture all contracts
parent
368f21d8d6
commit
d145a5a219
|
@ -60,6 +60,17 @@ async def stocks_quote(
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
async def option_chain(
|
||||||
|
brokermod: ModuleType,
|
||||||
|
symbol: str,
|
||||||
|
) -> Dict[str, Dict[str, Dict[str, Any]]]:
|
||||||
|
"""Return option chain (all expiries) for ``symbol``.
|
||||||
|
"""
|
||||||
|
async with brokermod.get_client() as client:
|
||||||
|
return await client.option_chains(
|
||||||
|
await client.get_contracts([symbol]))
|
||||||
|
|
||||||
|
|
||||||
async def wait_for_network(net_func: Callable, sleep: int = 1) -> dict:
|
async def wait_for_network(net_func: Callable, sleep: int = 1) -> dict:
|
||||||
"""Wait until the network comes back up.
|
"""Wait until the network comes back up.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -78,8 +78,7 @@ class _API:
|
||||||
|
|
||||||
async def option_quotes(
|
async def option_quotes(
|
||||||
self,
|
self,
|
||||||
ids: List[int],
|
contracts: Dict[int, Dict[str, dict]],
|
||||||
expiry: str,
|
|
||||||
option_ids: List[int] = [], # if you don't want them all
|
option_ids: List[int] = [], # if you don't want them all
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"Retrieve option chain quotes for all option ids or by filter(s)."
|
"Retrieve option chain quotes for all option ids or by filter(s)."
|
||||||
|
@ -87,14 +86,17 @@ class _API:
|
||||||
{
|
{
|
||||||
"underlyingId": int(symbol_id),
|
"underlyingId": int(symbol_id),
|
||||||
"expiryDate": str(expiry),
|
"expiryDate": str(expiry),
|
||||||
} for symbol_id in ids
|
}
|
||||||
|
# every expiry per symbol id
|
||||||
|
for symbol_id, expiries in contracts.items()
|
||||||
|
for expiry in expiries
|
||||||
]
|
]
|
||||||
|
|
||||||
resp = await self._sess.post(
|
resp = await self._sess.post(
|
||||||
path=f'/markets/quotes/options',
|
path=f'/markets/quotes/options',
|
||||||
json={'filters': filters, 'optionIds': option_ids}
|
json={'filters': filters, 'optionIds': option_ids}
|
||||||
)
|
)
|
||||||
return resproc(resp, log)
|
return resproc(resp, log)['optionQuotes']
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
|
@ -263,37 +265,41 @@ class Client:
|
||||||
item for item in contracts
|
item for item in contracts
|
||||||
}
|
}
|
||||||
|
|
||||||
async def max_contract_expiry(
|
async def get_contracts(
|
||||||
self,
|
self,
|
||||||
symbols: List[str]
|
symbols: List[str]
|
||||||
) -> Tuple[List[int], datetime]:
|
# {symbol_id: {dt_iso_contract: {strike_price: {contract_id: id}}}}
|
||||||
|
) -> Dict[int, Dict[str, Dict[int, Any]]]:
|
||||||
"""Look up all contracts for each symbol in ``symbols`` and return the
|
"""Look up all contracts for each symbol in ``symbols`` and return the
|
||||||
list of symbol ids as well as the maximum possible option contract
|
of symbol ids to contracts by further organized by expiry and strike
|
||||||
expiry out of the bunch.
|
price.
|
||||||
|
|
||||||
This routine is a bit slow doing all the contract lookups (a request
|
This routine is a bit slow doing all the contract lookups (a request
|
||||||
per symbol) and thus the return values should be cached for use with
|
per symbol) and thus the return values should be cached for use with
|
||||||
``option_chains()``.
|
``option_chains()``.
|
||||||
"""
|
"""
|
||||||
batch = {}
|
by_id = {}
|
||||||
for symbol in symbols:
|
for symbol in symbols:
|
||||||
id, contracts = await self.option_contracts(symbol)
|
id, contracts = await self.option_contracts(symbol)
|
||||||
batch[id] = max(contracts)
|
by_id[id] = {
|
||||||
|
dt.isoformat(timespec='microseconds'): {
|
||||||
return tuple(batch.keys()), max(batch.values())
|
item['strikePrice']: item for item in
|
||||||
|
byroot['chainPerRoot'][0]['chainPerStrikePrice']
|
||||||
|
}
|
||||||
|
for dt, byroot in sorted(
|
||||||
|
# sort by datetime
|
||||||
|
contracts.items(), key=lambda item: item[0]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return by_id
|
||||||
|
|
||||||
async def option_chains(
|
async def option_chains(
|
||||||
self,
|
self,
|
||||||
symbol_ids: List[int],
|
contracts: dict, # see ``get_contracts()``
|
||||||
max_expiry: str # iso format datetime (microseconds)
|
|
||||||
) -> Dict[str, Dict[str, Dict[str, Any]]]:
|
) -> Dict[str, Dict[str, Dict[str, Any]]]:
|
||||||
"""Return option chain snap quote for each ticker in ``symbols``.
|
"""Return option chain snap quote for each ticker in ``symbols``.
|
||||||
"""
|
"""
|
||||||
quotes = (await self.api.option_quotes(
|
quotes = await self.api.option_quotes(contracts)
|
||||||
ids=symbol_ids,
|
|
||||||
expiry=max_expiry.isoformat(timespec='microseconds')
|
|
||||||
))['optionQuotes']
|
|
||||||
|
|
||||||
batch = {}
|
batch = {}
|
||||||
for quote in quotes:
|
for quote in quotes:
|
||||||
batch.setdefault(quote['underlying'], {})[quote['symbol']] = quote
|
batch.setdefault(quote['underlying'], {})[quote['symbol']] = quote
|
||||||
|
@ -416,6 +422,7 @@ async def quoter(client: Client, tickers: List[str]):
|
||||||
# `client.ensure_access()` locally thus blocking until
|
# `client.ensure_access()` locally thus blocking until
|
||||||
# the user provides an API key on the "client side"
|
# the user provides an API key on the "client side"
|
||||||
await client.ensure_access(force_refresh=True)
|
await client.ensure_access(force_refresh=True)
|
||||||
|
quotes_resp = await client.api.quotes(ids=ids)
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
@ -449,7 +456,6 @@ _qt_keys = {
|
||||||
'askPrice': 'ask',
|
'askPrice': 'ask',
|
||||||
'bidPrice': 'bid',
|
'bidPrice': 'bid',
|
||||||
'lastTradeSize': 'size',
|
'lastTradeSize': 'size',
|
||||||
'lastTradeTime': ('time', datetime.fromisoformat),
|
|
||||||
'bidSize': 'bsize',
|
'bidSize': 'bsize',
|
||||||
'askSize': 'asize',
|
'askSize': 'asize',
|
||||||
'VWAP': ('VWAP', partial(round, ndigits=3)),
|
'VWAP': ('VWAP', partial(round, ndigits=3)),
|
||||||
|
@ -463,6 +469,7 @@ _qt_keys = {
|
||||||
# 'low52w': 'low52w', # put in info widget
|
# 'low52w': 'low52w', # put in info widget
|
||||||
# 'high52w': 'high52w',
|
# 'high52w': 'high52w',
|
||||||
# "lastTradePriceTrHrs": 7.99,
|
# "lastTradePriceTrHrs": 7.99,
|
||||||
|
# 'lastTradeTime': ('time', datetime.fromisoformat),
|
||||||
# "lastTradeTick": "Equal",
|
# "lastTradeTick": "Equal",
|
||||||
# "symbolId": 3575753,
|
# "symbolId": 3575753,
|
||||||
# "tier": "",
|
# "tier": "",
|
||||||
|
|
Loading…
Reference in New Issue