PyQt5_股票技术图形查看工具

技术图形,诸如头肩顶、头肩底、W底、圆底等,代码逻辑实现后,要使用股票数据验证,这类主要依靠视觉判断的技术图形,获得的结果能及时在图表中展示出来,对代码的开发、校验、结果的准确度确认等能起到事半功倍的效果,本工具就是基于此需求所做的开发。

本文以“头肩底”为例进行讲解

目录

效果

计算技术图形策略代码

工具代码

工具使用

数据


效果

PyQt5_股票技术图形查看工具_第1张图片

计算技术图形策略代码

前置说明:

1. 必须以“excute_strategy”为方法名

2. 一个参数,股票日数据文件路径

3. 策略代码写完后,命名,保存在“shape_recognition_strategy”文件夹中,‘shape_recognition_strategy’文件夹的创建位置在下文中会介绍

4. 将策略文件名写入主程序类StrategeMainWidget的self.strategyname_code_map对应的兼职对中

def excute_strategy(daily_file_path):
    '''
    名称:头肩底
    处理过程:结合图形说明,从最近的日期往前找
    1. (1)号位为起点位
    2. 从(1)号位开始找最近最小值设为(2)号位
    3. 找到(2)号位后,找最近最大值设为(3)号位
    4. 判断(3)号位是否小于(1)号位:
    5. (3)号位小于(1)号位,找最近最小值设为(4)号位
    6. (3)号位大于等于(1)号位,将(3)号位设为(1)号位,从第二步开始,直到找到(4)号位
    7. 找到(4)号位后,判断(4)号位是否小于(2)号位:
    8. (4)号位小于(2)号位,找最近最大值设为(5)号位
    9. (4)号位大于等于(2)号位,将(3)号位设为(1)号位,从第二步开始,直到找到(5)号位
    10. 找到(5)号位后,判断(5)号位是否和(3)号位在相近的水平位置:
    11. (5)号位和(3)号位在相近的水平位置,找最近最小值设为(6)号位
    12. 找到(6)号位后,判断(6)号位是否大于(4)号位:
    13. (6)号位大于(4)号位,找最近最大值设为(7)号位
    14. (6)号位小于等于(4)号位,将(5)号位设为(1)号位,从第二步开始,直到找到(7)号位
    15. 找到(7)号位后,判断(7)号位是否大于(5)号位:
    16. (7)号位大于(5)号位,找图完毕。
    17. (7)号位小于等于(5)号位,将(5)号位设为(1)号位,从第二步开始,直到完毕。

    前置条件:计算时间区间 2021-01-01 到 2022-01-01
    :param daily_file_path: 股票日数据文件路径
    :return:
    '''
    import pandas as pd
    import os

    start_date_str = '2021-01-01'
    end_date_str = '2022-01-01'
    df = pd.read_csv(daily_file_path,encoding='utf-8')
    # 删除停牌的数据
    df = df.loc[df['openPrice'] > 0].copy()
    df['o_date'] = df['tradeDate']
    df['o_date'] = pd.to_datetime(df['o_date'])
    df = df.loc[(df['o_date'] >= start_date_str) & (df['o_date']<=end_date_str)].copy()
    # 保存未复权收盘价数据
    df['close'] = df['closePrice']
    # 计算前复权数据
    df['openPrice'] = df['openPrice'] * df['accumAdjFactor']
    df['closePrice'] = df['closePrice'] * df['accumAdjFactor']
    df['highestPrice'] = df['highestPrice'] * df['accumAdjFactor']
    df['lowestPrice'] = df['lowestPrice'] * df['accumAdjFactor']

    df.reset_index(inplace=True)
    df['i_row'] = [i for i in range(len(df))]
    # 开始计算
    one_point = None
    one_val = None
    two_point = None
    two_val = None
    three_point = None
    three_val = None
    four_point = None
    four_val = None
    five_point = None
    five_val = None
    six_point = None
    six_val = None
    seven_point = None
    seven_val = None

    gap_pct = 0.005
    for i in range(len(df)-1,0,-1):
        if seven_point:
            if six_point-seven_point < 5 or seven_val < five_val:
                one_point = seven_point
                one_val = seven_val
                two_point = None
                two_val = None
                three_point = None
                three_val = None
                four_point = None
                four_val = None
                five_point = None
                five_val = None
                six_point = None
                six_val = None
                seven_point = None
                seven_val = None
            else:
                break
        if six_point:
            if five_point - six_point < 3 or six_val < four_val:
                one_point = five_point
                one_val = five_val
                two_point = six_point
                two_val = six_val
                three_point = None
                three_val = None
                four_point = None
                four_val = None
                five_point = None
                five_val = None
                six_point = None
                six_val = None
                seven_point = None
                seven_val = None
                pass
        if five_point:
            if four_point - five_point < 3 or five_val*(1+gap_pct)<=three_val or five_val*(1-gap_pct)>=three_val:
                one_point = five_point
                one_val = five_val
                two_point = None
                two_val = None
                three_point = None
                three_val = None
                four_point = None
                four_val = None
                five_point = None
                five_val = None
                six_point = None
                six_val = None
                seven_point = None
                seven_val = None
                pass
        if four_point:
            if three_point - four_point < 3 or four_val > two_val:
                one_point = three_point
                one_val = three_val
                two_point = four_point
                two_val = four_val
                three_point = None
                three_val = None
                four_point = None
                four_val = None
                five_point = None
                five_val = None
                six_point = None
                six_val = None
                seven_point = None
                seven_val = None
                pass
        if three_point:
            if two_point - three_point < 3 or three_val > one_val:
                one_point = three_point
                one_val = three_val
                two_point = None
                two_val = None
                three_point = None
                three_val = None
                four_point = None
                four_val = None
                five_point = None
                five_val = None
                six_point = None
                six_val = None
                seven_point = None
                seven_val = None
            pass
        if two_point:
            if one_point - two_point < 5:
                one_point = None
                one_val = None
                two_point = None
                two_val = None
                three_point = None
                three_val = None
                four_point = None
                four_val = None
                five_point = None
                five_val = None
                six_point = None
                six_val = None
                seven_point = None
                seven_val = None

        if one_point is None:
            if one_val is None:
                one_val = df.iloc[i]['highestPrice']
            else:
                if one_val < df.iloc[i]['highestPrice']:
                    one_val = df.iloc[i]['highestPrice']
                else:
                    if one_val*(1-gap_pct) <= df.iloc[i]['highestPrice']:
                        pass
                    else:
                        one_point = i + 1
                        two_val = df.iloc[i]['lowestPrice']
        if one_point and two_point is None:
            if two_val is None:
                two_val = df.iloc[i]['lowestPrice']
            else:
                if two_val > df.iloc[i]['lowestPrice']:
                    two_val = df.iloc[i]['lowestPrice']
                else:
                    if two_val*(1+gap_pct) >= df.iloc[i]['lowestPrice']:
                        pass
                    else:
                        two_point = i+1
                        three_val = df.iloc[i]['highestPrice']
        if one_point and two_point and three_point is None:
            if three_val is None:
                three_val = df.iloc[i]['highestPrice']
            else:
                if three_val < df.iloc[i]['highestPrice']:
                    three_val = df.iloc[i]['highestPrice']
                else:
                    if three_val*(1-gap_pct) <= df.iloc[i]['highestPrice']:
                        pass
                    else:
                        three_point = i+1
                        four_val = df.iloc[i]['lowestPrice']
        if one_point and two_point and three_point and four_point is None:
            if four_val is None:
                four_val = df.iloc[i]['lowestPrice']
            else:
                if four_val > df.iloc[i]['lowestPrice']:
                    four_val = df.iloc[i]['lowestPrice']
                else:
                    if four_val*(1+gap_pct) >= df.iloc[i]['lowestPrice']:
                        pass
                    else:
                        four_point = i + 1
                        five_val = df.iloc[i]['highestPrice']
        if one_point and two_point and three_point and four_point and five_point is None:
            if five_val is None:
                five_val = df.iloc[i]['highestPrice']
            else:
                if five_val < df.iloc[i]['highestPrice']:
                    five_val = df.iloc[i]['highestPrice']
                else:
                    if five_val*(1-gap_pct) <= df.iloc[i]['highestPrice']:
                        pass
                    else:
                        five_point = i + 1
                        six_val = df.iloc[i]['lowestPrice']
        if one_point and two_point and three_point and four_point and five_point and six_point is None:
            if six_val is None:
                six_val = df.iloc[i]['lowestPrice']
            else:
                if six_val > df.iloc[i]['lowestPrice']:
                    six_val = df.iloc[i]['lowestPrice']
                else:
                    if six_val*(1+gap_pct) >= df.iloc[i]['lowestPrice']:
                        pass
                    else:
                        six_point = i+1
                        seven_val = df.iloc[i]['highestPrice']
        if one_point and two_point and three_point and four_point and five_point and six_point and seven_point is None:
            if seven_val is None:
                seven_val = df.iloc[i]['highestPrice']
            else:
                if seven_val < df.iloc[i]['highestPrice']:
                    seven_val = df.iloc[i]['highestPrice']
                else:
                    if seven_val*(1-gap_pct) <= df.iloc[i]['highestPrice']:
                        pass
                    else:
                        seven_point = i + 1
        pass


    res_duration = []
    res_line = []
    res_table = []
    if one_point and two_point and three_point and four_point and five_point and six_point and seven_point:
        res_duration.append([seven_point,one_point])
        res_line.append([(five_point,five_val),(three_point,three_val)])
        res_table = [
            ['1',df.iloc[one_point]['tradeDate'],one_val],
            ['2',df.iloc[two_point]['tradeDate'],two_val],
            ['3',df.iloc[three_point]['tradeDate'],three_val],
            ['4',df.iloc[four_point]['tradeDate'],four_val],
            ['5',df.iloc[five_point]['tradeDate'],five_val],
            ['6',df.iloc[six_point]['tradeDate'],six_val],
            ['7',df.iloc[seven_point]['tradeDate'],seven_val]
        ]
        pass

    file_name = os.path.basename(daily_file_path)
    title_str = file_name.split('.')[0]

    line_data = {
        'title_str':title_str,
        'whole_header':['日期','收','开','高','低'],
        'whole_df':df,
        'whole_pd_header':['tradeDate','closePrice','openPrice','highestPrice','lowestPrice'],
        'start_date_str':start_date_str,
        'end_date_str':end_date_str,
        'res_duration':res_duration,
        'res_line':res_line,
        'res_table':res_table,
        'temp':len(res_duration)
    }
    return line_data

工具代码

导入需要的包

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

pygtgraph 日期横坐标控件、蜡烛图控件、分页表格控件,请查看该博文。

 K线与结果显示控件

class PyQtGraphKWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.init_data()
        self.init_ui()
    def init_data(self):
        # https://www.sioe.cn/yingyong/yanse-rgb-16/
        # self.color_line = (30, 144, 255)
        self.color_line = (255, 255, 0)
        # 0 幽灵的白色; 1 纯黄; 2 紫红色; 3 纯绿; 4 道奇蓝
        self.color_list = [(248, 248, 255), (255, 255, 0), (255, 0, 255), (0, 128, 0), (30, 144, 255)]
        self.main_fixed_target_list = []  # 主体固定曲线,不能被删除
        self.whole_df = None
        self.whole_header = None
        self.whole_pd_header = None
        self.current_whole_data = None
        self.current_whole_df = None
        self.res_duration = None
        self.res_line = None
        self.res_table = None
        pass
    def init_ui(self):
        self.whole_duration_label = QtWidgets.QLabel('左边界~右边界')

        self.title_label = QtWidgets.QLabel('执行过程查看')
        self.title_label.setAlignment(Qt.AlignCenter)
        self.title_label.setStyleSheet('QLabel{font-size:18px;font-weight:bold}')

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

        layout_right = QtWidgets.QVBoxLayout()
        layout_right.addWidget(self.title_label)
        layout_right.addWidget(self.whole_duration_label)
        layout_right.addWidget(self.pw)
        self.setLayout(layout_right)
        pass

    def set_data(self, data: Dict[str, Any]):
        title_str = data['title_str']
        whole_header = data['whole_header']
        whole_df = data['whole_df']
        whole_pd_header = data['whole_pd_header']
        res_duration = data['res_duration']
        res_line = data['res_line']
        res_table = data['res_table']

        self.whole_header = whole_header
        self.whole_df = whole_df
        self.whole_pd_header = whole_pd_header
        self.res_duration = res_duration
        self.res_line = res_line
        self.res_table = res_table

        self.title_label.setText(title_str)
        self.whole_duration_label.setText(f"{self.whole_df.iloc[0]['tradeDate']}~{self.whole_df.iloc[-1]['tradeDate']}")

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

    def caculate_and_show_data(self):
        df = self.current_whole_df.copy()
        df.reset_index(inplace=True)
        df['i_count'] = [i for i in range(len(df))]
        tradeDate_list = df['tradeDate'].values.tolist()
        x = range(len(df))
        xTick_show = []
        x_dur = math.ceil(len(df) / 20)
        for i in range(0, len(df), x_dur):
            xTick_show.append((i, tradeDate_list[i]))
        if len(df) % 20 != 0:
            xTick_show.append((len(df) - 1, tradeDate_list[-1]))
        candle_data = []
        for i, row in df.iterrows():
            candle_data.append(
                (row['i_count'], row['openPrice'], row['closePrice'], row['lowestPrice'], row['highestPrice']))

        self.current_whole_data = df.loc[:, self.whole_pd_header].values.tolist()
        # 开始配置显示的内容
        self.pw.clear()

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

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

        # 标记技术图形 start
        if len(self.res_duration)>0:
            for item in self.res_duration:
                signal_fiexed_target = pg.LinearRegionItem([item[0], item[1]],
                                                           movable=False, brush=(
                        self.color_line[0], self.color_line[1], self.color_line[2], 50))
                self.pw.addItem(signal_fiexed_target)
            pass
        if len(self.res_line)>0:
            for item in self.res_line:
                angle = math.atan2((item[1][1] - item[0][1]),
                                   (item[1][0] - item[0][0]))
                theta = angle * (180 / math.pi)
                signal_fiexed_target = pg.InfiniteLine(pos=item[0], movable=False, angle=theta,
                                                       pen=pg.mkPen({'color': self.color_line, 'width': 1}))
                self.pw.addItem(signal_fiexed_target)
            pass
        # 标记技术图形 end


        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.vb = self.pw.getViewBox()
        self.proxy = pg.SignalProxy(self.pw.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
        self.pw.enableAutoRange()
        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_whole_data):
                target_data = self.current_whole_data[index]
                html_str = ''
                for i, item in enumerate(self.whole_header):
                    html_str += f"
{item}:{target_data[i]}" self.label.setHtml(html_str) self.label.setPos(mousePoint.x(), mousePoint.y()) self.vLine.setPos(mousePoint.x()) self.hLine.setPos(mousePoint.y()) pass def mouseClicked(self, evt): pass def updateViews(self): pass pass

主程序控件

class StrategeMainWidget(QtWidgets.QWidget):
    signal_runcode = QtCore.pyqtSignal(object)
    signal_time = QtCore.pyqtSignal(object)
    def __init__(self):
        super().__init__()
        self.thread_run: Thread = None
        self.thread_time: Thread = None

        self.init_data()
        self.init_ui()
        self.register_event()
        pass
    def init_data(self):
        self.pre_output_dir = './'
        self.results_output_dir = './k_recognition_output/'
        self.please_select_str: str = '--请选择--'
        self.k_strategy_path: str = '../shape_recognition_strategy/'
        self.stratege_run_start_time = None
        self.stratege_start = False
        self.current_stratege_py_str: str = ''
        self.dailydata_path:str = ''
        self.k_strategy_map: Dict[str,Any] = {
            '转势技术图形':['头肩顶','头肩底','复合头肩模式','圆底(蝶形底)','圆顶(蝶形顶)','双底(W底)','双顶(M顶)','三重顶和三重底','潜伏底','V形反转(V形底)','倒置V形反转(尖顶)','缺口','底部岛形反转','顶部岛形反转'],
            '整理技术图形':['上升三角形','下降三角形','底部三角形','扩散三角形(喇叭形)','收敛三角形','菱形(钻石形)','上升旗形(下飘旗形)','下降旗形(上飘旗形)','上升楔形','下降楔形','矩形(箱体)']
        }
        self.strategyname_code_map:Dict[str,str] = {
            '头肩顶': '',
            '头肩底': '',
            '复合头肩模式': '000',
            '圆底(蝶形底)': '',
            '圆顶(蝶形顶)': '',
            '双底(W底)': '',
            '双顶(M顶)': '',
            '三重顶和三重底': '',
            '潜伏底': '',
            'V形反转(V形底)': '',
            '倒置V形反转(尖顶)': '',
            '缺口': '',
            '底部岛形反转': '',
            '顶部岛形反转': '',
            '上升三角形': '',
            '下降三角形': '',
            '底部三角形': '',
            '扩散三角形(喇叭形)': '',
            '收敛三角形': '',
            '菱形(钻石形)': '',
            '上升旗形(下飘旗形)': '',
            '下降旗形(上飘旗形)': '',
            '上升楔形': '',
            '下降楔形': '',
            '矩形(箱体)': ''
        }
        self.table_header: List = ['点位','日期','值']
        pass
    def init_ui(self):
        self.setWindowTitle('股票技术图形识别工具')
        tip_0 = QtWidgets.QLabel('股票日数据文件:')
        self.dailydata_filepath_lineedit = QtWidgets.QLineEdit()
        self.dailydata_filepath_lineedit.setReadOnly(True)
        dailydata_choice_btn = QtWidgets.QPushButton('选择文件')
        dailydata_choice_btn.clicked.connect(self.dailydata_choice_btn_clicked)

        layout_top = QtWidgets.QHBoxLayout()
        layout_top.addWidget(tip_0)
        layout_top.addWidget(self.dailydata_filepath_lineedit)
        layout_top.addWidget(dailydata_choice_btn)
        layout_top.addStretch(1)

        tip_1 = QtWidgets.QLabel('类别:')
        self.type_combox = QtWidgets.QComboBox()
        self.type_combox.addItem(self.please_select_str)
        self.type_combox.addItems(list(self.k_strategy_map.keys()))
        self.type_combox.currentIndexChanged.connect(self.type_combox_currentIndexChanged)

        tip_2 = QtWidgets.QLabel('技术图形:')
        self.shape_combox = QtWidgets.QComboBox()
        self.shape_combox.addItem(self.please_select_str)
        self.shape_combox.currentIndexChanged.connect(self.shape_combox_currentIndexChanged)

        self.run_btn = QtWidgets.QPushButton('运行')
        self.run_btn.clicked.connect(self.run_btn_clicked)

        self.time_label = QtWidgets.QLabel('')

        layout_combox = QtWidgets.QFormLayout()
        layout_combox.addRow(tip_1,self.type_combox)
        layout_combox.addRow(tip_2,self.shape_combox)
        layout_combox.addRow(self.run_btn,self.time_label)

        self.code_textedit = QtWidgets.QTextEdit()
        self.code_textedit.setReadOnly(True)

        self.results_table = PageTableWidget()
        self.results_table.set_table_init_data({'headers':self.table_header})

        layout_left = QtWidgets.QVBoxLayout()
        layout_left.addLayout(layout_combox)
        layout_left.addWidget(self.code_textedit)
        layout_left.addWidget(self.results_table)

        self.line_widget = PyQtGraphKWidget()

        layout_down = QtWidgets.QHBoxLayout()
        layout_down.addLayout(layout_left,1)
        layout_down.addWidget(self.line_widget,2)

        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addLayout(layout_down)
        self.setLayout(layout)
        pass
    def register_event(self):
        self.signal_runcode.connect(self.thread_run_excuted)
        self.signal_time.connect(self.thread_time_excuted)
        pass
    def dailydata_choice_btn_clicked(self):
        path, _ = QtWidgets.QFileDialog.getOpenFileName(
            self,
            '打开股票日数据所在文件',
            self.pre_output_dir
        )
        if not path:
            return
        self.dailydata_filepath_lineedit.setText(path)
        pass
    def type_combox_currentIndexChanged(self,cur_i:int):
        cur_txt = self.type_combox.currentText()
        if not cur_txt or cur_txt == self.please_select_str:
            return
        shape_name_list = self.k_strategy_map[cur_txt]
        self.shape_combox.clear()
        self.shape_combox.addItem(self.please_select_str)
        self.shape_combox.addItems(shape_name_list)
        pass
    def shape_combox_currentIndexChanged(self,cur_i:int):
        cur_txt = self.shape_combox.currentText()
        if not cur_txt or cur_txt == self.please_select_str:
            return
        cur_strategy_name = self.strategyname_code_map[cur_txt]
        if cur_strategy_name == '000':
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '代码实现太复杂,还是靠肉眼吧。。。',
                QtWidgets.QMessageBox.Yes
            )
            return


        if len(cur_strategy_name)<=0:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '该K线形态的策略还没上线',
                QtWidgets.QMessageBox.Yes
            )
            return
        strategy_file_path = self.k_strategy_path + cur_strategy_name
        with open(strategy_file_path,'r',encoding='utf-8') as fr:
            py_str = fr.read()
        if len(py_str)<=20:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '策略文件代码为空',
                QtWidgets.QMessageBox.Yes
            )
            return
        self.code_textedit.setPlainText(py_str)
        pass
    def run_btn_clicked(self):
        '''运行按钮'''
        # 检查股票日数据文件夹
        dailydata_filepath = self.dailydata_filepath_lineedit.text()
        dailydata_filepath = dailydata_filepath.strip()
        if len(dailydata_filepath)<=0:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请选择股票日数据文件',
                QtWidgets.QMessageBox.Yes
            )
            return

        py_str = self.code_textedit.toPlainText()
        if len(py_str)<20:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '请选择要执行的策略',
                QtWidgets.QMessageBox.Yes
            )
            return
        self.current_stratege_py_str = py_str

        self.run_btn.setDisabled(True)
        self.shape_combox.setDisabled(True)
        self.stratege_run_start_time = datetime.now()
        self.stratege_start = True

        if self.thread_run:
            QtWidgets.QMessageBox.information(
                self,
                '提示',
                '有策略正在运行',
                QtWidgets.QMessageBox.Yes
            )
            return
        pre_data = {
            'py_str':py_str,
            'dailydata_filepath':dailydata_filepath
        }
        self.thread_run = Thread(
            target=self.running_run_thread,
            args=(pre_data,)
        )
        self.thread_run.start()
        self.thread_time = Thread(
            target=self.running_time_thread
        )
        self.thread_time.start()
        pass
    def running_run_thread(self,data:Dict[str,Any]):
        '''执行代码线程'''
        py_str = data['py_str']
        dailydata_filepath = data['dailydata_filepath']

        namespace = {}
        fun_stragegy = compile(py_str,'','exec')
        exec(fun_stragegy,namespace)
        ret = namespace['excute_strategy'](dailydata_filepath)
        self.signal_runcode.emit(ret)
        pass
    def thread_run_excuted(self,data:Dict):
        '''策略代码执行返回结果'''
        self.run_btn.setDisabled(False)
        self.shape_combox.setDisabled(False)

        # 保存结果文件
        self.results_table.set_table_full_data(data['res_table'])

        self.line_widget.set_data(data)

        self.thread_run = None
        self.thread_time = None
        self.stratege_start = False

        QtWidgets.QMessageBox.information(
            self,
            '提示',
            '当前策略运行完毕',
            QtWidgets.QMessageBox.Yes
        )
        pass
    def running_time_thread(self):
        '''计时线程'''
        while self.stratege_start:
            now = datetime.now()
            interval_time = (now-self.stratege_run_start_time).seconds
            res_map = {'res':interval_time}
            self.signal_time.emit(res_map)
            time.sleep(1)
        pass
    def thread_time_excuted(self,data:Dict):
        '''计时返回结果'''
        res = data['res']
        self.time_label.setText(f"{res}s")
        pass

    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        if self.thread_time:
            self.thread_time = None
        if self.thread_run:
            self.thread_run = None
        self.close()

工具使用

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

1. 在入口代码对应的py文件的上一级目录下创建 shape_recognition_strategy 文件夹,后续K线技术图形判别的策略代码都保存在这个文件夹下

PyQt5_股票技术图形查看工具_第2张图片

 

数据

链接:https://pan.baidu.com/s/1acghH4GQyu_OaOUmEjPdHw 
提取码:6toe

你可能感兴趣的:(金融,PyQt5,pandas基础与金融实例练习,python,开发语言)