用途:绘制股票kline图
说明:
绘制基本的股票kline图及相关指标图如ma移动平均线等,绘制其他指标只需传入相关数据及线的颜色即可。
绘制鼠标移动显示交易时间及open,high,low,close
有两个版本的实现,一个是数据是list(tuple),一个是数据是pd.DataFrame,前一个版本的速度优于后者,故建议使用前者。(版本1较完善,版本2不够完善)
测试1:基本的类测试
测试2:在MainWindow中测试,你可以先用qt designer画好图,在要显示的区域设置控件widget,在应用中传入该控件即可。
数据:
实例1数据类型及格式参考get_data()函数;实例2数据类型及格式在封装中做了说明
类说明:
# 自定义横坐标控件
class XaxisItem(pg.AxisItem):内部使用,不直接使用
# 绘制指标线-ma移动平均
class DrawIndicatorLine(object):内部使用,不直接使用
# 绘制蜡烛控件
class CandlestickItem(pg.GraphicsObject):内部使用,不直接使用
# 应用类包装,主要应用;使用中将相关函数放入相应的指定位置即可
class UserPlt(QObject):
@classmethod
def _init_plt(cls, xaxis_args=None):
@classmethod
def _set_plot_style(cls, plt, width=None):
@classmethod
def _set_Y_range(cls, plt, high=4400, low=2800, y_margin=0.05):
@classmethod
def init_ui(
cls,
self,
kline_data,
xaxis_args=None,
indicator_data=None,
parent=None):
@classmethod
def mouseMoved(cls, self, event):
@classmethod
def draw_kline(cls, self, func, title_label=None):
# 绘制蜡烛图控件为测试类
class PyQtGraphWidget(QtWidgets.QWidget):
使用方法:
步骤1:在界面初始化中添加UserPlt.init_ui(parent) 注1
步骤2:在该类中添加函数:UserPlt.draw_kline(),mouseMoved(self, event)
完成,就这么简单
注1:
主要一定要传入界面中要显示图片的控件的widget,即parent=self.widget,
以下的类测试该参数为parent=None
实例:
# 绘制蜡烛图控件为测试类
class PyQtGraphWidget(QtWidgets.QWidget):
def __init__(self, kline_data, indicator_data=None):
super(PyQtGraphWidget, self).__init__()
self.init_ui(kline_data, xaxis_args, indicator_data,parent=None)
def init_ui(
self,
kline_data,
xaxis_args=None,
indicator_data=None,
parent=None):
UserPlt.init_ui(self, kline_data, xaxis_args, indicator_data,parent)
def draw_kline(self):
'''k线图'''
UserPlt.draw_kline(self, self.mouseMoved, self.title_label)
def mouseMoved(self, event):
UserPlt.mouseMoved(self, event)
#=====================================================
#以下为测试程序:
# 测试1
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
kline_data, ma_data, xaxis_args = get_data()
win = PyQtGraphWidget(kline_data, ma_data)
win.show()
win.draw_kline()
sys.exit(app.exec_())
实例1: 先贴出效果图
?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Project:TcyQuantTrade
# @Module:dd1
# @Author: tcy
# @Date: 2022/5/10 0:51
# @Emial: 3615693665@qq.com
# @Version: 1.18
# @Last Modified time:
# @City: China Shanghai Songjiang Xiaokunshan
# @Company: Weishi Machinery Manufacturing Priority
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from typing import Any, Dict
import pyqtgraph as pg
from PyQt5.QtCore import pyqtSignal, QEvent, QObject, QMutex
_xaxis_args = {
'show_xaxis_line': True, # 显示x轴线
'show_xaxis_tick': True, # 显示x轴刻度线
'show_xaxis_text': True, # 显示x轴文本
'xaxis_text_rotate': -30, # x轴文本倾斜角度-文本左倾斜30度
'xaxis_text_height': 50, # 显示x轴文本的高度
'tick_font': None, # xy刻度字体
'xaxis_data_n': None # 显示x轴数据数量
}
def get_data():
#kline数据
candle_data = [
(0, 9, 16, 8, 15),
(1, 10, 15, 5, 13),
(2, 13, 20, 9, 17),
(3, 17, 23, 11, 14),
(4, 14, 19, 5, 15),
]
kline_data = {
'kline_title': 'K线图',
'x_tick': [(i, '2022-01-1%s' % v) for i, v in enumerate(range(5))],
'xy': candle_data, # 第一列为x轴数据,其他为y轴数据
}
kline_data['tick_gap'] = kline_data['xy'][1][0] - kline_data['xy'][0][0]
kline_data['candle_halfwidth'] = kline_data['tick_gap'] / 3.
#指标线数据-ma
madata = [
(0, 9, 16, 8),
(1, 10, 15, 5),
(2, 13, 20, 9),
(3, 17, 23, 33),
(4, 14, 19, 22),
]
ma_data = {'data': madata, 'colors': ['r', 'b', 'g']}
#轴参数设置
xaxis_args = _xaxis_args
return kline_data, ma_data,xaxis_args
# 自定义横坐标控件
class XaxisItem(pg.AxisItem):
def __init__(self, orientation='bottom', xaxis_args: dict = None):
'''
参数:
orientation:str='bottom'
xaxis_args={
'show_xaxis_line:bool':True,#显示x轴线
'show_xaxis_tick':True,#显示x轴刻度线
'show_xaxis_text':True,#显示x轴文本
'xaxis_text_rotate':30,#显示x轴文本选择角度
'xaxis_text_height':50,#显示x轴文本的高度
'xaxis_data_n:int=None#显示x轴数据数量
}
'''
self._xaxis_args = xaxis_args if xaxis_args else _xaxis_args
super(XaxisItem, self).__init__(orientation)
self.set_height()
def _draw_xaxis_line(self, p, axisSpec: '[pen, p1, p2]'):
'''绘制x轴长横线(坐标线)'''
pen, p1, p2 = axisSpec
p.setPen(pen)
p.drawLine(p1, p2)
p.translate(0.5, 0) # 解决了一些该死的像素模糊性
def _draw_xaxis_ticks(self, p, tickSpecs: '[pen, p1, p2]'):
'''绘制x轴刻度线'''
for pen, p1, p2 in tickSpecs:
p.setPen(pen)
p.drawLine(p1, p2)
def _draw_xaxis_text(self, p, textSpecs: '[rect, flags, text]'):
'''绘制x轴倾斜文本'''
if self._xaxis_args['tick_font']:
p.setFont(self._xaxis_args['tick_font'])
p.setPen(self.pen())
for rect, flags, text in textSpecs: # 这是最重要的部分
p.save()
p.translate(rect.x(), rect.y())
if self._xaxis_args['show_xaxis_text']:
p.rotate(self._xaxis_args['xaxis_text_rotate'])
w, h = int(rect.width()), int(rect.height())
p.drawText(-w, h, w, h, int(flags), text)
p.restore() # 恢复painter是必需的
def drawPicture(self, p, axisSpec, tickSpecs, textSpecs): # 不能更名
p.setRenderHint(p.Antialiasing, False) # 设置渲染-反锯齿
p.setRenderHint(p.TextAntialiasing, True) # 消除混叠现象
if self._xaxis_args['show_xaxis_line']:
self._draw_xaxis_line(p, axisSpec)
if self._xaxis_args['show_xaxis_tick']:
self._draw_xaxis_ticks(p, tickSpecs)
if self._xaxis_args['show_xaxis_text']:
self._draw_xaxis_text(p, textSpecs)
def set_height(self):
if self._xaxis_args['show_xaxis_text']:
self.setHeight(self._xaxis_args['xaxis_text_height'])
# 绘制指标线-ma移动平均
class DrawIndicatorLine(object):
@classmethod
def _set_pen_brush(cls, p, color_pen='g', color_bursh=None):
p.setPen(pg.mkPen(color_pen))
if color_bursh:
p.setBrush(pg.mkBrush(color_bursh))
@classmethod
def draw_line(cls, p, x1, y1, x2, y2, color_pen='c', color_bursh=None):
def point(x, y): return QtCore.QPointF(x, y)
cls._set_pen_brush(p, color_pen, color_bursh)
p.drawLine(point(x1, y1), point(x2, y2))
@classmethod
def draw_ma_lines(cls, p, ma_data: dict = None, xaxis_tick_gap=1):
'''
ma_data:dict
ma_data={'data':[(),(),...],tuple[0] is x axis,tuple[1:] is mult y axis data
'colors':=[] indicator line color
'''
if ma_data is None:
return
data = ma_data['data']
colors = ma_data['colors']
n = len(data[0][1:])
pre_madata = [0] * n # 前一个数据-n=数据长度
if colors is None:
colors = ['g'] * n # ma线数量
for i, ma in enumerate(data):
x, y = ma[0], ma[1:]
x1 = (x - 1) * xaxis_tick_gap
x2 = x * xaxis_tick_gap
for j, v in enumerate(y): # 绘制多条ma线
if pre_madata[j] != 0:
cls.draw_line(p, x1, pre_madata[j], x2, v, colors[j])
pre_madata[j] = v
# 绘制蜡烛控件
class CandlestickItem(pg.GraphicsObject):
'''创建GraphicsObject子类。唯一需要方法paint()和 boundingRect()'''
def __init__(self, kline_data, indicator_data: dict = None):
'''
self.kline_data:dict keys= ['kline_title', 'x_tick': , 'xy','tick_gap','candle_halfwidth']
self.kline_data['kline_title' ]:str
self.kline_data['x_tick'] x axis time str
self.kline_data['xy'] x,y axis kline_data:list(tuple)
self.kline_data['xy'][:][0] x axis kline_data int or float
self.kline_data['xy'][:][1:] y axis kline_data:tuple (open, high,low,close)
self.kline_data[''tick_gap'] int or float
self.kline_data['candle_halfwidth'] int or float
self.indicator_data:dict 指标线数据
'''
pg.GraphicsObject.__init__(self)
self.kline_data = kline_data
self.indicator_data = indicator_data
self.gen_picture()
def gen_picture(self):
'''预计算QPicture对象允许paint()运行得更快,而不是每次都重新画出形状'''
self.picture = QtGui.QPicture()
p = QtGui.QPainter(self.picture)
w = self.kline_data['candle_halfwidth']
for (x, open, high, low, close) in self.kline_data['xy']:
color = 'g' if open > close else 'r'
p.setPen(pg.mkPen(color))
p.setBrush(pg.mkBrush(color))
p.drawLine(QtCore.QPointF(x, low), QtCore.QPointF(x, high))
p.drawRect(QtCore.QRectF(x - w, open, w * 2, close - open))
# 绘制指标线-ma
tick_gap=self.kline_data['tick_gap']
DrawIndicatorLine.draw_ma_lines(p,self.indicator_data,tick_gap)
p.end()
def paint(self, p, *args):
p.drawPicture(0, 0, self.picture)
def boundingRect(self):
'''boundingRect 边界区域必须指示要绘制的整个区域
否则我们就会得到工件,并有可能崩溃。
(在这种情况下,QPicture为我们完成了计算rect边界的所有工作)'''
return QtCore.QRectF(self.picture.boundingRect())
# 应用类包装
class UserPlt(QObject):
def __init__(self):
super(UserPlt, self).__init__()
@classmethod
def _init_plt(cls, xaxis_args=None):
xaxis = XaxisItem(orientation='bottom', xaxis_args=xaxis_args)
plt = pg.PlotWidget(axisItems={'bottom': xaxis})
plt.setMouseEnabled(x=True, y=False)
plt.enableAutoRange(x=False, y=True)
plt.setAutoVisible(x=False, y=True)
UserPlt._set_plot_style(plt,width=xaxis_args['xaxis_data_n'])
UserPlt._set_Y_range(plt,high=100,low=0,y_margin=0.05)
return plt
@classmethod
def _set_plot_style(cls, plt, width=None):
# plt.setMouseEnabled(x=False, y=False) # 禁止鼠标拖动-禁止轴向操作
if width is not None:
plt.setXRange(-1, width + 1, padding=0) # x轴多显示一些区域
plt.showGrid(x=False, y=True) # 显示网格线
color = QtGui.QColor(110, 110, 110) #浅灰色
plt.getAxis('bottom').setTextPen(color) # x轴颜色
plt.getAxis('bottom').setPen(color) # x轴刻度颜色
plt.getAxis('left').setTextPen(color) # y轴颜色
plt.getAxis('left').setPen(color) # y轴刻度颜色
@classmethod
def _set_Y_range(cls, plt, high=4400, low=2800, y_margin=0.05):
delta = high - low
delta_t = delta * y_margin * 0.5
plt.setYRange(low - delta_t, high + delta_t, padding=0) # y轴范围
@classmethod
def init_ui(
cls,
self,
kline_data,
xaxis_args=None,
indicator_data=None,
parent=None):
'''
kline_data:dict kline数据,
xaxis_args=None,x轴参数
parent=None 父窗口的控件-也就是要在其中显示的控件如self.widget
'''
self.kline_data = kline_data
self.indicator_data = indicator_data
pg.setConfigOption('background', QtGui.QColor(0, 0, 0))
pg.setConfigOption('foreground', 'r')
self.vLine = pg.InfiniteLine(angle=90, movable=False)
self.hLine = pg.InfiniteLine(angle=0, movable=False)
self.label = pg.TextItem()
self.title_label = QtWidgets.QLabel('折线图')
self.title_label.setAlignment(Qt.AlignCenter)
self.plt = cls._init_plt(xaxis_args)
my_verticalLayout = QtGui.QVBoxLayout(parent)
my_verticalLayout.setObjectName("my_verticalLayout")
my_verticalLayout.setContentsMargins(0, 0, 0, 0)
if __name__ == '__main__':
my_verticalLayout.addWidget(self.title_label)
my_verticalLayout.addWidget(self.plt)
self.setLayout(my_verticalLayout)
# 设置显示鼠标跟随'+'线及文本
@classmethod
def _exists_pos_mouse_move_text(cls, self, mousePoint, idx):
f_pos = mousePoint.x()
n = len(self.kline_data['xy'])
min = idx * self.kline_data['tick_gap'] - \
self.kline_data['candle_halfwidth']
max = idx * self.kline_data['tick_gap'] + \
self.kline_data['candle_halfwidth']
return f_pos >= min and f_pos <= max and idx >= 0 and idx < n
@classmethod
def _set_mouse_move_text(cls, self, mousePoint, idx, enable=True):
html_str = ''
if enable:
lst = ['<p style="color:white;font-size:10px;font-weight:bold;"> ']
lst.append(self.kline_data['x_tick'][idx][1])
lst.append(' ')
# y, open,high,low close
for i, v in enumerate(['开盘', '最高', '最低', '收盘']):
xy = self.kline_data['xy']
lst.append('<br/> %s:%s' % (v, xy[idx][i + 1]))
lst.append('</p>')
html_str = ''.join(lst)
self.label.setHtml(html_str)
self.label.setPos(mousePoint.x(), mousePoint.y())
self.vLine.setPos(mousePoint.x())
self.hLine.setPos(mousePoint.y())
@classmethod
def mouseMoved(cls, self, event):
pos = event[0]
if self.plt.sceneBoundingRect().contains(pos):
mousePoint = self.vb.mapSceneToView(pos)
idx = int(mousePoint.x() + self.kline_data['candle_halfwidth'])
disp_flag = cls._exists_pos_mouse_move_text(self, mousePoint, idx)
cls._set_mouse_move_text(self, mousePoint, idx, disp_flag)
@classmethod
def draw_kline(cls, self, func, title_label=None):
'''绘制k线图'''
self.plt.clear()
if title_label:
title_label.setText(self.kline_data['kline_title'])
xaxis = self.plt.getAxis('bottom')
xaxis.setTicks([self.kline_data['x_tick']])
candle_item = CandlestickItem(self.kline_data, self.indicator_data)
self.plt.addItem(candle_item)
self.plt.addItem(self.vLine, ignoreBounds=True)
self.plt.addItem(self.hLine, ignoreBounds=True)
self.plt.addItem(self.label, ignoreBounds=True)
self.vb = self.plt.getViewBox()
self.proxy = pg.SignalProxy(
self.plt.scene().sigMouseMoved,
rateLimit=60,
slot=func)
# 显示整条折线图
self.plt.enableAutoRange()
# =============================================================
# 绘制蜡烛图控件
class PyQtGraphWidget(QtWidgets.QWidget):
def __init__(self, kline_data, indicator_data=None):
super(PyQtGraphWidget, self).__init__()
self.init_ui(kline_data, xaxis_args, indicator_data,parent=None)
def init_ui(
self,
kline_data,
xaxis_args=None,
indicator_data=None,
parent=None):
UserPlt.init_ui(self, kline_data, xaxis_args, indicator_data,parent)
def draw_kline(self):
'''k线图'''
UserPlt.draw_kline(self, self.mouseMoved, self.title_label)
def mouseMoved(self, event):
UserPlt.mouseMoved(self, event)
#=====================================================
#以下为测试程序:
# 测试1
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
kline_data, ma_data, xaxis_args = get_data()
win = PyQtGraphWidget(kline_data, ma_data)
win.show()
win.draw_kline()
sys.exit(app.exec_())
#测试2:
# 原文链接:https: // blog.csdn.net / m0_37967652 / article / details / 123248250
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Project:TcyQuantTrade
# @Module:test_dd
# @Author: tcy
# @Date: 2022/5/12 9:52
# @Emial: 3615693665@qq.com
# @Version: 1.18
# @Last Modified time:
# @City: China Shanghai Songjiang Xiaokunshan
# @Company: Weishi Machinery Manufacturing Priority
from PyQt5.QtWidgets import QMainWindow, QWidget, QApplication
from dlg.tcy_kline import *
from dlg.tcy_kline_ui_main_window import Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow):
main_win_exit_signal = pyqtSignal(object)
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
kline_data, ma_data, xaxis_args=get_data()
UserPlt.init_ui(self, kline_data, xaxis_args, ma_data, parent=self.widget)
def draw_kline(self,title_label=None):
'''k线图'''
UserPlt.draw_kline(self,self.mouseMoved,title_label)
def mouseMoved(self, event):
UserPlt.mouseMoved(self, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
win.draw_kline()
sys.exit(app.exec())
实例2:效果图
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Project:TcyQuantTrade
# @Module:test_dd
# @Author: tcy
# @Date: 2022/5/12 9:52
# @Emial: 3615693665@qq.com
# @Version: 1.18
# @Last Modified time:
# @City: China Shanghai Songjiang Xiaokunshan
# @Company: Weishi Machinery Manufacturing Priority
from PyQt5.QtWidgets import QMainWindow, QWidget, QApplication
from PyQt5.QtCore import pyqtSignal, QEvent, QObject, QMutex
from dlg.tcy_kline_df import *
from dlg.tcy_kline_ui_main_window import Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow):
main_win_exit_signal = pyqtSignal(object)
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.verticalLayout_2 = QtGui.QVBoxLayout(self.widget)
self.verticalLayout_2.setObjectName("verticalLayout")
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.drawChart = DrawChart(get_data(), x_axis_tick_gap=1.0, candleline_halfwidth_ratio=0.3)
self.verticalLayout_2.addWidget(self.drawChart.pyqtgraphDrawChart())
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec())
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Project:TcyQuantTrade
# @Module:dd
# @Author: tcy
# @Date: 2022/5/4 21:12
# @Emial: 3615693665@qq.com
# @Version: 1.18
# @Last Modified time:
# @City: China Shanghai Songjiang Xiaokunshan
# @Company: Weishi Machinery Manufacturing Priority
import sys
import pandas as pd
from PyQt5 import QtCore, QtGui
import datetime
import pyqtgraph as pg
import cgitb#关于QT异常直接退出没有报错的情况,查bug比较麻烦
# 这句放在所有程序开始前,这样就可以正常打印异常了
cgitb.enable(format="text")
#测试数据格式
def get_data(file=r'C:\Users\Administrator\Desktop\m22051.csv'):
'''
日期,open,high,low,close,vol,成交额,持仓量,ma5,ma10,ma20,symbol,结束时间
日期 open high low ... 持仓量 ma5 ma10 ma20
0 2021/6/17 3309 3311 3239 ... 27582 3347.8 3373.7 3344.80
1 2021/6/18 3216 3246 3151 ... 30270 3300.6 3351.2 3337.25
2 2021/6/21 3202 3232 3196 ... 30785 3253.8 3336.0 3331.75
'''
df = pd.read_csv(file)
cols = ['日期', 'open', 'high', 'low', 'close', 'vol', '成交额', '持仓量', 'ma5', 'ma10', 'ma20']
df = df[cols]
df.reset_index(inplace=True, drop=True)
return df
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout_2 = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout_2.setObjectName("verticalLayout")
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 31))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.drawChart = DrawChart(get_data(),x_axis_tick_gap=1.0,candleline_halfwidth_ratio=0.3)
self.verticalLayout_2.addWidget(self.drawChart.pyqtgraphDrawChart())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
#应用类
class DrawChart():
def __init__(self,data,x_axis_tick_gap=1.0,candleline_halfwidth_ratio=0.3):
'''
data:DataFrame cols=
[日期,open,high,low,close,vol,成交额,持仓量,ma5,ma10,ma20]
前6列是必须的,索引必须是整数升序
self._x_axis_tick_gap #x轴2刻度之间的距离
self._candleline_halfwidth_ratio #蜡烛线图半宽占x轴2刻度之间的距离的比率
self._candleline_halfwidth #蜡烛线图半宽
= self._x_axis_tick_gap*self._candleline_halfwidth_ratio
'''
self.data=data# 4266,2890
self._x_axis_tick_gap=x_axis_tick_gap
self._candleline_halfwidth_ratio=candleline_halfwidth_ratio
self._candleline_halfwidth = self._x_axis_tick_gap*self._candleline_halfwidth_ratio
def draw_mouse_move_cross_line(self):
# 添加鼠标移动+线
color = QtGui.QColor(255, 255, 255)
pen = pg.mkPen(color, width=1, style=QtCore.Qt.SolidLine)
self.vline = pg.InfiniteLine(angle=90, movable=False, pen=pen) # 创建垂直线
self.hline = pg.InfiniteLine(angle=0, movable=False, pen=pen) # 创建水平线
self.vline.setPos(-100)
self.hline.setPos(-100)
self.plt.addItem(self.vline, ignoreBounds=True)
self.plt.addItem(self.hline, ignoreBounds=True)
self.move_slot = pg.SignalProxy(
self.plt.scene().sigMouseMoved,
rateLimit=100,
slot=self.PlotCursor)
def pyqtgraphDrawChart(self):
def get_xaxis_data():
n_data = len(self.data)
s = self.data['日期']
k1, v1 = int((n_data + 1) / 2) - 1, str(s[int((n_data + 1) / 2)])
x_axis_data = {0: str(s[0]), k1: v1, n_data - 1: str(s.iloc[-1])}
return x_axis_data,n_data
try:
self.item = CandlestickItem(self.data,self._x_axis_tick_gap,self._candleline_halfwidth)
x_axis = pg.AxisItem(orientation='bottom')
x_axis_data, n_data=get_xaxis_data()
x_axis.setTicks([x_axis_data.items()])
axisItems = {'bottom': x_axis}
self.plt = pg.PlotWidget(axisItems=axisItems,enableMenu=False)
self._set_plot_style(width=n_data)
self._set_Y_range()
self.plt.addItem(self.item)
self.draw_mouse_move_cross_line()
return self.plt
except BaseException:
return pg.PlotWidget()
def _set_plot_style(self, width):
# self.plt.setMouseEnabled(x=False, y=False) # 禁止鼠标拖动-禁止轴向操作
self.plt.setXRange(-1, width + 1, padding=0) # x轴多显示一些区域
self.plt.showGrid(x=False, y=True) # 显示网格线
color = QtGui.QColor(110, 110, 110)
self.plt.getAxis('left').setTextPen(color) # y轴颜色
self.plt.getAxis('left').setPen(color) # x轴颜色
self.plt.getAxis('bottom').setTextPen(color) # y轴刻度颜色
self.plt.getAxis('bottom').setPen(color) # x轴刻度颜色
def _set_Y_range(self, high=4400, low=2800, y_margin=0.05):
delta = high - low
delta_t = delta * y_margin * 0.5
self.plt.setYRange(low - delta_t, high + delta_t, padding=0) # y轴范围
def PlotCursor(self, event=None):
#获取当前光标位置
def get_cursor_pos(mousePoint):
float_cursor_pos = mousePoint.x()
adjust_pos=float_cursor_pos+self._candleline_halfwidth
pos=int((adjust_pos)/self._x_axis_tick_gap)
return pos
pos = event[0]
if self.plt.sceneBoundingRect().contains(pos):
mousePoint = self.plt.plotItem.vb.mapSceneToView(pos) # 转换坐标系
# index = int(mousePoint.x() + self._candleline_halfwidth)
index=get_cursor_pos(mousePoint)# 鼠标所处的x轴坐标
if True:
# # if -1 < index < len(self.data['high']):
# # trade_date = self.data['trade_date'][index]
# 设置垂直线条和水平线条的位置组成十字光标
self.vline.setPos(mousePoint.x())
self.hline.setPos(mousePoint.y())
# # 显示x, y坐标跟随鼠标移动并且居中
# if self.ylabel is not None:
# self.ylabel.setText(str(round(mousePoint.y(), 2)))
# self.ylabel.move(
# 0, pos.y() - self.ylabel.geometry().height() / 2)
# if self.ylabel.isHidden():
# self.ylabel.show()
# if self.xlabel is not None:
# # self.xlabel.setText(trade_date)
# self.xlabel.move(
# pos.x() - self.xlabel.geometry().width() / 2,
# self.xlabel.geometry().y())
# if self.xlabel.isHidden():
# self.xlabel.show()
def leaveEvent(self, a0):
self.vline.setPos(-100)
self.hline.setPos(-100)
if self.ylabel is not None:
self.ylabel.hide()
if self.xlabel is not None:
self.xlabel.hide()
class CandlestickItem(pg.GraphicsObject):
def __init__(self, data,x_axis_tick_gap=1,candleline_halfwidth=0.3):
'''
data:DataFrame cols=
[日期,open,high,low,close,vol,成交额,持仓量,ma5,ma10,ma20]
前6列是必须的,索引必须是整数升序
x_axis_tick_gap:float=1.0, 两个蜡烛线x轴之间的距离
candleline_halfwidth:float=0.3 蜡烛线图矩形半宽
'''
pg.GraphicsObject.__init__(self)
self.data = data
self._paint = None
self._x_axis_tick_gap = x_axis_tick_gap
self._candleline_halfwidth = self._x_axis_tick_gap * candleline_halfwidth
self.draw_picture()
def set_pen_brush(self,color_pen='g', color_bursh='g'):
self._paint.setPen(pg.mkPen(color_pen))
self._paint.setBrush(pg.mkBrush(color_bursh))
def draw_line(self,x1, y1, x2, y2, color_pen='c', color_bursh='c'):
point=lambda x,y:QtCore.QPointF(x, y)
self.set_pen_brush(color_pen, color_bursh)
self._paint.drawLine(point(x1, y1), point(x2, y2))
def draw_line_ma(
self,
x1: float,
y1: list,
x2: float,
y2: float,
color_pen='c',
color_bursh='c'):
if y1[0] != 0:
self.draw_line(x1, y1[0], x2, y2, color_pen, color_bursh)
y1[0] = y2
def draw_line_rect(
self,
line: '(x1,y1,x2,y2)',
rect: '(x,y,w,h)',
color_pen='g',
color_bursh='g'):
'''
drawRect(int x, int y, int width, int height)绘制一个矩形,
其左上角位于 ( x , y ) 并具有给定的宽度和高度
'''
point = lambda x, y: QtCore.QPointF(x, y)
self.set_pen_brush(color_pen, color_bursh)
p1,p2=point( line[0], line[1]), point( line[2], line[3])
self._paint.drawLine(p1,p2 )
self._paint.drawRect(QtCore.QRectF(*rect))
def draw_picture(self):
def draw_kline(id,row):
open, high, low, close = row.open, row.high, row.low, row.close
color = 'g' if open > close else 'r'
x = id * self._x_axis_tick_gap
line = (x, low, x, high)
x1 = x - self._candleline_halfwidth
width = self._candleline_halfwidth * 2
rect = (x1, open, width, close - open)
self.draw_line_rect(line, rect, color, color)
def draw_ma_lines(id,row,prema5, prema10, prema20):
ma5, ma10, ma20 = row.ma5, row.ma10, row.ma20
x1=(id-1)*self._x_axis_tick_gap
x2=id*self._x_axis_tick_gap
self.draw_line_ma(x1, prema5,x2, ma5, 'w', 'w')
self.draw_line_ma(x1, prema10, x2, ma10, 'c', 'c')
self.draw_line_ma(x1, prema20, x2, ma20, 'g', 'g')
self.picture = QtGui.QPicture()
self._paint = QtGui.QPainter(self.picture)
self._paint.setPen(pg.mkPen('w'))
prema5, prema10, prema20 = [0], [0], [0]
for id, row in self.data.iterrows():
draw_kline(id, row)
draw_ma_lines(id, row, prema5, prema10, prema20)
self._paint.end()
def paint(self, p, *args):
p.drawPicture(0, 0, self.picture)
def boundingRect(self):#必须大写
return QtCore.QRectF(self.picture.boundingRect())
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
m22051.csv
日期,open,high,low,close,vol,成交额,持仓量,ma5,ma10,ma20,symbol,结束时间
2021/6/17,3309,3311,3239,3254,12835,419973700,27582,3347.8,3373.7,3344.8,DCE.m2205,2021/6/17
2021/6/18,3216,3246,3151,3181,20165,642556400,30270,3300.6,3351.2,3337.25,DCE.m2205,2021/6/18
2021/6/21,3202,3232,3196,3206,12152,390039400,30785,3253.8,3336,3331.75,DCE.m2205,2021/6/21
2021/6/22,3196,3236,3194,3212,6638,213566200,31897,3229.4,3315.6,3326.7,DCE.m2205,2021/6/22
2021/6/23,3211,3234,3205,3210,9895,318182700,34174,3212.6,3294.9,3321.4,DCE.m2205,2021/6/23
2021/6/24,3208,3222,3193,3208,11008,352982600,37187,3203.4,3275.6,3316.95,DCE.m2205,2021/6/24
2021/6/25,3195,3218,3182,3211,11337,362804600,38998,3209.4,3255,3314.65,DCE.m2205,2021/6/25
2021/6/28,3216,3251,3188,3245,16012,515883000,39004,3217.2,3235.5,3311.55,DCE.m2205,2021/6/28
2021/6/29,3231,3267,3231,3262,11277,366842700,39072,3227.2,3228.3,3309.5,DCE.m2205,2021/6/29
2021/6/30,3265,3480,3244,3278,12858,422672100,40154,3240.8,3226.7,3306.5,DCE.m2205,2021/6/30
2021/7/1,3268,3415,3254,3409,29095,978757000,42488,3281,3242.2,3307.95,DCE.m2205,2021/7/1
2021/7/2,3433,3455,3418,3445,26959,926811400,48092,3327.8,3268.6,3309.9,DCE.m2205,2021/7/2
2021/7/5,3454,3455,3400,3414,18647,637672500,50078,3361.6,3289.4,3312.7,DCE.m2205,2021/7/5
2021/7/6,3413,3423,3395,3399,15311,521520700,51238,3389,3308.1,3311.85,DCE.m2205,2021/7/6
2021/7/7,3398,3398,3302,3333,31882,1063143200,57972,3400,3320.4,3307.65,DCE.m2205,2021/7/7
2021/7/8,3321,3340,3309,3327,36346,1207426800,69317,3383.6,3332.3,3303.95,DCE.m2205,2021/7/8
2021/7/9,3312,3334,3303,3316,35274,1169163400,73301,3357.8,3342.8,3298.9,DCE.m2205,2021/7/9
2021/7/12,3311,3332,3291,3317,47903,1584315500,79226,3338.4,3350,3292.75,DCE.m2205,2021/7/12
2021/7/13,3318,3350,3314,3336,33184,1105637000,81207,3325.8,3357.4,3292.85,DCE.m2205,2021/7/13
2021/7/14,3337,3348,3315,3339,24267,808842700,84627,3327,3363.5,3295.1,DCE.m2205,2021/7/14
2021/7/15,3343,3384,3340,3372,18031,607095400,85545,3336,3359.8,3301,DCE.m2205,2021/7/15
2021/7/16,3368,3379,3358,3379,16664,561485700,84964,3348.6,3353.2,3310.9,DCE.m2205,2021/7/16
2021/7/19,3389,3455,3385,3420,31880,1091316300,85605,3369.2,3353.8,3321.6,DCE.m2205,2021/7/19
2021/7/20,3411,3415,3365,3414,23087,784584700,87641,3384.8,3355.3,3331.7,DCE.m2205,2021/7/20
2021/7/21,3419,3444,3402,3421,36622,1252738100,86457,3401.2,3364.1,3342.25,DCE.m2205,2021/7/21
2021/7/22,3426,3444,3380,3382,45951,1564735400,91600,3403.2,3369.6,3350.95,DCE.m2205,2021/7/22
2021/7/23,3371,3375,3312,3320,42168,1407296900,100235,3391.4,3370,3356.4,DCE.m2205,2021/7/23
2021/7/26,3326,3335,3263,3279,74151,2437301900,123807,3363.2,3366.2,3358.1,DCE.m2205,2021/7/26
2021/7/27,3319,3336,3273,3322,44764,1480879600,125793,3344.8,3364.8,3361.1,DCE.m2205,2021/7/27
2021/7/28,3329,3378,3313,3316,56079,1872350300,132358,3323.8,3362.5,3363,DCE.m2205,2021/7/28
2021/7/29,3329,3355,3324,3354,43660,1456120300,137562,3318.2,3360.7,3360.25,DCE.m2205,2021/7/29
2021/7/30,3353,3371,3335,3369,38838,1301303500,144219,3328,3359.7,3356.45,DCE.m2205,2021/7/30
2021/8/2,3351,3360,3298,3349,47262,1574456200,144606,3342,3352.6,3353.2,DCE.m2205,2021/8/2
2021/8/3,3344,3365,3324,3359,35108,1174296200,147928,3349.4,3347.1,3351.2,DCE.m2205,2021/8/3
2021/8/4,3333,3344,3305,3315,43770,1453118100,144410,3349.2,3336.5,3350.3,DCE.m2205,2021/8/4
2021/8/5,3318,3321,3298,3301,46477,1538387700,156698,3338.6,3328.4,3349,DCE.m2205,2021/8/5
2021/8/6,3309,3326,3303,3313,48574,1608818400,166227,3327.4,3327.7,3348.85,DCE.m2205,2021/8/6
2021/8/9,3315,3343,3306,3335,57633,1916279600,173070,3324.6,3333.3,3349.75,DCE.m2205,2021/8/9
2021/8/10,3327,3356,3326,3348,45559,1521100400,176661,3322.4,3335.9,3350.35,DCE.m2205,2021/8/10
2021/8/11,3348,3352,3330,3341,47431,1584108700,181374,3327.6,3338.4,3350.45,DCE.m2205,2021/8/11
2021/8/12,3339,3350,3271,3279,65163,2155525400,187944,3323.2,3330.9,3345.8,DCE.m2205,2021/8/12
2021/8/13,3292,3369,3280,3365,92218,3057651200,198358,3333.6,3330.5,3345.1,DCE.m2205,2021/8/13
2021/8/16,3373,3406,3361,3400,82018,2774692300,200926,3346.6,3335.6,3344.1,DCE.m2205,2021/8/16
2021/8/17,3395,3415,3376,3405,61071,2076543400,208989,3358,3340.2,3343.65,DCE.m2205,2021/8/17
2021/8/18,3400,3418,3365,3388,84848,2876097700,219813,3367.4,3347.5,3342,DCE.m2205,2021/8/18
2021/8/19,3382,3392,3342,3349,82210,2763724100,223341,3381.4,3352.3,3340.35,DCE.m2205,2021/8/19
2021/8/20,3338,3342,3313,3322,89193,2969458900,237029,3372.8,3353.2,3340.45,DCE.m2205,2021/8/20
2021/8/23,3316,3318,3261,3270,113203,3718854800,266480,3346.8,3346.7,3340,DCE.m2205,2021/8/23
2021/8/24,3271,3288,3245,3272,111612,3646373200,288613,3320.2,3339.1,3337.5,DCE.m2205,2021/8/24
2021/8/25,3274,3298,3271,3288,104342,3429018700,294158,3300.2,3333.8,3336.1,DCE.m2205,2021/8/25
2021/8/26,3290,3307,3277,3297,112694,3712611500,295632,3289.8,3335.6,3333.25,DCE.m2205,2021/8/26
2021/8/27,3297,3302,3275,3287,83004,2729713900,297696,3282.8,3327.8,3329.15,DCE.m2205,2021/8/27
2021/8/30,3282,3318,3276,3299,120605,3980621800,303015,3288.6,3317.7,3326.65,DCE.m2205,2021/8/30
2021/8/31,3302,3305,3265,3286,102606,3367404900,301867,3291.4,3305.8,3323,DCE.m2205,2021/8/31
2021/9/1,3278,3284,3247,3258,102383,3339240300,312285,3285.4,3292.8,3320.15,DCE.m2205,2021/9/1
2021/9/2,3255,3268,3239,3257,140449,4570471100,308249,3277.4,3283.6,3317.95,DCE.m2205,2021/9/2
2021/9/3,3260,3262,3222,3232,146170,4733769500,332232,3266.4,3274.6,3313.9,DCE.m2205,2021/9/3
2021/9/6,3237,3246,3217,3239,145826,4713221400,347346,3254.4,3271.5,3309.1,DCE.m2205,2021/9/6
2021/9/7,3245,3285,3237,3278,117869,3845260700,339706,3252.8,3272.1,3305.6,DCE.m2205,2021/9/7
2021/9/8,3275,3279,3237,3239,128189,4181329200,343362,3249,3267.2,3300.5,DCE.m2205,2021/9/8
2021/9/9,3248,3252,3205,3218,166671,5382141000,359286,3241.2,3259.3,3297.45,DCE.m2205,2021/9/9
2021/9/10,3216,3258,3204,3254,162757,5248786200,361906,3245.6,3256,3291.9,DCE.m2205,2021/9/10
2021/9/13,3278,3279,3246,3268,131460,4293756600,364633,3251.4,3252.9,3285.3,DCE.m2205,2021/9/13
2021/9/14,3260,3278,3249,3274,134887,4404673400,358785,3250.6,3251.7,3278.75,DCE.m2205,2021/9/14
2021/9/15,3278,3283,3257,3260,97729,3192841600,370571,3254.8,3251.9,3272.35,DCE.m2205,2021/9/15
2021/9/16,3262,3270,3236,3248,141447,4600446000,369513,3260.8,3251,3267.3,DCE.m2205,2021/9/16
2021/9/17,3248,3268,3228,3260,196871,6392860500,361212,3262,3253.8,3264.2,DCE.m2205,2021/9/17
2021/9/22,3248,3253,3220,3223,87371,2822966300,361991,3253,3252.2,3261.85,DCE.m2205,2021/9/22
2021/9/23,3230,3246,3225,3239,110432,3571591900,357664,3246,3248.3,3260.2,DCE.m2205,2021/9/23
2021/9/24,3240,3249,3222,3229,95001,3071359800,363423,3239.8,3247.3,3257.25,DCE.m2205,2021/9/24
2021/9/27,3224,3262,3220,3258,153764,4986622300,370070,3241.8,3251.3,3255.3,DCE.m2205,2021/9/27
2021/9/28,3260,3267,3224,3227,127269,4127044900,373217,3235.2,3248.6,3252.3,DCE.m2205,2021/9/28
2021/9/29,3229,3229,3202,3204,134160,4312441500,381317,3231.4,3242.2,3247.55,DCE.m2205,2021/9/29
2021/9/30,3207,3212,3181,3190,109629,3503991900,382784,3221.6,3233.8,3242.75,DCE.m2205,2021/9/30
2021/10/8,3130,3145,3083,3094,256115,7943902200,425874,3194.6,3217.2,3234.55,DCE.m2205,2021/10/8
2021/10/11,3100,3121,3071,3090,226946,7022010000,467282,3161,3201.4,3226.2,DCE.m2205,2021/10/11
2021/10/12,3095,3098,3049,3091,223594,6889526600,473022,3133.8,3184.5,3219.15,DCE.m2205,2021/10/12
2021/10/13,3088,3098,3033,3037,300004,9197667100,523083,3100.4,3165.9,3209.05,DCE.m2205,2021/10/13
2021/10/14,3033,3044,3011,3034,224174,6792088800,544807,3069.2,3145.4,3196.85,DCE.m2205,2021/10/14
2021/10/15,3037,3041,3015,3039,193141,5848933500,579050,3058.2,3126.4,3186.85,DCE.m2205,2021/10/15
2021/10/18,3042,3056,3021,3027,169323,5147325500,585423,3045.6,3103.3,3177.3,DCE.m2205,2021/10/18
2021/10/19,3025,3028,3003,3017,172691,5208136700,596251,3030.8,3082.3,3165.45,DCE.m2205,2021/10/19
2021/10/20,3015,3046,3015,3024,233217,7064899900,612055,3028.2,3064.3,3153.25,DCE.m2205,2021/10/20
2021/10/21,3028,3040,3012,3027,252070,7628370700,647887,3026.8,3048,3140.9,DCE.m2205,2021/10/21
2021/10/22,3019,3047,3005,3045,255494,7756113600,637070,3028,3043.1,3130.15,DCE.m2205,2021/10/22
2021/10/25,3042,3075,3026,3054,283459,8651910300,660504,3033.4,3039.5,3120.45,DCE.m2205,2021/10/25
2021/10/26,3055,3056,3023,3039,231502,7026740400,673655,3037.8,3034.3,3109.4,DCE.m2205,2021/10/26
2021/10/27,3042,3042,3015,3029,229531,6945591900,694785,3038.8,3033.5,3099.7,DCE.m2205,2021/10/27
2021/10/28,3025,3062,3019,3055,304681,9280924100,724236,3044.4,3035.6,3090.5,DCE.m2205,2021/10/28
2021/10/29,3052,3078,3043,3045,268304,8207484800,742230,3044.4,3036.2,3081.3,DCE.m2205,2021/10/29
2021/11/1,3045,3069,2997,3008,456290,13852158600,731679,3035.2,3034.3,3068.8,DCE.m2205,2021/11/1
2021/11/2,3012,3024,2999,3003,288479,8683592300,739780,3028,3032.9,3057.6,DCE.m2205,2021/11/2
2021/11/3,3005,3028,2947,2961,454252,13551221300,762989,3014.4,3026.6,3045.45,DCE.m2205,2021/11/3
2021/11/4,2963,2980,2946,2969,262835,7789123200,779099,2997.2,3020.8,3034.4,DCE.m2205,2021/11/4
2021/11/5,2972,2979,2899,2906,342593,10056265300,794011,2969.4,3006.9,3025,DCE.m2205,2021/11/5
2021/11/8,2902,2957,2890,2928,331234,9685170500,800403,2953.4,2994.3,3016.9,DCE.m2205,2021/11/8
2021/11/9,2928,2935,2890,2926,244551,7128439700,814056,2938,2983,3008.65,DCE.m2205,2021/11/9
2021/11/10,2927,2986,2916,2955,252272,7442076600,801364,2936.8,2975.6,3004.55,DCE.m2205,2021/11/10
2021/11/11,2925,2982,2925,2977,200537,5943287200,804922,2938.4,2967.8,3001.7,DCE.m2205,2021/11/11
2021/11/12,2975,3004,2967,2998,227865,6805930200,823452,2956.8,2963.1,2999.65,DCE.m2205,2021/11/12
2021/11/15,2995,3032,2972,3008,255257,7665989500,824954,2972.8,2963.1,2998.7,DCE.m2205,2021/11/15
2021/11/16,3015,3050,3012,3033,232083,7036195800,849921,2994.2,2966.1,2999.5,DCE.m2205,2021/11/16
2021/11/17,3036,3042,3011,3023,177027,5350552400,837004,3007.8,2972.3,2999.45,DCE.m2205,2021/11/17
2021/11/18,3025,3061,3025,3048,211696,6441358500,836967,3022,2980.2,3000.5,DCE.m2205,2021/11/18
2021/11/19,3050,3067,3018,3054,228370,6957930800,840307,3033.2,2995,3000.95,DCE.m2205,2021/11/19
2021/11/22,3042,3050,3021,3045,253514,7690828100,827605,3040.6,3006.7,3000.5,DCE.m2205,2021/11/22
2021/11/23,3045,3096,3036,3086,335401,10289022700,871904,3051.2,3022.7,3002.85,DCE.m2205,2021/11/23
2021/11/24,3085,3100,3069,3097,271587,8384649500,885070,3066,3036.9,3006.25,DCE.m2205,2021/11/24
2021/11/25,3097,3117,3055,3075,298635,9211136800,898919,3071.4,3046.7,3007.25,DCE.m2205,2021/11/25
2021/11/26,3087,3087,3055,3067,224944,6897331000,897679,3074,3053.6,3008.35,DCE.m2205,2021/11/26
2021/11/29,3065,3082,3014,3081,407054,12422100900,904296,3081.2,3060.9,3012,DCE.m2205,2021/11/29
2021/11/30,3084,3095,3037,3045,339007,10379193300,918506,3073,3062.1,3014.1,DCE.m2205,2021/11/30
2021/12/1,3045,3052,3025,3049,317023,9621734500,934760,3063.4,3064.7,3018.5,DCE.m2205,2021/12/1
2021/12/2,3049,3057,3016,3051,377561,11467561000,955511,3058.6,3065,3022.6,DCE.m2205,2021/12/2
2021/12/3,3051,3107,3048,3105,441421,13608381000,1017986,3066.2,3070.1,3032.55,DCE.m2205,2021/12/3
2021/12/6,3107,3113,3069,3080,508591,15725076800,1039224,3066,3073.6,3040.15,DCE.m2205,2021/12/6
2021/12/7,3077,3079,3037,3043,662140,20231316200,1050786,3065.6,3069.3,3046,DCE.m2205,2021/12/7
2021/12/8,3043,3050,3021,3037,566631,17183961100,1047536,3063.2,3063.3,3050.1,DCE.m2205,2021/12/8
2021/12/9,3034,3111,3023,3096,862760,26534585000,1109751,3072.2,3065.4,3056.05,DCE.m2205,2021/12/9
2021/12/10,3086,3138,3077,3124,809073,25174058300,1176444,3076,3071.1,3062.35,DCE.m2205,2021/12/10
2021/12/13,3130,3155,3118,3124,704516,22084459000,1208914,3084.8,3075.4,3068.15,DCE.m2205,2021/12/13
2021/12/14,3114,3129,3071,3073,868554,26890990400,1164929,3090.8,3078.2,3070.15,DCE.m2205,2021/12/14
2021/12/15,3083,3148,3082,3124,1089715,34001035900,1237025,3108.2,3085.7,3075.2,DCE.m2205,2021/12/15
2021/12/16,3134,3176,3107,3168,1010061,31799227500,1285138,3122.6,3097.4,3081.2,DCE.m2205,2021/12/16
2021/12/17,3167,3178,3146,3174,706739,22370833100,1319789,3132.6,3104.3,3087.2,DCE.m2205,2021/12/17
2021/12/20,3180,3180,3138,3159,850416,26871480800,1279944,3139.6,3112.2,3092.9,DCE.m2205,2021/12/20
2021/12/21,3151,3183,3145,3153,781166,24717467300,1299656,3155.6,3123.2,3096.25,DCE.m2205,2021/12/21
2021/12/22,3147,3198,3140,3179,827218,26246569500,1308354,3166.6,3137.4,3100.35,DCE.m2205,2021/12/22
2021/12/23,3187,3248,3186,3246,1125843,36214088800,1384424,3182.2,3152.4,3108.9,DCE.m2205,2021/12/23
2021/12/24,3230,3272,3224,3263,805794,26175528600,1399752,3200,3166.3,3118.7,DCE.m2205,2021/12/24
2021/12/27,3265,3268,3226,3230,726395,23544958800,1371882,3214.2,3176.9,3126.15,DCE.m2205,2021/12/27
2021/12/28,3248,3290,3231,3257,1054025,34355921100,1396194,3235,3195.3,3136.75,DCE.m2205,2021/12/28
2021/12/29,3259,3260,3205,3226,869507,28082728200,1383950,3244.4,3205.5,3145.6,DCE.m2205,2021/12/29
2021/12/30,3202,3247,3191,3234,739453,23819750200,1401816,3242,3212.1,3154.75,DCE.m2205,2021/12/30
2021/12/31,3215,3217,3170,3189,875469,27953126000,1388687,3227.2,3213.6,3158.95,DCE.m2205,2021/12/31
2022/1/4,3220,3263,3218,3250,625772,20320787000,1424194,3231.2,3222.7,3167.45,DCE.m2205,2022/1/4
2022/1/5,3242,3298,3238,3293,787718,25793324300,1453763,3238.4,3236.7,3179.95,DCE.m2205,2022/1/5
2022/1/6,3283,3285,3212,3215,1031941,33510139400,1416152,3236.2,3240.3,3188.85,DCE.m2205,2022/1/6
2022/1/7,3225,3245,3215,3225,697417,22525669700,1396599,3234.4,3238.2,3195.3,DCE.m2205,2022/1/7
2022/1/10,3230,3283,3206,3231,1035124,33562896800,1373919,3242.8,3235,3200.65,DCE.m2205,2022/1/10
2022/1/11,3241,3260,3221,3229,715204,23168420000,1364909,3238.6,3234.9,3205.9,DCE.m2205,2022/1/11
2022/1/12,3229,3259,3198,3247,895344,28905146500,1374316,3229.4,3233.9,3214.6,DCE.m2205,2022/1/12
2022/1/13,3233,3259,3210,3243,947940,30637294200,1368176,3235,3235.6,3220.55,DCE.m2205,2022/1/13
2022/1/14,3230,3232,3178,3186,906804,29035657300,1383324,3227.2,3230.8,3221.45,DCE.m2205,2022/1/14
2022/1/17,3195,3205,3144,3170,966711,30677648300,1387885,3215,3228.9,3221.25,DCE.m2205,2022/1/17
2022/1/18,3174,3176,3144,3156,639618,20221168500,1403804,3200.4,3219.5,3221.1,DCE.m2205,2022/1/18
2022/1/19,3143,3183,3121,3177,856746,27016694400,1388303,3186.4,3207.9,3222.3,DCE.m2205,2022/1/19
2022/1/20,3184,3247,3175,3243,1007446,32457304900,1351217,3186.4,3210.7,3225.5,DCE.m2205,2022/1/20
2022/1/21,3239,3281,3228,3270,941279,30662234300,1302675,3203.2,3215.2,3226.7,DCE.m2205,2022/1/21
2022/1/24,3278,3282,3244,3253,835944,27279482000,1313246,3219.8,3217.4,3226.2,DCE.m2205,2022/1/24
2022/1/25,3249,3253,3207,3248,762507,24663705200,1273850,3238.2,3219.3,3227.1,DCE.m2205,2022/1/25
2022/1/26,3242,3267,3235,3260,634022,20615235400,1263818,3254.8,3220.6,3227.25,DCE.m2205,2022/1/26
2022/1/27,3269,3379,3268,3338,1231088,40910467000,1285356,3273.8,3230.1,3232.85,DCE.m2205,2022/1/27
2022/1/28,3358,3393,3345,3378,863987,29094882400,1238750,3295.4,3249.3,3240.05,DCE.m2205,2022/1/28
2022/2/7,3634,3636,3614,3636,223073,8106879200,1227362,3372,3295.9,3262.4,DCE.m2205,2022/2/7
2022/2/8,3710,3754,3683,3695,1480421,54884110800,1301272,3461.4,3349.8,3284.65,DCE.m2205,2022/2/8
2022/2/9,3705,3764,3688,3748,1420390,52916662400,1427058,3559,3406.9,3307.4,DCE.m2205,2022/2/9
2022/2/10,3754,3843,3733,3814,1538508,58354708500,1472010,3654.2,3464,3337.35,DCE.m2205,2022/2/10
2022/2/11,3850,3903,3731,3745,1840992,69965804600,1441043,3727.6,3511.5,3363.35,DCE.m2205,2022/2/11
2022/2/14,3781,3794,3709,3724,1349966,50668861100,1408680,3745.2,3558.6,3388,DCE.m2205,2022/2/14
2022/2/15,3698,3723,3659,3687,1388308,51183248300,1361717,3743.6,3602.5,3410.9,DCE.m2205,2022/2/15
2022/2/16,3655,3727,3646,3708,1197867,44137281600,1360212,3735.6,3647.3,3433.95,DCE.m2205,2022/2/16
2022/2/17,3708,3778,3660,3769,1409416,52401623100,1376629,3726.6,3690.4,3460.25,DCE.m2205,2022/2/17
2022/2/18,3785,3824,3746,3781,1274942,48228107200,1351180,3733.8,3730.7,3490,DCE.m2205,2022/2/18
2022/2/21,3785,3817,3762,3803,1197690,45363033300,1351065,3749.6,3747.4,3521.65,DCE.m2205,2022/2/21
2022/2/22,3815,3885,3806,3877,1309910,50362861500,1402037,3787.6,3765.6,3557.7,DCE.m2205,2022/2/22
2022/2/23,3803,3953,3746,3906,2065057,79870590600,1407668,3827.2,3781.4,3594.15,DCE.m2205,2022/2/23
2022/2/24,3924,4107,3896,4062,1954776,77994077800,1390834,3885.8,3806.2,3635.1,DCE.m2205,2022/2/24
2022/2/25,4009,4067,3884,3918,2445430,97086312800,1314116,3913.2,3823.5,3667.5,DCE.m2205,2022/2/25
2022/2/28,3855,3899,3758,3862,2149034,82177501500,1232452,3925,3837.3,3697.95,DCE.m2205,2022/2/28
2022/3/1,3862,3955,3820,3911,1430739,55608869000,1215730,3931.8,3859.7,3731.1,DCE.m2205,2022/3/1
2022/3/2,3952,3996,3836,3903,1969304,77080921600,1203928,3931.2,3879.2,3763.25,DCE.m2205,2022/3/2
2022/3/3,3915,3929,3834,3895,1558260,60515275600,1182290,3897.8,3891.8,3791.1,DCE.m2205,2022/3/3
2022/3/4,3869,3958,3851,3902,1595387,62251911200,1201748,3894.6,3903.9,3817.3,DCE.m2205,2022/3/4
2022/3/7,3936,4096,3930,4089,1644052,65894978700,1249559,3940,3932.5,3839.95,DCE.m2205,2022/3/7
2022/3/8,4075,4194,4001,4153,2191347,89483058200,1276621,3988.4,3960.1,3862.85,DCE.m2205,2022/3/8
2022/3/9,4110,4266,4098,4222,1993209,83632153700,1248409,4052.2,3991.7,3886.55,DCE.m2205,2022/3/9
2022/3/10,4151,4192,4064,4130,1716504,70928400400,1161873,4099.2,3998.5,3902.35,DCE.m2205,2022/3/10
2022/3/11,4150,4232,4143,4186,1242858,52020262200,1181709,4156,4025.3,3924.4,DCE.m2205,2022/3/11
|