From ca1c1cf41542448a66201b730f557b372cfe71f4 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Thu, 10 Feb 2022 11:58:45 -0500 Subject: [PATCH 1/2] Annoying doc strings --- piker/brokers/ib.py | 11 +++++++---- piker/clearing/_ems.py | 3 ++- piker/clearing/_messages.py | 14 ++++++++++---- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/piker/brokers/ib.py b/piker/brokers/ib.py index 788bc829..5cf7d2f0 100644 --- a/piker/brokers/ib.py +++ b/piker/brokers/ib.py @@ -20,6 +20,7 @@ Interactive Brokers API backend. Note the client runs under an ``asyncio`` loop (since ``ib_insync`` is built on it) and thus actor aware API calls must be spawned with ``infected_aio==True``. + """ from contextlib import asynccontextmanager as acm from dataclasses import asdict @@ -547,10 +548,12 @@ class Client: # existing order so ask the client to create a new one (which it # seems to do by allocating an int counter - collision prone..) reqid: int = None, - ) -> int: - """Place an order and return integer request id provided by client. - """ + ) -> int: + ''' + Place an order and return integer request id provided by client. + + ''' try: contract = self._contracts[symbol] except KeyError: @@ -1608,7 +1611,7 @@ async def handle_order_requests( global _accounts2clients - # request_msg: dict + request_msg: dict async for request_msg in ems_order_stream: log.info(f'Received order request {request_msg}') diff --git a/piker/clearing/_ems.py b/piker/clearing/_ems.py index 1567f795..10b1b18d 100644 --- a/piker/clearing/_ems.py +++ b/piker/clearing/_ems.py @@ -521,7 +521,8 @@ async def translate_and_relay_brokerd_events( router: Router, ) -> AsyncIterator[dict]: - '''Trades update loop - receive updates from ``brokerd`` trades + ''' + Trades update loop - receive updates from ``brokerd`` trades endpoint, convert to EMS response msgs, transmit **only** to ordering client(s). diff --git a/piker/clearing/_messages.py b/piker/clearing/_messages.py index e7fadccd..ec5f4afb 100644 --- a/piker/clearing/_messages.py +++ b/piker/clearing/_messages.py @@ -155,8 +155,11 @@ class BrokerdOrder(BaseModel): class BrokerdOrderAck(BaseModel): - '''Immediate reponse to a brokerd order request providing - the broker specifci unique order id. + ''' + Immediate reponse to a brokerd order request providing the broker + specific unique order id so that the EMS can associate this + (presumably differently formatted broker side ID) with our own + ``.oid`` (which is a uuid4). ''' name: str = 'ack' @@ -203,7 +206,8 @@ class BrokerdStatus(BaseModel): class BrokerdFill(BaseModel): - '''A single message indicating a "fill-details" event from the broker + ''' + A single message indicating a "fill-details" event from the broker if avaiable. ''' @@ -227,9 +231,11 @@ class BrokerdFill(BaseModel): class BrokerdError(BaseModel): - '''Optional error type that can be relayed to emsd for error handling. + ''' + Optional error type that can be relayed to emsd for error handling. This is still a TODO thing since we're not sure how to employ it yet. + ''' name: str = 'error' oid: str From 7b13124dd4acd26f0e7dbb04fed88e5170a4a93f Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Thu, 10 Feb 2022 12:48:13 -0500 Subject: [PATCH 2/2] Keep clear loop price pedantically up to date To avoid the "trigger finger" issue (darks execing before they should due to a stale last price state, normally when generating a trigger predicate..) always iterate the loop and update the last known book price even when no execs/triggered orders are registered. --- piker/clearing/_ems.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/piker/clearing/_ems.py b/piker/clearing/_ems.py index 10b1b18d..ee1ad8ac 100644 --- a/piker/clearing/_ems.py +++ b/piker/clearing/_ems.py @@ -54,7 +54,8 @@ def mk_check( action: str, ) -> Callable[[float, float], bool]: - """Create a predicate for given ``exec_price`` based on last known + ''' + Create a predicate for given ``exec_price`` based on last known price, ``known_last``. This is an automatic alert level thunk generator based on where the @@ -62,7 +63,7 @@ def mk_check( interest is; pick an appropriate comparison operator based on avoiding the case where the a predicate returns true immediately. - """ + ''' # str compares: # https://stackoverflow.com/questions/46708708/compare-strings-in-numba-compiled-function @@ -139,29 +140,32 @@ async def clear_dark_triggers( book: _DarkBook, ) -> None: - """Core dark order trigger loop. + ''' + Core dark order trigger loop. Scan the (price) data feed and submit triggered orders to broker. - """ - # this stream may eventually contain multiple symbols + ''' # XXX: optimize this for speed! + # TODO: + # - numba all this! + # - this stream may eventually contain multiple symbols async for quotes in quote_stream: - - # TODO: numba all this! - # start = time.time() for sym, quote in quotes.items(): - - execs = book.orders.get(sym, None) - if execs is None: - continue + execs = book.orders.get(sym, {}) for tick in iterticks( quote, # dark order price filter(s) - types=('ask', 'bid', 'trade', 'last') + types=( + 'ask', + 'bid', + 'trade', + 'last', + # 'dark_trade', # TODO: should allow via config? + ) ): price = tick.get('price') ttype = tick['type'] @@ -178,7 +182,6 @@ async def clear_dark_triggers( ) in ( tuple(execs.items()) ): - if ( not pred or ttype not in tf or @@ -290,7 +293,8 @@ class TradesRelay: class Router(BaseModel): - '''Order router which manages and tracks per-broker dark book, + ''' + Order router which manages and tracks per-broker dark book, alerts, clearing and related data feed management. A singleton per ``emsd`` actor.