diff --git a/piker/ui/_axes.py b/piker/ui/_axes.py index 46f64b5d..24389f77 100644 --- a/piker/ui/_axes.py +++ b/piker/ui/_axes.py @@ -1,8 +1,6 @@ """ Chart axes graphics and behavior. """ -import time -from functools import partial from typing import List @@ -12,7 +10,6 @@ import pyqtgraph as pg from PyQt5 import QtCore, QtGui from PyQt5.QtCore import QPointF -from .quantdom.utils import fromtimestamp from ._style import _font, hcolor @@ -78,7 +75,8 @@ class DynamicDateAxis(pg.AxisItem): bars = self.linked_charts.chart._array times = bars['time'] bars_len = len(bars) - delay = times[-1] - times[times != times[-1]][-1] + # delay = times[-1] - times[times != times[-1]][-1] + delay = times[-1] - times[-2] epochs = times[list( map(int, filter(lambda i: i < bars_len, indexes)) @@ -87,7 +85,6 @@ class DynamicDateAxis(pg.AxisItem): dts = pd.to_datetime(epochs, unit='s') - 4*pd.offsets.Hour() return dts.strftime(self.tick_tpl[delay]) - def tickStrings(self, values: List[float], scale, spacing): return self._indexes_to_timestrs(values) diff --git a/piker/ui/_chart.py b/piker/ui/_chart.py index dd100fb9..13071f1a 100644 --- a/piker/ui/_chart.py +++ b/piker/ui/_chart.py @@ -22,7 +22,7 @@ from .. import brokers from .. import data from ..log import get_logger from ._exec import run_qtractor -from ._source import ohlc_dtype +from ._source import base_ohlc_dtype from ._interaction import ChartView from .. import fsp @@ -507,13 +507,13 @@ class ChartPlotWidget(pg.PlotWidget): # TODO: should probably just have some kinda attr mark # that determines this behavior based on array type try: - ylow = bars['low'].min() - yhigh = bars['high'].max() + ylow = np.nanmin(bars['low']) + yhigh = np.nanmax(bars['high']) # std = np.std(bars['close']) except IndexError: # must be non-ohlc array? - ylow = bars.min() - yhigh = bars.max() + ylow = np.nanmin(bars) + yhigh = np.nanmax(bars) # std = np.std(bars) # view margins: stay within 10% of the "true range" @@ -589,14 +589,13 @@ async def add_new_bars(delay_s, linked_charts): def incr_ohlc_array(array: np.ndarray): (index, t, close) = array[-1][['index', 'time', 'close']] - new_array = np.append( - array, - np.array( - [(index + 1, t + delay_s, close, close, - close, close, 0)], - dtype=array.dtype - ), - ) + + # this copies non-std fields (eg. vwap) from the last datum + _next = np.array(array[-1], dtype=array.dtype) + _next[ + ['index', 'time', 'volume', 'open', 'high', 'low', 'close'] + ] = (index + 1, t + delay_s, 0, close, close, close, close) + new_array = np.append(array, _next,) return new_array # add new increment/bar @@ -668,6 +667,9 @@ async def _async_main( # figure out the exact symbol bars = await client.bars(symbol=sym) + # allow broker to declare historical data fields + ohlc_dtype = getattr(brokermod, 'ohlc_dtype', base_ohlc_dtype) + # remember, msgpack-numpy's ``from_buffer` returns read-only array bars = np.array(bars[list(ohlc_dtype.names)]) diff --git a/piker/ui/_source.py b/piker/ui/_source.py index 0224538b..b8816636 100644 --- a/piker/ui/_source.py +++ b/piker/ui/_source.py @@ -8,7 +8,7 @@ import numpy as np import pandas as pd -ohlc_dtype = np.dtype( +base_ohlc_dtype = np.dtype( [ ('index', int), ('time', float), @@ -38,7 +38,7 @@ def ohlc_zeros(length: int) -> np.ndarray: For "why a structarray" see here: https://stackoverflow.com/a/52443038 Bottom line, they're faster then ``np.recarray``. """ - return np.zeros(length, dtype=ohlc_dtype) + return np.zeros(length, dtype=base_ohlc_dtype) @dataclass @@ -88,7 +88,7 @@ def from_df( df = df.rename(columns=columns) for name in df.columns: - if name not in ohlc_dtype.names[1:]: + if name not in base_ohlc_dtype.names[1:]: del df[name] # TODO: it turns out column access on recarrays is actually slower: