Python quantitative stock trading (12) --- Use pyqt5 to build a stock trading software homepage

Real-time stock data

Following the content of the previous blog post, today we will realize the acquisition and drawing of real-time stock market data. First, we need to obtain real-time transaction data for a certain day through the akshare library. The specific code is as follows:

import akshare as ak
df = ak.stock_zh_a_tick_tx(code="sh600690", trade_date="20210203")
df.to_excel("sh600690.xlsx")

After obtaining, we will get the following data:
data
Among them, here we can get the data of real-time stock trading changes every 3 seconds, and at the same time get the current transaction is a buy order or a sell order, and how many lots are bought and sold. Of course, for novices in stocks, there must be something very confusing, that is, the neutral market. In stock trading, according to the conventional logic, we either sell or buy. What the hell is neutral?

In fact, the neutral order means that if you place an order and sell 10 lots, and there is an order in the buying order, which happens to be 10 lots, and the prices of the two are the same, then you will directly match the transaction. This kind of transaction It is called a neutral disk, which can be understood as offset.

Detailed data of each transaction

Now that we have obtained the detailed data of daily stock transactions, the next thing to do is to draw, the specific code is as follows:

df = pd.read_excel("sh600690.xlsx")
df['成交时间'] = pd.to_datetime(df['成交时间'])
df['成交时间'] = df['成交时间'].apply(lambda x: x.strftime('%H:%M'))
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111)
plt.rcParams['font.sans-serif'] = ['SimHei']
ax.plot(np.arange(0, len(df["成交时间"])), df["成交价格"])
ax.xaxis.set_major_locator(ticker.MaxNLocator(20))


def format_date(x, pos=None):
    if x < 0 or x > len(df['成交时间']) - 1:
        return ''
    return df['成交时间'][int(x)]


ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
ax.grid(True)
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
plt.show()

After running, the effect is as shown in the figure below:
Real-time market data

Draw stock chart and order data

Although we already know how to draw a trend chart and get the data of inverted orders, then according to the code of the previous pyqt5, we will add it to the home page. The specific code is as follows:

# mian.py代码
def init_hometab(self):
	#第一篇代码
	self.mainThread = MainPlotThread()
    self.mainThread.setValue("sh600690")
    self.mainThread._signal.connect(self.mianThread_callbacklog)
    self.mainThread._orderList.connect(self.orderThread_callbacklog)
    self.mainThread.start()

def mianThread_callbacklog(self, df):
    mpl = StockMplCanvas(self, width=5, height=4, dpi=100)
    mpl.start_staict_plot(df)
    mpl_ntb = NavigationToolbar(mpl, self)
    mpl_ntb.setStyleSheet("background-color:white;color:black")

    self.grid.addWidget(mpl, 2, 0, 12, 12)
    self.grid.addWidget(mpl_ntb, 2, 0, 1, 5)

 # 指数显示模块
def tableWidget_connect(self, item):
    QMessageBox.information(self, "QTableWidget", "你选择了" + item.text())

def orderThread_callbacklog(self, urlList):
    ft = QFont()
    ft.setPointSize(10)
    ft.setBold(True)
    m_color = None
    j = 0
    if not self.isListView:
        self.tableWidget.clear()
        self.tableWidget.setHorizontalHeaderLabels(['性质', '成交量(手)', '成交额(元)'])
        for qlist in urlList:
            for index, m_dict in enumerate(qlist):
                if index == 0:
                    if str(m_dict).strip() == "买盘":
                        m_color = QColor(255, 0, 0)
                    elif str(m_dict).strip() == "卖盘":
                        m_color = QColor(0, 255, 0)
                    else:
                        m_color = QColor(255, 255, 255)
                newItem = QTableWidgetItem(str(m_dict))
                newItem.setFont(ft)
                newItem.setForeground(QBrush(m_color))
                self.tableWidget.setItem(j, index, newItem)
            j += 1
    else:
        # 各个板块指数
        self.tableWidget = QTableWidget(len(urlList), 3)
        self.tableWidget.setHorizontalHeaderLabels(['性质', '成交量(手)', '成交额(元)'])
        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)  # 不可编辑
        self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)  # 禁止拖拽
        self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)  # 只能选中一行
        self.tableWidget.itemClicked.connect(self.tableWidget_connect)
        self.tableWidget.verticalHeader().setVisible(False)
        self.tableWidget.setShowGrid(False)  # 不显示子线条
        self.tableWidget.setColumnWidth(0, 70)  # 设置第一列宽
        self.tableWidget.setColumnWidth(1, 70)  # 设置第二列宽
        self.tableWidget.setColumnWidth(2, 70)  # 设置第三列宽
        for qlist in urlList:
            for index, m_dict in enumerate(qlist):
                if index == 0:
                    if str(m_dict).strip() == "买盘":
                        m_color = QColor(255, 0, 0)
                    elif str(m_dict).strip() == "卖盘":
                        m_color = QColor(0, 255, 0)
                    else:
                        m_color = QColor(255, 255, 255)
                newItem = QTableWidgetItem(str(m_dict))
                newItem.setFont(ft)
                newItem.setForeground(QBrush(m_color))
                self.tableWidget.setItem(j, index, newItem)
            j += 1
        self.grid.addWidget(self.tableWidget, 2, 12, 12, 4)
        self.isListView = False
    self.tableWidget.scrollToBottom()

Here we use FigureCanvas to display the graph drawn by matplotlib on the interface, and use QTableWidget to display the order data on the interface. Note that the order data is always at the bottom, which is the most recent time, so we need to move the low end through scrollToBottom.

Next, let's take a look at the drawing class StockMplCanvas:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np

from matplotlib import gridspec
class StockMplCanvas(FigureCanvas):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        plt.rcParams['font.sans-serif'] = ['SimHei']
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        FigureCanvas.__init__(self, self.fig)
        spec = gridspec.GridSpec(2, 1, height_ratios=[2, 1])
        self.ax1 = self.fig.add_subplot(spec[0])
        self.ax2 = self.fig.add_subplot(spec[1])
        self.setParent(parent)

        FigureCanvas.updateGeometry(self)


    def start_staict_plot(self, df):
        df['成交时间'] = pd.to_datetime(df['成交时间'])
        df['成交时间'] = df['成交时间'].apply(lambda x: x.strftime('%H:%M'))
        self.ax1.plot(np.arange(0, len(df["成交时间"])), df["成交价格"], color='black')
        df_buy = np.where(df["性质"] == "买盘", df["成交量(手)"], 0)
        df_sell = np.where(df["性质"] == "卖盘", df["成交量(手)"], 0)
        self.ax1.set(ylabel=u"股价走势图")
        self.ax2.bar(np.arange(0, len(df)), df_buy, color="red")
        self.ax2.bar(np.arange(0, len(df)), df_sell, color="blue")
        self.ax2.set_ylim([0, df["成交量(手)"].max()/3])
        self.ax2.set(ylabel=u"成交量分时图")
        self.ax1.xaxis.set_major_locator(ticker.MaxNLocator(3))

        def format_date(x, pos=None):
            if x < 0 or x > len(df['成交时间']) - 1:
                return ''
            return df['成交时间'][int(x)]

        self.ax1.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
        self.ax1.grid(True)
        plt.setp(self.ax2.get_xticklabels(), visible=False)
        plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')

Here, we draw two graphs, one is the stock trading graph, and the other is the trading volume time-sharing graph. The code is very simple. I have introduced it before, so I won’t repeat it here.

Next, we need to obtain these data to facilitate its drawing:

import akshare as ak
import pandas as pd
from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSignal
from pandas import DataFrame

class MainPlotThread(QtCore.QThread):
    _signal = pyqtSignal(DataFrame)
    _orderList = pyqtSignal(list)
    def setValue(self, shareNumber):
        self.share_num = shareNumber

    def run(self):
        self.list = []
        df = pd.read_excel("sh600690.xlsx")
        self._signal.emit(df)
        self.list.clear()
        for index, row in df.iterrows():
            self.list.append([row['性质'], row['成交量(手)'], row['成交额(元)']])
        self._orderList.emit(self.list)

Here, we obtain the data through files. You can also directly obtain it through akshare. However, the blogger recommends obtaining network data first, and then obtaining document data, because the data has not changed after 15:00 on the trading day. These free data have a very high latency and are stored locally, which can speed up the speed of data acquisition during non-transaction time periods.

After running, the displayed effect is as shown in the figure below:
Transaction data

Guess you like

Origin blog.csdn.net/liyuanjinglyj/article/details/113572380