Add proper x-axis time-stamping

bar_select
Tyler Goodlet 2020-08-31 17:18:02 -04:00
parent ea2a675adf
commit 17d205f773
1 changed files with 52 additions and 42 deletions

View File

@ -1,12 +1,17 @@
"""
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
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QPointF
# from .quantdom.base import Quotes
from .quantdom.utils import fromtimestamp
from ._style import _font, hcolor
@ -15,7 +20,6 @@ class PriceAxis(pg.AxisItem):
def __init__(
self,
# chart: 'ChartPlotWidget',
) -> None:
super().__init__(orientation='right')
self.setStyle(**{
@ -28,10 +32,7 @@ class PriceAxis(pg.AxisItem):
})
self.setLabel(**{'font-size': '10pt'})
self.setTickFont(_font)
self.setWidth(150)
# self.chart = chart
# accesed normally via
# .getAxis('right')
self.setWidth(125)
# XXX: drop for now since it just eats up h space
@ -43,9 +44,20 @@ class PriceAxis(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)
self.linked_charts = linked_charts
self.setTickFont(_font)
@ -59,24 +71,25 @@ class DynamicDateAxis(pg.AxisItem):
)
# self.setHeight(35)
def tickStrings(self, values, scale, spacing):
# if len(values) > 1 or not values:
# values = Quotes.time
# strings = super().tickStrings(values, scale, spacing)
s_period = 'D1'
strings = []
def _indexes_to_timestrs(
self,
indexes: List[int],
) -> List[str]:
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:
if ibar > quotes_count:
return strings
dt_tick = fromtimestamp(bars[int(ibar)]['time'])
strings.append(
dt_tick.strftime(self.tick_tpl[s_period])
)
return strings
epochs = times[list(
map(int, filter(lambda i: i < bars_len, indexes))
)]
# TODO: **don't** have this hard coded shift to EST
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)
class AxisLabel(pg.GraphicsObject):
@ -88,7 +101,7 @@ class AxisLabel(pg.GraphicsObject):
def __init__(
self,
parent=None,
digits=1,
digits=2,
color=None,
opacity=1,
**kwargs
@ -128,6 +141,7 @@ class AxisLabel(pg.GraphicsObject):
p.drawText(option.rect, self.text_flags, self.label_str)
# uggggghhhh
def tick_to_string(self, tick_pos):
raise NotImplementedError()
@ -160,24 +174,20 @@ class XAxisLabel(AxisLabel):
)
# 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
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):
# ibar = view_pos.x()
# if ibar > self.quotes_count:
# return
self.label_str = self.tick_to_string(data)
def update_label(
self,
abs_pos: QPointF, # scene coords
data: float, # data for text
offset: int = 0 # if have margins, k?
) -> None:
self.label_str = self.parent._indexes_to_timestrs([int(data)])[0]
width = self.boundingRect().width()
offset = 0 # if have margins
new_pos = QPointF(abs_pos.x() - width / 2 - offset, 0)
self.setPos(new_pos)
@ -202,10 +212,10 @@ class YAxisLabel(AxisLabel):
self,
abs_pos: QPointF, # scene coords
data: float, # data for text
offset: int = 0 # if have margins, k?
) -> None:
self.label_str = self.tick_to_string(data)
height = self.boundingRect().height()
offset = 0 # if have margins
new_pos = QPointF(0, abs_pos.y() - height / 2 - offset)
self.setPos(new_pos)