Change `Position.clearsdict()` -> `.clearsitems()`
Since apparently rendering to dict from a sorted generator func clearly doesn't preserve the order when using a `dict`-comprehension.. Further, there's really no reason to strictly return a `dict`. Adjust `.calc.ppu()` to make the return value instead a `list[tuple[str, dict]]`; this results in the current df cumsum values matching the original impl and the existing `binance.paper` unit tests now passing XD Other details that fix a variety of nonsense.. - adjust all `.clearsitems()` consumers to the new list output. - use `str(pendulum.now())` in `Position.from_msg()` since adding multiples with an `unknown` str will obviously discard them, facepalm. - fix `.calc.ppu()` to NOT short circuit when `accum_size` is 0; it's been causing all sorts of incorrect size outputs in the clearing table.. lel, this is what fixed the unit test!account_tests
parent
fe78277948
commit
8a10cbf6ab
|
@ -211,9 +211,16 @@ class TransactionLedger(UserDict):
|
|||
Return entire output from ``.iter_txns()`` in a ``dict``.
|
||||
|
||||
'''
|
||||
return {
|
||||
t.tid: t for t in self.iter_txns(symcache=symcache)
|
||||
}
|
||||
txns: dict[str, Transaction] = {}
|
||||
for t in self.iter_txns(symcache=symcache):
|
||||
|
||||
if not t:
|
||||
log.warning(f'{self.mod.name}:{self.account} TXN is -> {t}')
|
||||
continue
|
||||
|
||||
txns[t.tid] = t
|
||||
|
||||
return txns
|
||||
|
||||
def write_config(self) -> None:
|
||||
'''
|
||||
|
@ -386,7 +393,7 @@ def open_trade_ledger(
|
|||
account=account,
|
||||
mod=mod,
|
||||
symcache=symcache,
|
||||
tx_sort=tx_sort,
|
||||
tx_sort=getattr(mod, 'tx_sort', tx_sort),
|
||||
)
|
||||
try:
|
||||
yield ledger
|
||||
|
|
|
@ -144,12 +144,11 @@ class Position(Struct):
|
|||
# def bep() -> float:
|
||||
# ...
|
||||
|
||||
def clearsdict(self) -> dict[str, dict]:
|
||||
clears: dict[str, dict] = ppu(
|
||||
def clearsitems(self) -> list[(str, dict)]:
|
||||
return ppu(
|
||||
self.iter_by_type('clear'),
|
||||
as_ledger=True
|
||||
)
|
||||
return clears
|
||||
|
||||
def iter_by_type(
|
||||
self,
|
||||
|
@ -195,7 +194,7 @@ class Position(Struct):
|
|||
cumsize: float = 0
|
||||
clears_since_zero: list[dict] = []
|
||||
|
||||
for tid, cleardict in self.clearsdict().items():
|
||||
for tid, cleardict in self.clearsitems():
|
||||
cumsize = float(
|
||||
# self.mkt.quantize(cumsize + cleardict['tx'].size
|
||||
self.mkt.quantize(cleardict['cumsize'])
|
||||
|
@ -295,6 +294,8 @@ class Position(Struct):
|
|||
) -> None:
|
||||
|
||||
mkt: MktPair = self.mkt
|
||||
now_dt: pendulum.DateTime = now()
|
||||
now_str: str = str(now_dt)
|
||||
|
||||
# NOTE WARNING XXX: we summarize the pos with a single
|
||||
# summary transaction (for now) until we either pass THIS
|
||||
|
@ -303,13 +304,16 @@ class Position(Struct):
|
|||
t = Transaction(
|
||||
fqme=mkt.fqme,
|
||||
bs_mktid=mkt.bs_mktid,
|
||||
tid='unknown',
|
||||
size=msg['size'],
|
||||
price=msg['avg_price'],
|
||||
cost=0,
|
||||
|
||||
# NOTE: special provisions required!
|
||||
# - tid needs to be unique or this txn will be ignored!!
|
||||
tid=now_str,
|
||||
|
||||
# TODO: also figure out how to avoid this!
|
||||
dt=now(),
|
||||
dt=now_dt,
|
||||
)
|
||||
self.add_clear(t)
|
||||
|
||||
|
@ -342,11 +346,11 @@ class Position(Struct):
|
|||
Inserts are always done in datetime sorted order.
|
||||
|
||||
'''
|
||||
added: bool = False
|
||||
# added: bool = False
|
||||
tid: str = t.tid
|
||||
if tid in self._events:
|
||||
log.warning(f'{t} is already added?!')
|
||||
return added
|
||||
# return added
|
||||
|
||||
# TODO: apparently this IS possible with a dict but not
|
||||
# common and probably not that beneficial unless we're also
|
||||
|
@ -390,9 +394,9 @@ class Position(Struct):
|
|||
if self.expired():
|
||||
return 0.
|
||||
|
||||
clears: list[dict] = list(self.clearsdict().values())
|
||||
clears: list[(str, dict)] = self.clearsitems()
|
||||
if clears:
|
||||
return clears[-1]['cumsize']
|
||||
return clears[-1][1]['cumsize']
|
||||
else:
|
||||
return 0.
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ if TYPE_CHECKING:
|
|||
TransactionLedger,
|
||||
)
|
||||
|
||||
|
||||
def ppu(
|
||||
clears: Iterator[Transaction],
|
||||
|
||||
|
@ -56,7 +57,7 @@ def ppu(
|
|||
# new position fields inserted alongside each entry.
|
||||
as_ledger: bool = False,
|
||||
|
||||
) -> float:
|
||||
) -> float | list[(str, dict)]:
|
||||
'''
|
||||
Compute the "price-per-unit" price for the given non-zero sized
|
||||
rolling position.
|
||||
|
@ -86,7 +87,8 @@ def ppu(
|
|||
'''
|
||||
asize_h: list[float] = [] # historical accumulative size
|
||||
ppu_h: list[float] = [] # historical price-per-unit
|
||||
ledger: dict[str, dict] = {}
|
||||
# ledger: dict[str, dict] = {}
|
||||
ledger: list[dict] = []
|
||||
|
||||
t: Transaction
|
||||
for t in clears:
|
||||
|
@ -95,16 +97,10 @@ def ppu(
|
|||
is_clear: bool = not isinstance(clear_price, str)
|
||||
|
||||
last_accum_size = asize_h[-1] if asize_h else 0
|
||||
accum_size = last_accum_size + clear_size
|
||||
accum_size: float = last_accum_size + clear_size
|
||||
accum_sign = copysign(1, accum_size)
|
||||
|
||||
sign_change: bool = False
|
||||
|
||||
if accum_size == 0:
|
||||
ppu_h.append(0)
|
||||
asize_h.append(0)
|
||||
continue
|
||||
|
||||
# on transfers we normally write some non-valid
|
||||
# price since withdrawal to another account/wallet
|
||||
# has nothing to do with inter-asset-market prices.
|
||||
|
@ -170,9 +166,6 @@ def ppu(
|
|||
else:
|
||||
ppu = cost_basis / abs_new_size
|
||||
|
||||
# ppu_h.append(ppu)
|
||||
# asize_h.append(accum_size)
|
||||
|
||||
else:
|
||||
# TODO: for PPU we should probably handle txs out
|
||||
# (aka withdrawals) similarly by simply not having
|
||||
|
@ -185,8 +178,6 @@ def ppu(
|
|||
# need to be updated since the ppu remains constant
|
||||
# and gets weighted by the new size.
|
||||
ppu: float = ppu_h[-1] # set to previous value
|
||||
# ppu_h.append(ppu_h[-1])
|
||||
# asize_h.append(accum_size)
|
||||
|
||||
# extend with new rolling metric for this step
|
||||
ppu_h.append(ppu)
|
||||
|
@ -194,13 +185,17 @@ def ppu(
|
|||
|
||||
# ledger[t.tid] = {
|
||||
# 'txn': t,
|
||||
ledger[t.tid] = t.to_dict() | {
|
||||
'ppu': ppu,
|
||||
'cumsize': accum_size,
|
||||
'sign_change': sign_change,
|
||||
# ledger[t.tid] = t.to_dict() | {
|
||||
ledger.append((
|
||||
t.tid,
|
||||
t.to_dict() | {
|
||||
'ppu': ppu,
|
||||
'cumsize': accum_size,
|
||||
'sign_change': sign_change,
|
||||
|
||||
# TODO: cum_pnl, bep
|
||||
}
|
||||
# TODO: cum_pnl, bep
|
||||
}
|
||||
))
|
||||
|
||||
final_ppu = ppu_h[-1] if ppu_h else 0
|
||||
# TODO: once we have etypes in all ledger entries..
|
||||
|
|
Loading…
Reference in New Issue