Establish a websocket connection and set headers?

Hello, I am using R software and struggling to make a websocket connection. The initial source for my websocket connection is here https://github.com/rstudio/websocket The codes, which I want to repicate ar here https://github.com/Refinitiv/websocket-api/blob/master/Applications/Examples/R/market_price_authentication.R


websocket function in github is old one and seems not to work.


header_entry = list(name="Cookie", value=paste("AuthToken=", auth_token, ";AuthPosition=", position, ";applicationId=", app_id,";", sep=""))
#header_entry_new = list(Domain="Login",ID=1, Key=list(Elements=list(ApplicationId=app_id,AuthenticationToken=auth_token,
Position=paste(position,"/S24533",sep = "")),NameType="AuthnToken"))
#header_entry_new<-jsonlite::toJSON(header_entry_new)
#header_entry_new<-gsub("\\[|\\]","",header_entry_new)
headers_list = list(header_entry)

ws <- WebSocket$new("wss://emea-1.pricing.streaming.edp.thomsonreuters.com:443/WebSocket", headers =header_entry)


By using wss://emea-1.pricing.streaming.edp.thomsonreuters.com:443/WebSocket and header_entry_new (in header) I tried to replicate following command in Python. I also tried in R to use only wss://emea-1.pricing.streaming.edp.thomsonreuters.com (+ headers =header_entry, port=443) and multiple different combinations, because in the github code :443/WebSocket part is neglected. However I got an error message saying that Error in .subset2(public_bind_env, "initialize")(...) : unused arguments (headers = list("Cookie" .....


Connecting to WebSocket wss://emea-1.pricing.streaming.edp.thomsonreuters.com:443/WebSocket ...
WebSocket successfully connected!
SENT:
{
  "Domain":"Login",
  "ID":1,
  "Key":{
    "Elements":{
      "ApplicationId":"256",
      "AuthenticationToken":"XXXXX",
      "Position":"172.17.57.17/S24533"
    },
    "NameType":"AuthnToken"
  }
}

What else can I change to establish a connection? (Authentication token I could retrieve)

Best Answer

  • @g.suhharukov

    I have tested it with R-4.0.3. It can send an item request properly. It looks like that there is a problem with the SEND_REQUEST flag.

    Got Message [{"ID":1,"Type":"Refresh","Domain":"Login","Key":{"Name":"xxx","Elements":{"AllowSuspectData":1,"ApplicationId":"256","ApplicationName":"ADS","AuthenticationErrorCode":0,"AuthenticationErrorText":{"Type":"AsciiString","Data":null},"AuthenticationTTReissue":1605263502,"Position":"192.168.56.1","ProvidePermissionExpressions":1,"ProvidePermissionProfile":0,"SingleOpen":1,"SupportEnhancedSymbolList":1,"SupportOMMPost":1,"SupportPauseResume":0,"SupportStandby":0,"SupportBatchRequests":7,"SupportViewRequests":1,"SupportOptimizedPauseResume":0}},"State":{"Stream":"Open","Data":"Ok","Text":"Login accepted by host ads-premium-az1-blue-15-main-prd.euw1-az1."},"Elements":{"PingTimeout":30,"MaxMsgSize":61430}}]
    Single Message
    ### Check Message:  Refresh Login FALSE
    {"ID":2,"Key":{"Name":"TRI.N"},"View":["BID","ASK"]}
    Got Message [{"ID":2,"Type":"Status","Key":{"Service":"ELEKTRON_DD","Name":"TRI.N"},"State":{"Stream":"Closed","Data":"Suspect","Code":"NotEntitled","Text":"Access Denied: User req to PE(6562)"}}]

    You may try to change = to <- at the beginning.

    REFINITIV_API_URL <- "https://api.refinitiv.com/&quot;
    OAUTH2_TOKEN_URL <- paste(REFINITIV_API_URL, "auth/oauth2/v1/token", sep="")
    RELOGIN_INTERVAL <- 250
    NEXT_RELOGIN_TIME <- Sys.time()
    SEND_REQUEST <- FALSE

    If it is still not working, please remove your credentials from the example code, and then share the source file.

Answers

  • Hello @g.suhharukov,

    I would approach this via Python first, let me explain:

    For Python integration, you can follow Quick Start - Connecting to Elektron Real Time in Cloud tutorial, step by step.

    Once you have completed it and verify by observing the streaming market data, next, would move on to R, and at this point integrating in R using this example should be more straightforward, you will be able to proceed by analogy with Python quickstart, but analogous, in R.

    While running quickstart, you will also be able to verify that machineId, password and clientId combination you are passing as parameters is valid, for the streaming ERT request.

  • @zoya.farberov Thank you for reply. I already connected via Python and got the answer from the server, thereafter I moved to the next step - apply R. In R I also succeeded in getting an authentication token (using all necessary information: machine ID, password...). However, the key problem is that I cannot/do not know how connect to the websocket server using different websocket function in R.

  • Hello @g.suhharukov,

    Just to confirm, when you say you got the answer from the server in python- you mean that you have received a token, or you also see the streaming market data?

  • Hello @g.suhharukov,

    Just an idea rather then the ready answer.

    There are two working Python examples:

    Quickstart for TREP -> Python and Quickstart = Try it out for ERT

    One implements websocket to deployed infra = TREP, another is websocket to ERT in cloud, what you are looking to implement in R.

    market_price_edpgw_authentication.R is example that also targets deployed infra, TREP. Websockets in the example are old, but still should be working. This example is analogous to the former, the deployed example.

    The differences in handling between the two python examples, makret_price_authentication.py and market_price_edpgw_authentication.py is essentially what you have to modify in market_price_authentication.R to arrive at market_price_edpgw_authentication.R. Do you see?

    For instance, I am noticing that websocket.WebSocketApp for ERT does not pass any cookies. This can potentially be what is specifically causing the issue.

    Hope this helps

  • I got both of them.
  • @g.suhharukov

    Please try the attached code. I installed both:

    • install_github("rstudio/websocket")
    • install_github("rstudio/httpuv")

    You need to specify username, password, and clientid in the code.

    USERNAME <- "username"
    PASSWORD <- "password"
    CLIENTID <- "clientid"

    Then, run it with RScript. websocket.R.txt


  • jirapongse.phuriphanvichai

    Thank you for the provided code, it is very helpful. I got the authentication token. However, as before, when I run following line

    ws <- WebSocket$new("wss://emea-1.pricing.streaming.edp.thomsonreuters.com:443/WebSocket", protocol="tr_json2", autoConnect = FALSE)

    Error in .subset2(public_bind_env, "initialize")(...) : 
      unused arguments (protocol = "tr_json2", autoConnect = FALSE)

    The same error appears every time. Do not know how avoid it.

  • Add the sessioInfo() before creating a WebSocket.

    ACCESS_TOKEN = get_access_token()
    sessionInfo()
    ws <- WebSocket$new("wss://emea-1.pricing.streaming.edp.thomsonreuters.com:443/WebSocket", protocol="tr_json2", autoConnect = FALSE)

    Please share the output:

    R version 3.6.3 (2020-02-29)
    Platform: x86_64-w64-mingw32/x64 (64-bit)
    Running under: Windows 10 x64 (build 18363)

    Matrix products: default

    locale:
    [1] LC_COLLATE=English_United States.1252
    [2] LC_CTYPE=English_United States.1252
    [3] LC_MONETARY=English_United States.1252
    [4] LC_NUMERIC=C
    [5] LC_TIME=English_United States.1252

    attached base packages:
    [1] stats     graphics  grDevices utils     datasets  methods   base

    other attached packages:
    [1] httr_1.4.2           jsonlite_1.7.1       websocket_1.3.1.9000

    loaded via a namespace (and not attached):
    [1] compiler_3.6.3 R6_2.5.0       later_1.1.0.1  curl_4.3       Rcpp_1.0.5
    [6] rlang_0.4.8
  • Here is the output

    jirapongse.phuriphanvichai

    > ACCESS_TOKEN = get_access_token() 
    get_access_token
    > sessionInfo()
    R version 4.0.3 (2020-10-10)
    Platform: x86_64-w64-mingw32/x64 (64-bit)
    Running under: Windows 10 x64 (build 18363)
    Matrix products: default

    locale: [1] LC_COLLATE=Estonian_Estonia.1257  LC_CTYPE=Estonian_Estonia.1257    LC_MONETARY=Estonian_Estonia.1257 LC_NUMERIC=C                      [5] LC_TIME=Estonian_Estonia.1257    

    attached base packages: [1] grid      stats     graphics  grDevices utils     datasets  methods   base     

    other attached packages:  [1] httr_1.4.2       httpuv_1.5.4     websocket_1.3.1  gridExtra_2.3    scales_1.1.1     ggthemes_4.2.0   reshape2_1.4.4   xlsx_0.6.4.2     RCurl_1.98-1.2   [10] XML_3.99-0.5     ggplot2_3.3.2    shiny_1.5.0      dplyr_1.0.2      GetoptLong_1.0.4 curl_4.3         jsonlite_1.7.1   websockets_1.1.7

    loaded via a namespace (and not attached):  [1] Rcpp_1.0.5          prettyunits_1.1.1   xlsxjars_0.6.1      ps_1.4.0            assertthat_0.2.1    rprojroot_1.3-2     digest_0.6.27        [8] mime_0.9            R6_2.4.1            plyr_1.8.6          backports_1.1.10    pillar_1.4.6        GlobalOptions_0.1.2 rlang_0.4.8         [15] rstudioapi_0.11     callr_3.5.1         labeling_0.4.2      desc_1.2.0          devtools_2.3.2      stringr_1.4.0       munsell_0.5.0       [22] compiler_4.0.3      pkgconfig_2.0.3     pkgbuild_1.1.0      htmltools_0.5.0     tidyselect_1.1.0    tibble_3.0.4        fansi_0.4.1         [29] crayon_1.3.4        withr_2.3.0         later_1.1.0.1       bitops_1.0-6        xtable_1.8-4        gtable_0.3.0        lifecycle_0.2.0     [36] magrittr_1.5        cli_2.1.0           stringi_1.5.3       farver_2.0.3        fs_1.5.0            promises_1.1.1      remotes_2.2.0       [43] testthat_2.3.2      ellipsis_0.3.1      generics_0.0.2      vctrs_0.3.4         rjson_0.2.20        tools_4.0.3         glue_1.4.2          [50] purrr_0.3.4         rsconnect_0.8.16    processx_3.4.4      pkgload_1.1.0       fastmap_1.0.1       colorspace_1.4-1    caTools_1.18.0      [57] sessioninfo_1.1.1   memoise_1.1.0       rJava_0.9-13        usethis_1.6.3      

    > ws <- WebSocket$new("wss://emea-1.pricing.streaming.edp.thomsonreuters.com:443/WebSocket", protocol="tr_json2", autoConnect = FALSE)
    Error in .subset2(public_bind_env, "initialize")(...) :    unused arguments (protocol = "tr_json2", autoConnect = FALSE)
  • jirapongse.phuriphanvichai

    I added an output below in the answers, because in comments characters limits are exceeded

  • @g.suhharukov

    I assume that it may conflict with the httpuv library.

    I got the same error when using the httpuv library.

    image

    The workaround is using websocket::WebSocket$new instead.

    > ws <- websocket::WebSocket$new("wss://emea-1.pricing.streaming.edp.thomsonreuters.com:443/WebSocket", protocol="tr_json2", autoConnect = FALSE)
    >



  • Yes, the problem was in this aspect. Do you know why I do not get prices and other indexes from the server? I only changed


    mp_req_json_string = "{\"ID\":2,\"Key\":{\"Name\":\"TRI.N\"}}"

    When I run the whole script the following output I got


    get_access_token
    send login request
    Got Message [{"ID":1,"Type":"Refresh","Domain":"Login","Key" ....

    Single Message
    Got Message [{"Type":"Ping"}]
    Single Message
    send pong
    Got Message [{"Type":"Ping"}] .....

    And it continues Ping-Pong until a new Auth. token is obtained. However, send_market_price_request(ws) is not run. Seems that server does not send message_domain == "Login". Do you know how to get prices?


  • Does it work with "JPY="? Have you seen this kind of message?

    Got Message [{"ID":2,"Type":"Status","Key":{"Service":"ELEKTRON_DD","Name":"TRI.N"},"State":{"Stream":"Closed","Data":"Suspect","Code":"NotEntitled","Text":"Access Denied: User req to PE(6562)"}}]
  • No, I tried for JPY and only "Got Message" is following

    Got Message [{"ID":1,"Type":"Refresh","Domain":"Login","Key"

    same as for TRI.N


    In python code I got

    "Position":"172.17.57.17/S24533"

    So I also changed in R position<-"172.17.57.17" , However, the same output.

  • Add the following code in the process_message.

     cat("### Check Message: ",message_type, message_json[['Domain']], SEND_REQUEST, "\n")
    process_message = function(message_json) {
    cat("Single Message","\n")
       message_type = message_json[['Type']]
       cat("### Check Message: ",message_type, message_json[['Domain']], SEND_REQUEST, "\n")
       if(message_type == "Refresh") {
          message_domain = message_json[['Domain']]
          if(!is.null(message_domain)) {

    It will send a request when:

    • message_type is Refresh
    • message_json[['Domain']] is Login
    • SEND_REQUEST is FALSE


  • websockev2.txtThe output changed to

    Got Message [{"ID":1,"Type":"Refresh","Domain":"Login","Key":{"Name":"xxxx","Elements":{"AllowSuspectData":1,"ApplicationId":"256","ApplicationName":"ADS","AuthenticationErrorCode":0,"AuthenticationErrorText":{"Type":"AsciiString","Data":null},"AuthenticationTTReissue":1605261819,"Position":"10.100.8.81","ProvidePermissionExpressions":1,"ProvidePermissionProfile":0,"SingleOpen":1,"SupportEnhancedSymbolList":1,"SupportOMMPost":1,"SupportPauseResume":0,"SupportStandby":0,"SupportBatchRequests":7,"SupportViewRequests":1,"SupportOptimizedPauseResume":0}},"State":{"Stream":"Open","Data":"Ok","Text":"Login accepted by host ads-premium-az1-blue-15-main-prd.euw1-az1."},"Elements":{"PingTimeout":30,"MaxMsgSize":61430}}]
    Single Message
    ### Check Message: Refresh Login TRUE
    Got Message [{"Type":"Ping"}]
    Single Message
    ### Check Message: Ping TRUE
    send pong
    Got Message [{"Type":"Ping"}]
    Single Message
    ### Check Message: Ping TRUE


    I also attached the file with the full code

  • @g.suhharukov

    The value of SEND_REQUEST should be FALSE.

    RELOGIN_INTERVAL = 250
    NEXT_RELOGIN_TIME = Sys.time()
    SEND_REQUEST=FALSE

    It is set at the beginning of the example.

    Can you verify it?

  • Yes, it is. I used the same file as you sent above

  • Yes, now I got the same output as you and not getting the prices ("Text":"Access Denied: User req to PE(526))

  • It means the credential doesn't have permission to access that item. You need to contact your Refinitiv account team or sales team to verify it.

    You can try JPY=.

  • Yes, I got trial version , which does not support JPY, however TRI.N does. and the message is following (sam as yours) with no price output

    "Text":"Access Denied: User req to PE(6562)"
  • Hi @g.suhharukov

    did you try JPY= or just JPY?

    Most trial accounts can access currency RICS such as JPY=, EUR=, GBP= etc.

  • I found the error. RIC should be written with " /" sign before its name, so "/EUR=" or "/TRI.N" should be instead

  • Hi @g.suhharukov

    The / symbol is for requesting Delayed data - not the latest realtime data.

    For example /EUR= is 15 minutes delayed compared to EUR=

    If you want the latest realtime date then please speak to your Refinitiv Account team or your internal Market Data team.