Add proper x-axis time-stamping
parent
ea2a675adf
commit
17d205f773
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue