Эта страница переведена автоматически. Оригинал на английском языке является каноническим. Читать на английском
Перейти к основному содержимому

Experimental Combo API

Combos trade a fixed ratio of option legs as one order. A fill executes every required leg together. Your positions remain the individual options.

Experimental contract

All /experimental endpoints and explicitly experimental WebSocket messages are unstable. Breaking changes may take effect with one day (24 hours) of advance notice, including removing or renaming fields or endpoints, changing field types, and changing request or response behavior. Changes are announced in the API changelog. Clients must monitor these notices and update before the stated effective time. Existing non-experimental API contracts are outside this policy.

Availability depends on your environment. This page describes the experimental interface; it does not announce production availability or a new interface in the trading app.

Use the REST reference, authentication guide, and WebSocket guide for the shared connection and signing conventions.

Discover a combo

RequestResult
GET /experimental/combosA bounded page of unexpired definitions, optionally filtered by underlying
GET /experimental/combos/{symbol}One unexpired definition and its resolved option legs

First-order creation: submit a canonical combo_definition with POST /order when the combo is not yet discoverable. The first accepted order publishes its definition, including an order that fills immediately. A rejected order publishes nothing. There is no separate creation endpoint.

Discovery lifetime: a definition stays discoverable until its first leg expires, even when it has no resting orders.

Pagination: responses contain combos and next_cursor. Set limit to 1–1,000 (default 100). Pass the returned cursor as cursor on the next request, keeping the same underlying filter. A null cursor means no further row was observed. Invalid limits or cursors return HTTP 400.

GET /experimental/combos?underlying=BTC&limit=100
GET /experimental/combos?underlying=BTC&limit=100&cursor=<next_cursor>

Page ordering: earliest leg expiry, then combo ID. Treat cursors as opaque. Each page reflects current discovery state; definitions can expire or be added between requests. Use creation updates or restart discovery to capture newly created definitions that sort before a saved cursor.

Identity: a symbol is COMBO- followed by 64 lowercase hexadecimal characters. Its content-bound ID fixes the leg instruments and signed integer ratios. An existing symbol cannot change meaning.

Initial scope: two through eight distinct option legs with the same underlying. Every leg must be listed, unexpired, and eligible for the requested execution route.

Understand side, price, and size

For a canonical definition with ratios +1 A, -1 B:

  • Buy one package: buy one A and sell one B.
  • Sell one package: sell one A and buy one B.
  • Net price: price(A) - price(B), quoted per package.
  • Limit: a buy accepts a net price at or below its limit; a sell accepts a net price at or above its limit.

Negative and zero prices are valid. If A trades at 8andBat8 and B at 10, the canonical net price is -2. Buying that package receives 2beforefees.Sellingitpays2 before fees. Selling it pays 2 before fees. Each actual option leg still has a positive execution price.

Order increments: package size uses human contract units with an increment of 0.000001; net limit price uses an increment of 0.000001. Every executed leg must also satisfy its own quantity and price increments. A partial fill preserves all ratios and fills a complete permissible package quantity.

Fees: existing per-leg rates and eligibility apply, with no package discount. The incoming order is the taker on its own legs, with its submitted builder attribution. In an outright-through-combo route, the combo parent receives normal taker fee attribution on the additional supporting legs against the supporting outright makers; those legs have no builder attribution. Resting combo reservations conservatively include prospective taker fees on the gross leg amounts. Current Standard Margin execution requires zero trading fees for book and RFQ fills; a route involving an SM participant cannot execute with nonzero trading fees.

Margin: the exchange checks the resulting option positions and remaining order exposure for each account. A combo does not combine collateral across wallets or promise a particular margin reduction. If your account tier permits only covered option sales, resting outright orders and every combo parent's sell legs share the same filled long inventory. Separate parents and split fills cannot each reuse that inventory; unfilled buy legs do not add coverage.

Place an order

Use the existing signed POST /order request with the combo symbol. The order signing fields are unchanged. Sign the exact symbol, size, and price strings you send, including a negative price's minus sign. For a new combo, add its canonical combo_definition as described below. The signed content-bound symbol commits to that definition; a mismatched definition is rejected. Known combos can omit it.

{
"wallet": "<your wallet>",
"symbol": "<discovered COMBO symbol>",
"side": "buy",
"size": "1",
"price": "-2",
"tif": "gtc",
"route": "best_execution",
"client_id": "spread-001",
"reduce_only": false,
"mmp_enabled": false,
"nonce": 1,
"signature": "<signed order>"
}

Replace the placeholders and nonce with your actual values. The price is an illustration, not a current market quote.

SettingBehavior
route: "book_only"Match available direct and supported implied liquidity, then apply the time in force
route: "best_execution"Consider a full-package price-improvement auction, then fall back to book execution when appropriate
route: "rfq_only"Rejected on /order
tif: "gtc"Rest the unfilled package remainder
tif: "ioc"Cancel the unfilled remainder
tif: "fok"Execute the entire requested package quantity or execute nothing

Price improvement compares the full package's signed net price against an executable full-size book reference. Quote providers must supply every leg at the exact requested ratio and quantity. Ranking a quote by only its first leg is insufficient. Both direct combo liquidity and supported implied routes can contribute to the reference. An unavailable or incomplete reference sends the order to book execution.

Quote eligibility: existing RFQ fee rules also apply. If either participant uses Standard Margin, RFQ execution requires zero trading fees. A quote that fails fee, collateral, or exact-allocation checks leaves execution with the current book path; it does not partially execute its legs.

Implied matching can combine one combo with its supporting outright option liquidity. For example, an outright A order can trade against an A-minus-B combo and B liquidity atomically. A customer trading only A receives no B position.

Implied searches have resource limits. If an outright order reaches those limits, its supporting liquidity becomes unavailable, or the optional route cannot represent the outright order increments, it can still trade against its direct option book under the usual order rules. Combo support does not change accepted outright quantity or price increments. The target option must remain eligible for book trading. A combo order exceeding the search limits is rejected without a partial allocation.

Current restrictions: native combo orders require mmp_enabled: false. Protected outright participants retain MMP. A threshold-triggering package completes its legs and stops further matching; an incomplete FOK or atomic replacement rolls back the complete candidate. Reduce-only orders skip the price-improvement auction and use book admission, where each resulting leg must satisfy reduce-only checks. Cancel a resting combo by its parent order ID or client order ID using the existing cancellation endpoints.

Replace: PUT /order can atomically replace a parent within the same combo definition. A rejected replacement leaves its predecessor intact. Native entries in bulk replacement also use one atomic command per parent; the batch is not one all-or-nothing transaction. Replacing between a combo and an outright, or between different combo definitions, is rejected.

Self-trade prevention: matching stops before a route would trade an account against itself, and cancels the resting maker order. Earlier completed fills remain, while the incoming remainder is canceled. With no earlier fills, the incoming order is rejected. FOK orders and failed atomic replacements preserve their all-or-nothing behavior, including rolling back tentative maker cancellations.

Define a combo in its first order

Canonicalize before signing: combine duplicate instrument IDs, remove zero ratios, sort IDs numerically, divide ratios by their greatest common divisor, and make the first ratio positive. If normalization reverses the ratios, reverse the intended order side and negate the net price. If it divides ratios by a factor, multiply package size by that factor and divide net price by it.

The version-one ID is Keccak-256 of the following concatenation:

UTF-8("hypercall:combo-definition\0")
|| version as unsigned 16-bit big-endian (1)
|| leg count as unsigned 16-bit big-endian
|| each sorted leg:
instrument ID as 32 big-endian bytes
ratio as signed 64-bit two's-complement big-endian

Instrument IDs are Keccak-256 of UTF-8 "instrument" followed by the exact canonical option symbol. The published combo ID is the full digest, encoded as 0x plus 64 lowercase hexadecimal characters. The combo symbol uses the same hex digits after COMBO-.

Include combo_definition in the ordinary signed POST /order body. The definition contains version, id, and legs; each leg contains instrument_id and ratio. Encode IDs as 0x plus 64 lowercase hexadecimal digits and ratios as canonical signed decimal strings, such as "1" or "-1". JSON numbers, leading plus signs, and leading zeros are rejected for ratios.

{
"combo_definition": {
"version": 1,
"id": "<canonical content hash as 0x plus 64 hex digits>",
"legs": [
{"instrument_id": "<first canonical instrument ID>", "ratio": "1"},
{"instrument_id": "<second canonical instrument ID>", "ratio": "-1"}
]
}
}

This fragment is added to the complete order example above. Replace the placeholders with actual IDs and use the corresponding COMBO- symbol. There is no additional definition signature or separate publication nonce. The service verifies canonical content and its identity against the signed symbol; outright orders must omit combo_definition.

Acceptance and discovery: every accepted combo order retains its definition in its durable order record and idempotently ensures the catalog entry exists. A later order does not overwrite the first creation record. An immediately filled order still creates discovery data; rejected orders do not. Discovery can lag the order acknowledgment because it is projected from committed data. Resubmitting the same definition in a later order is supported, including while its first catalog entry is still catching up.

Read orders and executions

RequestPurpose
GET /experimental/ordersRead orders with explicit instrument classification, including combo parents
GET /experimental/tradesRead real leg trades by default, or package summaries with view=packages
GET /experimental/fillsRead wallet fills by default, or wallet package summaries with view=packages

Use the REST reference for the supported filters and cursors. Package summaries are grouping records: execution IDs and leg trade IDs let you join them to actual option executions. Do not add package quantity, premium, or fees to the constituent executions when computing account totals.

Identifier precision: experimental order IDs, package execution IDs, constituent trade/order IDs, parent-order IDs, and package pagination cursors are decimal strings. Keep them as strings in your client; converting them to JavaScript numbers can lose precision. Legacy view=legs responses retain their existing representations.

Compatibility: legacy instrument discovery and order views retain their outright contract. Actual option leg executions continue to appear in legacy trade/fill feeds, and positions remain option positions. A combo's parent order is not a collection of independently resting leg orders.

Subscribe explicitly

Experimental private channels require the existing WebSocket authentication step and an explicit subscription. They only publish the authenticated wallet's parent records.

ChannelMessageAudience
experimental_order_updatesExperimentalOrderUpdate with parent ID, symbol, instrument type, quantity, filled quantity, and net priceAuthenticated wallet
experimental_combo_tradesComboTrade with execution ID, symbol, package quantity, net price, and leg trade IDsPublic
experimental_combo_fillsComboFill with the wallet's parent order ID, side, and package executionAuthenticated wallet
{"type":"Subscribe","channel":"experimental_order_updates"}

Subscribe to the existing book channel using a discovered combo symbol:

{"type":"Subscribe","channel":"orderbook","symbols":["<discovered COMBO symbol>"]}

Market discovery updates can repeat the same immutable definition; deduplicate by combo ID. They use MarketUpdate on market_updates, with action: "ComboCreated", the combo symbol, ID, canonical legs, and timestamp. Treat discovery, parent order status, package execution summaries, and actual leg fills as distinct records when reconciling your client.