python_PyQt5运行股票研究python方法工具V1.0

news2024/12/23 11:00:45

写在前面:

1 在写研究方法过程中(例如:股票研究),很多方法根据数据的更新需要重复运行获取新的结果,本工具就是固化这些需要重复运行的代码,可以直接在工具中运行得到更新的结果。

2 本文是V1.0版本,提供运行python方法的框架,结果显示的控件后续根据研究过程的需要会陆续补充

界面展示:

 代码:

日志窗体

class LogShowWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.init_data()
        self.init_ui()
        pass
    def init_data(self):
        self.whole_data:List = []
        self.current_log: str = None
        pass
    def init_ui(self):
        self.setWindowTitle('执行日志')
        self.setMinimumWidth(600)
        self.setMinimumHeight(600)

        pre_btn = QtWidgets.QPushButton('上一个')
        pre_btn.clicked.connect(self.pre_btn_clicked)
        next_btn = QtWidgets.QPushButton('下一个')
        next_btn.clicked.connect(self.next_btn_clicked)

        layout_one = QtWidgets.QHBoxLayout()
        layout_one.addStretch(1)
        layout_one.addWidget(pre_btn)
        layout_one.addWidget(next_btn)
        layout_one.addStretch(1)

        self.log_textedit = QtWidgets.QTextEdit()

        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(layout_one)
        layout.addWidget(self.log_textedit)
        self.setLayout(layout)
        pass
    def set_data(self,data:List):
        self.whole_data.clear()
        self.whole_data = data

        self.current_log = self.whole_data[-1]
        self.fill_log()
        pass
    def pre_btn_clicked(self):
        cur_i = self.whole_data.index(self.current_log)
        if cur_i<=0:
            cur_i = len(self.whole_data)-1
        else:
            cur_i = cur_i -1
        self.current_log = self.whole_data[cur_i]
        self.fill_log()
        pass
    def next_btn_clicked(self):
        cur_i = self.whole_data.index(self.current_log)
        if cur_i >= len(self.whole_data) - 1:
            cur_i = 0
        else:
            cur_i = cur_i + 1
        self.current_log = self.whole_data[cur_i]
        self.fill_log()
        pass
    def fill_log(self):
        self.log_textedit.clear()
        self.log_textedit.setPlainText(self.current_log)
        pass
    pass

 代码执行控件(界面中蓝色框部分)

class ExcuteShowWidget(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.please_select_str: str = '-- 请选择 --'
        self.dir_path: str = ''
        self.log_list: List[str] = []
        self.log_widget: QtWidgets.QWidget = None
        pass
    def init_ui(self):
        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)

        log_btn = QtWidgets.QPushButton('日志')
        log_btn.clicked.connect(self.log_btn_clicked)

        self.code_combox = QtWidgets.QComboBox()
        self.code_combox.addItem(self.please_select_str)

        excute_code_btn = QtWidgets.QPushButton('执行')
        excute_code_btn.clicked.connect(self.excute_code_btn_clicked)
        self.excute_info_label = QtWidgets.QLabel()
        self.excute_info_label.setStyleSheet('QLabel{font-size:18px;color:red;font-weight:bold;}')

        layout_one = QtWidgets.QHBoxLayout()
        layout_one.addWidget(log_btn)
        layout_one.addWidget(self.code_combox)
        layout_one.addWidget(excute_code_btn)
        layout_one.addWidget(self.excute_info_label)

        self.scroll_layout = QtWidgets.QVBoxLayout()
        self.scroll_area = QtWidgets.QScrollArea()
        self.scroll_area.setWidgetResizable(True)

        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(layout_progress)
        layout.addLayout(layout_one)
        layout.addWidget(self.scroll_area)
        self.setLayout(layout)
        pass
    def register_event(self):
        self.signal_excute.connect(self.process_excute_event)
        pass
    def process_excute_event(self,data:Dict):
        mark_str = data['mark_str']
        status = data['status']
        if status == 'success':
            self.excute_info_label.setText(f'{mark_str} 执行成功')

            ret = data['ret']
            target_style = ret['target_style']
            if target_style == 'table':
                # 表格类型结果
                pre_map = {
                    'header':ret['target_header'],
                    'data':ret['target_data']
                }
                node_widget = TableNodeWidget()
                node_widget.set_data(pre_map)
                self.fill_scroll_area([node_widget])
                pass
            elif target_style == 'graph':
                # 图类型
                pre_map = {
                    'data':ret['target_data']
                }
                node_widget = GraphNodeWidget()
                node_widget.set_data(pre_map)
                self.fill_scroll_area([node_widget])
                pass

            self.thread_caculate = None
            self.progress_finished()
            pass
        else:
            self.excute_info_label.setText(f'{mark_str} 失败!失败!')
            now_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            log_str = f'{now_str}::{mark_str}::{data["msg"]}'
            self.log_list.append(log_str)

            self.thread_caculate = None
            self.progress_finished()
            pass
        pass

    def excute_code_btn_clicked(self):
        cur_txt = self.code_combox.currentText()
        if not cur_txt or cur_txt == self.please_select_str:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请选择要执行的代码',
                QtWidgets.QMessageBox.Yes
            )
            return
        py_file_path = self.dir_path+ os.path.sep + cur_txt + '.py'
        json_file_path = self.dir_path + os.path.sep + cur_txt + '.json'
        if not os.path.exists(py_file_path):
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '不存在该py文件',
                QtWidgets.QMessageBox.Yes
            )
            return
        if not os.path.exists(json_file_path):
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '不存在该json文件',
                QtWidgets.QMessageBox.Yes
            )
            return
        with open(py_file_path,'r',encoding='utf-8') as fr:
            py_code_str = fr.read()
        try:
            with open(json_file_path,'r',encoding='utf-8') as fr:
                json_obj = json.load(fr)
        except Exception as e:
            QtWidgets.QMessageBox.information(
                self,
                '报错',
                e.__str__(),
                QtWidgets.QMessageBox.Yes
            )
            return
        self.start_caculate_thread(cur_txt,{'py_code':py_code_str,'json_obj':json_obj})
        pass
    def set_target_combox_data(self,data:List,dir_path:str):
        self.dir_path = dir_path
        self.code_combox.clear()
        self.code_combox.addItem(self.please_select_str)
        self.code_combox.addItems(data)
        pass
    def log_btn_clicked(self):
        if not self.log_widget:
            self.log_widget = LogShowWidget()
        self.log_widget.set_data(self.log_list)
        self.log_widget.show()
        pass
    def fill_scroll_area(self,widget_list:List):
        while self.scroll_layout.count():
            item = self.scroll_layout.takeAt(0)
            widget = item.widget()
            if widget is not None:
                widget.deleteLater()
            pass
        sc_child_widget = self.scroll_area.takeWidget()
        if sc_child_widget is not None:
            sc_child_widget.deleteLater()
        for item in widget_list:
            self.scroll_layout.addWidget(item)
        one_sc_child_widget = QtWidgets.QWidget()
        one_sc_child_widget.setLayout(self.scroll_layout)
        self.scroll_area.setWidget(one_sc_child_widget)
        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]):
        py_code = data['py_code']
        json_obj = data['json_obj']
        try:
            namespace = {}
            fun_code = compile(py_code,'<string>','exec')
            exec(fun_code,namespace)
            ret = namespace['excute_code'](json_obj)

            res_map = {
                'mark_str':mark_str,
                'status':'success',
                'ret':ret
            }
            self.signal_excute.emit(res_map)
        except Exception as e:
            res_map = {
                'mark_str':mark_str,
                'status':'error',
                'msg':e.__str__()
            }
            self.signal_excute.emit(res_map)
        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.log_widget:
            self.log_widget.close()
        self.close()
        pass

主界面

class StockAnalysisMainWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.init_data()
        self.init_ui()
        pass
    def init_data(self):
        self.code_py_list:List = []
        pass
    def init_ui(self):
        self.setWindowTitle('PyQt5运行股票研究python方法工具V1.0')

        code_py_dir_btn = QtWidgets.QPushButton('代码py文件目录')
        code_py_dir_btn.clicked.connect(self.code_py_dir_btn_clicked)
        self.code_py_dir_lineedit = QtWidgets.QLineEdit()
        tip_label = QtWidgets.QLabel('提示:json文件为参数文件,同一业务json和py文件同名')

        layout_one = QtWidgets.QFormLayout()
        layout_one.addRow(code_py_dir_btn,self.code_py_dir_lineedit)
        layout_one.addWidget(tip_label)

        copy_one_widget_btn = QtWidgets.QPushButton('复制窗体')
        copy_one_widget_btn.clicked.connect(self.copy_one_widget_btn_clicked)

        layout_two = QtWidgets.QHBoxLayout()
        layout_two.addWidget(copy_one_widget_btn)
        layout_two.addStretch(1)

        layout_three = QtWidgets.QVBoxLayout()
        layout_three.addLayout(layout_one)
        layout_three.addLayout(layout_two)

        # 分界线 s
        h_line = QtWidgets.QFrame()
        h_line.setFrameShape(QtWidgets.QFrame.HLine)
        h_line.setFrameShadow(QtWidgets.QFrame.Sunken)
        # 分界线 e

        self.excute_show_widget = ExcuteShowWidget()

        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(layout_three)
        layout.addWidget(h_line)
        layout.addWidget(self.excute_show_widget)
        self.setLayout(layout)
        pass
    def code_py_dir_btn_clicked(self):
        path = QtWidgets.QFileDialog.getExistingDirectory(
            self,
            '打开py和json文件所在目录',
            '.'
        )
        if not path:
            return
        self.code_py_list.clear()
        py_file_list = os.listdir(path)
        for item in py_file_list:
            if item.endswith('.py'):
                self.code_py_list.append(item[0:-3])
        self.code_py_dir_lineedit.setText(path)
        self.excute_show_widget.set_target_combox_data(self.code_py_list,path)
        pass
    def copy_one_widget_btn_clicked(self):
        pass
    pass

执行代码:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/879156.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

并发编程系列-Semaphore

Semaphore&#xff0c;如今通常被翻译为"信号量"&#xff0c;过去也曾被翻译为"信号灯"&#xff0c;因为类似于现实生活中的红绿灯&#xff0c;车辆是否能通行取决于是否是绿灯。同样&#xff0c;在编程世界中&#xff0c;线程是否能执行取决于信号量是否允…

DevOps?自动化运维!

by: 雪月三十 DevOps流程图 DevOps介绍 命名 DevOps是Dev和Ops的结合 Dev&#xff08;developer开发&#xff09; Ops&#xff08;operation运维&#xff09; 矛盾 在企业中dev和ops是有一种天然的矛盾&#xff0c;dev要求的是快速迭代&#xff0c;给公司挖掘出商业的价值…

c++实现多进程执行多个shell脚本

一 参考 system()、exec()、fork()三个与进程有关的函数的比较 - 青儿哥哥 - 博客园 (cnblogs.com)https://www.cnblogs.com/qingergege/p/6601807.htmlfork执行流程分析_fork子进程和父进程执行顺序_cytf的博客-CSDN博客https://blog.csdn.net/qq_27420299/articl

IE实验-Qos教学实验

S1 diffserv domain boss //创建差分服务域 8021p-inbound 0 phb ef green //将外部优先级为0的流量&#xff0c;映射到内部优先级ef interface GigabitEthernet0/0/2 trust upstream boss //在接口下调用查分服务域 trust dscp override qos map-table dscp-dscp acl …

【新品发布】ChatWork企业知识库系统源码

系统简介 基于前后端分离架构以及Vue3、uni-app、ThinkPHP6.x、PostgreSQL、pgvector技术栈开发&#xff0c;包含PC端、H5端。 ChatWork支持问答式和文档式知识库&#xff0c;能够导入txt、doc、docx、pdf、md等多种格式文档。 导入数据完成向量化训练后&#xff0c;用户提问…

小米发布会:雷军成长故事与创新壮举,AI大模型技术引领未来,雷军探索之路之从创业波折到小米AI领航,成就高端化传奇!

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

基于物理场的动态模式分解(piDMD)研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

翻转二叉树

声明 该系列文章仅仅展示个人的解题思路和分析过程&#xff0c;并非一定是优质题解&#xff0c;重要的是通过分析和解决问题能让我们逐渐熟练和成长&#xff0c;从新手到大佬离不开一个磨练的过程&#xff0c;加油&#xff01; 原题链接 翻转二叉树备战技术面试&#xff1f;…

shell之正则表达式及三剑客grep命令

一、正则表达式概述 什么是正则表达式&#xff1f; 正则表达式是一种描述字符串匹配规则的重要工具 1、正则表达式定义: 正则表达式&#xff0c;又称正规表达式、常规表达式 使用字符串描述、匹配一系列符合某个规则的字符串 正则表达式 普通字符&#xff1a; 大小写字母…

LED全彩显示屏的前后维护

LED全彩显示屏的维护问题成为一个备受关注的难题。特别是对于采用镶嵌式或壁挂式安装的用户而言&#xff0c;检修和维护工作变得异常繁琐&#xff0c;仿佛一举一动都会影响整体运行。在这一背景下&#xff0c;LED全彩显示屏不仅需要符合严格的标准化要求&#xff0c;更需要具备…

【CHI】(三)网络层

网络层负责确定目标节点的NodeID。本章包含以下部分&#xff1a; 系统地址映射&#xff0c;SAM节点ID目标ID确定网络层flow示例 1. System address map 系统中每个Requester(包括RN和HN)必须有一个System Address Map(SAM)来决定一个request的target ID。SAM的范围可能只是简…

【Spring】深入探索 Spring AOP:概念、使用与实现原理解析

文章目录 前言一、初识 Spring AOP1.1 什么是 AOP1.2 什么是 Spring AOP 二、AOP 的核心概念2.1 切面&#xff08;Aspect&#xff09;2.2 切点&#xff08;Pointcut&#xff09;2.3 通知&#xff08;Advice&#xff09;2.4 连接点&#xff08;Join Point&#xff09; 三、Sprin…

Android复习(Android基础-四大组件)——Broadcast

1. 广播分类 广播的发送方式&#xff1a;标准广播、有序广播、粘性广播广播的类型&#xff1a;系统广播、本地广播 1.1 标准广播 完全异步&#xff0c;无序的广播发出后&#xff0c;所有的广播接收器几乎都会在同一时间收到消息。&#xff08;异步&#xff09;但是消息无法截…

科技云报道:算力之战,英伟达再度释放AI“炸弹”

科技云报道原创。 近日&#xff0c;在计算机图形学顶会SIGGRAPH 2023现场&#xff0c;英伟达再度释放深夜“炸弹”&#xff0c;大模型专用芯片迎来升级版本。 英伟达在会上发布了新一代GH200 Grace Hopper平台&#xff0c;该平台依托于搭载全球首款搭载HBM3e处理器的新型Grac…

Java并发之ReentrantLock

AQS AQS&#xff08;AbstractQueuedSynchronizer&#xff09;&#xff1a;抽象队列同步器&#xff0c;是一种用来构建锁和同步器的框架。在是JUC下一个重要的并发类&#xff0c;例如&#xff1a;ReentrantLock、Semaphore、CountDownLatch、LimitLatch等并发都是由AQS衍生出来…

ElementUI的MessageBox的按钮置灰且不可点击

// this.$confirmthis.$alert(这是一段内容, 标题名称, {confirmButtonText: 确定,confirmButtonCLass: confirmButton,beforeClose: (action,instance,done) > {if (action confirm) {return false} else {done()}});}.confirmButton {background: #ccc !important;cursor…

淘宝API接口的实时数据和缓存数据区别

电商API接口实时数据是指通过API接口获取到的与电商相关的实时数据。这些数据可以包括商品库存、订单状态、销售额、用户活跃度等信息。 通过电商API接口&#xff0c;可以实时获取到电商平台上的各种数据&#xff0c;这些数据可以帮助企业或开发者做出及时的决策和分析。例如&…

16.3.1 【Linux】程序的观察

既然程序这么重要&#xff0c;那么我们如何查阅系统上面正在运行当中的程序呢&#xff1f;利用静态的 ps 或者是动态的 top&#xff0c;还能以 pstree 来查阅程序树之间的关系。 ps &#xff1a;将某个时间点的程序运行情况撷取下来 仅观察自己的 bash 相关程序&#xff1a; p…

安达发APS|APS排产软件之计划甘特图

在当今全球化和竞争激烈的市场环境下&#xff0c;制造业企业面临着巨大的压力&#xff0c;如何在保证产品质量、降低成本以及满足客户需求的同时&#xff0c;提高生产效率和竞争力成为企业需要迫切解决的问题。在这个背景下&#xff0c;生产计划的制定和执行显得尤为重要。然而…

Spring Boot 集成 XXL-JOB 任务调度平台

一、下载xxl-job并使用。 二、将xxl-job集成到springboot里 一、 下载xxl-job并使用。 这一步没完成的请参考这个博客&#xff1a;http://t.csdn.cn/lsp4r 二、将xxl-job集成到springboot里 1、引入依赖 <dependency><groupId>org.springframework.boot</group…