[Mod] improve chart appearance
This commit is contained in:
parent
9fb8b1fc2b
commit
85e10ddb8a
@ -2,13 +2,8 @@ from typing import List
|
|||||||
|
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
|
|
||||||
from vnpy.trader.ui import QtGui
|
|
||||||
|
|
||||||
from .manager import BarManager
|
from .manager import BarManager
|
||||||
|
from .base import AXIS_WIDTH, NORMAL_FONT
|
||||||
|
|
||||||
AXIS_WIDTH = 0.8
|
|
||||||
AXIS_FONT = QtGui.QFont("Arial", 10, QtGui.QFont.Bold)
|
|
||||||
|
|
||||||
|
|
||||||
class DatetimeAxis(pg.AxisItem):
|
class DatetimeAxis(pg.AxisItem):
|
||||||
@ -21,7 +16,7 @@ class DatetimeAxis(pg.AxisItem):
|
|||||||
self._manager: BarManager = manager
|
self._manager: BarManager = manager
|
||||||
|
|
||||||
self.setPen(width=AXIS_WIDTH)
|
self.setPen(width=AXIS_WIDTH)
|
||||||
self.setStyle(tickFont=AXIS_FONT, autoExpandTextSpace=True)
|
self.tickFont = NORMAL_FONT
|
||||||
|
|
||||||
def tickStrings(self, values: List[int], scale: float, spacing: int):
|
def tickStrings(self, values: List[int], scale: float, spacing: int):
|
||||||
"""
|
"""
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
from vnpy.trader.ui import QtGui
|
||||||
|
|
||||||
|
|
||||||
WHITE_COLOR = (255, 255, 255)
|
WHITE_COLOR = (255, 255, 255)
|
||||||
BLACK_COLOR = (0, 0, 0)
|
BLACK_COLOR = (0, 0, 0)
|
||||||
GREY_COLOR = (100, 100, 100)
|
GREY_COLOR = (100, 100, 100)
|
||||||
@ -9,6 +12,9 @@ CURSOR_COLOR = (255, 245, 162)
|
|||||||
PEN_WIDTH = 1
|
PEN_WIDTH = 1
|
||||||
BAR_WIDTH = 0.4
|
BAR_WIDTH = 0.4
|
||||||
|
|
||||||
|
AXIS_WIDTH = 0.8
|
||||||
|
NORMAL_FONT = QtGui.QFont("Arial", 9)
|
||||||
|
|
||||||
|
|
||||||
def to_int(value: float) -> int:
|
def to_int(value: float) -> int:
|
||||||
""""""
|
""""""
|
||||||
|
@ -55,6 +55,13 @@ class ChartItem(pg.GraphicsObject):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_info_text(self, ix: int) -> str:
|
||||||
|
"""
|
||||||
|
Get information text to show by cursor.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def update_history(self, history: List[BarData]) -> BarData:
|
def update_history(self, history: List[BarData]) -> BarData:
|
||||||
"""
|
"""
|
||||||
Update a list of bar data.
|
Update a list of bar data.
|
||||||
@ -204,6 +211,38 @@ class CandleItem(ChartItem):
|
|||||||
min_price, max_price = self._manager.get_price_range(min_ix, max_ix)
|
min_price, max_price = self._manager.get_price_range(min_ix, max_ix)
|
||||||
return min_price, max_price
|
return min_price, max_price
|
||||||
|
|
||||||
|
def get_info_text(self, ix: int) -> str:
|
||||||
|
"""
|
||||||
|
Get information text to show by cursor.
|
||||||
|
"""
|
||||||
|
bar = self._manager.get_bar(ix)
|
||||||
|
|
||||||
|
if bar:
|
||||||
|
words = [
|
||||||
|
"Date",
|
||||||
|
bar.datetime.strftime("%Y-%m-%d"),
|
||||||
|
"",
|
||||||
|
"Time",
|
||||||
|
bar.datetime.strftime("%H:%M"),
|
||||||
|
"",
|
||||||
|
"Open",
|
||||||
|
str(bar.open_price),
|
||||||
|
"",
|
||||||
|
"High",
|
||||||
|
str(bar.high_price),
|
||||||
|
"",
|
||||||
|
"Low",
|
||||||
|
str(bar.low_price),
|
||||||
|
"",
|
||||||
|
"Close",
|
||||||
|
str(bar.close_price)
|
||||||
|
]
|
||||||
|
text = "\n".join(words)
|
||||||
|
else:
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
class VolumeItem(ChartItem):
|
class VolumeItem(ChartItem):
|
||||||
""""""
|
""""""
|
||||||
@ -258,3 +297,16 @@ class VolumeItem(ChartItem):
|
|||||||
"""
|
"""
|
||||||
min_volume, max_volume = self._manager.get_volume_range(min_ix, max_ix)
|
min_volume, max_volume = self._manager.get_volume_range(min_ix, max_ix)
|
||||||
return min_volume, max_volume
|
return min_volume, max_volume
|
||||||
|
|
||||||
|
def get_info_text(self, ix: int) -> str:
|
||||||
|
"""
|
||||||
|
Get information text to show by cursor.
|
||||||
|
"""
|
||||||
|
bar = self._manager.get_bar(ix)
|
||||||
|
|
||||||
|
if bar:
|
||||||
|
text = f"Volume {bar.volume}"
|
||||||
|
else:
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
return text
|
||||||
|
@ -6,8 +6,11 @@ from vnpy.trader.ui import QtGui, QtWidgets, QtCore
|
|||||||
from vnpy.trader.object import BarData
|
from vnpy.trader.object import BarData
|
||||||
|
|
||||||
from .manager import BarManager
|
from .manager import BarManager
|
||||||
from .base import GREY_COLOR, WHITE_COLOR, CURSOR_COLOR, BLACK_COLOR, to_int
|
from .base import (
|
||||||
from .axis import DatetimeAxis, AXIS_FONT
|
GREY_COLOR, WHITE_COLOR, CURSOR_COLOR, BLACK_COLOR,
|
||||||
|
to_int, NORMAL_FONT
|
||||||
|
)
|
||||||
|
from .axis import DatetimeAxis
|
||||||
from .item import ChartItem
|
from .item import ChartItem
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +52,8 @@ class ChartWidget(pg.PlotWidget):
|
|||||||
def add_cursor(self) -> None:
|
def add_cursor(self) -> None:
|
||||||
""""""
|
""""""
|
||||||
if not self._cursor:
|
if not self._cursor:
|
||||||
self._cursor = ChartCursor(self, self._manager, self._plots)
|
self._cursor = ChartCursor(
|
||||||
|
self, self._manager, self._plots, self._item_plot_map)
|
||||||
|
|
||||||
def add_plot(
|
def add_plot(
|
||||||
self,
|
self,
|
||||||
@ -89,7 +93,7 @@ class ChartWidget(pg.PlotWidget):
|
|||||||
# Set right axis
|
# Set right axis
|
||||||
right_axis = plot.getAxis('right')
|
right_axis = plot.getAxis('right')
|
||||||
right_axis.setWidth(60)
|
right_axis.setWidth(60)
|
||||||
right_axis.setStyle(tickFont=AXIS_FONT)
|
right_axis.tickFont = NORMAL_FONT
|
||||||
|
|
||||||
# Connect x-axis link
|
# Connect x-axis link
|
||||||
if self._plots:
|
if self._plots:
|
||||||
@ -294,7 +298,8 @@ class ChartCursor(QtCore.QObject):
|
|||||||
self,
|
self,
|
||||||
widget: ChartWidget,
|
widget: ChartWidget,
|
||||||
manager: BarManager,
|
manager: BarManager,
|
||||||
plots: Dict[str, pg.GraphicsObject]
|
plots: Dict[str, pg.GraphicsObject],
|
||||||
|
item_plot_map: Dict[ChartItem, pg.GraphicsObject]
|
||||||
):
|
):
|
||||||
""""""
|
""""""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -302,6 +307,7 @@ class ChartCursor(QtCore.QObject):
|
|||||||
self._widget: ChartWidget = widget
|
self._widget: ChartWidget = widget
|
||||||
self._manager: BarManager = manager
|
self._manager: BarManager = manager
|
||||||
self._plots: Dict[str, pg.GraphicsObject] = plots
|
self._plots: Dict[str, pg.GraphicsObject] = plots
|
||||||
|
self._item_plot_map: Dict[ChartItem, pg.GraphicsObject] = item_plot_map
|
||||||
|
|
||||||
self._x: int = 0
|
self._x: int = 0
|
||||||
self._y: int = 0
|
self._y: int = 0
|
||||||
@ -346,9 +352,11 @@ class ChartCursor(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
self._y_labels: Dict[str, pg.TextItem] = {}
|
self._y_labels: Dict[str, pg.TextItem] = {}
|
||||||
for plot_name, plot in self._plots.items():
|
for plot_name, plot in self._plots.items():
|
||||||
label = pg.TextItem(plot_name, fill=CURSOR_COLOR, color=BLACK_COLOR)
|
label = pg.TextItem(
|
||||||
|
plot_name, fill=CURSOR_COLOR, color=BLACK_COLOR)
|
||||||
label.hide()
|
label.hide()
|
||||||
label.setZValue(2)
|
label.setZValue(2)
|
||||||
|
label.setFont(NORMAL_FONT)
|
||||||
plot.addItem(label, ignoreBounds=True)
|
plot.addItem(label, ignoreBounds=True)
|
||||||
self._y_labels[plot_name] = label
|
self._y_labels[plot_name] = label
|
||||||
|
|
||||||
@ -356,17 +364,25 @@ class ChartCursor(QtCore.QObject):
|
|||||||
"datetime", fill=CURSOR_COLOR, color=BLACK_COLOR)
|
"datetime", fill=CURSOR_COLOR, color=BLACK_COLOR)
|
||||||
self._x_label.hide()
|
self._x_label.hide()
|
||||||
self._x_label.setZValue(2)
|
self._x_label.setZValue(2)
|
||||||
|
self._x_label.setFont(NORMAL_FONT)
|
||||||
plot.addItem(self._x_label, ignoreBounds=True)
|
plot.addItem(self._x_label, ignoreBounds=True)
|
||||||
|
|
||||||
def _init_info(self) -> None:
|
def _init_info(self) -> None:
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
self._info = pg.TextItem("info", color=CURSOR_COLOR)
|
self._infos: Dict[str, pg.TextItem] = {}
|
||||||
self._info.hide()
|
for plot_name, plot in self._plots.items():
|
||||||
self._info.setZValue(2)
|
info = pg.TextItem(
|
||||||
|
"info",
|
||||||
plot = list(self._plots.values())[0]
|
color=CURSOR_COLOR,
|
||||||
plot.addItem(self._info, ignoreBounds=True)
|
border=CURSOR_COLOR,
|
||||||
|
fill=BLACK_COLOR
|
||||||
|
)
|
||||||
|
info.hide()
|
||||||
|
info.setZValue(2)
|
||||||
|
info.setFont(NORMAL_FONT)
|
||||||
|
plot.addItem(info) # , ignoreBounds=True)
|
||||||
|
self._infos[plot_name] = info
|
||||||
|
|
||||||
def _connect_signal(self) -> None:
|
def _connect_signal(self) -> None:
|
||||||
"""
|
"""
|
||||||
@ -444,24 +460,25 @@ class ChartCursor(QtCore.QObject):
|
|||||||
|
|
||||||
def update_info(self) -> None:
|
def update_info(self) -> None:
|
||||||
""""""
|
""""""
|
||||||
bar = self._manager.get_bar(self._x)
|
buf = {}
|
||||||
|
|
||||||
if bar:
|
for item, plot in self._item_plot_map.items():
|
||||||
op = bar.open_price
|
item_info_text = item.get_info_text(self._x)
|
||||||
hp = bar.high_price
|
if item_info_text:
|
||||||
lp = bar.low_price
|
if plot not in buf:
|
||||||
cp = bar.close_price
|
buf[plot] = item_info_text
|
||||||
v = bar.volume
|
else:
|
||||||
text = f"(open){op} (high){hp} (low){lp} (close){cp} (volume){v}"
|
buf[plot] += ("\n\n" + item_info_text)
|
||||||
else:
|
|
||||||
text = ""
|
|
||||||
|
|
||||||
self._info.setText(text)
|
for plot_name, plot in self._plots.items():
|
||||||
self._info.show()
|
plot_info_text = buf[plot]
|
||||||
|
info = self._infos[plot_name]
|
||||||
|
info.setText(plot_info_text)
|
||||||
|
info.show()
|
||||||
|
|
||||||
view = list(self._views.values())[0]
|
view = self._views[plot_name]
|
||||||
top_left = view.mapSceneToView(view.sceneBoundingRect().topLeft())
|
top_left = view.mapSceneToView(view.sceneBoundingRect().topLeft())
|
||||||
self._info.setPos(top_left)
|
info.setPos(top_left)
|
||||||
|
|
||||||
def move_right(self) -> None:
|
def move_right(self) -> None:
|
||||||
"""
|
"""
|
||||||
@ -501,8 +518,8 @@ class ChartCursor(QtCore.QObject):
|
|||||||
self._y = 0
|
self._y = 0
|
||||||
self._plot_name = ""
|
self._plot_name = ""
|
||||||
|
|
||||||
for line in self._v_lines + self._h_lines:
|
for line in list(self._v_lines.values()) + list(self._h_lines.values()):
|
||||||
line.hide()
|
line.hide()
|
||||||
|
|
||||||
for label in self._y_labels + [self._x_label]:
|
for label in list(self._y_labels.values()) + [self._x_label]:
|
||||||
label.hide()
|
label.hide()
|
||||||
|
Loading…
Reference in New Issue
Block a user