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
## ....