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

fix: exceeding max open trades #462

Merged
merged 21 commits into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
fea6d39
fix: exceeding max open trades
uhliksk Aug 8, 2022
6dfc0d0
Merge branch 'chrisleekr:master' into fix/exceeding-max-open-trades
uhliksk Aug 10, 2022
2f39816
Merge branch 'chrisleekr:master' into fix/exceeding-max-open-trades
uhliksk Aug 14, 2022
1fe9e72
fix: queue symbols to check max. open trades
uhliksk Aug 14, 2022
0f92374
fix: replace map with forEach
uhliksk Aug 14, 2022
a17331c
refactor: move cancelOrder to common
habibalkhabbaz Aug 14, 2022
0f285e6
Merge branch 'chrisleekr:master' into fix/exceeding-max-open-trades
uhliksk Aug 14, 2022
6d3bdef
fix: check if open orders exceeding the max open trades
habibalkhabbaz Aug 14, 2022
4157d8a
Merge branch 'fix/exceeding-max-open-trades' of https://github.com/uh…
habibalkhabbaz Aug 14, 2022
53f11e3
fix: missed husky
habibalkhabbaz Aug 14, 2022
5c488b3
fix: ensure-grid-trade-order-executed
habibalkhabbaz Aug 14, 2022
4c1cc08
fix: check open orders
habibalkhabbaz Aug 14, 2022
7672ba4
chore: lint
habibalkhabbaz Aug 14, 2022
5c4fbc2
fix: minor change
habibalkhabbaz Aug 14, 2022
d964d22
fix: clear open orders after cancellation
habibalkhabbaz Aug 14, 2022
6c8467f
test: handle-open-orders
habibalkhabbaz Aug 14, 2022
d7bb220
fix: clean open orders when order cancellation is successfull
uhliksk Aug 14, 2022
b7b47ab
refactor: updated handle open orders
chrisleekr Aug 15, 2022
12bbd3a
refactor: updated handle open orders
chrisleekr Aug 15, 2022
0acf1e6
chore: added comments
chrisleekr Aug 15, 2022
b492360
docs: updated CHANGELOG.md
chrisleekr Aug 15, 2022
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
310 changes: 74 additions & 236 deletions app/cronjob/trailingTrade/step/__tests__/determine-action.test.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ describe('ensure-grid-trade-order-executed.js', () => {
let mockGetGridTradeLastOrder;
let mockDeleteGridTradeOrder;

let mockQueue;

describe('execute', () => {
beforeEach(async () => {
jest.clearAllMocks().resetModules();
Expand All @@ -31,6 +33,12 @@ describe('ensure-grid-trade-order-executed.js', () => {
jest.requireActual('moment')(nextCheck || '2020-01-02T00:00:00+00:00')
);

mockQueue = {
executeFor: jest.fn().mockResolvedValue(true)
};

jest.mock('../../../trailingTradeHelper/queue', () => mockQueue);

const { slack, logger, PubSub } = require('../../../../helpers');

slackMock = slack;
Expand Down Expand Up @@ -488,6 +496,10 @@ describe('ensure-grid-trade-order-executed.js', () => {
);
});

it('triggers queue.executeFor', () => {
expect(mockQueue.executeFor).toHaveBeenCalled();
});

it('triggers saveOrderStats', () => {
expect(mockSaveOrderStats).toHaveBeenCalledWith(loggerMock, [
'BTCUSDT',
Expand Down
253 changes: 185 additions & 68 deletions app/cronjob/trailingTrade/step/__tests__/handle-open-orders.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ describe('handle-open-orders.js', () => {
let mockUpdateAccountInfo;
let mockSaveOverrideAction;

let mockIsExceedingMaxOpenTrades;

const accountInfoJSON = require('./fixtures/binance-account-info.json');

describe('execute', () => {
Expand All @@ -32,6 +34,8 @@ describe('handle-open-orders.js', () => {
mockUpdateAccountInfo = jest.fn().mockResolvedValue({
account: 'updated'
});

mockIsExceedingMaxOpenTrades = jest.fn().mockResolvedValue(false);
});

describe('when symbol is locked', () => {
Expand Down Expand Up @@ -626,35 +630,29 @@ describe('handle-open-orders.js', () => {
});

describe('when stop price is less than current limit price', () => {
beforeEach(async () => {
mockGetAccountInfo = jest.fn().mockResolvedValue(accountInfoJSON);
mockGetAndCacheOpenOrdersForSymbol = jest.fn().mockResolvedValue([]);
describe('when open trade limit is reached', () => {
beforeEach(async () => {
mockGetAccountInfo = jest.fn().mockResolvedValue(accountInfoJSON);
mockGetAndCacheOpenOrdersForSymbol = jest
.fn()
.mockResolvedValue([]);
mockIsExceedingMaxOpenTrades = jest.fn().mockResolvedValue(true);

jest.mock('../../../trailingTradeHelper/common', () => ({
getAccountInfo: mockGetAccountInfo,
updateAccountInfo: mockUpdateAccountInfo,
saveOverrideAction: mockSaveOverrideAction,
getAndCacheOpenOrdersForSymbol: mockGetAndCacheOpenOrdersForSymbol
}));
jest.mock('../../../trailingTradeHelper/common', () => ({
getAccountInfo: mockGetAccountInfo,
updateAccountInfo: mockUpdateAccountInfo,
saveOverrideAction: mockSaveOverrideAction,
getAndCacheOpenOrdersForSymbol:
mockGetAndCacheOpenOrdersForSymbol,
isExceedingMaxOpenTrades: mockIsExceedingMaxOpenTrades
}));

step = require('../handle-open-orders');
step = require('../handle-open-orders');

rawData = {
symbol: 'BTCUSDT',
isLocked: false,
action: 'not-determined',
openOrders: [
{
symbol: 'BTCUSDT',
orderId: 46838,
price: '1799.58000000',
stopPrice: '1800.1000',
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
],
buy: {
limitPrice: 1810,
rawData = {
symbol: 'BTCUSDT',
isLocked: false,
action: 'not-determined',
openOrders: [
{
symbol: 'BTCUSDT',
Expand All @@ -664,49 +662,155 @@ describe('handle-open-orders.js', () => {
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
]
},
sell: {
limitPrice: 1800,
openOrders: []
},
symbolInfo: {
quoteAsset: 'USDT'
}
};
],
buy: {
limitPrice: 1810,
openOrders: [
{
symbol: 'BTCUSDT',
orderId: 46838,
price: '1799.58000000',
stopPrice: '1800.1000',
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
]
},
sell: {
limitPrice: 1800,
openOrders: []
},
symbolInfo: {
quoteAsset: 'USDT'
}
};

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

it('does not trigger cancelOrder', () => {
expect(binanceMock.client.cancelOrder).not.toHaveBeenCalled();
});
it('does trigger cancelOrder', () => {
expect(binanceMock.client.cancelOrder).toHaveBeenCalled();
});

it('does not trigger getAndCacheOpenOrdersForSymbol', () => {
expect(mockGetAndCacheOpenOrdersForSymbol).not.toHaveBeenCalled();
});
it('does not trigger getAndCacheOpenOrdersForSymbol', () => {
expect(mockGetAndCacheOpenOrdersForSymbol).not.toHaveBeenCalled();
});

it('does not trigger getAccountInfo', () => {
expect(mockGetAccountInfo).not.toHaveBeenCalled();
it('does not trigger getAccountInfo', () => {
expect(mockGetAccountInfo).not.toHaveBeenCalled();
});

it('returns expected value', () => {
expect(result).toStrictEqual({
symbol: 'BTCUSDT',
isLocked: false,
action: 'buy-order-cancelled',
openOrders: [
{
symbol: 'BTCUSDT',
orderId: 46838,
price: '1799.58000000',
stopPrice: '1800.1000',
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
],
buy: {
limitPrice: 1810,
openOrders: [
{
symbol: 'BTCUSDT',
orderId: 46838,
price: '1799.58000000',
stopPrice: '1800.1000',
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
]
},
sell: { limitPrice: 1800, openOrders: [] },
symbolInfo: {
quoteAsset: 'USDT'
}
});
});
});

it('returns expected value', () => {
expect(result).toStrictEqual({
symbol: 'BTCUSDT',
isLocked: false,
action: 'buy-order-wait',
openOrders: [
{
symbol: 'BTCUSDT',
orderId: 46838,
price: '1799.58000000',
stopPrice: '1800.1000',
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
describe('when open trade limit is not reached', () => {
beforeEach(async () => {
mockGetAccountInfo = jest.fn().mockResolvedValue(accountInfoJSON);
mockGetAndCacheOpenOrdersForSymbol = jest
.fn()
.mockResolvedValue([]);
mockIsExceedingMaxOpenTrades = jest.fn().mockResolvedValue(false);

jest.mock('../../../trailingTradeHelper/common', () => ({
getAccountInfo: mockGetAccountInfo,
updateAccountInfo: mockUpdateAccountInfo,
saveOverrideAction: mockSaveOverrideAction,
getAndCacheOpenOrdersForSymbol:
mockGetAndCacheOpenOrdersForSymbol,
isExceedingMaxOpenTrades: mockIsExceedingMaxOpenTrades
}));

step = require('../handle-open-orders');

rawData = {
symbol: 'BTCUSDT',
isLocked: false,
action: 'not-determined',
openOrders: [
{
symbol: 'BTCUSDT',
orderId: 46838,
price: '1799.58000000',
stopPrice: '1800.1000',
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
],
buy: {
limitPrice: 1810,
openOrders: [
{
symbol: 'BTCUSDT',
orderId: 46838,
price: '1799.58000000',
stopPrice: '1800.1000',
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
]
},
sell: {
limitPrice: 1800,
openOrders: []
},
symbolInfo: {
quoteAsset: 'USDT'
}
],
buy: {
limitPrice: 1810,
};

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

it('does not trigger cancelOrder', () => {
expect(binanceMock.client.cancelOrder).not.toHaveBeenCalled();
});

it('does not trigger getAndCacheOpenOrdersForSymbol', () => {
expect(mockGetAndCacheOpenOrdersForSymbol).not.toHaveBeenCalled();
});

it('does not trigger getAccountInfo', () => {
expect(mockGetAccountInfo).not.toHaveBeenCalled();
});

it('returns expected value', () => {
expect(result).toStrictEqual({
symbol: 'BTCUSDT',
isLocked: false,
action: 'buy-order-wait',
openOrders: [
{
symbol: 'BTCUSDT',
Expand All @@ -716,12 +820,25 @@ describe('handle-open-orders.js', () => {
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
]
},
sell: { limitPrice: 1800, openOrders: [] },
symbolInfo: {
quoteAsset: 'USDT'
}
],
buy: {
limitPrice: 1810,
openOrders: [
{
symbol: 'BTCUSDT',
orderId: 46838,
price: '1799.58000000',
stopPrice: '1800.1000',
type: 'STOP_LOSS_LIMIT',
side: 'BUY'
}
]
},
sell: { limitPrice: 1800, openOrders: [] },
symbolInfo: {
quoteAsset: 'USDT'
}
});
});
});
});
Expand Down
41 changes: 1 addition & 40 deletions app/cronjob/trailingTrade/step/determine-action.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { slack } = require('../../../helpers');
const {
isActionDisabled,
getNumberOfBuyOpenOrders,
getNumberOfOpenTrades,
isExceedingMaxOpenTrades,
getAPILimit
} = require('../../trailingTradeHelper/common');
const { getGridTradeOrder } = require('../../trailingTradeHelper/order');
Expand Down Expand Up @@ -122,45 +122,6 @@ const isExceedingMaxBuyOpenOrders = async (logger, data) => {
return false;
};

/**
* Check whether max number of open trades has reached
*
* @param {*} logger
* @param {*} data
* @returns
*/
const isExceedingMaxOpenTrades = async (logger, data) => {
const {
symbolConfiguration: {
botOptions: {
orderLimit: {
enabled: orderLimitEnabled,
maxOpenTrades: orderLimitMaxOpenTrades
}
}
},
sell: { lastBuyPrice }
} = data;

if (orderLimitEnabled === false) {
return false;
}

let currentOpenTrades = await getNumberOfOpenTrades(logger);

// If the last buy price is recorded, this is one of open trades.
// Deduct 1 from the current open trades and calculate it.
if (lastBuyPrice) {
currentOpenTrades -= 1;
}

if (currentOpenTrades >= orderLimitMaxOpenTrades) {
return true;
}

return false;
};

/**
* Set buy action and message
*
Expand Down
Loading