Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Customise the last buy price removing threshold #206

Merged
merged 19 commits into from
Jul 7, 2021
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ data
log

.env
.vs
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
## Unreleased

- Support ATH buy restriction by [@habibalkhabbaz](https://github.com/habibalkhabbaz) - [#82](https://github.com/chrisleekr/binance-trading-bot/issues/82)
- Support last buy price removing threshold by [@pedrohusky](https://github.com/pedrohusky) - [#190](https://github.com/chrisleekr/binance-trading-bot/issues/190)

## [0.0.71] - 2021-06-14

Expand Down
179 changes: 134 additions & 45 deletions app/cronjob/trailingTrade/step/__tests__/remove-last-buy-price.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: true,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -98,6 +101,9 @@ describe('remove-last-buy-price.js', () => {
action: 'buy',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -150,6 +156,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -196,6 +205,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -242,6 +254,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -304,6 +319,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -357,6 +375,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -405,6 +426,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'ALPHABTC',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 0.0001 }
},
symbolInfo: {
filterLotSize: {
stepSize: '1.00000000',
Expand Down Expand Up @@ -467,6 +491,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -537,6 +564,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down Expand Up @@ -570,62 +600,118 @@ describe('remove-last-buy-price.js', () => {
});

describe('when cannot find open orders', () => {
beforeEach(async () => {
jest.mock('../../../trailingTradeHelper/common', () => ({
getAndCacheOpenOrdersForSymbol: mockGetAndCacheOpenOrdersForSymbol,
isActionDisabled: mockIsActionDisabled,
getAPILimit: mockGetAPILimit
}));
describe('last buy price remove threshold is same as minimum notional', () => {
beforeEach(async () => {
jest.mock('../../../trailingTradeHelper/common', () => ({
getAndCacheOpenOrdersForSymbol:
mockGetAndCacheOpenOrdersForSymbol,
isActionDisabled: mockIsActionDisabled,
getAPILimit: mockGetAPILimit
}));

const step = require('../remove-last-buy-price');
const step = require('../remove-last-buy-price');

rawData = {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
minQty: '0.01000000'
rawData = {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
filterMinNotional: {
minNotional: '10.00000000'
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
minQty: '0.01000000'
},
filterMinNotional: {
minNotional: '10.00000000'
}
},
openOrders: [],
baseAssetBalance: {
free: 0,
locked: 0.04
},
sell: {
currentPrice: 200,
lastBuyPrice: 160
}
},
openOrders: [],
baseAssetBalance: {
free: 0,
locked: 0.04
},
sell: {
currentPrice: 200,
lastBuyPrice: 160
}
};
};

result = await step.execute(loggerMock, rawData);
});
result = await step.execute(loggerMock, rawData);
});

it('triggers mongo.deleteOne', () => {
expect(mongoMock.deleteOne).toHaveBeenCalledWith(
loggerMock,
'trailing-trade-symbols',
{ key: 'BTCUPUSDT-last-buy-price' }
);
it('triggers mongo.deleteOne', () => {
expect(mongoMock.deleteOne).toHaveBeenCalledWith(
loggerMock,
'trailing-trade-symbols',
{ key: 'BTCUPUSDT-last-buy-price' }
);
});

it('returns expected data', () => {
expect(result).toStrictEqual({
...rawData,
...{
sell: {
currentPrice: 200,
lastBuyPrice: 160,
processMessage:
'Balance is less than the last buy price remove threshold. Delete last buy price.',
updatedAt: expect.any(Object)
}
}
});
});
});

it('returns expected data', () => {
expect(result).toStrictEqual({
...rawData,
...{
describe('last buy price remove threshold is less than minimum notional', () => {
beforeEach(async () => {
jest.mock('../../../trailingTradeHelper/common', () => ({
getAndCacheOpenOrdersForSymbol:
mockGetAndCacheOpenOrdersForSymbol,
isActionDisabled: mockIsActionDisabled,
getAPILimit: mockGetAPILimit
}));

const step = require('../remove-last-buy-price');

rawData = {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 5 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
minQty: '0.01000000'
},
filterMinNotional: {
minNotional: '10.00000000'
}
},
openOrders: [],
baseAssetBalance: {
free: 0,
locked: 0.04
},
sell: {
currentPrice: 200,
lastBuyPrice: 160,
processMessage:
'Balance is less than the notional value. Delete last buy price.',
updatedAt: expect.any(Object)
lastBuyPrice: 160
}
}
};

result = await step.execute(loggerMock, rawData);
});

it('does not trigger mongo.deleteOne', () => {
expect(mongoMock.deleteOne).not.toHaveBeenCalled();
});

it('returns expected data', () => {
expect(result).toStrictEqual(rawData);
});
});
});
Expand All @@ -645,6 +731,9 @@ describe('remove-last-buy-price.js', () => {
action: 'not-determined',
isLocked: false,
symbol: 'BTCUPUSDT',
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold: 10 }
},
symbolInfo: {
filterLotSize: {
stepSize: '0.01000000',
Expand Down
9 changes: 6 additions & 3 deletions app/cronjob/trailingTrade/step/remove-last-buy-price.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ const {
getAPILimit,
isActionDisabled
} = require('../../trailingTradeHelper/common');

/**
* Retrieve last buy order from cache
*
* @param {*} logger
* @param {*} symbol
* @returns
*/

const getLastBuyOrder = async (logger, symbol) => {
const cachedLastBuyOrder =
JSON.parse(await cache.get(`${symbol}-last-buy-order`)) || {};
Expand Down Expand Up @@ -67,6 +67,9 @@ const execute = async (logger, rawData) => {
isLocked,
action,
symbol,
symbolConfiguration: {
buy: { lastBuyPriceRemoveThreshold }
},
symbolInfo: {
filterLotSize: { stepSize, minQty },
filterMinNotional: { minNotional }
Expand Down Expand Up @@ -169,7 +172,7 @@ const execute = async (logger, rawData) => {
return data;
}

if (baseAssetQuantity * currentPrice < parseFloat(minNotional)) {
if (baseAssetQuantity * currentPrice < lastBuyPriceRemoveThreshold) {
// Final check for open orders
refreshedOpenOrders = await getAndCacheOpenOrdersForSymbol(logger, symbol);
if (refreshedOpenOrders.length > 0) {
Expand All @@ -178,7 +181,7 @@ const execute = async (logger, rawData) => {
}

processMessage =
'Balance is less than the notional value. Delete last buy price.';
'Balance is less than the last buy price remove threshold. Delete last buy price.';

logger.error({ baseAssetQuantity }, processMessage);

Expand Down
Loading