R IBrokers reqopenorders 未更新

发布于 2025-01-13 18:40:38 字数 4013 浏览 4 评论 0原文

我正在使用 IBrokers 包中的代码查询 TWS Interactive Brokers 中的挂单列表。

函数 reqOpenOrders(tws) 有一个错误,它挂起,如此处所示,即使它有效,输出也很混乱,如图所示此处

我将来自不同来源的一些代码放在一起,以创建一个清晰/逻辑易于理解的函数,同时输出结果的 data.frame。

功能如下,第一次使用效果很好。但是,当在 TWS 中进行更改时(例如取消挂单或下追踪订单),如果在 R 中运行以下函数,则更改不会更新。

如果我关闭并再次打开与 TWS 的连接,我会得到运行下面的函数后会出现一个空的 data.frame。如果我关闭所有连接并多次尝试该函数,最终它会返回更新的结果。

有谁知道为什么调用该函数不会查询TWS中最新的更改?

我认为这与 R 与 TWS 的连接有关。该函数似乎等待连接最终变得可用。如果我重新启动 R,第一次运行该函数时,结果会更新,这表明如果所有连接都恢复,该函数可以正常运行。对这个问题有什么建议吗?

我想知道退出函数后是否需要关闭所有套接字和连接?我尝试了该解决方案的不同版本,但没有成功。

非常感谢任何帮助。

library(IBrokers)

Get.Open.Orders<- function(tws)
{
library(dplyr)
Open.Orders <- function(tws)
  {
   con <- tws[[1]] #connector used to communicate with TWS
   VERSION <- "1"
   writeBin(c(.twsOutgoingMSG$REQ_OPEN_ORDERS, VERSION), con) #send request for open orders
   eW  <- eWrapper()                         #Creates a custom function to get the data that was requested
   socketSelect(list(con), FALSE, NULL)      #Wait for first socket connection to become available
   curMsg <- readBin(con, character(), 1L)   #read the response received from IB            
   processMsg(curMsg, con, eW)               #Process message 
 }

#orginize the data recieved into a data.frame, selects only  set of vaiables received.
open <- data.frame()
 i <- 0
   while(i < 2)
   {
     x <- Open.Orders(tws)
       if(!is.null(x) && x[1] == 53) # OPEN_ORDER_END
       {i = i + 1 } else if(!is.null(x) && x[1] == 5) # For Open Orders
         {
           x <- data.frame(t(x), stringsAsFactors = FALSE)
           open <- bind_rows(open, x)
         }
     rm(x)
   }

if(nrow(open) > 0)
{
 open <- open %>% distinct() %>%
   rename(conId = X4, symbol = X5, sectype = X6, strike = X10,
         currency = X11, action = X13, totalQuantity = X14,
         orderType = X15, lmtPrice = X16, auxPrice = X17,
         tif = X18, outsideRTH = X19, account = X20, orderId = X25, Status = X77
  ) %>%
  select(account, orderId, conId, symbol, sectype, strike, currency,
         action, totalQuantity, orderType, lmtPrice, auxPrice, tif, Status) %>%
  mutate(orderId = as.integer(orderId)
         , totalQuantity = as.numeric(totalQuantity)
         , lmtPrice = as.numeric(lmtPrice)
         , auxPrice = as.numeric(auxPrice) )
} else
{
open <- data.frame(account = character()
                   , orderId = integer()
                   , conId = character()
                   , symbol = character()
                   , sectype = character()
                   , strike = character()
                   , currency = character()
                   , action = character()
                   , totalQuantity = numeric()
                   , orderType = character()
                   , lmtPrice = numeric()
                   , auxPrice = numeric()
                   , tif = character()
                   , Status = character()
                   , stringsAsFactors = FALSE)
 }

 assign("IB.open.orders", open, envir = .GlobalEnv)
 rm(i, Open.Orders, open)
 return(data.frame(IB.open.orders))
 }


 #now connect to IB and get active orders; it works fine first time
 tws = twsConnect()
 Get.Open.Orders (tws)

 # now go to TWS and delete any given pending order for the sake of an example. Then in R run function again to request pending orders
Get.Open.Orders (tws)

#The change in TWS is now reflected in the output, so I disconnect TWS, and connect again

twsDisconnect(tws)  #disconned TWS
tws = twsConnect()  #connect to TWS
Get.Open.Orders (tws)

#the result is an empty dataframe. If I run the three lines of code above...say 10 times, eventually the updated results are returned.

showConnections(all = TRUE)
closeAllConnections()
tws = twsConnect()
Get.Open.Orders (tws)

I am querying the list of pending orders in TWS Interactive Brokers using codes from the IBrokers package.

The function reqOpenOrders(tws) has an error in it, in that it hangs as shown here, and even when it works the outputs are messy as shown here.

I have put together some snipes of code from different sources to create a function that is clear/logical to understand, while outputting a data.frame of the results.

The function is below, and it works well the first time that is used. However, when a change is done in TWS (like cancelling a pending order, or placing a trail order), the change is not updated if the function below is run in R.

If I close and open again the connection to TWS, I get a empty data.frame after running the function below. if I close all connections and try the function several times eventually it returns the updated results.

Does any one know why calling the function does not query the most updated changes in TWS?

I think it has something to do with R connectivity to TWS. It seems the function waits for the connection to eventually become available. If I restart R, the first time I run the function, the results are updated, suggesting that if all connections are restored the function works well. Any suggestion to this problem?

I wonder if all sockets and connections need to be closed after exiting the function? I tried different versions to this solution with no success.

Any help is greatly appreciated.

library(IBrokers)

Get.Open.Orders<- function(tws)
{
library(dplyr)
Open.Orders <- function(tws)
  {
   con <- tws[[1]] #connector used to communicate with TWS
   VERSION <- "1"
   writeBin(c(.twsOutgoingMSG$REQ_OPEN_ORDERS, VERSION), con) #send request for open orders
   eW  <- eWrapper()                         #Creates a custom function to get the data that was requested
   socketSelect(list(con), FALSE, NULL)      #Wait for first socket connection to become available
   curMsg <- readBin(con, character(), 1L)   #read the response received from IB            
   processMsg(curMsg, con, eW)               #Process message 
 }

#orginize the data recieved into a data.frame, selects only  set of vaiables received.
open <- data.frame()
 i <- 0
   while(i < 2)
   {
     x <- Open.Orders(tws)
       if(!is.null(x) && x[1] == 53) # OPEN_ORDER_END
       {i = i + 1 } else if(!is.null(x) && x[1] == 5) # For Open Orders
         {
           x <- data.frame(t(x), stringsAsFactors = FALSE)
           open <- bind_rows(open, x)
         }
     rm(x)
   }

if(nrow(open) > 0)
{
 open <- open %>% distinct() %>%
   rename(conId = X4, symbol = X5, sectype = X6, strike = X10,
         currency = X11, action = X13, totalQuantity = X14,
         orderType = X15, lmtPrice = X16, auxPrice = X17,
         tif = X18, outsideRTH = X19, account = X20, orderId = X25, Status = X77
  ) %>%
  select(account, orderId, conId, symbol, sectype, strike, currency,
         action, totalQuantity, orderType, lmtPrice, auxPrice, tif, Status) %>%
  mutate(orderId = as.integer(orderId)
         , totalQuantity = as.numeric(totalQuantity)
         , lmtPrice = as.numeric(lmtPrice)
         , auxPrice = as.numeric(auxPrice) )
} else
{
open <- data.frame(account = character()
                   , orderId = integer()
                   , conId = character()
                   , symbol = character()
                   , sectype = character()
                   , strike = character()
                   , currency = character()
                   , action = character()
                   , totalQuantity = numeric()
                   , orderType = character()
                   , lmtPrice = numeric()
                   , auxPrice = numeric()
                   , tif = character()
                   , Status = character()
                   , stringsAsFactors = FALSE)
 }

 assign("IB.open.orders", open, envir = .GlobalEnv)
 rm(i, Open.Orders, open)
 return(data.frame(IB.open.orders))
 }


 #now connect to IB and get active orders; it works fine first time
 tws = twsConnect()
 Get.Open.Orders (tws)

 # now go to TWS and delete any given pending order for the sake of an example. Then in R run function again to request pending orders
Get.Open.Orders (tws)

#The change in TWS is now reflected in the output, so I disconnect TWS, and connect again

twsDisconnect(tws)  #disconned TWS
tws = twsConnect()  #connect to TWS
Get.Open.Orders (tws)

#the result is an empty dataframe. If I run the three lines of code above...say 10 times, eventually the updated results are returned.

showConnections(all = TRUE)
closeAllConnections()
tws = twsConnect()
Get.Open.Orders (tws)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半夏半凉 2025-01-20 18:40:38

这可能不是最好的解决方案,但我找到了一种从 TWS 获取未结订单的最新数据的方法。上面的原始功能似乎只有在使用正确的连接时才起作用。在两次尝试之间,它返回一个空的 data.frame。因此,我所做的就是创建一个 while 循环,将查询发送到 TWS,直到使用正确的连接。代码如下。它可以工作并在几次尝试后返回正确的数据。我想我分享代码作为临时解决方案。

tws = twsConnect()

#Current pending orders
  OpenOrders=Get.Open.Orders (tws)
  showConnections(all = TRUE)    
  nOP=nrow(OpenOrders)

while (nOP==0){
  tws = twsConnect()
  OpenOrders=Get.Open.Orders (tws)  
  nOP=nrow(OpenOrders)
  quiet = TRUE
}

This is probably not the best solution, but I found a way around getting the most updated data on open orders from TWS. The original function above seems to work only when the right connection is used. In between tries, it returns an empty data.frame. So what I did was to create a while loop that sends queries to TWS until the right connection is used. The code is below. It works and returns the right data after a handful of attempts. I figure I share the code as a temporary solution.

tws = twsConnect()

#Current pending orders
  OpenOrders=Get.Open.Orders (tws)
  showConnections(all = TRUE)    
  nOP=nrow(OpenOrders)

while (nOP==0){
  tws = twsConnect()
  OpenOrders=Get.Open.Orders (tws)  
  nOP=nrow(OpenOrders)
  quiet = TRUE
}
我恋#小黄人 2025-01-20 18:40:38

这实际上是对上面唯一答案的评论,但我以前也这样做过循环,直到我意识到每个订单实际上都将客户名称和 reqID 附加到每个订单,所以我开始跟踪它们,然后我可以访问任何通过创建新客户端(使用旧客户端 ID)并使用 reqID 引用长期订单,然后在从函数返回结果之前关闭并销毁客户端,从函数环境内部进行订单。

因此,我将使用这样的代码作为括号订单的止盈部分:

  tporder <-
      placeOrder(
        mainclient,
        contract,
        bracketaction,
        abs(adj_quantity),
        transmit = T,
        orderType = "LMT",
        limitPrice = tpp,
        tif = tif,
        stopPrice = "0.0",
        ocaGroup = ocaGroup,
        ocaType = ocaType,
        trigger = tp_trigger,
        stf = stf
      )
    
    print(mainclient$clientId)
    tporder$clientid <- mainclient$clientId

然后稍后取消订单,我将使用这样的代码:

if (exists("tp_data")) {
  if (tp_data[1] != "NO ORDER") {
    # first check if the order is attached to current client
    cancelOrder(current_client, tp_data$order_id)
    
    # if it's not then this code would create a new client
    # and cancel the order
    cancel_con <- connectToIB(tp_data$clientid)
    cancelOrder(cancel_con, tp_data$order_id)
    twsDisconnect(cancel_con)
    print("Take Profit Order Cancelled")
  }
}

现有的答案对我不起作用,因为我的机器人连续运行并且很多时候我需要刷新连接,而当前客户端与设置顺序的原始客户端不同。我必须根据时间戳随机分配 clientId。另外,我交易不同的资产类别,因此我对列名称的分配略有不同。因此,对于手头的具体问题,我的实现可能看起来更像这样:

   library(IBrokers)
   library(dplyr)



connectToIB <-
    function(clientId = 1,
             host = "localhost",
             port = Sys.getenv("TWS_PORT")) {
      # Create a socket connection
      tws <- twsConnect(clientId = clientId,
                        host = host,
                        port = port)
      
      # Check if the connection was successful
      if (!is.null(tws)) {
        cat("Connected to Interactive Brokers TWS API\n")
        return(tws)
      } else {
        cat("Failed to connect to Interactive Brokers TWS API\n")
        return(NULL)
      }
    }
    
    openOrders <- function(tws_con) {
      con <- tws_con[[1]] #connector used to communicate with TWS
      VERSION <- "1"
      writeBin(c(.twsOutgoingMSG$REQ_OPEN_ORDERS, VERSION), con) #send request for open orders
      eW  <- eWrapper()                         #Creates a custom function to get the data that was requested
      socketSelect(list(con), FALSE, NULL)      #Wait for first socket connection to become available
      curMsg <- readBin(con, character(), 1L)   #read the response received from IB
      processMsg(curMsg, con, eW)               #Process message
    }
    
    getOpenOrders <- function(tws_con) {
      #orginize the data recieved into a data.frame, selects only  set of vaiables received.
      open <- data.frame()
      i <- 0
      while (i < 2) {
        x <- openOrders(tws_con)
        if (!is.null(x) && x[1] == 53)
          # OPEN_ORDER_END
        {
          i = i + 1
        } else if (!is.null(x) && x[1] == 5)
          # For Open Orders
        {
          x <- data.frame(t(x), stringsAsFactors = FALSE)
          open <- bind_rows(open, x)
        }
        rm(x)
      }
      
      if (nrow(open) > 0) {
        open <- data.frame(
          open %>% distinct() %>%
            rename(
              conId = X4,
              symbol = X5,
              sectype = X6,
              multiplier = X10,
              exchange = X11,
              currency = X12,
              instrName = X13,
              tradingClass = X14,
              action = X15,
              totalQuantity = X16,
              orderType = X17,
              lmtPrice = X18,
              strike = X19,
              tif = X20,
              account = X21,
              orderId = X25,
              status = X94
            ) %>%
            select(
              account,
              orderId,
              conId,
              symbol,
              sectype,
              strike,
              currency,
              exchange,
              action,
              totalQuantity,
              multiplier,
              orderType,
              lmtPrice,
              instrName,
              tradingClass,
              tif,
              status
            ) %>%
            mutate(
              orderId = as.integer(orderId),
              totalQuantity = as.integer(totalQuantity),
              lmtPrice = as.numeric(lmtPrice)
            )
        )
      } else
      {
        open <- "NO ORDER"
      }
      
      return(open)
    }
    
new_con <- connectToIB(tp_data$clientid)
    
getOpenOrders(new_con)

twsDisconnect(new_con)

This is really a comment to the only answer above, but I used to also do this looping thing until I realized that each order actually attaches the client name and reqID to each order, so I started keeping track of them and then I can access any order from inside the environment of a function by creating a new client (using the old client ID) and reference the standing order using the reqID, and then closing and trashing the client before returning results from the function.

So I'll use code like this for the take profit portion of a bracket order:

  tporder <-
      placeOrder(
        mainclient,
        contract,
        bracketaction,
        abs(adj_quantity),
        transmit = T,
        orderType = "LMT",
        limitPrice = tpp,
        tif = tif,
        stopPrice = "0.0",
        ocaGroup = ocaGroup,
        ocaType = ocaType,
        trigger = tp_trigger,
        stf = stf
      )
    
    print(mainclient$clientId)
    tporder$clientid <- mainclient$clientId

And then later to cancel the order, I'll use code like this:

if (exists("tp_data")) {
  if (tp_data[1] != "NO ORDER") {
    # first check if the order is attached to current client
    cancelOrder(current_client, tp_data$order_id)
    
    # if it's not then this code would create a new client
    # and cancel the order
    cancel_con <- connectToIB(tp_data$clientid)
    cancelOrder(cancel_con, tp_data$order_id)
    twsDisconnect(cancel_con)
    print("Take Profit Order Cancelled")
  }
}

The existing answer wouldn't work for me, because my bot runs continuously and often times I need to refresh my connection and the current client is not the same as the original client that set the order. I have to randomly assign clientId's based on time stamps. Also I trade a different asset class, so my assignment of column names is slightly different. So for the specific question at hand, my implementation might look something more like this:

   library(IBrokers)
   library(dplyr)



connectToIB <-
    function(clientId = 1,
             host = "localhost",
             port = Sys.getenv("TWS_PORT")) {
      # Create a socket connection
      tws <- twsConnect(clientId = clientId,
                        host = host,
                        port = port)
      
      # Check if the connection was successful
      if (!is.null(tws)) {
        cat("Connected to Interactive Brokers TWS API\n")
        return(tws)
      } else {
        cat("Failed to connect to Interactive Brokers TWS API\n")
        return(NULL)
      }
    }
    
    openOrders <- function(tws_con) {
      con <- tws_con[[1]] #connector used to communicate with TWS
      VERSION <- "1"
      writeBin(c(.twsOutgoingMSG$REQ_OPEN_ORDERS, VERSION), con) #send request for open orders
      eW  <- eWrapper()                         #Creates a custom function to get the data that was requested
      socketSelect(list(con), FALSE, NULL)      #Wait for first socket connection to become available
      curMsg <- readBin(con, character(), 1L)   #read the response received from IB
      processMsg(curMsg, con, eW)               #Process message
    }
    
    getOpenOrders <- function(tws_con) {
      #orginize the data recieved into a data.frame, selects only  set of vaiables received.
      open <- data.frame()
      i <- 0
      while (i < 2) {
        x <- openOrders(tws_con)
        if (!is.null(x) && x[1] == 53)
          # OPEN_ORDER_END
        {
          i = i + 1
        } else if (!is.null(x) && x[1] == 5)
          # For Open Orders
        {
          x <- data.frame(t(x), stringsAsFactors = FALSE)
          open <- bind_rows(open, x)
        }
        rm(x)
      }
      
      if (nrow(open) > 0) {
        open <- data.frame(
          open %>% distinct() %>%
            rename(
              conId = X4,
              symbol = X5,
              sectype = X6,
              multiplier = X10,
              exchange = X11,
              currency = X12,
              instrName = X13,
              tradingClass = X14,
              action = X15,
              totalQuantity = X16,
              orderType = X17,
              lmtPrice = X18,
              strike = X19,
              tif = X20,
              account = X21,
              orderId = X25,
              status = X94
            ) %>%
            select(
              account,
              orderId,
              conId,
              symbol,
              sectype,
              strike,
              currency,
              exchange,
              action,
              totalQuantity,
              multiplier,
              orderType,
              lmtPrice,
              instrName,
              tradingClass,
              tif,
              status
            ) %>%
            mutate(
              orderId = as.integer(orderId),
              totalQuantity = as.integer(totalQuantity),
              lmtPrice = as.numeric(lmtPrice)
            )
        )
      } else
      {
        open <- "NO ORDER"
      }
      
      return(open)
    }
    
new_con <- connectToIB(tp_data$clientid)
    
getOpenOrders(new_con)

twsDisconnect(new_con)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文