Skip to content

GreenGrassBlueOcean/RefinitivR

Repository files navigation

RefinitivR

Codecov test coverage R build status

Overview

RefinitivR is an R interface to LSEG Workspace (formerly Refinitiv Eikon) and Refinitiv DataStream.

Just load and go — the package auto-detects your running terminal and connects on the first API call. No API key, no setup code, no connection objects to manage. Repeated requests can be served from an opt-in session-scoped cache with configurable TTLs.

  • Snapshot & historical datard_GetData(), rd_GetHistory(), rd_GetHistoricalPricing()
  • Real-time streaming — WebSocket-based live market data with callbacks
  • ESG, estimates & ownershiprd_GetESG(), rd_GetEstimates(), rd_GetOwnership()
  • News & search — headlines, stories, top news, discovery search
  • Custom instruments — create, update, delete basket and formula instruments
  • DataStream — via DatastreamDSWS2R
  • Robust under the hood — three-layer retry with exponential backoff, automatic chunking, HTTP 429/503 handling, progress reporting for large requests

Note (v0.2.0): Python/reticulate support has been removed. All data retrieval now uses the JSON API exclusively. See NEWS.md for details.

This package is in no way affiliated with Thomson Reuters, Refinitiv, Eikon, Datastream, or LSEG. A subscription to Eikon/LSEG Workspace and/or Datastream is required. Use at your own risk!

Installation

install.packages("devtools")
devtools::install_github("GreenGrassBlueOcean/RefinitivR")
library(Refinitiv)

Quick Start

With LSEG Workspace running, no explicit connection step is needed:

library(Refinitiv)

# Get snapshot data
rd_GetData(rics = "AAPL.O", Eikonformulas = "TR.CompanyName")

# Get historical data
rd_GetHistory(universe = c("AAPL.O", "MSFT.O"))

Real-Time Streaming

stream <- rd_get_streaming_data(
  universe = "EUR=",
  fields = c("BID", "ASK", "OPEN_PRC")
)

stream$on_update(function(stream, instrument, fields) {
  cat(sprintf("%s: BID=%s, ASK=%s\n", instrument, fields$BID, fields$ASK))
})

stream$open()
Sys.sleep(10)
print(stream$get_latest_data())
stream$close()

Table of Contents

  1. Connecting to LSEG Workspace
  2. Real-Time Streaming
  3. Working with Refinitiv Data (RD)
  4. Legacy Eikon Functions
  5. DataStream
  6. Custom Instruments
  7. Caching
  8. Progress Reporting
  9. Building Custom Visualizations

Connecting to LSEG Workspace

No explicit connection step is needed. All API functions default to rd_connection(), which auto-creates and caches a connection on first use.

Make sure LSEG Workspace (or Eikon Desktop) is running and online before calling any API function. After a terminal restart, call rd_connection(reset = TRUE) to force a fresh connection.


Real-Time Streaming

The package includes a real-time streaming API for live market data using WebSocket connections.

Prerequisites

# Required packages (installed automatically)
install.packages(c("websocket", "later", "shiny", "data.table"))

Quick Example

library(Refinitiv)

stream <- rd_get_streaming_data(
  universe = "EUR=",
  fields = c("BID", "ASK")
)

stream$on_update(function(stream, instrument, fields) {
  cat(sprintf("[%s] BID: %s | ASK: %s\n", 
              instrument, fields$BID, fields$ASK))
})

stream$open()
Sys.sleep(10)
stream$close()

Multiple Instruments

stream <- rd_get_streaming_data(
  universe = c("EUR=", "GBP=", "JPY="),
  fields = c("BID", "ASK", "OPEN_PRC", "DSPLY_NAME")
)

Event Callbacks

# Refresh callback - called when initial data is received
stream$on_refresh(function(stream, instrument, fields) {
  cat(sprintf("Initial data for %s received\n", instrument))
})

# Update callback - called on every price update
stream$on_update(function(stream, instrument, fields) {
  # Process update
})

# Error callback - called on errors
stream$on_error(function(stream, error_message) {
  warning("Stream error: ", error_message)
})

Accessing Data

# Latest snapshot (all instruments)
latest <- stream$get_latest_data()

# Latest for specific instrument
eur_data <- stream$get_latest_data("EUR=")

# Full history (data.table)
history <- stream$get_data_history()

# Summary statistics
summary <- stream$get_summary()
summary_eur <- stream$get_summary(instrument = "EUR=")

Built-in Live Plotting

app <- stream$plot_live(field = "BID", instrument = "EUR=")
shiny::runApp(app)

Advanced Usage

# Enable debug logging
options(refinitiv_streaming_debug = TRUE)

# Create stream with custom manager
def <- rd_streaming_pricing$Definition$new(
  universe = "EUR=",
  fields = c("BID", "ASK")
)
stream <- def$get_stream()
stream$open()

Examples

Run the included examples:

# Quick example (~10 seconds)
source(system.file("examples", "streaming_quick_example.R", package = "Refinitiv"))

# Complete example (~30 seconds, all features)
source(system.file("examples", "streaming_complete_example.R", package = "Refinitiv"))

# Debug example (~15 seconds, with logging)
source(system.file("examples", "streaming_test_debug.R", package = "Refinitiv"))

Working with Refinitiv Data (RD)

Searching

# Basic search
results <- RDPsearch(query = "AAPL.O")

# Advanced search with filters
Presidents <- RDPsearch(
  view = "People", 
  query = 'president',
  filter = "startswith(LastName,'H')",
  select = 'DocumentTitle',
  order_by = 'DocumentTitle asc',
  top = 20
)

Get History

# Simple timeseries
timeseries <- rd_GetHistory(universe = c("AAPL.O", "NVDA.O"))

# With fields and parameters
data <- rd_GetHistory(
  universe = c("GOOG.O", "AAPL.O"),
  fields = c("TR.Revenue", "TR.GrossProfit"),
  parameters = list("SDate" = "0CY", "Curn" = "CAD")
)

Get Data

ex1 <- rd_GetData(
  rics = c("MMM", "III.L"),
  Eikonformulas = c("TR.PE(Sdate=0D)/*P/E (LTM) - Diluted Excl*/", 
                     "TR.CompanyName")
)

Historical Pricing

# Daily data
daily <- rd_GetHistoricalPricing(
  universe = "VOD.L", 
  interval = "P1D",
  count = 20L
)

# Intraday (1-minute)
intraday <- rd_GetHistoricalPricing(
  universe = c("VOD.L", "AAPL.O"),
  interval = "PT1M", 
  count = 500L,
  sessions = c("pre", "normal", "post")
)

Working with the Legacy Eikon Functions

The legacy Eikon* functions now also default to rd_connection(), so no explicit connection is needed:

News

headlines <- EikonGetNewsHeadlines(query = "R:MSFT.O", count = 2)
stories <- EikonGetNewsStory(story_id = headlines$storyId)

Timeseries

Timeseries <- EikonGetTimeseries(
  rics = c("MMM", "III.L"),
  start_date = "2020-01-01T01:00:00",
  end_date = paste0(Sys.Date(), "T01:00:00")
)

Data Requests

Data <- EikonGetData(
  rics = c("MMM", "III.L"),
  Eikonformulas = c("TR.PE(Sdate=0D)/*P/E (LTM) - Diluted Excl*/", 
                     "TR.CompanyName")
)

Custom Instruments

Setup

# Get UUID from Eikon Terminal: Help > About > User Details
RD <- RDConnect(UUID = "ABCDE-123456")

Create Simple Instrument

rd_ManageCustomInstruments(
  operation = "CREATE", 
  symbol = "testAAPLandAMZN",
  formula = "AAPL.O + AMZN.O"
)

rd_ManageCustomInstruments(operation = "GET", symbol = "testAAPLandAMZN")
rd_ManageCustomInstruments(
  operation = "UPDATE", 
  symbol = "testAAPLandAMZN",
  formula = "AAPL.O + 2 * AMZN.O"
)
rd_ManageCustomInstruments(operation = "DELETE", symbol = "testAAPLandAMZN")

Basket Instruments

basket <- CustomInstrumentBasketBuilder(
  RICs = c("AAPL.O", "AMZN.O"), 
  Weights = c(0.5, 0.5)
)

rd_ManageCustomInstruments(
  operation = "CREATE", 
  symbol = "InterestingBasket",
  basket = basket, 
  currency = "USD"
)

holidays <- CustomInstrumentHolidayBuilder(
  dates = c("2023-12-01", "2023-12-31"),
  reasons = c("Special Bank Holiday 1", "Special Bank Holiday 2")
)

rd_ManageCustomInstruments(
  operation = "UPDATE", 
  symbol = "InterestingBasket",
  holidays = holidays
)

Utilities

AllActiveCustomInstruments <- rd_SearchCustomInstruments()
RealInstrumentName <- CorrectCustomInstrument("InterestingBasket")

DataStream

DatastreamUserName <- "Your datastream username"
DatastreamPassword <- "Your datastream password"
DataStream <- DataStreamConnect(DatastreamUserName, DatastreamPassword)

DSResult <- DataStream$snapshotRequest(
  instrument = c("ABF", "RIO", "WPP"),
  datatype = "P",
  requestDate = "0D"
)

For further details, see DatastreamDSWS2R.


Caching

All data retrieval functions support opt-in session-scoped caching to avoid redundant API calls:

# Enable caching globally (uses per-function default TTLs, typically 300 s)
options(refinitiv_cache = TRUE)

# Or enable per call
rd_GetData(rics = "AAPL.O", Eikonformulas = "TR.CompanyName", cache = TRUE)

# Custom TTL (seconds)
rd_GetHistory(universe = "AAPL.O", cache = 600)

# Inspect and clear
rd_CacheInfo()
rd_ClearCache()

Caching is purely in-memory and scoped to the current R session — restarting R or calling rd_ClearCache() wipes all cached results.


Progress Reporting

Multi-chunk requests (large instrument universes, multi-query news, etc.) automatically show compact progress messages:

[RefinitivR] 500 instruments, 500 data points, 3 chunks
[RefinitivR] EikonGetData: Chunk 1/3 done (167 items, 0.3s)
[RefinitivR] EikonGetData: Chunk 2/3 done (167 items, 0.3s)
[RefinitivR] EikonGetData: Chunk 3/3 done (166 items, 0.3s)
[RefinitivR] EikonGetData: Download complete: 3/3 chunks succeeded in 2.5s

Single-instrument requests stay silent (one-chunk rule). Server-side polling and retriable errors always report status regardless of mode.

Control progress output with options(refinitiv_progress = ...) or the REFINITIV_PROGRESS environment variable in .Renviron:

Value Behavior
TRUE (default) Compact progress for multi-chunk requests
FALSE Silent
"verbose" Compact progress + full debug dumps
# Disable globally
options(refinitiv_progress = FALSE)

# Or per-call
rd_GetData(rics = large_universe, Eikonformulas = fields, verbose = FALSE)

# Or via .Renviron (read at package load)
# REFINITIV_PROGRESS=FALSE

All output uses message(), so suppressMessages() works as expected.


Building Custom Visualizations

The streaming API provides several ways to build custom visualizations:

Using Built-in plot_live()

stream <- rd_get_streaming_data(universe = "EUR=", fields = c("BID", "ASK"))
stream$open()

app <- stream$plot_live(field = "BID", instrument = "EUR=")
shiny::runApp(app)

Custom Shiny App

library(shiny)
library(Refinitiv)

stream <- rd_get_streaming_data(universe = "EUR=", fields = c("BID", "ASK"))
stream$open()

ui <- fluidPage(
  titlePanel("Custom Live Stream"),
  plotOutput("live_plot"),
  verbatimTextOutput("stats")
)

server <- function(input, output, session) {
  output$live_plot <- renderPlot({
    invalidateLater(1000, session)
    history <- stream$get_data_history()
    if (nrow(history) > 0) {
      plot(history$timestamp, history$BID, 
           type = "l", xlab = "Time", ylab = "BID",
           main = "EUR/USD Bid Price")
    }
  })
  
  output$stats <- renderText({
    latest <- stream$get_latest_data("EUR=")
    paste("Latest BID:", latest$BID)
  })
}

shinyApp(ui, server)

Static Plots with ggplot2

library(ggplot2)

stream <- rd_get_streaming_data(universe = "EUR=", fields = c("BID", "ASK"))
stream$open()
Sys.sleep(30)
stream$close()

history <- stream$get_data_history()

ggplot(history, aes(x = timestamp, y = BID)) +
  geom_line() +
  labs(title = "EUR/USD Bid Price Over Time",
       x = "Time", y = "BID Price") +
  theme_minimal()

Best Practices

  1. Always close streams when done to free resources
  2. Use callbacks for real-time updates instead of polling
  3. Filter history for large datasets before plotting
  4. Handle errors in callbacks to prevent crashes
  5. Use later::run_now() in long-running scripts to process events

Examples

Example scripts are included in the package:

list.files(system.file("examples", package = "Refinitiv"))
source(system.file("examples", "streaming_quick_example.R", package = "Refinitiv"))

License

See LICENSE file.


Acknowledgments

  • Uses DatastreamDSWS2R for DataStream connections
  • Built for stability and robustness with automatic retries and chunking

About

an R interface to Refinitv Eikon and Refinitiv DataStream

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages