v1.0.0 to v2.0.0
112 added, 23 removed. Audit A to A.
---
name: deutsche-borse-xetra-api-integration
- description: "Quantitative venue integration engine for Deutsche B\xF6rse Xetra T7\
- \ Enhanced Trading Interface (ETI), validating MiFID II RTS 28 order parameters,\
- \ T7 tick size regimes, and binary message formatting."
+ description: "Client-side pre-dispatch validation and T7 ETI request-header framing\
+ \ for Deutsche B\xF6rse Xetra cash orders — RTS 11 tick size by liquidity band,\
+ \ ETI field domains (TradingCapacity, Side, OrderOrigination), and scaled-integer\
+ \ price encoding."
domain: Venue Integration & Protocols
subdomain: European Exchange Integration (Xetra/Eurex)
tags:
- xetra
- t7-eti
- deutsche-borse
- mifid-ii
+ - rts-11
- tick-size-regime
- binary-protocol
- european-equities
brokers_frameworks:
- - "Deutsche B\xF6rse T7 ETI"
- - FIX 5.0 SP2
+ - "Deutsche B\xF6rse T7 ETI (Cash)"
+ - MiFID II RTS 11 (Delegated Regulation (EU) 2017/588)
- Python Dataclasses
- version: "1.0.0"
+ version: "2.0.0"
author: algo-trading-skills-contributors
license: Apache-2.0
---
## When to Use
- Use this skill in European algorithmic trading systems, broker execution adapters, and high-frequency market making engines connecting to Deutsche Börse Xetra and Eurex. Xetra is Europe's premier electronic venue for equities and ETFs. Order entry is conducted via the **T7 Enhanced Trading Interface (ETI)** using binary FIX 5.0 SP2 semantics. Orders must strictly conform to Xetra tick size regimes and include MiFID II Direct Electronic Access (DEA) short codes and account classification tags (`P` Proprietary, `A` Agent, `M` Market Maker).
+ 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 credentials (`session_id`, `party_id_session`, `sender_comp_id`).
- - Instrument ISIN / WKN identifier (e.g. `DE0007100000` - Mercedes-Benz Group AG).
- - Active Xetra tick size regime table.
+ - 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. **T7 ETI Message Construction**:
- - Format binary/FIX 5.0 SP2 header (`msg_type: 10100`, `session_id`, `seq_num`, `sending_time_ns`).
- 2. **MiFID II Parameter Validation**:
- - Verify `account_type` (`P`, `A`, `M`) and `mifid_short_code` (DEA Trader ID).
- 3. **Xetra Tick Size Audit**:
- - Audit order price $P$ against Xetra price-band tick rules ($P < €10 \implies \text{Tick}=€0.001$; $€10 \le P < €50 \implies \text{Tick}=€0.005$; $P \ge €50 \implies \text{Tick}=€0.01$).
- - If price violates tick step $\implies$ Reject order (`INVALID_TICK_SIZE`).
- 4. **Order Execution & T7 Response Processing**: Output structured `XetraOrderExecutionReport`.
+ 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
- - **Submitting Off-Tick Prices**: Submitting an order for €50.002 on a stock requiring €0.01 tick steps, causing immediate T7 ETI rejection (`10013 Invalid Price Step`).
- - **Missing MiFID II DEA Tags**: Omitting mandatory `mifid_short_code` or `account_type` attributes, triggering regulatory compliance rejection.
- - **Conflating ETI with Market Data**: Attempting to receive L2 market data on ETI order entry sessions instead of T7 MDI (Market Data Interface) multicast.
+ - **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
- - Instantiate `DeutscheBorseXetraApiEngine`. Construct order for `DE0007100000` (Price = €62.50, Qty = 500, Account = `'P'`, DEA ShortCode = 99201). Verify engine validates tick size (€0.01 step), formats T7 ETI binary header, and approves dispatch (`STATUS_OK`). Construct order for €62.503 (off-tick). Verify engine flags `INVALID_TICK_SIZE` rejection.
+ - `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 scripts/test_deutsche_borse_xetra_api_integration.py`.
## Related Skills
- `exchange-tick-size-regime-tracking`
+ - `mifid-ii-algo-trading-compliance-eu`
- `order-to-trade-ratio-fee-penalty-avoidance`
- ---