Fix incorrect bounding rect calc

basic_orders
Tyler Goodlet 2021-02-21 12:02:20 -05:00
parent 4b0e5662a5
commit f724798336
1 changed files with 39 additions and 17 deletions

View File

@ -21,7 +21,7 @@ from typing import List, Optional, Tuple
import numpy as np import numpy as np
import pyqtgraph as pg import pyqtgraph as pg
from numba import jit, float64, int64 # , optional from numba import njit, float64, int64 # , optional
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QLineF, QPointF from PyQt5.QtCore import QLineF, QPointF
# from numba import types as ntypes # from numba import types as ntypes
@ -46,10 +46,20 @@ def _mk_lines_array(
) )
def lines_from_ohlc(row: np.ndarray, w: float) -> Tuple[QLineF]: def lines_from_ohlc(
row: np.ndarray,
w: float
) -> Tuple[QLineF]:
open, high, low, close, index = row[ open, high, low, close, index = row[
['open', 'high', 'low', 'close', 'index']] ['open', 'high', 'low', 'close', 'index']]
# TODO: maybe consider using `QGraphicsLineItem` ??
# gives us a ``.boundingRect()`` on the objects which may make
# computing the composite bounding rect of the last bars + the
# history path faster since it's done in C++:
# https://doc.qt.io/qt-5/qgraphicslineitem.html
# high -> low vertical (body) line # high -> low vertical (body) line
if low != high: if low != high:
hl = QLineF(index, low, index, high) hl = QLineF(index, low, index, high)
@ -60,17 +70,18 @@ def lines_from_ohlc(row: np.ndarray, w: float) -> Tuple[QLineF]:
# NOTE: place the x-coord start as "middle" of the drawing range such # NOTE: place the x-coord start as "middle" of the drawing range such
# that the open arm line-graphic is at the left-most-side of # that the open arm line-graphic is at the left-most-side of
# the index's range according to the view mapping. # the index's range according to the view mapping coordinates.
# open line # open line
o = QLineF(index - w, open, index, open) o = QLineF(index - w, open, index, open)
# close line # close line
c = QLineF(index, close, index + w, close) c = QLineF(index, close, index + w, close)
return [hl, o, c] return [hl, o, c]
@jit( @njit(
# TODO: for now need to construct this manually for readonly arrays, see # TODO: for now need to construct this manually for readonly arrays, see
# https://github.com/numba/numba/issues/4511 # https://github.com/numba/numba/issues/4511
# ntypes.Tuple((float64[:], float64[:], float64[:]))( # ntypes.Tuple((float64[:], float64[:], float64[:]))(
@ -78,7 +89,6 @@ def lines_from_ohlc(row: np.ndarray, w: float) -> Tuple[QLineF]:
# int64, # int64,
# optional(float64), # optional(float64),
# ), # ),
nopython=True,
nogil=True nogil=True
) )
def path_arrays_from_ohlc( def path_arrays_from_ohlc(
@ -177,7 +187,7 @@ class BarItems(pg.GraphicsObject):
# XXX: for the mega-lulz increasing width here increases draw latency... # XXX: for the mega-lulz increasing width here increases draw latency...
# so probably don't do it until we figure that out. # so probably don't do it until we figure that out.
self.bars_pen = pg.mkPen(hcolor(pen_color)) self.bars_pen = pg.mkPen(hcolor(pen_color), width=1)
# NOTE: this prevents redraws on mouse interaction which is # NOTE: this prevents redraws on mouse interaction which is
# a huge boon for avg interaction latency. # a huge boon for avg interaction latency.
@ -314,15 +324,17 @@ class BarItems(pg.GraphicsObject):
['index', 'open', 'high', 'low', 'close', 'volume'] ['index', 'open', 'high', 'low', 'close', 'volume']
] ]
# assert i == self.start_index - 1 # assert i == self.start_index - 1
assert i == last_index # assert i == last_index
body, larm, rarm = self._last_bar_lines body, larm, rarm = self._last_bar_lines
# XXX: is there a faster way to modify this? # XXX: is there a faster way to modify this?
rarm.setLine(rarm.x1(), last, rarm.x2(), last) rarm.setLine(rarm.x1(), last, rarm.x2(), last)
# writer is responsible for changing open on "first" volume of bar # writer is responsible for changing open on "first" volume of bar
larm.setLine(larm.x1(), o, larm.x2(), o) larm.setLine(larm.x1(), o, larm.x2(), o)
if l != h: # noqa if l != h: # noqa
if body is None: if body is None:
body = self._last_bar_lines[0] = QLineF(i, l, i, h) body = self._last_bar_lines[0] = QLineF(i, l, i, h)
else: else:
@ -383,19 +395,29 @@ class BarItems(pg.GraphicsObject):
# apparently this a lot faster says the docs? # apparently this a lot faster says the docs?
# https://doc.qt.io/qt-5/qpainterpath.html#controlPointRect # https://doc.qt.io/qt-5/qpainterpath.html#controlPointRect
hb = self.path.controlPointRect() hb = self.path.controlPointRect()
hb_size = hb.size() hb_tl, hb_br = hb.topLeft(), hb.bottomRight()
# print(f'hb_size: {hb_size}')
w = hb_size.width() + 1 # need to include last bar height or BR will be off
h = hb_size.height() + 1 mx_y = hb_br.y()
mn_y = hb_tl.y()
br = QtCore.QRectF( body_line = self._last_bar_lines[0]
if body_line:
mx_y = max(mx_y, max(body_line.y1(), body_line.y2()))
mn_y = min(mn_y, min(body_line.y1(), body_line.y2()))
return QtCore.QRectF(
# top left # top left
QPointF(hb.topLeft()), QPointF(
hb_tl.x(),
mn_y,
),
# bottom right
QPointF(
hb_br.x() + 1,
mx_y,
)
# total size
QtCore.QSizeF(w, h)
) )
# print(f'bounding rect: {br}')
return br