101: EMC Perps - show Phoenix TWAP progress and time until next suborder
This commit is contained in:
+58
-4
@@ -1,6 +1,6 @@
|
||||
# Phoenix Perps read-only integration
|
||||
|
||||
`PhoenixPerpsService`, `PhoenixPerpsAccount` and `PhoenixPerpsPosition` live in
|
||||
`PhoenixPerpsService`, `PhoenixPerpsAccount`, `PhoenixPerpsPosition` 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
|
||||
@@ -26,11 +26,15 @@ The implementation uses these official endpoints at `https://perp-api.phoenix.tr
|
||||
supplies each symbol's `baseLotsDecimals`, `tickSize`, leverage tiers and taker fee.
|
||||
3. [`GET /v1/market/{symbol}/mark-price`](https://docs.phoenix.trade/api/exchange/get-mark-price)
|
||||
supplies `markPrice.price` in USD. The API permits an absent mark price; a held
|
||||
position without a valid positive price fails the lookup rather than appearing as zero.
|
||||
position remains visible with unknown price-dependent metrics when the mark is absent.
|
||||
A present nonpositive or malformed price still fails the lookup.
|
||||
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).
|
||||
|
||||
An empty trader state needs only the first request. Otherwise metadata is fetched once
|
||||
and each active symbol's price once per wallet lookup, including when that symbol is
|
||||
held in several subaccounts. Request starts are spaced at least one second apart across both environments to avoid
|
||||
held in several subaccounts, followed by one TWAP 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
|
||||
@@ -88,13 +92,63 @@ 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 33 seconds for their reads). Failed
|
||||
60-second pause (32 active markets need at least about 34 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.
|
||||
|
||||
## TWAP observations
|
||||
|
||||
TWAP data is matched by requested authority, PDA index, subaccount and market `assetId`
|
||||
using Phoenix metadata. Only an existing nonzero position can carry a TWAP, and the
|
||||
order itself must have `baseLotsFilled > 0` and remaining children. A new order without
|
||||
fills stays invisible even if the market already has a position. No TWAP-only row or
|
||||
group total is created. A successful snapshot without that active order clears its
|
||||
TWAP data. A failed or invalid TWAP read fails the whole wallet/venue observation,
|
||||
retaining the previous complete snapshot and its original timestamps as `(retained)`.
|
||||
|
||||
The [SDK snapshot](https://github.com/Ellipsis-Labs/rise-public/blob/master/ts/src/api/traders/twap.ts)
|
||||
reports `nChildOrders` as the total execution count including dust. With explicit
|
||||
`nDustOrders > 0`, regular count is total minus dust count. Legacy zero/omitted dust
|
||||
count with a positive `dustOrderSize` replaces one final regular child with dust.
|
||||
Total quantity is regular count × regular lot size plus dust count × dust lot size;
|
||||
the next size switches to dust when the regular children have executed. Convert all
|
||||
sizes and cumulative `baseLotsFilled` with `baseLotsDecimals`, using exact arithmetic.
|
||||
If size/dust metadata is unavailable, sizes remain unknown while independent counters
|
||||
and fills remain available. Execution progress is executed/total children; it does
|
||||
not assert that the planned quantity has filled completely.
|
||||
|
||||
Time estimates use the current nominal **200 ms per Solana slot**, documented by the
|
||||
[Solana Foundation in October 2026](https://solana.com/fr/upgrades/reduced-slot-times).
|
||||
The older 400 ms assumption no longer applies. At receipt of the TWAP response:
|
||||
|
||||
```text
|
||||
estimated next = observation time + (dueSlot - snapshot.slot) × 200 ms
|
||||
final slot = dueSlot + (childOrdersRemaining - 1) × cooldownSlots
|
||||
estimated end = observation time + (final slot - snapshot.slot) × 200 ms
|
||||
```
|
||||
|
||||
Receipt time is an approximate anchor; API lag, variable slot times and delayed
|
||||
execution can shift the estimates. No separate RPC sampling or live timer is used.
|
||||
Already-due schedules yield unavailable estimates, as do overflow or expiry before
|
||||
the scheduled child/completion. `lastValidSlot` is only an expiry boundary.
|
||||
|
||||
EMC appends **TWAP** after uPnL. Its progressbar overlays a snapshot duration with
|
||||
unbounded total hours, such as `≈ 28:32:10` or `≈ 128:32:10`. It updates only with new
|
||||
snapshots and is explicitly as of the tooltip's `Updated` time. Due/unavailable
|
||||
timing shows `Due / unknown`; a failed venue shows `Retained` instead of a fresh
|
||||
countdown. Other venues, positions without a relevant order and all groups have
|
||||
empty TWAP cells. Tooltips show progress, `Estimated completion`, total/next/fill
|
||||
quantities, different dust sizes where relevant, observation time and limitations.
|
||||
|
||||
Total and next-child USD values reuse that position's already fetched Phoenix mark,
|
||||
independently of the Ticker. They are approximate current notionals, excluding fees,
|
||||
not historical spend or a promise about future execution cost. An absent mark keeps
|
||||
token quantities visible with unavailable USD values; affected exposure, margin,
|
||||
PnL/equity/Value and dependent totals are unavailable rather than zero.
|
||||
|
||||
|
||||
## Valuations, funding and margin
|
||||
|
||||
|
||||
Reference in New Issue
Block a user