diff --git a/piker/clearing/_ems.py b/piker/clearing/_ems.py index ba33e584..477da310 100644 --- a/piker/clearing/_ems.py +++ b/piker/clearing/_ems.py @@ -46,6 +46,7 @@ from ..data._normalize import iterticks from ..data._source import ( unpack_fqsn, mk_fqsn, + float_digits, ) from ..data.feed import ( Feed, @@ -1250,6 +1251,7 @@ async def process_client_order_cmds( spread_slap: float = 5 min_tick = flume.symbol.tick_size + min_tick_digits = float_digits(min_tick) if action == 'buy': tickfilter = ('ask', 'last', 'trade') @@ -1258,12 +1260,18 @@ async def process_client_order_cmds( # TODO: we probably need to scale this based # on some near term historical spread # measure? - abs_diff_away = spread_slap * min_tick + abs_diff_away = round( + spread_slap * min_tick, + ndigits=min_tick_digits, + ) elif action == 'sell': tickfilter = ('bid', 'last', 'trade') percent_away = -0.005 - abs_diff_away = -spread_slap * min_tick + abs_diff_away = round( + -spread_slap * min_tick, + ndigits=min_tick_digits, + ) else: # alert tickfilter = ('trade', 'utrade', 'last') diff --git a/piker/pp.py b/piker/pp.py index 8fdaaa4d..48cf0daa 100644 --- a/piker/pp.py +++ b/piker/pp.py @@ -29,6 +29,7 @@ import re import time from typing import ( Any, + Iterator, Optional, Union, ) @@ -116,6 +117,21 @@ class Transaction(Struct, frozen=True): # from: Optional[str] = None +def iter_by_dt( + clears: dict[str, Any], +) -> Iterator[tuple[str, dict]]: + ''' + Iterate entries of a ``clears: dict`` table sorted by entry recorded + datetime presumably set at the ``'dt'`` field in each entry. + + ''' + for tid, data in sorted( + list(clears.items()), + key=lambda item: item[1]['dt'], + ): + yield tid, data + + class Position(Struct): ''' Basic pp (personal/piker position) model with attached clearing @@ -183,12 +199,7 @@ class Position(Struct): toml_clears_list = [] # reverse sort so latest clears are at top of section? - for tid, data in sorted( - list(clears.items()), - - # sort by datetime - key=lambda item: item[1]['dt'], - ): + for tid, data in iter_by_dt(clears): inline_table = toml.TomlDecoder().get_empty_inline_table() # serialize datetime to parsable `str` @@ -301,6 +312,14 @@ class Position(Struct): # def lifo_price() -> float: # ... + def iter_clears(self) -> Iterator[tuple[str, dict]]: + ''' + Iterate the internally managed ``.clears: dict`` table in + datetime-stamped order. + + ''' + return iter_by_dt(self.clears) + def calc_ppu( self, # include transaction cost in breakeven price @@ -331,10 +350,9 @@ class Position(Struct): asize_h: list[float] = [] # historical accumulative size ppu_h: list[float] = [] # historical price-per-unit - clears = list(self.clears.items()) - - for i, (tid, entry) in enumerate(clears): - + tid: str + entry: dict[str, Any] + for (tid, entry) in self.iter_clears(): clear_size = entry['size'] clear_price = entry['price'] @@ -344,6 +362,11 @@ class Position(Struct): sign_change: bool = False + if accum_size == 0: + ppu_h.append(0) + asize_h.append(0) + continue + if accum_size == 0: ppu_h.append(0) asize_h.append(0)