cme-globex-futures-api-integration · v2.0.0 · 2026-09-04 · sha256 ed7bf621dee045f6
cme-globex-futures-api-integration v2.0.0A
Immutable. This exact content is served forever at /api/v1/blob/ed7bf621dee045f6.
--- name: cme-globex-futures-api-integration description: >- Use when assembling CME Globex order entry messages yourself, to supply the Operator ID and Manual Order Indicator a message is rejected without, apply price banding and validate the fields before dispatch. This is live order entry over iLink 3. license: Apache-2.0 metadata: domain: algorithmic-trading subdomain: global-market-integration tags: cme-globex, ilink3, futures, tag50, tag1028, mwp, price-banding, tick-conformance brokers_frameworks: "CME Globex iLink 3; CME FIX" version: "2.0.0" author: algo-trading-skills-contributors --- ## When to Use Use this skill when a trading system sends orders to CME Globex — futures and options on futures such as `ES`, `CL`, `ZB` — and you are assembling the order entry message yourself rather than handing an order to a vendor OMS that already fills in the exchange-mandated fields. It covers the four gateway checks a hand-rolled CME client most often gets wrong: 1. **Operator ID (Tag 50 / iLink 3 `SenderID`)** absent or malformed — CME Rule 576. 2. **Manual Order Indicator (Tag 1028)** absent, or a team/ATS ID used on a manually entered order — CME Rule 536.B. 3. **Price banding** implemented as a two-sided check, which rejects perfectly legal resting orders that the exchange would accept. 4. **Market with Protection** treated as an unbounded market order, so the residual that rests at the protection limit is invisible to position and risk logic. ## When NOT to Use - **As a session layer.** This module validates and assembles fields. It does not encode SBE, run the FIXP session, sequence messages, or recover gaps — see `fix-protocol-session-management-across-venues`. - **For stop and stop-limit orders.** Stop orders on Globex have their own protection and trigger semantics; `process_order` rejects any order type other than `LIMIT` and `MARKET` rather than silently treating it as a limit. - **As an idempotency mechanism.** `cl_ord_id` is passed through, not tracked. Whether a resubmission after a lost response duplicates an order is out of scope — see `order-placement-idempotency`. - **As a source of contract parameters.** Tick size, Price Band Variation and protection points are inputs. They come from CME's published product reference files and change; nothing here derives or guesses them. - **As your only pre-trade risk gate.** These are exchange-conformance checks, not capital, exposure or drawdown limits — see `sec-rule-15c3-5-risk-controls-us`. ## Prerequisites - A CME Globex Firm ID, iLink session, and Operator IDs registered in the Exchange Fee System (EFS). The value transmitted must match the registration exactly. - Knowledge of which Operator IDs are registered to an individual and which to a team/ATS — the two are not interchangeable across manual and automated orders. - Per-symbol `ContractSpec`: tick size (minimum price increment), Price Band Variation, and Market-with-Protection points, refreshed from CME's product reference files. - Python 3.10+. Standard library only — `decimal`, `logging`, `dataclasses`. ## Workflow 1. **Load contract specifications.** Build a `ContractSpec` per symbol. The constructor rejects a non-positive tick size or negative band/protection values, because a zero-width band silently rejects every order and a zero tick makes every price off-tick. 2. **Construct the engine.** Pass `team_operator_ids` if you know which IDs are team/ATS registrations — the manual/automated pairing check is skipped when the set is empty rather than guessed at. Pass `permitted_operator_id_symbols` if the advisory notice in force for your firm differs from the default `_ - : @`. 3. **State Tag 1028 explicitly on every order.** `manual_order_indicator` has no default. `True` means a human entered the order; `False` means it was generated or routed without direct human interaction — anything an execution algorithm produces is `False`. An order that leaves it unset is rejected before transmission, because CME rejects the message anyway and a guessed audit-trail value is worse than a refusal. 4. **Call `process_order` with the market state the exchange will judge the order against.** `reference_price` is the CME Banding Reference Price — the last trade, else the best bid/offer, else the settlement price — and is required for a limit order. `current_bid` / `current_ask` are needed only for a market order, and only on the side the protection limit is computed from. 5. **Handle the rejection by type, not by string.** `OperatorIdError` and `ManualOrderIndicatorError` mean a registration or configuration fault: the same order will fail again, so do not retry it — escalate. `PriceBandingError` and `TickConformanceError` mean the price is wrong for the current market: re-price and resubmit. A bare `CmeOrderValidationError` on a market-data argument means the quote is unusable, so refresh it before retrying. 6. **Account for the Market-with-Protection residual.** On a market order the returned `price` is `None` — a market order carries no Tag 44 — and `protection_price_limit` says where unfilled quantity will rest as a limit order. Feed that into position tracking. If `protection_limit_outside_band` is set, the residual would rest outside the price band; the module flags and logs it rather than rejecting, because banding applies to price-based orders and a market order carries no price. ## Common Pitfalls - **Checking the price band on both sides.** CME rejects buys above BRP + PBV and sells below BRP − PBV, and deliberately does *not* stop a bid below the market or an offer above it. A symmetric `min <= price <= max` check rejects ordinary deep passive orders the exchange would have accepted — a silent loss of legitimate order flow that no exchange reject ever tells you about. - **Trusting `price % tick_size == 0`.** In binary floating point `5000.10 % 0.05` is about 0.049999999, so a naive modulo check rejects a valid price for any product whose tick is not a power of two. Tick arithmetic here runs in `decimal.Decimal`. - **Letting protection points off the tick.** If protection points are not a whole number of ticks, the computed protection limit is off-tick. This module rounds it *toward* the market — down for a buy, up for a sell — so rounding can only tighten protection. - **Sending a market order as if it were unbounded.** Globex fills a market order only inside the protected range and rests the remainder at the limit of that range. A client that does not model this ends up holding a resting limit order it never placed. - **Trimming whitespace off an Operator ID and sending it anyway.** The transmitted value must match the EFS registration exactly; a padded ID is a configuration fault, so it is rejected rather than normalised. - **Distinguishing Operator IDs by letter case.** CME Operator IDs are not case sensitive, so `DESK_01` and `desk_01` are the same registration. The team/ATS check here compares case-insensitively for the same reason. - **Omitting Tag 1028.** In-scope iLink order entry messages without it, or with an invalid value, are rejected — and a team/ATS Operator ID may only submit automated messages. ## Verification - Submit an order with `manual_order_indicator=None` and confirm it is rejected before transmission rather than defaulted. - Submit a limit buy far *below* the reference price and confirm it is **accepted** — the regression case a two-sided band check gets wrong — then a limit buy one tick above BRP + PBV and confirm `PriceBandingError`. - Submit a limit price off the product's tick (e.g. 5000.10 on a 0.25-tick product) and confirm `TickConformanceError`. - Submit a market buy and confirm `price is None`, `ord_type == "MARKET"`, and `protection_price_limit == best_offer + protection_points`, on-tick. - Run `python -m unittest discover -s skills/cme-globex-futures-api-integration/scripts`. ## Related Skills - `cme-stp-fix-and-ilink2-tag-value-encoding` - `fix-protocol-session-management-across-venues` - `order-placement-idempotency` - `exchange-self-match-prevention-configuration` - `sec-rule-15c3-5-risk-controls-us`