Article

Contributing your data to Refinitiv with WebSocket API and Refinitiv Real-Time Distribution System

Wasin Waeosri
Developer Advocate Developer Advocate

Introduction

Update: September 2021

This article is the other part of how to contribute data your data to Refinitiv article. The first article shows how to setup Refinitiv Real-Time Distribution System for RCC and how to contribute data with Refinitiv Real-Time SDK Java/C++ (formerly known as Elektron SDK). This second article focuses on how to contribute your data to RCC using Websocket API for Pricing Streaming and Real-Time Service (aka WebSocket API) through Refinitiv Real-Time Distribution System (Refinitiv Real-Time Advanced Distribution and Advanced Data Hub servers).

Note: RCC username, password, and host list credentials are required for contributing data to Refinitiv. Please reach out to your Refinitiv sales associate to acquire RCC access credentials.

RCC Overview

The Refinitiv Contribution Channel (RCC) is a new service for on-boarding content to Refinitiv. Depending on the client's needs, access to the service will be fulfilled by one or more of the following products: Contributions Channel for Refinitiv Real-Time Advanced Distribution Server/Advanced Data Hub Server, Contributions Channel for Real-Time API, Contributions Channel for Spreadsheet. RCC aims for replacing the legacy Market Link IP (MLIP) system.

Contribution Setup

Update (As of March 2021): The direct Websocket access to Contributions Channel Tutorial is available here.

Developers can contributing data to RCC with Real-Time SDK C++/Java (RSSL connection) and WebSocket API (WebSocket connection). Currently, there are three methods to contribute data to the RCC.

1. Use Refinitiv Real-Time SDKs to directly connect to RCC to contribute data. To use this method, please refer to the following tutorials

2. Use Refinitiv Real-Time SDKs or WebSocket API for contributing data to RCC via Refinitiv Real-Time Distribution System. To use this method, please refer to the following first article and continue on this article:

3. Use WebSocket API to directly connect to RCC to contribute data. To use this method, please refer to the following the Contributing Data to Refinitiv Contributions Channel (RCC) via WebSocket tutorial page.

This article is focusing on the second method which is contributing data via Refinitiv Real-Time Distribution System servers (Real-Time Advanced Distribution and Advanced Data Hub servers). The servers will take care of the RCC connection, JSON-OMM conversion, and login process for the application.

 

The Refinitiv Real-Time Advanced Data Hub server connects to RCC through the delivery direct network via Tunnel Stream Aggregator (TSA) adapter, which is a private network (TLS encrypted) between a client site and Refinitiv. The TSA adapter is already packaged with the  Advanced Data Hub version 3.2, and needs to be configured. You can find more detail regarding the Advanced Data Hub-RCC configurations in Contributing your data to Refinitiv article page.

You can find  Advanced Data Hub-RCC configuration parameters example in the project's /infra_config/rdms_trcc.cnf file (please note that it is not a completed  Advanced Data Hub configuration file).

Once this configuration is complete and the Contribution service RCC is available to the user, as shown in the Service-Up state in Advanced Data Hub and Advanced Distribution Server consoles. The WebSocket application can be used to POST data to this service in Advanced Distribution/Advanced Data Hub server.

If you are interested to contribute data using the RSSL connection (with or without Refinitiv Real-Time Distribution System)), please visit the following series of Real-Time SDK and RCC based on your prefer API:

Note: The reader must have an understanding of Real-Time SDK, WebSocket programming, and be familiar with OMM Market Price data. You should also have a basic understanding of Refinitiv Real-Time market data infrastructure components like Advanced Distribution Server, Advanced Data Hub, etc. The code snippets in this article are shown in Python programming language.

Contribution Process

The application requires the following steps to contribute data to RCC via Refinitiv Real-Time Advanced Distribution Server/Advanced Data Hub Server:

  1. The application initiates a WebSocket connection with Advanced Distribution Server.
  2. The application sends a OMM Login request message to Advanced Distribution Server in JSON format.
  3. Once the application receives a Login Refresh message from Advanced Distribution Server, the application can contribute data to RCC via an Off-Stream Post message.
  4. The RCC Off-Stream Post message must have the following conditions:
    • The Ack attribute must be true
    • The message must contain the PostID attribute and value
    • The Key information includes Name and Service attributes that refer to the contribution RIC name and RCC contribution service name
    • The Message payload must be an Update message type
    • The Message payload must contain the same Key information as the Post message

The example RCC Off-Stream Post message is shown in Posting result example section below.

Note: Please note that RCC supports Off-Stream Post only.

If you are not familiar with the WebSocket API Posting concept, please visit Contributing Data to Refinitiv Real-Time using the Websocket API article which will give you a full explanation of the WebSocket API Posting mechanisms and process.

Application Code Walkthrough

Following snippet of code is taken/modified from Elektron WebSocket API Python market_price_posting.py example, available in the Example Applications package. Complete RCC contribution posting sample is on Refinitiv-API-Samples GitHub page.

The example project contains both the Python console application and Jupyter Notebook application. please check the README.md in the source code project for more detail regarding how to run the example.

A successful login to Advanced Distribution Server, results in the Login-Refresh message. The process_login_response() function then calls c function to send the Post message.

    	
            

def process_message(ws, message_json):  # Process all incoming messages.

    """ Parse at high level and output JSON of message """

    message_type = message_json['Type']

 

    if message_type == "Refresh":

        if 'Domain' in message_json:

            message_domain = message_json['Domain']

            if message_domain == "Login":

                process_login_response(ws, message_json)

 

# Process incoming Login Refresh Response message.

def process_login_response(ws, message_json):

    """ Send Off-Stream Post """

    print("Sending Off-Stream Post to Real-Time Advanced Distribution Server")

    send_market_price_post(ws)

The send_market_price_post () function creates the Off-Stream post message in JSON format, then sends it to Advanced Distribution Server as follows:

    	
            

# Create JSON Off-Stream Post message and sends it to ADS server.

def send_market_price_post(ws):

    global post_id

    global bid_value

    global ask_value

    global primact_1_value

    """ Send a post message contains a market-price content to RCC """

 

    """ Contribution fields """

    contribution_fields = {

        "BID": bid_value,

        "ASK": ask_value,

        "PRIMACT_1": primact_1_value

    }

 

    """ OMM Post msg Key """

    mp_post_key = {

        "Name": post_item_name,

        "Service": service_name

    }

 

    """ OMM Post Payload """

    contribution_payload_json = {

        "ID": 0,

        "Type": "Update",

        "Domain": "MarketPrice",

        "Fields": contribution_fields,

        "Key": {}

    }

 

    """ OMM Off-Stream Post message """

    mp_post_json_offstream = {

        "Domain": "MarketPrice",

        "Ack": True,

        "PostID": post_id,

        "PostUserInfo": {

            "Address": position,

            "UserID": int(app_id)

        },

        "Key": {},

        "Message": {},

        "Type": "Post",

        "ID": login_id

    }

 

    contribution_payload_json["Key"] = mp_post_key

    mp_post_json_offstream["Key"] = mp_post_key

    mp_post_json_offstream["Message"] = contribution_payload_json

 

    ws.send(json.dumps(mp_post_json_offstream))

    print("SENT:")

    print(json.dumps(mp_post_json_offstream,

                     sort_keys=True, indent=2, separators=(',', ':')))

Posting result example

This posted data will automatically be forwarded to RCC and thus contributed to Refinitiv. The output from this example application shows a successful login to Advanced Distribution Server, followed by initial contribution upon login-refresh and multiple contributions upon receiving an acknowledgment:

Initiate and Login to Advanced Distribution Server

    	
            

Connecting to WebSocket ws://localhost:15000/WebSocket ...

WebSocket successfully connected!

SENT:

{

  "Domain":"Login",

  "ID":1,

  "Key":{

    "Elements":{

      "ApplicationId":"256",

      "Position":"10.42.68.162"

    },

    "Name":"root"

  }

}

RECEIVED:

[

  {

    "Domain":"Login",

    "Elements":{

      "MaxMsgSize":61430,

      "PingTimeout":30

    },

    "ID":1,

    "Key":{

      "Elements":{

        "AllowSuspectData":1,

        "ApplicationId":"256",

        "ApplicationName":"ADS",

        "Position":"10.42.68.162",

        "ProvidePermissionExpressions":1,

        "ProvidePermissionProfile":0,

        "SingleOpen":1,

        "SupportBatchRequests":7,

        "SupportEnhancedSymbolList":1,

        "SupportOMMPost":1,

        "SupportOptimizedPauseResume":1,

        "SupportPauseResume":1,

        "SupportStandby":1,

        "SupportViewRequests":1

      },

      "Name":"root"

    },

    "State":{

      "Data":"Ok",

      "Stream":"Open",

      "Text":"Login accepted by host apis30."

    },

    "Type":"Refresh"

  }

]

Contribution data via an Off-Stream Post message

    	
            

Sending Off-Stream Post to Real-Time Advanced Distribution Server

SENT:

{

  "Ack":true,

  "Domain":"MarketPrice",

  "ID":1,

  "Key":{

    "Name":"<CONTRIBUTION_RIC>",

    "Service":"<CONTRIBUTION_Service>"

  },

  "Message":{

    "Domain":"MarketPrice",

    "Fields":{

      "ASK":35.48,

      "BID":34.25,

      "PRIMACT_1":116.5

    },

    "ID":0,

    "Key":{

      "Name":"<CONTRIBUTION_RIC>",

      "Service":"<CONTRIBUTION_Service>"

    },

    "Type":"Update"

  },

  "PostID":1,

  "PostUserInfo":{

    "Address":"10.42.68.162",

    "UserID":256

  },

  "Type":"Post"

}

Here

RECEIVED: 

[

  {

    "AckID":1,

    "ID":1,

    "Key":{

      "Name":"<CONTRIBUTION_RIC>",

      "Service":"<CONTRIBUTION_Service>"

    },

    "Type":"Ack"

  }

]