From 34975dfbd5dec7e54cfdf54b03a0d1d50e10470d Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Thu, 26 May 2022 18:37:33 -0400 Subject: [PATCH 1/3] First-draft flex report loader/parsing and write to `trades.toml` conf file --- piker/brokers/ib.py | 76 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/piker/brokers/ib.py b/piker/brokers/ib.py index 2fed7581..f311477b 100644 --- a/piker/brokers/ib.py +++ b/piker/brokers/ib.py @@ -2614,3 +2614,79 @@ async def data_reset_hack( # we don't really need the ``xdotool`` approach any more B) return True + + +def load_flex_trades( + path: Optional[str] = None, + +) -> dict[str, str]: + + from pprint import pprint + from ib_insync import flexreport, util + + conf = get_config() + + if not path: + # load ``brokers.toml`` and try to get the flex + # token and query id that must be previously defined + # by the user. + token = conf.get('flex_token') + if not token: + raise ValueError( + 'You must specify a ``flex_token`` field in your' + '`brokers.toml` in order load your trade log, see our' + 'intructions for how to set this up here:\n' + 'PUT LINK HERE!' + ) + + qid = conf['flex_trades_query_id'] + + # TODO: hack this into our logging + # system like we do with the API client.. + util.logToConsole() + + # TODO: rewrite the query part of this with async..httpx? + report = flexreport.FlexReport( + token=token, + queryId=qid, + ) + + else: + # XXX: another project we could potentially look at, + # https://pypi.org/project/ibflex/ + report = flexreport.FlexReport(path=path) + + trade_entries = report.extract('Trade') + trades = { + # XXX: LOL apparently ``toml`` has a bug + # where a section key error will show up in the write + # if you leave this as an ``int``? + str(t.__dict__['tradeID']): t.__dict__ + for t in trade_entries + } + + ln = len(trades) + log.info(f'Loaded {ln} trades from flex query') + + trades_by_account = {} + for tid, trade in trades.items(): + trades_by_account.setdefault( + # oddly for some so-called "BookTrade" entries + # this field seems to be blank, no cuckin clue. + # trade['ibExecID'] + str(trade['accountId']), {} + )[tid] = trade + + section = {'ib': trades_by_account} + pprint(section) + + # TODO: load the config first and append in + # the new trades loaded here.. + try: + config.write(section, 'trades') + except KeyError: + import pdbpp; pdbpp.set_trace() + + +if __name__ == '__main__': + load_flex_trades() From 41f24f3de6e93a8f4b4b6b1b729b5f3d07e705c5 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Fri, 27 May 2022 08:01:57 -0400 Subject: [PATCH 2/3] Add example flex variables to brokers template --- config/brokers.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/brokers.toml b/config/brokers.toml index adee409e..18d67da5 100644 --- a/config/brokers.toml +++ b/config/brokers.toml @@ -26,6 +26,13 @@ ports = [ 7497, # tws ] +# XXX: for a paper account the flex web query service +# is not supported so you have to manually download +# and XML report and put it in a location that can be +# accessed by the ``brokerd.ib`` backend code for parsing. +flex_token = '666666666666666666666666' +flex_trades_query_id = '666666' # live account + # when clients are being scanned this determines # which clients are preferred to be used for data # feeds based on the order of account names, if From 827b5f9c45ef70ea5a2cc7bf13cc18a883a4ce5a Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Sat, 4 Jun 2022 13:44:12 -0400 Subject: [PATCH 3/3] Add event type into msg dict --- piker/brokers/ib.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/piker/brokers/ib.py b/piker/brokers/ib.py index f311477b..9b32521f 100644 --- a/piker/brokers/ib.py +++ b/piker/brokers/ib.py @@ -780,23 +780,29 @@ class Client: ) -> None: - log.error(errorString) reason = errorString if reqId == -1: # it's a general event? key = 'event' + log.info(errorString) + else: key = 'error' + log.error(errorString) try: to_trio.send_nowait(( key, # error "object" - {'reqid': reqId, - 'reason': reason, - 'contract': contract} + { + 'type': key, + 'reqid': reqId, + 'reason': reason, + 'error_code': errorCode, + 'contract': contract, + } )) except trio.BrokenResourceError: # XXX: eventkit's ``Event.emit()`` for whatever redic @@ -2248,6 +2254,7 @@ async def trades_dialogue( recv_trade_updates, client=client, ) as (first, trade_event_stream): + task_status.started(trade_event_stream) await trio.sleep_forever()