Copy non-base dtype fields on bar increment
							parent
							
								
									80f191c57d
								
							
						
					
					
						commit
						da2325239c
					
				|  | @ -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) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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)]) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue