IBrokers reqMktData,如何为回调函数添加超时?

时间:2013-02-26 18:50:40

标签: r ibrokers

我一直在使用来自伟大的IBrokers软件包的改进的snapShot功能来获得IB的“最后”价格,并且它一直非常适合流动性股票。 我做的电话是例如。

reqMktData(tws, twsSTK("AAPL"), eventWrapper=eWrapper.data.Last(1),CALLBACK=snapShot)

在尝试检索非流动性股票或期权时出现问题。因此,我需要为snapShot函数添加超时。如何以及在何处添加超时?

使用snapShot函数的代码:

library(IBrokers)
tws <- twsConnect()

eWrapper.data.Last <- function(n) {
  eW <- eWrapper(NULL)  # use basic template
  eW$assign.Data("data", rep(list(structure(.xts(matrix(rep(NA_real_,2),nc=2),0),
                                      .Dimnames=list(NULL,c("LastSize","Last")))),n))

  eW$tickPrice <- function(curMsg, msg, timestamp, file, ...) 
  {
    tickType = msg[3]
    msg <- as.numeric(msg)
    id <- msg[2] #as.numeric(msg[2])
    data <- eW$get.Data("data") #[[1]]  # list position of symbol (by id == msg[2])
    attr(data[[id]],"index") <- as.numeric(Sys.time())
    nr.data <- NROW(data[[id]])
    if(tickType == .twsTickType$LAST) {
      data[[id]][nr.data,2] <- 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 <- as.numeric(msg[2])
    attr(data[[id]],"index") <- as.numeric(Sys.time())
    nr.data <- NROW(data[[id]])
    if(tickType == .twsTickType$LAST_SIZE) {
      data[[id]][nr.data,1] <- msg[4]
    } 
    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]]
   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))
           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.na)))
               return(do.call(rbind, lapply(eWrapper$.Data$data,
                 as.data.frame)))
       }
   }
}

1 个答案:

答案 0 :(得分:4)

您可以使用R.utils中的evalWithTimeout。我没有测试它,但我很确定在while循环周围包裹evalWithTimeout会实现你所追求的目标。

library(R.utils)

evalWithTimeout(
   while (TRUE) {
       socketSelect(list(con), FALSE, NULL)
       curMsg <- .Internal(readBin(con, "character", 1L,
           NA_integer_, TRUE, FALSE))
       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.na)))
           return(do.call(rbind, lapply(eWrapper$.Data$data,
             as.data.frame)))
   }, timeout=5, onTimeout="warning")