Finally, support full `MktPair` + `Asset` msgs
Previously we weren't necessarily serializing mkt pairs (for IPC msging) entirely bc the assets `.src/.dst` were being sent just by their str-names. This now properly supports fully serializing `Asset`s as `dict`-msgs such that use of `MktPair.to_dict()` can be transmitted over `tractor.MsgStream`s and deserialized entirely back to struct from on the receiver end. Deats: - implement `Asset.to_dict()` and `.from_msg()` - adjust `MktPair.to_dict()` and `.from_msg()` to use these methods. - drop all the hacky "if .src/.dst is str" handling. - add better `MktPair.from_fqme()` input handling for expiry and venue; ensure that either can be extracted from passed fqme *and* if so they are also popped from any duplicate passed in `**kwargs**`.account_tests
parent
c8c28df62f
commit
309b91676d
|
@ -130,8 +130,26 @@ class Asset(Struct, frozen=True):
|
|||
# should not be explicitly required in our generic API.
|
||||
info: dict | None = None
|
||||
|
||||
# TODO?
|
||||
# _to_dict_skip = {'info'}
|
||||
# `None` is not toml-compat so drop info
|
||||
# if no extra data added..
|
||||
def to_dict(self) -> dict:
|
||||
dct = super().to_dict()
|
||||
if (info := dct.pop('info', None)):
|
||||
dct['info'] = info
|
||||
|
||||
assert dct['tx_tick']
|
||||
return dct
|
||||
|
||||
@classmethod
|
||||
def from_msg(
|
||||
cls,
|
||||
msg: dict[str, Any],
|
||||
) -> Asset:
|
||||
return Asset(
|
||||
tx_tick=Decimal(str(msg.pop('tx_tick'))),
|
||||
info=msg.pop('info', None),
|
||||
**msg,
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
@ -288,6 +306,8 @@ class MktPair(Struct, frozen=True):
|
|||
# strike price, call or put, swap type, exercise model, etc.
|
||||
contract_info: list[str] | None = None
|
||||
|
||||
# TODO: rename to sectype since all of these can
|
||||
# be considered "securities"?
|
||||
_atype: str = ''
|
||||
|
||||
# allow explicit disable of the src part of the market
|
||||
|
@ -298,6 +318,18 @@ class MktPair(Struct, frozen=True):
|
|||
def __str__(self) -> str:
|
||||
return self.fqme
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
d = super().to_dict()
|
||||
d['src'] = self.src.to_dict()
|
||||
d['dst'] = self.dst.to_dict()
|
||||
|
||||
if self.contract_info is None:
|
||||
d.pop('contract_info')
|
||||
|
||||
# d.pop('_fqme_without_src')
|
||||
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
def from_msg(
|
||||
cls,
|
||||
|
@ -309,35 +341,20 @@ class MktPair(Struct, frozen=True):
|
|||
|
||||
'''
|
||||
dst_asset_msg = msg.pop('dst')
|
||||
dst = Asset.from_msg(dst_asset_msg) # .copy()
|
||||
|
||||
src_asset_msg = msg.pop('src')
|
||||
src = Asset.from_msg(src_asset_msg) # .copy()
|
||||
|
||||
if isinstance(dst_asset_msg, str):
|
||||
src: str = str(src_asset_msg)
|
||||
assert isinstance(src, str)
|
||||
return cls.from_fqme(
|
||||
dst_asset_msg,
|
||||
src=src,
|
||||
**msg,
|
||||
)
|
||||
|
||||
else:
|
||||
# NOTE: we call `.copy()` here to ensure
|
||||
# type casting!
|
||||
dst = Asset(**dst_asset_msg).copy()
|
||||
if not isinstance(src_asset_msg, str):
|
||||
src = Asset(**src_asset_msg).copy()
|
||||
else:
|
||||
src = str(src_asset_msg)
|
||||
|
||||
return cls(
|
||||
dst=dst,
|
||||
src=src,
|
||||
**msg,
|
||||
# XXX NOTE: ``msgspec`` can encode `Decimal`
|
||||
# but it doesn't decide to it by default since
|
||||
# we aren't spec-cing these msgs as structs, SO
|
||||
# we have to ensure we do a struct type case (which `.copy()`
|
||||
# does) to ensure we get the right type!
|
||||
return cls(
|
||||
dst=dst,
|
||||
src=src,
|
||||
**msg,
|
||||
).copy()
|
||||
|
||||
@property
|
||||
|
@ -365,7 +382,20 @@ class MktPair(Struct, frozen=True):
|
|||
):
|
||||
_fqme = f'{fqme}.{broker}'
|
||||
|
||||
broker, mkt_ep_key, venue, suffix = unpack_fqme(_fqme)
|
||||
broker, mkt_ep_key, venue, expiry = unpack_fqme(_fqme)
|
||||
|
||||
kven: str = kwargs.pop('venue', venue)
|
||||
if venue:
|
||||
assert venue == kven
|
||||
else:
|
||||
venue = kven
|
||||
|
||||
exp: str = kwargs.pop('expiry', expiry)
|
||||
if expiry:
|
||||
assert exp == expiry
|
||||
else:
|
||||
expiry = exp
|
||||
|
||||
dst: Asset = Asset.guess_from_mkt_ep_key(
|
||||
mkt_ep_key,
|
||||
atype=kwargs.get('_atype'),
|
||||
|
@ -384,7 +414,7 @@ class MktPair(Struct, frozen=True):
|
|||
venue=venue,
|
||||
# XXX NOTE: we presume this token
|
||||
# if the expiry for now!
|
||||
expiry=suffix,
|
||||
expiry=expiry,
|
||||
|
||||
price_tick=price_tick,
|
||||
size_tick=size_tick,
|
||||
|
|
Loading…
Reference in New Issue