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 data —
rd_GetData(),rd_GetHistory(),rd_GetHistoricalPricing() - Real-time streaming — WebSocket-based live market data with callbacks
- ESG, estimates & ownership —
rd_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!
install.packages("devtools")
devtools::install_github("GreenGrassBlueOcean/RefinitivR")
library(Refinitiv)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"))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()- Connecting to LSEG Workspace
- Real-Time Streaming
- Working with Refinitiv Data (RD)
- Legacy Eikon Functions
- DataStream
- Custom Instruments
- Caching
- Progress Reporting
- Building Custom Visualizations
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.
The package includes a real-time streaming API for live market data using WebSocket connections.
# Required packages (installed automatically)
install.packages(c("websocket", "later", "shiny", "data.table"))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()stream <- rd_get_streaming_data(
universe = c("EUR=", "GBP=", "JPY="),
fields = c("BID", "ASK", "OPEN_PRC", "DSPLY_NAME")
)# 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)
})# 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=")app <- stream$plot_live(field = "BID", instrument = "EUR=")
shiny::runApp(app)# 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()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"))# 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
)# 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")
)ex1 <- rd_GetData(
rics = c("MMM", "III.L"),
Eikonformulas = c("TR.PE(Sdate=0D)/*P/E (LTM) - Diluted Excl*/",
"TR.CompanyName")
)# 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")
)The legacy Eikon* functions now also default to rd_connection(), so
no explicit connection is needed:
headlines <- EikonGetNewsHeadlines(query = "R:MSFT.O", count = 2)
stories <- EikonGetNewsStory(story_id = headlines$storyId)Timeseries <- EikonGetTimeseries(
rics = c("MMM", "III.L"),
start_date = "2020-01-01T01:00:00",
end_date = paste0(Sys.Date(), "T01:00:00")
)Data <- EikonGetData(
rics = c("MMM", "III.L"),
Eikonformulas = c("TR.PE(Sdate=0D)/*P/E (LTM) - Diluted Excl*/",
"TR.CompanyName")
)# Get UUID from Eikon Terminal: Help > About > User Details
RD <- RDConnect(UUID = "ABCDE-123456")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 <- 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
)AllActiveCustomInstruments <- rd_SearchCustomInstruments()
RealInstrumentName <- CorrectCustomInstrument("InterestingBasket")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.
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.
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=FALSEAll output uses message(), so suppressMessages() works as expected.
The streaming API provides several ways to build custom visualizations:
stream <- rd_get_streaming_data(universe = "EUR=", fields = c("BID", "ASK"))
stream$open()
app <- stream$plot_live(field = "BID", instrument = "EUR=")
shiny::runApp(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)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()- Always close streams when done to free resources
- Use callbacks for real-time updates instead of polling
- Filter history for large datasets before plotting
- Handle errors in callbacks to prevent crashes
- Use
later::run_now()in long-running scripts to process events
Example scripts are included in the package:
list.files(system.file("examples", package = "Refinitiv"))
source(system.file("examples", "streaming_quick_example.R", package = "Refinitiv"))See LICENSE file.
- Uses DatastreamDSWS2R for DataStream connections
- Built for stability and robustness with automatic retries and chunking