Skip to content

Commit

Permalink
Bug fix with configuration (#58)
Browse files Browse the repository at this point in the history
* Fix typo that caused buying action was not applied

* Updated global configuration to be able to apply for all symbols

* Updated symbol configuration to be able to reset to the global configuration
  • Loading branch information
chrisleekr authored Mar 27, 2021
1 parent c73ff5b commit 408f52d
Show file tree
Hide file tree
Showing 30 changed files with 929 additions and 324 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,8 @@ Or use the frontend to adjust configurations after launching the application.
- [x] Fix the bug with handling open orders
- [x] Fix the bug with limit step in the frontend
- [x] Updated the frontend to display buy open orders with the buy signal
- [x] Add frontend option to update all symbol configurations
- [ ] Update the bot to monitor all coins every second
- [ ] Add frontend option to update all symbol configurations
- [ ] Add frontend option to disable sorting
- [ ] Add minimum required order amount
- [ ] Allow browser notification in the frontend
Expand All @@ -328,6 +328,7 @@ Or use the frontend to adjust configurations after launching the application.
- [@OOtta](https://github.com/OOtta)
- [@ienthach](https://github.com/ienthach)
- [@PlayeTT](https://github.com/PlayeTT)
- [@chopeta](https://github.com/chopeta)

## Contributors

Expand Down
65 changes: 57 additions & 8 deletions app/helpers/__tests__/mongo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('mongo.js', () => {
let mockFindOne;
let mockInsertOne;
let mockUpdateOne;
let mockDeleteMany;
let mockDeleteOne;

beforeEach(() => {
Expand Down Expand Up @@ -121,13 +122,13 @@ describe('mongo.js', () => {

await mongo.connect(logger);

result = await mongo.findOne(logger, 'simple-stop-chaser-common', {
result = await mongo.findOne(logger, 'trailing-stop-common', {
key: 'configuration'
});
});

it('triggers database.collection', () => {
expect(mockCollection).toHaveBeenCalledWith('simple-stop-chaser-common');
expect(mockCollection).toHaveBeenCalledWith('trailing-stop-common');
});

it('triggers collection.findOne', () => {
Expand Down Expand Up @@ -172,14 +173,14 @@ describe('mongo.js', () => {

await mongo.connect(logger);

result = await mongo.insertOne(logger, 'simple-stop-chaser-common', {
result = await mongo.insertOne(logger, 'trailing-stop-common', {
key: 'configuration',
my: 'value'
});
});

it('triggers database.collection', () => {
expect(mockCollection).toHaveBeenCalledWith('simple-stop-chaser-common');
expect(mockCollection).toHaveBeenCalledWith('trailing-stop-common');
});

it('triggers collection.insertOne', () => {
Expand Down Expand Up @@ -224,7 +225,7 @@ describe('mongo.js', () => {

result = await mongo.upsertOne(
logger,
'simple-stop-chaser-common',
'trailing-stop-common',
{
key: 'configuration'
},
Expand All @@ -236,7 +237,7 @@ describe('mongo.js', () => {
});

it('triggers database.collection', () => {
expect(mockCollection).toHaveBeenCalledWith('simple-stop-chaser-common');
expect(mockCollection).toHaveBeenCalledWith('trailing-stop-common');
});

it('triggers collection.upsertOne', () => {
Expand All @@ -261,6 +262,54 @@ describe('mongo.js', () => {
});
});

describe('deleteAll', () => {
beforeEach(async () => {
mockDeleteMany = jest.fn().mockResolvedValue(true);
mockCollection = jest.fn(() => ({
deleteMany: mockDeleteMany
}));

mockDBCommand = jest.fn().mockResolvedValue(true);
mockDB = jest.fn(() => ({
command: mockDBCommand,
collection: mockCollection
}));

mockMongoClient = jest.fn(() => ({
connect: jest.fn().mockResolvedValue(true),
db: mockDB
}));

jest.mock('mongodb', () => ({
MongoClient: mockMongoClient
}));

require('mongodb');

mongo = require('../mongo');

await mongo.connect(logger);

result = await mongo.deleteAll(logger, 'trailing-stop-common', {
key: 'configuration'
});
});

it('triggers database.collection', () => {
expect(mockCollection).toHaveBeenCalledWith('trailing-stop-common');
});

it('triggers collection.deleteMany', () => {
expect(mockDeleteMany).toHaveBeenCalledWith({
key: 'configuration'
});
});

it('returns expected result', () => {
expect(result).toStrictEqual(true);
});
});

describe('deleteOne', () => {
beforeEach(async () => {
mockDeleteOne = jest.fn().mockResolvedValue(true);
Expand Down Expand Up @@ -289,13 +338,13 @@ describe('mongo.js', () => {

await mongo.connect(logger);

result = await mongo.deleteOne(logger, 'simple-stop-chaser-common', {
result = await mongo.deleteOne(logger, 'trailing-stop-common', {
key: 'configuration'
});
});

it('triggers database.collection', () => {
expect(mockCollection).toHaveBeenCalledWith('simple-stop-chaser-common');
expect(mockCollection).toHaveBeenCalledWith('trailing-stop-common');
});

it('triggers collection.deleteOne', () => {
Expand Down
20 changes: 19 additions & 1 deletion app/helpers/mongo.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ const upsertOne = async (funcLogger, collectionName, filter, document) => {
return result;
};

const deleteAll = async (funcLogger, collectionName, filter) => {
const logger = funcLogger.child({ helper: 'mongo', funcName: 'deleteAll' });

logger.info({ collectionName, filter }, 'Deleting documents from MongoDB');
const collection = database.collection(collectionName);
const result = collection.deleteMany(filter);
logger.info({ result }, 'Deleted documents from MongoDB');

return result;
};

const deleteOne = async (funcLogger, collectionName, filter) => {
const logger = funcLogger.child({ helper: 'mongo', funcName: 'deleteOne' });

Expand All @@ -80,4 +91,11 @@ const deleteOne = async (funcLogger, collectionName, filter) => {
return result;
};

module.exports = { connect, findOne, insertOne, upsertOne, deleteOne };
module.exports = {
connect,
findOne,
insertOne,
upsertOne,
deleteAll,
deleteOne
};
36 changes: 36 additions & 0 deletions app/jobs/trailingTrade/__tests__/configuration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,42 @@ describe('configuration.js', () => {
});
});

describe('deleteAllSymbolConfiguration', () => {
beforeEach(async () => {
mongo.deleteAll = jest.fn().mockResolvedValue(true);

result = await configuration.deleteAllSymbolConfiguration(logger);
});

it('trigger mongo.deleteAll', () => {
expect(mongo.deleteAll).toHaveBeenCalledWith(
logger,
'trailing-trade-symbols',
{
key: { $regex: /^(.+)-configuration/ }
}
);
});
});

describe('deleteSymbolConfiguration', () => {
beforeEach(async () => {
mongo.deleteOne = jest.fn().mockResolvedValue(true);

result = await configuration.deleteSymbolConfiguration(logger, 'BTCUSDT');
});

it('trigger mongo.deleteOne', () => {
expect(mongo.deleteOne).toHaveBeenCalledWith(
logger,
'trailing-trade-symbols',
{
key: `BTCUSDT-configuration`
}
);
});
});

describe('getConfiguration', () => {
beforeEach(() => {
mongo.upsertOne = jest.fn().mockResolvedValue(true);
Expand Down
12 changes: 12 additions & 0 deletions app/jobs/trailingTrade/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ const saveSymbolConfiguration = async (
);
};

const deleteAllSymbolConfiguration = async logger =>
mongo.deleteAll(logger, 'trailing-trade-symbols', {
key: { $regex: /^(.+)-configuration/ }
});

const deleteSymbolConfiguration = async (logger, symbol) =>
mongo.deleteOne(logger, 'trailing-trade-symbols', {
key: `${symbol}-configuration`
});

/**
* Get global/symbol configuration
*
Expand Down Expand Up @@ -131,5 +141,7 @@ module.exports = {
getSymbolConfiguration,
saveGlobalConfiguration,
saveSymbolConfiguration,
deleteAllSymbolConfiguration,
deleteSymbolConfiguration,
getConfiguration
};
86 changes: 55 additions & 31 deletions app/jobs/trailingTrade/step/__tests__/get-indicators.test.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
/* eslint-disable global-require */
const { binance, mongo, cache, logger } = require('../../../../helpers');

const step = require('../get-indicators');

describe('get-indicators.js', () => {
let result;
let rawData;
let step;

let binanceMock;
let loggerMock;

let mockGetLastBuyPrice;

describe('execute', () => {
beforeEach(() => {
cache.hget = jest.fn().mockResolvedValue(undefined);
cache.hset = jest.fn().mockResolvedValue(true);
mongo.findOne = jest.fn().mockResolvedValue(undefined);
binance.client.candles = jest.fn().mockResolvedValue();
binance.client.exchangeInfo = jest.fn().mockResolvedValue();
jest.clearAllMocks().resetModules();
});

describe('wit no open orders and no last buy price', () => {
describe('with no open orders and no last buy price', () => {
beforeEach(async () => {
mongo.findOne = jest.fn().mockResolvedValue(undefined);
const { binance, logger } = require('../../../../helpers');
binanceMock = binance;
loggerMock = logger;

binance.client.candles = jest
mockGetLastBuyPrice = jest.fn().mockResolvedValue(null);
jest.mock('../../symbol', () => ({
getLastBuyPrice: mockGetLastBuyPrice
}));
binanceMock.client = {};
binanceMock.client.candles = jest
.fn()
.mockResolvedValue(require('./fixtures/binance-candles.json'));

step = require('../get-indicators');

rawData = {
symbol: 'BTCUSDT',
symbolConfiguration: {
Expand All @@ -44,12 +52,8 @@ describe('get-indicators.js', () => {
result = await step.execute(logger, rawData);
});

it('triggers mongo.findOne', () => {
expect(mongo.findOne).toHaveBeenCalledWith(
logger,
'trailing-trade-symbols',
{ key: 'BTCUSDT-last-buy-price' }
);
it('triggers getLastBuyPrice', () => {
expect(mockGetLastBuyPrice).toHaveBeenCalledWith(loggerMock, 'BTCUSDT');
});

it('triggers expected value', () => {
Expand Down Expand Up @@ -106,14 +110,21 @@ describe('get-indicators.js', () => {

describe('with no open orders and last buy price', () => {
beforeEach(async () => {
mongo.findOne = jest.fn().mockResolvedValue({
lastBuyPrice: 9000
});
const { binance, logger } = require('../../../../helpers');
binanceMock = binance;
loggerMock = logger;

binance.client.candles = jest
mockGetLastBuyPrice = jest.fn().mockResolvedValue(9000);
jest.mock('../../symbol', () => ({
getLastBuyPrice: mockGetLastBuyPrice
}));
binanceMock.client = {};
binanceMock.client.candles = jest
.fn()
.mockResolvedValue(require('./fixtures/binance-candles.json'));

step = require('../get-indicators');

rawData = {
symbol: 'BTCUSDT',
symbolConfiguration: {
Expand Down Expand Up @@ -164,12 +175,8 @@ describe('get-indicators.js', () => {
result = await step.execute(logger, rawData);
});

it('triggers mongo.findOne', () => {
expect(mongo.findOne).toHaveBeenCalledWith(
logger,
'trailing-trade-symbols',
{ key: 'BTCUSDT-last-buy-price' }
);
it('triggers getLastBuyPrice', () => {
expect(mockGetLastBuyPrice).toHaveBeenCalledWith(loggerMock, 'BTCUSDT');
});

it('triggers expected value', () => {
Expand Down Expand Up @@ -319,12 +326,20 @@ describe('get-indicators.js', () => {

describe('with open orders and no last buy price', () => {
beforeEach(async () => {
mongo.findOne = jest.fn().mockResolvedValue(undefined);
const { binance, logger } = require('../../../../helpers');
binanceMock = binance;
loggerMock = logger;

binance.client.candles = jest
mockGetLastBuyPrice = jest.fn().mockResolvedValue(null);
jest.mock('../../symbol', () => ({
getLastBuyPrice: mockGetLastBuyPrice
}));
binanceMock.client = {};
binanceMock.client.candles = jest
.fn()
.mockResolvedValue(require('./fixtures/binance-candles.json'));

step = require('../get-indicators');
rawData = {
symbol: 'BTCUSDT',
symbolConfiguration: {
Expand Down Expand Up @@ -524,12 +539,21 @@ describe('get-indicators.js', () => {

describe('with balance is not found', () => {
beforeEach(async () => {
mongo.findOne = jest.fn().mockResolvedValue(undefined);
const { binance, logger } = require('../../../../helpers');
binanceMock = binance;
loggerMock = logger;

binance.client.candles = jest
mockGetLastBuyPrice = jest.fn().mockResolvedValue(null);
jest.mock('../../symbol', () => ({
getLastBuyPrice: mockGetLastBuyPrice
}));
binanceMock.client = {};
binanceMock.client.candles = jest
.fn()
.mockResolvedValue(require('./fixtures/binance-candles.json'));

step = require('../get-indicators');

rawData = {
symbol: 'BTCUSDT',
symbolConfiguration: {
Expand Down
Loading

0 comments on commit 408f52d

Please sign in to comment.