102: EMC Perps: show liquidation risk and account health
This commit is contained in:
+52
-6
@@ -1,10 +1,12 @@
|
||||
# Phoenix Perps read-only integration
|
||||
|
||||
`PhoenixPerpsService`, `PhoenixPerpsAccount`, `PhoenixPerpsPosition` and `PhoenixTwapOrder` live in
|
||||
`PhoenixPerpsService`, `PhoenixPerpsAccount`, `PhoenixPerpsPosition`, `PhoenixAccountRisk` and `PhoenixTwapOrder` live in
|
||||
`com.r35157.libs.phoenix.perps`; the REST implementation is in `impl.ref`.
|
||||
They contain no Evelyn/UI types or signing/trading operations. NenjimHub creates
|
||||
one adapter without a portfolio cache as `phoenix.perps.default` and injects it into both Evelyn
|
||||
Perps processes. Each process owns its own wallet list, refresh worker and snapshot.
|
||||
The adapter also receives the existing `SolanaBlockChain` for local trader PDA
|
||||
derivation only; risk lookup does not use its RPC or signing operations.
|
||||
See [Evelyn](Evelyn.md#12-perps-service-og-mission-control) for consumer behavior and
|
||||
[the canonical system overview](../../r35157_docs/projects/evelyn/README.md#evelynperpsservice)
|
||||
for configuration and deployment status.
|
||||
@@ -31,10 +33,17 @@ The implementation uses these official endpoints at `https://perp-api.phoenix.tr
|
||||
4. [`GET /v1/trader/{authority}/twap?traderPdaIndex=0`](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/src/api/traders/client.ts)
|
||||
supplies active TWAP snapshots when the wallet has held positions. Only filled orders
|
||||
with remaining children on matching existing positions are returned; see [TWAP observations](#twap-observations).
|
||||
5. [`GET /v1/view/trader/{pubkey}`](https://docs.phoenix.trade/api/trader/get-trader)
|
||||
supplies risk for each visible account, including funded empty Cross accounts.
|
||||
Its key is the derived trader account, not the wallet or a TWAP key. See
|
||||
[venue-reported account risk](#venue-reported-account-risk).
|
||||
|
||||
An empty trader state needs only the first request. Otherwise metadata is fetched once
|
||||
An empty trader state with no visible funded account needs only the first request.
|
||||
A funded empty Cross account additionally needs its risk read, without market/TWAP reads.
|
||||
Otherwise metadata is fetched once
|
||||
and each active symbol's price once per wallet lookup, including when that symbol is
|
||||
held in several subaccounts, followed by one TWAP read. Request starts are spaced at least one second apart across both environments to avoid
|
||||
held in several subaccounts, followed by one TWAP read and each visible account's
|
||||
risk read. Request starts are spaced at least one second apart across both environments to avoid
|
||||
bursts of per-market reads. Each HTTP request has a 10-second timeout and uses the
|
||||
Hub's existing HTTP client (no redirects by default). On HTTP 429 the adapter respects
|
||||
`Retry-After` (seconds or HTTP date; 60 seconds if missing/invalid). Further calls
|
||||
@@ -92,13 +101,49 @@ external data; EMC's three-second polling remains unchanged.
|
||||
Positions and prices are separate REST reads and can belong to different slots.
|
||||
This is a periodic current-notional estimate, not an atomic exchange valuation.
|
||||
A cycle's duration includes all sequential reads and request pacing before the
|
||||
60-second pause (32 active markets need at least about 34 seconds for their reads). Failed
|
||||
60-second pause (32 active markets and one visible account need at least about 35 seconds for their reads). Failed
|
||||
reads can leave old data visible indefinitely. A visible venue shows `(retained)` after
|
||||
a failed refresh; cell tooltips include the last-success time. Childless venues are hidden,
|
||||
with failed or pending first-read status available in their wallet's tooltip. Such unknown
|
||||
scopes cannot contribute fabricated zero totals.
|
||||
Trader PDA indices other than 0, streaming and position management are out of scope.
|
||||
|
||||
## Venue-reported account risk
|
||||
|
||||
The [official address derivation](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/src/pdas.ts)
|
||||
uses program `EtrnLzgbS7nMMy5fbD42kXiUzGg8XQzJ972Xtk1cjWih` and seeds
|
||||
`trader`, authority bytes, a one-byte PDA index and a one-byte subaccount index.
|
||||
The adapter uses the existing local Solana derivation, validates the returned
|
||||
authority/trader key/PDA/subaccount, and verifies the nonzero position membership
|
||||
and signed quantities against trader state. A fill during the separate reads can
|
||||
therefore cause a retained failed observation rather than attach risk to mismatched
|
||||
position state. Lookup works without any active TWAP.
|
||||
|
||||
TraderView returns `riskState`, `riskTier`, `effectiveCollateral`,
|
||||
`maintenanceMargin` and position `liquidationPrice`. The actual deployed amount
|
||||
objects contain integer `value` and `decimals`; the reader computes exact decimal
|
||||
amounts with decimal exponents from -18 through 18 and ignores formatted `ui` strings.
|
||||
Positive liquidation prices are
|
||||
retained; `-1`, zero, other nonpositive values and absent prices are unavailable.
|
||||
They are not zero risk or infinite safety. Optional missing fields and unsupported
|
||||
future tiers cannot silently become Safe. Malformed amounts, identity mismatches
|
||||
and rejected HTTP reads fail the complete wallet/venue observation.
|
||||
|
||||
Cross risk belongs to the shared account. The reported effective collateral can
|
||||
include funding, discounted positive PnL and collateral haircuts; it is distinct
|
||||
from the overview's undiscounted equity and estimated closing Value. Risk therefore
|
||||
can be available even where the older capital valuation cannot value spot collateral.
|
||||
The reported thresholds and tier are preserved without inventing a liquidation engine.
|
||||
See [Phoenix account health](https://docs.phoenix.trade/phoenix/margin-and-risk/account-health)
|
||||
and [margin math](https://docs.phoenix.trade/phoenix/margin-and-risk/margin-math).
|
||||
|
||||
Account risk carries its original response receipt time. Isolated risk combines
|
||||
that account's reported liquidation price with its already fetched Phoenix mark;
|
||||
its observation time is the older receipt. Prices and account data are separate
|
||||
reads and can lag the chain. Existing failures retain original timestamps. The
|
||||
[Risk presentation](Evelyn.md#risiko-i-perps) defines five-minute expiration,
|
||||
neutral isolated distance, venue tier colors and group summaries.
|
||||
|
||||
## TWAP observations
|
||||
|
||||
TWAP data is matched by requested authority, PDA index, subaccount and market `assetId`
|
||||
@@ -202,8 +247,9 @@ venue's displayed conventions have not been verified; the UI explains this and
|
||||
shows dollar PnL. Isolated leverage/ROI use actual collateral. Cross position
|
||||
Value is inapplicable; Cross account Value counts all shared capital once,
|
||||
including free collateral when its last position closes. Other aggregate ratios
|
||||
are blank. No account margin-utilization percentage is claimed; orders/risk
|
||||
adjustments are not included in such a metric.
|
||||
are blank. Risk separately displays reported maintenance-margin utilization
|
||||
against effective collateral. It is not total initial-margin utilization, free
|
||||
buying power or the ratio used for the Leverage column.
|
||||
|
||||
Value is an estimate at separately read reference prices, not an executable quote.
|
||||
Slippage, price impact, swaps, network fees, account rent, future funding and
|
||||
|
||||
Reference in New Issue
Block a user