Python Plotly动态图表100例:金融股票与地理信息可视化代码模板
构建金融量化与空间地理交互分析界面时,原生静态图表往往难以兼顾局部缩放、多轴联动与悬停明细检索。本文聚焦于 Python plotly 库在金融股票(K线图、量价联动、技术指标)与地理空间(经纬度散点、热力密度、区域分级着色)两大垂直场景的生产级可视化范式,提供开箱即用的高频代码模板与参数解析。
一、架构选型:Plotly Express 与 Graph Objects 的核心差异
Plotly 提供了高层快速封装接口 plotly.express (px) 与底层细粒度构建接口 plotly.graph_objects (go)。理解两者的设计边界与适用场景,是避免代码返工的关键第一步。
| 对比维度 | Plotly Express (px) | Plotly Graph Objects (go) |
|---|---|---|
| 设计哲学 | 针对规整数据(Tidy Data)的声明式快速调用,一行代码生成标准图表。 | 命令式组装图元,自由控制每一个 trace、坐标轴与图层几何属性。 |
| 多子图能力 | 通过 facet_row / facet_col 自动栅格化,但子图类型必须严格一致。 |
支持 make_subplots,可自由混合不同类型图元(如上方Candlestick下方Bar)。 |
| 坐标系与联动 | 适合统一的连续坐标或离散分类轴,复杂的跨轴联动与范围过滤器受限。 | 原生支持 spikelines(十字准星)、rangeslider、跳过休市日(rangebreaks)。 |
| 推荐业务场景 | 宏观地理分布、点位密度、快速探索性数据分析(EDA)。 | 金融股票量价盘口、多周期技术指标、多图层复合叠加。 |
二、图表工程执行管道:从数据流到离线渲染
无论渲染股票序列还是地理矢量,Plotly 的标准构建链路均遵循“数据清洗规整 → Figure 容器构造 → 多图层装配 → 交互与坐标轴约束 → 序列化导出”五个固定阶段。明确这一流程能够确保图表在各种生产环境下稳定运行。
三、金融股票可视化代码模板
金融量化分析对图表的核心要求包括:主图价格与技术指标(均线、布林带)叠加、副图成交量与动量振荡指标(MACD、RSI)严格对齐、鼠标十字准星全轴联动,以及通过过滤器去除周末与节假日的断档空白。
模板 1:标准股票量价联动面板(含非交易日空隙过滤)
此模板采用 plotly.subplots.make_subplots 划分上下行高比为 7:3 的双子图,共享时间轴 xaxis,并通过 rangebreaks 参数剔除周六与周日,使得时间跨度在视觉上保持等间距连续。
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np
def create_stock_volume_panel(df: pd.DataFrame, ticker: str = "600519.SH") -> go.Figure:
"""
生成标准量价联动看板
df 包含列: date, open, high, low, close, volume, ma20, ma60
"""
fig = make_subplots(
rows=2, cols=1,
shared_xaxes=True,
vertical_spacing=0.03,
row_heights=[0.7, 0.3],
subplot_titles=(f"{ticker} 价格走势与均线系统", "成交量 (Volume)")
)
# 1. 主图:K线图 (Candlestick)
fig.add_trace(
go.Candlestick(
x=df['date'],
open=df['open'],
high=df['high'],
low=df['low'],
close=df['close'],
name="K线",
increasing_line_color="#E53E3E", # 阳线红
decreasing_line_color="#38A169" # 阴线绿
),
row=1, col=1
)
# 2. 主图:20日均线
fig.add_trace(
go.Scatter(
x=df['date'], y=df['ma20'],
mode='lines',
line=dict(color='#3182CE', width=1.5),
name="MA20"
),
row=1, col=1
)
# 3. 副图:成交量柱状图
vol_colors = np.where(df['close'] >= df['open'], '#E53E3E', '#38A169')
fig.add_trace(
go.Bar(
x=df['date'], y=df['volume'],
marker_color=vol_colors,
name="成交量",
showlegend=False
),
row=2, col=1
)
# 4. 坐标轴与交互设置
fig.update_layout(
height=650,
margin=dict(l=50, r=50, t=50, b=40),
hovermode="x unified",
template="plotly_white",
xaxis2=dict(
rangeslider=dict(visible=False),
type="date"
)
)
# 5. 过滤周末空隙(避免时间轴断层)
fig.update_xaxes(
rangebreaks=[dict(bounds=["sat", "mon"])],
showspikes=True,
spikemode="across",
spikesnap="cursor",
spikethickness=1,
spikedash="solid"
)
return fig
rangeslider。如果未显式将其隐藏(即 xaxis_rangeslider_visible=False),副图区域会被挤压变形,导致高度比例严重失衡。
模板 2:布林通道与动态交易信号标注模板
量化回测展示中常需展示上轨、中轨、下轨组成的区间通道,并使用 annotations 或散点图标出买入与卖出信号。通过 fill='tonexty' 可直接在两条曲线间填充半透明背景带。
def add_bollinger_bands_with_signals(fig: go.Figure, df: pd.DataFrame) -> go.Figure:
"""
向现有主图中叠加布林带(Upper/Middle/Lower)与买卖点标记
"""
# 1. 布林带上轨
fig.add_trace(
go.Scatter(
x=df['date'], y=df['bb_upper'],
mode='lines',
line=dict(color='rgba(150, 150, 150, 0.4)', width=1),
name="BB Upper",
showlegend=False
),
row=1, col=1
)
# 2. 布林带下轨并填充通道背景色
fig.add_trace(
go.Scatter(
x=df['date'], y=df['bb_lower'],
mode='lines',
line=dict(color='rgba(150, 150, 150, 0.4)', width=1),
fill='tonexty',
fillcolor='rgba(200, 220, 240, 0.15)',
name="BB Lower",
showlegend=False
),
row=1, col=1
)
# 3. 买入信号(三角形箭头标记)
buy_signals = df[df['signal'] == 1]
fig.add_trace(
go.Scatter(
x=buy_signals['date'],
y=buy_signals['low'] * 0.98,
mode='markers',
marker=dict(symbol='triangle-up', size=11, color='#E53E3E'),
name="买入信号"
),
row=1, col=1
)
return fig
四、地理信息(GIS)动态可视化代码模板
空间地理分析场景主要分为离散点位分布(如营业网点、充电桩分布)、表面连续强度分布(如降雨热力、客流密度)以及基于行政区划的统计汇总(如各省份销售额分级着色)。
模板 3:空间点位与密度热力图模板(Scatter_mapbox & Density_mapbox)
在呈现点位密集或海量轨迹时,普通散点容易产生严重的遮挡叠压。通过 density_mapbox 能够基于高斯核密度估计快速转换为空间连续曲面;而 scatter_mapbox 则适合保留单个地标的交互悬停。
import plotly.express as px
import pandas as pd
def create_geospatial_density_map(df: pd.DataFrame) -> go.Figure:
"""
df 包含: lat(纬度), lon(经度), value(辐射强度/客流), city(城市标签)
使用开源 OpenStreetMap 瓦片源,无需申请商业 API Key
"""
fig = px.density_mapbox(
df,
lat="lat",
lon="lon",
z="value",
radius=18,
center=dict(lat=34.3416, lon=108.9398), # 默认中心定位
zoom=4,
mapbox_style="open-street-map",
hover_name="city",
hover_data={"lat": False, "lon": False, "value": ":.2f"},
title="全国区域客流热力密度分布"
)
fig.update_layout(
margin=dict(l=0, r=0, t=45, b=0),
height=600,
font=dict(family="system-ui, sans-serif")
)
return fig
模板 4:行政区划 Choropleth 分级色彩地图模板
分级色彩图(Choropleth)要求输入标准 GeoJSON 数据。关联时需特别注意两个关键匹配字段:一是 GeoJSON 中 features[i].properties 下的键名(通过 featureidkey 声明),二是 Pandas DataFrame 中与之对应的名称列(通过 locations 传入)。
def create_choropleth_map(df_region: pd.DataFrame, geojson_data: dict) -> go.Figure:
"""
df_region 包含列: region_name(省份/城市), gdp_growth(指标数值)
geojson_data 为解析后的字典对象
"""
fig = px.choropleth(
df_region,
geojson=geojson_data,
featureidkey="properties.name",
locations="region_name",
color="gdp_growth",
color_continuous_scale="Blues",
range_color=(0, df_region['gdp_growth'].max()),
title="各区域经济指标分级着色分布"
)
# 聚焦到中国范围投影
fig.update_geos(
fitbounds="locations",
visible=False
)
fig.update_layout(
height=620,
margin=dict(l=0, r=0, t=45, b=0)
)
return fig
五、交付与生产性能优化指南
在生成包含成千上万个数据点的动态图表时,若不加节制,导出的 HTML 往往可达十几兆甚至几十兆,严重拖慢渲染响应速度。以下是确保图表轻量化与高可用交付的关键策略:
-
JS 脚本引用方式:调用
fig.write_html()时,默认会将约 3MB 的plotly.js原生代码完整内联进每一个 HTML 文件中。若批量生成图表,应指定include_plotlyjs='cdn',或者将静态脚本统一托管在公司内网 CDN。 -
海量点位转用 WebGL 渲染管线:对于超过 20,000 个采样点的股票 Tick 数据或 GPS 轨迹,将
go.Scatter替换为go.Scattergl。底层将由 SVG DOM 渲染切换为 GPU 驱动的 WebGL Canvas,避免浏览器界面卡死。 -
精简 Hover 模板:默认 Hover 提示包含大量坐标格式计算,通过
hovertemplate="时间: %{x}自定义模板并关闭副图多余的指示图例,能够减少冗余计算开销。
价格: ¥%{y:.2f}"
# 生产环境高效导出配置示例
fig.write_html(
"stock_report_deliverable.html",
include_plotlyjs="cdn", # 使用 CDN 外部加载,单文件体积从 3.5MB 骤降至 40KB
full_html=True,
config={
"scrollZoom": True, # 支持鼠标滚轮缩放
"displayModeBar": True, # 始终显示控制栏
"displaylogo": False, # 移除 Plotly 官方水印
"modeBarButtonsToRemove": ["lasso2d", "select2d"] # 移除无关选框工具
}
)
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









