def appendCandlestickSeries(self, name): ls = QCandlestickSeries() ls.setName(name) ls.setIncreasingColor(QColor(Qt.green)) ls.setDecreasingColor(QColor(Qt.red)) self.series.append(ls) return ls
def addSeries( self, _x2idx: typing.Dict, _idx2x: list, _chart: QChart, _axis_x: QValueAxis, _axis_y: QValueAxis, ): series = QCandlestickSeries() series.setName(self.name) for x, y in zip(self.x_list, self.y_list): series.append(QCandlestickSet(*y, _x2idx[x])) if self.inc_color is not None: series.setIncreasingColor(self.inc_color) else: series.setIncreasingColor(QColor("#c41919")) if self.dec_color is not None: series.setDecreasingColor(self.dec_color) else: series.setDecreasingColor(QColor("#009f9f")) _chart.addSeries(series) _chart.setAxisX(_axis_x, series) _chart.setAxisY(_axis_y, series) if self.show_value: self.createShow()
def initChart(self): self._chart = QChart(title='蜡烛图悬浮提示') self._chart.setAnimationOptions(QChart.SeriesAnimations) series = QCandlestickSeries() series.setIncreasingColor(QColor(Qt.red)) series.setDecreasingColor(QColor(Qt.green)) series.setName(self.stocks['name'].iloc[0]) for _, stock in self.stocks.iterrows(): time_p = datetime.datetime.strptime(stock['trade_date'], '%Y%m%d') time_p = float(time.mktime(time_p.timetuple())) _set = QCandlestickSet(float(stock['open']), float(stock['high']), float(stock['low']), float(stock['close']), time_p, series) _set.hovered.connect(self.handleBarHoverd) # 鼠标悬停 series.append(_set) self._chart.addSeries(series) self._chart.createDefaultAxes() self._chart.setLocalizeNumbers(True) axis_x = self._chart.axisX() axis_y = self._chart.axisY() axis_x.setGridLineVisible(False) axis_y.setGridLineVisible(False) # axis_y.setLabelFormat("%.2f") axis_x.setCategories(self.category) max_p = self.stocks[['high', 'low']].stack().max() + 10 min_p = self.stocks[['high', 'low']].stack().min() - 10 axis_y.setRange(min_p, max_p) # chart的图例 legend = self._chart.legend() # 设置图例由Series来决定样式 legend.setMarkerShape(QLegend.MarkerShapeFromSeries) self.setChart(self._chart)
def main(): import sys a = QApplication(sys.argv) acmeSeries = QCandlestickSeries() acmeSeries.setName("Acme Ltd") acmeSeries.setIncreasingColor(QColor(Qt.green)) acmeSeries.setDecreasingColor(QColor(Qt.red)) acmeData = QFile(":acme") if not acmeData.open(QIODevice.ReadOnly | QIODevice.Text): sys.exit(1) categories = [] dataReader = CandlestickDataReader(acmeData) while not dataReader.atEnd(): _set = dataReader.readCandlestickSet() if _set is not None: acmeSeries.append(_set) categories.append( QDateTime.fromMSecsSinceEpoch(int( _set.timestamp())).toString("dd")) chart = QChart() chart.addSeries(acmeSeries) chart.setTitle("Acme Ltd Historical Data (July 2015)") chart.setAnimationOptions(QChart.SeriesAnimations) chart.createDefaultAxes() axisX = chart.axes(Qt.Horizontal)[0] axisX.setCategories(categories) axisY = chart.axes(Qt.Vertical)[0] axisY.setMax(axisY.max() * 1.01) axisY.setMin(axisY.min() * 0.99) chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) window = QMainWindow() window.setCentralWidget(chartView) window.resize(800, 600) window.show() sys.exit(a.exec_())
def addSeries( self, _x2idx: typing.Dict, _idx2x: list, _chart: QChart, _axis_x: QValueAxis, _axis_y: QValueAxis ): series = QCandlestickSeries() series.setName(self.name) for x, y in zip(self.x_list, self.y_list): series.append(QCandlestickSet(*y, _x2idx[x])) if self.inc_color is not None: series.setIncreasingColor(self.inc_color) else: series.setIncreasingColor(QColor('#c41919')) if self.dec_color is not None: series.setDecreasingColor(self.dec_color) else: series.setDecreasingColor(QColor('#009f9f')) _chart.addSeries(series) _chart.setAxisX(_axis_x, series) _chart.setAxisY(_axis_y, series) if self.show_value: self.createShow()
class MainClass(QWidget): def __init__(self): super().__init__() self.initUI() def getStockData(self): self.close() print("HI") self.mainLayout.removeWidget(self.newChartView) self.newSeries = QCandlestickSeries() self.newSeries.setName("Test Chart 2") self.saucePage = urllib.request.urlopen( 'https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=' + self.stockRequestBox.text() + '&interval=1min&apikey=NOC1N35PNDQOFF1A') self.output = self.saucePage.read() self.webContent = self.output.decode( 'utf-8') # Convert from bytes to string self.writePage = open( 'stock.json', 'w' ) # Write webContent to a html file because otherwise i can't use readlines() self.writePage.write( self.webContent) # It's very efficient code trust me self.writePage.close() self.sauce = json.load(open('stock.json')) # print(sauce["Monthly Time Series"]["2018-01-14 20:23:00"]["1. open"]) self.openStocks = {} for date in self.sauce["Monthly Time Series"]: self.openStocks[date] = self.sauce["Monthly Time Series"][date][ "1. open"] self.ordered = collections.OrderedDict(sorted(self.openStocks.items())) for k, v in self.ordered.items(): dateString = k dt = datetime.datetime(int(dateString[:4]), int(dateString[5:7]), int(dateString[8:10])) self.newSet = QCandlestickSet((time.mktime(dt.timetuple()) * 1000)) self.newSet.setOpen(float(v)) self.newSet.setHigh( float(self.sauce["Monthly Time Series"][k]["2. high"])) self.newSet.setLow( float(self.sauce["Monthly Time Series"][k]["3. low"])) self.newSet.setClose( float(self.sauce["Monthly Time Series"][k]["4. close"])) self.newSeries.append(self.newSet) self.newChart = QChart() self.newChart.addSeries(self.newSeries) self.newChart.setTitle("Test Actual Chart") self.newChart.createDefaultAxes() self.newChartView = QChartView(self.newChart) self.mainLayout.addWidget(self.newChartView) self.show() def initUI(self): self.mainLayout = QVBoxLayout() self.stockFrame = QFrame() self.mainLayout.addWidget(self.stockFrame) self.mainButton = QPushButton("Push Me!") self.mainButton.clicked.connect(self.getStockData) self.mainLayout.addWidget(self.mainButton) self.stockRequestLayout = QHBoxLayout() self.stockRequestedLabel = QLabel("Stock: ") self.stockRequestLayout.addWidget(self.stockRequestedLabel) self.stockRequestBox = QLineEdit() self.stockRequestLayout.addWidget(self.stockRequestBox) self.mainLayout.addLayout(self.stockRequestLayout) self.setLayout(self.mainLayout) self.newSeries = QCandlestickSeries() self.newSeries.setName("Test Chart") # for i in range(1000): # self.newSet = QCandlestickSet(time.time() * 1000 + (random.randint(-5, 5) * 60000)) # self.newSet.setOpen(random.randint(1, 10)) # self.newSet.setHigh(random.randint(1, 10)) # self.newSet.setLow(random.randint(1, 10)) # self.newSet.setClose(random.randint(1, 10)) # self.newSeries.append(self.newSet) # self.newSet2 = QCandlestickSet() # self.newSet2.setOpen(1.00) # self.newSet2.setHigh(10.00) # self.newSet2.setLow(0.50) # self.newSet2.setClose(5.00) # self.newSeries.append(self.newSet2) self.saucePage = urllib.request.urlopen( 'https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=BHP&apikey=NOC1N35PNDQOFF1A' ) self.output = self.saucePage.read() self.webContent = self.output.decode( 'utf-8') # Convert from bytes to string self.writePage = open( 'stock.json', 'w' ) # Write webContent to a html file because otherwise i can't use readlines() self.writePage.write( self.webContent) # It's very efficient code trust me self.writePage.close() self.sauce = json.load(open('stock.json')) # print(sauce["Monthly Time Series"]["2018-01-14 20:23:00"]["1. open"]) self.openStocks = {} for date in self.sauce["Monthly Time Series"]: self.openStocks[date] = self.sauce["Monthly Time Series"][date][ "1. open"] self.ordered = collections.OrderedDict(sorted(self.openStocks.items())) count = 0 for k, v in self.ordered.items(): dateString = k dt = datetime.datetime(int(dateString[:4]), int(dateString[5:7]), int(dateString[8:10])) self.newSet = QCandlestickSet((time.mktime(dt.timetuple()) * 1000)) self.newSet.setOpen(float(v)) self.newSet.setHigh( float(self.sauce["Monthly Time Series"][k]["2. high"])) self.newSet.setLow( float(self.sauce["Monthly Time Series"][k]["3. low"])) self.newSet.setClose( float(self.sauce["Monthly Time Series"][k]["4. close"])) self.newSeries.append(self.newSet) count = count + 1 # if count > 8: # break self.newChart = QChart() self.newChart.addSeries(self.newSeries) self.newChart.setTitle("Test Actual Chart") self.newChart.createDefaultAxes() self.newChartView = QChartView(self.newChart) self.mainLayout.addWidget(self.newChartView) # self.subjectLabel = QLabel() # self.subjectLabel.setAlignment(Qt.Qt.AlignCenter) # self.mainLayout.addWidget(self.subjectLabel) # self.testLabel = QLabel() # self.testLabel.setAlignment(Qt.Qt.AlignCenter) # self.mainLayout.addWidget(self.testLabel) # self.randomButton = QPushButton("Choose") # self.randomButton.clicked.connect(self.randomDef) # self.mainLayout.addWidget(self.randomButton) # self.setLayout(self.mainLayout) self.setGeometry(300, 300, 300, 300) self.setWindowTitle("Stocks") self.show()
from PyQt5.QtCore import Qt from PyQt5.Qt import QMainWindow, QApplication, QColor, QDateTime, QIODevice, QFile, QPainter from PyQt5.QtChart import QChart, QChartView, QLineSeries, QCandlestickSeries, QCandlestickSet from candlestickdatareader import CandlestickDataReader # example qtcharts/examples/candlestickchart tranlated in python if __name__ == '__main__': import sys app = QApplication(sys.argv) # [1] acmeSeries = QCandlestickSeries() acmeSeries.setName("Acme Ltd") acmeSeries.setIncreasingColor(QColor("light green")) acmeSeries.setDecreasingColor(QColor("red")) # [1] # [2] load the data acmeData = QFile("acme_data.txt") if not acmeData.open(QIODevice.ReadOnly | QIODevice.Text): sys.exit(1) categories = [] dataReader = CandlestickDataReader(acmeData) while not dataReader.atEnd(): line = dataReader.read_candlestick_set() if line is not None: acmeSeries.append(line) categories.append( QDateTime.fromMSecsSinceEpoch(line.timestamp()).toString("dd"))
class KLineChartView(QChartView): # QCandlestickSeries的hovered的信号响应后传递日期出去 candles_hovered = pyqtSignal(bool, str) def __init__(self, data: pd.DataFrame): super(KLineChartView, self).__init__() self.setRenderHint(QPainter.Antialiasing) # 抗锯齿 self._chart = QChart() self._series = QCandlestickSeries() self._stocks = data self._category = list() self._count = None self.init_chart() self._zero_value = (0, self._chart.axisY().min()) self._max_value = (len(self._chart.axisX().categories()), self._chart.axisY().max()) self._zero_point = self._chart.mapToPosition( QPointF(self._zero_value[0], self._zero_value[1])) self._max_point = self._chart.mapToPosition( QPointF(self._max_value[0], self._max_value[1])) # 计算x轴单个cate的宽度,用来处理横线不能画到边界 self._cate_width = (self._max_point.x() - self._zero_point.x()) / len( self._category) self._series.hovered.connect(self.on_series_hovered) def on_series_hovered(self, status, candles_set): trade_date = time.strftime('%Y%m%d', time.localtime(candles_set.timestamp())) self.candles_hovered.emit(status, trade_date) def set_name(self, name): self._series.setName(name) def clear_series_values(self): self._series.clear() self._chart.axisY().setRange(0, 10) self._chart.axisX().setCategories(list()) self._stocks = None def add_series_values(self, data: pd.DataFrame, is_init=False): self._stocks = data self._category = self._stocks['trade_date'] self._count = len(self._category) for _, stock in self._stocks.iterrows(): time_p = datetime.datetime.strptime(stock['trade_date'], '%Y%m%d') time_p = float(time.mktime(time_p.timetuple())) _set = QCandlestickSet(float(stock['open']), float(stock['high']), float(stock['low']), float(stock['close']), time_p, self._series) self._series.append(_set) if not is_init: self._stocks = data self._category = self._stocks['trade_date'] axis_x = self._chart.axisX() axis_y = self._chart.axisY() axis_x.setCategories(self._category) max_p = self._stocks[['high', 'low']].stack().max() min_p = self._stocks[['high', 'low']].stack().min() axis_y.setRange(min_p * 0.99, max_p * 1.01) self._zero_value = (0, self._chart.axisY().min()) self._max_value = (len(self._chart.axisX().categories()), self._chart.axisY().max()) # 计算x轴单个cate的宽度,用来处理横线不能画到边界 self._cate_width = (self._max_point.x() - self._zero_point.x()) / len(self._category) def resizeEvent(self, event): super(KLineChartView, self).resizeEvent(event) self._zero_point = self._chart.mapToPosition( QPointF(self._zero_value[0], self._zero_value[1])) self._max_point = self._chart.mapToPosition( QPointF(self._max_value[0], self._max_value[1])) self._cate_width = (self._max_point.x() - self._zero_point.x()) / len( self._category) def max_point(self): return QPointF(self._max_point.x() + self._cate_width / 2, self._max_point.y()) def min_point(self): return QPointF(self._zero_point.x() - self._cate_width / 2, self._zero_point.y()) def init_chart(self): self._chart.setAnimationOptions(QChart.SeriesAnimations) self._series.setIncreasingColor(QColor(Qt.red)) self._series.setDecreasingColor(QColor(Qt.green)) self._series.setName(self._stocks['name'].iloc[0]) self.add_series_values(self._stocks, True) self._chart.addSeries(self._series) self._chart.createDefaultAxes() self._chart.setLocalizeNumbers(True) axis_x = self._chart.axisX() axis_y = self._chart.axisY() axis_x.setGridLineVisible(False) axis_y.setGridLineVisible(False) axis_x.setCategories(self._category) axis_x.setLabelsVisible(False) axis_x.setVisible(False) max_p = self._stocks[['high', 'low']].stack().max() min_p = self._stocks[['high', 'low']].stack().min() axis_y.setRange(min_p * 0.99, max_p * 1.01) # chart的图例 legend = self._chart.legend() # 设置图例由Series来决定样式 legend.setMarkerShape(QLegend.MarkerShapeFromSeries) self.setChart(self._chart) # 设置外边界全部为0 self._chart.layout().setContentsMargins(0, 0, 0, 0) # 设置内边界的bottom为0 margins = self._chart.margins() self._chart.setMargins(QMargins(margins.left(), 0, margins.right(), 0)) # 设置背景区域无圆角 self._chart.setBackgroundRoundness(0)
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)