Skip to main content

create_architect_trade_id

Function create_architect_trade_id 

Source
pub fn create_architect_trade_id(
    ts_event: UnixNanos,
    price: Price,
    quantity: Quantity,
    aggressor_side: AggressorSide,
) -> Result<TradeId>
Expand description

Creates a [TradeId] for an AX market-data trade.

AX publishes no trade identifier for market data: GET /trades and the market-data WebSocket both carry only ts, tn, s, p, q, and d, and tn is the nanosecond component of the timestamp rather than a sequence number. The composed timestamp alone is not unique either, because one aggressor sweeping several levels reports multiple prints at an identical ts and tn. Across 100 sandbox trades on 2026-07-25, GBPUSD-PERP yielded only 64 distinct timestamps.

The identity is therefore the composed timestamp plus a digest over the price, quantity, and aggressor side, which separated 99 of those 100 prints. Two prints identical in all five fields remain indistinguishable; nothing the venue publishes separates them. A sandbox run on 2026-07-25 observed exactly that, two JPYUSD-PERP prints agreeing on timestamp, price, quantity, and side, so the residual is real rather than theoretical at roughly 1 to 4 percent of prints.

That residual is accepted because a duplicate here cannot reach an execution. Live fills carry the venue’s own identifiers, fill.trade_id on REST and execution.tid on the orders WebSocket, and the backtest matching engine mints its own trade IDs with a per-timestamp counter. This function is called only from the two market-data parse_trade_tick functions, so a duplicate is a market-data fidelity limit and never an execution or position-accounting risk. Only a consumer that itself deduplicates on [TradeId] is affected; nothing in the Nautilus data path compares them.

Both transports must call this so the same trade fetched historically and received live gets one identity. The digest covers the parsed [Price] and [Quantity] rather than the wire text, because AX sends the same price as "1.339700000000" over REST and in a shorter form over the WebSocket.

Both REST and WebSocket trade models require the aggressor side, preserving identity across transports for the same print.

The result is exactly 36 characters, which is [TradeId]’s maximum, so a timestamp beyond 19 digits (year 2262) returns an error rather than silently truncating.

§Errors

Returns an error if the composed identity is not a valid [TradeId].