class ChartWidget(QWidget): def __init__(self, parent=None, ticker="BTCUSDT"): super().__init__(parent) uic.loadUi("resource/chart.ui", self) self.ticker = ticker self.viewLimit = 10 self.tm = [] self.priceData = QCandlestickSeries() self.priceData.setDecreasingColor(Qt.red) self.priceData.setIncreasingColor(Qt.green) self.priceChart = QChart() self.priceChart.addSeries(self.priceData) self.priceChart.legend().hide() axisX = QDateTimeAxis() axisX.setFormat("hh:mm:ss") axisX.setTickCount(4) dt = QDateTime.currentDateTime() axisX.setRange(dt, dt.addSecs(self.viewLimit)) axisY = QValueAxis() axisY.setVisible(False) self.priceChart.addAxis(axisX, Qt.AlignBottom) self.priceChart.addAxis(axisY, Qt.AlignRight) self.priceData.attachAxis(axisX) self.priceData.attachAxis(axisY) self.priceChart.layout().setContentsMargins(0, 0, 0, 0) self.priceView.setChart(self.priceChart) self.priceView.setRenderHints(QPainter.Antialiasing) self.pw = PriceWorker(ticker) self.pw.dataSent.connect(self.appendData) self.pw.start() def appendData(self, o, h, l, c): if len(self.tm) == self.viewLimit: self.priceData.remove(0) self.tm.remove(0) dt = QDateTime.currentDateTime() self.priceData.append(QCandlestickSet(o, h, l, c)) print(dt.toMSecsSinceEpoch()) print(type(dt.toMSecsSinceEpoch())) self.tm.append(dt.toMSecsSinceEpoch()) self.__updateAxis() def __updateAxis(self): pvs = self.tm dtStart = QDateTime.fromMSecsSinceEpoch(int(pvs[0])) if len(self.priceData) == self.viewLimit: dtLast = QDateTime.fromMSecsSinceEpoch(int(pvs[-1])) else: dtLast = dtStart.addSecs(self.viewLimit) ax = self.priceChart.axisX() ax.setRange(dtStart, dtLast)
class PriceFigure: def __init__(self, name): self.name = name self.chart_view = QChartView() self.price_time_axis = QDateTimeAxis() self.price_time_axis.setFormat('h:mm') self.price_axis = QValueAxis() self.candle_stick_series = QCandlestickSeries() self.candle_stick_series.setIncreasingColor(Qt.red) self.candle_stick_series.setDecreasingColor(Qt.blue) self.moving_average_series = QLineSeries() self.top_edge_series = QScatterSeries() self.bottom_edge_series = QScatterSeries() self.trend_lines = [] self.short_top_trend_series = QLineSeries() self.short_bottom_trend_series = QLineSeries() self.long_top_trend_series = QLineSeries() self.long_bottom_trend_series = QLineSeries() self.trend_lines.append(self.short_top_trend_series) self.trend_lines.append(self.short_bottom_trend_series) self.trend_lines.append(self.long_top_trend_series) self.trend_lines.append(self.long_bottom_trend_series) self.chart_view.chart().addSeries(self.candle_stick_series) self.chart_view.chart().addSeries(self.moving_average_series) self.chart_view.chart().addSeries(self.top_edge_series) self.chart_view.chart().addSeries(self.bottom_edge_series) self.chart_view.chart().addSeries(self.short_top_trend_series) self.chart_view.chart().addSeries(self.long_top_trend_series) self.chart_view.chart().addSeries(self.short_bottom_trend_series) self.chart_view.chart().addSeries(self.long_bottom_trend_series) self.chart_view.chart().addAxis(self.price_time_axis, Qt.AlignBottom) self.chart_view.chart().addAxis(self.price_axis, Qt.AlignLeft) self.chart_view.chart().legend().hide() self.chart_view.setRenderHint(QPainter.Antialiasing) self.set_marker_color() self.set_trend_line_pen() def set_trend_line_pen(self): brushes = [ QBrush(QColor(255, 0, 0, 90)), QBrush(QColor(0, 0, 255, 90)), QBrush(QColor(205, 56, 47, 255)), QBrush(QColor(0, 153, 213, 255)) ] for i, tl in enumerate(self.trend_lines): tl.setPen(QPen(brushes[i], 4, Qt.DotLine)) def set_marker_color(self): self.top_edge_series.setPen(Qt.black) self.top_edge_series.setBrush(QBrush(QColor(255, 0, 255, 90))) self.bottom_edge_series.setPen(Qt.black) self.bottom_edge_series.setBrush(QBrush(QColor(0, 255, 255, 90))) def set_datetime(self, d): self.chart_datetime = d self.datetime_range = (d.timestamp() * 1000, d.replace(hour=23, minute=59).timestamp() * 1000) start_time = QDateTime() until_time = QDateTime() start_time.setDate(QDate(d.year, d.month, d.day)) until_time.setDate(QDate(d.year, d.month, d.day)) start_time.setTime(QTime(9, 0)) until_time.setTime(QTime(16, 0)) self.price_time_axis.setRange(start_time, until_time) def attach(self): self.price_time_axis.setTickCount(7) self.candle_stick_series.attachAxis(self.price_time_axis) self.candle_stick_series.attachAxis(self.price_axis) self.moving_average_series.attachAxis(self.price_time_axis) self.moving_average_series.attachAxis(self.price_axis) self.top_edge_series.attachAxis(self.price_time_axis) self.top_edge_series.attachAxis(self.price_axis) self.bottom_edge_series.attachAxis(self.price_time_axis) self.bottom_edge_series.attachAxis(self.price_axis) self.short_top_trend_series.attachAxis(self.price_time_axis) self.short_top_trend_series.attachAxis(self.price_axis) self.long_top_trend_series.attachAxis(self.price_time_axis) self.long_top_trend_series.attachAxis(self.price_axis) self.short_bottom_trend_series.attachAxis(self.price_time_axis) self.short_bottom_trend_series.attachAxis(self.price_axis) self.long_bottom_trend_series.attachAxis(self.price_time_axis) self.long_bottom_trend_series.attachAxis(self.price_axis) def in_datetime_range(self, q): return self.datetime_range[0] < q < self.datetime_range[1] def clear_series_data(self): self.candle_stick_series.clear() self.moving_average_series.clear() self.top_edge_series.clear() self.bottom_edge_series.clear() self.short_top_trend_series.clear() self.long_top_trend_series.clear() self.short_bottom_trend_series.clear() self.long_bottom_trend_series.clear() def get_chart_view(self): return self.chart_view def add_moving_average(self, q, price): if self.in_datetime_range(q): self.moving_average_series.append(q, price) def add_candle_stick(self, q, o, h, l, c): if self.in_datetime_range(q): self.candle_stick_series.append(QCandlestickSet(o, h, l, c, q)) def set_price_range(self, price_min, price_max): self.price_axis.setRange(price_min, price_max) tick_count = int( math.ceil((price_max - price_min) / price_min * 100. / 2.0)) self.price_axis.setTickCount(tick_count if tick_count + 1 > 2 else 2) def add_top_edge(self, q, price): if self.in_datetime_range(q): self.top_edge_series.append(q, price) def add_bottom_edge(self, q, price): if self.in_datetime_range(q): self.bottom_edge_series.append(q, price) def add_short_top_trend(self, q, price, draw_horizontal=False): if self.in_datetime_range(q): if draw_horizontal: self.short_top_trend_series.append(q, price) if self.name == 'yesterday': self.short_top_trend_series.append(self.datetime_range[1], price) else: self.short_top_trend_series.append(self.datetime_range[0], price) else: self.short_top_trend_series.append(q, price) def add_long_top_trend(self, q, price, draw_horizontal=False): if self.in_datetime_range(q): if draw_horizontal: self.long_top_trend_series.append(q, price) if self.name == 'yesterday': self.long_top_trend_series.append(self.datetime_range[1], price) else: self.long_top_trend_series.append(self.datetime_range[0], price) else: self.long_top_trend_series.append(q, price) def add_short_bottom_trend(self, q, price, draw_horizontal=False): if self.in_datetime_range(q): if draw_horizontal: self.short_bottom_trend_series.append(q, price) if self.name == 'yesterday': self.short_bottom_trend_series.append( self.datetime_range[1], price) else: self.short_bottom_trend_series.append( self.datetime_range[0], price) else: self.short_bottom_trend_series.append(q, price) def add_long_bottom_trend(self, q, price, draw_horizontal=False): if self.in_datetime_range(q): if draw_horizontal: self.long_bottom_trend_series.append(q, price) if self.name == 'yesterday': self.long_bottom_trend_series.append( self.datetime_range[1], price) else: self.long_bottom_trend_series.append( self.datetime_range[0], price) else: self.long_bottom_trend_series.append(q, price)
class VolumeFigure: def __init__(self, name): self.chart_volume_view = QChartView() self.chart_volume_view.chart().setLocalizeNumbers(True) self.volume_series = QCandlestickSeries() self.volume_time_axis = QDateTimeAxis() self.volume_time_axis.setFormat('h:mm') self.volume_axis = QValueAxis() self.volume_average_series = QLineSeries() self.chart_volume_view.chart().addSeries(self.volume_series) self.chart_volume_view.chart().addSeries(self.volume_average_series) self.chart_volume_view.chart().addAxis(self.volume_time_axis, Qt.AlignBottom) self.chart_volume_view.chart().addAxis(self.volume_axis, Qt.AlignLeft) self.chart_volume_view.chart().legend().hide() self.chart_volume_view.setRenderHint(QPainter.Antialiasing) def in_datetime_range(self, q): return self.datetime_range[0] < q < self.datetime_range[1] def get_chart_view(self): return self.chart_volume_view def clear_series_data(self): self.volume_series.clear() self.volume_average_series.clear() def set_volume_average(self, vol): self.volume_average_series.append(self.datetime_range[0], vol) self.volume_average_series.append(self.datetime_range[1], vol) def set_datetime(self, d): self.chart_datetime = d self.datetime_range = (d.timestamp() * 1000, d.replace(hour=23, minute=59).timestamp() * 1000) start_time = QDateTime() until_time = QDateTime() start_time.setDate(QDate(d.year, d.month, d.day)) until_time.setDate(QDate(d.year, d.month, d.day)) start_time.setTime(QTime(9, 0)) until_time.setTime(QTime(16, 0)) self.volume_time_axis.setRange(start_time, until_time) def add_volume_data(self, q, volume): if self.in_datetime_range(q): self.volume_series.append(QCandlestickSet(0, volume, 0, volume, q)) def attach(self): self.volume_time_axis.setTickCount(7) self.volume_average_series.attachAxis(self.volume_axis) self.volume_average_series.attachAxis(self.volume_time_axis) self.volume_series.attachAxis(self.volume_axis) self.volume_series.attachAxis(self.volume_time_axis) def set_max(self, vol): self.volume_axis.setRange(0, vol)
def __drawChart(self): ##绘制图表 self.chart.removeAllSeries() #删除所有序列 self.chart.setTitle("股票日线图--" + self.ui.tabWidget.tabText(0)) ## 1. 创建蜡烛图 seriesCandle = QCandlestickSeries() seriesCandle.setName("蜡烛图") seriesCandle.setIncreasingColor(Qt.red) #暴涨 seriesCandle.setDecreasingColor(Qt.darkGreen) #暴跌 visible = self.ui.chkBox_Outline.isChecked() seriesCandle.setBodyOutlineVisible(visible) seriesCandle.setCapsVisible(self.ui.chkBox_Caps.isChecked()) self.chart.addSeries(seriesCandle) seriesCandle.attachAxis(self.__axisX) seriesCandle.attachAxis(self.__axisY) seriesCandle.clicked.connect(self.do_candleClicked) seriesCandle.hovered.connect(self.do_candleHovered) ## 2. 创建MA曲线 pen = QPen() pen.setWidth(2) seriesMA1 = QLineSeries() #不能使用QSplineSeries seriesMA1.setName("MA5") pen.setColor(Qt.magenta) seriesMA1.setPen(pen) self.chart.addSeries(seriesMA1) seriesMA1.attachAxis(self.__axisX) seriesMA1.attachAxis(self.__axisY) seriesMA2 = QLineSeries() seriesMA2.setName("MA10") pen.setColor(Qt.yellow) seriesMA2.setPen(pen) self.chart.addSeries(seriesMA2) seriesMA2.attachAxis(self.__axisX) seriesMA2.attachAxis(self.__axisY) seriesMA3 = QLineSeries() seriesMA3.setName("MA20") pen.setColor(Qt.cyan) seriesMA3.setPen(pen) self.chart.addSeries(seriesMA3) seriesMA3.attachAxis(self.__axisX) seriesMA3.attachAxis(self.__axisY) seriesMA4 = QLineSeries() seriesMA4.setName("MA60") pen.setColor(Qt.green) #green seriesMA4.setPen(pen) self.chart.addSeries(seriesMA4) seriesMA4.attachAxis(self.__axisX) seriesMA4.attachAxis(self.__axisY) ## 3. 填充数据到序列 dataRowCount = self.itemModel.rowCount() #数据点个数 for i in range(dataRowCount): dateStr = self.itemModel.item(i, 0).text() #日期字符串,如"2017/02/03" dateValue = QDate.fromString(dateStr, "yyyy/MM/dd") #QDate dtValue = QDateTime(dateValue) #日期时间 QDateTime timeStamp = dtValue.toMSecsSinceEpoch() #毫秒数 oneCandle = QCandlestickSet() #QCandlestickSet oneCandle.setOpen(float(self.itemModel.item(i, 1).text())) #开盘 oneCandle.setHigh(float(self.itemModel.item(i, 2).text())) #最高 oneCandle.setLow(float(self.itemModel.item(i, 3).text())) #最低 oneCandle.setClose(float(self.itemModel.item(i, 4).text())) #收盘 oneCandle.setTimestamp(timeStamp) #时间戳 seriesCandle.append(oneCandle) #添加到序列 M1 = float(self.itemModel.item(i, 5).text()) M2 = float(self.itemModel.item(i, 6).text()) M3 = float(self.itemModel.item(i, 7).text()) M4 = float(self.itemModel.item(i, 8).text()) seriesMA1.append(timeStamp, M1) seriesMA2.append(timeStamp, M2) seriesMA3.append(timeStamp, M3) seriesMA4.append(timeStamp, M4) ## 4. 设置坐标轴范围 minDateStr = self.itemModel.item(0, 0).text() #日期字符串,如"2017/02/03" minDate = QDate.fromString(minDateStr, "yyyy/MM/dd") #QDate minDateTime = QDateTime(minDate) #最小日期时间,QDateTime maxDateStr = self.itemModel.item(dataRowCount - 1, 0).text() #日期字符串,如"2017/05/03" maxDate = QDate.fromString(maxDateStr, "yyyy/MM/dd") maxDateTime = QDateTime(maxDate) #最大日期时间 self.__axisX.setRange(minDateTime, maxDateTime) #日期时间范围 dateFormat = self.ui.comboDateFormat.currentText() #格式,如"MM-dd" self.__axisX.setFormat(dateFormat) #标签格式 self.__axisY.applyNiceNumbers() #自动 for marker in self.chart.legend().markers(): #QLegendMarker类型列表 marker.clicked.connect(self.do_LegendMarkerClicked)