ETA Consumer - Retrieving and decoding level 2 content

Download tutorial source code

Click here to download

Last update Dec 2020
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 (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 utilizing 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 Real-Time Distribution System to test. Defined within the basicConsumer.c file, these tutorials assume the following server has been defined:

    	
            

/* Server/Provider connection details */

#define RTDS_SERVER_NAME "rtds"

#define RTDS_SERVER_PORT "14002"

 

...

You can either define the server name 'rtds' 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.