Add proper x-axis time-stamping

its_happening
Tyler Goodlet 2020-08-31 17:18:02 -04:00
parent 30d8e096c6
commit 0f6589d9ff
1 changed files with 52 additions and 42 deletions

View File

@ -1,12 +1,17 @@
""" """
Chart axes graphics and behavior. Chart axes graphics and behavior.
""" """
import time
from functools import partial
from typing import List
# import numpy as np
import pandas as pd
import pyqtgraph as pg import pyqtgraph as pg
from PyQt5 import QtCore, QtGui from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QPointF from PyQt5.QtCore import QPointF
# from .quantdom.base import Quotes
from .quantdom.utils import fromtimestamp from .quantdom.utils import fromtimestamp
from ._style import _font, hcolor from ._style import _font, hcolor
@ -15,7 +20,6 @@ class PriceAxis(pg.AxisItem):
def __init__( def __init__(
self, self,
# chart: 'ChartPlotWidget',
) -> None: ) -> None:
super().__init__(orientation='right') super().__init__(orientation='right')
self.setStyle(**{ self.setStyle(**{
@ -28,10 +32,7 @@ class PriceAxis(pg.AxisItem):
}) })
self.setLabel(**{'font-size': '10pt'}) self.setLabel(**{'font-size': '10pt'})
self.setTickFont(_font) self.setTickFont(_font)
self.setWidth(150) self.setWidth(125)
# self.chart = chart
# accesed normally via
# .getAxis('right')
# XXX: drop for now since it just eats up h space # XXX: drop for now since it just eats up h space
@ -43,9 +44,20 @@ class PriceAxis(pg.AxisItem):
class DynamicDateAxis(pg.AxisItem): class DynamicDateAxis(pg.AxisItem):
tick_tpl = {'D1': '%Y-%b-%d'} # time formats mapped by seconds between bars
tick_tpl = {
60*60*24: '%Y-%b-%d',
60: '%H:%M',
30: '%H:%M:%S',
5: '%H:%M:%S',
}
def __init__(self, linked_charts, *args, **kwargs): def __init__(
self,
linked_charts,
*args,
**kwargs
) -> None:
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.linked_charts = linked_charts self.linked_charts = linked_charts
self.setTickFont(_font) self.setTickFont(_font)
@ -59,24 +71,25 @@ class DynamicDateAxis(pg.AxisItem):
) )
# self.setHeight(35) # self.setHeight(35)
def tickStrings(self, values, scale, spacing): def _indexes_to_timestrs(
# if len(values) > 1 or not values: self,
# values = Quotes.time indexes: List[int],
) -> List[str]:
# strings = super().tickStrings(values, scale, spacing)
s_period = 'D1'
strings = []
bars = self.linked_charts.chart._array bars = self.linked_charts.chart._array
quotes_count = len(bars) - 1 times = bars['time']
bars_len = len(bars)
delay = times[-1] - times[times != times[-1]][-1]
for ibar in values: epochs = times[list(
if ibar > quotes_count: map(int, filter(lambda i: i < bars_len, indexes))
return strings )]
dt_tick = fromtimestamp(bars[int(ibar)]['time']) # TODO: **don't** have this hard coded shift to EST
strings.append( dts = pd.to_datetime(epochs, unit='s') - 4*pd.offsets.Hour()
dt_tick.strftime(self.tick_tpl[s_period]) return dts.strftime(self.tick_tpl[delay])
)
return strings
def tickStrings(self, values: List[float], scale, spacing):
return self._indexes_to_timestrs(values)
class AxisLabel(pg.GraphicsObject): class AxisLabel(pg.GraphicsObject):
@ -88,7 +101,7 @@ class AxisLabel(pg.GraphicsObject):
def __init__( def __init__(
self, self,
parent=None, parent=None,
digits=1, digits=2,
color=None, color=None,
opacity=1, opacity=1,
**kwargs **kwargs
@ -128,6 +141,7 @@ class AxisLabel(pg.GraphicsObject):
p.drawText(option.rect, self.text_flags, self.label_str) p.drawText(option.rect, self.text_flags, self.label_str)
# uggggghhhh # uggggghhhh
def tick_to_string(self, tick_pos): def tick_to_string(self, tick_pos):
raise NotImplementedError() raise NotImplementedError()
@ -160,24 +174,20 @@ class XAxisLabel(AxisLabel):
) )
# text_flags = _common_text_flags # text_flags = _common_text_flags
def tick_to_string(self, tick_pos):
# TODO: change to actual period
tpl = self.parent.tick_tpl['D1']
bars = self.parent.linked_charts.chart._array
if tick_pos > len(bars):
return 'Unknown Time'
return fromtimestamp(bars[round(tick_pos)]['time']).strftime(tpl)
def boundingRect(self): # noqa def boundingRect(self): # noqa
return QtCore.QRectF(0, 0, 145, 40) # TODO: we need to get the parent axe's dimensions transformed
# to abs coords to be 100% correct here:
# self.parent.boundingRect()
return QtCore.QRectF(0, 0, 100, 31)
def update_label(self, abs_pos, data): def update_label(
# ibar = view_pos.x() self,
# if ibar > self.quotes_count: abs_pos: QPointF, # scene coords
# return data: float, # data for text
self.label_str = self.tick_to_string(data) offset: int = 0 # if have margins, k?
) -> None:
self.label_str = self.parent._indexes_to_timestrs([int(data)])[0]
width = self.boundingRect().width() width = self.boundingRect().width()
offset = 0 # if have margins
new_pos = QPointF(abs_pos.x() - width / 2 - offset, 0) new_pos = QPointF(abs_pos.x() - width / 2 - offset, 0)
self.setPos(new_pos) self.setPos(new_pos)
@ -202,10 +212,10 @@ class YAxisLabel(AxisLabel):
self, self,
abs_pos: QPointF, # scene coords abs_pos: QPointF, # scene coords
data: float, # data for text data: float, # data for text
offset: int = 0 # if have margins, k?
) -> None: ) -> None:
self.label_str = self.tick_to_string(data) self.label_str = self.tick_to_string(data)
height = self.boundingRect().height() height = self.boundingRect().height()
offset = 0 # if have margins
new_pos = QPointF(0, abs_pos.y() - height / 2 - offset) new_pos = QPointF(0, abs_pos.y() - height / 2 - offset)
self.setPos(new_pos) self.setPos(new_pos)