Trading and fees

Place binary options orders, calculate fees, and handle market-specific restrictions.

Binary options use the same CreateOrder, ModifyOrder and CancelOrder transactions and the same SDK / WASM signer calls as other markets. Pass the binary options market_id and:

📘

For the current binary options discovery methods and response models, use lighter-sdk 1.1.8 or newer, or lighter-go v1.0.12 or newer. Python 1.1.8 also fixes the boPnl authorization header. The standard create, modify and cancel order flow is unchanged; discover binary options market IDs through events.

The shared-library signer uses signed 64-bit market indices (int64). If you call it directly from C/C++ or a custom FFI binding, use a .h file and bindings that match your signer library. Update declarations that still use int cMarketIndex to long long int cMarketIndex, as shown in the current signer header.

See the Python binary options examples, especially create_order_from_event.py, for market discovery through events followed by create_order.

ParameterBinary options
priceInteger price ticks: 51 = 0.51 USDC. Must be > 0 and < settlement_cap (100)
baseAmountInteger shares × 10^size_decimals: 1000000 = 100.0000 shares
isAsk0 buy = Up, 1 sell = Down
orderType0 Limit or 1 Market only
timeInForce0 IOC · 1 Good-till-time · 2 Post-only
reduceOnlyMust be 0
triggerPriceMust be 0 (no stop / take-profit / TWAP)

Place an order

Python

Use an initialized SignerClient from Signing transactions. Set MARKET_ID to a current binary options market ID from Discover markets.

tx, tx_hash, err = await client.create_order(
    market_index=MARKET_ID,      # market_id from /api/v1/events
    client_order_index=1234,
    base_amount=1000000,         # 100.0000 shares
    price=51,                    # 0.51 USDC per Up share
    is_ask=False,                # buy = Up
    order_type=client.ORDER_TYPE_LIMIT,
    time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
    reduce_only=False,
    order_expiry=client.DEFAULT_28_DAY_ORDER_EXPIRY,
)

TypeScript (WASM)

This snippet uses the signer and submission helpers from the TypeScript quickstart.

const tx = check(lighter.SignCreateOrder(
  MARKET_ID, clientOrderIndex, 1000000, 51, 0 /* buy = Up */, 0 /* limit */, 1 /* GTT */,
  0, 0, orderExpiry,
  0, 0, 0,                    // integrator account, taker fee, maker fee
  0, 0, 0, nonce, API_KEY_INDEX, ACCOUNT_INDEX,
));
await sendTx(tx);

Order rules

  • Create and modify requests must pass the same trading-window, frozen-book and price-cap checks: start_timestamp ≤ block time ≤ end_timestamp, is_frozen = false, and 0 < price < settlement_cap. A start_timestamp of 0 means trading can start from listing. Cancellation is allowed outside the trading window.
  • For resting orders, buy cost is P × size and sell cost is (1 − P) × size, where P is the Up price in USDC and size is shares. The USDC reserve is calculated per market as max(Σ buy costs − Down shares held × 1.00, Σ sell costs − Up shares held × 1.00, 0). Buy and sell requirements are not added together; existing shares offset the opposite side. IOC and market orders are funded at fill time.
  • The min_quote_amount check uses P × size for both buys and sells, even though opening a Down position costs (1 − P) × size. Read both minimums from events. For example, mainnet markets checked on October 19, 2026 have min_base_amount = 5 shares and min_quote_amount = 0.000001 USDC. A 5-share sell at P = 0.02 has an Up notional of 0.10 USDC and passes that quote minimum; its Down cost is 4.90 USDC. In this configuration the 5-share base minimum is the binding minimum. Also respect order_quote_limit.
  • A market order's price is the worst acceptable Up price, as on other markets.
  • Public pool and insurance fund accounts cannot trade binary options.

Errors

CodeMessageCause
21618invalid order type for marketStop, take-profit, TWAP or reduceOnly = 1
21631market is outside its trading windowCreate or modify request before start_timestamp or after end_timestamp
21632order price must be below the full payoutCreate or modify request with price ≥ settlement_cap
21638order book is frozenCreate or modify request while the operator has frozen the market
21752pools are not allowed to trade in binary options marketsPublic pool / insurance fund account

Orders and trades

accountActiveOrders, accountInactiveOrders and trades accept market_type=bo (all by default) and work with a binary options market_id. Trades carry market_kind: "bo". Settlement records use type: "market-settlement"; see Positions and settlement.

recentTrades returns an empty list once a binary options market has settled. Use trades with market_id for historical fills and settlement records. exchangeStats includes binary options symbols such as ETH-UPDOWN-…; filter its market entries by symbol when separating market types.

Fees

Each market has a maximum taker_fee and maker_fee (Up/Down series: taker 1%, maker 0%). Both sides pay in USDC on the trade notional, scaled by the trade price and by the account's binary options fee multiplier:

fee = marketFee × bo_fee_rate × size × P × (1 − P)

Use decimal rates in the formula: marketFee = 0.01 for a 1% market fee. P is the Up price in USDC (0.51, not 51 price ticks).

  • size × P is the Up-price notional in USDC. Opening Down costs (1 − P) × size; resting-order reserves follow the per-market rule above. Use the same fee formula for both sides.
  • (1 − P) makes fees smaller as the outcome becomes certain: highest at P = 0.50, near zero at 0.01 and 0.99.
  • bo_fee_rate is the account's multiplier, the product of its binary options volume tier and LIT staking tier, 1 by default.

Binary options fees are separate from the perps/spot account tiers. feeTiers with filter=bo returns the bo_tiers (by trailing volume) and staking_tiers tables; accountLimits returns the account's bo_user_tier_name and bo_fee_rate. Read the current tables from the endpoint instead of hard-coding volume thresholds or staking discounts.

curl "https://mainnet.zklighter.elliot.ai/api/v1/feeTiers?filter=bo"

Fees in trade responses

In trade JSON, taker_fee / maker_fee are the effective rate in fee ticks (1e6 = 100%): with bo_fee_rate = 1, a 1% market taker fee on a fill at 0.51 shows as taker_fee: 4900 (10000 × (1 − 0.51)), i.e. 51.00 × 0.49% = 0.2499 USDC on 100 shares.


Did this page help you?