python_PyQt5开发验证K线视觉想法工具V1.0

这篇具有很好参考价值的文章主要介绍了python_PyQt5开发验证K线视觉想法工具V1.0。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

写在前面:

使用过程:

代码:

导入的包、字符型横坐标、K线控件

 K线图控件

放置标记数据表格控件

输入并设置标记数据控件

 主界面

运行代码


写在前面:

开发这个工具的初衷,是基于在分析股票实践中想批量计算股票最近一次的上升振幅或下降振幅,视觉上,我们寻找波段低点和高点很容易,但如果用代码寻找波段低点与高点就颇为复杂,在实现代码过程中经常性快速验证代码得出的结果是否正确,这时如果能在K线上把计算出来的点直接标注出来就能一目了然。基于此,开发了这个工具辅助自己做视觉想法相关的代码设计,在我的理解,诸如波段的划分、股票是否在低位、股票是否在震荡这些都属于视觉感知的范畴,所以该工具就取名为“PyQt5开发验证K线视觉想法工具”。

V1.0版本,只做了单个验证里的点验证,即计算所得点在K线中进行标注

使用过程:

python_PyQt5开发验证K线视觉想法工具V1.0,python杂项,python

 1 选择要验证的日数据文件(数据来自优矿)

2 选择与计算过程相同的时间区间

3 显示K线

4 输入并设置标记数据:点击该按钮后会弹出输入框,输入待标记的数据

python_PyQt5开发验证K线视觉想法工具V1.0,python杂项,python

1 输入标题:这个标题的作用是便于使用者区分多个标记

2 选择规则:当前V1.0版本只有“点””,选择规则后,在下一行会提示要输入的数据格式,输入的数据格式要和规则对应,否则会出错

3 选择点的形状

4 选择点的颜色

5 输入待标记的数据

6 点确定,左侧设置的结果将插入右侧的表格

7 点击提交,设置的结果将传入主界面

python_PyQt5开发验证K线视觉想法工具V1.0,python杂项,python

在主界面中点击“执行”,待标记的点将在K线图中标记出来,从上图可以看到,设置的两个点序列在K线图中标记出来了。文章来源地址https://www.toymoban.com/news/detail-610315.html

代码:

导入的包、字符型横坐标、K线控件

import os,sys,json,datetime
import pandas as pd
from threading import Thread
from typing import Dict,List,Any
from PyQt5 import QtCore,QtWidgets,QtGui
from PyQt5.QtCore import Qt
import pyqtgraph as pg
pg.setConfigOption('background','w')
pg.setConfigOption('foreground','k')

class RotateAxisItem(pg.AxisItem):
    def drawPicture(self, p, axisSpec, tickSpecs, textSpecs):
        p.setRenderHint(p.Antialiasing,False)
        p.setRenderHint(p.TextAntialiasing,True)

        ## draw long line along axis
        pen,p1,p2 = axisSpec
        p.setPen(pen)
        p.drawLine(p1,p2)
        p.translate(0.5,0)  ## resolves some damn pixel ambiguity

        ## draw ticks
        for pen,p1,p2 in tickSpecs:
            p.setPen(pen)
            p.drawLine(p1,p2)

        ## draw all text
        # if self.tickFont is not None:
        #     p.setFont(self.tickFont)
        p.setPen(self.pen())
        for rect,flags,text in textSpecs:
            # this is the important part
            p.save()
            p.translate(rect.x(),rect.y())
            p.rotate(-30)
            p.drawText(int(-rect.width()),int(rect.height()),int(rect.width()),int(rect.height()),flags,text)
            # restoring the painter is *required*!!!
            p.restore()

class CandlestickItem(pg.GraphicsObject):
    def __init__(self, data):
        pg.GraphicsObject.__init__(self)
        self.data = data  ## data must have fields: time, open, close, min, max
        self.generatePicture()

    def generatePicture(self):
        ## pre-computing a QPicture object allows paint() to run much more quickly,
        ## rather than re-drawing the shapes every time.
        self.picture = QtGui.QPicture()
        p = QtGui.QPainter(self.picture)
        p.setPen(pg.mkPen('d'))
        w = (self.data[1][0] - self.data[0][0]) / 3.
        for (t, open, close, min, max) in self.data:
            p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
            if open < close:
                p.setBrush(pg.mkBrush('r'))
            else:
                p.setBrush(pg.mkBrush('g'))
            p.drawRect(QtCore.QRectF(t-w, open, w * 2, close - open))
        p.end()

    def paint(self, p, *args):
        p.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        ## boundingRect _must_ indicate the entire area that will be drawn on
        ## or else we will get artifacts and possibly crashing.
        ## (in this case, QPicture does all the work of computing the bouning rect for us)
        return QtCore.QRectF(self.picture.boundingRect())

class ExtendedComboBox(QtWidgets.QComboBox):
    def __init__(self, parent=None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        # add a filter model to filter matching items
        self.pFilterModel = QtCore.QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.pFilterModel.setSourceModel(self.model())

        # add a completer, which uses the filter model
        self.completer = QtWidgets.QCompleter(self.pFilterModel, self)
        # always show all (filtered) completions
        self.completer.setCompletionMode(QtWidgets.QCompleter.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)

        # connect signals
        self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.on_completer_activated)

    # on selection of an item from the completer, select the corresponding item from combobox
    def on_completer_activated(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
            self.activated[str].emit(self.itemText(index))

    # on model change, update the models of the filter and completer as well
    def setModel(self, model):
        super(ExtendedComboBox, self).setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)

    # on model column change, update the model column of the filter and completer as well
    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super(ExtendedComboBox, self).setModelColumn(column)

 K线图控件

class Graph_Widget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.init_data()
        self.init_ui()
        pass
    def init_data(self):
        self.whole_header = None
        self.whole_df = None
        self.whole_pd_header = None
        self.whole_xTick = None

        self.current_df = None
        self.current_data = None
        self.dur_len = 20

        self.add_items_list = []
        self.pointshape_map: Dict = {
            '圆': 'o',
            '三角形': 't',
            '星形': 'star',
            '正方形': 's',
            '菱形': 'd',
            '加号': '+',
            '向下箭头': 'arrow_down',
            '向左箭头': 'arrow_left',
            '向上箭头': 'arrow_up',
            '向右箭头': 'arrow_right'
        }
        pass
    def init_ui(self):
        self.duration_label = QtWidgets.QLabel('左边界~右边界')

        layout_top = QtWidgets.QHBoxLayout()
        layout_top.addWidget(self.duration_label)
        layout_top.addStretch(1)

        xax = RotateAxisItem(orientation='bottom')
        xax.setHeight(h=50)
        self.pw = pg.PlotWidget(axisItems={'bottom': xax})
        self.pw.setMouseEnabled(x=True, y=False)
        # self.pw.enableAutoRange(x=False,y=True)
        self.pw.setAutoVisible(x=False, y=True)

        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addWidget(self.pw)
        self.setLayout(layout)
        pass

    def first_setData(self,data:Dict):
        whole_header = data['whole_header']
        whole_df = data['whole_df']
        whole_pd_header = data['whole_pd_header']

        whole_xTick = whole_df['xTick'].values.tolist()

        self.whole_header = whole_header
        self.whole_df = whole_df
        self.whole_pd_header = whole_pd_header
        self.whole_xTick = whole_xTick

        self.current_df = self.whole_df.copy()
        self.caculate_and_show_data()
        pass

    def caculate_and_show_data(self):
        df = self.current_df.copy()
        df.reset_index(inplace=True)
        df['x'] = [i for i in range(len(df))]
        xTick = df['xTick'].values.tolist()
        xTick00 = []
        dur_num = int(len(xTick)/self.dur_len)
        if dur_num > 2:
            for i in range(0,len(xTick),dur_num):
                xTick00.append((i,xTick[i]))
            pass
        else:
            for i,item in enumerate(xTick):
                xTick00.append((i,item))
            pass
        candle_data = []
        for i,row in df.iterrows():
            candle_data.append((row['x'],row['open'],row['close'],row['lowest'],row['highest']))
        self.current_data = df.loc[:,self.whole_pd_header].values.tolist()
        y_min = df['lowest'].min()
        y_max = df['highest'].max()

        # 开始配置显示内容
        self.pw.clear()

        self.duration_label.setText(f"{xTick[0]}~{xTick[-1]}")

        xax = self.pw.getAxis('bottom')
        xax.setTicks([xTick00])

        self.vb = self.pw.getViewBox()
        self.vb.setLimits(yMin=y_min,yMax=y_max)

        candle_fixed_target = CandlestickItem(candle_data)
        self.pw.addItem(candle_fixed_target)

        self.vLine = pg.InfiniteLine(angle=90,movable=False)
        self.hLine = pg.InfiniteLine(angle=0,movable=False)
        self.label = pg.TextItem()

        self.pw.addItem(self.vLine,ignoreBounds=True)
        self.pw.addItem(self.hLine,ignoreBounds=True)
        self.pw.addItem(self.label,ignoreBounds=True)

        self.proxy = pg.SignalProxy(self.pw.scene().sigMouseMoved,rateLimit=60,slot=self.mouseMoved)
        self.pw.enableAutoRange()
        self.pw.setAutoVisible()
        pass

    def mouseMoved(self,evt):
        pos = evt[0]
        if self.pw.sceneBoundingRect().contains(pos):
            mousePoint = self.vb.mapSceneToView(pos)
            index = int(mousePoint.x())
            if index>=0 and index<len(self.current_data):
                target_data = self.current_data[index]
                html_str = ''
                for i,item in enumerate(self.whole_header):
                    html_str += f"<br/>{item}:{target_data[i]}"
                self.label.setHtml(html_str)
                self.label.setPos(mousePoint.x(),mousePoint.y())
                pass
            self.vLine.setPos(mousePoint.x())
            self.hLine.setPos(mousePoint.y())
            pass
        pass

    def add_marks(self,data:List):
        # 点,曲线,区间
        # '标题','规则','形状','颜色','数据'
        self.del_marks()
        for row in data:
            try:
                rule_str = row[1]
                shape_str = row[2]
                color_str = row[3]
                data_str = row[4]
                data_json = json.loads(data_str)
                if rule_str == '点':
                    for node in data_json:
                        targetItem = pg.TargetItem(
                            pos=node,
                            size=20,
                            symbol=self.pointshape_map[shape_str],
                            pen=color_str,
                            brush=color_str,
                            movable=False
                        )
                        self.pw.addItem(targetItem)
                        self.add_items_list.append(targetItem)
                    pass
                if rule_str == '连线':
                    for node in data_json:
                        targetItem = pg.PlotCurveItem(
                            x=node[0],
                            y=node[1],
                            pen=color_str,
                            symbol=self.pointshape_map[shape_str]
                        )
                        self.pw.addItem(targetItem)
                        self.add_items_list.append(targetItem)
                        pass
                    pass
                if rule_str == '区间':
                    for node in data_json:
                        targetItem = pg.LinearRegionItem(
                            values=node,
                            pen=color_str,
                            movable=False
                        )
                        self.pw.addItem(targetItem)
                        self.add_items_list.append(targetItem)
                        pass
                    pass
            except:
                continue
            pass
        pass
    def del_marks(self):
        if self.add_items_list:
            for item in self.add_items_list:
                self.pw.removeItem(item)
            self.add_items_list.clear()
        pass
    pass

放置标记数据表格控件

class MarkTableWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.init_data()
        self.init_ui()
        pass
    def init_data(self):
        self.header = ['标题','规则','形状','颜色','数据']
        pass
    def init_ui(self):
        self.table = QtWidgets.QTableWidget()
        self.table.setColumnCount(len(self.header))
        self.table.setHorizontalHeaderLabels(self.header)
        self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.table.setColumnHidden(len(self.header)-1,True)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.table)
        self.setLayout(layout)
        pass
    def set_data(self,data:List):
        # '标题','规则','形状','颜色','数据’
        self.table.clearContents()
        self.table.setRowCount(len(data))
        for r,row in enumerate(data):
            self.table.setItem(r,0,QtWidgets.QTableWidgetItem(row[0]))
            self.table.setItem(r,1,QtWidgets.QTableWidgetItem(row[1]))
            self.table.setItem(r,2,QtWidgets.QTableWidgetItem(row[2]))
            one_item = QtWidgets.QTableWidgetItem(row[3])
            one_item.setForeground(QtGui.QColor(row[3]))
            self.table.setItem(r, 3, one_item)
            self.table.setItem(r, 4, QtWidgets.QTableWidgetItem(row[4]))
            pass
        pass
    def insert_one_row(self,data:List):
        self.table.insertRow(0)
        self.table.setItem(0,0,QtWidgets.QTableWidgetItem(data[0]))
        self.table.setItem(0,1,QtWidgets.QTableWidgetItem(data[1]))
        self.table.setItem(0,2,QtWidgets.QTableWidgetItem(data[2]))
        color_item = QtWidgets.QTableWidgetItem(data[3])
        color_item.setForeground(QtGui.QColor(data[3]))
        self.table.setItem(0,3,color_item)
        self.table.setItem(0,4,QtWidgets.QTableWidgetItem(data[4]))
        pass
    def clear_table_contents(self):
        # 清空表内容
        self.table.clearContents()
        self.table.setRowCount(0)
        pass
    def del_selected_rows(self):
        # 删除选中项
        selected_items = self.table.selectedItems()
        if len(selected_items)<=0:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请选择要删除的行',
                QtWidgets.QMessageBox.Yes
            )
            return
        col_len = self.table.columnCount()
        row_index_list = []
        for i in range(0,len(selected_items)-1,col_len):
            row_index_list.append(selected_items[i].row())
        for i in row_index_list:
            self.table.removeRow(i)
        pass
    def res_name_list(self)->List[str]:
        # 返回标题列表
        row_count = self.table.rowCount()
        if row_count<=0:
            return []
        else:
            res_list = []
            for i in range(row_count):
                item = self.table.item(i,0)
                res_list.append(item.text())
            return res_list
        pass
    def res_data_content(self)->List:
        row_count = self.table.rowCount()
        if row_count<=0:
            return None
        res_data = []
        col_count = self.table.columnCount()
        for i in range(row_count):
            node = []
            for j in range(col_count):
                item_txt = self.table.item(i,j).text()
                node.append(item_txt)
                pass
            res_data.append(node)
            pass
        return res_data

输入并设置标记数据控件

class SettingMarksWidget(QtWidgets.QWidget):
    signal_excute = QtCore.pyqtSignal(object)
    def __init__(self):
        super().__init__()
        self.init_data()
        self.init_ui()
        pass
    def init_data(self):
        self.please_select_str: str = '-- 请选择 --'
        self.rule_map: Dict = {
            '点':'数据格式提示:[[x,y],[x,y],...]',
            '连线':'数据格式提示:[[x_list,y_list],...]',
            '区间':'数据格式提示:[[x0,x1],[x0,x1],...]'
        }
        self.pointshape_map: Dict = {
            '圆':'o',
            '三角形':'t',
            '星形':'star',
            '正方形':'s',
            '菱形':'d',
            '加号':'+',
            '向下箭头':'arrow_down',
            '向左箭头':'arrow_left',
            '向上箭头':'arrow_up',
            '向右箭头':'arrow_right'
        }
        pass
    def init_ui(self):
        self.setWindowTitle('输入并设置标记数据')
        self.setMinimumWidth(800)
        self.setMinimumHeight(600)

        submit_btn = QtWidgets.QPushButton('提交')
        submit_btn.clicked.connect(self.submit_btn_clicked)

        layout_top = QtWidgets.QHBoxLayout()
        layout_top.addStretch(1)
        layout_top.addWidget(submit_btn)

        h_line = QtWidgets.QFrame()
        h_line.setFrameShape(QtWidgets.QFrame.HLine)
        h_line.setFrameShadow(QtWidgets.QFrame.Sunken)

        layout_hline = QtWidgets.QVBoxLayout()
        layout_hline.addWidget(h_line)
        layout_hline.addSpacing(20)

        tip_label = QtWidgets.QLabel('标题')
        self.name_lineedit = QtWidgets.QLineEdit()
        tip_label2 = QtWidgets.QLabel('规则')
        self.rule_combox = QtWidgets.QComboBox()
        self.rule_combox.addItem(self.please_select_str)
        self.rule_combox.addItems(list(self.rule_map.keys()))
        self.rule_combox.currentTextChanged.connect(self.rule_combox_currentTextChanged)
        self.rule_label = QtWidgets.QLabel('数据格式提示')
        self.rule_label.setWordWrap(True)
        tip_label3 = QtWidgets.QLabel('点形状')
        self.pointshape_combox = QtWidgets.QComboBox()
        self.pointshape_combox.addItem(self.please_select_str)
        self.pointshape_combox.addItems(list(self.pointshape_map.keys()))
        color_btn = QtWidgets.QPushButton('颜色')
        color_btn.clicked.connect(self.color_btn_clicked)
        self.color_label = QtWidgets.QLabel()
        tip_label4 = QtWidgets.QLabel('数据')
        self.data_textedit = QtWidgets.QTextEdit()

        check_btn = QtWidgets.QPushButton('确定')
        check_btn.clicked.connect(self.check_btn_clicked)

        layout_left = QtWidgets.QFormLayout()
        layout_left.addRow(tip_label,self.name_lineedit)
        layout_left.addRow(tip_label2,self.rule_combox)
        layout_left.addRow(self.rule_label)
        layout_left.addRow(tip_label3,self.pointshape_combox)
        layout_left.addRow(color_btn,self.color_label)
        layout_left.addRow(tip_label4,self.data_textedit)
        layout_left.addRow(check_btn)

        self.results_table = MarkTableWidget()
        clear_table_btn = QtWidgets.QPushButton('清空')
        clear_table_btn.clicked.connect(self.clear_table_btn_clicked)
        del_table_btn = QtWidgets.QPushButton('删除选中项')
        del_table_btn.clicked.connect(self.del_table_btn_clicked)

        layout_table_btn = QtWidgets.QHBoxLayout()
        layout_table_btn.addWidget(clear_table_btn)
        layout_table_btn.addWidget(del_table_btn)

        layout_right = QtWidgets.QVBoxLayout()
        layout_right.addWidget(self.results_table)
        layout_right.addLayout(layout_table_btn)

        layout_bottom = QtWidgets.QHBoxLayout()
        layout_bottom.addLayout(layout_left)
        layout_bottom.addLayout(layout_right)

        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addLayout(layout_hline)
        layout.addLayout(layout_bottom)

        self.setLayout(layout)
        pass
    def rule_combox_currentTextChanged(self,txt:str):
        cur_txt = self.rule_combox.currentText()
        if not cur_txt or cur_txt == self.please_select_str:
            self.rule_label.setText('')
            return
        self.rule_label.setText(self.rule_map[cur_txt])
        if cur_txt == '区间':
            self.pointshape_combox.setCurrentText(self.please_select_str)
            self.pointshape_combox.setDisabled(True)
        else:
            self.pointshape_combox.setDisabled(False)
        pass
    def color_btn_clicked(self):
        res = QtWidgets.QColorDialog.getColor()
        self.color_label.setText(res.name())
        style_str = 'QLabel{font-weight:bold;color:'+res.name()+';}'
        self.color_label.setStyleSheet(style_str)
        pass
    def check_btn_clicked(self):
        cur_name = self.name_lineedit.text()
        now_name_list = self.results_table.res_name_list()
        if now_name_list:
            if cur_name in now_name_list:
                QtWidgets.QMessageBox.information(
                    self,
                    '提示',
                    '该标题已经设置过',
                    QtWidgets.QMessageBox.Yes
                )
                return
        rule_str = self.rule_combox.currentText()
        if not rule_str or rule_str==self.please_select_str:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请选择规则',
                QtWidgets.QMessageBox.Yes
            )
            return
        pointshape_str = ''
        if rule_str!='区间':
            pointshape_str = self.pointshape_combox.currentText()
            if not pointshape_str or pointshape_str==self.please_select_str:
                QtWidgets.QMessageBox.information(
                    self,
                    '提示',
                    '请选择点形状',
                    QtWidgets.QMessageBox.Yes
                )
                return
            pass
        color_str = self.color_label.text()
        if not color_str:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请选择颜色',
                QtWidgets.QMessageBox.Yes
            )
            return
        data_str = self.data_textedit.toPlainText()
        if not data_str:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请输入数据',
                QtWidgets.QMessageBox.Yes
            )
            return
        # ['标题','规则','形状','颜色','数据']
        res_data = [cur_name,rule_str,pointshape_str,color_str,data_str]
        self.results_table.insert_one_row(res_data)
        pass
    def clear_table_btn_clicked(self):
        self.results_table.clear_table_contents()
    def del_table_btn_clicked(self):
        self.results_table.del_selected_rows()
    def submit_btn_clicked(self):
        res_data = self.results_table.res_data_content()
        if not res_data:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '没有设置相关项,提交的内容为空',
                QtWidgets.QMessageBox.Yes
            )
            return
        self.signal_excute.emit(res_data)
        self.close()
        pass

 主界面

class EyeCheckMainWidget(QtWidgets.QWidget):
    signal_excute = QtCore.pyqtSignal(object)
    def __init__(self):
        super().__init__()

        self.thread_caculate: Thread = None

        self.init_data()
        self.init_ui()
        self.register_event()
        self.progress_init()
        pass
    def init_data(self):
        self.single_settingMark_widget: QtWidgets.QWidget = None
        self.target_column_list: List[str] = ['xTick', 'open', 'close', 'highest', 'lowest']
        pass
    def init_ui(self):
        self.setWindowTitle('验证K线视觉想法工具')

        self.caculate_progress = QtWidgets.QProgressBar()
        self.caculate_status_label = QtWidgets.QLabel()

        layout_progress = QtWidgets.QHBoxLayout()
        layout_progress.addWidget(self.caculate_progress)
        layout_progress.addWidget(self.caculate_status_label)

        groupbox_one = QtWidgets.QGroupBox('选择',self)

        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
        groupbox_one.setSizePolicy(sizePolicy)

        self.radio_group = QtWidgets.QButtonGroup()
        single_radio_btn = QtWidgets.QRadioButton('单个验证')
        single_radio_btn.setChecked(True)
        batch_radio_btn = QtWidgets.QRadioButton('批量验证')
        self.radio_group.addButton(single_radio_btn,1)
        self.radio_group.addButton(batch_radio_btn,2)
        self.radio_group.buttonClicked.connect(self.radio_group_buttonClicked)

        layout_one = QtWidgets.QVBoxLayout()
        layout_one.addWidget(single_radio_btn)
        layout_one.addWidget(batch_radio_btn)
        layout_one.addStretch(1)

        groupbox_one.setLayout(layout_one)

        self.stack_one = QtWidgets.QWidget()
        self.stack_two = QtWidgets.QWidget()

        self.fill_stack_widget_one()
        self.fill_stack_widget_two()

        self.stack_widget = QtWidgets.QStackedWidget()
        self.stack_widget.setSizePolicy(sizePolicy)
        self.stack_widget.addWidget(self.stack_one)
        self.stack_widget.addWidget(self.stack_two)

        layout_two = QtWidgets.QHBoxLayout()
        layout_two.addWidget(groupbox_one,1)
        layout_two.addWidget(self.stack_widget,4)

        groupbox_two = QtWidgets.QGroupBox('选择与待验证数据相同区间', self)
        tip_label = QtWidgets.QLabel('区间')
        self.left_point = QtWidgets.QDateEdit()
        self.left_point.setDisplayFormat('yyyy-MM-dd')
        self.left_point.setCalendarPopup(True)
        self.right_point = QtWidgets.QDateEdit()
        self.right_point.setDisplayFormat('yyyy-MM-dd')
        self.right_point.setCalendarPopup(True)
        self.right_point.setDate(QtCore.QDate.currentDate())
        tip_label2 = QtWidgets.QLabel('请先设置好对应区间')
        tip_label2.setStyleSheet('QLabel{color:red;}')

        layout_three = QtWidgets.QHBoxLayout()
        layout_three.addWidget(tip_label)
        layout_three.addWidget(self.left_point)
        layout_three.addWidget(self.right_point)
        layout_three.addWidget(tip_label2)
        layout_three.addStretch(1)

        groupbox_two.setLayout(layout_three)

        self.graph_title_label = QtWidgets.QLabel('图标题')
        self.graph_title_label.setAlignment(Qt.AlignCenter)
        self.graph_title_label.setStyleSheet('QLabel{font-size:18px;font-weight:bold;}')
        self.graph_widget = Graph_Widget()

        layout_four = QtWidgets.QVBoxLayout()
        layout_four.addWidget(self.graph_title_label)
        layout_four.addWidget(self.graph_widget)

        tip_label3 = QtWidgets.QLabel('标记详情列表')
        self.mark_table = MarkTableWidget()

        layout_five = QtWidgets.QVBoxLayout()
        layout_five.addWidget(tip_label3)
        layout_five.addWidget(self.mark_table)

        layout_six = QtWidgets.QHBoxLayout()
        layout_six.addLayout(layout_four,4)
        layout_six.addLayout(layout_five,1)

        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(layout_progress)
        layout.addLayout(layout_two)
        layout.addWidget(groupbox_two)
        layout.addLayout(layout_six)
        self.setLayout(layout)
        pass
    def register_event(self):
        self.signal_excute.connect(self.process_excute_event)
        pass
    def process_excute_event(self,data:Dict):
        pass
    def fill_stack_widget_one(self):
        single_choice_one_daily_file_path = QtWidgets.QPushButton('选择股票日数据文件')
        single_choice_one_daily_file_path.clicked.connect(self.single_choice_one_daily_file_path_clicked)
        self.single_choice_one_daily_file_lineedit = QtWidgets.QLineEdit()
        single_show_k_btn = QtWidgets.QPushButton('显示K线')
        single_show_k_btn.clicked.connect(self.single_show_k_btn_clicked)
        single_input_marks_btn = QtWidgets.QPushButton('输入并设置标记数据')
        single_input_marks_btn.clicked.connect(self.single_input_marks_btn_clicked)
        mark_excute_btn = QtWidgets.QPushButton('执行')
        mark_excute_btn.clicked.connect(self.mark_excute_btn_clicked)

        single_layout_one = QtWidgets.QHBoxLayout()
        single_layout_one.addWidget(single_choice_one_daily_file_path)
        single_layout_one.addWidget(self.single_choice_one_daily_file_lineedit)
        single_layout_one.addWidget(single_show_k_btn)

        single_layout_two = QtWidgets.QHBoxLayout()
        single_layout_two.addWidget(single_input_marks_btn)
        single_layout_two.addWidget(mark_excute_btn)

        single_layout = QtWidgets.QVBoxLayout()
        single_layout.addLayout(single_layout_one)
        single_layout.addLayout(single_layout_two)
        single_layout.addStretch(1)
        self.stack_one.setLayout(single_layout)
        pass
    def fill_stack_widget_two(self):
        batch_layout = QtWidgets.QVBoxLayout()
        self.stack_two.setLayout(batch_layout)
        pass
    def radio_group_buttonClicked(self,obj):
        radio_id = self.radio_group.checkedId()
        self.stack_widget.setCurrentIndex(radio_id - 1)
        pass
    def single_choice_one_daily_file_path_clicked(self):
        path,_ = QtWidgets.QFileDialog.getOpenFileName(
            self,
            '选择股票日数据文件',
            '.',
            'CSV(*.csv)'
        )
        if not path:
            return
        self.single_choice_one_daily_file_lineedit.setText(path)
        pass
    def single_show_k_btn_clicked(self):
        daily_file = self.single_choice_one_daily_file_lineedit.text()
        if not daily_file or not os.path.exists(daily_file):
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请选择要验证的日数据',
                QtWidgets.QMessageBox.Yes
            )
            return
        file_name = os.path.basename(daily_file)
        left_point = self.left_point.date().toString('yyyy-MM-dd')
        right_point = self.right_point.date().toString('yyyy-MM-dd')
        left_datetime = datetime.datetime.strptime(left_point,'%Y-%m-%d')
        right_datetime = datetime.datetime.strptime(right_point,'%Y-%m-%d')
        if left_datetime >= right_datetime:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请选择时间区间',
                QtWidgets.QMessageBox.Yes
            )
            return
        df = pd.read_csv(daily_file,encoding='utf-8')
        df = df.loc[df['openPrice']>0].copy()
        df['o_date'] = pd.to_datetime(df['tradeDate'])
        df = df.loc[(df['o_date']>=left_point) & (df['o_date']<=right_point)].copy()
        df['open'] = df['openPrice']*df['accumAdjFactor']
        df['close'] = df['closePrice']*df['accumAdjFactor']
        df['highest'] = df['highestPrice']*df['accumAdjFactor']
        df['lowest'] = df['lowestPrice']*df['accumAdjFactor']
        df['xTick'] = df['tradeDate']

        k_data = {
            'whole_df':df,
            'whole_header':['日期','开盘','收盘','最高','最低'],
            'whole_pd_header': self.target_column_list
        }
        self.graph_widget.first_setData(k_data)
        self.graph_title_label.setText(file_name)
        pass
    def single_input_marks_btn_clicked(self):
        if not self.single_settingMark_widget:
            self.single_settingMark_widget = SettingMarksWidget()
            self.single_settingMark_widget.signal_excute.connect(self.single_settingMark_widget_signal_emit)
        self.single_settingMark_widget.show()
        pass
    def single_settingMark_widget_signal_emit(self,data:List):
        if not data:
            return
        self.mark_table.set_data(data)
        pass
    def mark_excute_btn_clicked(self):
        mark_data = self.mark_table.res_data_content()
        if mark_data:
            self.graph_widget.add_marks(mark_data)
        pass
    def start_caculate_thread(self,mark_str:str,data:Dict[str,Any]):
        if self.thread_caculate:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '线程正在执行任务,请稍后。。。',
                QtWidgets.QMessageBox.Yes
            )
            return
        self.thread_caculate = Thread(
            target=self.running_caculate_thread,
            args=(
                mark_str, data,
            )
        )
        self.thread_caculate.start()
        self.progress_busy()
        pass
    def running_caculate_thread(self,mark_str:str,data:Dict[str,Any]):
        pass
    def progress_init(self) -> None:
        self.caculate_progress.setValue(0)
        self.caculate_status_label.setText('无任务')
    def progress_busy(self) -> None:
        self.caculate_progress.setRange(0, 0)
        self.caculate_status_label.setText('正在执行')
    def progress_finished(self) -> None:
        self.caculate_progress.setRange(0, 100)
        self.caculate_progress.setValue(100)
        self.caculate_status_label.setText('执行完毕')
        pass
    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        if self.single_settingMark_widget:
            self.single_settingMark_widget.close()
        self.close()
        pass

运行代码

if __name__ == '__main__':
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
    app = QtWidgets.QApplication(sys.argv)
    main_window = EyeCheckMainWidget()
    main_window.showMaximized()
    app.exec()
    pass

到了这里,关于python_PyQt5开发验证K线视觉想法工具V1.0的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于PyQt5的图形化界面开发——自制ssh工具

    本节我们使用PyQt5来制作一个简单的ssh小工具。 操作系统:Windows10 专业版 开发环境:Pycahrm Comunity 2022.3 Python解释器版本:Python3.8 第三方库: PyQt5 和 paramiko 本节需要安装第三方库PyQt5和paramiko,如果你并不熟悉第三方库的安装,你可以参考以下文章来学习: Python第三方库安装

    2024年02月06日
    浏览(43)
  • 视觉惯性组合导航技术最新综述:应用优势、主要类别及一种视觉惯性组合导航无人系统开发验证平台分享

    导读: 随着无人机、无人车以及移动机器人的井喷式发展,导航技术成为了制约无人平台广泛应用的瓶颈技术之一。在应用需求的牵引下, 视觉惯性组合导航技术,特别是视觉与微惯性传感器的组合, 逐渐发展成为当前自主导航及机器人领域的研究热点。 Part1视觉惯性组合导

    2023年04月08日
    浏览(40)
  • 竞赛项目 深度学习验证码识别 - 机器视觉 python opencv

    🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习验证码识别 - 机器视觉 python opencv 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.

    2024年02月13日
    浏览(72)
  • python GUI工具之PyQt5模块,pyCharm 配置PyQt5可视化窗口

    https://doc.qt.io/qt-5/qtwidgets-module.html https://doc.qt.io/qt-5/qt.html#AlignmentFlag-enum 一、简介 PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件。 PyQt5是由一系列Python模块组成,有超过6

    2024年02月11日
    浏览(54)
  • whisper实践--基于whisper+pyqt5开发的语音识别翻译生成字幕工具

    大家新年快乐,事业生活蒸蒸日上,解封的第一个年,想必大家都回家过年,好好陪陪家人了吧,这篇文章也是我在老家码的,还记得上篇我带大家基本了解了whisper,相信大家对whisper是什么,怎么安装whisper,以及使用都有了一个认识,这次作为新年第一篇文章,我将介绍一

    2024年02月01日
    浏览(45)
  • 【Unity 框架】QFramework v1.0 使用指南 工具篇:13. 其他事件工具 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏

    QFramework 除了支持了 TypeEventSystem、EasyEvent 还支持了 EnumEventSystem、StringEventSystem。 EnumEventSystem 前身是 老版本 QFramework 的 QEventSystem StringEventSystem 的前身是,老版本的 MsgDispatcher TypeEventSystem: 事件体定义简洁 比较适合用于设计框架 支持 struct 获得较好内存性能 使用反射,CPU

    2023年04月17日
    浏览(61)
  • Python——Pyqt5的数据可视化小工具(完整代码)

    作业要求:【都已经打包放网上了,有缘人需要就自取】 一份报告书 (在全球变暖背景下碳中和对各国的二氧化碳排放量的影响项目报告书) 一份代码 作业包: python数据可视化小工具.zip - 蓝奏云 大一的时候,当时的python作业,交完作业后,忘记记录了(难受.jpg) 现在大

    2024年02月02日
    浏览(51)
  • 02、Pycharm中配置PyQt/PySide开发工具Qt Designer、PyUIC、PyRcc(详细)

    上一篇文章: 01、Pyqt/PySide6简介及安装方法 PySide6、PyQt5 都是基于Qt 库。Qt库里面有非常强大的图形界面开发库,但是Qt库是C++语言开发的,PySide2、PySide6、PyQt5可以让我们通过Python语言使用Qt https://blog.csdn.net/python_sy/article/details/127425142 目录 前言 一、Qt Designer、PyUic、PyRcc是什么

    2023年04月14日
    浏览(48)
  • 【Python游戏开发】超级玛丽v1.0——《跟老吕学Python编程》附录资料

    在一个背景上,超级玛丽通过 空格键 跳跃,越过水管和飞弹 本次系统的软件开发及运行环境具体如下: 操作系统: Windows 10(WindowsXP以上系统均可运行) Python版本:Python 3.12.2(凡是3.0及以上版本均可运行) 开发工具:PyCharm(老吕比较习惯PyCharm和VS开发环境) 第三方模块

    2024年04月11日
    浏览(45)
  • Python桌面应用开发之PyQt

    Tkinter:优势是免安装、相对简单,缺点是功能少,无界面设计工具。 PyQT:使用率高,功能最为强大,代码可维护性和易读性高。 WxPython:介于Tkinter和PyQT之间,相当于压缩版QT。 总结:三种框架各有优劣,有时间可以全部学习,并不复杂。如果只选一种,这里推荐使用最主

    2024年02月13日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包