Skip to content
This repository has been archived by the owner on Feb 15, 2022. It is now read-only.

Corrected engine.js to include held assets in calculations for buy_max_amt and buy_pct #1112

Merged
merged 3 commits into from
Jan 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions lib/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
})
})
}

Expand Down Expand Up @@ -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')
Expand Down
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

306 changes: 206 additions & 100 deletions test/lib/engine.test.js
Original file line number Diff line number Diff line change
@@ -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() { },
Expand Down