Order Entry API
The Trading Data Model API document describes the Order Entry API used by the Execution Server, Quote Flow, and other Deltix products. The Market Data model is described in a separate document.
Concept
The Deltix Trading API is influenced by the FIX Protocol and native APIs of various trading systems that Deltix has previously worked with. It is designed to provide a high-level normalized format suitable for interacting with 99% of trading venues.
The primary API language is Java. Currently, Deltix only provides Java and C# bindings for the API.
Order States
Deltix supports the following order states:
Status | Final | Description |
---|---|---|
UNACKNOWLEDGED | N | Order has not been submitted yet. This status is similar to OrderStatus.PendingSubmit in the QuantOffice API. |
ACKNOWLEDGED | N | The order has been acknowledged by the trading provider and is waiting to become open. (Also was known as \"ACKNOWLEDGED\"). |
OPEN | N | The order has been submitted but not yet executed. (Also was known as \"OPEN\"). |
OPEN_PARTIALLY_FILLED | N | The order has been partially filled. |
COMPLETELY_FILLED | Y | The order has been completely filled. In the case of cancel-replace chains, this status indicates that the cumulative executed quantity of the entire chain has reached the requested size. |
REJECTED | Y | The order has been rejected. |
CANCELLED | Y | The order has been cancelled. |
Please note that the status codes marked with "Y" under the "Final" column indicate that the corresponding order status is considered final, meaning it represents the end state of the order. Status codes marked with "N" are non-final statuses, indicating that the order is still in progress or can transition to another status.
The following diagram from shows possible state transitions:
Brief note on "exceptional" transitions. These are very rare but can happen in some markets:
- OPEN -> REJECTED - Unfortunately we've observed that some crypto exchanges may reject order even after it was accepted on the trading floor.
- FILLED to not filled transitions are possible when market venue issues Trade Cancellation or Trade Bust events. This kind of corrections are rare but even major exchanges like CME sometimes issue these. See section below for additional information.
Requests And Events
Messages in the system are categorized into two types based on their direction: trading Requests and trading Events. Each request generates one or more response events.
The current version of the API supports four types of trading requests:
OrderNewRequest - Places a new order on the market.
OrderCancelRequest - Cancels a previously placed order.
OrderReplaceRequest - Modifies a previously placed order.
OrderStatusRequest - Requests information about the current order status.
For users familiar with the FIX protocol, these requests correspond to the NewOrderSingle(D), OrderCancelRequest(F), OrderReplaceRequest(G), and OrderStatusRequest(H) FIX messages.
When it comes to trading events, the system currently supports the following types:
OrderPendingNewEvent - Indicates that the trading venue that has received the order, but it is not active in the market yet.
OrderNewEvent - Signifies that the order is active and working in the market of the trading venue destination.
OrderRejectEvent - Indicates that the trading venue or market rejected the order.
OrderPendingCancelEvent - Indicates that the trading venue is processing the order cancellation request.
OrderCancelEvent - Signifies that the trading venue or market rejected the order.
OrderCancelRejectEvent - Indicates that the trading venue cannot cancel the order.
OrderTradeReportEvent - Reports a trade, indicating that the order is fully or partially filled.
OrderPendingReplaceEvent - Indicates that the trading venue received a request to modify an order.
OrderReplaceEvent - Signifies that the trading venue modified an order in the market.
OrderReplaceRejectEvent - Indicates that the trading venue rejected a a request to modify an order.
OrderStatusEvent - Reports the current status of the order, including the filled amount and other relevant information.
OrderRestateEvent - Signifies that the trading venue made changes to an order parameter (e.g., triggering a stop order).
Users familiar with the FIX protocol will recognize that most of these events represent different types of Execution Report messages:
API Event | FIX Protocol |
---|---|
OrderPendingNewEvent | ExecutionReport(8) with ExecType(150)=A Pending New |
OrderNewEvent | ExecutionReport(8) with ExecType(150)=0 New |
OrderRejectEvent | ExecutionReport(8) with ExecType(150)=8 Reject |
OrderPendingCancelEvent | ExecutionReport(8) with ExecType(150)=6 Cancel |
OrderCancelEvent | ExecutionReport(8) with ExecType(150)=4 Cancel or =C Expired |
OrderCancelRejectedEvent | OrderCancelReject(9) with CxlRejResponseTo(434)=1 Cancel Request |
OrderTradeReportEvent | ExecutionReport(8) with ExecType(150)=F Trade |
OrderTradeCorrectEvent | ExecutionReport(8) with ExecType(150)=G Trade Correct |
OrderTradeCancelEvent | ExecutionReport(8) with ExecType(150)=H Trade Cancel |
OrderPendingReplaceEvent | ExecutionReport(8) with ExecType(150)=E Pending Replace |
OrderReplaceEvent | ExecutionReport(8) with ExecType(150)=5 Replace |
OrderReplaceRejectEvent | OrderCancelReject(9) with CxlRejResponseTo(434)=2 Replace Request |
OrderStatusEvent | ExecutionReport(8) with ExecType(150)=I Status |
OrderRestateEvent | ExecutionReport(8) with ExecType(150)=D Restated |
Order Status vs. Order Event Type
In alignment with the FIX Protocol, the Deltix trading model distinguishes between Order Status and Order Event Type. The following information heavily references the section of FIX Protocol Volume 4: Orders and Execution that describes FIX Execution Reports.
Order events serve the purpose of communicating the following:
- Confirming the receipt of an order.
- Confirming changes to an existing order, (i.e., accepting cancel and replace requests).
- Conveying order status information.
- Relaying fill information on working orders.
- Rejecting orders.
In each of these cases, a specialized event is used to convey what happened to the order (or the purpose of the event). Meanwhile, the attribute orderStatus
available in each event conveys the current state of the order as understood by the execution venue. In scenarios where an order exists simultaneously in multiple order states, the OrdStatus
field reports the value with the highest precedence.
The order statuses are as follows (ranked from highest to lowest precedence):
Precedence | Order Status | Description |
---|---|---|
7 | Pending Cancel | Indicates that an Order Cancel Request is pending, serving to confirm receipt of the request. Note: This does not indicate that the order has been canceled. |
6 | Pending Replace | Indicates that an Order Cancel/Replace Request is pending, serving to confirm receipt of the request. Note: This does not indicate that the order has been replaced. |
5 | Filled | Denotes that the order has been completely filled, with no remaining quantity. |
4 | Suspended | Indicates that the order has been placed in a suspended state at the client's request. |
3 | Canceled | Represents a canceled order, with or without executions. |
3 | Expired | Indicates that the order has been canceled in the broker's system due to time-in-force instructions. |
2 | Partially Filled | Signifies an outstanding order with executions and a remaining quantity. |
1 | New | Represents an outstanding order with no executions. |
1 | Rejected | Denotes that the order has been rejected by the sell-side (broker, exchange, ECN). Note: An order can be rejected after order acknowledgment, transitioning from New to Rejected status. |
1 | Pending New | Indicates that the order has been received by the sell-side's (broker, exchange, ECN) system but has not yet been accepted for execution. An execution message with this status is only sent in response to a Status Request message. |
For instance, in the case of an algorithmic order that receives a fill while pending cancellation, the OrderTradeReport Event is utilized to communicate the filled amount and price. However, the orderStatus
in this event will be set to "Pending Cancel" to reflect the pending cancellation status of the order.
Another scenario to consider is an Immediate-or-Cancel (IOC) order. In certain cases, partial fill and cancellation for IOC orders may be reported using a single OrderTradeReportEvent with the orderStatus
set to "Cancelled." This conveys that the IOC order has been canceled, even if there was a partial fill before the cancellation occurred.
Source and Destination
Each message has a source and a destination. For Requests and Events that come in response, the source and destination are usually reversed. In other words, the destination of an event corresponds to the source of the original request, and vice versa.
For trading requests, the Source field is required, while the Destination field is optional. When a destination is not specified, the system will apply custom routing rules to determine the appropriate destination for the message. However, for order cancel and order replace requests, the destination field can be skipped altogether, as the Order Management System (OMS) can infer the destination from the order itself.
In the Trading API, both the Source and the Destination are represented by an INT64 data type.
For example, the Execution Server uses ALPHANUMERIC(10) encoding to convert human-readable sources and destinations into their corresponding INT64 identifiers. Further details on this encoding process are provided in the Special Types section.
Order Destination vs. Order Exchange
- Order Exchange - Identifies an order's final destination by defining the specific trading venue where the order will be executed, such as the "CME" exchange.
- Order Destination - Identifies the immediate next step in the order routing process. In order words, this field guides the order toward its intended trading venue, for example, by identifying a specific CME trading connector configured in our system.
It's important to note the following:
- The Order Exchange field is optional. For example, this field is omitted when Ember works with single trading venue.
- The Order Destination field is also optional. However, when it is not specified, Ember's Order Router will assign an appropriate destination to the order based on its routing rules and algorithms.
For example, let's consider an order designated for the CME exchange. In this case, the order may be routed to a destination called "TWAP" (Time-Weighted Average Price) which represents a specific execution algorithm. The TWAP algorithm will then take the order and divide it into smaller chunks, sending them to the CME trading connector for execution.
In summary, while the Order Exchange field defines the final trading venue, the Order Destination field guides the order to its destination within the system's routing infrastructure.
Identity
When it comes to identifying orders and requests, the Order Entry API follows the conventions of the FIX protocol.
Order ID
Each order submitted by an API client or algorithm is associated with a unique textual identifier known as the Order ID. The uniqueness of the Order ID is scoped within a specific order source, which is identified by the Source ID. In other words, the Order ID is unique within the context of a particular order source.
When an order is modified, the client provides a new Order ID and must explicitly specify the original Order ID that is being modified. Once the modification is approved, the working order will be identified by the ID of the replacement order request. In cases where the modification (replace) request is rejected, the order retains its original identity. This approach is consistent with the handling of order modifications in the FIX protocol, which is familiar to users experienced with FIX-based trading systems.
Correlation Order ID
For the convenience of handling a large chain of cancellation and replace requests, the API supports an optional attribute called the Correlation Order ID. This attribute serves as a means of matching the ID of the first order in the replacement chain. The Correlation Order ID helps in tracking the relationship between the original order and subsequent modifications or replacements. The concept of a Correlation ID can also be found in other trading APIs like CME iLink.
Cancel Replace workflow
When an order undergoes the Cancel Replace workflow, each OrderReplaceRequest
uses a separate unique order ID and identifies which [predecessor] order request it replaces using the Original Order ID attribute. For example, if an order was replaced twice, the cancel replace chain will have three order identifiers - original order and two replacement requests.
For any Cancel Replace chain of messages, an optional attribute called Correlation Order ID identifies the very first order in the chain. This attribute can be provided by the API user, and the OMS automatically populates this attribute for downstream messages.
External Order ID
Trading Venues may assign their identifiers to orders represented as an \"external order ID\". These identifiers are unique only within the scope of each trading venue, identified by the Destination ID and Exchange.
An external order ID is typically reported with order events and may or may not change each time the order is modified using a CancelReplaceRequest
.
Request ID
To distinguish repeated attempts to cancel the same order, each CancelRequest
is identified by a Request ID. The required identifier is subsequently reported in the ACK/NACK events, such as OrderCancelEvent
and OrderCancelRejectEventcancel
.
Trade ID
Trades (fills, executions) are identified using the eventId
field. This event identifier should be unique in the scope of a single order or the order's cancel-replace chain. Deltix OMS uses this field to identify duplicate trade reports.
Message timestamps
Field | Requests | Events |
---|---|---|
timestamp | Typically indicates the moment when the request is first processed by Ember. For instance, in the FIX API gateway, this field captures the time when the request is decoded from the FIX message. | Indicates when the event was processed by the Trade Connector, i.e., when the event entered Ember. |
originalTimestamp | Usually reflects when the request was initiated by the source. For example, in the FIX API gateway, it is populated from the TransactTime(60) tag of an inbound new order request (35=D). | Represents the actual time when the event occurred on the exchange (market venue). |
When Ember algorithms create new trading requests (e.g., submitting an order to the market), they can initialize the originalTimestamp
field to match the market data signal timestamp (commonly using MarketData.receiveTime
). This facilitates tick-to-order latency monitoring.
Prior to Ember version 1.14, order requests did not include the originalTimestamp
field. In earlier versions, the Ember API gateway would set the request timestamp
to the current request arrival time, but only if the client had not already defined the field when submitting the request.
More about timestamp data format can be read later in this document.
Required and Optional Attributes
Each message in the API is composed of a set of required and optional fields. For example, in each order event field, the Order ID is a required field, while the External Order ID field is optional.
Refer to sources/javadoc to get information on each field. Typically, optional fields have additional logical methods that check whether a field is defined or not. For example, you can use the OrderEvent.hasExternalOrderId() method
. The Ember Java binding of this API uses the @Required
or @Optional
annotations when defining field getters and setters.
Field Enrichment
When a trading message passes through the Deltix OMS system on its way to a destination, it undergoes the enrichment step. The OMS attempts to define all optional attributes based on the context. For example, the OMS can define instrument type based on the order symbol. For messages that affect a previously known order, the OMS can copy the missing fields from the last known order state. That is, the OMS can derive order symbol and side (BUY or SELL) for a CancelRequest from the symbol and side specified during the order submission. Some trading venues require the order side, symbol, and other fields for each cancellation request.
Quantities
In accordance with FIX protocol, when you modify an order, you need to specify the total desired order quantity.
The following table illustrates various quantity-related attributes on requests and events. The original order quantity is 5, which is subsequently increased to 10. During this time, the order receives partial fills.
Message | Quantity | Trade Quantity | Cumulative Quantity | Remaining Quantity | Order State |
---|---|---|---|---|---|
OrderNewRequest | 5 | UNACKNOWLEDGED | |||
OrderNewEvent (ACK) | 5 | 0 | 5 | NEW | |
OrderTradeReportEvent | 5 | 2 | 2 | 3 | PARTIALLY FILLED |
OrderTradeReportEvent | 5 | 1 | 3 | 2 | PARTIALLY FILLED |
OrderReplaceRequest | 10 | PARTIALLY FILLED | |||
OrderReplaceEvent (ACK) | 10 | 3 | 7 | PARTIALLY FILLED | |
OrderTradeReportEvent | 10 | 7 | 10 | 0 | COMPLETELY FILLED |
Custom Attributes
The FIX Protocol specifies many more fields than are represented in the Deltix Trading API. While Deltix has made an effort to include the most common fields,in cases where specific fields are not available, custom attributes can be used.
Each trading message in the Deltix Trading API can contain a list of custom attributes. Each attribute is identified by a numeric key and stores a text value.
Mutable and Immutable Messages
For each message in the Trading API, there is usually an immutable interface presented to message consumers, and a mutable message interface that is available to message producers.
For example, the immutable interface for an order cancellation event is called OrderCancelEvent
, while the corresponding mutable message interface is called MutableOrderCancelEvent
. Similarly, in the TimeBase API, these messages are referred to as OrderCancelEventInfo
and OrderCancelEventInterface
.
Supported codecs
The Trading API supports multiple codecs for different purposes:
- TimeBase - Trading Messages can be stored and loaded from TimeBase.
- Binary - The Deltix Execution Server includes a set of high-performance codecs for working with in-memory buffers or communication frameworks like Aeron.
- JSON - Messages can be converted back and forth to JSON.
- FIX - The FIX Server components include codecs for working with FIX 4.4.
Special Types
Decimal
In the Java language, there is no data type for the accurate representation of money. The built-in \'double\' data type introduces rounding errors, while BigDecimal is slow and immutable, requiring frequent memory allocations.
Deltix addresses this limitation by using the Decimal64 IEEE 754 format to represent prices and sizes using the INT64 (Java \'long\') data type.
For more information about Decimal64, you can visit the following GitHub repository: https://github.com/epam/DFP.
Here are some key points to remember:
- Use the
@Decimal
annotation to mark fields, parameters, and methods that pass Decimal64 values using the INT64 data type. - Use the
com.epam.deltix.decimal.Decimal64Util
library for conversions to various data types and frequently used operations.
Here's an example of how decimal expressions may look in your code:
import com.epam.deltix.dfp.Decimal64Util.*;
@Decimal final long totalValue = add(order.getTotalExecutedValue(), multiply(event.getTradePrice(), event.getTradeQuantity()));
With a little practice, these prefix math operations are easy to follow.
Timestamp
All timestamps are stored as INT64 (Java \'long\') data type for effectiveness. The numeric value represents the number of milliseconds since midnight on January 1st, 1970 (Linux epoch time).
To indicate fields, parameters, and methods that represent timestamp values using the INT64 data type, use the @Timestamp annotation.
This timestamp format corresponds to the millisecond time used by java.util.Date
and java.util.Calendar
.
Update: since Ember 1.14 all timestamps internally switched to use nanosecond epoch time. API compatibility was preserved so you may observe both nanosecond and millisecond version of timestamp attribute getters and setters:
/**
* Message timestamp (in epoch time).
* Similar to tag TransactTime(60) in FIX ExecutionReport.
* Input value should have NANOSECOND resolution!
*/
void setTimestampNs(@Timestamp(TimeUnit.NANOSECONDS) long timestamp);
/**
* Legacy API method takes millisecond resolution Timestamp
*/
void setTimestamp(@Timestamp long timestamp);
Alphanumeric
In many cases, short textual identifiers like exchange codes or component names (used as Source or Destination IDs), can be efficiently stored in a single INT64 data type. Deltix uses ALPHANUMERIC(10) TimeBase encoding for this purpose.
ALPHANUMERIC(10) text values must not exceed 10 characters. Valid characters include upper case letters, and digits, and punctuation characters (ASCII range 0x20..0x5F).
For example, the text "COINBASE" is encoded as 0x88EFA6E8A1CE5000 and represented inside the INT64 data type as shown below:
As you can see, the lengh is stored in bits 60-63, and each character is compressed to 6 bites.
To indicate fields, parameters, methods that transmit ALPHANUMERIC-encoded text values using INT64 data type in Java, use the @Alphanumeric
Java annotation.
The following Java algorithm demonstrates this encoding process:
public static long parse(final CharSequence text) {
if (text == null)
return TypeConstants.ALPHANUMERIC_NULL;
int length = text.length();
if (length > 10)
throw new IllegalArgumentException("Text \"" + text + "\" exceeds max length of alphanumeric text");
long value = (long) length << 60L;
for (int i = 0, shift = 54; i < length; i++, shift -= 6) {
final char c = text.charAt(i);
if (c < 0x20 | c > 0x5F) {
throw new IllegalArgumentException("Text \"" + text + "\" contains non-alphanumeric char at " + i);
}
value |= (c - 0x20L) << shift;
}
return value;
}
Trade Corrections and Cancellations
Trade Corrections or Trade Cancellations are special type of events that some market places may issue to nullify previous Order Trade Report event. Both events provide Reference Trade ID of the original trade (the trade that is getting corrected and cancelled). Typically Trade Correction communicate adjusted price or quantity, however it is possible for Trade Correction to communicate correct trade quantity as zero (and hence de-facto notify of trade cancellation).
Remaining Order Quantity and Order Status are two important attributes that help to understand outcome of trade correction / cancellation for completely filled orders. When remaining order quantity is communicated as zero or when order status is communicated as CANCELLED or COMPLETELY_FILLED order remains inactive. When remaining quantity is greater than zero, or when order status is reported as NEW or PARTIALLY_FILLED order become active. This is rare exceptional order state transition from COMPLETELY_FILLED to NEW or PARTIALLY FILLED. Remaining quantity attribute if provided has precedence in this decision making.
Samples
In this section, you will find several fragments that illustrate how the Order Entry API is used.
Order Submission
The following sample demonstrates the filling of an Order New Request for submitting a new order:
MutableOrderNewRequest request = new MutableOrderNewRequest();
request.setOrderId(idGenerator.next());
request.setSide(side);
request.setQuantity(FP.fromLong(size));
request.setSymbol(symbol);
request.setLimitPrice(FP.fromDouble(price));
request.setTimeInForce(TimeInForce.DAY);
request.setOrderType(OrderType.LIMIT);
request.setDestinationId(getServiceByName("marketfactory"));
request.setExchangeId(ExchangeCodec.codeToLong("HOTSPOT"));
request.setSourceId(CLIENT_SOURCE_ID); // Identify order source
request.setTimestamp(System.currentTimeMillis());
Order Fill Event
The following sample reports a fill event:
tradeEvent.setSourceId(MARKET_FACTORY_SOURCE_ID);
tradeEvent.setSymbol(symbol);
tradeEvent.setTradeQuantity(tradeQuantity);
tradeEvent.setTradePrice(tradePrice);
tradeEvent.setDestinationId(orderEntry.getSourceId());
tradeEvent.setOrderId(orderEntry.getOrderId());
tradeEvent.setExternalOrderId(orderEntry.getExternalOrderId());
tradeEvent.setSide(orderEntry.getSide());
tradeEvent.setEventId(tradeId);
tradeEvent.setCumulativeQuantity(orderEntry.getCumulativeQuantity());
tradeEvent.setAveragePrice(orderEntry.getAveragePrice());
tradeEvent.setRemainingQuantity(orderEntry.getRemainingQuantity());
tradeEvent.setAggressorSide(AggressorIndicator.ORDER_INITIATOR_IS_AGGRESSOR);
tradeEvent.setTimestamp(clock.time());
UML Diagram
Mapping to FIX protocol
The Trading Data Model used by Deltix is heavily influenced by messages of the FIX Protocol. Deltix has selected a subset of the most used FIX tags and mapped them as "first class" attributes in the Trading Data Model. Less frequently used tags can still be specified using custom message attributes.
Standard Attributes
The table below describes the mapping of standard message attributes to FIX.
FIX Tag | Deltix API | Description |
---|---|---|
MsgType(35) | Mapped to a specific class, for example OrderNewSingle(35=D) is mapped to OrderNewRequest. | |
ClOrdId(11) | Mapped to a pair {SourceId,OrderId} | See Order Id section |
OrigClOrdId(41) | Mapped to a pair {SourceId, OriginalOrderId} | |
Account(1) | Account | |
Price(44) | LimitPrice | |
StopPx(99) | StopPrice | |
PegDifference(211) | PegDifference | Depends on trading connector |
QuoteId(117) | QuoteID | Identifies quote for previously quoted order |
MinQty(110) | MinQuantity | Depends on trading connector |
MaxFloor(111) | DisplayQuantity | Depends on trading connector |
TimeInForce(59) | TimeInForce | |
ExpireDate(432) or ExpireTime(126) | ExpireTime | |
Currency(15) | Currency | Depends on trading connector |
Side(54) | Side | |
OrderQty(38) | Quantity | Trading connectors may perform quantity translation (using size multiplier) |
OrdType(40) | OrderType | |
Clearing Account (440) | ClearingAccount | |
SenderSubID(50) | TraderId | Depends on trading connector |
ExDestination(100) | Exchange | Depends on trading connector |
Symbol(55) | Symbol | Trading connectors may perform symbol translation |
SecurityType(167) | InstrumentType | |
TransactTime(60) | Timestamp | |
ExBroker(76) | Destination | Depends on trading connector |
Text(56) | UserData | Depends on trading connector |
Commission(12) | Commission | On events only |
LastPx(31) | TradePrice | On events only |
LastShares(32) | TradeQuantity | On events only |
TradeDate(75) | TradeDate | On events only |
FutSettlDate(64) | SettlementDate | On events only |
AggressorIndicator(1057) | AggressorSide | On events only |
MultiLegReportingType(442) | MultiLegReportingType | On events only |
OrdStatus(39) | OrderStatus | On events only |
ExecType(150) and ExecTransType(20) | Mapped to event type (e.g. OrderTradeReportedEvent is 150=F) | On events only |
ExecId(17) | EventId | On events only |
CumQty(14) | CumulativeQuantity | On events only |
AvgPx(6) | AveragePrice | On events only |
LeavesQty(151) | RemainingQuantity | On events only |
TransactTime(60) | OriginalTimestamp | On events only |
Custom Attributes
The following code example demonstrates use of custom order attributes.
import deltix.ember.util.CustomAttributeListBuilder;
private static void addCustomAttributes(MutableOrderNewRequest request) {
attributeListBuilder.clear();
// Repeated group
attributeListBuilder\
.addInteger(Tag.NoPartyIDs, 2)
.addText(Tag.PartyID, "AAA\")
.addInteger(Tag.PartyRole, PartyRole.CLIENT_ID)
.addText(Tag.PartyID, "BBB")
.addInteger(Tag.PartyRole, PartyRole.AGENT);
attributeListBuilder
.addTimestamp(7050, System.currentTimeMillis() + 1000);
request.setAttributes(attributeListBuilder.build());
}
Multi-legged Contracts
The data model supports multi-legged securities (e.g., Calendar spreads on the CME exchange).
When submitting a trade request for a multi-legged security, you can use the multi-legged security symbol, such as "ZFH20-ZFM20" for a calendar spread on US Treasury Bond Future contracts. Optionally, you can supply the instrument type "MLEG" (MULTI_LEG_INSTRUMENT) with each request.
When processing fills for multi-legged orders, you need to pay attention to the MultiLegReportingType and Symbol attributes of events.
Here is an example of a fill event for an individual leg:
OrderTradeReport.setMultiLegReportingType(INDIVIDUAL_LEG_SECURITY);
OrderTradeReport.setSymbol("ZFH20") <-- identifies *leg* instrument
Here is an example of fill event for a multi-legged contract:
OrderTradeReport.setMultiLegReportingType(MULTI_LEG_SECURITY);
OrderTradeReport.setSymbol("ZFH20-ZFM20") <-- identifies *spread* instrument
When implementing a custom trade connector that reports trades for multileg instrument you need to issue a series of trade report events. There must be trade reported for synthetic instrument itself (tagged with MultiLegReportingType.MULTI_LEG_SECURITY
) and a trade event for each leg of the synthetic instrument (tagged with MultiLegReportingType.INDIVIDUAL_LEG_SECURITY
and event symbol identifying the leg). Trade quantity and side reported for each individual leg must follow synthetic composition formula. This behavior follows API of exchanges like CME and ICE.