Getting historical data from the IB API in R
A simple tutorial how to get historical data from the Interactive Brokers API, using package rib.
Load and attach the package first. We also fix set option
warn
to 1, so that any warning message is shown at once.
options(warn = 1) ## show warnings at once library("rib")
The main task is to define a wrapper that handles the incoming messages. For historical data, we do not need much:
wrap <- R6::R6Class("IBWrapCustom", class = FALSE, cloneable = FALSE, lock_class = TRUE, inherit = rib::IBWrap, public = list( Data = NULL, initialize = function() { self$Data <- new.env() self$Data$HistData <- list() }, error = function(id, errorCode, errorString, advancedOrderRejectJson) { ## errors and other messages are shown message(errorString) }, nextValidId = function(orderId) NULL, ## data is ignored managedAccounts = function(accountsList) NULL, ## data is ignored historicalData= function(reqId, bar) { self$Data$HistData[[reqId]] <- bar message("done") TRUE } ) )
Create an instance of the wrapper.
wr <- wrap$new()
We define a contract (see Finding the contract specification).
contr <- IBContract(localSymbol = "SAP", exchange = "IBIS", secType = "STK", currency = "EUR")
Now we have the ingredients. It remains to get the data. Create a client.
ic <- IBClient$new()
ic$connect(port = 7496, clientId = 1)
ic$checkMsg(wr)
server version: 180 timestamp: 20231130 17:54:37 CET Market data farm connection is OK:... ## .... and more messages
Now we have the client request historical data. When done, we disconnect.
reqId <- 1 ic$reqHistoricalData(tickerId = reqId, contr, endDateTime = "", barSizeSetting = "30 secs", durationStr = "1 D", useRTH = FALSE, whatToShow = "TRADES", formatDate = 2, keepUpToDate = FALSE) ## 'historicalData' returns TRUE when it received data done <- FALSE while (!done) { Sys.sleep(.5) done <- ic$checkMsg(wr) } ic$disconnect()
done
Extract and check the data.
data <- wr$Data$HistData[[reqId]]
str(data)
'data.frame': 1050 obs. of 8 variables: $ time : chr "1701331200" "1701331230" "1701331260" ... $ open : num 145 145 145 146 146 ... $ high : num 145 145 146 146 146 ... $ low : num 145 145 145 146 146 ... $ close : num 145 145 146 146 146 ... $ volume: num 127081 12810 12708 6009 300 ... $ wap : num 145 145 145 146 146 ... $ count : int 140 49 37 34 2 7 9 12 6 13 ...
Transform the timestamp.
data[["time"]] <- .POSIXct(as.numeric(data[["time"]])) str(data)
'data.frame': 1050 obs. of 8 variables: $ time : POSIXct, format: "2023-11-30 09:00:00" ... $ open : num 145 145 145 146 146 ... $ high : num 145 145 146 146 146 ... $ low : num 145 145 145 146 146 ... $ close : num 145 145 146 146 146 ... $ volume: num 127081 12810 12708 6009 300 ... $ wap : num 145 145 145 146 146 ... $ count : int 140 49 37 34 2 7 9 12 6 13 ...
And a check.
library("IButils") ib_hist_data(Symbol = "SAP", Exchange = "IBIS", Currency = "EUR", Security_Type = "STK", barSize = "30 secs", durationStr = "1 D", whatToShow = "TRADES", start = as.POSIXct("2023-11-30 09:00:00"), directory = tempdir(), accumulate = TRUE)
timestamp open high low close volume vwap count 2023-11-30 09:00:00 1701331200 145.00 145.26 144.60 145.12 127081 145.000 140 2023-11-30 09:00:30 1701331230 145.22 145.48 145.08 145.32 12810 145.255 49 2023-11-30 09:01:00 1701331260 145.36 145.58 145.36 145.58 12708 145.493 37 2023-11-30 09:01:30 1701331290 145.60 145.70 145.54 145.62 6009 145.623 34 2023-11-30 09:02:00 1701331320 145.64 145.64 145.62 145.62 300 145.639 2 2023-11-30 09:02:30 1701331350 145.66 145.66 145.60 145.60 675 145.618 7 ## ....