trading-visualization
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTrading Visualization
交易可视化
Visualization is the primary interface between a trader and their data. Charts reveal patterns that tables and numbers cannot: breakdowns in strategy, regime transitions, clustering of losses, and the shape of risk. A well-designed chart communicates more in a glance than a page of statistics.
Three uses of trading charts:
- Pattern recognition — Spot structural changes in price, volume, and momentum that quantitative filters miss.
- Strategy evaluation — Equity curves, drawdown plots, and return distributions expose whether a strategy is robust or curve-fit.
- Reporting — Communicate performance to stakeholders, journals, or your future self with publication-quality visuals.
可视化是交易者与数据之间的主要交互界面。图表能够展现表格和数字无法呈现的模式:策略失效、市场状态转换、亏损集中情况以及风险形态。设计精良的图表一眼传达的信息,胜过一页统计数据。
交易图表的三大用途:
- 模式识别 — 发现量化过滤器遗漏的价格、成交量和动量的结构性变化。
- 策略评估 — 权益曲线、回撤图和收益分布图能揭示策略是稳健可靠还是过拟合。
- 报告展示 — 用出版级别的可视化效果向利益相关方、期刊或未来的自己展示业绩表现。
Chart Types Covered
涵盖的图表类型
| Chart Type | Purpose | Library |
|---|---|---|
| Candlestick | OHLCV price action with overlays | mplfinance |
| Equity curve | Portfolio value over time | matplotlib |
| Drawdown | Underwater equity plot | matplotlib |
| Return distribution | Histogram + normal fit | matplotlib |
| Correlation heatmap | Cross-asset correlation matrix | matplotlib / seaborn |
| Trade markers | Entry/exit points on price chart | mplfinance / matplotlib |
| Indicator panels | RSI, MACD below price chart | mplfinance |
| Position timeline | When positions were held | matplotlib |
| 图表类型 | 用途 | 库 |
|---|---|---|
| K线图 | 带叠加层的OHLCV价格走势 | mplfinance |
| 权益曲线 | 投资组合随时间的价值变化 | matplotlib |
| 回撤图 | 水下权益图 | matplotlib |
| 收益分布图 | 直方图+正态拟合 | matplotlib |
| 相关性热力图 | 跨资产相关矩阵 | matplotlib / seaborn |
| 交易标记 | 价格图表上的进出点位 | mplfinance / matplotlib |
| 指标面板 | 价格图表下方的RSI、MACD | mplfinance |
| 持仓时间线 | 持仓时间段 | matplotlib |
Libraries
相关库
mplfinance
mplfinance
Best for candlestick charts. Built on matplotlib with finance-specific defaults.
bash
uv pip install mplfinancepython
import mplfinance as mpf最适合绘制K线图。基于matplotlib构建,带有金融领域专属默认设置。
bash
uv pip install mplfinancepython
import mplfinance as mpfBasic candlestick from a DataFrame with DatetimeIndex
基于带DatetimeIndex的DataFrame绘制基础K线图
Columns: Open, High, Low, Close, Volume
列:Open, High, Low, Close, Volume
mpf.plot(df, type="candle", volume=True, style="charles")
Key features:
- Native OHLCV support — pass a DataFrame directly
- Built-in volume bars
- `addplot` for overlays (moving averages, Bollinger Bands)
- Custom styles via `mpf.make_mpf_style()`mpf.plot(df, type="candle", volume=True, style="charles")
核心特性:
- 原生OHLCV支持 — 直接传入DataFrame
- 内置成交量柱状图
- `addplot`用于叠加层(移动平均线、布林带)
- 通过`mpf.make_mpf_style()`自定义样式matplotlib
matplotlib
General purpose, most flexible. Use when you need full control over layout.
bash
uv pip install matplotlibpython
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 1, figsize=(14, 8), height_ratios=[3, 1],
sharex=True)
axes[0].plot(dates, equity, color="#00ff88")
axes[1].fill_between(dates, drawdown, 0, color="#ff4444", alpha=0.5)通用绘图库,灵活性最强。需要完全控制布局时使用。
bash
uv pip install matplotlibpython
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 1, figsize=(14, 8), height_ratios=[3, 1],
sharex=True)
axes[0].plot(dates, equity, color="#00ff88")
axes[1].fill_between(dates, drawdown, 0, color="#ff4444", alpha=0.5)plotly
plotly
Interactive charts rendered as HTML. Best for exploration and dashboards.
bash
uv pip install plotlypython
import plotly.graph_objects as go
fig = go.Figure(data=[go.Candlestick(
x=df.index, open=df["Open"], high=df["High"],
low=df["Low"], close=df["Close"]
)])
fig.update_layout(template="plotly_dark")
fig.write_html("chart.html")渲染为HTML的交互式图表。最适合探索分析和仪表盘。
bash
uv pip install plotlypython
import plotly.graph_objects as go
fig = go.Figure(data=[go.Candlestick(
x=df.index, open=df["Open"], high=df["High"],
low=df["Low"], close=df["Close"]
)])
fig.update_layout(template="plotly_dark")
fig.write_html("chart.html")Styling: Dark Theme Default
样式:默认深色主题
Trading terminals use dark backgrounds by default. All charts in this skill follow that convention.
交易终端默认使用深色背景。本技能中的所有图表均遵循此惯例。
Quick dark theme setup
快速设置深色主题
python
import matplotlib.pyplot as plt
plt.style.use("dark_background")
plt.rcParams.update({
"figure.facecolor": "#1a1a2e",
"axes.facecolor": "#1a1a2e",
"axes.edgecolor": "#333333",
"grid.color": "#333333",
"grid.alpha": 0.4,
"text.color": "#e0e0e0",
"xtick.color": "#aaaaaa",
"ytick.color": "#aaaaaa",
})python
import matplotlib.pyplot as plt
plt.style.use("dark_background")
plt.rcParams.update({
"figure.facecolor": "#1a1a2e",
"axes.facecolor": "#1a1a2e",
"axes.edgecolor": "#333333",
"grid.color": "#333333",
"grid.alpha": 0.4,
"text.color": "#e0e0e0",
"xtick.color": "#aaaaaa",
"ytick.color": "#aaaaaa",
})Trading color scheme
交易配色方案
| Element | Color | Hex |
|---|---|---|
| Bullish / profit | Green | |
| Bearish / loss | Red | |
| Neutral / info | Blue | |
| Warning | Amber | |
| MA short | Orange | |
| MA long | Blue | |
| MA signal | Yellow | |
See for complete typography, layout ratios, and export settings.
references/styling_guide.md| 元素 | 颜色 | 十六进制码 |
|---|---|---|
| 上涨/盈利 | 绿色 | |
| 下跌/亏损 | 红色 | |
| 中性/信息 | 蓝色 | |
| 警告 | 琥珀色 | |
| 短期均线 | 橙色 | |
| 长期均线 | 蓝色 | |
| 信号均线 | 黄色 | |
完整的排版、布局比例和导出设置请查看。
references/styling_guide.mdChart Composition: Multi-Panel Layout
图表布局:多面板结构
Most trading charts need multiple synchronized panels — price on top, volume in the middle, indicators at the bottom.
大多数交易图表需要多个同步面板 — 顶部价格图、中间成交量、底部指标。
Stacked panels with shared x-axis
共享X轴的堆叠面板
python
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure(figsize=(14, 10))
gs = gridspec.GridSpec(3, 1, height_ratios=[3, 1, 1], hspace=0.05)
ax_price = fig.add_subplot(gs[0])
ax_volume = fig.add_subplot(gs[1], sharex=ax_price)
ax_rsi = fig.add_subplot(gs[2], sharex=ax_price)python
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure(figsize=(14, 10))
gs = gridspec.GridSpec(3, 1, height_ratios=[3, 1, 1], hspace=0.05)
ax_price = fig.add_subplot(gs[0])
ax_volume = fig.add_subplot(gs[1], sharex=ax_price)
ax_rsi = fig.add_subplot(gs[2], sharex=ax_price)Hide x-tick labels on upper panels
隐藏上方面板的X轴刻度标签
ax_price.tick_params(labelbottom=False)
ax_volume.tick_params(labelbottom=False)
undefinedax_price.tick_params(labelbottom=False)
ax_volume.tick_params(labelbottom=False)
undefinedPanel height ratios
面板高度比例
| Layout | Ratios | Use Case |
|---|---|---|
| Price + Volume | | Simple OHLCV chart |
| Price + Volume + Indicator | | Standard analysis view |
| Equity + Drawdown | | Performance review |
| Price + RSI + MACD | | Full indicator stack |
| 布局 | 比例 | 使用场景 |
|---|---|---|
| 价格+成交量 | | 简单OHLCV图表 |
| 价格+成交量+指标 | | 标准分析视图 |
| 权益+回撤 | | 业绩回顾 |
| 价格+RSI+MACD | | 完整指标堆叠 |
Candlestick Charts with Overlays
带叠加层的K线图
python
import mplfinance as mpf
import pandas as pdpython
import mplfinance as mpf
import pandas as pddf: DataFrame with DatetimeIndex, columns Open/High/Low/Close/Volume
df:带DatetimeIndex的DataFrame,列包含Open/High/Low/Close/Volume
ema20 = df["Close"].ewm(span=20).mean()
ema50 = df["Close"].ewm(span=50).mean()
ap = [
mpf.make_addplot(ema20, color="#ff6600", width=1.2),
mpf.make_addplot(ema50, color="#3399ff", width=1.2),
]
style = mpf.make_mpf_style(
base_mpf_style="nightclouds",
marketcolors=mpf.make_marketcolors(
up="#00ff88", down="#ff4444",
wick={"up": "#00ff88", "down": "#ff4444"},
edge={"up": "#00ff88", "down": "#ff4444"},
volume={"up": "#00ff88", "down": "#ff4444"},
),
facecolor="#1a1a2e", figcolor="#1a1a2e",
gridcolor="#333333", gridstyle="--",
)
mpf.plot(df, type="candle", style=style, addplot=ap,
volume=True, figsize=(14, 8),
title="Token / SOL — 15m", savefig="candles.png")
---ema20 = df["Close"].ewm(span=20).mean()
ema50 = df["Close"].ewm(span=50).mean()
ap = [
mpf.make_addplot(ema20, color="#ff6600", width=1.2),
mpf.make_addplot(ema50, color="#3399ff", width=1.2),
]
style = mpf.make_mpf_style(
base_mpf_style="nightclouds",
marketcolors=mpf.make_marketcolors(
up="#00ff88", down="#ff4444",
wick={"up": "#00ff88", "down": "#ff4444"},
edge={"up": "#00ff88", "down": "#ff4444"},
volume={"up": "#00ff88", "down": "#ff4444"},
),
facecolor="#1a1a2e", figcolor="#1a1a2e",
gridcolor="#333333", gridstyle="--",
)
mpf.plot(df, type="candle", style=style, addplot=ap,
volume=True, figsize=(14, 8),
title="Token / SOL — 15m", savefig="candles.png")
---Equity Curve with Drawdown Panel
带回撤面板的权益曲线
python
import numpy as np
import matplotlib.pyplot as plt
def plot_equity_drawdown(equity: pd.Series, title: str = "Portfolio") -> plt.Figure:
"""Plot equity curve with drawdown panel below."""
peak = equity.cummax()
drawdown = (equity - peak) / peak
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 8),
height_ratios=[2, 1], sharex=True)
ax1.plot(equity.index, equity, color="#00ff88", linewidth=1.5)
ax1.plot(equity.index, peak, color="#555555", linewidth=0.8,
linestyle="--", label="Peak")
ax1.set_title(title, fontsize=14, fontweight="bold", color="white")
ax1.set_ylabel("Portfolio Value", fontsize=11)
ax1.legend(loc="upper left")
ax1.grid(True, alpha=0.3)
ax2.fill_between(equity.index, drawdown, 0, color="#ff4444", alpha=0.5)
ax2.set_ylabel("Drawdown", fontsize=11)
ax2.set_xlabel("Date", fontsize=11)
ax2.grid(True, alpha=0.3)
fig.tight_layout()
return figpython
import numpy as np
import matplotlib.pyplot as plt
def plot_equity_drawdown(equity: pd.Series, title: str = "Portfolio") -> plt.Figure:
"""绘制权益曲线,下方附带回撤面板。"""
peak = equity.cummax()
drawdown = (equity - peak) / peak
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 8),
height_ratios=[2, 1], sharex=True)
ax1.plot(equity.index, equity, color="#00ff88", linewidth=1.5)
ax1.plot(equity.index, peak, color="#555555", linewidth=0.8,
linestyle="--", label="Peak")
ax1.set_title(title, fontsize=14, fontweight="bold", color="white")
ax1.set_ylabel("投资组合价值", fontsize=11)
ax1.legend(loc="upper left")
ax1.grid(True, alpha=0.3)
ax2.fill_between(equity.index, drawdown, 0, color="#ff4444", alpha=0.5)
ax2.set_ylabel("回撤", fontsize=11)
ax2.set_xlabel("日期", fontsize=11)
ax2.grid(True, alpha=0.3)
fig.tight_layout()
return figReturn Distribution
收益分布图
python
from scipy import stats
def plot_return_distribution(returns: pd.Series) -> plt.Figure:
"""Histogram of returns with normal fit and risk metrics."""
fig, ax = plt.subplots(figsize=(10, 6))
ax.hist(returns, bins=50, density=True, alpha=0.7,
color="#4488ff", edgecolor="#333333")
# Normal fit overlay
mu, sigma = returns.mean(), returns.std()
x = np.linspace(returns.min(), returns.max(), 200)
ax.plot(x, stats.norm.pdf(x, mu, sigma), color="#ffaa00",
linewidth=2, label=f"Normal(μ={mu:.4f}, σ={sigma:.4f})")
# VaR line
var_95 = returns.quantile(0.05)
ax.axvline(var_95, color="#ff4444", linestyle="--",
label=f"VaR 95%: {var_95:.4f}")
ax.set_title("Return Distribution", fontsize=14, fontweight="bold")
ax.set_xlabel("Return", fontsize=11)
ax.legend()
ax.grid(True, alpha=0.3)
fig.tight_layout()
return figpython
from scipy import stats
def plot_return_distribution(returns: pd.Series) -> plt.Figure:
"""收益直方图,附带正态拟合和风险指标。"""
fig, ax = plt.subplots(figsize=(10, 6))
ax.hist(returns, bins=50, density=True, alpha=0.7,
color="#4488ff", edgecolor="#333333")
# 正态拟合叠加层
mu, sigma = returns.mean(), returns.std()
x = np.linspace(returns.min(), returns.max(), 200)
ax.plot(x, stats.norm.pdf(x, mu, sigma), color="#ffaa00",
linewidth=2, label=f"Normal(μ={mu:.4f}, σ={sigma:.4f})")
# VaR线
var_95 = returns.quantile(0.05)
ax.axvline(var_95, color="#ff4444", linestyle="--",
label=f"VaR 95%: {var_95:.4f}")
ax.set_title("收益分布", fontsize=14, fontweight="bold")
ax.set_xlabel("收益", fontsize=11)
ax.legend()
ax.grid(True, alpha=0.3)
fig.tight_layout()
return figCorrelation Heatmap
相关性热力图
python
def plot_correlation_heatmap(returns_df: pd.DataFrame) -> plt.Figure:
"""Correlation matrix heatmap with annotations."""
corr = returns_df.corr()
fig, ax = plt.subplots(figsize=(10, 8))
im = ax.imshow(corr, cmap="RdYlGn", vmin=-1, vmax=1, aspect="auto")
ax.set_xticks(range(len(corr.columns)))
ax.set_yticks(range(len(corr.columns)))
ax.set_xticklabels(corr.columns, rotation=45, ha="right")
ax.set_yticklabels(corr.columns)
for i in range(len(corr)):
for j in range(len(corr)):
ax.text(j, i, f"{corr.iloc[i, j]:.2f}",
ha="center", va="center", fontsize=9,
color="black" if abs(corr.iloc[i, j]) < 0.5 else "white")
fig.colorbar(im, ax=ax, shrink=0.8)
ax.set_title("Correlation Matrix", fontsize=14, fontweight="bold")
fig.tight_layout()
return figpython
def plot_correlation_heatmap(returns_df: pd.DataFrame) -> plt.Figure:
"""带标注的相关矩阵热力图。"""
corr = returns_df.corr()
fig, ax = plt.subplots(figsize=(10, 8))
im = ax.imshow(corr, cmap="RdYlGn", vmin=-1, vmax=1, aspect="auto")
ax.set_xticks(range(len(corr.columns)))
ax.set_yticks(range(len(corr.columns)))
ax.set_xticklabels(corr.columns, rotation=45, ha="right")
ax.set_yticklabels(corr.columns)
for i in range(len(corr)):
for j in range(len(corr)):
ax.text(j, i, f"{corr.iloc[i, j]:.2f}",
ha="center", va="center", fontsize=9,
color="black" if abs(corr.iloc[i, j]) < 0.5 else "white")
fig.colorbar(im, ax=ax, shrink=0.8)
ax.set_title("相关矩阵", fontsize=14, fontweight="bold")
fig.tight_layout()
return figTrade Markers on Price Chart
价格图表上的交易标记
python
def plot_trades_on_price(
price: pd.Series,
entries: pd.DataFrame, # columns: date, price, side
exits: pd.DataFrame, # columns: date, price, pnl
) -> plt.Figure:
"""Price chart with entry/exit markers."""
fig, ax = plt.subplots(figsize=(14, 7))
ax.plot(price.index, price, color="#aaaaaa", linewidth=1)
# Entry markers
buy_mask = entries["side"] == "long"
ax.scatter(entries.loc[buy_mask, "date"], entries.loc[buy_mask, "price"],
marker="^", color="#00ff88", s=100, zorder=5, label="Buy")
ax.scatter(entries.loc[~buy_mask, "date"], entries.loc[~buy_mask, "price"],
marker="v", color="#ff4444", s=100, zorder=5, label="Short")
# Exit markers
win_mask = exits["pnl"] > 0
ax.scatter(exits.loc[win_mask, "date"], exits.loc[win_mask, "price"],
marker="x", color="#00ff88", s=80, zorder=5)
ax.scatter(exits.loc[~win_mask, "date"], exits.loc[~win_mask, "price"],
marker="x", color="#ff4444", s=80, zorder=5)
ax.set_title("Trades on Price", fontsize=14, fontweight="bold")
ax.legend()
ax.grid(True, alpha=0.3)
fig.tight_layout()
return figpython
def plot_trades_on_price(
price: pd.Series,
entries: pd.DataFrame, # 列:date, price, side
exits: pd.DataFrame, # 列:date, price, pnl
) -> plt.Figure:
"""带进出点位标记的价格图表。"""
fig, ax = plt.subplots(figsize=(14, 7))
ax.plot(price.index, price, color="#aaaaaa", linewidth=1)
# 入场标记
buy_mask = entries["side"] == "long"
ax.scatter(entries.loc[buy_mask, "date"], entries.loc[buy_mask, "price"],
marker="^", color="#00ff88", s=100, zorder=5, label="Buy")
ax.scatter(entries.loc[~buy_mask, "date"], entries.loc[~buy_mask, "price"],
marker="v", color="#ff4444", s=100, zorder=5, label="Short")
# 出场标记
win_mask = exits["pnl"] > 0
ax.scatter(exits.loc[win_mask, "date"], exits.loc[win_mask, "price"],
marker="x", color="#00ff88", s=80, zorder=5)
ax.scatter(exits.loc[~win_mask, "date"], exits.loc[~win_mask, "price"],
marker="x", color="#ff4444", s=80, zorder=5)
ax.set_title("价格图表上的交易", fontsize=14, fontweight="bold")
ax.legend()
ax.grid(True, alpha=0.3)
fig.tight_layout()
return figOutput Formats
输出格式
| Format | Method | Use Case |
|---|---|---|
| PNG | | Sharing, embedding |
| SVG | | Editing, scaling |
| HTML | | Interactive exploration |
| Inline | | Jupyter notebooks |
| 格式 | 方法 | 使用场景 |
|---|---|---|
| PNG | | 分享、嵌入 |
| SVG | | 编辑、缩放 |
| HTML | | 交互式探索 |
| 内联显示 | | Jupyter笔记本 |
Saving with dark background
保存深色背景图表
python
fig.savefig("chart.png", dpi=150, facecolor=fig.get_facecolor(),
edgecolor="none", bbox_inches="tight")python
fig.savefig("chart.png", dpi=150, facecolor=fig.get_facecolor(),
edgecolor="none", bbox_inches="tight")Integration with Other Skills
与其他技能的集成
| Skill | Integration |
|---|---|
| Compute indicators, pass to addplot overlays |
| Extract equity curve and trade list for visualization |
| Plot Sharpe, drawdown, and return metrics |
| Visualize position limits and exposure over time |
| Chart position size vs account equity over time |
| Color background by detected market regime |
| Generate correlation heatmaps from return data |
| 技能 | 集成方式 |
|---|---|
| 计算指标,传入addplot叠加层 |
| 提取权益曲线和交易列表用于可视化 |
| 绘制夏普比率、回撤和收益指标 |
| 可视化持仓限制和随时间的风险敞口 |
| 绘制持仓规模与账户权益随时间的变化 |
| 根据检测到的市场状态为背景上色 |
| 根据收益数据生成相关性热力图 |
Files
文件
References
参考资料
- — Complete code recipes for six common chart types
references/chart_recipes.md - — Dark theme setup, colors, typography, layout, and export settings
references/styling_guide.md
- — 六种常见图表类型的完整代码示例
references/chart_recipes.md - — 深色主题设置、配色、排版、布局和导出设置
references/styling_guide.md
Scripts
脚本
- — Generate four chart types from synthetic data (candlestick, equity, returns, trades)
scripts/chart_generator.py - — Multi-chart performance report with summary statistics
scripts/performance_report.py
- — 从合成数据生成四种图表类型(K线图、权益曲线、收益分布、交易标记)
scripts/chart_generator.py - — 包含汇总统计的多图表业绩报告
scripts/performance_report.py