Learn-skills.dev trading-visualization
Professional trading charts including candlesticks, equity curves, drawdowns, correlation heatmaps, and return distributions
git clone https://github.com/NeverSight/learn-skills.dev
T=$(mktemp -d) && git clone --depth=1 https://github.com/NeverSight/learn-skills.dev "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/skills-md/agiprolabs/claude-trading-skills/trading-visualization" ~/.claude/skills/neversight-learn-skills-dev-trading-visualization && rm -rf "$T"
data/skills-md/agiprolabs/claude-trading-skills/trading-visualization/SKILL.mdTrading 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 |
Libraries
mplfinance
Best for candlestick charts. Built on matplotlib with finance-specific defaults.
uv pip install mplfinance
import mplfinance as mpf # Basic candlestick from a DataFrame with DatetimeIndex # Columns: 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
for overlays (moving averages, Bollinger Bands)addplot- Custom styles via
mpf.make_mpf_style()
matplotlib
General purpose, most flexible. Use when you need full control over layout.
uv pip install matplotlib
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
Interactive charts rendered as HTML. Best for exploration and dashboards.
uv pip install plotly
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
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
references/styling_guide.md for complete typography, layout ratios, and export settings.
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
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 ax_price.tick_params(labelbottom=False) ax_volume.tick_params(labelbottom=False)
Panel 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 |
Candlestick Charts with Overlays
import mplfinance as mpf import pandas as pd # df: DataFrame with DatetimeIndex, columns 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")
Equity Curve with Drawdown Panel
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
Return Distribution
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
Correlation Heatmap
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
Trade Markers on Price Chart
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
Output Formats
| Format | Method | Use Case |
|---|---|---|
| PNG | | Sharing, embedding |
| SVG | | Editing, scaling |
| HTML | (plotly) | Interactive exploration |
| Inline | | Jupyter notebooks |
Saving with dark background
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 |
Files
References
— Complete code recipes for six common chart typesreferences/chart_recipes.md
— Dark theme setup, colors, typography, layout, and export settingsreferences/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 statisticsscripts/performance_report.py