Elektron SDK - C/C++

API Family: Elektron

ETA Consumer - Retrieving and decoding level 2 content

Download tutorial source code

Click here to download

Last update May 2018
Compilers Refer to the ETA Compiler Guides for a complete list.
Prerequisites ETA Consumer - Retrieving and decoding level 1 content

Introduction

Extending from Tutorial 4, this tutorial will support additional RDM (Reuters Data Models) types such as the SymbolList as well as the level 2 content - MBP (Market By Price) and MBO (Market By Order) models.

Description

In this tutorial, we extend the functionality defined within the "basicMsgHandler.c" to include additional message structure parsing algorithms to manage the new models of data we retrieve from the OMM-based data Provider.

Implementation Overview - Requesting and parsing additional RDM message

In tutorial 4, we put in place the basic framework to request, process and decode level 1 Market Price data. Within this framework, a generic request routine sendItemRequest was designed to not only allow for level 1 requests, but for multiple message model types. In addition, the framework to parse multiple message types was also established to identify message structure as opposed to message model types. In the case of SymbolList and the level 2 data, they all utilize the same message structure thus allowing for a single processing algorithm to parse multiple message types.

As in the case of Tutorial 4, we can issue our request for new models of data upon a Channel Ready event as defined in the following:

/* Name of our market data service, item and domain of our subscription */
#define SERVICE   "ELEKTRON_AD"
char itemName[] = "BB.TO";
RsslUInt8 domainType = RSSL_DMT_MARKET_BY_PRICE;

...

RsslReactorCallbackRet channelEventCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslReactorChannelEvent *pConnEvent)
{
    switch (pConnEvent->channelEventType)
    {
        ...

        case RSSL_RC_CET_CHANNEL_READY:
            printf("Channel is ready.  Subscribing to %s\n", itemName);
            sendItemRequest(pReactor, pReactorChannel, itemName, service.serviceId, domainType);
            break;

        ...
    }
}

In the above code segment, the domainType was changed to an alternate message model. In our example, we chose Market By Price, but could also have been set to Market By Order or SymbolList - so long as the specified item supports that model.  Refer to your Market Data team to determine supported data models for your environment.

The above request will result in a MBP (Market By Price) response that will contain a Map as the core of its message structure. Each element within the Map will contain a List. In some cases, the messages will contain a SUMMARY section at the beginning of the message. The SUMMARY is a nested List structure. Because we have already defined a List structure for our level 1 (Market Price) message in Tutorial 4, the Map can piggyback off of the List processing to handle its nested structures.

To recognize the new structure of data, we extend the functionality within the processRDMResponse function defined within the "basicMsgHandler.c" file:

RsslRet processRDMResponse(RsslReactorChannel *pReactorChannel, RsslMsg *msg, RsslDecodeIterator* dIter)
{
    RsslRet ret = RSSL_RET_SUCCESS;

    ...

    switch (msg->msgBase.msgClass)
    {
        case RSSL_MC_REFRESH:

		    ...

        case RSSL_MC_UPDATE:
            printf("Domain: %s\n", rsslDomainTypeToString(msg->msgBase.domainType));

            switch (msg->msgBase.containerType)
            {
                case RSSL_DT_FIELD_LIST:
                    ret = decodeFieldList(getDictionary(), dIter);
                    break;

                case RSSL_DT_MAP:
                    ret = decodeMap(getDictionary(), msg->msgBase.domainType, dIter);
                    break;

                default:
                    printf("ContainType: %i not handled\n", msg->msgBase.containerType);
            }

            break;

            ...
    }

    return(ret);
}

The decodeMap routine processes map elements and utilizes our existing List processing to handle nested list structures. While the processing details are important, it is beyond the scope of this tutorial.

Build and run

For these instructions, refer to the Build and Run section within the first tutorial of this series.

Note: Ensure you can connect into a valid Elektron or TREP environment to test. Defined within the basicConsumer.c file, these tutorials assume the following server has been defined:

/* Server/Provider connection details */
#define TREP_SERVER_NAME	"elektron"
#define TREP_SERVER_PORT	"14002"

...

You can either define the service name 'elektron' within your environment to point to a valid market data server or simply modify these server configuration paramters to suit your setup. In our execution, we are downloading the dictionaries from the OMM-based Provider.  After specifying the appropriate item and message model (domainType - Market By Price), we subscribe to the OMM-based Provider. The streaming response will first contain the initial image (REFRESH) followed by update events, based on change. It is worth noting that very large structures are normally broken down into multiple messages. This is especially common for both MBP and MBO models.

Received activity on channel: 432
Item: BB.TO
State: Open/Ok/None - text: "All is well"
Domain: RSSL_DMT_MARKET_BY_PRICE
SUMMARY DATA
PROD_PERM           3044
DSPLY_NAME          BLACKBERRY LTD
CURRENCY            CAD(124)
ACTIV_DATE          27 FEB 2015
PRC_QL2             
LOT_SIZE_A          100
RECORDTYPE          113
PREF_DISP           
RDN_EXCHD2          TOR(10)
LIST_MKT            TOR
PROV_SYMB           BB
PR_RNK_RUL          NOR(1)
OR_RNK_RUL          PTS (2)
MNEMONIC            BB
MKT_STATUS          F
TIMACT_MS           79200002
CONTEXT_ID          2171
DDS_DSO_ID          8244
SPS_SP_RIC          .[SPSTL2TRL2
BOOK_STATE          N(1)
HALT_REASN          
ORD_ENT_ST          I(2)
MKT_OR_RUL           (0)
TRD_STATUS          N (1)
HALT_RSN            

PRICE POINT: 14.480000A ACTION: RSSL_MPEA_ADD_ENTRY
ORDER_PRC           14.480000
ORDER_SIDE          ASK(2)
NO_ORD              2
ACC_SIZE            1300
LV_TIM_MS           53450245
LV_TIM_MSP          304
LV_DATE             27 FEB 2015

> PRICE POINT: 12.700000B ACTION: RSSL_MPEA_ADD_ENTRY
ORDER_PRC           12.700000
ORDER_SIDE          BID(1)
NO_ORD              3
ACC_SIZE            1600
LV_TIM_MS           45059516
LV_TIM_MSP          214
LV_DATE             26 FEB 2015

...

PRICE POINT: 21.380000A ACTION: RSSL_MPEA_ADD_ENTRY
ORDER_PRC           21.380000
ORDER_SIDE          ASK(2)
NO_ORD              1
ACC_SIZE            1000
LV_TIM_MS           52462212
LV_TIM_MSP          263
LV_DATE             15 JAN 2015

PRICE POINT: 14.040000A ACTION: RSSL_MPEA_ADD_ENTRY
ORDER_PRC           14.040000
NO_ORD              1
ORDER_SIDE          ASK(2)
ACC_SIZE            100
LV_TIM_MS           53587649
LV_TIM_MSP          888
LV_DATE             27 FEB 2015

References

For more information, refer to the Transport API - C Development Guides.

Tutorial Group: 
ETA Consumer