Allow mkt info table input to `.iter_trans()`

Since ledger records are often provided (and thus stored) from most
backends *without* containing the info we normally need for accounting
defined by `MktPair`, this extends the ledger method to take in a table
that allows assigning the `Transaction.sys` from an fqme lookup. This
way client code (like the paper engine and new ledger mgmt tools) can
do the mkt info lookup before hand and then load both ledger
`Transactions` and positions via the `PpTable` and get correct
accounting calculations, always :fingers_crossed:

Also adds `TransactionLedger.update_from_t(t: Transaction)` to allow
updating directly from an existing tran instead of making the user cast
to a `dict` first. Includes fix to `.to_dict()` to always pop the `.sym`
again to avoid client code having to do so.
rekt_pps
Tyler Goodlet 2023-04-17 14:50:07 -04:00
parent 0d2e713e9a
commit bba1ee43ff
1 changed files with 29 additions and 3 deletions

View File

@ -72,7 +72,8 @@ class Transaction(Struct, frozen=True):
def fqme(self) -> str: def fqme(self) -> str:
return self.fqsn return self.fqsn
# TODO: drop the Symbol type # TODO: drop the Symbol type, construct using
# t.sys (the transaction system)
# the underlying "transaction system", normally one of a ``MktPair`` # the underlying "transaction system", normally one of a ``MktPair``
# (a description of a tradable double auction) or a ledger-recorded # (a description of a tradable double auction) or a ledger-recorded
@ -93,6 +94,10 @@ class Transaction(Struct, frozen=True):
def to_dict(self) -> dict: def to_dict(self) -> dict:
dct = super().to_dict() dct = super().to_dict()
# TODO: switch to sys!
dct.pop('sym')
# ensure we use a pendulum formatted # ensure we use a pendulum formatted
# ISO style str here!@ # ISO style str here!@
dct['dt'] = str(self.dt) dct['dt'] = str(self.dt)
@ -122,11 +127,24 @@ class TransactionLedger(UserDict):
''' '''
with self.file_path.open(mode='w') as fp: with self.file_path.open(mode='w') as fp:
# rewrite the key name to fqme if needed
fqsn: str = self.data.get('fqsn')
if fqsn:
self.data['fqme'] = fqsn
toml.dump(self.data, fp) toml.dump(self.data, fp)
def update_from_t(
self,
t: Transaction,
) -> None:
self.data[t.tid] = t.to_dict()
def iter_trans( def iter_trans(
self, self,
broker: str = 'paper', broker: str = 'paper',
mkt_by_fqme: dict[str, MktPair] | None = None,
) -> Generator[ ) -> Generator[
tuple[str, Transaction], tuple[str, Transaction],
@ -158,6 +176,7 @@ class TransactionLedger(UserDict):
fqme = txdict.get('fqme', txdict['fqsn']) fqme = txdict.get('fqme', txdict['fqsn'])
dt = parse(txdict['dt']) dt = parse(txdict['dt'])
expiry = txdict.get('expiry') expiry = txdict.get('expiry')
mkt_by_fqme = mkt_by_fqme or {}
yield ( yield (
tid, tid,
@ -171,7 +190,7 @@ class TransactionLedger(UserDict):
bs_mktid=txdict['bs_mktid'], bs_mktid=txdict['bs_mktid'],
# optional # optional
sym=None, sym=mkt_by_fqme[fqme] if mkt_by_fqme else None,
expiry=parse(expiry) if expiry else None, expiry=parse(expiry) if expiry else None,
) )
) )
@ -180,12 +199,19 @@ class TransactionLedger(UserDict):
self, self,
broker: str = 'paper', broker: str = 'paper',
**kwargs,
) -> dict[str, Transaction]: ) -> dict[str, Transaction]:
''' '''
Return the entire output from ``.iter_trans()`` in a ``dict``. Return the entire output from ``.iter_trans()`` in a ``dict``.
''' '''
return dict(self.iter_trans()) return dict(
self.iter_trans(
broker,
**kwargs,
)
)
@cm @cm