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 |
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.
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.
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.
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
For more information, refer to the Transport API - C Development Guides.