diff --git a/piker/accounting/__init__.py b/piker/accounting/__init__.py index 4c4a0ca1..778bdd4e 100644 --- a/piker/accounting/__init__.py +++ b/piker/accounting/__init__.py @@ -38,23 +38,33 @@ from ._mktinfo import ( dec_digits, digits_to_dec, MktPair, + Symbol, unpack_fqme, ) +from ._allocate import ( + mk_allocator, + Allocator, +) log = get_logger(__name__) __all__ = [ + 'Allocator', 'Asset', - 'dec_digits', - 'digits_to_dec', 'MktPair', 'Position', 'PpTable', + 'Symbol', 'Transaction', 'TransactionLedger', + 'dec_digits', + 'digits_to_dec', + 'iter_by_dt', 'load_pps_from_ledger', + 'mk_allocator', 'open_pps', 'open_trade_ledger', + 'unpack_fqme', ] diff --git a/piker/accounting/_allocate.py b/piker/accounting/_allocate.py index 18900c9f..b4345785 100644 --- a/piker/accounting/_allocate.py +++ b/piker/accounting/_allocate.py @@ -24,7 +24,7 @@ from typing import Optional from bidict import bidict from ._pos import Position -from ._mktinfo import Symbol +from . import MktPair from ..data.types import Struct @@ -42,7 +42,7 @@ SizeUnit = Enum( class Allocator(Struct): - symbol: Symbol + mkt: MktPair # TODO: if we ever want ot support non-uniform entry-slot-proportion # "sizes" @@ -114,8 +114,8 @@ class Allocator(Struct): depending on position / order entry config. ''' - sym = self.symbol - ld = sym.lot_size_digits + mkt: MktPair = self.mkt + ld: int = mkt.size_tick_digits size_unit = self.size_unit live_size = live_pp.size @@ -125,13 +125,13 @@ class Allocator(Struct): u_per_slot, currency_per_slot = self.step_sizes() if size_unit == 'units': - slot_size = u_per_slot - l_sub_pp = self.units_limit - abs_live_size + slot_size: float = u_per_slot + l_sub_pp: float = self.units_limit - abs_live_size elif size_unit == 'currency': - live_cost_basis = abs_live_size * live_pp.ppu - slot_size = currency_per_slot / price - l_sub_pp = (self.currency_limit - live_cost_basis) / price + live_cost_basis: float = abs_live_size * live_pp.ppu + slot_size: float = currency_per_slot / price + l_sub_pp: float = (self.currency_limit - live_cost_basis) / price else: raise ValueError( @@ -141,8 +141,14 @@ class Allocator(Struct): # an entry (adding-to or starting a pp) if ( live_size == 0 - or (action == 'buy' and live_size > 0) - or action == 'sell' and live_size < 0 + or ( + action == 'buy' + and live_size > 0 + ) + or ( + action == 'sell' + and live_size < 0 + ) ): order_size = min( slot_size, @@ -178,7 +184,7 @@ class Allocator(Struct): order_size = max(slotted_pp, slot_size) if ( - abs_live_size < slot_size or + abs_live_size < slot_size # NOTE: front/back "loading" heurstic: # if the remaining pp is in between 0-1.5x a slot's @@ -187,14 +193,17 @@ class Allocator(Struct): # **without** going past a net-zero pp. if the pp is # > 1.5x a slot size, then front load: exit a slot's and # expect net-zero to be acquired on the final exit. - slot_size < pp_size < round((1.5*slot_size), ndigits=ld) or + or slot_size < pp_size < round((1.5*slot_size), ndigits=ld) + or ( - # underlying requires discrete (int) units (eg. stocks) - # and thus our slot size (based on our limit) would - # exit a fractional unit's worth so, presuming we aren't - # supporting a fractional-units-style broker, we need - # exit the final unit. - ld == 0 and abs_live_size == 1 + # underlying requires discrete (int) units (eg. stocks) + # and thus our slot size (based on our limit) would + # exit a fractional unit's worth so, presuming we aren't + # supporting a fractional-units-style broker, we need + # exit the final unit. + ld == 0 + and abs_live_size == 1 + ) ): order_size = abs_live_size @@ -203,13 +212,14 @@ class Allocator(Struct): # compute a fractional slots size to display slots_used = self.slots_used( Position( - mkt=sym, + mkt=mkt, size=order_size, ppu=price, - bs_mktid=sym, + bs_mktid=mkt.bs_mktid, ) ) + # TODO: render an actual ``Executable`` type here? return { 'size': abs(round(order_size, ndigits=ld)), 'size_digits': ld, @@ -249,7 +259,7 @@ class Allocator(Struct): def mk_allocator( - symbol: Symbol, + mkt: MktPair, startup_pp: Position, # default allocation settings @@ -276,6 +286,6 @@ def mk_allocator( defaults.update(user_def) return Allocator( - symbol=symbol, + mkt=mkt, **defaults, ) diff --git a/piker/accounting/_ledger.py b/piker/accounting/_ledger.py index 23845fde..5107f2bb 100644 --- a/piker/accounting/_ledger.py +++ b/piker/accounting/_ledger.py @@ -22,9 +22,9 @@ from __future__ import annotations from collections import UserDict from contextlib import contextmanager as cm from pathlib import Path -import time from typing import ( Any, + Callable, Iterator, Union, Generator @@ -158,7 +158,7 @@ class TransactionLedger(UserDict): for tid, txdict in self.data.items(): # special field handling for datetimes # to ensure pendulum is used! - fqme = txdict.get('fqme', txdict['fqsn']) + fqme = txdict.get('fqme') or txdict['fqsn'] dt = parse(txdict['dt']) expiry = txdict.get('expiry') @@ -242,8 +242,6 @@ def iter_by_dt( datetime presumably set at the ``'dt'`` field in each entry. ''' - txs = records.items() - def dyn_parse_to_dt( pair: tuple[str, dict], ) -> DateTime: diff --git a/piker/accounting/_mktinfo.py b/piker/accounting/_mktinfo.py index 653c8d04..046195ca 100644 --- a/piker/accounting/_mktinfo.py +++ b/piker/accounting/_mktinfo.py @@ -519,11 +519,11 @@ class MktPair(Struct, frozen=True): return self._atype @property - def tick_size_digits(self) -> int: + def price_tick_digits(self) -> int: return float_digits(self.price_tick) @property - def lot_size_digits(self) -> int: + def size_tick_digits(self) -> int: return float_digits(self.size_tick) diff --git a/piker/accounting/_pos.py b/piker/accounting/_pos.py index dda39177..3af0eeef 100644 --- a/piker/accounting/_pos.py +++ b/piker/accounting/_pos.py @@ -44,7 +44,6 @@ from ._ledger import ( open_trade_ledger, ) from ._mktinfo import ( - Symbol, MktPair, Asset, unpack_fqme, @@ -247,11 +246,8 @@ class Position(Struct): # XXX: better place to do this? mkt = self.mkt - - # TODO: switch to new fields..? - # .size_tick_digits, .price_tick_digits - size_tick_digits = mkt.lot_size_digits - price_tick_digits = mkt.tick_size_digits + size_tick_digits = mkt.size_tick_digits + price_tick_digits = mkt.price_tick_digits self.ppu = round( # TODO: change this to ppu?