ARTICLE

How to expand Chain RIC using the Tick History REST API in Python

Moragodkrit Chumsri
Developer Advocate Developer Advocate

Last Updated: 21 Oct 2021

Overview

LSEG Tick History - REST API is a Representational State Transfer (REST)-compliant API that programmatically exposes Tick History functionality on the DataScope Select platform. Client applications can be written in most programming languages, such as C#, C++, Visual Basic, Java, Python, Objective-C, and Swift.

One of the favorite use cases for applications that use the legacy SOAP-based Tick History API is to use the API to expand a Chain RIC and get a RIC list. After getting the list, they can pass the list to retrieve some specific data using other Tick History functions and they can also export the list to other applications. This article will demonstrate how to use the new REST API to expand a Chain RIC and get a RIC list like the legacy API.

This example demonstrates how to interact with the LSEG Tick HIstory REST API without using.Net SDK. And we use Python programming language to demonstrate the API usages as it works as a script and it can work across OS. This example applies knowledge from Tick History document and tutorial from developer community website.

Introduction

The Legacy SOAP API has the ExpandChain method which will return a list of the RICs for all instruments that were part of the given chain at any time during the given time period. This Function expands the chain for the given RIC independently on each day in the requested range of dates and then collates the results as a single list of RICs. For the new REST API, clients can expand a chain RIC and get underlying RICs using HTTP endpoint /Search/HistoricalChainResolution. The API calls resolve current and past chain constituents given a Chain RIC. Instruments may be currently active, or inactive. It can be very time consuming on both SOAP and REST API. Try not to use this function with large ranges of dates.

HTTP Request

  • Endpoint URL:
    	
            
https://selectapi.datascope.refinitiv.com/RestApi/v1/Search/HistoricalChainResolution
  • Method: POST
  • Headers:
    	
            

Prefer: respond-async

Content-Type: application/json; odata.metadata=minimal

Authorization: <Your Authorization Token>

  • Body:
    	
            

ChainRics: Identifies one or more chain RICs, each of which will be resolved into its constituent RICs.

Start: Start date. For example, 2017-01-01T00:00:00.000Z.

End: End date. For example, 2017-01-01T00:00:00.000Z.

  • Sample Request Body
    	
            

 {

       "Request":

                {

                     "ChainRics": [ "0#HO:" ],

                     "Range": {

                            "Start": "2008-01-01T00:00:00.000Z",

                            "End": "2016-01-01T00:00:00.000Z"

                          }

               }

}

HTTP Response

  • Sample Response message
    	
            
HTTP/1.1 200 OK
    	
            

 {

    "@odata.context": "https://selectapi.datascope.refinitiv.com/RestApi/v1/$metadata#Collection(DataScope.Select.Api.Search.HistoricalChainInstrument)",

    "value": [

              {

                "Identifier": "0#HO:",

                "IdentifierType": "ChainRIC",

                "Source": "",

                "Key": "VjF8MHgxMDAwMDAwMDAwMDAwMDAwfDB4MTAwMDAwMDAwMDAwMDAwMHx8Q0hSfENIUnxDSFJ8SHx8MCNITzp8",

                "Description": "Historical Chain",

                "InstrumentType": "Unknown",

                "Status": "Valid",

                "Constituents": [

                               {             

                                  "Identifier": "HOF0",

                                  "IdentifierType": "Ric",

                                  "Source": "", "Key": "VjF8MHgzMDAwMDAwMDAwMDAwMDAwfDB4MzAwMDAwMDAwMDAwMDAwMHx8fHx8fHxIT0YwfA",

                                  "Description": "Historical Instrument",

                                  "InstrumentType": "Unknown",

                                  "Status": "Valid",

                                  "DomainCode": "6"

                               },

 

              . . .                                                                                           

                               {

                                 "Identifier": "HOZ9",

                                   "IdentifierType": "Ric",

                                   "Source": "",

                                   "Key": "VjF8MHgzMDAwMDAwMDAwMDAwMDAwfDB4MzAwMDAwMDAwMDAwMDAwMHx8fHx8fHxIT1o5fA",

                                   "Description": "Historical Instrument",

                                   "InstrumentType": "Unknown",

                                   "Status": "Valid",

                                   "DomainCode": "6"

                               }]

               ]

 

          }

    ]

}

From the HTTP response, it presents the chain’s constituent RICs. Hence the application has to parse JSON object and get the RIC list by accessing the value of Constituents.

Python Example

Prerequisite

  • To run the example user should have python 2.7 or 3.6 installed on OS. A user can download python installer from the link below. Basically, users can open the example with any text editor. There are free Python IDEs such as PyCharm Community edition and Visual Studio Code developers can use to open python source file.
    	
            
https://www.python.org
  • In order to access the Tick History Endpoint, a user must have DSS account with permission to access Tick History’s REST API. Please contact your LSEG Account representative if you need a new account or additional permissions.
  • To use HTTP request and response, this example uses the Python 'requests' module. 
  • This example uses pandas data frames and some functions from numpy to parse and display data so you have to install pandas and numpy module.

Implementation

The example starts from importing the required Python modules so you need to import requests and JSON module to the example. It also requires pandas and numpy module to convert JSON data to the pandas data frame.

    	
            

from json import dumps, loads, load

from requests import post,get

...

import pandas as pd

import numpy as np

Authentication

To get an Authentication Token, the example will require a valid username and password and then send a new Authentication request to the DSS server to get a new Token. After it gets a new Token, it will pass the token to the Http request header. Below is the code for requesting a new token from the DSS server. If a user doesn’t want to get a new token as the old one still valid for 24 hours, feel free to modify RequestNewToken function to return valid token instead.

    	
            

def RequestNewToken(username="",password=""):

    _AuthenURL = "https://selectapi.datascope.refinitiv.com/RestApi/v1/Authentication/RequestToken"

    _header= {}

    _header['Prefer']='respond-async'

    _header['Content-Type']='application/json; odata.metadata=minimal'

    _data={'Credentials':{

        'Password':password,

        'Username':username

        }

    }

 

    print("Send Login request")

    resp=post(_AuthenURL,json=_data,headers=_header)

 

    if resp.status_code!=200:

        message="Authentication Error Status Code: "+ str(resp.status_code) +" Message:"+resp.text

        raise Exception(dumps(message,indent=4))

 

    return loads(resp.text)['value']

Expand Chain

Before sending an Http request with a post message to HistoricalChainResolution endpoint, it required the Authorization Token from the previous steps with JSON payload containing Chain RIC, start date and end date. Please find sample JSON payload from section Sample Request Body.

In order to get underlying RICs from HTTP response message(see section Sample Response message), the application has to access the Constituents list from JSON object and then convert the list to a pandas data frame. And then it can access RIC list under the Constituents list. Below is the python code from the example. It will print a data frame containing RIC name and Status to console.

    	
            

def ExpandChain(token,json_payload):

    _expandChainURL = "https://selectapi.datascope.refinitiv.com/RestApi/v1/Search/HistoricalChainResolution"

    _header = {}

    _header['Prefer'] = 'respond-async'

    _header['Content-Type'] = 'application/json; odata.metadata=minimal'

    _header['Accept-Charset'] = 'UTF-8'

    _header['Authorization'] = 'Token' + token

    resp = post(_expandChainURL, data=None, json=json_payload, headers=_header)

    item_list = []

    if(resp.status_code==200):

        json_object=loads(resp.text,object_pairs_hook=OrderedDict)

        if len(json_object['value']) > 0:

            dataFrame = pd.DataFrame.from_dict(json_object['value'][0]['Constituents'])

        else:

            return pd.DataFrame()

    else:

        print("Unable to expand chain response return status code:",resp.status_code)

 

    return dataFrame

    	
            

#In the Main function

            _jsonquery={

                        "Request": {

                            "ChainRics": [

                                    _chainRIC

                                    ],

                            "Range": {

                                "Start": _startDate,

                                "End": _endDate

                            }

                         }

            }

            print("Start Expanding Chain "+_chainRIC+"\n")

            df=ExpandChain(_token,_jsonquery)

            if df.empty:

                print("Unable to expand chain "+_chainRIC) 

                return

 

            ricCount=len(df['Identifier'])

            print("Found "+str(ricCount)+" RIC")

            #Filter and print only RIC name and Status columns

            pd.set_option('display.max_rows', ricCount)

            newDF = df.filter(items=['Identifier','Status'])

            newDF.index = np.arange(1,len(newDF)+1)

            print(newDF)

Running example

To test the example, please run the following python command

>python ExpandChainREST.py

The example will ask a user to input DSS username and password then it will request a new Token and pass it to HTTP request as described. Feel free to change the following variables if you want to set chain RIC, start date, end date.

_chainRIC="0#.FTSE"

_startDate="2017-03-14T00:00:00.000Z"

_endDate="2017-03-15T00:00:00.000Z"

After running the example, it will display the following console output

    	
            

Login to DSS Server

Send Login request

Authorization Token:_tHSMJfR5k2n4a56GCmGhhyCCYjt1AA6F5FC3DswB9ad55M5TQhpkOuK6jw5NWy3ir9Vzq5phjQ71rHkZhYrB7tA0c6eBEAVDlOK26H98YWYe9QqVSYp-5IeaMsI9QYIvB-ZxQr5xEv1Mc6u1KF9Afzbq3LtSC11qALNdIIS4JbGjNLqKJ8HgTD6VYuUa6Vc-OlXvEkIlClkUH7_tLCKNwqNZZYK7LPFxnhXWq9NhsoxAoxMOj2kRM1NnhUoCIIgOYfkyw69GEMTauLoHLyOHprN_4KsDlBQN59BQ8OAQu5c

 

Start Expanding Chain 0#.FTSE

 

Found 103 RIC

    Identifier Status

1     .AD.FTSE  Valid

2        .FTSE  Valid

3        AAL.L  Valid

4        ABF.L  Valid

5       ADML.L  Valid

6        AHT.L  Valid

7       ANTO.L  Valid

8         AV.L  Valid

9        AZN.L  Valid

10       BAB.L  Valid

11      BAES.L  Valid

12      BARC.L  Valid

13      BATS.L  Valid

14      BDEV.L  Valid

15      BLND.L  Valid

16       BLT.L  Valid

17      BNZL.L  Valid

18        BP.L  Valid

19      BRBY.L  Valid

20        BT.L  Valid

21       CCH.L  Valid

22       CCL.L  Valid

23       CNA.L  Valid

24       CPG.L  Valid

25      CRDA.L  Valid

26       CRH.L  Valid

27      CTEC.L  Valid

28       DCC.L  Valid

29       DGE.L  Valid

30      DLGD.L  Valid

31      EXPN.L  Valid

32       EZJ.L  Valid

33      FRES.L  Valid

34       GKN.L  Valid

35      GLEN.L  Valid

36       GSK.L  Valid

37       HIK.L  Valid

38      HMSO.L  Valid

39      HRGV.L  Valid

40      HSBA.L  Valid

41      ICAG.L  Valid

42       IHG.L  Valid

43       III.L  Valid

44       IMB.L  Valid

45       INF.L  Valid

46     INTUP.L  Valid

47      ITRK.L  Valid

48       ITV.L  Valid

49      JMAT.L  Valid

50       KGF.L  Valid

51      LAND.L  Valid

52      LGEN.L  Valid

53      LLOY.L  Valid

54       LSE.L  Valid

55      MCRO.L  Valid

56      MDCM.L  Valid

57      MERL.L  Valid

58       MKS.L  Valid

59      MNDI.L  Valid

60       MRW.L  Valid

61        NG.L  Valid

62       NXT.L  Valid

63       OML.L  Valid

64       PFG.L  Valid

65       PPB.L  Valid

66       PRU.L  Valid

67       PSN.L  Valid

68      PSON.L  Valid

69        RB.L  Valid

70       RBS.L  Valid

71      RDSa.L  Valid

72      RDSb.L  Valid

73       REL.L  Valid

74       RIO.L  Valid

75       RMG.L  Valid

76        RR.L  Valid

77       RRS.L  Valid

78       RSA.L  Valid

79       RTO.L  Valid

80      SBRY.L  Valid

81       SDR.L  Valid

82       SGE.L  Valid

83       SHP.L  Valid

84       SJP.L  Valid

85       SKG.L  Valid

86      SKYB.L  Valid

87        SL.L  Valid

88      SMIN.L  Valid

89       SMT.L  Valid

90        SN.L  Valid

91       SSE.L  Valid

92      STAN.L  Valid

93       SVT.L  Valid

94      TSCO.L  Valid

95      TUIT.L  Valid

96        TW.L  Valid

97      ULVR.L  Valid

98        UU.L  Valid

99       VOD.L  Valid

100      WOS.L  Valid

101      WPG.L  Valid

102      WPP.L  Valid

103      WTB.L  Valid

Note

The time to expand chain is proportional to the number of days in the date range. Do not specify longer date ranges than necessary.

Source Code Downloads

The sources code can be downloaded from ExpandChain

Downloads

Article.RTH.Python.REST.ExpandChain