Elektron SDK - Java

API Family: Elektron

EMA Consumer - Requesting and displaying MarketPrice data

Download tutorial source code

Click here to download

Last update May 2018
Environment Windows, Linux
Compilers JDK 1.7 or greater
Prerequisite Creating a barebones EMA consumer application

Introduction

The goal of this tutorial is to introduce EMA's Consumer interface which provides the ability to request MarketPrice data and receive responses from a connected market data system. By utilizing the OmmConsumerClient callback interface defined within Tutorial 1, we demonstrate how to receive these realtime, asynchronous responses. For simplicity, this tutorial will only display the raw messages to the terminal window.

Description

The EMA Consumer (OmmConsumer) represents the main communication link between this application (Consumer) and the market data system (Provider). The OmmConsumer is primarily responsible for managing the connection into the Provider, establishing a session which involves logging in, requesting dictionaries and retrieving the source directory of services available from the Provider. In addition, supports the ability to request and receive realtime market data.

The following concepts will be outlined:

Consumer creation and Configuration

Within this tutorial, we have introduced a new method within our shell application that will be responsible for managing all aspects of communication to the Provider. The run method below defines the EMA Consumer interface that establishes communication, requests for data and dispatches data events to our callbacks. To initiate communication, the code snippet below has been defined:

public class basicConsumer implements OmmConsumerClient
{
    // Define our consumer communication channel to our Provider managing connection and item registration
    OmmConsumer consumer = null; 

    ...
	
    // run
    // Connect to our provider, request for data and run the application for a short time to capture the 
    // realtime data.
    private void run()
    {
        try
        {
            // The consumer configuration class allows the customization of the consumer (OmmConsumer) 
            // interface, i.e. name of the server or IP, port, connection type, login username, etc.
            OmmConsumerConfig config = EmaFactory.createOmmConsumerConfig();
			
            // Create an instance of our consumer in preparation for communication.
            // When instructing the consumer to communicate with a provider, we provide the following 
            // connection details.  The connection details are set within our configuration (OmmConsumerConfig).
            //
            // Note:    After creating our consumer, by default, EMA will launch a background thread to manage 
            //          communication and message dispatching.  Within EMA, this is controlled by the 
            //          OperationModel available within the OmmConsumerConfig interface.  Refer to the 
            //          documentation for more details.
            //
            //          For example, EMA sets the following model by default:
            //             config.operationModel(OmmConsumerConfig.OperationModel.API_DISPATCH);
            consumer = EmaFactory.createOmmConsumer(
                  config.host("elektron:14002")
                        .username("user")
            );
			
            ...
        } 
        ...
    }
	
    ...
}

When creating an instance of the OmmConsumer interface, you must supply an OmmConsumerConfig specification defining the required configuration details necessary to establish basic communication to the Provider. In the above segment, our configuration specifies we are connecting to the Provider on the host elektron:14002 using the login ID of user. You may likely need to change the above when you build and run to test in your environment.

Note: For simplicity, these tutorials will hard-code the configuration entries necessary to connect and request data. EMA supports multiple mechansims to configure your applications if you wish to explore at a later date.

Requesting for data

Once we have defined our Consumer channel, we can register interest in the data we want to watch. Referring to the following code segment, the registerClient method is responsible for registering interest in an item. This method takes 2 parameters. The first parameter represents the details of the item request and the second defines the OmmConsumerClient interface to handle events generated by our interest. In our implementation, the basicConsumer class represents the interface or eventHandler where callbacks are captured.

	public class basicConsumer implements OmmConsumerClient	
{
    ...
	
    // run
    // Connect to our provider, request for data and run the application for a short time to capture the 
    // realtime data.
    private void run()
    {
        try
        {
            ...
			
            // Define what data we want and register it with our consumer
            //  
            // When registering, we also need to specify where we want to capture all the events generated by 
            // this request.  
            OmmConsumerClient eventHandler = this;

            consumer.registerClient(
                  EmaFactory.createReqMsg()
                                .serviceName("ELEKTRON_AD")
                                .name("IBM.N"), 
                  eventHandler
            );		

            ...
        } 
        ...
    }
}

When registering interest in an item, you have the choice to request for a snapshot or streaming response. In both cases, you will receive an initial image which contains the complete list of fields for that item. However, the streaming request or subscription-based request, may result in realtime updates based on changes in the market. The decision is determined by a method on the request. By default, the request will be streaming.  In addition, you can also optionally specify what domain the item you are interested in.  By default, the request selects the MarketPrice domain.

In the above example, we are requesting for MarketPrice data based on the item name IBM.N within the service ELEKTRON_AD. You will likely need to change the above when you build and run to test in your environment.

Note: EMA is an event-driven, asynchronous environment where success and failure is determined by realtime events.  Specifically, EMA will monitor these events on behalf of the developer and manage interaction appropriately.  For example, the code segment outlined above initiates a connection request then immediately requests for data without waiting for the result of the connection.  Behind the scenes, EMA is managing the status of the connection and will only submit interest in data once it establishes successful communication.  EMA will maintain knowledge about the activity you are interested in and will continually manage it on your behalf. EMA is an intelligent API that was designed with simplicity and ease of use to manage communication in this way.

Event Dispatch

As outlined above, the OmmConsumer interface utilizes the OmmConsumerConfig interface to capture configuration details such as your connection and login details. Although not defined, the interface also allows the specification of an Operation Model, via the operationModel. The Operation Model determines what thread to dispatch events to your client callback. Specifically, the model chooses whether to capture your callback events within a user thread, or within an Api thread. In our case, we are using the default Operation Model which dispatches events in an Api thread. 

Note: Refer to tutorial 5 within the download package for an example of dispatching using a User thread.

Operation Model

User

The user model specification utilizes your application thread of execution to dispatch messages. The application thread is commonly your main thread of execution. When using this model, you must explicitly call the OmmConsumer.dispatch() method to capture messages within your client callback.

Api

The Api model specification utilizes an internally EMA-managed thread that will automatically dispatch events during the life of the OmmConsumer instance. Once the instance uninitializes, the thread will automatically stop dispatching events. Note: Be aware when using this model, your application is multi-threaded. Ensure you take appropriate actions to protect your application resources against concurrent access.

These tutorials utilize the default Operation Model Api which is why we need to temporarily sleep within the main thread to capture our messages.

private void run()
{
    try
    {
        ...

        // Because we are using the default operation model: API_DISPATCH where EMA manages the dispatching of
        // events within a background thread, we must block and wait on our application thread for a short 
        // period to capture our market data events.
        Thread.sleep(30000);
    }
}		

Callback implementation - message display

As outlined in the previous tutorial, the OmmConsumerClient interface defines a number of mandatory callbacks to capture the different events generated when you register interest in an item. The following code snippet outlines the callbacks this tutorial is using to capture the different events generated by our item registration:

public class basicConsumer implements OmmConsumerClient
{
    ... 
	
    //*************************************************************************************************
    // Callback methods required by the OmmConsumerClient Interface.
    //
    // The following methods allow us to capture realtime events such as status and data events.
    //*************************************************************************************************
	
    // onRefreshMsg
    // Capture the initial image after subscribing (registering interest) in a market data item.  This 
    // callback utlizes the convenient print method to display output.
    public void onRefreshMsg(RefreshMsg refreshMsg, OmmConsumerEvent event)
    {
        System.out.println(refreshMsg);
    }
	
    // onUpdateMsg
    // After receiving the initial image, we capture any updates to the item based on market events.
    // This callback utlizes the convenient print method to display output.
    public void onUpdateMsg(UpdateMsg updateMsg, OmmConsumerEvent event)
    {
        System.out.println(updateMsg);
    }
	
    // onStatusMsg
    // General status messages related to your consumer item registration.  For example, you will receive a 
    // status message if you register interest in an invalid item.  This callback utlizes the convenient 
    // print method to display output.	
    public void onStatusMsg(StatusMsg statusMsg, OmmConsumerEvent event)
    {
        System.out.println(statusMsg);
    }
	
    ...
}

The above 3 methods outline different events we would expect when we request interest in an item. As outlined in the Requesting for Data section, when we perform a streaming request, we will receive an initial image followed by updates. The onRefreshMsg callback is responsible for capturing the initial image. The onUpdateMsg callback is responsible for capturing any updates that may follow due to changes in market conditions. The third callback onStatusMsg will report general status or issues based on your request. For example, if you request for an invalid item, you will be notified within this method.

Each callback will simply output the message received to the terminal window. This is more of a convenience or testing capability to demonstrate we can see data and what is inside. The next tutorial will extend this functionality by processing and decoding the details of the responses which will allow applications to capture specific details of the responses.

Build and run

Refer to the Build and run section within the Tutorial 1 - Creating a barebones EMA consumer application for instructions to successfully execute this tutorial.  

Before building and executing this tutorial, ensure you have properly configured the connection details as well as the item request values for your environment.  Contact your market data administrator to acquire these details.

Eg (Windows):

> buildConsumer 2

Building tutorial 2...

Done.

> runConsumer 2

Running the tutorial will report back some general startup details followed by the data we requested.  As outlined when we executed the Quick Start application, we are presented with our initial image RefreshMsg followed by zero or more updates (UpdateMsg).  In both cases, the output dumps a collection of entries which represents the market data fields for the update.  For example, the following output:

FieldEntry fid="22" name="BID" dataType="Real" value="155.45"

defines a FieldEntry which represents a record of information related to a specific field within the update. The fid and name attributes represent the field ID and corresponding name of the field respectively. In addition, we also see the type and value of the data received. The next tutorial will provide additional details of the structure of the response messages and how to parse and decode.

Note: This tutorial will automatically exit after ~30 seconds.  Alternatively, you can (Ctrl+C) to exit at any time.

Running tutorial 2...
Jul 11, 2016 3:38:45 PM com.thomsonreuters.ema.access.ConfigErrorTracker log
INFO: loggerMsg
    ClientName: EmaConfig
    Severity: Info
    Text:    reading configuration file [EmaConfig.xml] from [c:\emaj-tutorials]
loggerMsgEnd


Jul 11, 2016 3:38:45 PM com.thomsonreuters.ema.access.ConfigErrorTracker log
SEVERE: loggerMsg
    ClientName: EmaConfig
    Severity: Error
    Text:    Cannot locate configuration source EmaConfig.xml
loggerMsgEnd


Jul 11, 2016 3:38:45 PM com.thomsonreuters.ema.access.ChannelCallbackClient reactorChannelEventCallback
INFO: loggerMsg
    ClientName: ChannelCallbackClient
    Severity: Info
    Text:    Received ChannelUp event on channel null
        Consumer Name EmaConsumer_1
loggerMsgEnd


RefreshMsg
    streamId="5"
    domain="MarketPrice Domain"
    solicited
    RefreshComplete
    state="Open / Ok / None / 'All is well'"
    itemGroup="00 05"
    permissionData="03 01 64 62 c0"
    name="IBM.N"
    nameType="1"
    serviceId="356"
    serviceName="ELEKTRON_AD"
    Payload dataType="FieldList"
        FieldList FieldListNum="79" DictionaryId="1"
            FieldEntry fid="1" name="PROD_PERM" dataType="UInt" value="62"
            FieldEntry fid="2" name="RDNDISPLAY" dataType="UInt" value="64"
            FieldEntry fid="3" name="DSPLY_NAME" dataType="Rmtes" value="INTL BUS MACHINE"
            FieldEntry fid="4" name="RDN_EXCHID" dataType="Enum" value="2"
            FieldEntry fid="6" name="TRDPRC_1" dataType="Real" value="155.47"
            FieldEntry fid="7" name="TRDPRC_2" dataType="Real" value="155.47"
            FieldEntry fid="8" name="TRDPRC_3" dataType="Real" value="155.48"
            FieldEntry fid="9" name="TRDPRC_4" dataType="Real" value="155.48"
            FieldEntry fid="10" name="TRDPRC_5" dataType="Real" value="155.46"
            FieldEntry fid="11" name="NETCHNG_1" dataType="Real" value="1.01"
            FieldEntry fid="12" name="HIGH_1" dataType="Real" value="156.01"
            FieldEntry fid="13" name="LOW_1" dataType="Real" value="154.6"
            FieldEntry fid="14" name="PRCTCK_1" dataType="Enum" value="2"
            FieldEntry fid="15" name="CURRENCY" dataType="Enum" value="840"
            FieldEntry fid="16" name="TRADE_DATE" dataType="Date" value="11 JUL 2016 "
            FieldEntry fid="18" name="TRDTIM_1" dataType="Time" value="19:38:00:000:000:000"
            FieldEntry fid="19" name="OPEN_PRC" dataType="Real" value="154.6"
            FieldEntry fid="21" name="HST_CLOSE" dataType="Real" value="154.46"
            FieldEntry fid="22" name="BID" dataType="Real" value="155.45"
            FieldEntry fid="23" name="BID_1" dataType="Real" value="155.45"
            FieldEntry fid="24" name="BID_2" dataType="Real" value="155.45"
            FieldEntry fid="25" name="ASK" dataType="Real" value="155.46"
            FieldEntry fid="26" name="ASK_1" dataType="Real" value="155.46"
            FieldEntry fid="27" name="ASK_2" dataType="Real" value="155.46"
            FieldEntry fid="28" name="NEWS" dataType="Rmtes" value="YYYY"
            FieldEntry fid="29" name="NEWS_TIME" dataType="Time" value="17:36:10:000:000:000"
            FieldEntry fid="30" name="BIDSIZE" dataType="Real" value="3.0"
            FieldEntry fid="31" name="ASKSIZE" dataType="Real" value="2.0"
            FieldEntry fid="32" name="ACVOL_1" dataType="Real" value="609871.0"
            FieldEntry fid="34" name="EARNINGS" dataType="Real" value="13.2768"
            FieldEntry fid="35" name="YIELD" dataType="Real" value="3.6255"
            FieldEntry fid="36" name="PERATIO" dataType="Real" value="11.6338"
            ...
            FieldEntry fid="32582" name="ODDTRN_UNS" dataType="Real" value="1.061942317E7"
            FieldEntry fid="32741" name="TRNOVR_UNS" dataType="Real" value="9.4730049421E7"
            FieldEntry fid="32743" name="ACVOL_UNS" dataType="UInt" value="609871"
        FieldListEnd
    PayloadEnd
RefreshMsgEnd

UpdateMsg
    streamId="5"
    domain="MarketPrice Domain"
    updateTypeNum="1"
    name="IBM.N"
    serviceId="356"
    serviceName="ELEKTRON_AD"
    Payload dataType="FieldList"
        FieldList
            FieldEntry fid="22" name="BID" dataType="Real" value="155.45"
            FieldEntry fid="25" name="ASK" dataType="Real" value="155.46"
            FieldEntry fid="30" name="BIDSIZE" dataType="Real" value="2.0"
            FieldEntry fid="31" name="ASKSIZE" dataType="Real" value="2.0"
            FieldEntry fid="6579" name="BID_COND_N" dataType="Rmtes" value="R"
            FieldEntry fid="6580" name="ASK_COND_N" dataType="Rmtes" value="R"
            FieldEntry fid="6516" name="BOOK_STATE" dataType="Enum" value="1"
            FieldEntry fid="1000" name="GV1_TEXT" dataType="Rmtes" value=" "
            FieldEntry fid="8937" name="LIMIT_INDQ" dataType="Enum" value="0"
            FieldEntry fid="118" name="PRC_QL_CD" dataType="Enum" value="60"
            FieldEntry fid="3264" name="PRC_QL3" dataType="Enum" value="60"
            FieldEntry fid="8406" name="QTE_ORIGIN" dataType="Rmtes" value=" "
            FieldEntry fid="1041" name="GV1_FLAG" dataType="Rmtes" value=" "
            FieldEntry fid="8935" name="RETAIL_INT" dataType="Enum" value="4"
            FieldEntry fid="3887" name="SEQNUM_QT" dataType="Real" value="2.1929983E7"
            FieldEntry fid="6513" name="SETL_TYPE" dataType="Enum" value="5"
            FieldEntry fid="1501" name="STOCK_TYPE" dataType="Rmtes" value="C"
            FieldEntry fid="12784" name="TEST_MSG" dataType="Enum" value="1"
            FieldEntry fid="12783" name="NBBO_IND" dataType="Enum" value="2"
            FieldEntry fid="3855" name="QUOTIM_MS" dataType="UInt" value="70729612"
            FieldEntry fid="1025" name="QUOTIM" dataType="Time" value="19:38:49:000:000:000"
            FieldEntry fid="14238" name="ORDRECV_MS" dataType="Time" value="19:38:49:611:000:000"
        FieldListEnd
    PayloadEnd
UpdateMsgEnd

UpdateMsg
    streamId="5"
    domain="MarketPrice Domain"
    updateTypeNum="1"
    name="IBM.N"
    serviceId="356"
    serviceName="ELEKTRON_AD"
    Payload dataType="FieldList"
        FieldList
            FieldEntry fid="22" name="BID" dataType="Real" value="155.44"
            FieldEntry fid="25" name="ASK" dataType="Real" value="155.46"
            FieldEntry fid="30" name="BIDSIZE" dataType="Real" value="1.0"
            FieldEntry fid="31" name="ASKSIZE" dataType="Real" value="2.0"
            FieldEntry fid="6579" name="BID_COND_N" dataType="Rmtes" value="R"
            FieldEntry fid="6580" name="ASK_COND_N" dataType="Rmtes" value="R"
            FieldEntry fid="6516" name="BOOK_STATE" dataType="Enum" value="1"
            FieldEntry fid="1000" name="GV1_TEXT" dataType="Rmtes" value=" "
            FieldEntry fid="8937" name="LIMIT_INDQ" dataType="Enum" value="0"
            FieldEntry fid="118" name="PRC_QL_CD" dataType="Enum" value="60"
            FieldEntry fid="3264" name="PRC_QL3" dataType="Enum" value="60"
            FieldEntry fid="8406" name="QTE_ORIGIN" dataType="Rmtes" value=" "
            FieldEntry fid="1041" name="GV1_FLAG" dataType="Rmtes" value=" "
            FieldEntry fid="8935" name="RETAIL_INT" dataType="Enum" value="4"
            FieldEntry fid="3887" name="SEQNUM_QT" dataType="Real" value="2.1930075E7"
            FieldEntry fid="6513" name="SETL_TYPE" dataType="Enum" value="5"
            FieldEntry fid="1501" name="STOCK_TYPE" dataType="Rmtes" value="C"
            FieldEntry fid="12784" name="TEST_MSG" dataType="Enum" value="1"
            FieldEntry fid="12783" name="NBBO_IND" dataType="Enum" value="1"
            FieldEntry fid="3855" name="QUOTIM_MS" dataType="UInt" value="70729758"
            FieldEntry fid="1025" name="QUOTIM" dataType="Time" value="19:38:49:000:000:000"
            FieldEntry fid="14238" name="ORDRECV_MS" dataType="Time" value="19:38:49:758:000:000"
        FieldListEnd
    PayloadEnd
UpdateMsgEnd

Reference

To learn more about EMA please refer to the

Tutorial Group: 
EMA Consumer