underlyingKey: the underlying, a 64-bit key assigned when the underlying
is listed. Find them at GET /v1/underlyings.specifier (optionSpecifier in an order): the contract within that
underlying, packing its expiry, strike and right./v1/book/7/859008923130267914, book:7:859008923130267914.| Bits | Field | Value |
| 63–32 | Expiry | whole seconds since 2020-01-01T00:00:00Z |
| 31–12 | Strike | micros: 50000, 100000, …, 950000 |
| 11 | Right | 0 call, 1 put |
| 10–8 | Style | 1, European |
| 7–0 | Multiplier ÷ 10 | 10 |
1specifier = expirySeconds << 32 | strike << 12 | right << 11 | 1 << 8 | 10
expiryMs is that
times 1000. A specifier that decodes to anything other than a listed strike,
European style and a multiplier of 100 names no contract, and the gateway refuses
an order for it.12345678910def encode(strike: int, right: int, expiry_ms: int) -> int: assert expiry_ms % 1000 == 0 return (expiry_ms // 1000) << 32 | strike << 12 | right << 11 | 1 << 8 | 10 def decode(spec: int) -> dict: return { "expiryMs": (spec >> 32) * 1000, "strike": (spec >> 12) & 0xFFFFF, "right": (spec >> 11) & 1, }
| Strike | Right | Expiry (engine ms) | Specifier |
50000 | call | 200003600000 | 859008921287065866 (0x0bebd0100c35010a) |
500000 | put | 200003600000 | 859008923130267914 (0x0bebd0107a12090a) |
Number cannot hold them.
Use BigInt, and a JSON parser that keeps large integers.underlyingKey << 64 | expiryMs, big-endian. It
appears as 64 hex characters in the instrument catalog and in your account's
books, and the settlement contract uses it to post settlement prices and pay
claims.GET /v1/instruments lists every listed contract
with its strike, right, expiry, bucket and fee rates, so most clients never
encode a specifier themselves. They pick one from the catalog.