Download tutorial source code |
Click here to download |
Last update | Aug 2024 |
Compilers | Tutorial demonstration: Visual Studio 2022 |
Prerequisites | Tutorial 3 - Decoding MarketPrice data |
The goal of this tutorial is to programmatically decode the response received from API.
In the previous tutorial, we subscribed and decoded MarketPrice data for "IBM.N". Following on similar approach, we will subscribe and decode a MarketByOrder (OrderBook) data for "IBM". MarketByOrder RDM is modeled using the OMM Map data structure and is well suited to convey OrderBook information for an instrument. Various OMM container classes are described in OMM White Paper.
The main method in Step4.cpp is modified and now instead of subscribing to MMT_MARKET_PRICE (default), we specify the requested domain as MMT_MARKET_BY_ORDER. The service you are using should carry the level II data for that instrument. All remaining semantics of requests is the same as in previous steps.
int main( int argc, char* argv[] )
{
.
.
.
// subscribe to Level2 market data
consumer.registerClient(
ReqMsg()
.domainType( MMT_MARKET_BY_ORDER )
.serviceName( "ELEKTRON_AD" )
.name( "TD.TO" ),
client );
return 0;
}
Just like Market Price, Market By Order message also consist of an initial Image which contains all the fields followed by Updates which contain only the fields which have changed since last image or update. It also contains status message which indicates status of our request and upstream delivery system.
In callback method for Refresh (Initial Image), we first dump the status of our request to console, and then check if the data payload is an OMM Map. If it is, we pass that payload to overloaded decode method which takes Map as an argument.
void AppClient::onRefreshMsg( const RefreshMsg& refreshMsg, const OmmConsumerEvent& event)
{
.
.
.
// display the status of current request
cout << endl << "Item State: " << refreshMsg.getState().toString() << endl;
// Level2 data payload is encoded as an OMM Map or NoData if no payload data is available
if( DataType::MapEnum == refreshMsg.getPayload().getDataType() )
decode( refreshMsg.getPayload().getMap(), true );
}
MarketByOrder RDM data is modelled using an OMM data structure called a Map. A Map contains Summary data and Map entries. Summary data common set of information that is applicable to all Map entries and is encoded as OMM FieldList. We will use previously defined decode method for it. Map entries are composed of Key, Action and Data. A Key uniquely identifies a particular map entry. Action is either Add, Delete or Update the Map entry; and Data is a FieldList which describes that entry.
Map (used for MarketByOrder) vs FieldList (used in MarketPrice):
MAP | FIELDLIST | |
---|---|---|
Summary | Yes | No |
Key | Complex data buffer | Integer |
Data | FieldList | Basic OMM data types like Int, Real etc |
To decode a Map, we will first check is it has summary data and use previously defined FieldList decode method to display the summary values on console. Then, we loop over all the Map entries, displaying the key code and action on console. If the Map action is Add or Update, it also carries a valid data, which we display on console using FieldList decode method. In real world scenerio, the application maintains a shadow copy of OrderBook in memory. This shadow book is best implemented using some sort of Map (e.g. std::map), where Add and Update actions update the book and delete action deletes an entry from shadow book. In the example, we just display everything on console.
void AppClient::decode( const Map& map, bool echo )
{
// if map has summary data, it is of type OMM Fieldlist
if( map.getSummaryData() == DataType::FieldListEnum )
{
cout << "Map Summary:" << endl;
decode( map.getSummaryData().getFieldList() );
}
// loop over map entries
while ( map.forth() ) {
const MapEntry& me = map.getEntry();
.
.
// data for Add and Update actions is OMM Fieldlist
switch ( me.getAction() ) {
case MapEntry::AddEnum:
cout<< "ADD Entry, Key: [" << keyBuf << "]" << endl;
if (me.getLoadType() == DataType::FieldListEnum )
decode( me.getFieldList() );
break;
.
.
.
}
}
}
}
Assuming you have properly setup the Visual Studio project, you can now compile and run the tutorial. If you encounter any compile errors, ensure your environment variables are properly defined. When you run the tutorial, you should see no errors and application will connect, send subscription request and display decoded market by order at the command line.