From 85e10ddb8a2027855836c1b42cd3864bbfda903a Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Thu, 18 Jul 2019 21:06:08 +0800 Subject: [PATCH] [Mod] improve chart appearance --- vnpy/chart/axis.py | 9 ++---- vnpy/chart/base.py | 6 ++++ vnpy/chart/item.py | 52 ++++++++++++++++++++++++++++++ vnpy/chart/widget.py | 75 +++++++++++++++++++++++++++----------------- 4 files changed, 106 insertions(+), 36 deletions(-) diff --git a/vnpy/chart/axis.py b/vnpy/chart/axis.py index 6a63d990..c8e3a2b5 100644 --- a/vnpy/chart/axis.py +++ b/vnpy/chart/axis.py @@ -2,13 +2,8 @@ from typing import List import pyqtgraph as pg -from vnpy.trader.ui import QtGui - from .manager import BarManager - - -AXIS_WIDTH = 0.8 -AXIS_FONT = QtGui.QFont("Arial", 10, QtGui.QFont.Bold) +from .base import AXIS_WIDTH, NORMAL_FONT class DatetimeAxis(pg.AxisItem): @@ -21,7 +16,7 @@ class DatetimeAxis(pg.AxisItem): self._manager: BarManager = manager 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): """ diff --git a/vnpy/chart/base.py b/vnpy/chart/base.py index 629a1fec..274cbd8c 100644 --- a/vnpy/chart/base.py +++ b/vnpy/chart/base.py @@ -1,3 +1,6 @@ +from vnpy.trader.ui import QtGui + + WHITE_COLOR = (255, 255, 255) BLACK_COLOR = (0, 0, 0) GREY_COLOR = (100, 100, 100) @@ -9,6 +12,9 @@ CURSOR_COLOR = (255, 245, 162) PEN_WIDTH = 1 BAR_WIDTH = 0.4 +AXIS_WIDTH = 0.8 +NORMAL_FONT = QtGui.QFont("Arial", 9) + def to_int(value: float) -> int: """""" diff --git a/vnpy/chart/item.py b/vnpy/chart/item.py index e1435ccc..e04c7643 100644 --- a/vnpy/chart/item.py +++ b/vnpy/chart/item.py @@ -55,6 +55,13 @@ class ChartItem(pg.GraphicsObject): """ 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: """ 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) 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): """""" @@ -258,3 +297,16 @@ class VolumeItem(ChartItem): """ min_volume, max_volume = self._manager.get_volume_range(min_ix, max_ix) 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 diff --git a/vnpy/chart/widget.py b/vnpy/chart/widget.py index 8ec3a044..4c13a900 100644 --- a/vnpy/chart/widget.py +++ b/vnpy/chart/widget.py @@ -6,8 +6,11 @@ from vnpy.trader.ui import QtGui, QtWidgets, QtCore from vnpy.trader.object import BarData from .manager import BarManager -from .base import GREY_COLOR, WHITE_COLOR, CURSOR_COLOR, BLACK_COLOR, to_int -from .axis import DatetimeAxis, AXIS_FONT +from .base import ( + GREY_COLOR, WHITE_COLOR, CURSOR_COLOR, BLACK_COLOR, + to_int, NORMAL_FONT +) +from .axis import DatetimeAxis from .item import ChartItem @@ -49,7 +52,8 @@ class ChartWidget(pg.PlotWidget): def add_cursor(self) -> None: """""" 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( self, @@ -89,7 +93,7 @@ class ChartWidget(pg.PlotWidget): # Set right axis right_axis = plot.getAxis('right') right_axis.setWidth(60) - right_axis.setStyle(tickFont=AXIS_FONT) + right_axis.tickFont = NORMAL_FONT # Connect x-axis link if self._plots: @@ -294,7 +298,8 @@ class ChartCursor(QtCore.QObject): self, widget: ChartWidget, manager: BarManager, - plots: Dict[str, pg.GraphicsObject] + plots: Dict[str, pg.GraphicsObject], + item_plot_map: Dict[ChartItem, pg.GraphicsObject] ): """""" super().__init__() @@ -302,6 +307,7 @@ class ChartCursor(QtCore.QObject): self._widget: ChartWidget = widget self._manager: BarManager = manager self._plots: Dict[str, pg.GraphicsObject] = plots + self._item_plot_map: Dict[ChartItem, pg.GraphicsObject] = item_plot_map self._x: int = 0 self._y: int = 0 @@ -346,9 +352,11 @@ class ChartCursor(QtCore.QObject): """ self._y_labels: Dict[str, pg.TextItem] = {} 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.setZValue(2) + label.setFont(NORMAL_FONT) plot.addItem(label, ignoreBounds=True) self._y_labels[plot_name] = label @@ -356,17 +364,25 @@ class ChartCursor(QtCore.QObject): "datetime", fill=CURSOR_COLOR, color=BLACK_COLOR) self._x_label.hide() self._x_label.setZValue(2) + self._x_label.setFont(NORMAL_FONT) plot.addItem(self._x_label, ignoreBounds=True) def _init_info(self) -> None: """ """ - self._info = pg.TextItem("info", color=CURSOR_COLOR) - self._info.hide() - self._info.setZValue(2) - - plot = list(self._plots.values())[0] - plot.addItem(self._info, ignoreBounds=True) + self._infos: Dict[str, pg.TextItem] = {} + for plot_name, plot in self._plots.items(): + info = pg.TextItem( + "info", + color=CURSOR_COLOR, + 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: """ @@ -444,24 +460,25 @@ class ChartCursor(QtCore.QObject): def update_info(self) -> None: """""" - bar = self._manager.get_bar(self._x) + buf = {} - if bar: - op = bar.open_price - hp = bar.high_price - lp = bar.low_price - cp = bar.close_price - v = bar.volume - text = f"(open){op} (high){hp} (low){lp} (close){cp} (volume){v}" - else: - text = "" + for item, plot in self._item_plot_map.items(): + item_info_text = item.get_info_text(self._x) + if item_info_text: + if plot not in buf: + buf[plot] = item_info_text + else: + buf[plot] += ("\n\n" + item_info_text) - self._info.setText(text) - self._info.show() + for plot_name, plot in self._plots.items(): + plot_info_text = buf[plot] + info = self._infos[plot_name] + info.setText(plot_info_text) + info.show() - view = list(self._views.values())[0] - top_left = view.mapSceneToView(view.sceneBoundingRect().topLeft()) - self._info.setPos(top_left) + view = self._views[plot_name] + top_left = view.mapSceneToView(view.sceneBoundingRect().topLeft()) + info.setPos(top_left) def move_right(self) -> None: """ @@ -501,8 +518,8 @@ class ChartCursor(QtCore.QObject): self._y = 0 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() - for label in self._y_labels + [self._x_label]: + for label in list(self._y_labels.values()) + [self._x_label]: label.hide()