From 9c7ca84fef5665a629a4a94979d0231b407cecdc Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Sun, 2 Dec 2018 00:37:27 -0500 Subject: [PATCH] Include strike and expiry in option quotes --- piker/brokers/questrade.py | 21 ++++++++++++++++++--- tests/test_questrade.py | 2 ++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/piker/brokers/questrade.py b/piker/brokers/questrade.py index 330580af..ea530c97 100644 --- a/piker/brokers/questrade.py +++ b/piker/brokers/questrade.py @@ -124,6 +124,7 @@ class Client: self._reload_config(config) self._symbol_cache: Dict[str, int] = {} self._contracts2expiries = {} + self._optids2contractinfo = {} def _reload_config(self, config=None, **kwargs): log.warn("Reloading access config data") @@ -323,6 +324,16 @@ class Client: item['strikePrice']: item for item in byroot['chainPerRoot'][0]['chainPerStrikePrice'] } + + # fill out contract id to strike expiry map + for key, bystrikes in by_key.items(): + for strike, ids in bystrikes.items(): + for elem in ('callSymbolId', 'putSymbolId'): + self._optids2contractinfo[ + ids[elem]] = { + 'strike': strike, + 'expiry': key.expiry, + } return by_key async def option_chains( @@ -339,6 +350,12 @@ class Client: # index by .symbol, .expiry since that's what # a subscriber (currently) sends initially quote['key'] = (key[0], key[2]) + # update with expiry and strike (Obviously the + # QT api designers are using some kind of severely + # stupid disparate table system where they keep + # contract info in a separate table from the quote format + # keys. I'm really not surprised though - windows shop..) + quote.update(self._optids2contractinfo[quote['symbolId']]) batch.extend(quotes) return batch @@ -471,9 +488,7 @@ async def option_quoter(client: Client, tickers: List[str]): if isinstance(tickers[0], tuple): datetime.fromisoformat(tickers[0][1]) else: - log.warn(f"Ignoring option quoter call with {tickers}") - # TODO make caller always check that a quoter has been set - return + raise ValueError(f'Option subscription format is (symbol, expiry)') @async_lifo_cache(maxsize=128) async def get_contract_by_date(sym_date_pairs: Tuple[Tuple[str, str]]): diff --git a/tests/test_questrade.py b/tests/test_questrade.py index 482c1e37..4c3ac059 100644 --- a/tests/test_questrade.py +++ b/tests/test_questrade.py @@ -53,6 +53,7 @@ _ex_quotes = { 'bidSize': 0, 'delay': 0, 'delta': -0.212857, + "expiry": "2021-01-15T00:00:00.000000-05:00", 'gamma': 0.003524, 'highPrice': 0, 'isHalted': False, @@ -66,6 +67,7 @@ _ex_quotes = { 'openInterest': 1, 'openPrice': 0, 'rho': -0.891868, + "strike": 8, 'symbol': 'WEED15Jan21P54.00.MX', 'symbolId': 22739148, 'theta': -0.012911,