From 9c6ad4ccef327993154d81a41782e0948c2e9aed Mon Sep 17 00:00:00 2001 From: T-rav Date: Fri, 12 Jan 2018 14:03:01 +0200 Subject: [PATCH] Cherry picked master branch changes into unstable branch --- lib/engine.js | 31 ++-- package-lock.json | 1 + test/lib/engine.test.js | 306 +++++++++++++++++++++++++++------------- 3 files changed, 225 insertions(+), 113 deletions(-) diff --git a/lib/engine.js b/lib/engine.js index b9baf0dfd5..2a295dc93c 100644 --- a/lib/engine.js +++ b/lib/engine.js @@ -18,6 +18,7 @@ module.exports = function container (get, set, clear) { s.product_id = so.selector.product_id s.asset = so.selector.asset s.currency = so.selector.currency + s.asset_capital = 0 if (typeof so.period_length == 'undefined') so.period_length = so.period @@ -192,18 +193,19 @@ module.exports = function container (get, set, clear) { s.exchange.getBalance({currency: s.currency, asset: s.asset}, function (err, balance) { if (err) return cb(err) s.balance = balance - if (!s.start_capital) { - s.exchange.getQuote({product_id: s.product_id}, function (err, quote) { - if (err) return cb(err) + s.exchange.getQuote({product_id: s.product_id}, function (err, quote) { + if (err) return cb(err) + + if (!s.start_capital) { s.start_price = n(quote.ask).value() s.start_capital = n(s.balance.currency).add(n(s.balance.asset).multiply(quote.ask)).value() pushMessage('Balance ' + s.exchange.name.toUpperCase(), 'sync balance ' + s.start_capital + ' ' + s.currency + '\n') - - cb() - }) - } - else cb() + } + + s.asset_capital = n(s.balance.asset).multiply(quote.ask).value() + cb() + }) }) } @@ -435,11 +437,14 @@ module.exports = function container (get, set, clear) { if (!size) { if (so.mode === 'live' || so.mode === 'paper') { var buy_pct = so.buy_pct - if(so.buy_max_amt){ - var buy_max_as_pct = n(so.buy_max_amt).divide(s.balance.currency).multiply(100) - if(buy_max_as_pct < buy_pct){ - buy_pct = buy_max_as_pct - } + if(so.buy_max_amt){ // account for held assets as buy_max + var adjusted_buy_max_amt = n(so.buy_max_amt).subtract(s.asset_capital).value() + var buy_max_as_pct = n(adjusted_buy_max_amt).divide(s.balance.currency).multiply(100).value() + buy_pct = buy_max_as_pct + }else{ // account for held assets as % + var held_pct = n(s.asset_capital).divide(s.balance.currency).multiply(100).value() + var to_buy_pct = n(so.buy_pct).subtract(held_pct).value() + buy_pct = to_buy_pct } if (so.order_type === 'maker') { size = n(s.balance.currency).multiply(buy_pct).divide(100).multiply(s.exchange.makerFee / 100).format('0.00000000') diff --git a/package-lock.json b/package-lock.json index 2655853faa..1c4fad6996 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12206,3 +12206,4 @@ } } } + diff --git a/test/lib/engine.test.js b/test/lib/engine.test.js index 2b44bb56c6..4a3bd62bef 100644 --- a/test/lib/engine.test.js +++ b/test/lib/engine.test.js @@ -1,121 +1,227 @@ describe("Engine", function() { describe("executeSignal", function() { - describe("when maker", function(){ - it("with buy_max_amt less than buy_pct amount should use buy_max_amt", function(){ - // arrange - var signal_type = "buy" - var currency_amount = 1 - var buy_pct = 50 - var buy_max_amt = 0.25 - var order_type = "maker" - var buy_spy = jasmine.createSpy() - var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, buy_spy) - // act - sut.executeSignal(signal_type) - // assert - var expected = "2.77500000" - var buyArgs = buy_spy.calls.mostRecent().args[0] - expect(buyArgs.size).toBe(expected) + describe("when maker in live mode", function(){ + describe("with buy_max set", function(){ + it("and no held assets should use raw buy_max_amt", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1.0 + var buy_pct = 50 + var buy_max_amt = 0.25 + var order_type = "maker" + var held_asset = 0 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + var expected = "2.77500000" + var buyArgs = buy_spy.calls.mostRecent().args[0] + expect(buyArgs.size).toBe(expected) + }) + it("and held assets should use adjusted buy_max_amt", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 3.0 + var buy_pct = 50 + var buy_max_amt = 0.25 + var order_type = "maker" + var held_asset = 0.75 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + var expected = "1.85925000" + var buyArgs = buy_spy.calls.mostRecent().args[0] + expect(buyArgs.size).toBe(expected) + }) + it("and held assets so large adjusted buy_max_amt is below order minimum should not place order", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1.0 + var buy_pct = 50 + var buy_max_amt = 0.25 + var order_type = "maker" + var held_asset = 2.0 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + expect(buy_spy).not.toHaveBeenCalled() + }) }) - - it("with buy_max_amt more than buy_pct amount should use buy_pct", function(){ - // arrange - var signal_type = "buy" - var currency_amount = 1 - var buy_pct = 50 - var buy_max_amt = 0.75 - var order_type = "maker" - var buy_spy = jasmine.createSpy() - var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, buy_spy) - // act - sut.executeSignal(signal_type) - // assert - var expected = "5.55000000" - var buyArgs = buy_spy.calls.mostRecent().args[0] - expect(buyArgs.size).toBe(expected) - }) - - it("with buy_max_amt equals buy_pct amount should use buy_pct", function(){ - // arrange - var signal_type = "buy" - var currency_amount = 1 - var buy_pct = 50 - var buy_max_amt = 0.50 - var order_type = "maker" - var buy_spy = jasmine.createSpy() - var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, buy_spy) - // act - sut.executeSignal(signal_type) - // assert - var expected = "5.55000000" - var buyArgs = buy_spy.calls.mostRecent().args[0] - expect(buyArgs.size).toBe(expected) + describe("with no buy_max set", function(){ + it("and no held assets should use raw buy_pct", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1.0 + var buy_pct = 50 + var buy_max_amt = undefined + var order_type = "maker" + var held_asset = 0 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + var expected = "5.55000000" + var buyArgs = buy_spy.calls.mostRecent().args[0] + expect(buyArgs.size).toBe(expected) + }) + it("and held assets should use adjusted buy_pct", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1.0 + var buy_pct = 50 + var buy_max_amt = undefined + var order_type = "maker" + var held_asset = 0.5 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + var expected = "4.93950000" + var buyArgs = buy_spy.calls.mostRecent().args[0] + expect(buyArgs.size).toBe(expected) + }) + it("and held assets so large adjusted buy_pct is below order minimum should not place order", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1.0 + var buy_pct = 50 + var buy_max_amt = undefined + var order_type = "maker" + var held_asset = 5.25 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + expect(buy_spy).not.toHaveBeenCalled() + }) }) }) - describe("when taker", function(){ - it("with buy_max_amt less than buy_pct amount should use buy_max_amt", function(){ - // arrange - var signal_type = "buy" - var currency_amount = 1 - var buy_pct = 50 - var buy_max_amt = 0.25 - var order_type = "taker" - var buy_spy = jasmine.createSpy() - var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, buy_spy) - // act - sut.executeSignal(signal_type) - // assert - var expected = "2.77222222" - var buyArgs = buy_spy.calls.mostRecent().args[0] - expect(buyArgs.size).toBe(expected) - }) - - it("with buy_max_amt more than buy_pct amount should use buy_pct", function(){ - // arrange - var signal_type = "buy" - var currency_amount = 1 - var buy_pct = 50 - var buy_max_amt = 0.75 - var order_type = "taker" - var buy_spy = jasmine.createSpy() - var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, buy_spy) - // act - sut.executeSignal(signal_type) - // assert - var expected = "5.54444444" - var buyArgs = buy_spy.calls.mostRecent().args[0] - expect(buyArgs.size).toBe(expected) + describe("when taker in live mode", function(){ + describe("with buy_max_amt set",function(){ + it("and no held assets should use raw buy_max_amt", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1 + var buy_pct = 50 + var buy_max_amt = 0.25 + var order_type = "taker" + var held_asset = 0 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + var expected = "2.77222222" + var buyArgs = buy_spy.calls.mostRecent().args[0] + expect(buyArgs.size).toBe(expected) + }) + + it("and held assets should use adjusted buy_max_amt", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 3.0 + var buy_pct = 50 + var buy_max_amt = 0.25 + var order_type = "taker" + var held_asset = 0.75 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + var expected = "1.85738888" + var buyArgs = buy_spy.calls.mostRecent().args[0] + expect(buyArgs.size).toBe(expected) + }) + + it("and held assets so large adjusted buy_max_amt is below order minimum should not place order", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1.0 + var buy_pct = 50 + var buy_max_amt = 0.25 + var order_type = "taker" + var held_asset = 2.0 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + expect(buy_spy).not.toHaveBeenCalled() + }) }) - - it("with buy_max_amt equals buy_pct amount should use buy_pct", function(){ - // arrange - var signal_type = "buy" - var currency_amount = 1 - var buy_pct = 50 - var buy_max_amt = 0.50 - var order_type = "taker" - var buy_spy = jasmine.createSpy() - var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, buy_spy) - // act - sut.executeSignal(signal_type) - // assert - var expected = "5.54444444" - var buyArgs = buy_spy.calls.mostRecent().args[0] - expect(buyArgs.size).toBe(expected) + describe("with no buy_max_amt set",function(){ + it("with no buy_max_amt set and no held assets should use raw buy_pct", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1 + var buy_pct = 50 + var buy_max_amt = undefined + var order_type = "taker" + var held_asset = 0 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + var expected = "5.54444444" + var buyArgs = buy_spy.calls.mostRecent().args[0] + expect(buyArgs.size).toBe(expected) + }) + it("and held assets should use adjusted buy_pct", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1.0 + var buy_pct = 50 + var buy_max_amt = undefined + var order_type = "taker" + var held_asset = 0.5 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + var expected = "4.93455555" + var buyArgs = buy_spy.calls.mostRecent().args[0] + expect(buyArgs.size).toBe(expected) + }) + it("and held assets so large adjusted buy_pct is below order minimum should not place order", function(){ + // arrange + var signal_type = "buy" + var currency_amount = 1.0 + var buy_pct = 50 + var buy_max_amt = undefined + var order_type = "taker" + var held_asset = 5.25 + var buy_spy = jasmine.createSpy() + var sut = createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy) + // act + sut.executeSignal(signal_type) + // assert + expect(buy_spy).not.toHaveBeenCalled() + }) }) }) }) }) -function createEngine(currency_amount, buy_pct, buy_max_amt, order_type, buy_spy){ +function createEngine(currency_amount, buy_pct, buy_max_amt, order_type, held_asset, buy_spy){ var fake_asset = "test_asset" var fake_currency = "BTC" var fake_exchange = "test_exchange" var fake_project = "test_product" var fake_bid = 0.10 var fake_ask = 0.11 - var fake_balance = { currency: currency_amount, asset:0} + var fake_balance = { currency: currency_amount, asset:held_asset} var fakes = { get: function() { },