2018-03-20 17:13:07 +00:00
|
|
|
"""
|
2018-11-22 20:53:00 +00:00
|
|
|
Broker high level API layer.
|
2018-03-20 17:13:07 +00:00
|
|
|
"""
|
|
|
|
import inspect
|
|
|
|
from types import ModuleType
|
2018-11-22 20:53:00 +00:00
|
|
|
from typing import List, Dict, Any, Optional
|
2018-03-20 17:13:07 +00:00
|
|
|
|
2018-11-15 03:58:12 +00:00
|
|
|
from ..log import get_logger
|
2018-11-30 13:14:36 +00:00
|
|
|
from .data import DataFeed
|
2018-06-26 21:55:52 +00:00
|
|
|
|
|
|
|
|
2018-03-20 17:13:07 +00:00
|
|
|
log = get_logger('broker.core')
|
|
|
|
|
|
|
|
|
|
|
|
async def api(brokermod: ModuleType, methname: str, **kwargs) -> dict:
|
2018-11-12 02:44:46 +00:00
|
|
|
"""Make (proxy through) a broker API call by name and return its result.
|
2018-03-20 17:13:07 +00:00
|
|
|
"""
|
|
|
|
async with brokermod.get_client() as client:
|
2018-11-12 02:44:46 +00:00
|
|
|
|
2018-03-20 17:13:07 +00:00
|
|
|
meth = getattr(client.api, methname, None)
|
2018-11-12 02:44:46 +00:00
|
|
|
if meth is None:
|
|
|
|
log.warning(
|
2018-11-30 13:14:36 +00:00
|
|
|
f"Couldn't find API method {methname} looking up on client")
|
2018-11-12 02:44:46 +00:00
|
|
|
meth = getattr(client, methname, None)
|
|
|
|
|
2018-03-20 17:13:07 +00:00
|
|
|
if meth is None:
|
|
|
|
log.error(f"No api method `{methname}` could be found?")
|
|
|
|
return
|
2018-11-12 02:44:46 +00:00
|
|
|
|
|
|
|
if not kwargs:
|
2018-03-20 17:13:07 +00:00
|
|
|
# verify kwargs requirements are met
|
|
|
|
sig = inspect.signature(meth)
|
|
|
|
if sig.parameters:
|
|
|
|
log.error(
|
|
|
|
f"Argument(s) are required by the `{methname}` method: "
|
|
|
|
f"{tuple(sig.parameters.keys())}")
|
|
|
|
return
|
|
|
|
|
|
|
|
return await meth(**kwargs)
|
|
|
|
|
|
|
|
|
2018-11-12 02:44:46 +00:00
|
|
|
async def stocks_quote(
|
|
|
|
brokermod: ModuleType,
|
|
|
|
tickers: List[str]
|
|
|
|
) -> Dict[str, Dict[str, Any]]:
|
2018-03-20 17:13:07 +00:00
|
|
|
"""Return quotes dict for ``tickers``.
|
|
|
|
"""
|
|
|
|
async with brokermod.get_client() as client:
|
2018-03-21 01:01:55 +00:00
|
|
|
results = await client.quote(tickers)
|
2018-11-30 13:14:36 +00:00
|
|
|
for val in results:
|
2018-03-21 01:01:55 +00:00
|
|
|
if val is None:
|
|
|
|
brokermod.log.warn(f"Could not find symbol {key}?")
|
|
|
|
|
|
|
|
return results
|
2018-03-20 17:13:07 +00:00
|
|
|
|
|
|
|
|
2018-11-30 13:14:36 +00:00
|
|
|
# TODO: these need tests
|
2018-11-13 17:57:21 +00:00
|
|
|
async def option_chain(
|
|
|
|
brokermod: ModuleType,
|
|
|
|
symbol: str,
|
2018-11-22 20:53:00 +00:00
|
|
|
date: Optional[str] = None,
|
2018-11-13 17:57:21 +00:00
|
|
|
) -> Dict[str, Dict[str, Dict[str, Any]]]:
|
2018-11-22 20:53:00 +00:00
|
|
|
"""Return option chain for ``symbol`` for ``date``.
|
|
|
|
|
|
|
|
By default all expiries are returned. If ``date`` is provided
|
|
|
|
then contract quotes for that single expiry are returned.
|
|
|
|
"""
|
|
|
|
async with brokermod.get_client() as client:
|
|
|
|
if date:
|
|
|
|
id = int((await client.tickers2ids([symbol]))[symbol])
|
|
|
|
# build contracts dict for single expiry
|
2018-11-30 13:14:36 +00:00
|
|
|
return await client.option_chains(
|
|
|
|
{(symbol, id, date): {}})
|
2018-11-22 20:53:00 +00:00
|
|
|
else:
|
|
|
|
# get all contract expiries
|
|
|
|
# (takes a long-ass time on QT fwiw)
|
|
|
|
contracts = await client.get_all_contracts([symbol])
|
|
|
|
# return chains for all dates
|
|
|
|
return await client.option_chains(contracts)
|
|
|
|
|
|
|
|
|
|
|
|
async def contracts(
|
|
|
|
brokermod: ModuleType,
|
|
|
|
symbol: str,
|
|
|
|
) -> Dict[str, Dict[str, Dict[str, Any]]]:
|
|
|
|
"""Return option contracts (all expiries) for ``symbol``.
|
2018-11-13 17:57:21 +00:00
|
|
|
"""
|
|
|
|
async with brokermod.get_client() as client:
|
2018-11-30 13:14:36 +00:00
|
|
|
# return await client.get_all_contracts([symbol])
|
2018-11-22 20:53:00 +00:00
|
|
|
return await client.get_all_contracts([symbol])
|