GithubHelp home page GithubHelp logo

herrold / rib Goto Github PK

View Code? Open in Web Editor NEW

This project forked from lbilli/rib

0.0 1.0 0.0 68 KB

An R implementation of Interactive Brokers API

License: GNU General Public License v3.0

R 100.00%

rib's Introduction

rib

An R implementation of Interactive Brokers API

Originally inspired by IBrokers, rib is a native R client that implements Interactive Brokers API to communicate with their TWS or IBGateway.

It aims to be feature complete, though it does not support legacy versions: i.e. only API versions v100 and above are currently supported. This limit may become even stricter in the future.

The package design mirrors the official C++/Java IB API, which is based on an asynchronous request-response communication model over a TCP socket.

Installation

To install from GitHub, assuming devtools or at least remotes is already installed:

remotes::install_github("lbilli/rib")

Usage

The user interacts mainly with two classes, implemented here as R6 objects:

  • IBClient: responsible to establish the connection and send requests to the server.
  • IBWrap: base class holding the callbacks that are executed when the client processes the responses. Customized versions are derived from this class.

Other data structures, such as Contract and Order, are implemented as R lists, or nested lists, and mirror the respective classes in the official IB API.

A complete minimal working example is shown. For this code to work, an instance of the IB TWS or IBGateway needs to be running on the local machine, listening on port 4002. Note: demo or paper account recommended!! ๐Ÿ˜

library(rib)

# Define a customized callbacks wrapper
IBWrapCustom <- R6::R6Class("IBWrapCustom",
  class=      FALSE,
  cloneable=  FALSE,
  lock_class= TRUE,

  inherit= IBWrap,

  public= list(
    # Customized methods
    connectAck=       function() {},

    connectionClosed= function() cat("Connection Closed.\n"),

    error=            function(id, errorCode, errorString) cat(id, errorCode, errorString, "\n"),

    nextValidId=      function(orderId) cat("Next OrderId:", orderId, "\n"),

    managedAccounts=  function(accountsList) cat("Managed Accounts:", accountsList, "\n")
  )
)

# Instantiate wrapper and client
wrap <- IBWrapCustom$new()
ic   <- IBClient$new(wrap)

# Connect to the server with clientId = 1
ic$connect(port=4002, clientId=1)

# Check connection messages (optional)
ic$checkMsg()

# Define contract
contract <- IBContract("GOOG")

# Define order
order <- IBOrder("BUY", 10, "LMT", 1000)

orderId <- 1    # Should match whatever is returned by the server

# Send order
ic$placeOrder(orderId, contract, order)

# Check messages
ic$checkMsg()

# Disconnect
ic$disconnect()

As R is single threaded, in general it is the user's responsability to code an event loop that handles the request-response pattern: i.e. there is no Reader in the background monitoring the connection and processing the server responses.

Two possible approaches, with or without a loop, are described:

Straight Request-Response pattern. No loop.

This is the simplest case. Not suitable for data subscriptions or whenever a stream of messages is expected. It follows the pattern:

  • connect
  • send requests
  • process responses
  • disconnect
library(rib)

# Instantiate wrapper, client and connect
wrap <- IBWrapSimple$new()
ic   <- IBClient$new(wrap)
ic$connect(port=4002, clientId=1)

# Send requests, e.g.:
contract <- IBContract("GOOG")
ic$reqContractDetails(11, contract)

# more requests can go here...

# Parse responses.
# Might need to be called several times to process all messages
ic$checkMsg(2)

# Find results in
wrap$context

# Disconnect
ic$disconnect()
Request-Response loop

A more realistic application requires a loop around the previous example:

  • connect
  • repeat
    • send requests
    • process responses
    • if done exit
  • disconnect
library(rib)

# Instantiate wrapper, client and connect
wrap <- IBWrapSimple$new()
ic   <- IBClient$new(wrap)
ic$connect(port=4002, clientId=1)

# Main loop
repeat {

  # Application logic goes here
  # e.g.: send request
  ic$reqContractDetails(...)

  # Wait and process responses
  ic$checkMsg(2)

  if(done)
    break

  # It is convenient to have a little wait here
  Sys.sleep(1)
}

# Disconnect
ic$disconnect()

Implementation Details

This implements the IB EClient class functionality. Among its methods:

  • new(wrap): constructor. Require an object derived from IBWrap as argument.
  • replaceWrap(wrap): replace the wrap. As the client runs in a single thread, it is possible to replace the set of callbacks in a connected client.
  • connect(host, port, clientId, connectOptions): establish a connection.
  • disconnect(): close the connection.
  • checkMsg(timeout): wait for responses and dispatch callbacks. If no response is available, it blocks up to timeout seconds. Return the number of responses processed. Needs to be called regularly.
  • flush(): flush unprocessed responses, without dispatching callbacks. Mostly for debugging or testing.
  • all other methods that send specific requests to the server. Refer to the official IB EClient class documentation for details and method signatures.

Like the official IB EWrapper class, this holds the callbacks that are dispatched when responses are processed. IBWrap itself is a base class containing only dummy methods. Users need to derive from it and override the desired methods. The code above provides a quick view of the procedure.

For a more extensive example, refer to the definition of IBWrapSimple, which is provided for illustrative purposes and which prints out the content of the responses or store it within IBWrapSimple$context for later inspection.

For more details about callback definitions and signatures, refer again to the official IB EWrapper class documentation.

Notes

Callbacks are generally invoked with arguments and types matching the signatures as described in the official documentation. However, there are few notable exceptions:

  • tickPrice() has an extra size argument, which is meaningful only when TickType = {BID, ASK, LAST}. In these cases, the official IB API fires an extra tickSize() event instead.
  • historicalData() is invoked only once per request, presenting all the historical data as a single data.frame, whereas the official IB API invokes it row-by-row.
  • scannerData() is also invoked once per request and its arguments are in fact vectors rather than single values.

These modifications make it possible to establish the rule: one callback per server response.

As a corollary, historicalDataEnd() and scannerDataEnd() are redundant and thus are not used in this package.

data.frame structures are also used as arguments in several other callbacks, such as: softDollarTiers(), familyCodes(), mktDepthExchanges(), smartComponents(), newsProviders(), histogramData(), marketRule() and the historicalTicks*() family.

Data Structures

Other classes that mainly hold data are also defined. They are implemented as simple R (nested) lists with names, types and default values matching the IB API counterparts. Examples are: Contract, Order, ComboLeg, ExecutionFilter, ScannerSubscription and Condition.

To use them, simply make a copy and override their elements:

contract          <- Contract
contract$conId    <- 12345
contract$currency <- "USD"

In the case of Contract and Order, convenience functions are also provided to prefill some common fields:

contract <- IBContract("GOOG")

# Equivalent to
contract <- Contract
contract$symbol   <- "GOOG"
contract$secType  <- "STK"
contract$exchange <- "SMART"
contract$currency <- "USD"

and

order <- IBOrder(totalQuantity=100, lmtPrice=50)

# Equivalent to
order <- Order
order$action        <- "BUY"
order$totalQuantity <- 100
order$orderType     <- "LMT"
order$lmtPrice      <- 50

To instantiate a Condition, invoke fCondition(type) like this:

condition <- fCondition("Price")

TagValue types are implemented as R named character vectors:

# Wherever a TagValue is needed, something like this can be used:
c(tag1="value1", tag2="value2")

rib's People

Contributors

lbilli avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.