125 lines
6.3 KiB
JSON
125 lines
6.3 KiB
JSON
{
|
|
"dashboard_title": "Paper Trading PnL",
|
|
"description": "Paper trading performance tracking with PnL curves, position snapshots, order history, and trade detail drill-down.",
|
|
"slug": "paper-trading-pnl",
|
|
"position_json": {
|
|
"HEADER_ID": {"id": "HEADER_ID", "type": "HEADER", "meta": {"text": "Paper Trading PnL"}},
|
|
"ROW-1": {
|
|
"type": "ROW",
|
|
"children": ["CHART-total-net-pnl-kpi", "CHART-win-rate-kpi", "CHART-total-orders-kpi", "CHART-active-positions-kpi"]
|
|
},
|
|
"ROW-2": {
|
|
"type": "ROW",
|
|
"children": ["CHART-cumulative-pnl-timeseries", "CHART-daily-pnl-bar"]
|
|
},
|
|
"ROW-3": {
|
|
"type": "ROW",
|
|
"children": ["CHART-pnl-by-symbol", "CHART-order-status-pie"]
|
|
},
|
|
"ROW-4": {
|
|
"type": "ROW",
|
|
"children": ["CHART-positions-table"]
|
|
},
|
|
"ROW-5": {
|
|
"type": "ROW",
|
|
"children": ["CHART-scorecard-table"]
|
|
},
|
|
"ROW-6": {
|
|
"type": "ROW",
|
|
"children": ["CHART-recent-orders-table"]
|
|
}
|
|
},
|
|
"metadata": {
|
|
"refresh_frequency": 300,
|
|
"default_filters": "{}",
|
|
"color_scheme": "supersetColors"
|
|
},
|
|
"charts": [
|
|
{
|
|
"slice_name": "Total Net PnL",
|
|
"viz_type": "big_number_total",
|
|
"description": "Cumulative net PnL across all paper trading activity",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT ROUND(SUM(net_pnl), 2) AS total_net_pnl FROM lakehouse.stonks.pnl_daily WHERE execution_mode = 'paper'"
|
|
},
|
|
{
|
|
"slice_name": "Win Rate",
|
|
"viz_type": "big_number_total",
|
|
"description": "Fraction of trading days with positive net PnL",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT ROUND(CAST(COUNT(CASE WHEN net_pnl > 0 THEN 1 END) AS DOUBLE) / NULLIF(COUNT(*), 0), 4) AS win_rate FROM lakehouse.stonks.pnl_daily WHERE execution_mode = 'paper'"
|
|
},
|
|
{
|
|
"slice_name": "Total Orders",
|
|
"viz_type": "big_number_total",
|
|
"description": "Total paper trade orders submitted",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT COUNT(DISTINCT order_id) AS total_orders FROM lakehouse.stonks.trade_orders WHERE execution_mode = 'paper'"
|
|
},
|
|
{
|
|
"slice_name": "Active Positions",
|
|
"viz_type": "big_number_total",
|
|
"description": "Number of symbols with open positions as of the latest snapshot",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT COUNT(DISTINCT ticker) AS active_positions FROM lakehouse.stonks.positions_daily WHERE execution_mode = 'paper' AND quantity <> 0 AND dt = (SELECT MAX(dt) FROM lakehouse.stonks.positions_daily WHERE execution_mode = 'paper')"
|
|
},
|
|
{
|
|
"slice_name": "Cumulative PnL Over Time",
|
|
"viz_type": "echarts_timeseries_line",
|
|
"description": "Running cumulative net PnL across all paper trades",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT dt AS bucket, SUM(net_pnl) AS daily_net_pnl, SUM(SUM(net_pnl)) OVER (ORDER BY dt) AS cumulative_pnl FROM lakehouse.stonks.pnl_daily WHERE execution_mode = 'paper' GROUP BY dt ORDER BY dt"
|
|
},
|
|
{
|
|
"slice_name": "Daily PnL",
|
|
"viz_type": "echarts_timeseries_bar",
|
|
"description": "Daily net PnL for paper trading, colored by positive/negative",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT dt AS bucket, ROUND(SUM(net_pnl), 2) AS daily_pnl, ROUND(SUM(realized_pnl), 2) AS realized, ROUND(SUM(unrealized_pnl), 2) AS unrealized FROM lakehouse.stonks.pnl_daily WHERE execution_mode = 'paper' GROUP BY dt ORDER BY dt",
|
|
"params": {
|
|
"x_axis": "bucket",
|
|
"metrics": ["daily_pnl"]
|
|
}
|
|
},
|
|
{
|
|
"slice_name": "PnL by Symbol",
|
|
"viz_type": "echarts_timeseries_bar",
|
|
"description": "Total net PnL per symbol for paper trading",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT ticker, ROUND(SUM(net_pnl), 2) AS total_pnl, ROUND(SUM(realized_pnl), 2) AS realized_pnl, ROUND(SUM(fees), 2) AS total_fees FROM lakehouse.stonks.pnl_daily WHERE execution_mode = 'paper' GROUP BY ticker ORDER BY total_pnl DESC",
|
|
"params": {
|
|
"x_axis": "ticker",
|
|
"metrics": ["total_pnl"]
|
|
}
|
|
},
|
|
{
|
|
"slice_name": "Order Status Distribution",
|
|
"viz_type": "pie",
|
|
"description": "Breakdown of paper trade order statuses",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT status, COUNT(*) AS count FROM lakehouse.stonks.trade_orders WHERE execution_mode = 'paper' GROUP BY status ORDER BY count DESC"
|
|
},
|
|
{
|
|
"slice_name": "Current Positions",
|
|
"viz_type": "table",
|
|
"description": "Latest position snapshot for all paper trading symbols",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT p.ticker, p.quantity, ROUND(p.avg_entry_price, 2) AS avg_entry, ROUND(p.close_price, 2) AS close_price, ROUND(p.market_value, 2) AS market_value, ROUND(p.unrealized_pnl, 2) AS unrealized_pnl, p.snapshot_at FROM lakehouse.stonks.positions_daily p WHERE p.execution_mode = 'paper' AND p.dt = (SELECT MAX(dt) FROM lakehouse.stonks.positions_daily WHERE execution_mode = 'paper') ORDER BY ABS(p.unrealized_pnl) DESC"
|
|
},
|
|
{
|
|
"slice_name": "Paper Trade Scorecard",
|
|
"viz_type": "table",
|
|
"description": "Per-symbol paper trading scorecard with win rates, PnL, and order counts",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT pnl.ticker, COUNT(DISTINCT pnl.dt) AS trading_days, ROUND(SUM(pnl.net_pnl), 2) AS total_net_pnl, ROUND(AVG(pnl.net_pnl), 2) AS avg_daily_pnl, ROUND(CAST(COUNT(CASE WHEN pnl.net_pnl > 0 THEN 1 END) AS DOUBLE) / NULLIF(COUNT(*), 0), 4) AS win_rate, ROUND(MIN(pnl.net_pnl), 2) AS worst_day, ROUND(MAX(pnl.net_pnl), 2) AS best_day, ROUND(SUM(pnl.fees), 2) AS total_fees, MIN(pnl.dt) AS first_trade, MAX(pnl.dt) AS last_trade FROM lakehouse.stonks.pnl_daily pnl WHERE pnl.execution_mode = 'paper' GROUP BY pnl.ticker ORDER BY total_net_pnl DESC"
|
|
},
|
|
{
|
|
"slice_name": "Recent Orders",
|
|
"viz_type": "table",
|
|
"description": "Most recent paper trade orders with fill details",
|
|
"datasource_type": "trino",
|
|
"query": "SELECT o.ticker, o.side, o.order_type, o.quantity, ROUND(o.limit_price, 2) AS limit_price, o.status, f.fill_price, f.fill_quantity, f.commission, o.submitted_at, f.filled_at FROM lakehouse.stonks.trade_orders o LEFT JOIN lakehouse.stonks.trade_fills f ON o.order_id = f.order_id AND o.dt = f.dt WHERE o.execution_mode = 'paper' ORDER BY o.submitted_at DESC LIMIT 50"
|
|
}
|
|
]
|
|
}
|