xiaohongshu
xiaohongshu
dashboard-pnl-visualization
Trading dashboard P&L visualization with profit tracker integration, win-rate overlays, R-multiples, and configurable settings
Full skill instructions
| Item | Details |
|---|---|
| Date | 2025-12-13 |
| Goal | Enhance trading dashboard with comprehensive P&L tracking, win-rate overlays from profit tracker, and R-multiple position visualization |
| Environment | Python 3.10, matplotlib, alpaca-py, Alpaca Trading API |
| Status | Success |
Trading dashboards often show only gross P&L without breaking down realized vs unrealized, cost coverage, or win-rate context. This skill documents patterns for integrating profit tracker data into dashboard visualizations.
Create a configurable runtime settings system:
from dataclasses import dataclass, field
from typing import List
import json
from pathlib import Path
@dataclass
class DashboardConfig:
"""Runtime configuration for the monitoring dashboard."""
symbols: List[str] = field(default_factory=lambda: ["SPY", "QQQ", "AAPL"])
lookback_days: int = 30
interval_seconds: int = 60
output_dir: str = "dashboards"
cost_data: float = 3.33 # Daily data cost
cost_software: float = 6.67 # Daily software cost
risk_limit_pct: float = 10.0 # Portfolio risk limit
profit_log_dir: str = "logs/live"
save_latest: bool = True
@classmethod
def from_json(cls, path: str) -> "DashboardConfig":
if not path or not Path(path).exists():
return cls()
return cls(**json.loads(Path(path).read_text()))
Fetch real portfolio equity data from Alpaca:
def get_equity_history(
self,
period: str = "1M", # '1D', '1W', '1M', '3M', '1A'
timeframe: str = "1D", # '1Min', '5Min', '15Min', '1H', '1D'
) -> List[Dict[str, Any]]:
"""Return historical equity curve from the broker."""
from alpaca.trading.requests import GetPortfolioHistoryRequest
request = GetPortfolioHistoryRequest(period=period, timeframe=timeframe)
history = self._client.get_portfolio_history(request)
if hasattr(history, "equity") and hasattr(history, "timestamp"):
return [
{"timestamp": ts, "value": eq}
for ts, eq in zip(history.timestamp, history.equity)
]
return []
Load profit summary for live metrics overlay:
def load_profit_summary(log_dir: str) -> Dict:
"""Load profit tracker summary for win-rate overlays."""
path = Path(log_dir)
summary_files = sorted(path.glob("*/profit_summary.json"))
if not summary_files:
return {}
with summary_files[-1].open() as f:
summary = json.load(f)
trades = summary.get("trades", [])
pnls = [t.get("pnl", 0.0) for t in trades]
wins = [p for p in pnls if p > 0]
# Calculate loss streak
loss_streak = 0
for pnl in reversed(pnls):
if pnl <= 0:
loss_streak += 1
else:
break
return {
"win_rate": len(wins) / len(pnls) if pnls else 0.0,
"loss_streak": loss_streak,
"trade_count": len(pnls),
}
def get_pnl_breakdown(broker, cfg, profit_overlay, open_pnl=0.0) -> dict:
"""Get P&L breakdown with realized/unrealized split."""
account = broker.get_account()
equity = float(account['equity'])
last_equity = float(account.get('last_equity', equity))
daily_pnl = equity - last_equity
unrealized_pnl = float(open_pnl)
realized_pnl = daily_pnl - unrealized_pnl
breakdown = {
'gross_pnl': daily_pnl,
'unrealized_pnl': unrealized_pnl,
'realized_pnl': realized_pnl,
'data_cost': cfg.cost_data,
'software_cost': cfg.cost_software,
}
breakdown['net_pnl'] = breakdown['gross_pnl'] - cfg.cost_data - cfg.cost_software
# Add win-rate overlay
if profit_overlay:
breakdown['win_rate'] = profit_overlay.get('win_rate')
breakdown['loss_streak'] = profit_overlay.get('loss_streak')
return breakdown
def calculate_r_multiple(entry_price, current_price, stop_price, side):
"""Calculate R-multiple for position risk-reward."""
if not stop_price:
return None
if side != 'short':
risk_per_share = entry_price - stop_price
profit_per_share = current_price - entry_price
else:
risk_per_share = stop_price - entry_price
profit_per_share = entry_price - current_price
if risk_per_share <= 0:
return None
return profit_per_share / risk_per_share
# Color coding for R-multiples
def get_r_color(r_multiple):
if r_multiple is None:
return 'gray'
elif r_multiple >= 2:
return 'darkgreen' # Excellent
elif r_multiple >= 1:
return 'green' # Good
else:
return 'orange' # Below target
| Attempt | Why it Failed | Lesson Learned |
|---|---|---|
Using account.equity - account.last_equity directly | Doesn't separate realized from unrealized | Pass open_pnl from position calculations |
| Hardcoding cost values | Different users have different infrastructure costs | Use DashboardConfig dataclass |
| Reading profit_summary from fixed path | Path varies by session date | Use glob to find most recent summary |
| Displaying R-multiple without stop price | Division by zero / meaningless value | Return None and show "--" in display |
# CLI arguments for dashboard
parser.add_argument('--config', type=str, help='JSON config path')
parser.add_argument('--symbols', type=str, help='Comma-separated symbols')
parser.add_argument('--lookback-days', type=int, default=30)
parser.add_argument('--data-cost', type=float, default=3.33)
parser.add_argument('--software-cost', type=float, default=6.67)
parser.add_argument('--risk-limit', type=float, default=10.0)
parser.add_argument('--profit-log-dir', type=str, default='logs/live')
alpaca_trading/broker.py - get_equity_history() methodalpaca_trading/visualization/dashboard.py - R-multiple renderingscripts/monitor_dashboard.py - Full implementationdocs/dashboard_improvements.md - Feature documentationxiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience