Skip to content

Deutsche Borse XETRA API Integration

deutsche-borse-xetra-api-integrationsource

Use when building an order path into Deutsche Boerse Xetra over the T7 Enhanced Trading Interface, validating RTS 11 tick size by liquidity band and the ETI field domains client-side before the message leaves your process.

Version
2.0.0
Reading
5 min
Hands off to
3
Handed off from
4
License
Apache-2.0
CoversDeutsche Börse T7 ETI (Cash)MiFID II RTS 11 (Delegated Regulation (EU) 2017/588)Python Dataclasses

When to Use

Use this skill when building or auditing an order path into Deutsche Börse Xetra (MIC XETR) over the T7 Enhanced Trading Interface (ETI) — a little-endian binary protocol with FIX 5.0 SP2 semantics. It covers the checks that must happen on the client side, before a message leaves your process:

  • Is the limit price on the RTS 11 tick for this instrument's liquidity band?
  • Are the ETI field values in their documented numeric domains (Side, TradingCapacity, OrderOrigination, short-code qualifiers)?
  • Is the price encoded as the scaled integer ETI actually carries?
  • Is the 24-byte ETI request header framed correctly, with a gap-free MsgSeqNum?

When NOT to Use

  • Not a transport. Nothing here opens a socket, logs on to a gateway, or sends an order. ready_to_send means "passed local validation", never "the exchange has it". Session establishment, throttling, heartbeats, and recovery are out of scope.
  • Not a full message encoder. It frames the header, not the message body. Body layouts are release-specific — take them from the ETI Cash Message Reference for the release you are certified against.
  • Not a source of liquidity bands. The RTS 11 band is per-instrument reference data you must supply from the venue's Reference Data file. This skill will not guess it, because it cannot be inferred from the price.
  • Not for Eurex derivatives. Eurex runs T7 too, but with its own message reference, product identifiers, and account-type conventions.

Prerequisites

  • T7 ETI session and user credentials; SenderSubID is the T7 User ID.
  • Instrument reference data: SecurityID (tag 48), MarketSegmentID (tag 1300), and the instrument's RTS 11 liquidity band (1–6). The ISIN is for human readability — the wire identifies instruments numerically.
  • Your firm's RTS 24 short codes, already uploaded to the venue's short/long code database with a valid-from date.
  • The ETI Cash Message Reference for your target release.

Workflow

  1. Resolve the liquidity band before pricing anything. Read it from venue reference data. It changes annually: ESMA publishes ADNT figures and venues apply the new bands from the first Monday of April (RTS 11 Art. 3(4), as amended by Delegated Regulation (EU) 2023/960 — the original text said 1 April). On changeover, Xetra deletes resting orders whose limits no longer comply, so re-price or re-submit rather than assuming your book survived.
  2. Look up the tick in the RTS 11 Annex matrix — 19 price bands × 6 liquidity bands. Never from price alone. At €62.50 the tick is €0.01 in band 6 but €0.50 in band 1; a price-only rule silently accepts prices the venue rejects for illiquid names.
  3. Validate field domains before the tick check. An invalid quantity or side makes the tick question meaningless, so report the first real defect rather than a downstream symptom. Side (tag 54) is 1/2, not "BUY"/"SELL". TradingCapacity (tag 1815) is 1 Customer (Agency), 5 Principal (Proprietary), 6 Market Maker, 9 Riskless Principal, 10 Retail Customer (Agency) — numeric, and not the letters P/A/M.
  4. Encode the price as an integer with 8 implied decimals. ETI PriceType is an 8-byte signed integer scaled by 10^8. Refuse a price that needs more than 8 decimals instead of rounding it — rounding sends a price the caller did not ask for.
  5. Frame the header and advance MsgSeqNum only on success. BodyLen is the whole message length including the BodyLen field itself (24 + body). A rejected order must not consume a sequence number, because a gap is a session-level fault.
  6. Pick a template that still exists. The R14.0 change log schedules New Order Single (10100) and its short layout (10125) for decommissioning with ETI 14.1 in mid-2026, naming New Order Single or Multi Leg (10138) and 10139 as replacements. Confirm against the reference for your release.

Full procedure: see references/workflows.md. Standards reference: see references/standards.md. Printable pre-flight checklist: see assets/checklist.md.

Common Pitfalls

  • Treating the tick size as a function of price. This is the single most expensive mistake here. RTS 11 indexes the tick by price band and liquidity band. A hard-coded price-only ladder accepts off-tick prices for illiquid instruments and reports the wrong rounding increment even where the accept/reject verdict happens to agree.
  • Float modulo for tick checks. -5.0 % 0.001 == 0.0 in Python, so a naive float check passes negative prices; and 0.1 as a float is 0.1000000000000000055…, which is not a multiple of any tick. Use Decimal, and validate that the price is positive as its own check.
  • Sending P/A/M as the capacity. Those are leading characters of the ETI Account field (tag 1, valid characters 1-9, A, G, M, P), which books positions. The MiFID capacity is the numeric TradingCapacity (tag 1815). They are different fields with different purposes.
  • Assuming one "MiFID short code" field. There are several distinct fields: OrderOrigination (1724, value 5 = order received from a direct access customer) flags DEA; ExecutingTrader (25123) with ExecutingTraderQualifier (25124, 22 Algo / 24 Human) and PartyIdInvestmentDecisionMaker with its qualifier (21222) carry the RTS 24 short codes. A short code only resolves if the matching long code was uploaded to the venue beforehand — unresolved combinations surface in the TR160/TR161/TR166 reports.
  • Burning a sequence number on a rejected order. MsgSeqNum must increase by exactly one per request on a session.
  • Sending the ISIN as the instrument identifier. T7 ETI uses the numeric SecurityID (tag 48) plus MarketSegmentID (tag 1300).
  • Conflating ETI with market data. ETI is order entry. Level 2 depth comes from the separate T7 Market Data Interface (MDI) multicast feeds.
  • Copying field offsets across releases. Offsets and field widths change — OrderQty moved from 4 to 8 bytes between Release 5.0 and Release 14.0. Only the header layout has held stable.

Verification

  • rts11_tick_size("62.50", 6) $\implies$ Decimal("0.01"); rts11_tick_size("62.50", 1) $\implies$ Decimal("0.5"). Both are read directly off the RTS 11 Annex row 50 ≤ price < 100.
  • Instantiate DeutscheBorseXetraApiEngine(sender_sub_id=98765). Submit an order for DE0007100000 at €62.50, qty 500, liquidity_band=6, trading_capacity=5 $\implies$ STATUS_OK, price_eti_int == 6_250_000_000, side_wire_value == 1.
  • The same order at €62.503 $\implies$ INVALID_TICK_SIZE. At €62.53 with liquidity_band=1 $\implies$ INVALID_TICK_SIZE (tick €0.50).
  • Negative or zero price, non-positive quantity, an unknown side, and a letter trading_capacity $\implies$ INVALID_ORDER_FIELD, and none of them consume a sequence number.
  • header.pack() $\implies$ exactly 24 bytes, with BodyLen at offset 0 and TemplateID at offset 4, little endian.
  • Run python -m unittest discover -s skills/deutsche-borse-xetra-api-integration/scripts.

Verify it, from the repository root

python -m unittest discover -s skills/deutsche-borse-xetra-api-integration/scripts

Hands off to 3

Skills this document names, usually in When NOT to Use, as the owner of a case it excludes.

SEC, FINRA, MiFID II, FCA, SEBI

Calendars, timezones, symbology

Colocation, clocks, tick-to-trade

Handed off from 4

Skills that name this one as the place a case belongs. The reverse edges of the graph.

SEC, FINRA, MiFID II, FCA, SEBI

Calendars, timezones, symbology