Skip to content

Commit

Permalink
Merge pull request #20 from Adamant-im/dev
Browse files Browse the repository at this point in the history
v5.3.0
  • Loading branch information
adamant-al authored Feb 25, 2023
2 parents ac4642a + cfbf081 commit 6b19811
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 909 deletions.
1 change: 0 additions & 1 deletion config.default.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@

/** List of supported exchanges **/
"exchanges": [
"CoinDeal",
"Resfinex",
"P2PB2B"
],
Expand Down
109 changes: 88 additions & 21 deletions helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ const log = require('./log');
const tradeParams = require('../trade/settings/tradeParams_' + config.exchange);
const fs = require('fs');
const { SAT, EPOCH, MINUTE, LIQUIDITY_SS_MAX_SPREAD_PERCENT } = require('./const');
const equal = require('fast-deep-equal');

const AVERAGE_SPREAD_DEVIATION = 0.15;

module.exports = {

saveConfig(isWebApi = false) {
const toSave = 'module.exports = ' + JSON.stringify(tradeParams, null, 2).replace(/"/g, '\'').replace(/\n\}/g, ',\n};\n');
fs.writeFileSync('./trade/settings/tradeParams_' + config.exchange + '.js', toSave);
let oldConfig;
eval(fs.readFileSync(config.fileWithPath).toString().replace('module.exports', 'oldConfig'));
if (!equal(tradeParams, oldConfig)) {
const toSave = 'module.exports = ' + JSON.stringify(tradeParams, null, 2).replace(/"/g, '\'').replace(/\n\}/g, ',\n};\n');
fs.writeFileSync(config.fileWithPath, toSave);
log.log(`Config is updated and saved: ${config.file}`);
}
},

/**
Expand Down Expand Up @@ -125,6 +130,25 @@ module.exports = {
} catch (e) { }
},

/**
* Rounds up to precision
* roundUp(6, 10) -> 10
* roundUp(30, 10) -> 30
* roundUp(31, 10) -> 30
* roundUp(36, 10) -> 40
* roundUp(561, 100) -> 600
* roundUp(66, 5) -> 65
* roundUp(1, 10) -> 1
* roundUp(7, 10) -> 1
* @param {Number} value Value to round up
* @param {Number} precision 5, 10, 100, etc.
* @return {Number} Rounded value
*/
roundUp(value, precision) {
if (!this.isNumber(value) || !this.isInteger(precision) || precision < 1 || value < precision) return value;
return Math.round(value / precision) * precision;
},

/**
* Returns integer random of (min-max)
* @param {number} min Minimum is inclusive
Expand Down Expand Up @@ -1211,14 +1235,33 @@ module.exports = {

/**
* Returns decimals for precision
* @param precision e.g. 0.00001
* 0.00001 -> 5
* 1000 -> 0
* 1 -> 0
* 0 -> undefined
* @param {Number|String} precision e.g. 0.00001
* @returns {number} returns 5
*/
getDecimalsFromPrecision(precision) {
if (!precision) return;
if (precision > 1) return 0;
return Math.round(Math.abs(Math.log10(+precision)));
},

/**
* Returns decimals for precision for number greater than 1
* 0.00001 -> 5
* 1000 -> -3
* 1 -> 0
* 0 -> undefined
* @param {Number|String} precision e.g. 0.00001
* @returns {number} returns 5
*/
getDecimalsFromPrecisionForBigNumbers(precision) {
if (!precision) return;
return Math.round(-Math.log10(+precision));
},

/**
* Checks if order price is out of order book custom percent (as mm_liquiditySpreadPercent) spread
* @param order Object of ordersDb
Expand Down Expand Up @@ -1397,28 +1440,42 @@ module.exports = {
/**
* Creates a difference string for current and previous balances
* @param {Array of Object} a Current balances
* @param {Array of Object} b Previous balances
* @param {Object<timestamp, balances>} b Previous balances with timestamp
* @return {String} Difference string
*/
differenceInBalancesString(a, b, marketInfo) {
let output = '';
const diff = this.differenceInBalances(a, b);
const diff = this.differenceInBalances(a, b?.balances);
const timeDiffString = b?.timestamp ? ' in ' + this.timestampInDaysHoursMins(Date.now() - b.timestamp) : '';
if (diff) {
if (diff[0]) {
output += '\nChanges:\n';
let delta; let deltaUSD = 0; let deltaBTC = 0; let deltaCoin1 = 0; let deltaCoin2 = 0;
let sign; let signUSD = ''; let signBTC = ''; let signCoin1 = ''; let signCoin2 = '';
output += `\nChanges${timeDiffString}:\n`;

let delta; let deltaTotalUSD = 0; let deltaTotalBTC = 0;
let deltaCoin1 = 0; let deltaCoin2 = 0; let deltaTotalNonCoin1USD = 0; let deltaTotalNonCoin1BTC = 0;
let sign; let signTotalUSD = ''; let signTotalBTC = '';
let signCoin1 = ''; let signCoin2 = ''; let signTotalNonCoin1USD = ''; let signTotalNonCoin1BTC = '';
diff.forEach((crypto) => {
delta = Math.abs(crypto.now - crypto.prev);
sign = crypto.now > crypto.prev ? '+' : '−';
if (crypto.code === 'totalUSD') {
deltaUSD = delta;
signUSD = sign;
deltaTotalUSD = delta;
signTotalUSD = sign;
return;
}
if (crypto.code === 'totalBTC') {
deltaBTC = delta;
signBTC = sign;
deltaTotalBTC = delta;
signTotalBTC = sign;
return;
}
if (crypto.code === 'totalNonCoin1USD') {
deltaTotalNonCoin1USD = delta;
signTotalNonCoin1USD = sign;
return;
}
if (crypto.code === 'totalNonCoin1BTC') {
deltaTotalNonCoin1BTC = delta;
signTotalNonCoin1BTC = sign;
return;
}
if (crypto.code === config.coin1) {
Expand All @@ -1432,13 +1489,25 @@ module.exports = {
output += `_${crypto.code}_: ${sign}${this.formatNumber(+(delta).toFixed(8), true)}`;
output += '\n';
});
output += `Total holdings ${signUSD}${this.formatNumber(+deltaUSD.toFixed(2), true)} _USD_ or ${signBTC}${this.formatNumber(deltaBTC.toFixed(8), true)} _BTC_`;
if (deltaCoin1 && deltaCoin2 && (signCoin1 !== signCoin2)) {
const price = deltaCoin2 / deltaCoin1;

if (Math.abs(deltaTotalUSD)> 0.01 || Math.abs(deltaTotalBTC > 0.00000009)) {
output += `Total holdings ${signTotalUSD}${this.formatNumber(+deltaTotalUSD.toFixed(2), true)} _USD_ or ${signTotalBTC}${this.formatNumber(deltaTotalBTC.toFixed(8), true)} _BTC_`;
} else {
output += `Total holdings ~ No changes`;
}

if (Math.abs(deltaTotalNonCoin1USD) > 0.01 || Math.abs(deltaTotalNonCoin1BTC) > 0.00000009) {
output += `\nTotal holdings (non-${config.coin1}) ${signTotalNonCoin1USD}${this.formatNumber(+deltaTotalNonCoin1USD.toFixed(2), true)} _USD_ or ${signTotalNonCoin1BTC}${this.formatNumber(deltaTotalNonCoin1BTC.toFixed(8), true)} _BTC_`;
} else {
output += `\nTotal holdings (non-${config.coin1}) ~ No changes`;
}

if (deltaCoin1 && deltaTotalNonCoin1USD && (signCoin1 !== signTotalNonCoin1USD)) {
const price = deltaTotalNonCoin1USD / deltaCoin1;
output += `\n[Can be wrong] ${signCoin1 === '+' ? 'I\'ve bought' : 'I\'ve sold'} ${this.formatNumber(+deltaCoin1.toFixed(marketInfo.coin1Decimals), true)} _${config.coin1}_ at ${this.formatNumber(price.toFixed(marketInfo.coin2Decimals), true)} _${config.coin2}_ price.`;
}
} else {
output += '\nNo changes.\n';
output += `\nNo changes${timeDiffString}.\n`;
}
}
return output;
Expand Down Expand Up @@ -1562,16 +1631,14 @@ module.exports = {
/**
* Inclines a number
* @param {Number} number Number to incline
* @return {String} 1-st, 2-d, 3-d, 4-th, 10-th, 20-th, 21-st, 22-d, 23-d, 30-th
* @return {String} 0th, 1st, 2d, 3d, 4th, 10th, 20th, 21st, 22d, 23d, 30th
*/
inclineNumber(number) {
if (!this.isPositiveOrZeroInteger(number)) {
return number;
}

if (number === 0) {
return `zero-index`;
} else if (number % 10 === 1 && number !== 11) {
if (number % 10 === 1 && number !== 11) {
return `${number}st`;
} else if ([2, 3].includes(number % 10) && ![12, 13].includes(number)) {
return `${number}d`;
Expand Down
42 changes: 30 additions & 12 deletions modules/commandTxs.js
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,8 @@ async function fill(params) {
};
}

const onWhichAccount = traderapi.isSecondAccount ? ' on second account' : '';

const balances = await traderapi.getBalances(false);
let balance;
let isBalanceEnough = true;
Expand Down Expand Up @@ -2075,13 +2077,14 @@ async function calc(params, tx, isWebApi = false) {
function balancesString(balances, caption, params) {
let output = '';
let totalBTC = 0; let totalUSD = 0;
let totalNonCoin1BTC = 0; let totalNonCoin1USD = 0;
const unknownCryptos = [];

if (balances.length === 0) {
output = `All empty.`;
} else {
output = caption;
balances = balances.filter((crypto) => !['totalBTC', 'totalUSD'].includes(crypto.code));
balances = balances.filter((crypto) => !['totalBTC', 'totalUSD', 'totalNonCoin1BTC', 'totalNonCoin1USD'].includes(crypto.code));
balances.forEach((crypto) => {
const accountTypeString = params?.[0] ? `[${crypto.accountType}] ` : '';
output += `${accountTypeString}${utils.formatNumber(+(crypto.total).toFixed(8), true)} _${crypto.code}_`;
Expand All @@ -2098,25 +2101,30 @@ function balancesString(balances, caption, params) {
const skipUnknownCryptos = ['BTXCRD'];
if (utils.isPositiveOrZeroNumber(crypto.usd)) {
totalUSD += crypto.usd;
if (crypto.code !== config.coin1) totalNonCoin1USD += crypto.usd;
} else {
value = exchangerUtils.convertCryptos(crypto.code, 'USD', crypto.total).outAmount;
if (utils.isPositiveOrZeroNumber(value)) {
totalUSD += value;
if (crypto.code !== config.coin1) totalNonCoin1USD += value;
} else if (!skipUnknownCryptos.includes(crypto.code)) {
unknownCryptos.push(crypto.code);
}
}
if (utils.isPositiveOrZeroNumber(crypto.btc)) {
totalBTC += crypto.btc;
if (crypto.code !== config.coin1) totalNonCoin1BTC += crypto.btc;
} else {
value = exchangerUtils.convertCryptos(crypto.code, 'BTC', crypto.total).outAmount;
if (utils.isPositiveOrZeroNumber(value)) {
totalBTC += value;
if (crypto.code !== config.coin1) totalNonCoin1BTC += value;
}
}
});

output += `Total holdings ~ ${utils.formatNumber(+totalUSD.toFixed(2), true)} _USD_ or ${utils.formatNumber(totalBTC.toFixed(8), true)} _BTC_`;
output += `\nTotal holdings (non-${config.coin1}) ~ ${utils.formatNumber(+totalNonCoin1USD.toFixed(2), true)} _USD_ or ${utils.formatNumber(totalNonCoin1BTC.toFixed(8), true)} _BTC_`;
if (unknownCryptos.length) {
output += `. Note: I didn't count unknown cryptos ${unknownCryptos.join(', ')}.`;
}
Expand All @@ -2130,6 +2138,14 @@ function balancesString(balances, caption, params) {
code: 'totalBTC',
total: totalBTC,
});
balances.push({
code: 'totalNonCoin1USD',
total: totalNonCoin1USD,
});
balances.push({
code: 'totalNonCoin1BTC',
total: totalNonCoin1BTC,
});
}

return { output, balances };
Expand All @@ -2138,33 +2154,34 @@ function balancesString(balances, caption, params) {
/**
* Create balance info string for an account, including balance difference from previous request
* @param {Number} accountNo 0 for first account, 1 for second one
* @param {Object} tx Income ADM transaction
* @param {Object} tx [deprecated] Income ADM transaction to get senderId
* @param {String} userId senderId or userId for web
* @param {Boolean} isWebApi If true, info messages will be different
* @param {Array} params First parameter: account type, like main, trade, margin, or 'full'.
* Note: Balance difference only for 'trade' account
* @return {String}
*/
async function getBalancesInfo(accountNo = 0, tx, isWebApi = false, params) {
async function getBalancesInfo(accountNo = 0, tx, isWebApi = false, params, userId) {
let output = '';

try {

let balances =
await traderapi.getBalances();

const caption = `${config.exchangeName} balances:\n`;
const balancesObject = balancesString(balances, caption);
const accountTypeString = params?.[0] ? ` _${params?.[0]}_ account` : '';
const caption = `${config.exchangeName}${accountTypeString} balances:\n`;
const balancesObject = balancesString(balances, caption, params);
output = balancesObject.output;
balances = balancesObject.balances;

if (!isWebApi && !params?.[0]) {
output += utils.differenceInBalancesString(
balances,
previousBalances[accountNo][tx.senderId],
previousBalances[accountNo][userId],
orderUtils.parseMarket(config.pair),
);

previousBalances[accountNo][tx.senderId] = balances;
previousBalances[accountNo][userId] = { timestamp: Date.now(), balances: balances };
}
} catch (e) {
log.error(`Error in getBalancesInfo() of ${utils.getModuleName(module.id)} module: ` + e);
Expand All @@ -2179,11 +2196,12 @@ async function getBalancesInfo(accountNo = 0, tx, isWebApi = false, params) {
* If undefined, will show balances for 'trade' account. If 'full', for all account types.
* Exchange should support features().accountTypes
* Note: Both account balances in case of two-keys trading will show only for 'trade'
* @param {Object} tx Income ADM transaction
* @param {Object} tx Income ADM transaction for in-chat command
* @param {Object} user User info for web
* @param {Boolean} isWebApi If true, info messages will be different
* @return {String}
*/
async function balances(params, tx, isWebApi = false) {
async function balances(params, tx, user, isWebApi = false) {
let output = '';

try {
Expand All @@ -2195,7 +2213,8 @@ async function balances(params, tx, isWebApi = false) {
}
}

const account0Balances = await getBalancesInfo(0, tx, isWebApi);
const userId = isWebApi ? user.login : tx.senderId;
const account0Balances = await getBalancesInfo(0, tx, isWebApi, params, userId);
const account1Balances = undefined;
output = account1Balances ? account0Balances + '\n\n' + account1Balances : account0Balances;

Expand All @@ -2208,7 +2227,6 @@ async function balances(params, tx, isWebApi = false) {
msgSendBack: output,
notifyType: 'log',
};

}

function version() {
Expand Down
2 changes: 2 additions & 0 deletions modules/configReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ try {
config.supported_exchanges = config.exchanges.join(', ');
config.exchangeName = config.exchange;
config.exchange = config.exchangeName.toLowerCase();
config.file = 'tradeParams_' + config.exchange + '.js';
config.fileWithPath = './trade/settings/' + config.file;
config.pair = config.pair.toUpperCase();
config.coin1 = config.pair.split('/')[0].trim();
config.coin2 = config.pair.split('/')[1].trim();
Expand Down
Loading

0 comments on commit 6b19811

Please sign in to comment.