0

I am just starting to use the IBrokers package and I would like to know how to get out of the reqMktData function properly once tickGenerics is filled. Thank you for your answers. For instance:

library(IBrokers)
PATH <- ""
# initialize log file 
fnIB <- paste(PATH,"IBlog.csv",sep="")
if( file.exists(fnIB) )
  file.remove(fnIB)

tws <- twsConnect()
file.csv <- file(fnIB,open="wa")
reqMktData(tws, twsEquity("SPY", "SMART"),tickGenerics="456",file=file.csv)
close(file.csv)  
twsDisconnect(tws)
blueangel
  • 81
  • 4

2 Answers2

0

Thank you for the help. Here is the answer with the code where the snapShot function can be found there (It took me time to understand what was going and to set up an efficient debugging strategy...).

library(IBrokers)
tws <- twsConnect()
aaz <- reqMktData(tws,twsSTK("SPY"),tickGenerics="456",eventWrapper=eWrapper.mydata(1),CALLBACK=snapShot)
twsDisconnect(tws)

where

eWrapper.mydata <- function (n) 
{
eW <- eWrapper(NULL)
eW$assign.Data("data", rep(list(structure(.xts(matrix(rep(NA_real_, 
    9), ncol = 9), 0), .Dimnames = list(NULL, c("BidSize", 
    "BidPrice", "AskPrice", "AskSize", "Last", "LastSize", 
    "Volume","Ex-Date","Amount")))), n))
eW$tickPrice <- function(curMsg, msg, timestamp, file, ...) {
    tickType = msg[3]
    msg <- as.numeric(msg)
    id <- msg[2]
    data <- eW$get.Data("data")
    attr(data[[id]], "index") <- as.numeric(Sys.time())
    nr.data <- NROW(data[[id]])
    if (tickType == .twsTickType$BID) {
        data[[id]][nr.data, 1:2] <- msg[5:4]
    }
    else if (tickType == .twsTickType$ASK) {
        data[[id]][nr.data, 3:4] <- msg[4:5]
    }
    else if (tickType == .twsTickType$LAST) {
        data[[id]][nr.data, 5] <- msg[4]
    }
    eW$assign.Data("data", data)
    c(curMsg, msg)
  }
eW$tickSize <- function(curMsg, msg, timestamp, file, ...) {
    data <- eW$get.Data("data")
    tickType = msg[3]
    msg <- as.numeric(msg)
    id <- msg[2]
    attr(data[[id]], "index") <- as.numeric(Sys.time())
    nr.data <- NROW(data[[id]])
    if (tickType == .twsTickType$BID_SIZE) {
        data[[id]][nr.data, 1] <- msg[4]
    }
    else if (tickType == .twsTickType$ASK_SIZE) {
        data[[id]][nr.data, 4] <- msg[4]
    }
    else if (tickType == .twsTickType$LAST_SIZE) {
        data[[id]][nr.data, 6] <- msg[4]
    }
    else if (tickType == .twsTickType$VOLUME) {
        data[[id]][nr.data, 7] <- msg[4]
    }
    eW$assign.Data("data", data)
    c(curMsg, msg)
  }
eW$tickString <- function(curMsg, msg, timestamp, file, ...) {
   data <- eW$get.Data("data")
   tickType = msg[3]
   id <- as.numeric(msg[2])
   attr(data[[id]], "index") <- as.numeric(Sys.time())
   nr.data <- NROW(data[[id]])
   if (tickType == 59) {
     data[[id]][nr.data, 8:9] <- unlist(strsplit(msg[4],","))[3:4]
   }
   eW$assign.Data("data", data)
   c(curMsg, msg)
  }
return(eW)
}

For multiple tickers (see code below) it does not work because only one security gets the tickGenerics (which refers for "456" to the tickString function...) info.

nms <- c("LQD","JNK")
bbz <- reqMktData(tws,lapply(nms,twsSTK),tickGenerics="456",eventWrapper=eWrapper.mydata(length(nms)),CALLBACK=snapShot)
blueangel
  • 81
  • 4
0

To avoid NA fields provided by IB the "data" structure should be initialize with -1. Hence the following modifications:

is.negative <- function (x) {
tmp <- FALSE
if (is.numeric(x)) tmp <- (x<0)
return (tmp)
}

eWrapper.mydata <- function (n) 
{
eW <- eWrapper(NULL)
eW$assign.Data("data", rep(list(structure(.xts(matrix(rep(-1, 2), ncol = 2), 0), .Dimnames = list(NULL, c("Ex-Date","Amount")))), n))

eW$tickString <- function(curMsg, msg, timestamp, file, ...) {
   data <- eW$get.Data("data")
   tickType = msg[3]
   #print(paste("curMsg",curMsg,"tickString",tickType,sep=" "))
   #print(msg)
   id <- as.numeric(msg[2])
   attr(data[[id]], "index") <- as.numeric(Sys.time())
   nr.data <- NROW(data[[id]])
   if (tickType == 59) {
     data[[id]][nr.data, 1:2] <- unlist(strsplit(msg[4],","))[3:4]
   }
   #print(data)
   eW$assign.Data("data", data)
   c(curMsg, msg)
}
return(eW)
}

snapShot <- function (twsCon, eWrapper, timestamp, file, playback = 1, ...)
{
if (missing(eWrapper)) eWrapper <- eWrapper()
names(eWrapper$.Data$data) <- eWrapper$.Data$symbols
con <- twsCon[[1]]
# print("snapShot")
if (inherits(twsCon, "twsPlayback")) {
    sys.time <- NULL
    while (TRUE) {
        if (!is.null(timestamp)) {
            last.time <- sys.time
            sys.time <- as.POSIXct(strptime(paste(readBin(con,
              character(), 2), collapse = " "), timestamp))
            if (!is.null(last.time)) {
              Sys.sleep((sys.time - last.time) * playback)
            }
            curMsg <- .Internal(readBin(con, "character",
              1L, NA_integer_, TRUE, FALSE))
            if (length(curMsg) < 1)
              next
            processMsg(curMsg, con, eWrapper, format(sys.time,
              timestamp), file, ...)
        }
        else {
            curMsg <- readBin(con, character(), 1)
            if (length(curMsg) < 1)
              next
            processMsg(curMsg, con, eWrapper, timestamp,
              file, ...)
            if (curMsg == .twsIncomingMSG$REAL_TIME_BARS)
              Sys.sleep(5 * playback)
        }
    }
}
else {
    while (TRUE) {
        socketSelect(list(con), FALSE, NULL)
        curMsg <- .Internal(readBin(con, "character", 1L,NA_integer_, TRUE, FALSE))
        # print(paste("snapShot curMsg: ",curMsg,sep=""))
        if (!is.null(timestamp)) {
            processMsg(curMsg, con, eWrapper, format(Sys.time(),timestamp), file, ...)
        }
        else {
            processMsg(curMsg, con, eWrapper, timestamp,file, ...)
        }
        if (!any(sapply(eWrapper$.Data$data, is.negative)))
            return(do.call(rbind, lapply(eWrapper$.Data$data, as.data.frame)))
    }
}
}
blueangel
  • 81
  • 4