Port paper engine to latest `.accounting` sys fixes
- only preload necessary (one for clearing, all for ledger sync) `MktPair` info from the backend using `.get_mkt_info()`, build the `mkt_by_fqme: dict[str, MktPair]` and pass it to `TransactionLedger.iter_trans()`. - use new `TransactionLedger.update_from_t()` method on clears. - sanity check all `mkt_by_fqme` entries against `Flume.mkt` values when we open a data feed. - rename `PaperBoi._syms` -> `._mkts`.rekt_pps
parent
7ee6f36e62
commit
4b7ac1d895
|
@ -38,7 +38,6 @@ from ..brokers import get_brokermod
|
||||||
from .. import data
|
from .. import data
|
||||||
from ..data.types import Struct
|
from ..data.types import Struct
|
||||||
from ..accounting._mktinfo import (
|
from ..accounting._mktinfo import (
|
||||||
Symbol,
|
|
||||||
MktPair,
|
MktPair,
|
||||||
)
|
)
|
||||||
from ..accounting import (
|
from ..accounting import (
|
||||||
|
@ -85,7 +84,7 @@ class PaperBoi(Struct):
|
||||||
_buys: defaultdict[str, bidict]
|
_buys: defaultdict[str, bidict]
|
||||||
_sells: defaultdict[str, bidict]
|
_sells: defaultdict[str, bidict]
|
||||||
_reqids: bidict
|
_reqids: bidict
|
||||||
_syms: dict[str, Symbol] = {}
|
_mkts: dict[str, MktPair] = {}
|
||||||
|
|
||||||
# init edge case L1 spread
|
# init edge case L1 spread
|
||||||
last_ask: tuple[float, float] = (float('inf'), 0) # price, size
|
last_ask: tuple[float, float] = (float('inf'), 0) # price, size
|
||||||
|
@ -262,7 +261,7 @@ class PaperBoi(Struct):
|
||||||
bs_mktid: str = fqme
|
bs_mktid: str = fqme
|
||||||
t = Transaction(
|
t = Transaction(
|
||||||
fqsn=fqme,
|
fqsn=fqme,
|
||||||
sym=self._syms[fqme],
|
sym=self._mkts[fqme],
|
||||||
tid=oid,
|
tid=oid,
|
||||||
size=size,
|
size=size,
|
||||||
price=price,
|
price=price,
|
||||||
|
@ -271,11 +270,8 @@ class PaperBoi(Struct):
|
||||||
bs_mktid=bs_mktid,
|
bs_mktid=bs_mktid,
|
||||||
)
|
)
|
||||||
|
|
||||||
tx = t.to_dict()
|
|
||||||
tx.pop('sym')
|
|
||||||
|
|
||||||
# update in-mem ledger and pos table
|
# update in-mem ledger and pos table
|
||||||
self.ledger.update({oid: tx})
|
self.ledger.update_from_t(t)
|
||||||
self.ppt.update_from_trans({oid: t})
|
self.ppt.update_from_trans({oid: t})
|
||||||
|
|
||||||
# transmit pp msg to ems
|
# transmit pp msg to ems
|
||||||
|
@ -293,12 +289,13 @@ class PaperBoi(Struct):
|
||||||
# inferred from the pair?
|
# inferred from the pair?
|
||||||
# currency=bs_mktid,
|
# currency=bs_mktid,
|
||||||
)
|
)
|
||||||
await self.ems_trades_stream.send(pp_msg)
|
# write all updates to filesys immediately
|
||||||
|
# (adds latency but that works for simulation anyway)
|
||||||
# write all updates to filesys
|
|
||||||
self.ledger.write_config()
|
self.ledger.write_config()
|
||||||
self.ppt.write_config()
|
self.ppt.write_config()
|
||||||
|
|
||||||
|
await self.ems_trades_stream.send(pp_msg)
|
||||||
|
|
||||||
|
|
||||||
async def simulate_fills(
|
async def simulate_fills(
|
||||||
quote_stream: tractor.MsgStream, # noqa
|
quote_stream: tractor.MsgStream, # noqa
|
||||||
|
@ -552,36 +549,51 @@ async def trades_dialogue(
|
||||||
'paper',
|
'paper',
|
||||||
) as ledger
|
) as ledger
|
||||||
):
|
):
|
||||||
# attempt to get market info from the backend instead of presuming
|
# NOTE: retreive market(pair) info from the backend broker
|
||||||
# the ledger entries have everything correct.
|
# since ledger entries (in their backend native format) often
|
||||||
|
# don't contain necessary market info per trade record entry..
|
||||||
|
# - if no fqme was passed in, we presume we're running in
|
||||||
|
# "ledger-sync-only mode" and thus we load mkt info for
|
||||||
|
# each symbol found in the ledger to a ppt table manually.
|
||||||
|
|
||||||
# TODO: how to process ledger info from backends?
|
# TODO: how to process ledger info from backends?
|
||||||
# - should we be rolling our own actor-cached version of these
|
# - should we be rolling our own actor-cached version of these
|
||||||
# client API refs or using portal IPC to send requests to the
|
# client API refs or using portal IPC to send requests to the
|
||||||
# existing brokerd daemon?
|
# existing brokerd daemon?
|
||||||
# - alternatively we can possibly expect and use
|
# - alternatively we can possibly expect and use
|
||||||
# a `.broker.norm_trade_records()` ep?
|
# a `.broker.norm_trade_records()` ep?
|
||||||
fqmes: list[str] = [fqme]
|
brokermod = get_brokermod(broker)
|
||||||
if fqme is None:
|
gmi = getattr(brokermod, 'get_mkt_info', None)
|
||||||
fqmes = list(ppt.pps)
|
|
||||||
|
|
||||||
for fqme in fqmes:
|
# update all transactions with mkt info before
|
||||||
mkt: MktPair | None = None
|
# loading any pps
|
||||||
brokermod = get_brokermod(broker)
|
mkt_by_fqme: dict[str, MktPair | None] = {}
|
||||||
gmi = getattr(brokermod, 'get_mkt_info', None)
|
for tid, tdict in ledger.data.items():
|
||||||
if gmi:
|
|
||||||
|
# TODO: switch this to fqme
|
||||||
|
l_fqme = tdict['fqsn']
|
||||||
|
if (
|
||||||
|
gmi
|
||||||
|
and l_fqme not in mkt_by_fqme
|
||||||
|
):
|
||||||
mkt, pair = await brokermod.get_mkt_info(
|
mkt, pair = await brokermod.get_mkt_info(
|
||||||
fqme.rstrip(f'.{broker}'),
|
l_fqme.rstrip(f'.{broker}'),
|
||||||
)
|
)
|
||||||
|
mkt_by_fqme[l_fqme] = mkt
|
||||||
|
|
||||||
# update pos table from ledger history
|
# if an ``fqme: str`` input was provided we only
|
||||||
ppt.update_from_trans(
|
# need a ``MktPair`` for that one market, since we're
|
||||||
ledger.to_trans(),
|
# running in real simulated-clearing mode, not just ledger
|
||||||
|
# syncing.
|
||||||
|
if (
|
||||||
|
fqme is not None
|
||||||
|
and fqme in mkt_by_fqme
|
||||||
|
):
|
||||||
|
break
|
||||||
|
|
||||||
# NOTE: here we pass in any `MktPair` provided by the
|
# update pos table from ledger history and provide a ``MktPair``
|
||||||
# backend broker instead of assuming the pps.toml contains
|
# lookup for internal position accounting calcs.
|
||||||
# the correct contents!
|
ppt.update_from_trans(ledger.to_trans(mkt_by_fqme=mkt_by_fqme))
|
||||||
force_mkt=mkt
|
|
||||||
)
|
|
||||||
|
|
||||||
pp_msgs: list[BrokerdPosition] = []
|
pp_msgs: list[BrokerdPosition] = []
|
||||||
pos: Position
|
pos: Position
|
||||||
|
@ -621,6 +633,10 @@ async def trades_dialogue(
|
||||||
loglevel=loglevel,
|
loglevel=loglevel,
|
||||||
) as feed,
|
) as feed,
|
||||||
):
|
):
|
||||||
|
# sanity check all the mkt infos
|
||||||
|
for fqme, flume in feed.flumes.items():
|
||||||
|
assert mkt_by_fqme[fqme] == flume.mkt
|
||||||
|
|
||||||
async with (
|
async with (
|
||||||
ctx.open_stream() as ems_stream,
|
ctx.open_stream() as ems_stream,
|
||||||
trio.open_nursery() as n,
|
trio.open_nursery() as n,
|
||||||
|
@ -635,11 +651,8 @@ async def trades_dialogue(
|
||||||
_sells=_sells,
|
_sells=_sells,
|
||||||
_reqids=_reqids,
|
_reqids=_reqids,
|
||||||
|
|
||||||
# TODO: load postions from ledger file
|
_mkts=mkt_by_fqme,
|
||||||
_syms={
|
|
||||||
fqme: flume.symbol
|
|
||||||
for fqme, flume in feed.flumes.items()
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
n.start_soon(
|
n.start_soon(
|
||||||
|
|
Loading…
Reference in New Issue