# Phoenix — market metadata, lots, ticks, and after-hours bands

This file explains Phoenix perpetuals numeric units and market metadata, including negative base-lot decimals and RWA execution bands. The public market response was checked on 2026-10-03.

## TL;DR

1. Base lot is `10^-baseLotsDecimals`; negative decimals mean lots larger than one unit.
2. Quote lot is one millionth of a USD; price tick depends on both tick size and base-lot decimals.
3. Exact integer arithmetic prevents the SDK's floating-point floor trap.
4. Market status and isolated-only eligibility are separate conditions.
5. After-hours does not itself mean closed. Bands expire at reopening and must come from fresh metadata.

## 1. Exact units

For `bld = baseLotsDecimals` and integer `tickSize`:

```text
baseLotUnits = 10^(-bld)
quoteLotUsd = 10^(-6)
tickUsdPerUnit = tickSize × 10^(bld - 6)
priceTicks = priceUsdPerUnit × 10^(6 - bld) / tickSize
```

Quote decimals 6 were verified against the on-chain global configuration on 2026-09-24. A negative `bld`, such as -2, yields a lot of 100 units. Such metadata was present in the public list on 2026-10-03.

Synthetic examples illustrate arithmetic, not actual current listings: `tickSize=100, bld=4` gives a one-dollar price tick and a 0.0001-unit lot; `tickSize=10, bld=2` gives a 0.001-dollar tick and a 0.01-unit lot.

Use a shortest-decimal representation converted to a rational and integer division. The evaluated Rise 0.5.28 `priceToTicks` uses floating-point multiplication and floors; a price intended to sit exactly on-grid can shift one tick. Resting nearest rounding and IoC buy-floor/sell-ceil are distinct operations. Size conversion uses caller-selected floor/ceil and a small numerical tolerance for double artifacts, without adding a full lot.

u64 and i64 parsers accept decimal strings and enforce their bounds. Numbers are rejected because precision may already be lost. One lot was sufficient for tested resting/IoC orders on 2026-09-24; an additional universal dollar floor was not established.

## 2. Metadata and statuses

Required market fields include symbol, asset ID, book and spline addresses, tick size, base-lot decimals, status, isolated-only flag, and leverage-tier data. The toolkit decoder accepts the documented array/envelope forms and rejects duplicates or malformed grids as a whole response.

Statuses from the protocol are `uninitialized`, `active`, `postOnly`, `paused`, `closed`, and `tombstoned`. Active and post-only can be listed; paused is unknown tradability, while closed/tombstoned/uninitialized are not tradable. A post-only market still needs the appropriate order instruction; packet acceptance in this mode was not tested in the evaluated implementation.

The 2026-10-03 public response contained 92 active markets, 9 isolated-only markets, and 43 RWA markets. These counts describe that response only. The first leverage tier supplies a maximum leverage; there is no per-account leverage setter in the evaluated protocol.

Isolated markets use child subaccounts according to the official SDK. The toolkit can decode their metadata and account rows; child registration/funding/trading orchestration is not implemented or live verified.

## 3. RWA after-hours metadata

RWA rows may carry `commodityMetadata` with after-hours flag, index anchor, band radius, mark band, execution band, and index-expiry timestamp. Calendar metadata includes a calendar URI, content hash, and next transition time.

REST execution bands use `{min, max}`; SDK stream shapes can use `{lower, upper}`. Validate both bounds, allowing a zero lower bound where applicable. A malformed band makes that band unusable without necessarily invalidating all otherwise valid market metadata.

The after-hours helper returns a band only when metadata is fresh, `isAfterHours` is true, and the calendar/index-expiry evidence has not expired. Stop using it at the next transition even if a cached response still says after-hours. A future expiry value is a response field, never the date of verification.

Public data observed 2026-10-03 showed calendar transition and index expiry values consistent with an expiry shortly after opening; that observation does not establish a permanent timing guarantee.

## 4. Band execution and caching

Off-hours trading inside a static execution band was observed on 2026-09-27. Out-of-band rejection is described by `OutsideExecutionPriceBand` in public Rust event source. Band-edge inclusivity and the fill behavior of an IoC clamped exactly to that edge remain unverified. `clampIocToBand` is therefore experimental.

The market cache has explicit TTL, freshness window, and failed-refresh backoff settings; freshness is not an implicit multiple of TTL. Reject an update that drops an in-use market or changes asset ID/tick/lot unexpectedly. Transaction-key pinning compares book, spline, tick, and lot metadata; a changed pin is a review condition, not permission to trade a newly mapped instrument.

## Pitfalls

| What breaks | Why | Correct approach |
|---|---|---|
| Negative decimals produce a tiny lot | Decimal exponent was reversed | Use `10^-bld` |
| On-grid price shifts down | Float-floor SDK conversion | Exact rational quantization |
| Weekend marked as delisted | After-hours confused with status | Inspect fresh execution band and calendar |
| A cached band blocks a reopened market | Transition evidence expired | Discard at transition |
| Cross account sends an isolated-only order | Eligibility ignored | Explicitly unsupported orchestration |

## Open questions / not verified

- Band-edge inclusivity, clamped IoC behavior, and post-only market packet acceptance.
- Delegate permissions for isolated child registration/funding.
- Calendar or metadata transitions during an in-flight order.

## Sources

[Public Phoenix market metadata](https://perp-api.phoenix.trade/v1/view/exchange/markets) (GET checked 2026-10-03); [List markets](https://docs.phoenix.trade/api/exchange/list-markets); [Mark price and bounds](https://docs.phoenix.trade/phoenix/real-world-assets/mark-price-and-bounds); [Market specs](https://docs.phoenix.trade/phoenix/real-world-assets/market-specs); Rise 0.5.28 numeric builders in [Rise public source](https://github.com/Ellipsis-Labs/rise-public). After-hours observation: 2026-09-27. Cache/pinning policies are toolkit safeguards.

<!-- license-footer -->
_© markpaper authors. Licensed under [CC BY 4.0](LICENSE.md): when publishing or adapting this material, credit “markpaper — Phoenix knowledge base” and link to the original and the license._
