量化投资系列之《股票日行情数据可视化》
k 线图可视化很重要,中医有望闻问切,股票 k 线形态很重要,掌握可视化技术,为后续可视化报告打下基础。
安装
安装 matplotlib 库,数据可视化库
pip install -U matplotlib
安装 mplfinance 库,股票 k 线图可视化库
pip install --upgrade mplfinance
matplotlib 基础
matplotlib Python 2D-绘图领域使用最广泛的套件,它很轻松的将数据可视化,了解 matplotlib ,请学习教程1 链接[2],教程2 链接[3]
plt 函数
函数 | 描述 | 函数 | 描述 |
---|---|---|---|
plt.plot(x,y) | 画线 | plt.title('title') | 添加图标标题 |
plt.xlabel('x轴') | x轴标签 | plt.ylabel('y轴') | y轴标签 |
中文问题
方法一
# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解决负号显示方块问题
plt.rcParams['axes.unicode_minus'] = False
方法二
# 下载字体放在工程,例如'font/SourceHanSansSC-Bold.otf',然后引用
zhfont1 = mpl.font_manager.FontProperties(fname='字体路径')
# 标题格式,字体为中文字体,颜色为黑色,粗体,水平中心对齐
title_font = {'fontproperties': zhfont1,
'size': '16',
'color': 'black',
'weight': 'bold',
'va': 'bottom',
'ha': 'center'}
plt.title('测试', **title_font)
多图绘制
画布和多张子图概念,在画布 figure 上绘制多张子图 axes . 常采用 subplot() 函数或 subplots() 函数进行绘制。
figure 对象
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
num | int | 1 | 图像数量 |
figsize | tuple | figure.figsize | 图像的长和宽(英寸) |
dpi | int | figure.dpi | 分辨率(点/英寸) |
facecolor | tuple | figure.facecolor | 绘制区域背景色 |
edgecolor | tuple | figure.edgecolor | 绘图区域边缘的颜色 |
frameon | bool | True | 是否绘制图像边缘 |
Axes 对象
plt.axes([left, bottom, width, height])
axes 对象是个列表,四个数值分别是相对于 figure 对象左下角坐标的左距离、底部距离、宽、高。
示例代码
fig = plt.figure(figsize=(10, 8), dpi=80,
facecolor=(0.82, 0.83, 0.85),
edgecolor=(1, 1, 1),
frameon=True)
# 设置图片边缘距离
plt.subplots_adjust(left=0.08, right=0.92, top=0.92, bottom=0.08)
# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解决负号显示方块问题
plt.rcParams['axes.unicode_minus'] = False
plt.title('绘制多子图')
plt.xlabel('x 轴')
plt.ylabel('y 轴')
plt.grid(color='r', linestyle='--', linewidth=0.5)
plt.axes([0.1, 0.1, .5, .5])
# 设置横轴记号 设置纵轴记号
plt.xticks([]), plt.yticks([])
plt.text(0.1, 0.1, 'axes([0.1,0.1,.5,.5])', ha='left', va='center', size=16, alpha=.5)
plt.axes([0.2, 0.2, .5, .5])
plt.xticks([]), plt.yticks([])
plt.text(0.1, 0.1, 'axes([0.2,0.2,.5,.5])', ha='left', va='center', size=16, alpha=.5)
plt.axes([0.3, 0.3, .5, .5])
plt.xticks([]), plt.yticks([])
plt.text(0.1, 0.1, 'axes([0.3,0.3,.5,.5])', ha='left', va='center', size=16, alpha=.5)
plt.axes([0.4, 0.4, .5, .5])
plt.xticks([]), plt.yticks([])
plt.text(0.1, 0.1, 'axes([0.4,0.4,.5,.5])', ha='left', va='center', size=16, alpha=.5)
plt.show()
mplfinance 库使用
mplfinance 里面提供的函数,其实封装了 pyplot 库,本质上是 pyplot 库 k 线的定制版。
蜡烛图
画图之前,先了解下蜡烛图概念,蜡烛线将各种股票每日、每周、每月开盘价、收盘价、最高价、最低价等涨跌变化状况,用图形方式表现出来,即蜡烛图。如下图所示,K线最上方细线称为上影线,中间条粗线为实体。下面的细线为下影线。
绘制
自定义风格
关键函数 mpf.make_mpf_style() 和 mpf.make_marketcolors()
# 设置marketcolors
# up:设置K线线柱颜色,up意为收盘价大于等于开盘价
# down:与up相反,这样设置与国内K线颜色标准相符
# edge:K线线柱边缘颜色(i代表继承自up和down的颜色),下同。详见官方文档)
# wick:灯芯(上下影线)颜色
# volume:成交量直方图的颜色
# inherit:是否继承,选填
mc = mpf.make_marketcolors(
up='red',
down='green',
edge='in',
wick='in',
volume='in',
inherit=True)
# 设置图形风格
# gridaxis:设置网格线位置
# gridstyle:设置网格线线型
# y_on_right:设置y轴位置是否在右
m_style = mpf.make_mpf_style(
gridaxis='both',
gridstyle='-.',
figcolor='(0.82, 0.83, 0.85)',
gridcolor='(0.82, 0.83, 0.85)',
y_on_right=False,
marketcolors=mc)
简单绘制
mpf.plot(df.iloc[20:147], style=m_style, type='candle', volume=True)
进阶绘制
按自定义风格,已经可以得到了一张简单包含 k 线和成交量的图,但还想显示更多指标,例如 KDJ,MACD 等,表格顶部区域预留空白显示价格等指标。所以需要用到库的 External Axes Mode 模式绘制。
在 External Axes Mode 模式下,可以更自由画布上的每个图标和文字元素,获得更大的绘制自由。
定制对象
为了能更大的获取绘制自由度,需要获取画布对象 figure、子图 Axes 、文字 Text。文字和图表的位置、大小、格式完全自定义。参数使用解析,请查看上面的 matplotlib 多图绘制。
生成主画布 fig,日行情 k 线子图 ax1,成交量子图 ax2,macd 子图 ax3。
# 获取figure对象,以便对Axes对象和figure对象的自由控制
fig = mpf.figure(style=m_style, figsize=(12, 8),
facecolor=(0.82, 0.83, 0.85))
# 主图相对figure 底部 0.06,0.25,宽(0.88)、高(0.60)
ax1 = fig.add_axes([0.06, 0.25, 0.88, 0.60])
# 指标图 sharex 关键字指明与ax1在x轴上对齐,且共用x轴
ax2 = fig.add_axes([0.06, 0.15, 0.88, 0.10], sharex=ax1)
# macd
ax3 = fig.add_axes([0.06, 0.05, 0.88, 0.10], sharex=ax1)
# 设置y轴标签
ax1.set_ylabel('price')
ax2.set_ylabel('volume')
ax3.set_ylabel('macd')
字体自定义
# 下载的字体路径
zhfont = mpl.font_manager.FontProperties(fname=sc.text_font)
# 标题格式,字体为中文字体,颜色为黑色,粗体,水平中心对齐
title_font = {'fontproperties': zhfont,
'size': '16',
'color': 'black',
'weight': 'bold',
'va': 'bottom',
'ha': 'center'}
# 红色数字格式(显示开盘收盘价)粗体红色24号字
large_red_font = {'fontproperties': zhfont,
'size': '24',
'color': 'red',
'weight': 'bold',
'va': 'bottom'}
# 绿色数字格式(显示开盘收盘价)粗体绿色24号字
large_green_font = {'fontproperties': zhfont,
'size': '24',
'color': 'green',
'weight': 'bold',
'va': 'bottom'}
# 小数字格式(显示其他价格信息)粗体红色12号字
small_red_font = {'fontproperties': zhfont,
'size': '12',
'color': 'red',
'weight': 'bold',
'va': 'bottom'}
# 小数字格式(显示其他价格信息)粗体绿色12号字
small_green_font = {'fontproperties': zhfont,
'size': '12',
'color': 'green',
'weight': 'bold',
'va': 'bottom'}
# 标签格式,可以显示中文,普通黑色12号字
normal_label_font = {'fontproperties': zhfont,
'size': '12',
'color': 'black',
'va': 'bottom',
'ha': 'right'}
# 普通文本格式,普通黑色12号字
normal_font = {'fontproperties': zhfont,
'size': '12',
'color': 'black',
'va': 'bottom',
'ha': 'left'}
Ta-lib 获取金融指标 MA ,MACD
talib 是一个金融指标库,包含 150 种常用金融指标,github 地址[5]
计算5日、10日、20日、60日均线
N = [5, 10, 20, 60]
for i in N:
df['MA' + str(i)] = ta.EMA(df['Close'], timeperiod=i)
计算 macd 指标
# 通过金融库 talib 生成MACD指标,
short_win = 12 # 短期EMA平滑天数
long_win = 26 # 长期EMA平滑天数
macd_win = 9 # DEA线平滑天数
macd_tmp = ta.MACD(df['Close'], fastperiod=short_win, slowperiod=long_win, signalperiod=macd_win)
DIF = macd_tmp[0][start_index:end_index]
DEA = macd_tmp[1][start_index:end_index]
MACD = macd_tmp[2][start_index:end_index]
添加指标到子图
注意,最后 mpf.plot 绘制是需要添加指标参数 addplot=ap
ap = []
ap.append(mpf.make_addplot(df[['MA5', 'MA10', 'MA20', 'MA60']].iloc[start_index:end_index], ax=ax1))
mpf.plot(df_data,
ax=ax1,
volume=ax2,
addplot=ap,
style=m_style,
type='candle')
完整示例
绘制平安银行 2022-01-01 到 2022-09-30,完整的日行情 k 线图,添加头部股票简述、均线指标、成交量指标、macd 指标。
代码
"""
用于绘制股票k线
"""
import matplotlib as mpl
import matplotlib.pyplot as plt
import mplfinance as mpf
import numpy as np
import talib as ta
import stock_constant as sc
import stock_db as sdb
# 下载的字体路径
zhfont = mpl.font_manager.FontProperties(fname=sc.text_font)
# 标题格式,字体为中文字体,颜色为黑色,粗体,水平中心对齐
title_font = {'fontproperties': zhfont,
'size': '16',
'color': 'black',
'weight': 'bold',
'va': 'bottom',
'ha': 'center'}
# 红色数字格式(显示开盘收盘价)粗体红色24号字
large_red_font = {'fontproperties': zhfont,
'size': '24',
'color': 'red',
'weight': 'bold',
'va': 'bottom'}
# 绿色数字格式(显示开盘收盘价)粗体绿色24号字
large_green_font = {'fontproperties': zhfont,
'size': '24',
'color': 'green',
'weight': 'bold',
'va': 'bottom'}
# 小数字格式(显示其他价格信息)粗体红色12号字
small_red_font = {'fontproperties': zhfont,
'size': '12',
'color': 'red',
'weight': 'bold',
'va': 'bottom'}
# 小数字格式(显示其他价格信息)粗体绿色12号字
small_green_font = {'fontproperties': zhfont,
'size': '12',
'color': 'green',
'weight': 'bold',
'va': 'bottom'}
# 标签格式,可以显示中文,普通黑色12号字
normal_label_font = {'fontproperties': zhfont,
'size': '12',
'color': 'black',
'va': 'bottom',
'ha': 'right'}
# 普通文本格式,普通黑色12号字
normal_font = {'fontproperties': zhfont,
'size': '12',
'color': 'black',
'va': 'bottom',
'ha': 'left'}
def kline(code, start_time, end_time):
"""
绘制某股票某时间段的日行情k线图
:param code:
:param start_time:
:param end_time:
:return:
"""
# 数据库读取数据
df = sdb.stock_daily(code=code, start_time=start_time, end_time=end_time)
print(df)
# 重命名列
df.rename(
columns={
'date': 'Date', 'open': 'Open',
'high': 'High', 'low': 'Low',
'close': 'Close', 'volume': 'Volume'},
inplace=True)
start_index = 20
end_index = 147
df_data = df.iloc[start_index:end_index]
# 读取显示区间最后一个交易日的数据
last_data = df_data.iloc[-1]
# 设置图片边缘距离
plt.subplots_adjust(left=0.08, right=0.92, top=0.92, bottom=0.08)
# 设置marketcolors
# up:设置K线线柱颜色,up意为收盘价大于等于开盘价
# down:与up相反,这样设置与国内K线颜色标准相符
# edge:K线线柱边缘颜色(i代表继承自up和down的颜色),下同。详见官方文档)
# wick:灯芯(上下影线)颜色
# volume:成交量直方图的颜色
# inherit:是否继承,选填
mc = mpf.make_marketcolors(
up='red',
down='green',
edge='in',
wick='in',
volume='in',
inherit=True)
# 设置图形风格
# gridaxis:设置网格线位置
# gridstyle:设置网格线线型
# y_on_right:设置y轴位置是否在右
m_style = mpf.make_mpf_style(
gridaxis='both', gridstyle='-.',
figcolor='(0.82, 0.83, 0.85)',
gridcolor='(0.82, 0.83, 0.85)',
y_on_right=False,
marketcolors=mc)
# 获取figure对象,以便对Axes对象和figure对象的自由控制
fig = mpf.figure(style=m_style, figsize=(12, 8),
facecolor=(0.82, 0.83, 0.85))
# 主图相对figure 底部 0.06,0.25,宽(0.88)、高(0.60)
ax1 = fig.add_axes([0.06, 0.25, 0.88, 0.60])
# 指标图 sharex 关键字指明与ax1在x轴上对齐,且共用x轴
ax2 = fig.add_axes([0.06, 0.15, 0.88, 0.10], sharex=ax1)
# macd
ax3 = fig.add_axes([0.06, 0.05, 0.88, 0.10], sharex=ax1)
# 设置y轴标签
ax1.set_ylabel('price')
ax2.set_ylabel('volume')
ax3.set_ylabel('macd')
# 在figure对象上添加文本对象,用于显示各种价格和标题
fig.text(0.50, 0.94, '平安银行', **title_font)
fig.text(0.12, 0.90, '开/收: ', **normal_label_font)
fig.text(0.14, 0.89, '%.2f / %.2f' % (np.around(last_data["Open"], 2),
np.round(last_data["Close"], 2)), **large_red_font)
fig.text(0.12, 0.86, f'{last_data.name.date()}', **normal_label_font)
change = last_data["Close"] - last_data["Open"]
fig.text(0.14, 0.86, '%.2f' % change, **small_red_font)
change_percent = (change / last_data["Open"]) * 100
fig.text(0.22, 0.86, '%.2f%%' % change_percent, **small_red_font)
fig.text(0.40, 0.90, '高: ', **normal_label_font)
fig.text(0.40, 0.90, '%.2f' % (last_data["High"]), **small_red_font)
fig.text(0.40, 0.86, '低: ', **normal_label_font)
fig.text(0.40, 0.86, '%.2f' % (last_data["Low"]), **small_green_font)
fig.text(0.55, 0.90, '量(万手): ', **normal_label_font)
fig.text(0.55, 0.90, '%.2f' % (np.round(last_data["Volume"] / 10000, 3)), **normal_font)
fig.text(0.55, 0.86, '额(亿元): ', **normal_label_font)
fig.text(0.55, 0.86, '%.2f' % (last_data["amount"] / 100000000), **normal_font)
ap = []
# 通过金融库 talib 生成移动平均线,为了生成没空白的,使用原数据
N = [5, 10, 20, 60]
for i in N:
df['MA' + str(i)] = ta.EMA(df['Close'], timeperiod=i)
# 通过ax=ax1参数指定把新的线条添加到ax1中,与K线图重叠
# 通过ax=ax1参数指定把新的线条添加到ax1中,与K线图重叠,注意均线切片iloc[20:147]与ax1时间维度一样
ap.append(mpf.make_addplot(df[['MA5', 'MA10', 'MA20', 'MA60']].iloc[start_index:end_index], ax=ax1))
# 通过金融库 talib 生成MACD指标,
short_win = 12 # 短期EMA平滑天数
long_win = 26 # 长期EMA平滑天数
macd_win = 9 # DEA线平滑天数
macd_tmp = ta.MACD(df['Close'], fastperiod=short_win, slowperiod=long_win, signalperiod=macd_win)
DIF = macd_tmp[0][start_index:end_index]
DEA = macd_tmp[1][start_index:end_index]
MACD = macd_tmp[2][start_index:end_index]
# 生成一个空列表用于存储多个addplot
# 在ax3图表中绘制 MACD指标中的快线和慢线
ap.append(mpf.make_addplot(DIF, ax=ax3))
ap.append(mpf.make_addplot(DEA, ax=ax3))
# 使用柱状图绘制快线和慢线的差值,根据差值的数值大小,分别用红色和绿色填充
# 红色和绿色部分需要分别填充,因此先生成两组数据,分别包含大于零和小于等于零的数据
bar_r = np.where(MACD > 0, MACD, 0)
bar_g = np.where(MACD <= 0, MACD, 0)
# 使用柱状图填充(type='bar'),设置颜色分别为红色和绿色
ap.append(mpf.make_addplot(bar_r, type='bar', color='red', ax=ax3))
ap.append(mpf.make_addplot(bar_g, type='bar', color='green', ax=ax3))
# 注意添加均线参数,macd, addplot=ap
mpf.plot(df_data,
ax=ax1,
volume=ax2,
addplot=ap,
style=m_style,
type='candle')
fig.show()
if __name__ == '__main__':
kline('000001', '2022-01-01', '2022-09-30')
pass
效果图:
下篇预告
回测神器框架 backtrader 的使用
学习到现在,已经具备了股票代码本地化,k 线可视化,后面的重头戏是如何编写复利策略,并使用历史数据进行回测,检验策略是否有效。
调查了不少回测框架,最终选择 backtrader 这个框架。这框架模块划分很明确,虽然回测速度慢点,但是社区已经稳定齐全,全部由 python 编写,也方便后续的优化和接入机器学习。
就选它,就选它,就选它,回测神器 backtrader。
参考链接
[1] mplfinance 库地址: https://github.com/matplotlib...
[2] matplotlib 教程1: https://www.runoob.com/matplo...
[3] matplotlib 教程2: https://www.runoob.com/w3cnot...
[4] k线可视化示例地址: https://blog.csdn.net/m0_6739...
[5] ta-lib 库地址: https://mrjbq7.github.io/ta-lib/
写于 2022 年 9 月 12 日 17:25:27
本文由mdnice多平台发布