trading-visualization

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Trading 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:
  1. Pattern recognition — Spot structural changes in price, volume, and momentum that quantitative filters miss.
  2. Strategy evaluation — Equity curves, drawdown plots, and return distributions expose whether a strategy is robust or curve-fit.
  3. Reporting — Communicate performance to stakeholders, journals, or your future self with publication-quality visuals.

可视化是交易者与数据之间的主要交互界面。图表能够展现表格和数字无法呈现的模式:策略失效、市场状态转换、亏损集中情况以及风险形态。设计精良的图表一眼传达的信息,胜过一页统计数据。
交易图表的三大用途:
  1. 模式识别 — 发现量化过滤器遗漏的价格、成交量和动量的结构性变化。
  2. 策略评估 — 权益曲线、回撤图和收益分布图能揭示策略是稳健可靠还是过拟合。
  3. 报告展示 — 用出版级别的可视化效果向利益相关方、期刊或未来的自己展示业绩表现。

Chart Types Covered

涵盖的图表类型

Chart TypePurposeLibrary
CandlestickOHLCV price action with overlaysmplfinance
Equity curvePortfolio value over timematplotlib
DrawdownUnderwater equity plotmatplotlib
Return distributionHistogram + normal fitmatplotlib
Correlation heatmapCross-asset correlation matrixmatplotlib / seaborn
Trade markersEntry/exit points on price chartmplfinance / matplotlib
Indicator panelsRSI, MACD below price chartmplfinance
Position timelineWhen positions were heldmatplotlib

图表类型用途
K线图带叠加层的OHLCV价格走势mplfinance
权益曲线投资组合随时间的价值变化matplotlib
回撤图水下权益图matplotlib
收益分布图直方图+正态拟合matplotlib
相关性热力图跨资产相关矩阵matplotlib / seaborn
交易标记价格图表上的进出点位mplfinance / matplotlib
指标面板价格图表下方的RSI、MACDmplfinance
持仓时间线持仓时间段matplotlib

Libraries

相关库

mplfinance

mplfinance

Best for candlestick charts. Built on matplotlib with finance-specific defaults.
bash
uv pip install mplfinance
python
import mplfinance as mpf
最适合绘制K线图。基于matplotlib构建,带有金融领域专属默认设置。
bash
uv pip install mplfinance
python
import mplfinance as mpf

Basic 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 matplotlib
python
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 matplotlib
python
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 plotly
python
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 plotly
python
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

交易配色方案

ElementColorHex
Bullish / profitGreen
#00ff88
Bearish / lossRed
#ff4444
Neutral / infoBlue
#4488ff
WarningAmber
#ffaa00
MA shortOrange
#ff6600
MA longBlue
#3399ff
MA signalYellow
#ffcc00
See
references/styling_guide.md
for complete typography, layout ratios, and export settings.

元素颜色十六进制码
上涨/盈利绿色
#00ff88
下跌/亏损红色
#ff4444
中性/信息蓝色
#4488ff
警告琥珀色
#ffaa00
短期均线橙色
#ff6600
长期均线蓝色
#3399ff
信号均线黄色
#ffcc00
完整的排版、布局比例和导出设置请查看
references/styling_guide.md

Chart 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)
undefined
ax_price.tick_params(labelbottom=False) ax_volume.tick_params(labelbottom=False)
undefined

Panel height ratios

面板高度比例

LayoutRatiosUse Case
Price + Volume
[3, 1]
Simple OHLCV chart
Price + Volume + Indicator
[3, 1, 1]
Standard analysis view
Equity + Drawdown
[2, 1]
Performance review
Price + RSI + MACD
[3, 1, 1]
Full indicator stack

布局比例使用场景
价格+成交量
[3, 1]
简单OHLCV图表
价格+成交量+指标
[3, 1, 1]
标准分析视图
权益+回撤
[2, 1]
业绩回顾
价格+RSI+MACD
[3, 1, 1]
完整指标堆叠

Candlestick Charts with Overlays

带叠加层的K线图

python
import mplfinance as mpf
import pandas as pd
python
import mplfinance as mpf
import pandas as pd

df: 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 fig

python
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 fig

Return 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 fig

python
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 fig

Correlation 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 fig

python
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 fig

Trade 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 fig

python
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 fig

Output Formats

输出格式

FormatMethodUse Case
PNG
fig.savefig("chart.png", dpi=150)
Sharing, embedding
SVG
fig.savefig("chart.svg")
Editing, scaling
HTML
fig.write_html("chart.html")
(plotly)
Interactive exploration
Inline
plt.show()
Jupyter notebooks
格式方法使用场景
PNG
fig.savefig("chart.png", dpi=150)
分享、嵌入
SVG
fig.savefig("chart.svg")
编辑、缩放
HTML
fig.write_html("chart.html")
(plotly)
交互式探索
内联显示
plt.show()
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

与其他技能的集成

SkillIntegration
pandas-ta
Compute indicators, pass to addplot overlays
vectorbt
Extract equity curve and trade list for visualization
portfolio-analytics
Plot Sharpe, drawdown, and return metrics
risk-management
Visualize position limits and exposure over time
position-sizing
Chart position size vs account equity over time
regime-detection
Color background by detected market regime
correlation-analysis
Generate correlation heatmaps from return data

技能集成方式
pandas-ta
计算指标,传入addplot叠加层
vectorbt
提取权益曲线和交易列表用于可视化
portfolio-analytics
绘制夏普比率、回撤和收益指标
risk-management
可视化持仓限制和随时间的风险敞口
position-sizing
绘制持仓规模与账户权益随时间的变化
regime-detection
根据检测到的市场状态为背景上色
correlation-analysis
根据收益数据生成相关性热力图

Files

文件

References

参考资料

  • references/chart_recipes.md
    — Complete code recipes for six common chart types
  • references/styling_guide.md
    — Dark theme setup, colors, typography, layout, and export settings
  • references/chart_recipes.md
    — 六种常见图表类型的完整代码示例
  • references/styling_guide.md
    — 深色主题设置、配色、排版、布局和导出设置

Scripts

脚本

  • scripts/chart_generator.py
    — Generate four chart types from synthetic data (candlestick, equity, returns, trades)
  • scripts/performance_report.py
    — Multi-chart performance report with summary statistics
  • scripts/chart_generator.py
    — 从合成数据生成四种图表类型(K线图、权益曲线、收益分布、交易标记)
  • scripts/performance_report.py
    — 包含汇总统计的多图表业绩报告