From 16b9e39e1168f8d2ba8368ace0919c2d1e9b5686 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Wed, 2 Mar 2022 09:20:17 -0500 Subject: [PATCH] Dis-allow an allocator limit less then the current pp size --- piker/clearing/_allocate.py | 21 +++++++++++++---- piker/ui/_position.py | 47 +++++++++++++++++++++++++++++-------- piker/ui/order_mode.py | 3 ++- 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/piker/clearing/_allocate.py b/piker/clearing/_allocate.py index 7b61a4bd..6ef38692 100644 --- a/piker/clearing/_allocate.py +++ b/piker/clearing/_allocate.py @@ -29,7 +29,8 @@ from ._messages import BrokerdPosition, Status class Position(BaseModel): - '''Basic pp (personal position) model with attached fills history. + ''' + Basic pp (personal position) model with attached fills history. This type should be IPC wire ready? @@ -61,6 +62,15 @@ class Position(BaseModel): self.avg_price = avg_price self.size = size + @property + def dsize(self) -> float: + ''' + The "dollar" size of the pp, normally in trading (fiat) unit + terms. + + ''' + return self.avg_price * self.size + _size_units = bidict({ 'currency': '$ size', @@ -114,7 +124,8 @@ class Allocator(BaseModel): def step_sizes( self, ) -> (float, float): - '''Return the units size for each unit type as a tuple. + ''' + Return the units size for each unit type as a tuple. ''' slots = self.slots @@ -142,7 +153,8 @@ class Allocator(BaseModel): action: str, ) -> dict: - '''Generate order request info for the "next" submittable order + ''' + Generate order request info for the "next" submittable order depending on position / order entry config. ''' @@ -250,7 +262,8 @@ class Allocator(BaseModel): pp: Position, ) -> float: - '''Calc and return the number of slots used by this ``Position``. + ''' + Calc and return the number of slots used by this ``Position``. ''' abs_pp_size = abs(pp.size) diff --git a/piker/ui/_position.py b/piker/ui/_position.py index e057154e..0abb6459 100644 --- a/piker/ui/_position.py +++ b/piker/ui/_position.py @@ -71,10 +71,10 @@ async def update_pnl_from_feed( log.info(f'Starting pnl display for {pp.alloc.account}') if live.size < 0: - types = ('ask', 'last', 'last', 'utrade') + types = ('ask', 'last', 'last', 'dark_trade') elif live.size > 0: - types = ('bid', 'last', 'last', 'utrade') + types = ('bid', 'last', 'last', 'dark_trade') else: log.info(f'No position (yet) for {tracker.alloc.account}@{key}') @@ -119,7 +119,8 @@ async def update_pnl_from_feed( @dataclass class SettingsPane: - '''Composite set of widgets plus an allocator model for configuring + ''' + Composite set of widgets plus an allocator model for configuring order entry sizes and position limits per tradable instrument. ''' @@ -151,7 +152,8 @@ class SettingsPane: key: str, ) -> None: - '''Called on any order pane drop down selection change. + ''' + Called on any order pane drop down selection change. ''' log.info(f'selection input {key}:{text}') @@ -164,7 +166,8 @@ class SettingsPane: value: str, ) -> bool: - '''Called on any order pane edit field value change. + ''' + Called on any order pane edit field value change. ''' mode = self.order_mode @@ -219,16 +222,36 @@ class SettingsPane: else: value = puterize(value) if key == 'limit': + pp = mode.current_pp.live_pp + if size_unit == 'currency': + dsize = pp.dsize + if dsize > value: + log.error( + f'limit must > then current pp: {dsize}' + ) + raise ValueError + alloc.currency_limit = value + else: + size = pp.size + if size > value: + log.error( + f'limit must > then current pp: {size}' + ) + raise ValueError + alloc.units_limit = value elif key == 'slots': + if value <= 0: + raise ValueError('slots must be > 0') alloc.slots = int(value) else: - raise ValueError(f'Unknown setting {key}') + log.error(f'Unknown setting {key}') + raise ValueError log.info(f'settings change: {key}: {value}') @@ -363,7 +386,8 @@ def position_line( marker: Optional[LevelMarker] = None, ) -> LevelLine: - '''Convenience routine to create a line graphic representing a "pp" + ''' + Convenience routine to create a line graphic representing a "pp" aka the acro for a, "{piker, private, personal, puny, } position". @@ -417,7 +441,8 @@ def position_line( class PositionTracker: - '''Track and display real-time positions for a single symbol + ''' + Track and display real-time positions for a single symbol over multiple accounts on a single chart. Graphically composed of a level line and marker as well as labels @@ -497,7 +522,8 @@ class PositionTracker: @property def pane(self) -> FieldsForm: - '''Return handle to pp side pane form. + ''' + Return handle to pp side pane form. ''' return self.chart.linked.godwidget.pp_pane @@ -507,7 +533,8 @@ class PositionTracker: marker: LevelMarker ) -> None: - '''Update all labels. + ''' + Update all labels. Meant to be called from the maker ``.paint()`` for immediate, lag free label draws. diff --git a/piker/ui/order_mode.py b/piker/ui/order_mode.py index 437e4ca5..9f4dbadb 100644 --- a/piker/ui/order_mode.py +++ b/piker/ui/order_mode.py @@ -107,7 +107,8 @@ def on_level_change_update_next_order_info( @dataclass class OrderMode: - '''Major UX mode for placing orders on a chart view providing so + ''' + Major UX mode for placing orders on a chart view providing so called, "chart trading". This is the other "main" mode that pairs with "view mode" (when