使用工具:
- 使用PySide6制作界面UI
- 使用Matplotlib下关于量化数据可视化Mplfinance库绘制K线图等信息
- 使用Tushare、AKShare库获取实时交易数据以及历史数据
- 使用tensorflow库,基于历史数据对未来走势进行预测
- tuchare官方文档:https://tushare.pro/
- akshare官方文档:https://akshare.akfamily.xyz/introduction.html
- k线图绘制:https://blog.youkuaiyun.com/Shepherdppz/article/details/108205721
界面UI:

k线图UI:
k线图绘制:
import numpy as np
import mplfinance as mpf
from stockData import get_realtime_quotes
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class KLineChart:
def __init__(self):
pass
def draw_chart(self, data, code, start_date, end_date):
my_color = mpf.make_marketcolors(up='r',
down='g',
edge='inherit',
wick='inherit',
volume='inherit')
my_style = mpf.make_mpf_style(marketcolors=my_color,
figcolor='(0.82, 0.83, 0.85)',
gridcolor='(0.82, 0.83, 0.85)')
title_font = {'fontname': 'SimHei', 'size': '14', 'color': 'black', 'weight': 'bold', 'va': 'bottom',
'ha': 'center'}
large_red_font = {'fontname': 'Arial', 'size': '18', 'color': 'red', 'weight': 'bold', 'va': 'bottom'}
large_green_font = {'fontname': 'Arial', 'size': '18', 'color': 'green', 'weight': 'bold', 'va': 'bottom'}
small_red_font = {'fontname': 'Arial', 'size': '10', 'color': 'red', 'weight': 'bold', 'va': 'bottom'}
small_green_font = {'fontname': 'Arial', 'size': '10', 'color': 'green', 'weight': 'bold', 'va': 'bottom'}
normal_label_font = {'fontname': 'SimHei', 'size': '10', 'color': 'black', 'va': 'bottom', 'ha': 'right'}
normal_font = {'fontname': 'Arial', 'size': '10', 'color': 'black', 'va': 'bottom', 'ha': 'left'}
last_data = get_realtime_quotes(code, start_date, end_date)
fig = mpf.figure(
style=my_style,
figsize=(12, 8),
facecolor=(0.82, 0.83, 0.85),
)
ax1 = fig.add_axes([0.11, 0.25, 0.8, 0.60])
ax2 = fig.add_axes([0.11, 0.15, 0.8, 0.10], sharex=ax1)
ax1.set_ylabel('Price, MA:[5,10,20]', fontsize=8)
ax2.set_ylabel('Volume', fontsize=8)
fig.text(0.50, 0.94, f'{code} - 纳指ETF:', **title_font)
fig.text(0.08, 0.90, '开/收:', **normal_label_font)
fig.text(0.08, 0.89, f'{np.round(last_data["open"], 3)} / {np.round(last_data["close"], 3)}', **large_red_font)
fig.text(0.14, 0.86, f'{last_data["change"]}', **small_red_font)
fig.text(0.22, 0.86, f'[{np.round(last_data["pct_chg"], 2)}%]', **small_red_font)
fig.text(0.1, 0.86, f'{last_data.name.date()}', **normal_label_font)
fig.text(0.42, 0.90, '高:', **normal_label_font)
fig.text(0.42, 0.90, f'{last_data["high"]}', **small_red_font)
fig.text(0.42, 0.86, '低:', **normal_label_font)
fig.text(0.42, 0.86, f'{last_data["low"]}', **small_green_font)
fig.text(0.6, 0.90, '量(手):', **normal_label_font)
fig.text(0.6, 0.90, f'{np.round(last_data["vol"] / 10000, 3)}', **normal_font)
fig.text(0.6, 0.86, '额(千元):', **normal_label_font)
fig.text(0.6, 0.86, f'{last_data["amount"]}', **normal_font)
fig.text(0.80, 0.86, '昨收:', **normal_label_font)
fig.text(0.80, 0.86, f'{last_data["pre_close"]}', **normal_font)
try:
mpf.plot(data,
ax=ax1,
volume=ax2,
type='candle',
style=my_style,
mav=(5, 10, 20),
)
except Exception as e:
print(e)
canvas = FigureCanvas(fig)
return canvas
错误信息窗口:
from PySide6.QtWidgets import QMessageBox
def errorWindow_info():
msgBox = QMessageBox()
msgBox.setIcon(QMessageBox.Warning)
msgBox.setText("请填写正确信息!")
msgBox.setWindowTitle("提示")
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec_()
def errorWindow_date():
msgBox = QMessageBox()
msgBox.setIcon(QMessageBox.Warning)
msgBox.setText("请填写正确日期顺序!")
msgBox.setWindowTitle("提示")
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec_()
数据获取
def get_day_data(code, start_date, end_date):
"""
获取指定股票指定时间段的日线数据
"""
data = pro.daily(ts_code=code, start_date=start_date, end_date=end_date)
if data.empty:
data = pro.index_daily(ts_code=code, start_date=start_date, end_date=end_date)
data.index = data.trade_date
data = data.rename(index=pd.Timestamp)
data.drop(columns=['ts_code', 'trade_date', 'pre_close', 'change', 'pct_chg', 'amount'], inplace=True)
data.columns = ['open', 'high', 'low', 'close', 'volume']
data.sort_index(inplace=True)
return data
def get_week_data(code, start_date, end_date):
"""
获取指定股票指定时间段的周线数据
"""
data = pro.weekly(ts_code=code, start_date=start_date, end_date=end_date)
if data.empty:
data = pro.index_weekly(ts_code=code, start_date=start_date, end_date=end_date)
data.index = data.trade_date
data = data.rename(index=pd.Timestamp)
data.drop(columns=['ts_code', 'trade_date', 'pre_close', 'change', 'pct_chg', 'amount'], inplace=True)
data.columns = ['open', 'high', 'low', 'close', 'volume']
data.sort_index(inplace=True)
return data
def get_realtime_quotes(code, start_date, end_date):
"""
获取最后一天的实时行情数据
"""
data = pro.daily(ts_code=code, start_date=start_date, end_date=end_date)
if data.empty:
data = pro.index_daily(ts_code=code, start_date=start_date, end_date=end_date)
data.index = data.trade_date
data = data.rename(index=pd.Timestamp)
data.sort_index(inplace=True)
return data.iloc[-1]
def get_realtime_trades():
stock = ak.stock_zh_a_spot_em()
stock.index = stock['代码']
stock = stock.drop(
columns=['代码','序号', '涨跌额', '成交量', '成交额', '振幅', '最高', '最低', '量比', '换手率', '市盈率-动态',
'市净率',
'总市值', '流通市值', '涨速', '60日涨跌幅', '年初至今涨跌幅'])
stock.columns = [ '名称', '最新价', '涨跌幅', '今开', '昨收', '5分钟涨跌']
return stock.head(30)
模型预测:
import pandas as pd
import numpy as np
from stockData import get_day_data
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM
from sklearn.preprocessing import MinMaxScaler
def prediction_data(stock_code, start_date, end_date):
data = get_day_data(stock_code, start_date, end_date)
last_10_days = data[-30:]
features = ['open', 'high', 'low', 'close', 'volume']
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data[features])
def create_dataset(data, time_step=1):
X, Y = [], []
for i in range(len(data) - time_step - 1):
a = data[i:(i + time_step), :]
X.append(a)
Y.append(data[i + time_step, :])
return np.array(X), np.array(Y)
time_step = 10
X, Y = create_dataset(scaled_data, time_step)
model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(time_step, len(features))))
model.add(LSTM(50, return_sequences=False))
model.add(Dense(len(features)))
model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(X,
Y,
epochs=100,
batch_size=1,
verbose=2
)
last_10_days_scaled = scaler.transform(last_10_days[features])
X_test = np.array([last_10_days_scaled])
predictions = []
for _ in range(15):
pred = model.predict(X_test)
predictions.append(pred[0])
X_test = np.append(X_test[:, 1:, :], [[pred[0]]], axis=1)
predictions = scaler.inverse_transform(predictions)
future_dates = pd.date_range(start=data.index[-1] + pd.Timedelta(days=1), periods=15, freq='D')
predicted_data = pd.DataFrame(predictions, columns=features, index=future_dates)
combined_data = pd.concat([last_10_days, predicted_data])
return combined_data