diff --git a/piker/data/_source.py b/piker/data/_source.py index bcfc6025..5eb210fe 100644 --- a/piker/data/_source.py +++ b/piker/data/_source.py @@ -62,6 +62,9 @@ tf_in_1m = { def float_digits( value: float, ) -> int: + if value == 0: + return 0 + return int(-decimal.Decimal(str(value)).as_tuple().exponent) @@ -82,28 +85,20 @@ class Symbol(BaseModel): Yah, i guess dats what it izz. """ key: str - tick_size: float = 0.01 - lot_tick_size: float = 0.01 # "volume" precision as min step value + type_key: str # {'stock', 'forex', 'future', ... etc.} + tick_size: float + lot_tick_size: float # "volume" precision as min step value + tick_size_digits: int + lot_size_digits: int broker_info: Dict[str, Dict[str, Any]] = {} # specifies a "class" of financial instrument # ex. stock, futer, option, bond etc. - type_key: str @property def brokers(self) -> List[str]: return list(self.broker_info.keys()) - def digits(self) -> int: - """Return the trailing number of digits specified by the min - tick size for the instrument. - - """ - return float_digits(self.tick_size) - - def lot_digits(self) -> int: - return float_digits(self.lot_tick_size) - def nearest_tick(self, value: float) -> float: """Return the nearest tick value based on mininum increment. @@ -112,6 +107,30 @@ class Symbol(BaseModel): return round(value * mult) / mult +def mk_symbol( + + key: str, + type_key: str, + tick_size: float = 0.01, + lot_tick_size: float = 0, + broker_info: dict[str, Any] = {}, + +) -> Symbol: + '''Create and return an instrument description for the + "symbol" named as ``key``. + + ''' + return Symbol( + key=key, + type_key=type_key, + tick_size=tick_size, + lot_tick_size=lot_tick_size, + tick_size_digits=float_digits(tick_size), + lot_size_digits=float_digits(lot_tick_size), + broker_info=broker_info, + ) + + def from_df( df: pd.DataFrame, source=None, diff --git a/piker/data/feed.py b/piker/data/feed.py index 72d3c50d..7b390ece 100644 --- a/piker/data/feed.py +++ b/piker/data/feed.py @@ -49,7 +49,7 @@ from ._sharedmem import ( ShmArray, ) from .ingest import get_ingestormod -from ._source import base_iohlc_dtype, Symbol +from ._source import base_iohlc_dtype, mk_symbol, Symbol from ..ui import _search from ._sampling import ( _shms, @@ -535,7 +535,7 @@ async def open_feed( si = data['symbol_info'] ohlc_sample_rates.append(data['sample_rate']) - symbol = Symbol( + symbol = mk_symbol( key=sym, type_key=si.get('asset_type', 'forex'), tick_size=si.get('price_tick_size', 0.01), diff --git a/piker/ui/_chart.py b/piker/ui/_chart.py index 5ba6ff82..5a1f8f9b 100644 --- a/piker/ui/_chart.py +++ b/piker/ui/_chart.py @@ -371,7 +371,7 @@ class LinkedSplits(QWidget): # add crosshairs self.cursor = Cursor( linkedsplits=self, - digits=symbol.digits(), + digits=symbol.tick_size_digits, ) self.chart = self.add_plot( @@ -882,7 +882,7 @@ class ChartPlotWidget(pg.PlotWidget): # use the tick size precision for display sym = self.linked.symbol if name == sym.key: - digits = sym.digits() + digits = sym.tick_size_digits else: digits = 2 @@ -1144,8 +1144,8 @@ async def chart_from_quotes( l1 = L1Labels( chart, # determine precision/decimal lengths - digits=symbol.digits(), - size_digits=symbol.lot_digits(), + digits=symbol.tick_size_digits, + size_digits=symbol.lot_size_digits, ) chart._l1_labels = l1 diff --git a/piker/ui/_position.py b/piker/ui/_position.py index c5806c23..be851b1a 100644 --- a/piker/ui/_position.py +++ b/piker/ui/_position.py @@ -169,7 +169,7 @@ def mk_alloc( ''' tracker = self._position pp_size = tracker.live_pp.size - ld = symbol.lot_digits() + ld = symbol.lot_size_digits if ( action == 'buy' and pp_size > 0 or @@ -289,7 +289,7 @@ class PositionTracker: ) pp_label.render() - nsize = self.chart.linked.symbol.lot_digits() + nsize = self.chart.linked.symbol.lot_size_digits self.size_label = size_label = Label( view=view, diff --git a/piker/ui/order_mode.py b/piker/ui/order_mode.py index 310ccd10..0ccbb33d 100644 --- a/piker/ui/order_mode.py +++ b/piker/ui/order_mode.py @@ -116,12 +116,9 @@ class OrderMode: # TODO: convert these values into human-readable form # (i.e. with k, m, M, B) type embedded suffixes level=order.price, - # level_digits=symbol.digits(), action=order.action, size=order.size, - # TODO: we need truncation checks in the EMS for this? - # size_digits=min(symbol.lot_digits(), 3), color=self._colors[order.action], dotted=True if (