17 KiB
evelyn-perps-overview Specification
Purpose
Let the owner inspect Evelyn perpetual positions grouped by wallet and venue in Mission Control, with stable row identities across service snapshot updates.
Requirements
Requirement: Perps overview displays a collapsible position hierarchy
The Perps tab SHALL display Position, Risk, Direction, Margin, Collateral, Leverage, Exposure, Value, uPnL and TWAP beneath the visible Perpetual Contracts root. Isolated hierarchy SHALL be wallet → venue → position; each Phoenix Cross account SHALL add a Cross group above its positions. Groups SHALL show applicable totals and risk summaries, leave direction/aggregate ratios blank, show TWAP warnings when applicable, and be expanded by default.
Scenario: Open either environment's Perps tab
- WHEN the owner opens Perps in Production or Test
- THEN all ten columns and the account-aware hierarchy are available with Risk near the position name
Scenario: Collapse and expand groups
- WHEN the owner collapses a wallet, venue or Cross account
- THEN the group still shows its worst known risk and incomplete-observation counts without changing totals
Requirement: Asynchronous polling follows window visibility
EMC SHALL request the current Perps snapshot from each environment's own service immediately on opening and every three seconds while visible, without blocking the UI thread. UI updates SHALL occur only on the JavaFX thread. Hiding the window SHALL stop polling; reopening SHALL create only one active polling loop and ignore results belonging to an earlier window session. Poll failures SHALL preserve the current view and allow subsequent attempts.
Scenario: Read takes time or fails
- WHEN a snapshot read is delayed or fails
- THEN the UI remains responsive and the existing view is retained
- AND later polling remains possible without overlapping scheduled reads
Scenario: Hide and reopen
- WHEN the owner hides and reopens EMC repeatedly
- THEN each visible session has only one polling loop and obsolete results cannot update its views
Scenario: Environment data stays separate
- WHEN TEST and PROD return different snapshots
- THEN each tab displays only its own service's data
- AND a failure reading one service does not prevent attempting the other service
Requirement: Polling preserves Perps view state
The Perps table SHALL retain matching wallet, venue and position identities across snapshots. Repeated unchanged snapshots SHALL leave retained rows, expansion, selection and formatting untouched except when risk or TWAP-warning freshness changes, without flicker or table rebuild. New groups SHALL be expanded by default, and added or removed positions SHALL be reconciled by identity without resetting retained groups.
Scenario: Poll unchanged positions
- WHEN a user collapses a group or selects a position and repeated snapshots are unchanged
- THEN the same rows remain with the same expansion and selection
- AND only a changed risk or TWAP-warning freshness indication requires a row-value update
Requirement: Jupiter positions communicate direction and USD size
Positions SHALL show readable Long/Short direction and Isolated/Cross margin text. USD amounts SHALL use grouping and two decimals; leverage SHALL use a multiplication sign. Signed uPnL SHALL be green for positive, red for negative and neutral for rounded zero without negative zero. Existing faint direction backgrounds SHALL remain; groups SHALL have distinct weight and no direction color. Numeric columns SHALL be right-aligned with useful widths and tooltips.
Scenario: Small or unavailable PnL
- WHEN PnL rounds to zero or is unavailable
- THEN zero has no negative sign/color and unavailable values show an em dash with an explanation
Scenario: Inspect real positions
- WHEN real Jupiter positions are displayed
- THEN direction appears as readable text and background color, with formatted gross USD exposure and applicable valuation metrics
Requirement: EMC presents service data without sample notices
EMC SHALL obtain positions only from its environment's in-memory service snapshot and SHALL contain no sample positions, sample notices, illustrative-Phoenix notices, or Refresh button. EMC SHALL own UI components, colors and formatting; integration reads SHALL belong to the service.
Scenario: Snapshot changes
- WHEN positions are added or removed after refresh
- THEN EMC reconciles rows by identity while preserving retained selections and expansion state
- AND no sample labels or Phoenix examples appear
Requirement: Definitions distinguish owned collateral and margin requirements
Tooltips SHALL explain isolated collateral, exposure-based leverage, collateral-based ROI, estimated net Value and excluded slippage/swaps/rent. Cross position collateral SHALL be identified as initial margin required against shared collateral. Cross position Value SHALL be unavailable; unsupported Cross ROI/leverage SHALL be explained. Cross account leverage SHALL identify undiscounted equity before exit fees as its denominator.
Scenario: Inspect a Cross position
- WHEN the owner inspects a Cross row and its account group
- THEN the position shows a USD margin requirement and the account shows shared capital once
- AND no position-only metric is labeled account utilization
Requirement: Venue visibility follows available child rows
EMC SHALL hide venue rows with neither positions, Cross accounts nor TWAP warnings and show them when children reappear. Funded empty Cross accounts and accounts with eligible TWAP warnings SHALL keep their venue visible. Unmatched isolated warnings SHALL remain on the venue with true subaccount identity, never on an invented Cross parent. Hidden venues SHALL remain in snapshots and totals, with read status available in wallet tooltips. Unknown scopes SHALL NOT become zero totals; failed reads SHALL preserve last-success totals. Without a text filter, wallet rows and the root SHALL remain visible. With a text filter, only matching branches SHALL remain, with the root always retained as context.
Scenario: Empty venue
- WHEN Jupiter or Phoenix has no positions, Cross accounts or TWAP warnings
- THEN its heading is absent from that wallet's displayed children
- AND a successful empty scope still contributes zero to totals
Scenario: Funded Cross account without positions
- WHEN Phoenix returns a Cross account with capital but no open positions
- THEN Phoenix and its Cross account remain visible with that capital counted once
Scenario: Positions disappear and return
- WHEN a venue loses its last child and later returns a position
- THEN its heading disappears and reappears with the correct child
- AND unrelated retained rows keep their selection and expansion state
Scenario: Hidden scope has not been read successfully
- WHEN a childless venue has never been read successfully and its first read is pending or failed
- THEN the heading is hidden and its read status is available on the wallet tooltip
- AND required totals remain unavailable rather than reporting zero
Requirement: TWAP cells show execution progress and snapshot duration
Matching filled Phoenix TWAPs SHALL show a progressbar using executed/total child counts and an overlaid estimated duration to the next child in unbounded hours, minutes and seconds. Cells with no eligible progress or warning SHALL be empty. Matched timing warnings SHALL coexist with their progressbar. Updates SHALL follow existing snapshots without a live timer. Failed retained observations SHALL be labeled retained; due or unknown schedules SHALL not show negative or wrapped times or imply execution.
Scenario: Long interval
- WHEN the snapshot's estimated wait is 28 hours 32 minutes 10 seconds, or 128 hours 32 minutes 10 seconds
- THEN the text is approximately 28:32:10 or 128:32:10 respectively
Scenario: Failed or due observation
- WHEN the venue read fails or the latest observed next slot is already due
- THEN the cell communicates retained or awaiting-update status without advancing progress
Requirement: TWAP tooltip distinguishes estimates from fills
TWAP tooltips SHALL show executed/total progress, Estimated completion, total size, next child size, filled quantity and observation time. Sizes SHALL include their symbol and approximate USD values from Phoenix mark prices where available. Distinct regular/dust sizes and periodic nominal-slot timing assumptions SHALL be explained. Unknown values SHALL remain unknown; expiry SHALL never be presented as completion.
Scenario: Missing price or smaller next child
- WHEN the mark price is unavailable or the next child is a smaller rest order
- THEN token amounts remain visible with unknown USD values, or the next size reflects that rest order respectively
Requirement: Risk cells distinguish distance and account health
Risk cells SHALL show neutral isolated distance and red reached/crossed boundaries, while Phoenix tiers use their own severity colors. Cross account cells SHALL label MM utilization; their children SHALL indicate Shared scope. Missing risk SHALL be Unknown. Text, indicators and tooltips SHALL explain units, reference/liquidation prices, account scope, thresholds, original observation time and limitations without changing direction backgrounds.
Scenario: Safe account without liquidation estimate
- WHEN Phoenix reports a valid Safe account but a nonpositive liquidation-price sentinel
- THEN account health remains available while the position price estimate is unavailable
Requirement: Risk freshness expires unchanged snapshots
EMC SHALL mark risk stale after five minutes from its original observation, on read failure or for future timestamps. Existing UI polling SHALL update freshness even when the snapshot is unchanged, without additional venue calls/timers. Old critical states SHALL remain prominent with uncertainty; stale or incomplete noncritical observations SHALL NOT appear fresh green. Reconciliation SHALL preserve row identity, selection, expansion and TWAP state.
Scenario: Unchanged successful snapshot grows old
- WHEN time passes the five-minute risk age limit without new data or errors
- THEN existing UI polling changes its freshness indication without resetting the tree
Scenario: Retained critical risk
- WHEN a previously critical observation fails to refresh
- THEN its critical state and original time remain visible with stale/retained indication
Requirement: TWAP warnings propagate through every ancestor
EMC SHALL show an amber warning triangle and concise text at the owning position or Cross group and on every actual ancestor through Perpetual Contracts. Summaries SHALL count each distinct order once per scope independently of expansion state. Unfilled and completed orders SHALL remain invisible. Risk and capital totals SHALL remain independent.
Scenario: Collapsed Cross branch
- WHEN a filled outstanding Cross order has missing market metadata and Cross or Phoenix is collapsed
- THEN Cross, Phoenix, wallet and Perpetual Contracts still carry the warning
- AND each summary counts that order once
Scenario: Position and multiple wallets
- WHEN a position warning and an unmatched Cross warning affect different wallets
- THEN each follows only its actual ancestors and the root counts two orders
- AND clearing one warning leaves the other and its ancestor summaries intact
Requirement: Warning details preserve reason and freshness
Warning tooltips SHALL identify wallet/account/position, reason, TWAP address, asset/subaccount IDs, raw progress/fills and original observation time. Unknown metadata SHALL remain unknown without unsupported cancellation/delisting/stoppage claims. Failure retention, future timestamps and the existing five-minute observation-age cutoff SHALL qualify all affected summaries.
Scenario: Retained or aged warning
- WHEN a warned venue or consumer read fails, or its original observation becomes five minutes old
- THEN source and inherited warnings remain visible with retained/stale qualification and original times
- AND existing UI polling updates age without additional venue reads or resetting selection and expansion
Requirement: Estimated Value is visibly qualified at every level
Available estimated Value SHALL show one ≈ before USD formatting with two decimals, including signed/zero values and every affected venue, wallet and root total. Unavailable Value SHALL show — without a numeric approximation marker. Tooltips SHALL identify contributing estimate sources and distinguish estimates from actual closing proceeds. Existing Phoenix account calculations and all independent columns SHALL remain intact.
Scenario: Jupiter position tooltip
- WHEN the owner inspects Jupiter position Value
- THEN its tooltip says "Estimated position value reported by Jupiter. Actual proceeds on closing may differ."
- AND it explains the observed opening-fee treatment uncertainty and unverified collateral/profit-cap semantics without claiming differences are always small or every response is wrong
Scenario: Rounding and affected ancestors
- WHEN a Jupiter position Value is 123.234567 USD
- THEN its Value displays
≈$123.23 - AND Jupiter, wallet and root totals each display one
≈and explain the Jupiter contribution, even when collapsed
Scenario: Phoenix and incomplete totals
- WHEN Phoenix estimates contribute to a mixed portfolio
- THEN available affected totals also explain Phoenix's estimated closing Value
- AND a missing required contribution leaves the affected total
—without≈
Requirement: Perps text filtering responds immediately
Each environment's Perps tab SHALL provide a Filter text field and adjacent X clear button above the table. Every text change SHALL immediately apply case-insensitive literal substring matching only to Position and Risk text, including full wallet addresses, without Return, focus loss, polling or service calls. Empty text SHALL restore the normal overview.
Scenario: Edit and clear
- WHEN the owner types B, BT, BTC, changes it to btc, deletes text or pastes a query
- THEN every edit immediately updates the results and BTC and btc give identical matches
- AND X clears the field and immediately restores the normal overview
Scenario: Search scope is limited to Position and Risk
- WHEN a query occurs only in Direction, Margin, Collateral, Leverage, Exposure, Value, uPnL, TWAP or tooltip text
- THEN that content does not produce a match
- WHEN a query occurs in Position or Risk text, or the full wallet address behind a shortened Position label
- THEN the corresponding row matches
Requirement: Text filtering preserves hierarchical context
Matching positions SHALL retain their ancestors; matching groups SHALL include all descendants. Unrelated branches SHALL be hidden. The root SHALL always remain as context. Changing the query SHALL expand result ancestors so matches are readily visible.
Scenario: Symbol and wallet matches
- WHEN BTC matches positions only
- THEN those positions and their ancestors remain, without unrelated positions
- WHEN a substring matches a full wallet address, venue name or Cross group name
- THEN its whole branch remains, including descendants with other symbols
Scenario: No matches
- WHEN no row matches the query
- THEN only the contextual root remains
Requirement: Filtering preserves complete account context
Filtering SHALL preserve original snapshot totals, risk summaries, TWAP warnings and freshness/retention qualifications. While text is nonempty, an explanation near the filter SHALL state that totals include hidden positions; the explanation SHALL disappear when cleared. Shared Cross capital SHALL never be apportioned to visible positions.
Scenario: Partial portfolio shown
- WHEN the filter hides some positions
- THEN root and group values and summaries remain those of their complete scopes
- AND the active-filter explanation remains visible
Requirement: Filter state survives observation updates
Each Perps tab SHALL keep its own query through polling and read failures. Updates SHALL re-evaluate current rows. Unchanged observations SHALL retain visible row identities, selection and expansion. Clearing SHALL restore normal group expansion state from before filtering, with new groups expanded by default.
Scenario: Updates and recovery
- WHEN positions change or a read fails and recovers while filtering
- THEN the query persists and matching additions/removals appear immediately on update
- AND retained values keep their original freshness semantics
Scenario: Independent views and restoration
- WHEN one environment is filtered and groups in the normal overview were previously collapsed
- THEN the other environment's filter is unaffected
- AND clearing restores those collapsed groups