Skip to content

Commit

Permalink
add some more documentation to the README
Browse files Browse the repository at this point in the history
  • Loading branch information
cbilson committed Dec 20, 2012
1 parent 751343b commit e2d2734
Showing 1 changed file with 216 additions and 19 deletions.
235 changes: 216 additions & 19 deletions README.md
Expand Up @@ -6,25 +6,12 @@ A clojure friendly wrapper around the Interactive Brokers java API.

## Usage

I don't have permission to redistribute Interactive Broker's jars, so this is a little cludgey:
In project.clj:

1. Fetch the source code for ib-re-actor from github:

```bash
> git clone http://github.com/cbilson/ib-re-actor
```

2. Download the Interactive Brokers "IB API Software" from
http://individuals.interactivebrokers.com/en/p.php?f=programInterface&ib_entity=llc. Follow
the instructions to unpack it. Use maven to install the jtsclient.jar
with groupId 'com.ib', artifactId 'jtsclient', and version '9.68'. For me, this went like:

```bash
> cd ~/Downloads

> jar xf twsapi_unixmac_968.jar

> mvn install:install-file -Dfile=IBJts/jtsclient.jar -DgroupId=com.ib -DartifactId=jtsclient -Dversion=9.68 -Dpackaging=jar
```clojure
(project my.project "0.0.0"
:dependencies [[ib-re-actor "0.1.0"]]
...)
```

You can use ib-re-actor either with IB Trader Workstation or with IB
Expand All @@ -35,9 +22,212 @@ locally. It would be nice if there were a way to run the gateway
without X and without having to authenticate, but alas, that's not how
it works.

Since ib-re-actor is basically a wrapper around Interactive Brokers'
java API, [the documentation for that library][1] is often useful to have
around. It describes all the codes, order types, and the types of
errors you might get when using it.

## Examples

### historical-data-request
### Connecting

IB-React-or maintains a connection to the interactive brokers gateway
that you can share amongst many handler functions. To establish a connection:

```clojure
user> (connect)
#<Agent@3a33517f: nil>
```

In order to get called back when a message is received from the
gateway, use the subscribe function:

```clojure
user> (subscribe prn)
#<Agent@76115ae0: (#<core$prn clojure.core$prn@d1af848>)>
```

To see the callback in action, you can call something like
`request-current-time`. This sends a message to the gateway, then to
Interactive Broker servers, and eventually returns the current time to
our callback function via a :current-time message:

```clojure
user=> (request-current-time)
#<Agent@275997e4: #<EClientSocket com.ib.client.EClientSocket@5fd78173>>
user=> {:type :current-time, :value #<DateTime 2012-12-20T12:37:41.000Z>}
```

Note that the messages is rudely placed after your prompt (or if you
are using nrepl or swank in emacs, you won't see any response.) This
is because the message is dispatched on an agent thread. (If you are
using emacs, it's actually less rude, because your message will be
visible in the \*nrepl-server\* buffer, or whatever the equivalent is
in swank.)

To disconnect, simply call `disconnect`:

```clojure
user=> (disconnect)
#<Agent@275997e4: #<EClientSocket com.ib.client.EClientSocket@5fd78173>>
user=>
```

Any commands you issue after that will get back a "Not connected"
error message:

```clojure
user=> (disconnect)
#<Agent@275997e4: #<EClientSocket com.ib.client.EClientSocket@5fd78173>>
user=> (request-current-time)
#<Agent@275997e4: #<EClientSocket com.ib.client.EClientSocket@5fd78173>>
{:type :error, :request-id -1, :code 504, :message "Not connected"}
user=>
```

Note that there can be only one connection to the Interactive Brokers
gateway or TWS for a given client ID, so if you are writing an
application that makes multiple connections (from different
processes), you will want to come up with a way to keep the client IDs unique.

### Errors

Errors generally come back from the gateway in a message. They can be
request specific, in which case they will have a non-negative
`:request-id`, connection wide, in which case the `:request-id` will
be -1, and sometimes they may include an exception.

### Requesting Contract Information

All tradeable instruments are referred to as "contracts" in the
API documentation. Contracts are divided into a few types:

* :equity : stock, common stock, preferred stock
* :option : option contracts on stocks or other instruments
* :future : futures contracts on commodities
* :index : informational symbols, such as the value of the S&P
500. These are generally not tradeable, but you can use the
same API functions to get information about them as you
would for tradeable instruments.
* :future-option : options on futures contracts
* :cash, :bag: ???

When requesting information about the contract, you need to specify a
symbol to lookup. Your options are the `:symbol` key for the general
symbol, or `:local-symbol` for an exchange specific symbol. Generally,
you also want to specify an `:exchange`, and maybe a `:currency` as
well, unless you are not sure and want more results to look for.

```clojure
user> (request-contract-details {:symbol "AAPL" :type :equity})
6
user>
;;; many, many results
...
{:type :contract-details, :request-id 6, :value {:next-option-partial false, :time-zone-id "CTT", :underlying-contract-id 0, :price-magnifier 1, :industry "Technology", :trading-hours "20121220:0830-1500;20121221:0830-1500", :long-name "APPLE INC", :convertible? false, :subcategory "Computers", :liquid-hours "20121220:0830-1500;20121221:0830-1500", :callable? false, :order-types (:ACTIVETIM :ADJUST :ALERT :ALLOC :average-cost :basket :COND :CONDORDER :DAY :DEACT :DEACTDIS :DEACTEOD :good-after-time :good-till-canceled :good-till-date :GTT :HID :limit-if-touched :limit :market-if-touched :market :market-to-limit :NONALGO :one-cancels-all :scale :SCALERST :stop :stop-limit :trail :trailing-limit-if-touched :trailing-stop-limit :trailing-market-if-touched :what-if), :valid-exchanges ["MEXI"], :min-tick 0.01, :trading-class "AAPL", :putable? false, :summary {:include-expired? false, :type :equity, :currency "MXN", :primary-exchange "MEXI", :local-symbol "AAPL", :exchange "MEXI", :symbol "AAPL", :contract-id 38708077}, :market-name "AAPL", :coupon 0.0, :category "Computers"}}
...
{:type :contract-details-end, :request-id 6}

;;; more specifically, if we were interested in trading AAPL on
;;; ISLAND:

user> (request-contract-details {:symbol "AAPL" :type :equity :exchange "ISLAND"})

;;; only gets the one match

```

You can see all the valid exchanges for a security in the results from
a broad search and then be more specific when you actually want to
trade it.

As you can see, the response contains a `:local-symbol` which is the
same as the symbol we requested. I find this to generally be the case
with US equities. Even when the local-symbol and symbol don't match,
you can use `:symbol` and just specify the exchange:

```clojure
user> (request-contract-details {:symbol "BP" :type :equity})

;;; lot's of matches
...
;;; say we only wanted this one:
{:type :contract-details, :request-id 11, :value { ...
:long-name "BANCO POPOLARE SCARL", ...
:valid-exchanges ["SMART" "BVME" "FWB" "MIBSX" "SWB"], ...
:summary {..., :type :equity, :currency "EUR",
:primary-exchange "BVME",
:local-symbol "B8Z",
:exchange "SWB",
:symbol "BP", ...}, ...}}

;;; be more specific
user> (request-contract-details {:symbol "BP" :exchange "SWB" :type :equity})

;;; only gets the one match
{... :value {... :long-name "BANCO POPLARE SCARL" ...} ...}

;;; or:
user> (request-contract-details {:local-symbol "B8Z" :type :equity})

;;; actually gets 2 matches, because Banco Poplare's local symbol is
;;; the same on both the SWB (Stuttgart) and FWB (Frankfurt)
;;; exchanges.

```

For futures, I usually find it works best to use a local symbol with
a built in expiration:

```clojure
user> (request-contract-details {:local-symbol "ESH3" :type :future})

{... :value {... :long-name "E-mini S&P 500", :contract-month "201303",
:summary {:multiplier 50.0, :expiry #<DateTime 2013-03-15T00:00:00.000Z>,
:type :future, :currency "USD", :local-symbol "ESH3",
:exchange "GLOBEX", :symbol "ES", ..., :contract-id 98770297},
:market-name "ES", ...}}

user> (request-contract-details {:local-symbol "ZN DEC 12" :type :future})

{..., :value {... :long-name "10 Year US Treasury Note", :contract-month "201212",
:summary {:multiplier 1000.0, :expiry #<DateTime 2012-12-19T00:00:00.000Z>,
:type :future, :currency "USD", :local-symbol "ZN DEC 12",
:exchange "ECBOT", :symbol "ZN", :contract-id 94977350},
:market-name "ZN"}}

```

You can also use `:contract-id`, which is a unique identifier assigned
by Interactive Brokers to identify securities:

```clojure
user> (request-contract-details {:contract-id 98770297})

{... :value {... :long-name "E-mini S&P 500", :contract-month "201303",
:summary {:multiplier 50.0, :expiry #<DateTime 2013-03-15T00:00:00.000Z>,
:type :future, :currency "USD", :local-symbol "ESH3",
:exchange "GLOBEX", :symbol "ES", ..., :contract-id 98770297},
:market-name "ES", ...}}

```

## Requesting Historical Data

To get historical bars, use the `request-historical-data` function:

```clojure
user> (request-historical-data 1 {:symbol "AAPL" :type :equity :exchange "ISLAND"}
(date-time 2012 12 18 20) 1 :day 1 :hour)

{:WAP 524.187, :close 521.69, :has-gaps? false, :trade-count 4538, :low 521.27, :type :price-bar, :time #<DateTime 2012-12-18T14:30:00.000Z>, :open 524.88, :high 526.35, :volume 8260, :request-id 1}
...
{:WAP 529.905, :close 530.79, :has-gaps? false, :trade-count 2563, :low 527.79, :type :price-bar, :time #<DateTime 2012-12-18T19:00:00.000Z>, :open 530.27, :high 531.64, :volume 3293, :request-id 1}
{:type :price-bar-complete, :request-id 1}

```

Note, all date-times are in UTC unless otherwise noted.

Interactive Brokers throttles historical data requests. The
restrictions at the time this was written were:
Expand Down Expand Up @@ -76,9 +266,16 @@ total of 19 requests.

This example breaks the requested period up into retrievable chunks.

```clojure
user> (def prices (atom []))

```


## License

Copyright (C) 2011 Chris Bilson

Distributed under the Eclipse Public License, the same as Clojure.

[1]: http://www.interactivebrokers.com/en/software/api/api.htm

0 comments on commit e2d2734

Please sign in to comment.