NEO Dashboard Metrics Reference¶
Audited: 2026-04-16 (Vesper)
Status: Confirmed correct after full calculation audit. Bugs found and fixed same session.
Scope: Live trading mode (config_live_stage1.yaml). All RLUSD values unless noted.
Section: Balances & PnL¶
XRP / RLUSD / Total Value¶
Source: valuation_snapshots — latest row.
total_value_rlusd = xrp_balance × mid_price + rlusd_balance
Mid price is derived from the latest inventory: (total_value - rlusd_balance) / xrp_balance
Spread PnL RLUSD (session)¶
What it is: Realized spread profit from market making this session, in RLUSD.
Formula:
realized_spread_bps:
- BUY fill: (mid_price_at_fill - fill_price) / mid_price_at_fill × 10000
- SELL fill: (fill_price - mid_price_at_fill) / mid_price_at_fill × 10000
Session total = SUM(realized_spread_pnl_rlusd) WHERE session_id = current_session
Source: fills table, session-scoped.
Note: Fills detected at session startup on prior-session orders (NULL session_id) are excluded — these are edge-case fills that are not attributed to any session. Impact is typically < 0.02 RLUSD per session. See FLAG-024.
Spread PnL XRP (session)¶
Formula:
Fixed: 2026-04-16 — was previously multiplying instead of dividing (bug inflated by ~2×).
Spread Dom (session)¶
What it is: What fraction of this session's total PnL came from spread capture.
Formula:
session_total_pnl = ending_total_value - starting_total_value (session).
Shows "—" when: session total PnL is negative or near zero. DOM is not meaningful in losing sessions — the spread and inventory components should be read directly instead.
Fixed: 2026-04-16 — was previously dividing by all-time total PnL (wrong scope).
Spread PnL RLUSD (all-time · Nf)¶
Formula: SUM(realized_spread_pnl_rlusd) WHERE session_id IS NOT NULL
Filter excludes NULL session fills (pre-sessions-tracking paper/replay phases, confirmed ~11 bps avg vs ~2 bps live). Nf = fill count included.
Fixed: 2026-04-16 (FLAG-024) — was including NULL session fills that inflated all-time by ~70%.
Spread PnL XRP (all-time)¶
Same as session XRP formula applied to all session-tagged fills.
Spread Dom (all-time)¶
Formula: all_time_spread_pnl / all_time_total_pnl
Where all_time_total_pnl = current_total_value - paper.pnl_starting_value_rlusd (engine start baseline).
Fixed: 2026-04-16 — was using trading_value (total_value - net_deposits) as denominator. The trading_value baseline includes pre-engine value baked into the wallet, overstating the denominator. Total PnL is the correct engine-scoped denominator.
Total PnL (RLUSD)¶
Formula: current_total_value - paper.pnl_starting_value_rlusd
Where paper.pnl_starting_value_rlusd = total portfolio value at first engine tick ever (set once, never overwritten).
This is all-time — it spans all sessions since the engine was first started.
Total PnL (XRP)¶
Formula: total_pnl_rlusd / current_mid_price
Mid price derived from current inventory snapshot.
Inv PnL RLUSD (session)¶
What it is: Session inventory P&L from price moves on held XRP position.
Formula:
session_total_pnl = ending_total_value − starting_total_value for the current session.
Interpretation: Positive = XRP appreciated while holding. Negative = XRP declined (drag on session).
Fixed: 2026-04-16 — was previously all_time_total_pnl - session_spread_pnl (scope mismatch, off by ~4.6 RLUSD).
Section: Portfolio Value¶
Total Value (RLUSD)¶
Current portfolio marked-to-market. Source: valuation_snapshots latest row.
Net Deposits (RLUSD)¶
Cumulative capital added to wallet. Source: valuation_snapshots.net_deposits_rlusd_cum.
Trading Value (RLUSD)¶
Formula: current_total_value - net_deposits_rlusd_cum
What the portfolio is worth above cost basis. Can be negative on a loss run.
Note: This differs from Total PnL because net_deposits may include pre-engine deposits. Trading Value answers "how much is my capital worth above what I put in." Total PnL answers "how much did the engine gain since it started."
AVG XRP Cost (RLUSD)¶
Weighted average cost basis of current XRP position.
Source: valuation_snapshots.xrp_avg_cost_rlusd (WAC accounting).
Known bug: WAC rebuild fails after capital injection (FLAG-008). Value may be stale.
Unrealized Inv PnL¶
Formula: xrp_balance × (mid_price - xrp_avg_cost)
Current mark-to-market P&L on XRP position vs WAC.
Source: valuation_snapshots.unrealized_inventory_pnl_rlusd.
Realized Inv PnL (all-time)¶
Cumulative realized inventory P&L from closed XRP position changes.
Source: valuation_snapshots.realized_inventory_pnl_rlusd_cum.
Computed by InventoryManager via WAC method at each fill.
Section: Execution / Quality¶
VW Spread (bps)¶
Formula:
Source: fills table, session-scoped.
Avg Spread (bps)¶
Simple arithmetic mean of realized_spread_bps across session fills.
Less informative than VW — can be skewed by many small fills at wide spread.
Inventory Drift (%)¶
Formula: (xrp_value / total_value - 0.50) × 100
Where xrp_value = xrp_balance × mid_price. Target = 50% XRP.
Positive = long XRP, negative = long RLUSD. Engine skews quotes to rebalance.
Source: system_metrics.inventory_drift_pct.
Momentum Suppressions (Buy / Sell)¶
Counts of ticks where the momentum filter suppressed one side of the book.
Buy suppressions = ticks where BUY was blocked (price was falling).
Sell suppressions = ticks where SELL was blocked (price was rising).
Phase 6A metric. Source: engine_state.momentum.buy_suppressions / .sell_suppressions.
Note: Written per-tick (fixed 2026-04-16). Previously only written at shutdown — showed stale values during session.
Known Accounting Edge Cases¶
NULL session fills at session startup¶
When an order placed in session N is filled between sessions (engine offline), the fill is detected and recorded at the start of session N+1. At that moment _current_session_id is None, so the fill gets session_id = NULL. These fills:
- Are excluded from session-scoped PnL queries
- Are included in cumulative totals in valuation_snapshots
- Are excluded from all-time spread PnL display (session_id IS NOT NULL filter)
- Cause a gap: the fill is visible in total value history but invisible in session reports
This is a known limitation, not a bug. Impact is small (typically 0–3 fills per session boundary, < 0.02 RLUSD).
Valuation snapshot cumulative vs fills sum discrepancy¶
get_cumulative_realized_spread_pnl() queries SUM(realized_spread_pnl_rlusd) FROM fills with NO session filter. So the valuation_snapshots cumulative includes NULL session fills. The delta between two sessions' cumulative values therefore includes any NULL-session fills detected between those sessions. Always use session-filtered fills queries for session-scoped PnL.
Last updated: 2026-04-16 — Vesper