Skip to content

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_pnl_rlusd (per fill) = fill_quantity_rlusd × realized_spread_bps / 10000
Where 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:

xrp_spread_pnl = SUM(realized_spread_pnl_rlusd_i / fill_price_i)
Divides each fill's RLUSD spread PnL by that fill's execution price (RLUSD/XRP) to convert to XRP. Computed fill-by-fill (not total RLUSD ÷ avg price) to handle price variation correctly.

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_spread_dom = session_spread_pnl / session_total_pnl
Where 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_inv_pnl = session_total_pnl - session_spread_pnl
Where 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:

vw_spread_bps = SUM(realized_spread_bps × quantity) / SUM(quantity)
Volume-weighted by RLUSD notional. Weights larger fills more heavily. Primary efficiency metric.

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