Skip to content
dashboard-pnl-visualization logo

dashboard-pnl-visualization - Research Notes

dashboard-pnl-visualization

Trading dashboard P&L visualization with profit tracker integration, win-rate overlays, R-multiples, and configurable settings

SKILL.md

Full skill instructions

dashboard-pnl-visualization - Research Notes

Experiment Overview

ItemDetails
Date2025-12-13
GoalEnhance trading dashboard with comprehensive P&L tracking, win-rate overlays from profit tracker, and R-multiple position visualization
EnvironmentPython 3.10, matplotlib, alpaca-py, Alpaca Trading API
StatusSuccess

Context

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.

Verified Workflow

1. DashboardConfig Dataclass

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()))

2. Broker Equity History Integration

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 []

3. Win-Rate Overlay from Profit Tracker

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),
    }

4. Realized vs Unrealized P&L Split

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

5. R-Multiple Display for Positions

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

Failed Attempts (Critical)

AttemptWhy it FailedLesson Learned
Using account.equity - account.last_equity directlyDoesn't separate realized from unrealizedPass open_pnl from position calculations
Hardcoding cost valuesDifferent users have different infrastructure costsUse DashboardConfig dataclass
Reading profit_summary from fixed pathPath varies by session dateUse glob to find most recent summary
Displaying R-multiple without stop priceDivision by zero / meaningless valueReturn None and show "--" in display

Final Parameters

# 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')

Key Insights

  • Realized/​unrealized split requires tracking open position P&L separately
  • Win-rate overlays provide crucial context for daily P&L interpretation
  • R-multiples only meaningful when stop prices are set
  • Cost coverage percentage helps evaluate if trading covers infrastructure costs
  • JSON config files allow per-environment customization without code changes
  • Profit tracker summaries should be written with timestamp directories for history

References

  • alpaca_trading/​broker.py - get_equity_history() method
  • alpaca_trading/​visualization/​dashboard.py - R-multiple rendering
  • scripts/​monitor_dashboard.py - Full implementation
  • docs/​dashboard_improvements.md - Feature documentation

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

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...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

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...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

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.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View