100: Add Perps collateral, leverage, value, uPnL and gross-exposure totals in EMC

This commit is contained in:
2026-10-24 17:53:42 +02:00
parent 7e36b7ef95
commit 041b5c089a
35 changed files with 9110 additions and 180 deletions
+40 -7
View File
@@ -7,16 +7,15 @@ Let the owner inspect Evelyn perpetual positions grouped by wallet and venue in
## Requirements
### Requirement: Perps overview displays a collapsible position hierarchy
The Perps tab SHALL display a tree table with columns `Position`, `Direction`, and `Position size, USD`. The hierarchy SHALL be wallet → venue → position, expanded by default, with collapsible wallet and venue groups. Wallet and venue rows SHALL leave direction and size empty.
The Perps tab SHALL display Position, Direction, Margin, Collateral, Leverage, Exposure, Value and uPnL in that order 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, leave direction/aggregate ratios blank, and be expanded by default.
#### Scenario: Open either environment's Perps tab
- **WHEN** the owner opens Perps in Production or Test
- **THEN** the three named columns and the fully expanded hierarchy are visible
- **AND** direction and size appear only on position rows
- **THEN** all eight columns, root totals and the account-aware hierarchy are visible
#### Scenario: Collapse and expand groups
- **WHEN** the owner collapses and then expands a wallet or venue
- **THEN** its descendants are hidden and then shown again
- **WHEN** the owner collapses and expands a wallet, venue or Cross account
- **THEN** descendants hide and return 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.
@@ -43,11 +42,15 @@ The Perps table SHALL retain matching wallet, venue and position identities acro
- **THEN** the same rows remain, with the same expansion and selection and no rebuild or refresh
### Requirement: Jupiter positions communicate direction and USD size
Position rows SHALL show Long or Short and USD sizes with grouping separators and two decimal places. Long rows SHALL have faint green backgrounds and Short rows faint red backgrounds; wallet and venue rows SHALL have no direction-based color. Existing columns and hierarchy SHALL be preserved.
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 USD size
- **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.
@@ -56,3 +59,33 @@ EMC SHALL obtain positions only from its environment's in-memory service snapsho
- **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 nor Cross accounts and show them when children reappear. Funded empty Cross accounts SHALL keep their venue visible. 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. Wallet rows and the root SHALL remain visible.
#### Scenario: Empty venue
- **WHEN** Jupiter or Phoenix has no positions and no Cross accounts
- **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
+32 -5
View File
@@ -22,7 +22,7 @@ The service SHALL run as two separate Hub-managed processes registered as `evely
- **AND** no placeholder positions are generated before successful retrieval
### Requirement: Wallet configuration belongs to service construction
The Hub SHALL supply the six PROD wallet addresses and one TEST wallet address specified in issue #98 and the corresponding existing Jupiter integration plus a read-only Phoenix integration at construction. Each service SHALL retain immutable configuration and own its snapshot. Wallet addresses SHALL be used as stable identities and display labels. EMC SHALL neither own nor pass wallet configuration; reads SHALL remain parameterless.
The Hub SHALL supply the six PROD wallet addresses and one TEST wallet address specified in issue #98, a read-only Jupiter overview reader and a read-only Phoenix integration at construction. Each service SHALL retain immutable configuration and own its snapshot. Wallet addresses SHALL be used as stable identities and display labels. EMC SHALL neither own nor pass wallet configuration; reads SHALL remain parameterless. Existing Jupiter trading/alarm services SHALL retain their behavior.
#### Scenario: Separate configured instances
- **WHEN** the Hub constructs and starts both instances
@@ -30,15 +30,19 @@ The Hub SHALL supply the six PROD wallet addresses and one TEST wallet address s
- **AND** the implementation does not define the wallet list internally
### Requirement: Background Jupiter refresh
The service SHALL refresh immediately after startup and wait 60 seconds between completed cycles, without overlapping cycles or depending on EMC visibility. It SHALL use Jupiter and Phoenix read operations and respect the existing Jupiter cache. Snapshot reads SHALL make no integration calls. No transaction signing or position-management operation SHALL occur.
The service SHALL refresh immediately after startup and wait 60 seconds after completed cycles without overlap or dependence on EMC visibility. It SHALL use a dedicated read-only Jupiter overview and the Phoenix account reader. Snapshot reads SHALL make no integration calls. No signing or position-management operation SHALL occur; existing transaction/alarm reads SHALL retain their behavior.
#### Scenario: Background update while EMC is hidden
- **WHEN** EMC is hidden and the next refresh is due
- **THEN** the service still refreshes configured wallets and publishes immutable snapshots
- **AND** no freshness guarantee bypasses the existing 60-second integration cache
- **THEN** the service refreshes configured wallets and publishes immutable snapshots
- **AND** all UI snapshot reads remain in-memory
### Requirement: Position mapping is stable and complete
The service SHALL map position account to stable ID, mint to known instrument label or raw mint fallback, direction to Long/Short, and positionSize to USD size. Wallet order SHALL follow configuration, and positions SHALL be ordered deterministically by position account. Phoenix SHALL use PDA index, subaccount index and symbol as stable identity, signed quantity for direction and absolute current USD notional for size. Jupiter and Phoenix SHALL appear as separate venues, with no subaccount tree level.
The service SHALL preserve Jupiter position-account identities and its existing USD position-size basis. Phoenix SHALL preserve PDA/subaccount/symbol identities and absolute current notional. Isolated positions SHALL remain directly under venues; Cross accounts SHALL own their positions and shared balances separately. Wallet and position ordering SHALL be deterministic. No account membership SHALL be inferred from instrument labels.
#### Scenario: Same-market cross and isolated positions
- **WHEN** a Phoenix wallet holds SOL in Cross and an isolated subaccount
- **THEN** both positions retain distinct IDs and their actual account membership
#### Scenario: Changed and unknown positions
- **WHEN** a successful read returns newly opened positions including an unknown token mint
@@ -56,3 +60,26 @@ A failed read or mapping SHALL retain the last successful data for that wallet a
- **WHEN** Phoenix fails for a wallet while Jupiter succeeds, or vice versa
- **THEN** only the successful venue is updated and the failed venue retains its previous data
- **AND** subsequent wallets are still attempted
### Requirement: Complete gross and account-aware totals
Exposure and dollar price PnL SHALL sum through all levels. Exposure SHALL be gross, with positive absolute notionals. Capital and closing Value SHALL count isolated positions and shared Cross accounts once. Missing required components SHALL make only the affected total unavailable. Successfully read empty scopes SHALL total zero. Leverage and PnL percentages SHALL NOT be aggregated.
#### Scenario: Opposite directions and shared collateral
- **WHEN** two Cross positions have notionals 100 USD Long and 100 USD Short, shared collateral 80 USD, combined PnL 5 USD and closing fees 1 USD
- **THEN** exposure totals 200 USD, collateral 80 USD and Value 84 USD at account, venue, wallet and root levels
- **AND** collapsing any UI group does not change totals
#### Scenario: First read fails
- **WHEN** one configured venue has never been read successfully
- **THEN** it remains unknown and cannot silently produce complete portfolio totals
### Requirement: Retained observations communicate status
Each venue SHALL carry its last-success time and whether the latest attempt failed. Failure SHALL preserve positions and account balances independently per wallet/venue. A valid funded empty Cross account SHALL remain visible. Retained data SHALL NOT be described as fresh.
#### Scenario: Last Cross position closes
- **WHEN** a successful refresh returns a Cross account with nonzero collateral and no positions
- **THEN** its capital and Value remain included without synthetic positions
#### Scenario: Retained last success
- **WHEN** a subsequent read fails
- **THEN** its previous observations remain available with their original success time and failure indication
@@ -0,0 +1,29 @@
# jupiter-perps-overview Specification
## Purpose
Provide precise read-only Jupiter position metrics for capital and risk inspection without altering transaction or alarm behavior.
## Requirements
### Requirement: Coherent read-only position overview
The overview SHALL read the official positions response for one wallet, validate completeness and unique stable identities, and return immutable results. USD integer amounts SHALL be converted from micro-USD without binary floating point. Requests SHALL be interruptible and have bounded timeouts; failed or malformed reads SHALL NOT become empty portfolios.
#### Scenario: Incomplete response
- **WHEN** count differs from the returned position count, or identities are duplicated
- **THEN** the read fails and no partial portfolio is published
#### Scenario: Valid empty response
- **WHEN** the response contains count zero and an empty position list
- **THEN** the successful result clears that wallet's Jupiter scope
### Requirement: Verified metrics and unavailable valuations
The overview SHALL preserve size basis, use post-fee USD collateral and price PnL before separate fees, and calculate leverage and ROI against positive collateral. Unverified closing valuations SHALL be unavailable with an explanation; placeholder zeros and double subtraction of settled fees SHALL NOT be used.
#### Scenario: Unverified API closing value
- **WHEN** API value subtracts opening fees already settled in collateral or does not establish profit-cap valuation
- **THEN** closing Value is unavailable, while independently verified metrics remain available
#### Scenario: Nonpositive collateral
- **WHEN** a position's collateral is zero or negative
- **THEN** its leverage and PnL percentage are unavailable
@@ -36,3 +36,22 @@ HTTP, authentication, malformed schema, identity mismatch and numeric conversion
- **THEN** request starts SHALL be spaced at least one second apart
- **AND** HTTP 429 SHALL fail the lookup and establish a shared cooldown from Retry-After (seconds or HTTP date, 60 seconds fallback)
- **AND** lookups during cooldown SHALL fail without external calls, with no immediate retry
### Requirement: Separate account capital and precise position metrics
The reader SHALL return immutable account balances separately from positions, including funded empty Cross accounts. Quote lots SHALL convert at 1e-6 USD. Price PnL SHALL use precise virtual quote and signed base amounts at mark. Initial position margin SHALL follow size-dependent tiers including venue interpolation and rounding. Unsupported non-USDC collateral SHALL make affected valuations unavailable instead of being ignored.
#### Scenario: Size between margin tiers
- **WHEN** a position lies between two leverage tiers
- **THEN** its initial margin follows interpolated integer leverage and upward quote-lot rounding, rather than the market's maximum leverage
#### Scenario: Unsupported spot collateral
- **WHEN** an account has nonzero spot collateral that cannot be valued reliably
- **THEN** collateral, equity and closing Value are unavailable while independent exposure and price PnL remain available
### Requirement: Estimated account and isolated closing proceeds
Equity SHALL include collateral, undiscounted price PnL and signed unsettled funding once. Estimated Value SHALL subtract estimated closing taker fees with account fee overrides. Settled fees/funding SHALL NOT be subtracted again. Isolated position leverage/ROI SHALL use actual collateral; Cross position leverage/ROI SHALL remain unavailable unless their venue convention is verified.
#### Scenario: Funding signs and fee override
- **WHEN** collateral is 100 USD, PnL 5 USD, unsettled funding -2 USD, and estimated exit fee 1 USD
- **THEN** equity is 103 USD and estimated Value 102 USD
- **AND** effective Cross leverage uses 103 USD as its denominator