diff --git a/core/gekkoStream.js b/core/gekkoStream.js index d6721f355..61713986e 100644 --- a/core/gekkoStream.js +++ b/core/gekkoStream.js @@ -32,6 +32,10 @@ if(config.debug && mode !== 'importer') { // decorate with more debug information Gekko.prototype._write = function(chunk, encoding, _done) { + if(chunk.isFinished) { + return this.finalize(); + } + const start = moment(); var relayed = false; var at = null; @@ -58,6 +62,10 @@ if(config.debug && mode !== 'importer') { } else { // skip decoration Gekko.prototype._write = function(chunk, encoding, _done) { + if(chunk.isFinished) { + return this.finalize(); + } + const flushEvents = _.after(this.candleConsumers.length, () => { this.flushDefferedEvents(); _done(); @@ -94,6 +102,7 @@ Gekko.prototype.finalize = function() { } Gekko.prototype.shutdown = function() { + this.end(); async.eachSeries( this.plugins, function(c, callback) { diff --git a/core/markets/backtest.js b/core/markets/backtest.js index 2e7cd3e53..95f7b3eea 100644 --- a/core/markets/backtest.js +++ b/core/markets/backtest.js @@ -74,7 +74,7 @@ Market.prototype.processCandles = function(err, candles) { if(this.ended) { this.closed = true; this.reader.close(); - this.emit('end'); + this.push({isFinished: true}); } else { util.die('Query returned no candles (do you have local data for the specified range?)'); } diff --git a/exchange/exchangeUtils.js b/exchange/exchangeUtils.js index 3d6c902f4..51c48ee37 100644 --- a/exchange/exchangeUtils.js +++ b/exchange/exchangeUtils.js @@ -4,7 +4,7 @@ const retry = require('retry'); const errors = require('./exchangeErrors'); const _ = require('lodash'); -const retryInstance = (options, checkFn, callback) => { +const retryInstance = (options, checkFn, callback, e) => { if(!options) { options = { retries: 100, @@ -19,10 +19,13 @@ const retryInstance = (options, checkFn, callback) => { const operation = retry.operation(options); operation.attempt(function(currentAttempt) { checkFn((err, result) => { + if(!err) { return callback(undefined, result); } + console.log(new Date, err.message); + let maxAttempts = err.retry; if(maxAttempts === true) maxAttempts = 10; diff --git a/exchange/orders/sticky.js b/exchange/orders/sticky.js index 282f88583..bfad5cdeb 100644 --- a/exchange/orders/sticky.js +++ b/exchange/orders/sticky.js @@ -43,10 +43,14 @@ class StickyOrder extends BaseOrder { return false; } + console.log(new Date, 'sticky create', side); + this.side = side; this.amount = this.roundAmount(rawAmount); + this.initialLimit = params.initialLimit; + if(side === 'buy') { if(params.limit) this.limit = this.roundPrice(params.limit); @@ -66,9 +70,19 @@ class StickyOrder extends BaseOrder { this.outbid = params.outbid && _.isFunction(this.outbidPrice); - this.price = this.calculatePrice(this.data.ticker); + if(this.data && this.data.ticker) { + this.price = this.calculatePrice(this.data.ticker); + this.createOrder(); + } else { + this.api.getTicker((err, ticker) => { + if(this.handleError(err)) { + return; + } - this.createOrder(); + this.price = this.calculatePrice(ticker); + this.createOrder(); + }); + } return this; } @@ -77,7 +91,13 @@ class StickyOrder extends BaseOrder { const r = this.roundPrice; + if(this.initialLimit && !this.id) { + console.log('passing initial limit of:', this.limit); + return r(this.limit); + } + if(this.side === 'buy') { + if(ticker.bid >= this.limit) { return r(this.limit); } diff --git a/exchange/util/genMarketFiles/update-kraken.js b/exchange/util/genMarketFiles/update-kraken.js index 7e05c9ebf..9bf11e658 100644 --- a/exchange/util/genMarketFiles/update-kraken.js +++ b/exchange/util/genMarketFiles/update-kraken.js @@ -60,6 +60,9 @@ let getMinTradeSize = asset => { case 'USDT': minTradeSize = '5' break; + case 'XXDG': + minTradeSize = '3000' + break; default: break; } diff --git a/exchange/wrappers/coinfalcon.js b/exchange/wrappers/coinfalcon.js index f85d2341a..2746bb7b5 100644 --- a/exchange/wrappers/coinfalcon.js +++ b/exchange/wrappers/coinfalcon.js @@ -100,8 +100,6 @@ Trader.prototype.retry = function(method, args) { // run the failed method again with the same arguments after wait setTimeout(() => { - console.log('cf retry..'); - console.log(args); method.apply(this, args); }, wait); }; @@ -257,6 +255,7 @@ Trader.prototype.cancelOrder = function(order, callback) { const args = _.toArray(arguments); const handle = this.processResponse(this.cancelOrder, args, (err, res) => { + if(err) { if(err.message.includes('has wrong status.')) { @@ -284,7 +283,9 @@ Trader.prototype.cancelOrder = function(order, callback) { return callback(err); } - callback(undefined, false); + callback(undefined, false, { + filled: res.data.size_filled + }); }); this.coinfalcon.delete('user/orders/' + order).then(handle.success).catch(handle.failure); diff --git a/exchange/wrappers/gdax.js b/exchange/wrappers/gdax.js index 1717d47cc..96f6018b7 100644 --- a/exchange/wrappers/gdax.js +++ b/exchange/wrappers/gdax.js @@ -18,8 +18,8 @@ const Trader = function(config) { this.asset = config.asset; this.currency = config.currency; - this.api_url = 'https://api.gdax.com'; - this.api_sandbox_url = 'https://api-public.sandbox.gdax.com'; + this.api_url = 'https://api.pro.coinbase.com'; + this.api_sandbox_url = 'https://api-public.sandbox.pro.coinbase.com'; if (_.isObject(config)) { this.key = config.key; @@ -374,7 +374,7 @@ Trader.prototype.getTrades = function(since, callback, descending) { _.bind(handler, this), _.bind(process, this) ); - } else { + } else if (since) { console.log('Scanning back in the history needed...', since); } } diff --git a/exchange/wrappers/kraken-markets.json b/exchange/wrappers/kraken-markets.json index 5e6d401f7..ea43f4b22 100644 --- a/exchange/wrappers/kraken-markets.json +++ b/exchange/wrappers/kraken-markets.json @@ -736,7 +736,7 @@ ], "book": "XXDGXXBT", "minimalOrder": { - "amount": 0.01, + "amount": "3000", "unit": "asset" }, "pricePrecision": 8, diff --git a/exchange/wrappers/kraken.js b/exchange/wrappers/kraken.js index 4762eef01..7358902a0 100644 --- a/exchange/wrappers/kraken.js +++ b/exchange/wrappers/kraken.js @@ -43,8 +43,8 @@ const recoverableErrors = [ 'Empty response', 'API:Invalid nonce', 'General:Temporary lockout', - 'Response code 520', - 'Response code 525' + 'Response code 525', + 'Service:Busy' ]; // errors that might mean @@ -53,6 +53,7 @@ const unknownResultErrors = [ 'Response code 502', 'Response code 504', 'Response code 522', + 'Response code 520', ] const includes = (str, list) => { @@ -149,7 +150,9 @@ Trader.prototype.handleResponse = function(funcName, callback, nonMutating, payl throw 'a'; } - if(order.status === 'canceled') { + console.log(order); + + if(order.status !== 'canceled') { console.log(new Date, 'it still exists, retrying cancel'); return this.cancelOrder(payload, callback); } @@ -215,8 +218,8 @@ Trader.prototype.getPortfolio = function(callback) { const handle = (err, data) => { if(err) return callback(err); - const assetAmount = parseFloat( data.result[this.market.prefixed[1]] ); - const currencyAmount = parseFloat( data.result[this.market.prefixed[0]] ); + let assetAmount = parseFloat( data.result[this.market.prefixed[1]] ); + let currencyAmount = parseFloat( data.result[this.market.prefixed[0]] ); if(!_.isNumber(assetAmount) || _.isNaN(assetAmount)) { console.log(`Kraken did not return portfolio for ${this.asset}, assuming 0.`);