Streaming API

ICBIT trading platform gives a way to get real time market information and issue/cancel your orders by providing a special fast streaming API.

The ICBIT API is implemented using socket.io which supports a number of different secure transports. An updated list of client libraries in different programming languages is being maintained at socket.io wiki page.

ICBIT provides a simpler to use HTTP requests based API for those who don't require frequent updates (as the HTTP API is limited).

Reference Implementation in C#

Open source trading bot reference implementation is available on GitHub - see SharpTrader repository. A good start for your own trading algorithm implementation!

Connecting

The following sample JavaScript code illustrates how to establish a connection:

    var conn = io.connect('https://api0.orderbook.net/icbit?key=API_KEY&signature=SIGNATURE&nonce=NONCE&cod=COD');
    conn.on('message', function(data) { // Handle incoming message });
  • API_KEY is an alphanumeric string used for authenticating the session.
  • SIGNATURE is generated for every connect request using your user id, your API secret and nonce value.
  • COD is an optional integer parameter. If it is set to 1 then all active orders issued within this connection will be automatically cancelled on disconnect.

Signature generation example in JavaScript:

    <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha256.js"></script>

    <script>

        var nonce = Math.round(new Date().getTime() / 1000); // Unix timestamp as nonce

        var userid = "111"; // Your user id

        var key = "8t3JvE7ZJKYiRibilqgOIuiL7GbQZehb"; // Your API key

        var secret = "cIPlpTkYzQIpSF6heEfRDT1y2wcVcEkA"; // Your API secret

        var signature = CryptoJS.HmacSHA256(nonce + userid + key, secret).toString(CryptoJS.enc.Hex).toUpperCase();

    </script>

Signature generation in Python:

    message = nonce + client_id + api_key
    signature = hmac.new(API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()

Signature generation in C# is implemented in SharpTrader.

API keys and secrets can be obtained from the API page in your profile.

Handling Events

There are mainly 4 types of events which you may want to handle: connect, disconnect, error and message. The code above shows how to register function handler for message event.

Incoming Data

The incoming data is a complete, easy to parse object. Minimally it contains one field:

{
    "op":<OPERATION_TYPE>
}

The <OPERATION_TYPE> field may take these values:

remark
Message from the server (info, warning, error, etc)
private
"Main" message operation type carrying different possible payloads

Operation Codes

op:remark

The remark message contains actual message text and severity flag (either "info", "warn" or "error")

{
    "op":"remark",
    "message":<MESSAGE>,
    "severity":<SEVERITY>
}

op:private

Private message includes a wide variety of possible incoming information. The generic structure of any private message is:

{
    "channel":<CHANNEL_ID>
    "op":"private",
    "update":<IS_UPDATE>,
    "private":<MESSAGE_TYPE>,
    "<MESSAGE_TYPE>":<DATA_PAYLOAD>
}

The <MESSAGE_TYPE> field may take these values:

instruments
A detailed list of all tradable instruments
status
Current status of the trading platform (trading, clearing, paused, etc).
trade
Trades information
ticker
Information update about all securities in the system (volume, open interest, high, low, etc). Uses ticker_<SECID> channel.
user_balance
Balance of the authenticated user
user_order
Orders of the authenticated user

The optional <IS_UPDATE> field may take either false or true value and it provides additional hint whether the incoming information is a full list (e.g. a full list of user orders) or just an update (e.g. just one new user order).

private:instruments

Message, containing all tradable financial instruments

{
    [
    "type": "", // Instrument type - currency exchange, bond, stock, futures contract
    "market_id": <MARKET_ID>, // Market where this instrument trades
    "ticker": <TICKER>, // Short instrument code
    "name": <STRING>, // Long name of the instrument
    "desc": <STRING>, // Description of the instrument (english only)
    "curid": <CURRENCY>, // Base currency of this futures contract
    "im_buy": <PRICE>, // margin requirement for long position
    "im_sell": <PRICE>, // margin requirement for short position
    "price_min": <PRICE>, // minimal price for the current session
    "price_max": <PRICE>, // maximum price for the current session
    "inverted": <BOOLEAN>, // Is this a so-called "inverted" futures
    "fee": <INTEGER>, // Trading fee (per transaction)
    "clr_fee": <INTEGER>, // Clearing fee (per clearing)
    "session": <SESSION_ID>, // Session these data are valid for
    "expiry": <DATE>, // Date of the contract's final settlement
    "r": <FLOAT>, // Tick size
    "w": <FLOAT> // Lot size
    ],...}

private:ticker

{
    "type": "ticker",
    "market_id": <MARKET_ID>,
    "ticker": <TICKER>,
    "ts": <TIMESTAMP>,
    "last": <PRICE>,
    "last_qty": <QTY>,
    "oi": <OPEN_INTEREST>,
    "volume": <VOLUME>, // total volume
    "im_buy": <PRICE>, // margin requirement for long position
    "im_sell": <PRICE>, // margin requirement for short position
    "bid": <PRICE>,
    "bid_qty": <QTY>,
    "ask": <PRICE>,
    "ask_qty": <QTY>,
    "open": <PRICE>,
    "high": <PRICE>,
    "low": <PRICE>,
    "vwap60": <PRICE> // 1 hour sliding window VWAP
}

private:trade

{
    "market": <MARKET_ID>,
    "ticker": <TICKER>,
    "ts": <TIMESTAMP>,
    "tid": <TRADE_ID>,
    "price": <PRICE>,
    "oi": <OPEN_INTEREST>,
    "qty": <VOLUME>,
    "buyer": <USERID>, // Valid only for your own trades
    "seller": <USERID>, // Valid only for your own trades
    "oid_buy": <ORDER_ID>, // Valid only for your own trades
    "oid_sell": <ORDER_ID>, // Valid only for your own trades
    "buyinit": <INT> // 1 if this trade was initiated by a buying order and 0 otherwise
}

private:user_balance

  {
  "channel":"user_balance",
  "op":"private",
  "private":"user_balance",
  "user_balance":
    [{
      "name": <STRING>, // Human-readable name of the instrument
      "ticker": <TICKER>,
      "curid": <CURRENCY>,
      "type": <TYPE>, // 0 = currency, 1 = futures contract
      "qty": <QTY>,
      "upl": <INTEGER>, // Unrealized profit/loss for this instrument
      "margin": <PRICE>,
      "mm": <PRICE>, // Futures only: margin requirement for maintaining this position
      "vm": <PRICE> // Futures only: variation margin. SUBJECT TO CHANGE!
  },...]

private:user_order

Message, containing all users orders, or update to the specific set of user orders

  {
  "channel":"user_order",
  "op":"private",
  "update":<IS_UPDATE>,
  "private":"user_order",
  "user_order":
  [{
  "oid": <ORDER_ID>,
  "date": <ORDER_TIMESTAMP>,
  "dir": <ORDER_BUY>,
  "type": <ORDER_TYPE>,
  "price": <ORDER_PRICE>,
  "qty": <ORDER_QTY>,
  "exec_qty": <ORDER_EXECQTY>,
  "status": <ORDER_STATUS>,
  "info": <ORDER_INFO>,
  "token": <USER_TOKEN>,
  "ticker": <SEC_ID>,
  "currency": <CURRENCY>,
  "market": <MARKET_ID>,
  "fills": [{
  "ts": <TIMESTAMP>,
  "price": <PRICE>,
  "qty": <QTY>,
  "tid": <TRADE_ID>,
  "pos": <QTY>, // total contracts quantity / base currency amount reached after this fill happened
  "pos_quoted": <QTY> // quoted currency amount reached after this fill happened
  },...],
  },...]
  }

Please note, that your application should be able to handle two types of user_order incoming messages.

The <IS_UPDATE> may take the following values:

FALSE
The array in the "user_order" field refers to all orders the user has
TRUE
The array in the "user_order" field contains only changed orders

If the <IS_UPDATE> field is set to FALSE everything you cached locally which is not in the list should be purged.

If the <IS_UPDATE> field is set to TRUE, user may have more orders than there is in the user_order array.

The <USER_TOKEN> is a user specific field of unsigned long (64 bits wide) type.

The "fills" array contains information in case this order update resulted from a trade (which means, the order was fully or partially filled).

Common data types

The <ORDER_STATUS> field indicates order status in the system and may take these values:

0
New
1
Partially Filled
2
Filled (trading, clearing, paused, etc).
4
Canceled
5
Rejected
6
Pending cancel
10
Pending new

The <MARKET_ID> field is section of the exchange and may take these values:

0
Currency exchange market
1
futures contracts market

The <ORDER_ID> is an unsigned 64-bit integer denoting order id in the market.

The <TICKER> is a short code of the contract and may take the following values

BU<X><Y>
Instrument of the futures market: <X>: Month, <Y> Year
<Z>
Currency pair id for the exchange market(e.g. 3 for BTC/USD)

Channels

Channel names are message type names <MESSAGE_TYPE> except for orderbooks updates.

  • Orderbook updates channel are called orderbook_<SEC_ID>, where <SEC_ID> is a global universal identifier of the tradable object. For futures <SEC_ID> would be its short code (e.g. orderbook_BUH3 for BTCUSD futures), and for currency exchange section it is a numerical identifier of the currency pair (e.g. orderbook_3 for BTC/USD pair).
  • Trades notification channels are called trades_<SEC_ID>.
  • Ticker information updates are sent via channels called ticker_<SEC_ID>.

Outgoing Commands

op:subscribe

Subscribe to a channel to start receiving data from it.

{
    "op":"subscribe",
    "channel":<CHANNEL_ID>
}

op:unsubscribe

Unsubscribe from a channel to stop receive data from it.

{
    "op":"unsubscribe",
    "channel":<CHANNEL_ID>
}

op:get

Get the newest information of a specified type. This commands requests a forceful update to be sent to the user. Reply is of type op:private with <MESSAGE_TYPE> corresponding to the requested <GETTYPE_ID>

{
    "op":"get",
    "type":<GETTYPE_ID>
}

The <GETTYPE_ID> field may take these values:

user_order
Unsupported
user_balance
Balance of the authenticated user.
status
Current status of the trading platform (trading, clearing, paused, etc).
user_trades
User's trading history

op:get user_trades

Get information about user's trades

{
    "op":"get",
    "type":"user_trades",
    "since":<TIMESTAMP>,
    "limit":<LIMIT>
}

The <since> parameter sets the oldest date (timestamp) after which you wish to receive trading history.

The <limit> parameter sets how many trades you wish to get at once (max. possible value for now is 500 trades records at once).

Reply would contain an array of requested trades in the standard reply structure. The array of requested trades will be sorted by timestamp descending (which means, the first array element will contain the newest trade).

{
    "private":"user_trades",
    "user_trades": [
        {
            buy: <BUY>,
            market: <MARKET_ID>,
            price: <PRICE>,
            qty: <QTY>,
            sid: <SESSION_ID>,
            ticker: <TICKER>,
            tid: <TRADE_ID>,
            ts: <TIMESTAMP>
        },...];
}

op:create_order

Creates a new order (right now, only in the futures section of the exchange). The reply to this command would be a notification (op:private, private:user_order) about a new order in the system with the "update" field set to true.

{
    "op":"create_order",
    "order":{
        "market": <MARKET_ID>,
        "ticker": <TICKER>,
        "buy": <BUY>,
        "price": <PRICE>,
        "qty": <QTY>,
        "token": <USER_TOKEN>
}

The <BUY> may take one of the following values:

0
means this is an order to sell
1
means this is an order to buy

The <PRICE>:

For futures section: The price in integer contract price units.
To convert contract price from human readable representation (e.g. $800) to integer contract units you need to divide it by the contract's minimum tick size R.

Example: If a minimum price tick of a contract is $0.1, then price in contract price units will be $800/$0.1=8000. Please check the tick size in contract specs! For majority of contracts it's $1.

For currency exchange section: The price in respective units.
For BTC/USD, this is the price in US dollars multiplied by 100000 and passed as integer.

The <QTY>:

For futures section: The number of contracts you want to buy/sell.

For currency exchange section: amount of the currency you are buying or selling.
For BTC/USD, this is the amount of bitcoins you want to buy/sell expressed in satoshis (BTC multiplied by 10e8).

The <USER_TOKEN> field may take one of the following values:

0
If you don't need it
<Z>
Any number user wishes to associate with a newly created order.

Order type is assumed to be LIMIT by default, market is assumed as futures by default.

op:cancel_order

Cancels an order. The reply to this command would be a notification (op:private, private:user_order) about a canceled order in the system with the "update" field set to true.

{
    "op":"cancel_order",
    "order":{
        "oid": <ORDER_ID>,
        "market": <MARKET_ID>
}

<ORDER_ID> is an id of the order you wish to cancel;