首页 > 编程开发 > python数据分析 >
-
交互式看盘:添加十字光标、缩放、平移功能
第9章 交互式股票可视化
9.1 交互式看盘:添加十字光标、缩放、平移功能
9.1.1 先讲个真实痛点:静态K线图的尴尬
之前我用Matplotlib画的K线图都是静态的,老板想看某一天的具体数据时,我只能用鼠标指着屏幕说“这一天收盘价是1800元”,非常尴尬。后来我发现Matplotlib可以添加交互式功能,比如十字光标、缩放、平移,这样老板就能自己操作看盘了,体验瞬vb.net教程C#教程python教程SQL教程access 2010教程间提升了一个档次。今天我就把这些交互式功能的实现方法讲清楚,帮你做出专业的交互式看盘工具。
9.1.2 核心技术:Matplotlib的交互模式
Matplotlib默认是静态模式,要实现交互式功能需要开启交互模式(plt.ion()),或者使用mplfinance的交互式功能,也可以使用plotly库实现更强大的交互式功能。
9.1.3 实战1:用Matplotlib添加十字光标、缩放、平移功能
-
实战代码:Matplotlib交互式看盘
python
# 1. 导入需要的库
import tushare as ts
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pylab import date2num
from matplotlib.widgets import Cursor
# 2. 获取贵州茅台的日线数据
pro = ts.pro_api()
df = pro.daily(ts_code='600519.SH', start_date='20250101', end_date='20250710')
# 3. 数据预处理
# 转换日期格式
df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
# 按时间从早到晚排序
df.sort_values('trade_date', inplace=True)
# 设置日期为索引
df.set_index('trade_date', inplace=True)
# 计算涨跌颜色
df['color'] = np.where(df['close'] >= df['open'], 'red', 'green')
# 把日期转成Matplotlib需要的数字格式
df['date_num'] = df.index.to_series().apply(date2num)
# 4. 创建画布和坐标轴
fig, ax = plt.subplots(
figsize=(16, 9), # 画布大小
dpi=100, # 分辨率
facecolor='#f0f0f0' # 画布背景颜色
)
# 5. 绘制K线图
# 绘制影线
ax.vlines(
x=df['date_num'],
ymin=df['low'],
ymax=df['high'],
color=df['color'],
linewidth=1
)
# 绘制实体
ax.bar(
x=df['date_num'],
height=abs(df['close'] - df['open']),
bottom=np.minimum(df['open'], df['close']),
width=0.6,
color=df['color'],
edgecolor='#333333',
linewidth=1
)
# 绘制均线
ax.plot(
df['date_num'], df['close'].rolling(window=5).mean(),
label='5日均线', color='#ff7f0e', linewidth=2
)
ax.plot(
df['date_num'], df['close'].rolling(window=20).mean(),
label='20日均线', color='#2ca02c', linewidth=2
)
ax.plot(
df['date_num'], df['close'].rolling(window=60).mean(),
label='60日均线', color='#d62728', linewidth=2
)
# 6. 添加十字光标
cursor = Cursor(
ax, # 要添加十字光标的坐标轴
useblit=True, # 使用blit技术,提高交互性能
color='#333333', # 十字光标颜色
linewidth=1, # 十字光标宽度
linestyle='--' # 十字光标样式,'--'是虚线
)
# 7. 添加数据提示框
# 创建一个文本对象,用于显示数据提示
text = ax.text(
0.02, 0.98, # 文本位置,相对于坐标轴的比例
'', # 初始文本为空
transform=ax.transAxes, # 坐标转换,使用坐标轴的比例
va='top', # 垂直对齐方式,top是顶部
ha='left', # 水平对齐方式,left是左侧
fontsize=12,
bbox=dict(
boxstyle='round', # 文本框样式,round是圆角矩形
facecolor='#ffffff', # 文本框背景颜色
edgecolor='#333333', # 文本框边框颜色
alpha=0.8 # 文本框透明度
)
)
# 定义鼠标移动事件处理函数
def on_mouse_move(event):
# 如果鼠标不在坐标轴上,返回
if not event.inaxes:
return
# 获取鼠标的X坐标(日期的数字格式)
x = event.xdata
# 找到最接近的日期
idx = np.argmin(np.abs(df['date_num'] - x))
# 获取该日期的数据
data = df.iloc[idx]
# 更新文本内容
text_str = f'日期: {data.name.strftime("%Y-%m-%d")}
'
f'开盘价: {data["open"]:.2f}元
'
f'收盘价: {data["close"]:.2f}元
'
f'最高价: {data["high"]:.2f}元
'
f'最低价: {data["low"]:.2f}元
'
f'成交量: {data["vol"]:.0f}手'
text.set_text(text_str)
# 重绘画布
fig.canvas.draw_idle()
# 绑定鼠标移动事件
fig.canvas.mpl_connect('motion_notify_event', on_mouse_move)
# 8. 设置坐标轴属性
ax.set_title('贵州茅台2025年交互式K线图', fontsize=16, fontweight='bold', pad=20)
ax.set_ylabel('价格(元)', fontsize=14, labelpad=15)
ax.set_xlabel('日期', fontsize=14, labelpad=15)
ax.set_xlim(df['date_num'].min() - 1, df['date_num'].max() + 1)
ax.legend(fontsize=12, loc='upper right')
ax.grid(True, linestyle='--', alpha=0.7, color='#cccccc')
# 设置日期显示格式
ax.xaxis_date()
ax.xaxis.set_major_formatter(plt.FixedFormatter(df.index.strftime('%Y-%m-%d')))
plt.setp(ax.get_xticklabels(), rotation=45, ha='right', fontsize=10)
# 9. 开启交互模式
plt.ion()
# 10. 显示画布
plt.show()
# 11. 保持交互模式
plt.ioff()
plt.show()
逐行讲解:
from matplotlib.widgets import Cursor:导入Cursor类,用于添加十字光标
cursor = Cursor(ax, ...):创建十字光标,绑定到ax坐标轴上
useblit=True:使用blit技术,只重绘变化的部分,提高交互性能
color='#333333':十字光标颜色为深灰色
linestyle='--':十字光标样式为虚线
text = ax.text(...):创建一个文本对象,用于显示数据提示
transform=ax.transAxes:使用坐标轴的比例来定位文本,0.02, 0.98表示左上角的位置
bbox=dict(...):设置文本框的样式,圆角矩形,白色背景,深灰色边框
def on_mouse_move(event)::定义鼠标移动事件处理函数
event.inaxes:判断鼠标是否在坐标轴上
event.xdata:获取鼠标的X坐标(日期的数字格式)
np.argmin(np.abs(df['date_num'] - x)):找到最接近鼠标X坐标的日期的索引
text.set_text(text_str):更新文本内容
fig.canvas.draw_idle():重绘画布
fig.canvas.mpl_connect('motion_notify_event', on_mouse_move):绑定鼠标移动事件到处理函数
plt.ion():开启交互模式,这样Matplotlib会实时响应鼠标事件
plt.ioff():关闭交互模式,保持窗口显示
运行结果:
会弹出一个窗口,显示贵州茅台2025年的交互式K线图:
移动鼠标会显示十字光标
鼠标悬停在K线上时,会显示该日期的详细数据
可以用鼠标滚轮缩放图表
可以按住鼠标左键拖动图表平移
9.1.4 实战2:用mplfinance实现交互式看盘
-
实战代码:mplfinance交互式看盘
python
# 1. 导入需要的库
import tushare as ts
import mplfinance as mpf
import pandas as pd
# 2. 获取贵州茅台的日线数据
pro = ts.pro_api()
df = pro.daily(ts_code='600519.SH', start_date='20250101', end_date='20250710')
# 3. 数据预处理
# 转换日期格式
df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
# 设置日期为索引
df.set_index('trade_date', inplace=True)
# 按时间从早到晚排序
df.sort_index(ascending=True, inplace=True)
# 重命名列名(mplfinance需要特定的列名:Open、High、Low、Close、Volume)
df_rename = df.rename(columns={
'open': 'Open',
'high': 'High',
'low': 'Low',
'close': 'Close',
'vol': 'Volume'
})
# 4. 自定义K线图样式
my_style = mpf.make_mpf_style(
base_mpf_style='yahoo', # 基础样式,yahoo是雅虎财经的风格
marketcolors=mpf.make_marketcolors(
up='red', # 上涨K线颜色,中国股市上涨是红色
down='green', # 下跌K线颜色,中国股市下跌是绿色
edge='inherit', # K线边框颜色,inherit表示继承up/down的颜色
wick='inherit', # K线影线颜色,inherit表示继承up/down的颜色
volume='inherit' # 成交量柱形图颜色,inherit表示继承up/down的颜色
),
gridstyle='--', # 网格线条样式,'--'是虚线
y_on_right=False, # Y轴标签在左侧还是右侧,False表示在左侧
facecolor='#f0f0f0', # 画布背景颜色
edgecolor='#333333', # 画布边框颜色
figcolor='#f0f0f0', # 图形背景颜色
gridcolor='#cccccc' # 网格颜色
)
# 5. 绘制交互式K线图
mpf.plot(
df_rename,
type='candle', # 绘制蜡烛图(K线图)
style=my_style, # 使用自定义样式
title='贵州茅台2025年交互式K线图', # 图表标题
ylabel='价格(元)', # 价格Y轴标签
ylabel_lower='成交量(手)', # 成交量Y轴标签
volume=True, # 显示成交量柱形图
mav=(5, 20, 60), # 显示5日、20日、60日均线
figratio=(16, 9), # 图形比例,16:9适合电脑屏幕
figscale=1.5, # 图形大小,1.5倍默认大小
tight_layout=True, # 自动调整布局
warn_too_much_data=1000, # 当数据超过1000条时才警告
interactive=True # 开启交互模式
)
逐行讲解:
mpf.plot(..., interactive=True):开启mplfinance的交互模式
mplfinance的交互功能包括:
移动鼠标显示十字光标和数据提示
鼠标滚轮缩放图表
按住鼠标左键拖动图表平移
右键菜单可以选择保存图片、调整坐标轴等
运行结果:
会弹出一个窗口,显示贵州茅台2025年的交互式K线图,支持十字光标、缩放、平移等功能,体验非常流畅。
9.1.5 实战3:用plotly实现更强大的交互式看盘
-
什么是plotly?
plotly是一个强大的交互式可视化库,支持多种图表类型,包括K线图、折线图、柱状图等,交互功能非常丰富,比如悬停提示、缩放、平移、下载图片等。 -
实战代码:plotly交互式看盘
python
# 1. 导入需要的库
import tushare as ts
import pandas as pd
import plotly.graph_objects as go
# 2. 获取贵州茅台的日线数据
pro = ts.pro_api()
df = pro.daily(ts_code='600519.SH', start_date='20250101', end_date='20250710')
# 3. 数据预处理
# 转换日期格式
df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
# 按时间从早到晚排序
df.sort_values('trade_date', inplace=True)
# 4. 计算均线
df['ma5'] = df['close'].rolling(window=5).mean()
df['ma20'] = df['close'].rolling(window=20).mean()
df['ma60'] = df['close'].rolling(window=60).mean()
# 5. 创建K线图
fig = go.Figure(data=[
# 绘制K线图
go.Candlestick(
x=df['trade_date'], # X轴数据,日期
open=df['open'], # 开盘价
high=df['high'], # 最高价
low=df['low'], # 最低价
close=df['close'], # 收盘价
name='K线图',
increasing_line_color='red', # 上涨K线颜色
decreasing_line_color='green' # 下跌K线颜色
),
# 绘制5日均线
go.Scatter(
x=df['trade_date'],
y=df['ma5'],
name='5日均线',
line=dict(color='#ff7f0e', width=2)
),
# 绘制20日均线
go.Scatter(
x=df['trade_date'],
y=df['ma20'],
name='20日均线',
line=dict(color='#2ca02c', width=2)
),
# 绘制60日均线
go.Scatter(
x=df['trade_date'],
y=df['ma60'],
name='60日均线',
line=dict(color='#d62728', width=2)
)
])
# 6. 添加成交量柱形图
# 创建子图
from plotly.subplots import make_subplots
fig = make_subplots(
rows=2, cols=1, # 2行1列的子图
shared_xaxes=True, # 共享X轴
vertical_spacing=0.05, # 子图之间的垂直间距
row_heights=[0.7, 0.3] # 子图的高度比例,7:3
)
# 添加K线图和均线到第一个子图
fig.add_trace(
go.Candlestick(
x=df['trade_date'],
open=df['open'],
high=df['high'],
low=df['low'],
close=df['close'],
name='K线图',
increasing_line_color='red',
decreasing_line_color='green'
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['ma5'],
name='5日均线',
line=dict(color='#ff7f0e', width=2)
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['ma20'],
name='20日均线',
line=dict(color='#2ca02c', width=2)
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['ma60'],
name='60日均线',
line=dict(color='#d62728', width=2)
),
row=1, col=1
)
# 添加成交量柱形图到第二个子图
fig.add_trace(
go.Bar(
x=df['trade_date'],
y=df['vol'],
name='成交量',
marker_color=np.where(df['close'] >= df['open'], 'red', 'green')
),
row=2, col=1
)
# 7. 设置图表布局
fig.update_layout(
title='贵州茅台2025年交互式K线图',
title_x=0.5, # 标题居中
yaxis_title='价格(元)',
yaxis2_title='成交量(手)',
xaxis_title='日期',
height=800, # 图表高度
width=1200, # 图表宽度
template='plotly_white', # 使用白色模板
hovermode='x unified' # 悬停时显示同一X轴的所有数据
)
# 8. 设置X轴和Y轴的范围
fig.update_xaxes(
rangeslider_visible=False, # 隐藏X轴的范围滑块
rangeselector=dict(
buttons=list([
dict(count=1, label='1月', step='month', stepmode='backward'),
dict(count=3, label='3月', step='month', stepmode='backward'),
dict(count=6, label='6月', step='month', stepmode='backward'),
dict(step='all', label='全部')
])
)
)
# 9. 显示图表
fig.show()
逐行讲解:
from plotly.subplots import make_subplots:导入make_subplots函数,用于创建子图
fig = make_subplots(...):创建2行1列的子图,共享X轴
go.Candlestick(...):创建K线图
go.Scatter(...):创建均线
go.Bar(...):创建成交量柱形图
fig.update_layout(...):设置图表布局,包括标题、坐标轴标签、高度、宽度等
fig.update_xaxes(...):设置X轴的范围滑块和范围选择器
fig.show():显示图表,会在浏览器中打开一个交互式网页
运行结果:
会在浏览器中打开一个网页,显示贵州茅台2025年的交互式K线图,支持以下功能:
移动鼠标显示悬停提示,包含K线图和成交量的详细数据
鼠标滚轮缩放图表
按住鼠标左键拖动图表平移
点击X轴的范围选择器,可以快速切换显示的时间范围(1月、3月、6月、全部)
点击右上角的下载按钮,可以下载图片或数据
点击图例可以显示或隐藏对应的线条
9.1.6 基础知识拓展:交互式可视化的应用场景
1.股票分析:分析师可以通过交互式K线图快速查看股票的走势、成交量、均线等数据,提高分析效率
2.量化策略回测:量化交易员可以通过交互式可视化工具查看策略的回测结果,比如收益率、最大回撤、持仓情况等
3.数据报告:在数据报告中添加交互式可视化图表,读者可以自己操作查看数据,提高报告的可读性和互动性
4.教学演示:在教学中使用交互式可视化工具,可以更直观地展示数据的变化和趋势,提高教学效果
9.1.7 总结:三种交互式看盘工具的对比
| 工具 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Matplotlib | 自定义程度高,可以实现任何效果 | 代码复杂,交互性能一般 | 需要高度自定义的交互式可视化 |
| mplfinance | 语法简单,专门用于金融数据可视化 | 自定义程度较低 | 快速绘制专业的金融交互式图表 |
| plotly | plotly | 交互功能丰富,图表美观,支持网页展示 | 代码相对复杂,需要学习plotly的语法 需要在网页中展示的交互式可视化 |
通过这个实战,你应该已经掌握了三种交互式看盘工具的使用方法,接下来可以尝试用这些工具制作更专业的交互式股票分析工具,或者结合量化策略实现自动交易。
下一节咱们就讲如何用Python做量化策略回测,帮你验证策略的有效性。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlePrograme/csharp49705.html










