Snap y-axis crosshair to min tick(s)

basic_orders
Tyler Goodlet 2021-01-22 22:59:00 -05:00
parent 50d2d8517b
commit f072e2551b
2 changed files with 35 additions and 21 deletions

View File

@ -1,5 +1,5 @@
# piker: trading gear for hackers # piker: trading gear for hackers
# Copyright (C) 2018-present Tyler Goodlet (in stewardship of piker0) # Copyright (C) Tyler Goodlet (in stewardship for piker0)
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by # it under the terms of the GNU Affero General Public License as published by
@ -138,7 +138,10 @@ class ChartSpace(QtGui.QWidget):
Expects a ``numpy`` structured array containing all the ohlcv fields. Expects a ``numpy`` structured array containing all the ohlcv fields.
""" """
# XXX: let's see if this causes mem problems # XXX: let's see if this causes mem problems
self.window.setWindowTitle(f'piker chart {symbol}') self.window.setWindowTitle(
f'piker chart {symbol.key}@{symbol.brokers} '
f'tick:{symbol.min_tick}'
)
# TODO: symbol search # TODO: symbol search
# # of course this doesn't work :eyeroll: # # of course this doesn't work :eyeroll:
@ -192,6 +195,7 @@ class LinkedSplitCharts(QtGui.QWidget):
self._cursor: Cursor = None # crosshair graphics self._cursor: Cursor = None # crosshair graphics
self.chart: ChartPlotWidget = None # main (ohlc) chart self.chart: ChartPlotWidget = None # main (ohlc) chart
self.subplots: Dict[Tuple[str, ...], ChartPlotWidget] = {} self.subplots: Dict[Tuple[str, ...], ChartPlotWidget] = {}
self.digits: int = 2
self.xaxis = DynamicDateAxis( self.xaxis = DynamicDateAxis(
orientation='bottom', orientation='bottom',
@ -241,6 +245,7 @@ class LinkedSplitCharts(QtGui.QWidget):
The data input struct array must include OHLC fields. The data input struct array must include OHLC fields.
""" """
self.min_tick = symbol.min_tick
self.digits = symbol.digits() self.digits = symbol.digits()
# add crosshairs # add crosshairs
@ -652,7 +657,7 @@ class ChartPlotWidget(pg.PlotWidget):
chart=self, chart=self,
parent=self.getAxis('right'), parent=self.getAxis('right'),
# TODO: pass this from symbol data # TODO: pass this from symbol data
# digits=0, digits=self._lc._symbol.digits(),
opacity=1, opacity=1,
bg_color=bg_color, bg_color=bg_color,
) )
@ -854,8 +859,6 @@ async def _async_main(
# historical data fetch # historical data fetch
brokermod = brokers.get_brokermod(brokername) brokermod = brokers.get_brokermod(brokername)
symbol = Symbol(sym, [brokername])
async with data.open_feed( async with data.open_feed(
brokername, brokername,
[sym], [sym],
@ -864,6 +867,7 @@ async def _async_main(
ohlcv = feed.shm ohlcv = feed.shm
bars = ohlcv.array bars = ohlcv.array
symbol = feed.symbols[sym]
# load in symbol's ohlc data # load in symbol's ohlc data
linked_charts, chart = chart_app.load_symbol(symbol, bars) linked_charts, chart = chart_app.load_symbol(symbol, bars)

View File

@ -1,5 +1,5 @@
# piker: trading gear for hackers # piker: trading gear for hackers
# Copyright (C) 2018-present Tyler Goodlet (in stewardship of piker0) # Copyright (C) Tyler Goodlet (in stewardship for piker0)
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by # it under the terms of the GNU Affero General Public License as published by
@ -226,6 +226,10 @@ class Cursor(pg.GraphicsObject):
self._hovered: Set[pg.GraphicsObject] = set() self._hovered: Set[pg.GraphicsObject] = set()
self._trackers: Set[pg.GraphicsObject] = set() self._trackers: Set[pg.GraphicsObject] = set()
# value used for rounding y-axis discreet tick steps
# computing once, up front, here cuz why not
self._y_incr_mult = 1 / self.lsc._symbol.min_tick
def add_hovered( def add_hovered(
self, self,
item: pg.GraphicsObject, item: pg.GraphicsObject,
@ -347,25 +351,31 @@ class Cursor(pg.GraphicsObject):
x, y = mouse_point.x(), mouse_point.y() x, y = mouse_point.x(), mouse_point.y()
plot = self.active_plot plot = self.active_plot
# update y-range items
self.graphics[plot]['hl'].setY(y)
self.graphics[self.active_plot]['yl'].update_label(
abs_pos=pos, value=y
)
# Update x if cursor changed after discretization calc # Update x if cursor changed after discretization calc
# (this saves draw cycles on small mouse moves) # (this saves draw cycles on small mouse moves)
lastx, lasty = self._datum_xy last_ix, last_iy = self._datum_xy
ix = round(x) # since bars are centered around index ix = round(x) # since bars are centered around index
# round y value to nearest tick step
m = self._y_incr_mult
iy = round(y * m) / m
if iy != last_iy:
# update y-range items
self.graphics[plot]['hl'].setY(iy)
self.graphics[self.active_plot]['yl'].update_label(
abs_pos=pos, value=iy
)
# update all trackers # update all trackers
for item in self._trackers: for item in self._trackers:
# print(f'setting {item} with {(ix, y)}') # print(f'setting {item} with {(ix, y)}')
item.on_tracked_source(ix, y) item.on_tracked_source(ix, iy)
if ix != lastx: if ix != last_ix:
for plot, opts in self.graphics.items(): for plot, opts in self.graphics.items():
# move the vertical line to the current "center of bar" # move the vertical line to the current "center of bar"
@ -390,7 +400,7 @@ class Cursor(pg.GraphicsObject):
value=x, value=x,
) )
self._datum_xy = ix, y self._datum_xy = ix, iy
def boundingRect(self): def boundingRect(self):
try: try: