Download tutorial source code |
Click here to download |
Last update | Aug 2024 |
Compilers | Tutorial demonstration: Visual Studio 2022 |
Prerequisites | Tutorial 3 - Decoding MarketPrice data, RTO Authentication Version 2 credentials |
Important Note: If you are using the Wealth solution (Pricing Streaming Optimized Service or Pricing Streaming Service), the products currently support Authentication Version 1 only (As of May 2024). Please contact your LSEG representative to verify if you are using Wealth or RTO solution.
This tutorial assumes you are familiar with consuming MarketPrice data from RTDS (Real-Time Distribution System) using EMA C++. In this tutorial, we will modify the code in the Tutorial 3 (EMA Consumer - Decoding MarketPrice data) to connect to LSEG Real-Time Optimized (RTO) using the Authentication Version 2 (aka Customer Identity and Access Management - CIAM, or Service Account) and consume MarketPrice data.
For further details about Migrating a EMA C++ API application from the Authentication Version 1 to Version 2, please check out the following resource:
LSEG Real-Time – Optimized is LSEG real-time content, hosted in the public cloud. It provides fast and simple access to our unparalleled content from hundreds of exchanges and OTC markets around the world. The existing consuming applications can be easily modified to connect to RTO and retrieve market data.
To connect the LSEG Real-Time Optimized on Cloud, the service account (v2 authentication) is required. The service account contains:
To get the service account (v2 authentication), please contact the LSEG representative directly.
You can find more information about the Authentication Version 2 from the following resources:
There are four steps to modify and configure the existing applications to connect to RTO and retrieve market data.
A client Id and client secret must be set in an instance of the OmmConsumerConfig class. Then, use it to create an instance of the OMMConsumer class.
OmmConsumer consumer(
OmmConsumerConfig()
.clientId("<client Id>")
.clientSecret("<client secret>"));
The Host and Username settings can be removed because it uses the client Id and client secret instead and the EMA will query the valid hostnames from the service discovery endpoint and select one to establish a connection.
The default real-time service name used by LSEG Real-Time Optimized is ELEKTRON_DD so we need to send item requests to this service.
consumer.registerClient(
ReqMsg().serviceName( "ELEKTRON_DD" ).name( "JPY=" ),
client);
The easiest way to connect to the RTO servers is specifying the Location configuration in the EMA configuration file (EmaConfig.cnf). The Location configuration specifies the cloud location of the RTO endpoint to which the RTSDK API establishes a connection. The content in the EMA configuration file (EmaConfig.cnf) looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<EmaConfig>
<ConsumerGroup>
<DefaultConsumer value="Consumer_1"/>
<ConsumerList>
<Consumer>
<Name value="Consumer_1"/>
<Channel value="Channel_1"/>
<Logger value="Logger_1"/>
<Dictionary value="Dictionary_1"/>
<XmlTraceToStdout value="0"/>
</Consumer>
</ConsumerList>
</ConsumerGroup>
<ChannelGroup>
<ChannelList>
<Channel>
<Name value="Channel_1"/>
<ChannelType value="ChannelType::RSSL_ENCRYPTED"/>
<Location value="ap-northeast-1"/>
<EnableSessionManagement value="1"/>
<EncryptedProtocolType value="EncryptedProtocolType::RSSL_SOCKET"/>
<ObjectName value=""/>
</Channel>
</ChannelList>
</ChannelGroup>
<LoggerGroup>
<LoggerList>
<Logger>
<Name value="Logger_1"/>
<LoggerType value="LoggerType::Stdout"/>
<LoggerSeverity value="LoggerSeverity::Success"/>
</Logger>
</LoggerList>
</LoggerGroup>
<DictionaryGroup>
<DictionaryList>
<Dictionary>
<Name value="Dictionary_1"/>
<DictionaryType value="DictionaryType::ChannelDictionary"/>
</Dictionary>
</DictionaryList>
</DictionaryGroup>
</EmaConfig>
The configuration file contains the Consumer_1 consumer configuration which is the default consumer. The Consumer_1 consumer uses the Channel_1 channel configuration that establish an encrypted socket connection to an RTO server in the ap-northeast-1 location. Finally, it uses the Dictionary_1 dictionary configuration which loads data dictionary from RTO.
Note:
To connect to RTO, it requires the curl library. This library is available in the RTSDK package. It is in the <RTSDK Directory>\installdb\WIN_64_VS143\bin directoty. Therefore, you need to copy this library (libcurl.dll or libcurl-d.dll) to the current working directly. Otherwise, you will see the following error message when running the application.
loggerMsg
TimeStamp: 17:29:53.200
ClientName: ChannelCallbackClient
Severity: Error
Text: Failed to add RsslChannel(s) to RsslReactor. Channel name(s) Channel_1
Instance Name Consumer_1_1
RsslReactor 0x0000017733330740
RsslChannel 0
Error Id -1
Internal sysError 0
Error Location D:\Jenkins\workspace\RTSDK_Core_DX1\OS\VS143-64\rcdev\source\rtsdk\Cpp-C\Eta\Impl\Reactor\rsslReactor.c:1404
Error Text Failed to initialize RsslRestClient. Text: <D:\Jenkins\workspace\RTSDK_Core_DX1\OS\VS143-64\rcdev\source\rtsdk\Cpp-C\Eta\Impl\Transport\rsslSocketTransportImpl.c:516> Error: 0012 Unable to load CURL.
loggerMsgEnd
Exception subscribing to market data: Exception Type='OmmInvalidUsageException', Text='Failed to add RsslChannel(s) to RsslReactor. Channel name(s) Channel_1
Instance Name Consumer_1_1
RsslReactor 0x0000017733330740
RsslChannel 0
Error Id -1
Internal sysError 0
Error Location D:\Jenkins\workspace\RTSDK_Core_DX1\OS\VS143-64\rcdev\source\rtsdk\Cpp-C\Eta\Impl\Reactor\rsslReactor.c:1404
Error Text Failed to initialize RsslRestClient. Text: <D:\Jenkins\workspace\RTSDK_Core_DX1\OS\VS143-64\rcdev\source\rtsdk\Cpp-C\Eta\Impl\Transport\rsslSocketTransportImpl.c:516> Error: 0012 Unable to load CURL.', ErrorCode='-1'
Assuming you have properly set up 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 the application will connect to RTO, send a subscription request, and display decoded market price at the command line.
Connecting to market data server
loggerMsg
TimeStamp: 17:34:27.157
ClientName: ChannelCallbackClient
Severity: Success
Text: Received ChannelUp event on channel Channel_1
Instance Name Consumer_1_1
Connected component version: ads3.7.2.E1.linux.rrg 64-bit
loggerMsgEnd
Subscribing to market data
----------------------------------
Refresh message, item Handle: 1536339132752 Closure: 0000000000000000
Item Name: JPY=
Service Name: ELEKTRON_DD
Item State: Open / Ok / None / ''
Fid: 1 Name: PROD_PERM DataType: UInt Value: 526
Fid: 2 Name: RDNDISPLAY DataType: UInt Value: 153
Fid: 3 Name: DSPLY_NAME DataType: Rmtes Value:
Fid: 5 Name: TIMACT DataType: Time Value: 10:34:0:0
Fid: 11 Name: NETCHNG_1 DataType: Real Value: -0.08
Fid: 12 Name: HIGH_1 DataType: Real Value: 155.93
Fid: 13 Name: LOW_1 DataType: Real Value: 155.13
Fid: 15 Name: CURRENCY DataType: Enum Value: 392
Fid: 17 Name: ACTIV_DATE DataType: Date Value: 7 / 6 / 2024
Fid: 19 Name: OPEN_PRC DataType: Real Value: 155.6
Fid: 21 Name: HST_CLOSE DataType: Real Value: 155.6
Fid: 22 Name: BID DataType: Real Value: 155.52
Fid: 23 Name: BID_1 DataType: Real Value: 155.52
Fid: 24 Name: BID_2 DataType: Real Value: 155.54
Fid: 25 Name: ASK DataType: Real Value: 155.55
Fid: 26 Name: ASK_1 DataType: Real Value: 155.55
Fid: 27 Name: ASK_2 DataType: Real Value: 155.55
Fid: 32 Name: ACVOL_1 DataType: Real Value: 57049
Fid: 53 Name: TRD_UNITS DataType: Enum Value: 2
Fid: 56 Name: PCTCHNG DataType: Real Value: -0.05
Fid: 57 Name: OPEN_BID DataType: Real Value: 155.6
Fid: 59 Name: OPEN_ASK DataType: Real Value: 155.63
Fid: 60 Name: CLOSE_BID DataType: Real Value: 155.6
Fid: 61 Name: CLOSE_ASK DataType: Real Value: 155.63
Fid: 77 Name: NUM_MOVES DataType: Real Value: 110541
Fid: 78 Name: OFFCL_CODE DataType: Rmtes Value:
Fid: 79 Name: HSTCLSDATE DataType: Date Value: 6 / 6 / 2024
Fid: 90 Name: YRHIGH DataType: Real Value: 160.03
Fid: 91 Name: YRLOW DataType: Real Value: 140.82
...
Waiting for updates. Application will exit in 30 seconds...
Item Name: JPY=
Service Name: ELEKTRON_DD
Fid: 22 Name: BID DataType: Real Value: 155.53
Fid: 393 Name: PRIMACT_1 DataType: Real Value: 155.53
Fid: 25 Name: ASK DataType: Real Value: 155.58
Fid: 275 Name: SEC_ACT_1 DataType: Real Value: 155.58
Fid: 875 Name: VALUE_DT1 DataType: Date Value: 7 / 6 / 2024
Fid: 1010 Name: VALUE_TS1 DataType: Time Value: 10:34:28:0
Fid: 5 Name: TIMACT DataType: Time Value: 10:34:0:0
Fid: 11 Name: NETCHNG_1 DataType: Real Value: -0.07
Fid: 17 Name: ACTIV_DATE DataType: Date Value: 7 / 6 / 2024
...
Item Name: JPY=
Service Name: ELEKTRON_DD
Fid: 3284 Name: EURO_NETCH DataType: Real Value: -0.44
Item Name: JPY=
Service Name: ELEKTRON_DD
Fid: 3378 Name: PCTCHG_3M DataType: Real Value: 5.07
Fid: 3379 Name: PCTCHG_6M DataType: Real Value: 7.92
Fid: 3380 Name: PCTCHG_MTD DataType: Real Value: -1.13
Fid: 3381 Name: PCTCHG_YTD DataType: Real Value: 10.26
Item Name: JPY=
Service Name: ELEKTRON_DD
Fid: 114 Name: BID_NET_CH DataType: Real Value: -0.07
Fid: 372 Name: IRGPRC DataType: Real Value: -0.04
For more information, refer to the following resources:
For any questions related to this tutorial or the RTSDK C/C++ page, please use the Developer Community Q&A Forum website.