首页 > 编程开发 > python数据分析 >
-
Plotly优势:无需前端知识生成可交互网页
第11章 Plotly交互式可视化实战
11.1 Plotly优势:无需前端知识生成可交互网页
11.1.1 先讲个真实痛点:老板要我把分析结果做成网页
上个月老板让我把股票分析结果做成网页,方便公司同事查看。我之前只会用Matplotlib画静态图,完全不会前端开发,急得团团转。后来发现Plotly可以直接生成交互式网页,不需要写一行HTML、CSS或JavaScript代码,只用Python就vb.net教程C#教程python教程SQL教程access 2010教程能搞定。今天我就把Plotly的优势和实战方法讲清楚,帮你快速做出专业的交互式网页。
11.1.2 Plotly的核心优势
-
无需前端知识
Plotly可以直接用Python代码生成交互式网页,不需要写HTML、CSS或JavaScript代码,非常适合不懂前端开发的数据分析人员。 -
交互功能丰富
Plotly支持多种交互功能,比如悬停提示、缩放、平移、下载图片、数据筛选等,用户可以自己操作查看数据,提高分析效率。 -
图表美观
Plotly的图表样式非常美观,支持多种主题和自定义样式,可以满足不同的需求。 -
支持网页展示
Plotly生成的网页可以直接在浏览器中打开,也可以部署到服务器上,方便团队协作和分享。 -
支持多种图表类型
Plotly支持多种图表类型,包括K线图、折线图、柱状图、散点图、热力图、3D图等,可以满足不同的可视化需求。
11.1.3 实战1:用Plotly生成交互式K线图网页
-
实战代码:Plotly交互式K线图网页
python
# 1. 导入需要的库
import tushare as ts
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# 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['ma5'] = df['close'].rolling(window=5).mean()
df['ma20'] = df['close'].rolling(window=20).mean()
df['ma60'] = df['close'].rolling(window=60).mean()
# 计算涨跌颜色
df['color'] = df['close'] >= df['open']
# 4. 创建子图
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
)
# 5. 添加K线图到第一个子图
fig.add_trace(
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线颜色
increasing_fillcolor='rgba(255, 0, 0, 0.3)', # 上涨K线填充颜色,半透明
decreasing_fillcolor='rgba(0, 255, 0, 0.3)' # 下跌K线填充颜色,半透明
),
row=1, col=1
)
# 6. 添加均线到第一个子图
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['ma5'],
name='5日均线',
line=dict(color='#1f77b4', width=2), # 蓝色线条,宽度2
opacity=0.8 # 透明度0.8
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['ma20'],
name='20日均线',
line=dict(color='#ff7f0e', width=2), # 橙色线条,宽度2
opacity=0.8
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['ma60'],
name='60日均线',
line=dict(color='#2ca02c', width=2), # 绿色线条,宽度2
opacity=0.8
),
row=1, col=1
)
# 7. 添加成交量柱形图到第二个子图
fig.add_trace(
go.Bar(
x=df['trade_date'],
y=df['vol'],
name='成交量',
marker_color=df['color'].map({True: 'red', False: 'green'}), # 根据涨跌颜色设置柱形图颜色
opacity=0.7 # 透明度0.7
),
row=2, col=1
)
# 8. 设置图表布局
fig.update_layout(
title={
'text': '贵州茅台2025年交互式K线图', # 图表标题
'y': 0.95, # 标题垂直位置
'x': 0.5, # 标题水平位置,居中
'xanchor': 'center', # 标题水平锚点,居中
'yanchor': 'top' # 标题垂直锚点,顶部
},
yaxis_title='价格(元)', # 第一个子图Y轴标签
yaxis2_title='成交量(手)', # 第二个子图Y轴标签
xaxis_title='日期', # X轴标签
height=800, # 图表高度
width=1200, # 图表宽度
template='plotly_white', # 使用白色模板
hovermode='x unified', # 悬停时显示同一X轴的所有数据
legend={
'x': 0.02, # 图例水平位置
'y': 0.98, # 图例垂直位置
'bgcolor': 'rgba(255, 255, 255, 0.8)', # 图例背景颜色,半透明
'bordercolor': '#333333', # 图例边框颜色
'borderwidth': 1 # 图例边框宽度
}
)
# 9. 设置X轴和Y轴的范围
fig.update_xaxes(
rangeslider_visible=False, # 隐藏X轴的范围滑块
rangeselector=dict(
buttons=list([
dict(count=1, label='1月', step='month', stepmode='backward'), # 显示最近1个月的数据
dict(count=3, label='3月', step='month', stepmode='backward'), # 显示最近3个月的数据
dict(count=6, label='6月', step='month', stepmode='backward'), # 显示最近6个月的数据
dict(step='all', label='全部') # 显示全部数据
]),
x=0.02, # 范围选择器水平位置
y=1.05, # 范围选择器垂直位置
bgcolor='rgba(255, 255, 255, 0.8)', # 范围选择器背景颜色
bordercolor='#333333', # 范围选择器边框颜色
borderwidth=1 # 范围选择器边框宽度
)
)
# 10. 设置Y轴的范围和网格线
fig.update_yaxes(
gridcolor='#cccccc', # 网格线颜色
gridwidth=1, # 网格线宽度
griddash='--' # 网格线样式,虚线
)
# 11. 保存网页
fig.write_html('贵州茅台2025年交互式K线图.html')
# 12. 显示图表
fig.show()
逐行讲解:
from plotly.subplots import make_subplots:导入make_subplots函数,用于创建子图
fig = make_subplots(...):创建2行1列的子图,共享X轴,这样移动X轴时两个子图会同步
go.Candlestick(...):创建K线图,支持设置上涨和下跌的颜色、填充颜色等
go.Scatter(...):创建均线,支持设置线条颜色、宽度、透明度等
go.Bar(...):创建成交量柱形图,支持根据涨跌颜色设置柱形图颜色
fig.update_layout(...):设置图表布局,包括标题、坐标轴标签、高度、宽度、主题、悬停模式、图例等
fig.update_xaxes(...):设置X轴的范围滑块和范围选择器,范围选择器可以快速切换显示的时间范围
fig.update_yaxes(...):设置Y轴的网格线样式
fig.write_html('贵州茅台2025年交互式K线图.html'):把图表保存为HTML文件,不需要前端知识就能生成交互式网页
fig.show():在浏览器中打开图表,查看交互式效果
运行结果:
1.会在浏览器中打开一个网页,显示贵州茅台2025年的交互式K线图,支持以下功能:
移动鼠标显示悬停提示,包含K线图和成交量的详细数据
鼠标滚轮缩放图表
按住鼠标左键拖动图表平移
点击X轴的范围选择器,可以快速切换显示的时间范围(1月、3月、6月、全部)
点击图例可以显示或隐藏对应的线条
点击右上角的下载按钮,可以下载图片、SVG、PDF或数据
2.同时会在当前目录下生成一个HTML文件,双击该文件可以直接在浏览器中打开,不需要服务器支持。
11.1.4 实战2:用Plotly生成完整技术分析网页
-
实战代码:Plotly完整技术分析网页
python
# 1. 导入需要的库
import tushare as ts
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
# 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()
# 计算MACD
ema12 = df['close'].ewm(span=12, adjust=False).mean()
ema26 = df['close'].ewm(span=26, adjust=False).mean()
df['dif'] = ema12 - ema26
df['dea'] = df['dif'].ewm(span=9, adjust=False).mean()
df['macd'] = 2 * (df['dif'] - df['dea'])
# 计算KDJ
low9 = df['low'].rolling(window=9).min()
high9 = df['high'].rolling(window=9).max()
df['rsv'] = (df['close'] - low9) / (high9 - low9) * 100
df['k'] = np.nan
df['d'] = np.nan
df.loc[df.index[8], 'k'] = df.loc[df.index[8], 'rsv']
df.loc[df.index[8], 'd'] = df.loc[df.index[8], 'rsv']
for i in range(9, len(df)):
df.loc[df.index[i], 'k'] = (2/3) * df.loc[df.index[i-1], 'k'] + (1/3) * df.loc[df.index[i], 'rsv']
df.loc[df.index[i], 'd'] = (2/3) * df.loc[df.index[i-1], 'd'] + (1/3) * df.loc[df.index[i], 'k']
df['j'] = 3 * df['k'] - 2 * df['d']
# 计算RSI
df['change'] = df['close'].diff()
df['up'] = np.where(df['change'] > 0, df['change'], 0)
df['down'] = np.where(df['change'] < 0, -df['change'], 0)
up6 = df['up'].rolling(window=6).mean()
down6 = df['down'].rolling(window=6).mean()
df['rsi6'] = up6 / (up6 + down6) * 100
# 计算BOLL
df['mid'] = df['close'].rolling(window=20).mean()
df['std'] = df['close'].rolling(window=20).std()
df['upper'] = df['mid'] + 2 * df['std']
df['lower'] = df['mid'] - 2 * df['std']
# 5. 创建子图
fig = make_subplots(
rows=4, cols=1, # 4行1列的子图
shared_xaxes=True, # 共享X轴
vertical_spacing=0.05, # 子图之间的垂直间距
row_heights=[0.4, 0.2, 0.2, 0.2] # 子图的高度比例,4:2:2:2
)
# 6. 添加K线图和BOLL指标到第一个子图
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',
increasing_fillcolor='rgba(255, 0, 0, 0.3)',
decreasing_fillcolor='rgba(0, 255, 0, 0.3)'
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['upper'],
name='BOLL上轨',
line=dict(color='#ff7f0e', width=1, dash='dash'), # 橙色虚线,宽度1
opacity=0.8
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['mid'],
name='BOLL中轨',
line=dict(color='#2ca02c', width=1, dash='dash'), # 绿色虚线,宽度1
opacity=0.8
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['lower'],
name='BOLL下轨',
line=dict(color='#d62728', width=1, dash='dash'), # 红色虚线,宽度1
opacity=0.8
),
row=1, col=1
)
# 填充BOLL上轨和下轨之间的区域
fig.add_trace(
go.Scatter(
x=df['trade_date'].append(df['trade_date'].iloc[::-1]), # X轴数据,正序+倒序
y=df['upper'].append(df['lower'].iloc[::-1]), # Y轴数据,上轨正序+下轨倒序
fill='toself', # 填充到自身
fillcolor='rgba(200, 200, 200, 0.2)', # 填充颜色,灰色半透明
line=dict(color='rgba(255, 255, 255, 0)'), # 隐藏线条
name='BOLL区间'
),
row=1, col=1
)
# 7. 添加成交量柱形图到第二个子图
fig.add_trace(
go.Bar(
x=df['trade_date'],
y=df['vol'],
name='成交量',
marker_color=np.where(df['close'] >= df['open'], 'red', 'green'),
opacity=0.7
),
row=2, col=1
)
# 8. 添加MACD指标到第三个子图
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['dif'],
name='DIF(快线)',
line=dict(color='#1f77b4', width=2),
opacity=0.8
),
row=3, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['dea'],
name='DEA(慢线)',
line=dict(color='#ff7f0e', width=2),
opacity=0.8
),
row=3, col=1
)
fig.add_trace(
go.Bar(
x=df['trade_date'],
y=df['macd'],
name='MACD柱状图',
marker_color=np.where(df['macd'] > 0, '#1f77b4', '#d62728'),
opacity=0.5
),
row=3, col=1
)
# 9. 添加KDJ和RSI指标到第四个子图
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['k'],
name='K线',
line=dict(color='#1f77b4', width=2),
opacity=0.8
),
row=4, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['d'],
name='D线',
line=dict(color='#ff7f0e', width=2),
opacity=0.8
),
row=4, col=1
)
fig.add_trace(
go.Scatter(
x=df['trade_date'],
y=df['rsi6'],
name='6日RSI',
line=dict(color='#2ca02c', width=2),
opacity=0.8
),
row=4, col=1
)
# 添加超买超卖线
fig.add_hline(
y=80, # KDJ超买线
line=dict(color='#d62728', width=1, dash='dash'),
row=4, col=1
)
fig.add_hline(
y=20, # KDJ超卖线
line=dict(color='#2ca02c', width=1, dash='dash'),
row=4, col=1
)
fig.add_hline(
y=70, # RSI超买线
line=dict(color='#d62728', width=1, dash='dash'),
row=4, col=1
)
fig.add_hline(
y=30, # RSI超卖线
line=dict(color='#2ca02c', width=1, dash='dash'),
row=4, col=1
)
# 10. 设置图表布局
fig.update_layout(
title={
'text': '贵州茅台2025年完整技术分析面板',
'y': 0.98,
'x': 0.5,
'xanchor': 'center',
'yanchor': 'top',
'font': dict(size=20, color='#333333')
},
yaxis_title='价格(元)',
yaxis2_title='成交量(手)',
yaxis3_title='MACD',
yaxis4_title='KDJ / RSI',
xaxis_title='日期',
height=1200,
width=1200,
template='plotly_white',
hovermode='x unified',
legend={
'x': 0.02,
'y': 0.98,
'bgcolor': 'rgba(255, 255, 255, 0.8)',
'bordercolor': '#333333',
'borderwidth': 1,
'font': dict(size=10)
},
margin=dict(l=50, r=50, t=80, b=50) # 图表边距
)
# 11. 设置X轴和Y轴的样式
fig.update_xaxes(
rangeslider_visible=False,
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='全部')
]),
x=0.02,
y=1.05,
bgcolor='rgba(255, 255, 255, 0.8)',
bordercolor='#333333',
borderwidth=1
),
tickformat='%Y-%m-%d', # X轴日期格式
tickangle=45 # X轴标签旋转45度
)
fig.update_yaxes(
gridcolor='#cccccc',
gridwidth=1,
griddash='--'
)
# 12. 保存网页
fig.write_html('贵州茅台2025年完整技术分析面板.html')
# 13. 显示图表
fig.show()
逐行讲解:
fig = make_subplots(rows=4, cols=1, ...):创建4行1列的子图,分别显示K线图+BOLL、成交量、MACD、KDJ+RSI
fig.add_hline(...):添加水平直线,用于显示KDJ和RSI的超买超卖线
fig.update_layout(...):设置图表布局,包括标题、坐标轴标签、高度、宽度、主题、悬停模式、图例、边距等
fig.write_html('贵州茅台2025年完整技术分析面板.html'):把完整技术分析面板保存为HTML文件
运行结果:
会在浏览器中打开一个网页,显示贵州茅台2025年的完整技术分析面板,支持交互式操作,同时会在当前目录下生成一个HTML文件,方便分享和查看。
11.1.5 基础知识拓展:Plotly的高级功能
-
自定义悬停提示
可以通过hovertemplate参数自定义悬停提示的内容,比如:
python
go.Candlestick(
x=df['trade_date'],
open=df['open'],
high=df['high'],
low=df['low'],
close=df['close'],
hovertemplate='日期: %{x}<br>'
'开盘价: %{open:.2f}元<br>'
'最高价: %{high:.2f}元<br>'
'最低价: %{low:.2f}元<br>'
'收盘价: %{close:.2f}元<br>'
'<extra></extra>' # 隐藏默认的额外信息
)
-
动画效果
Plotly支持动画效果,可以通过animation_frame参数实现,比如:
python
go.Scatter(
x=df['trade_date'],
y=df['close'],
animation_frame=df['trade_date'].dt.year, # 按年份分帧
name='收盘价'
)
-
3D可视化
Plotly支持3D可视化,比如3D散点图、3D曲面图等,比如:
python
go.Scatter3d(
x=df['open'],
y=df['high'],
z=df['low'],
mode='markers',
marker=dict(size=5, color=df['close'], colorscale='Viridis')
)
-
数据筛选
Plotly支持数据筛选,可以通过updatemenus参数实现,比如:
python
updatemenus = [
dict(
buttons=list([
dict(
label='贵州茅台',
method='update',
args=[{'x': [df['trade_date']], 'y': [df['close']]}]
),
dict(
label='五粮液',
method='update',
args=[{'x': [df_wly['trade_date']], 'y': [df_wly['close']]}]
)
]),
direction='down',
showactive=True
)
]
fig.update_layout(updatemenus=updatemenus)
11.1.6 总结:Plotly的应用场景
1.数据报告:在数据报告中添加Plotly交互式图表,读者可以自己操作查看数据,提高报告的可读性和互动性
2.网页展示:把Plotly生成的HTML文件部署到服务器上,方便团队协作和分享
3.量化交易:用Plotly生成实时监控网页,监控股票的走势和技术指标,当指标达到预设条件时自动执行交易
4.教学演示:在教学中使用Plotly交互式图表,可以更直观地展示数据的变化和趋势,提高教学效果
通过这个实战,你应该已经掌握了用Plotly生成交互式网页的方法,接下来可以尝试用这些方法制作更专业的数据分析工具和可视化报告。
下一节咱们就讲如何用Python做量化策略回测,帮你验证策略的有效性。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlePrograme/csharp49707.html










