Skip to content

Commit

Permalink
Add Cryptoquote to SDK (#9)
Browse files Browse the repository at this point in the history
* Add Cryptoquote provider

* Update README with Cryptoquote provider

* Add and prioritize URL authentication

* Update README and examples for URL authentication

* Refactor URL auth

* Change code samples from ruby to javascript...oops

* Change nil to null in README

* Update for Crypto message re-factor

* Updates to messages and channels

* Grammar
  • Loading branch information
atsmith813 authored and alexnsolo committed Nov 29, 2018
1 parent 4f1c986 commit 0415004
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 5 deletions.
96 changes: 95 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Currently, Intrinio offers realtime data from the following providers:

* IEX - [Homepage](https://iextrading.com/)
* QUODD - [Homepage](http://home.quodd.com/)
* Cryptoquote - [Homepage](https://www.cryptoquote.io/)

Each has distinct price channels and quote formats, but a very similar API.

Expand Down Expand Up @@ -169,6 +170,85 @@ NOTE: Messages from QUOOD reflect _changes_ in market data. Not all fields will
* **size** - the size of the `last` trade, or total volume of orders at the top-of-book `bid` or `ask` price
* **price** - the price in USD

### Cryptoquote

#### Level 1 - Price Update

NOTE: Null values for some fields denote no change from previous value.

```javascript
{ last_updated: "2018-10-29 23:08:02.277Z",
pair_name: "BTCUSD",
pair_code: "btcusd",
exchange_name: "Binance",
exchange_code: "binance",
bid: 6326,
bid_size: 6.51933000,
ask: 6326.97,
ask_size: 6.12643000,
change: -151.6899999999996,
change_percent: -2.340895061728389,
volume: 13777.232772,
open: 6480,
high: 6505.01,
low: 6315,
last_trade_time: "2018-10-29 23:08:01.834Z",
last_trade_side: null,
last_trade_price: 6326.97000000,
last_trade_size: 0.00001200,
type: "level_1" }
```

* **last_updated** - a UTC timestamp of when the data was last updated
* **pair_name** - the name of the currency pair
* **pair_code** - the code of the currency pair
* **exchange_name** - the name of the exchange
* **exchange_code** - the code of the exchange
* **ask** - the ask for the currency pair on the exchange
* **ask_size** - the size of the ask for the currency pair on the exchange
* **bid** - the bid for the currency pair on the exchange
* **bid_size** - the size of the bid for the currency pair on the exchange
* **change** - the notional change in price since the last ticker
* **change_percent** - the percent change in price since the last ticker
* **volume** - the volume of the currency pair on the exchange
* **open** - the opening price of the currency pair on the exchange
* **high** - the highest price of the currency pair on the exchange
* **low** - the lowest price of the currency pair on the exchange
* **last_trade_time** - a UTC timestamp of the last trade for the currency pair on the exchange
* **last_trade_side** - the side of the last trade
* **`buy`** - this is an update to the buy side of the book
* **`sell`** - this is an update to the sell side of the book
* **last_trade_price** - the price of the last trade for the currency pair on the exchange
* **last_trade_size** - the size of the last trade for the currency pair on the exchange
* **type** - the type of message this is
* **`level_1`** - a messages that denotes a change to the last traded price or top-of-the-book bid or ask
* **`level_2`** - a message that denotes a change to an order book

#### Level 2 - Book Update
```javascript
{ pair_name: "BTCUSD",
pair_code: "btcusd",
exchange_name: "Gemini",
exchange_code: "gemini",
side: "buy",
price: 6337.4,
size: 0.3,
type: "level_2" }
```

* **pair_name** - the name of the currency pair
* **pair_code** - the code of the currency pair
* **exchange_name** - the name of the exchange
* **exchange_code** - the code of the exchange
* **side** - the side of the book this update is for
* **`buy`** - this is an update to the buy side of the book
* **`sell`** - this is an update to the sell side of the book
* **price** - the price of this book entry
* **size** - the size of this book entry
* **type** - the type of message this is
* **`level_1`** - a messages that denotes a change to the last traded price or top-of-the-book bid or ask
* **`level_2`** - a message that denotes a change to an order book

## Channels

### QUODD
Expand All @@ -185,6 +265,20 @@ To receive price quotes from the Intrinio Real-Time API, you need to instruct th

Special access is required for both lobby channels. [Contact us](mailto:sales@intrinio.com) for more information.

### Cryptoquote

To receive price quotes from Cryptoquote, you need to instruct the client to "join" a channel. A channel can be

* `crypto:market_level_1:{pair_code}` - the Level 1 Market channel where all Level 1 price updates for the provided currency pair in all exchanges are posted (i.e. `crypto:pair:market_level_1:btcusd`)
* `crypto:exchange_level_1:{exchange_code}:{pair_code}` - the Level 1 Market channel where all Level 1 price updates for the provided currency pair and exchange are posted
* `crypto:exchange_level_2:{exchange_code}:{pair_code}` - the Level 2 Market channel where all Level 2 book updates for the provided currency pair and exchange are posted
* `crypto:firehose` - the Firehose channel where all message types for all currency pairs are posted (special access required)

The Intrinio REST API provides a listing of pairs, exchanges, and their corresponding codes:

* [Crypto Currency Pairs](https://intrinio.com/documentation/download#crypto_currency_pairs)
* [Crypto Exchanges](https://intrinio.com/documentation/download#crypto_exchanges)

## API Keys
You will receive your Intrinio API Key after [creating an account](https://intrinio.com/signup). You will need a subscription to the [IEX Real-Time Stock Prices](https://intrinio.com/data/realtime-stock-prices) data feed as well.

Expand All @@ -193,7 +287,7 @@ You will receive your Intrinio API Key after [creating an account](https://intri
### Methods

`constructor(options)` - Creates a new instance of the IntrinioRealtime client.
* **Parameter** `options`: An object with properties `api_key` and `provider`, corresponding to your Intrinio API Key and a provider code ("iex" or "quodd").
* **Parameter** `options`: An object with properties `api_key` and `provider`, corresponding to your Intrinio API Key and a provider code ("iex", "quodd", or "cryptoquote").
```javascript
var ir = new IntrinioRealtime({
api_key: "INTRINIO_API_KEY",
Expand Down
41 changes: 37 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class IntrinioRealtime extends EventEmitter {
}
}

if (!options.provider || (options.provider != "iex" && options.provider != "quodd")) {
this._throw("Need a valid provider: iex or quodd")
if (!options.provider || (options.provider != "iex" && options.provider != "quodd" && options.provider != "cryptoquote")) {
this._throw("Need a valid provider: iex, quodd, or cryptoquote")
}

// Establish connection
Expand Down Expand Up @@ -110,7 +110,7 @@ class IntrinioRealtime extends EventEmitter {
this.ready = true
this.emit('connect')
this._stopSelfHeal()
if (this.options.provider == "iex") {
if (this.options.provider == "iex" || this.options.provider == "cryptoquote") {
this._refreshChannels()
}
},
Expand Down Expand Up @@ -140,6 +140,12 @@ class IntrinioRealtime extends EventEmitter {
path: "/token?type=QUODD"
}
}
else if (this.options.provider == "cryptoquote") {
auth_url = {
host: "crypto.intrinio.com",
path: "/auth"
}
}

if (this.options.api_key) {
auth_url = this._makeAPIAuthUrl(auth_url)
Expand Down Expand Up @@ -228,6 +234,9 @@ class IntrinioRealtime extends EventEmitter {
else if (this.options.provider == "quodd") {
return 'wss://www5.quodd.com/websocket/webStreamer/intrinio/' + encodeURIComponent(this.token)
}
else if (this.options.provider == "cryptoquote") {
return 'wss://crypto.intrinio.com/socket/websocket?vsn=1.0.0&token=' + encodeURIComponent(this.token)
}
}

_refreshWebsocket() {
Expand Down Expand Up @@ -284,6 +293,11 @@ class IntrinioRealtime extends EventEmitter {
quote = message.data
}
}
else if (this.options.provider == "cryptoquote") {
if (message.event === 'book_update' || message.event === 'ticker' || message.event === 'trade') {
quote = message.payload
}
}

if (quote) {
if (typeof this.quote_callback === 'function') {
Expand Down Expand Up @@ -357,6 +371,9 @@ class IntrinioRealtime extends EventEmitter {
else if (this.options.provider == "quodd") {
return {event: 'heartbeat', data: {action: 'heartbeat', ticker: Date.now()}}
}
else if (this.options.provider == "cryptoquote") {
return {topic: 'phoenix', event: 'heartbeat', payload: {}, ref: null}
}
}

_heartbeat() {
Expand Down Expand Up @@ -390,7 +407,7 @@ class IntrinioRealtime extends EventEmitter {
})

channels.forEach(channel => {
if (channel.length == 0 || channel.length > 20) {
if (channel.length == 0) {
this._throw("Invalid channel provided")
}
})
Expand All @@ -416,6 +433,14 @@ class IntrinioRealtime extends EventEmitter {
}
}
}
else if (this.options.provider == "cryptoquote") {
return {
topic: channel,
event: 'phx_join',
payload: {},
ref: null
}
}
}

_makeLeaveMessage(channel) {
Expand All @@ -436,6 +461,14 @@ class IntrinioRealtime extends EventEmitter {
}
}
}
else if (this.options.provider == "cryptoquote") {
return {
topic: channel,
event: 'phx_leave',
payload: {},
ref: null
}
}
}

_parseIexTopic(channel) {
Expand Down

0 comments on commit 0415004

Please sign in to comment.