From d4c8ba19a226bcff9ee9f4a766e1c977c31a4071 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 18 Apr 2023 18:55:01 -0400 Subject: [PATCH] `.accounting._mktinfo`: better fqme `MktPair` handling It needed some work.. - Make `unpack_fqme()` always return a 4-tuple handling the venue and suffix parts more generally. - add `Asset.Asset.guess_from_mkt_ep_key()` a like-it-sounds hack at trying to render a `.dst: Asset` for most most purposes throughout the stack. - always try to preprocess the input `fqme: str` with `unpack_fqme()` in `MktPair.from_fqme()` and use the new `Asset` method (above) to make up a `.dst: Asset` pulling as much meta-info we can from the caller. - add `MktPair.bs_fqme` to get the thing without the broker part.. - add an `'unknown'` value to the `_derivs` def. - drop `Symbol.from_fqsn()` and `unpack_fqsn()` more generally (yes BREAKING). --- piker/accounting/_mktinfo.py | 104 ++++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 15 deletions(-) diff --git a/piker/accounting/_mktinfo.py b/piker/accounting/_mktinfo.py index 02ed7a9d..7ab59a66 100644 --- a/piker/accounting/_mktinfo.py +++ b/piker/accounting/_mktinfo.py @@ -54,6 +54,9 @@ _derivs: list[str] = [ 'continuous_future', 'option', 'futures_option', + + # if we can't figure it out, presume the worst XD + 'unknown', ] # NOTE: a tag for other subsystems to try @@ -143,6 +146,39 @@ class Asset(Struct, frozen=True): rounding=ROUND_HALF_EVEN ) + @classmethod + def guess_from_mkt_ep_key( + cls, + mkt_ep_key: str, + atype: str | None = None, + + ) -> Asset: + ''' + A hacky guess method for presuming a (target) asset's properties + based on either the actualy market endpoint key, or config settings + from the user. + + ''' + atype = atype or 'unknown' + + # attempt to strip off any source asset + # via presumed syntax of: + # - / + # - . + # - etc. + for char in ['/', '.']: + dst, _, src = mkt_ep_key.partition(char) + if src: + if not atype: + atype = 'fiat' + break + + return Asset( + name=dst, + atype=atype, + tx_tick=Decimal('0.01'), + ) + def maybe_cons_tokens( tokens: list[Any], @@ -269,15 +305,28 @@ class MktPair(Struct, frozen=True): def from_fqme( cls, fqme: str, + price_tick: float | str, size_tick: float | str, bs_mktid: str, + broker: str | None = None, **kwargs, ) -> MktPair: - broker, key, suffix = unpack_fqme(fqme) + _fqme: str = fqme + if ( + broker + and broker not in fqme + ): + _fqme = f'{fqme}.{broker}' + + broker, mkt_ep_key, venue, suffix = unpack_fqme(_fqme) + dst: Asset = Asset.guess_from_mkt_ep_key( + mkt_ep_key, + atype=kwargs.get('_atype'), + ) # XXX: loading from a fqme string will # leave this pair as "un resolved" meaning @@ -285,13 +334,21 @@ class MktPair(Struct, frozen=True): # which we expect to be filled in by some # backend client with access to that data-info. return cls( - dst=key, # not resolved + # XXX: not resolved to ``Asset`` :( + dst=dst, + + broker=broker, + venue=venue, + # XXX NOTE: we presume this token + # if the expiry for now! + expiry=suffix, + price_tick=price_tick, size_tick=size_tick, bs_mktid=bs_mktid, - broker=broker, **kwargs, + ).copy() @property @@ -381,6 +438,14 @@ class MktPair(Struct, frozen=True): self.broker, ]) + @property + def bs_fqme(self) -> str: + ''' + FQME sin broker part XD + + ''' + return self.fqme.rstrip(f'.{self.broker}') + @property def fqsn(self) -> str: return self.fqme @@ -428,7 +493,9 @@ class MktPair(Struct, frozen=True): def unpack_fqme( fqme: str, -) -> tuple[str, str, str]: + broker: str | None = None + +) -> tuple[str, ...]: ''' Unpack a fully-qualified-symbol-name to ``tuple``. @@ -442,17 +509,26 @@ def unpack_fqme( match tokens: case [mkt_ep, broker]: # probably crypto - # mkt_ep, broker = tokens return ( broker, mkt_ep, '', + '', ) # TODO: swap venue and suffix/deriv-info here? case [mkt_ep, venue, suffix, broker]: pass + # handle `bs_mktid` + `broker` input case + case [ + mkt_ep, venue, suffix + ] if ( + broker + and suffix != broker + ): + pass + case [mkt_ep, venue, broker]: suffix = '' @@ -461,14 +537,13 @@ def unpack_fqme( return ( broker, - '.'.join([mkt_ep, venue]), + mkt_ep, + venue, + # '.'.join([mkt_ep, venue]), suffix, ) -unpack_fqsn = unpack_fqme - - class Symbol(Struct): ''' I guess this is some kinda container thing for dealing with @@ -485,27 +560,26 @@ class Symbol(Struct): broker_info: dict[str, dict[str, Any]] = {} @classmethod - def from_fqsn( + def from_fqme( cls, fqsn: str, info: dict[str, Any], ) -> Symbol: - broker, key, suffix = unpack_fqsn(fqsn) + broker, mktep, venue, suffix = unpack_fqme(fqsn) tick_size = info.get('price_tick_size', 0.01) lot_size = info.get('lot_tick_size', 0.0) return Symbol( - key=key, + broker=broker, + key=mktep, tick_size=tick_size, lot_tick_size=lot_size, + venue=venue, suffix=suffix, broker_info={broker: info}, ) - # compat name mapping - from_fqme = from_fqsn - @property def type_key(self) -> str: return list(self.broker_info.values())[0]['asset_type']