Skip to content

Commit

Permalink
Minor fixes for Quadriga trading API (DeviaVir#421)
Browse files Browse the repository at this point in the history
* Quadriga CX Fixes

* Add amount for takers fee
* Minor update to backfill warning text
* Fix variable shadowing error
* Trades with the same timestamp are now ordered oldest to newest when r eturned from getTrades
* Trade volume now returned as number and not a string, prevents NaN on volume report
* Filter results on timestamp start to prevent re-reporting the same trades in the results

* Sometime opts.from is undefined, and we should return all results.

* Formatting

* Quadriga now supports trading LTC

* Fixing QCX API handling of numbers

Some argument about the lack of type safety in javascript.

* QCX fix incorrect error reporting

* * Adding debug output to help troubleshoot any more issues

* Clean up use of Number(), numbro() and String() in various API calls
* Fix error with error reporting for getTrades
* Clean up error handling conditions
* Remove excess semicolons for consistency

* Fix error with retry in getBalance

* QCX - Fix look up order

* Re-enabled taker order processing in buy/sell command

This doesn't appear strictly necessary, but if it reduces API calls back to the platform it could result in fewer API over-limits.
  • Loading branch information
cmroche authored and DeviaVir committed Jul 31, 2017
1 parent 2417a86 commit e55a66c
Showing 1 changed file with 51 additions and 31 deletions.
82 changes: 51 additions & 31 deletions extensions/exchanges/quadriga/exchange.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
var QuadrigaCX = require('quadrigacx'),
path = require('path'),
minimist = require('minimist'),
moment = require('moment'),
colors = require('colors'),
n = require('numbro')

module.exports = function container(get, set, clear) {
var c = get('conf')
var s = {
options: minimist(process.argv)
}
var so = s.options

var shownWarnings = false

var public_client, authed_client

function publicClient() {
if (!public_client) public_client = new QuadrigaCX("1", "", "");
if (!public_client) public_client = new QuadrigaCX("1", "", "")
return public_client
}

Expand All @@ -21,7 +27,7 @@ module.exports = function container(get, set, clear) {
throw new Error('please configure your Quadriga credentials in ' + path.resolve(__dirname, 'conf.js'))
}

authed_client = new QuadrigaCX(c.quadriga.client_id, c.quadriga.key, c.quadriga.secret);
authed_client = new QuadrigaCX(c.quadriga.client_id, c.quadriga.key, c.quadriga.secret)
}
return authed_client
}
Expand All @@ -33,7 +39,7 @@ module.exports = function container(get, set, clear) {
function retry(method, args, error) {
if (error.code === 200) {
console.error(('\QuadrigaCX API rate limit exceeded! unable to call ' + method + ', aborting').red)
return;
return
}

if (method !== 'getTrades') {
Expand All @@ -44,6 +50,10 @@ module.exports = function container(get, set, clear) {
}, 30000)
}

function debugOut(msg) {
if (so.debug) console.log(msg)
}

var orders = {}

var exchange = {
Expand All @@ -67,12 +77,12 @@ module.exports = function container(get, set, clear) {
client.api('transactions', args, function(err, body) {
if (!shownWarnings) {
console.log('please note: the quadriga api does not support backfilling.')
console.log('please note: periods should be set to 1h or less.');
shownWarnings = true;
console.log('please note: periods should be set to 1h or less.')
shownWarnings = true
}

if (err) return retry('getTrades', func_args, err)
if (body.error) return retry('getTrades', func_args, trades.error)
if (body.error) return retry('getTrades', func_args, body.error)

var trades = body.filter(t => {
return (typeof opts.from === 'undefined') ? true : (moment.unix(t.date).valueOf() > opts.from)
Expand All @@ -91,10 +101,11 @@ module.exports = function container(get, set, clear) {
},

getBalance: function(opts, cb) {
var func_args = [].slice.call(arguments)
var client = authedClient()
client.api('balance', function(err, wallet) {
if (err) return retry('getBalance', null, err)
if (wallet.error) return retry('getBalance', null, wallet.error)
if (err) return retry('getBalance', func_args, err)
if (wallet.error) return retry('getBalance', func_args, wallet.error)

var currency = opts.currency.toLowerCase()
var asset = opts.asset.toLowerCase()
Expand All @@ -104,11 +115,16 @@ module.exports = function container(get, set, clear) {
currency: 0
}

balance.currency = Number(wallet[currency + '_balance']);
balance.asset = Number(wallet[asset + '_balance']);
balance.currency = n(wallet[currency + '_balance']).format(0.00)
balance.asset = n(wallet[asset + '_balance']).format(0.00)

balance.currency_hold = n(wallet[currency + '_reserved']).format(0.00000000)
balance.asset_hold = n(wallet[asset + '_reserved']).format(0.00000000)

debugOut(`Balance/Reserve/Hold:`)
debugOut(` ${currency} (${wallet[currency + '_balance']}/${wallet[currency + '_reserved']}/${wallet[currency + '_available']})`)
debugOut(` ${asset} (${wallet[asset + '_balance']}/${wallet[asset + '_reserved']}/${wallet[asset + '_available']})`)

balance.currency_hold = Number(wallet[currency + '_reserved'])
balance.asset_hold = Number(wallet[asset + '_reserved'])
cb(null, balance)
})
},
Expand All @@ -126,8 +142,8 @@ module.exports = function container(get, set, clear) {
if (quote.error) return retry('getQuote', func_args, quote.error)

var r = {
bid: Number(quote.bid),
ask: Number(quote.ask)
bid: String(quote.bid),
ask: String(quote.ask)
}

cb(null, r)
Expand All @@ -140,6 +156,8 @@ module.exports = function container(get, set, clear) {
id: opts.order_id
}

debugOut(`Cancelling order ${opts.order_id}`)

var client = authedClient()
client.api('cancel_order', params, function(err, body) {
if (err) return retry('cancelOrder', func_args, err)
Expand All @@ -158,6 +176,8 @@ module.exports = function container(get, set, clear) {
params.price = n(opts.price).format('0.00')
}

debugOut(`Requesting ${opts.order_type} buy for ${opts.size} assets`)

var client = authedClient()
client.api('buy', params, function(err, body) {
var order = {
Expand All @@ -171,14 +191,11 @@ module.exports = function container(get, set, clear) {
}

if (err) return cb(err)
if (body.error) {
//console.log(`API Error: ${body.error.message}`);
return cb(body.error)
}
if (body.error) return cb(body.error)

if (opts.order_type === 'taker') {
order.status = 'done'
order.done_at = new Date().getTime();
order.done_at = new Date().getTime()

if (body.orders_matched) {
var asset_total = 0
Expand All @@ -197,6 +214,8 @@ module.exports = function container(get, set, clear) {
}
}

debugOut(` Purchase ID: ${body.id}`)

order.id = body.id
orders['~' + body.id] = order
cb(null, order)
Expand All @@ -213,6 +232,8 @@ module.exports = function container(get, set, clear) {
params.price = n(opts.price).format('0.00')
}

debugOut(`Requesting ${opts.order_type} sell for ${opts.size} assets`)

var client = authedClient()
client.api('sell', params, function(err, body) {
var order = {
Expand All @@ -226,22 +247,19 @@ module.exports = function container(get, set, clear) {
}

if (err) return cb(err)
if (body.error) {
//console.log(`API Error: ${body.error.message}`);
return cb(body.error)
}
if (body.error) return cb(body.error)

if (opts.order_type === 'taker') {
order.status = 'done'
order.done_at = new Date().getTime();
order.done_at = new Date().getTime()

if (body.orders_matched) {
var asset_total = 0
var price_total = 0.0
var order_count = body.orders_matched.length
for (var idx = 0; idx < order_count; idx++) {
asset_total = asset_total + Number(body.orders_matched[idx].amount)
price_total = price_total + (Number(body.orders_matched[idx].amount) * body.orders_matched[idx].price)
price_total = price_total + (Number(body.orders_matched[idx].amount) * Number(body.orders_matched[idx].price))
}

order.price = price_total / asset_total
Expand All @@ -252,6 +270,8 @@ module.exports = function container(get, set, clear) {
}
}

debugOut(` Sell ID: ${body.id}`)

order.id = body.id
orders['~' + body.id] = order
cb(null, order)
Expand All @@ -267,17 +287,17 @@ module.exports = function container(get, set, clear) {
var client = authedClient()
client.api('lookup_order', params, function(err, body) {
if (err) return cb(err)
if (body.error) {
//console.log(`API Error: ${body.error.message}`);
return cb(body.error)
}
if (body.error) return cb(body.error)

if (body.status === 2) {
if (body[0].status === 2) {
order.status = 'done'
order.done_at = new Date().getTime()
order.filled_size = Number(body.amount)
order.filled_size = Number(body[0].amount)
return cb(null, order)
}

debugOut(`Lookup order ${opts.order_id} status is ${body.status}`)

cb(null, order)
})
},
Expand Down

0 comments on commit e55a66c

Please sign in to comment.