OnixS C++ Eurex T7 Market and Reference Data (EMDI, MDI, RDI, EOBI) Handlers 20.0.1
Users' manual and API documentation
Loading...
Searching...
No Matches
Getting Started

Eurex T7 Market and Reference Data (RDI, MDI, EMDI, and EOBI) Handlers C++ library contains handlers that provide access to corresponding Eurex T7 interfaces:

  • RdiHandler for reference data. This interface provides reference data for products and instruments that are available for trading on the T7 Exchange's T7. The reference data is delivered on a product and instrument level. Every tradable object is referenced by a unique identifier, for this reason, the reference data information is essential for any trading application.
  • EmdiHandler for un-netted market data. The updates of the order book are delivered for all order book changes up to a given level; all on-exchange trades are reported individually.
  • MdiHandler for netted market data. The updates of the order book are sent at regular intervals; they are not provided for every order book change and are sent significantly less frequently than the T7 EMDI. On-exchange trades are not reported individually, however statistical information (daily high/low price, last trade price, and quantity) is provided instead.
  • EobiHandler for market data by orders. This interface provides the entire visible order book, by publishing information on each order and quote along with state information in an un-netted manner. All on-exchange trades are reported individually.
  • EmdsHandler for extended market data (Eurex Trade Prices, Settlement Prices, and Open Interest Data)

Most handler classes are placed into the OnixS::Eurex::MarketData namespace. EOBI handler classes are placed into the nested OnixS::Eurex::MarketData::EOBI namespace. Header files are collected in the master OnixS/Eurex/MarketData.h header file.

The typical way of using a handler is as follows:

  • Create an instance handler's settings.
  • Create an instance of the Handler class using a previously initialized instance of settings.
  • Register listener for errors and warnings to be notified about failures that occurred while the Handler processes market data.
  • Register listeners for different events.
  • Bind a FeedEngine instance.
  • Start market data processing by invoking the handlers' start method.
  • Process data of the events for which listeners were previously registered.
  • Stop market data processing using the handler's stop method.

Starting with Reference Data

Start RdiHandler before starting market data handlers. According to the T7 Market and Reference Data Interfaces Manual, T7 RDI publishes the technical configuration for market data access, including multicast address and port information for the available products and market data interfaces. It also delivers product and instrument reference data, including market segment and partition information required to select the proper market data channels and filters.

The Handler API uses this reference data as the source for interface descriptors. RdiHandler implements IInterfaceDescriptorProvider and exposes findEmdiDescriptors, findMdiDescriptors and findEobiDescriptors methods. Handler managers use the same contract: their start methods accept a pointer to an IInterfaceDescriptorProvider, a set of product names and a FeedEngine. Therefore the usual startup sequence is to start the RDI handler, wait until the reference data snapshot has been received, and only then start EMDI, MDI or EOBI processing for the required products.

RdiHandler must process the complete reference data snapshot cycle before descriptors for all products are available. After the full snapshot has been processed, the handler keeps the reference data in memory and can continue serving descriptor requests through IInterfaceDescriptorProvider. If the application does not need to process further live reference data updates, the RDI handler can be stopped after the snapshot has been cached.

Starting market data processing without current RDI data leaves the application without the up-to-date mapping between product names, market segment identifiers, partition identifiers and multicast channels. As a result, the application cannot reliably choose which feeds to join or which filters to apply for the products it wants to process.

Configuring and Constructing the Handler

All Handler' constructors accept an instance of the corresponding handler's settings class which defines values of various parameters for determination the Handler's behavior. The role of the most important parameters used in regular cases is described below.

Logging

By default, all the important aspects of the Handler's activity are logged. Therefore the handler must know where this kind of information can be stored on a local file system. HandlerSettings::logDirectory parameter needs to be defined for pointing the handlers place where log files to be stored.

Licensing

The handler can not be run without a license file. When the instance fails to find a valid license, it throws an exception at the initialization stage.

HandlerSettings::licenseString can be used to provide license data directly as a string. If HandlerSettings::licenseString is empty, the handler uses HandlerSettings::licenseDirectory as a path to directory containing license file(s).

Note
When there is more than one license file in the license directory the most significant one is chosen (for example, a production instead of a trial if both are available).

RDI Interface Descriptor

RdiHandlerSettings::interfaceDescriptor defines how the RDI handler connects to the T7 Reference Data Interface itself. This is the initial connectivity configuration required before the handler can receive reference data and build market data interface descriptors for EMDI, MDI and EOBI.

The descriptor contains separate endpoints for the RDI snapshot and incremental feeds. Each feed can contain Service A and Service B endpoints, depending on the network configuration used by the application. Use multicast addresses and ports from the current Eurex network configuration for the target environment.

Binding Feed Engine to the Handler

The network layer is responsible for receiving market data transmitted by Eurex data interfaces is encapsulated into a FeedEngine class. Therefore, to have successful market data processing, it's necessary to construct an instance of the Feed Engine and bind it to the previously constructed instance of a handler class.

The package provides two concrete feed engine types. SocketFeedEngine uses the standard socket API and is the default choice for regular live network processing. EfViFeedEngine uses the Solarflare ef_vi API for ultra-low-latency processing on supported systems.

A feed engine is driven by a FeedEngineThreadPool, which is created and gets the engine instance. Thread pool configuration is covered in Setting Up Feed Engine.

Listeners

Handlers deliver reference data, market data and service events through listener interfaces registered by the application. At minimum, applications should register ErrorListener and WarningListener instances to be notified about runtime failures and non-fatal conditions. Data-specific listeners are then registered for the events required by the application, for example ReferenceDataListener for RDI messages, DepthListener for price-level market data, OrderBookListener for order book updates, and TradeListener for trade events.

Listener registration is part of handler configuration. Public handler and handler manager APIs allow listeners to be changed only while the handler is disconnected; attempting to change listeners after the handler has started results in OperationException. Register all required listeners before calling start, and keep listener objects alive for as long as the handler or handler manager can call them.

Listener callbacks are invoked from the processing path, so callback implementations should avoid slow operations. Applications usually copy or aggregate the received data in the callback and defer expensive processing to another thread.

Example

The following example demonstrates how to set up initial settings for RdiHandler:

SocketFeedEngine feedEngine;
FeedEngineThreadPool fePool(settings, &feedEngine);
RdiHandlerSettings rdiSettings;
rdiSettings.logLevel = LogLevel::Debug;
rdiSettings.logDirectory = "logs";
rdiSettings.licenseDirectory = "../../license";
// Replace with addresses from the Eurex Network Configuration Guide to prevent copy-paste errors.
rdiSettings.interfaceDescriptor.snapshotFeed.serviceA.address = "224.0.0.1";
MyListener myListener;
RdiHandler rdiHandler(rdiSettings);
rdiHandler.bindFeedEngine(feedEngine);
rdiHandler.registerErrorListener(&myListener);
rdiHandler.registerWarningListener(&myListener);
rdiHandler.registerReferenceDataListener(&myListener);
rdiHandler.start();
myListener.waitUntilReferenceDataReceived();
// Stop the RDI handler once the snapshot cycle is complete, if live reference data updates are not needed
rdiHandler.stop();
Note
For more and up-to-date information on getting started aspects, see GettingStarted sample from the samples collection available in distributive package or see Getting Started Sample.

Handler Manager

Handler Manager automates market data handler creation for applications that subscribe to a set of products. Instead of manually creating handlers for every required interface and partition, the application passes a pointer to an IInterfaceDescriptorProvider, a list of required products and a FeedEngine to the manager's start method. The manager uses the reference data descriptors provided by RdiHandler to determine which market data channels are needed for the requested products and creates the necessary handler instances internally.

This is the recommended approach when the application subscribes by product names. It keeps the startup code independent from the current mapping between products, market segment identifiers, partitions and multicast channels.

Using a handler manager makes sense for a relatively small number of products. All handlers created by the manager use the same FeedEngine instance and, consequently, the same feed engine thread pool. For large product sets or workloads that require independent threading and resource allocation, create and configure handlers explicitly.

At any given moment, only one feed engine thread works with a particular handler instance. However, the listener objects registered on the manager are shared by all handler instances created by that manager. Listener implementations must therefore be prepared to receive callbacks from different handler instances and should protect any shared state they update.

The package contains the following managers:

Example

Following example demonstrates how to use EmdiHandlerManager:

//create instance of EMDI handler manager
EmdiHandlerSettings emdiSettings;
emdiSettings.logLevel = LogLevel::Debug;
emdiSettings.logDirectory = "logs";
emdiSettings.licenseDirectory = "../../license";
EmdiHandlerManager manager(emdiSettings);
//register user's callbacks
manager.registerErrorListener(&myListener);
manager.registerWarningListener(&myListener);
manager.registerDepthListener(&myListener);
manager.registerTopOfBookImpliedListener(&myListener);
manager.registerProductStateChangeListener(&myListener);
manager.registerMassInstrumentStateChangeListener(&myListener);
manager.registerInstrumentStateChangeListener(&myListener);
manager.registerQuoteRequestListener(&myListener);
manager.registerCrossRequestListener(&myListener);
manager.registerComplexInstrumentUpdateListener(&myListener);
manager.registerFlexibleInstrumentUpdateListener(&myListener);
manager.registerTradeListener(&myListener);
manager.registerOrderBookListener(&myListener);
//specify the list of products market data to receive for
MarketSegments productNames;
productNames.insert("FDAX");
productNames.insert("FGBL");
productNames.insert("FGBM");
//start manager
manager.start(&rdiHandler, productNames, feedEngine);
//....
manager.stop();
rdiHandler.stop();

More Topics