Rejig option chain schema to capture all contracts

kivy_mainline_and_py3.8
Tyler Goodlet 2018-11-13 12:57:21 -05:00
parent 368f21d8d6
commit d145a5a219
2 changed files with 38 additions and 20 deletions

View File

@ -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.
""" """

View File

@ -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": "",